From 933d8c7a3e55476dda85b547a814948d61039fee Mon Sep 17 00:00:00 2001
From: hanfi <ccc@spahan.ch>
Date: Fri, 11 Aug 2023 08:19:25 +0200
Subject: [PATCH] fix checkout

---
 dist/bundle.js          | 540 +++++++++++++++++++++++++++++++++++++++-
 dist/checkout.html      |   2 +-
 src/js/main.js          |  14 +-
 src/views/checkout.html |   2 +-
 4 files changed, 550 insertions(+), 8 deletions(-)

diff --git a/dist/bundle.js b/dist/bundle.js
index 5804372..f9be9cc 100644
--- a/dist/bundle.js
+++ b/dist/bundle.js
@@ -1 +1,539 @@
-var lib;(()=>{var __webpack_modules__={244:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('// ESM COMPAT FLAG\n__webpack_require__.r(__webpack_exports__);\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n  addItemByTag: () => (/* binding */ addItemByTag),\n  addItemImage: () => (/* binding */ addItemImage),\n  addItemScan: () => (/* binding */ addItemScan),\n  checkinItems: () => (/* binding */ checkinItems),\n  checkoutByTag: () => (/* binding */ checkoutByTag),\n  decreaseItemCount: () => (/* binding */ decreaseItemCount),\n  increaseItemCount: () => (/* binding */ increaseItemCount),\n  loadStorages: () => (/* binding */ loadStorages),\n  onPageLoad: () => (/* binding */ onPageLoad),\n  onTagInputChanged: () => (/* binding */ onTagInputChanged),\n  onTagTextUpdate: () => (/* binding */ onTagTextUpdate),\n  scanReceiver: () => (/* binding */ scanReceiver),\n  stopScanningItem: () => (/* binding */ stopScanningItem)\n});\n\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/core.js\nvar Html5QrcodeSupportedFormats;\n(function (Html5QrcodeSupportedFormats) {\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["QR_CODE"] = 0] = "QR_CODE";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["AZTEC"] = 1] = "AZTEC";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["CODABAR"] = 2] = "CODABAR";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["CODE_39"] = 3] = "CODE_39";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["CODE_93"] = 4] = "CODE_93";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["CODE_128"] = 5] = "CODE_128";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["DATA_MATRIX"] = 6] = "DATA_MATRIX";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["MAXICODE"] = 7] = "MAXICODE";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["ITF"] = 8] = "ITF";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["EAN_13"] = 9] = "EAN_13";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["EAN_8"] = 10] = "EAN_8";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["PDF_417"] = 11] = "PDF_417";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["RSS_14"] = 12] = "RSS_14";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["RSS_EXPANDED"] = 13] = "RSS_EXPANDED";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["UPC_A"] = 14] = "UPC_A";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["UPC_E"] = 15] = "UPC_E";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats["UPC_EAN_EXTENSION"] = 16] = "UPC_EAN_EXTENSION";\n})(Html5QrcodeSupportedFormats || (Html5QrcodeSupportedFormats = {}));\nvar html5QrcodeSupportedFormatsTextMap = new Map([\n    [Html5QrcodeSupportedFormats.QR_CODE, "QR_CODE"],\n    [Html5QrcodeSupportedFormats.AZTEC, "AZTEC"],\n    [Html5QrcodeSupportedFormats.CODABAR, "CODABAR"],\n    [Html5QrcodeSupportedFormats.CODE_39, "CODE_39"],\n    [Html5QrcodeSupportedFormats.CODE_93, "CODE_93"],\n    [Html5QrcodeSupportedFormats.CODE_128, "CODE_128"],\n    [Html5QrcodeSupportedFormats.DATA_MATRIX, "DATA_MATRIX"],\n    [Html5QrcodeSupportedFormats.MAXICODE, "MAXICODE"],\n    [Html5QrcodeSupportedFormats.ITF, "ITF"],\n    [Html5QrcodeSupportedFormats.EAN_13, "EAN_13"],\n    [Html5QrcodeSupportedFormats.EAN_8, "EAN_8"],\n    [Html5QrcodeSupportedFormats.PDF_417, "PDF_417"],\n    [Html5QrcodeSupportedFormats.RSS_14, "RSS_14"],\n    [Html5QrcodeSupportedFormats.RSS_EXPANDED, "RSS_EXPANDED"],\n    [Html5QrcodeSupportedFormats.UPC_A, "UPC_A"],\n    [Html5QrcodeSupportedFormats.UPC_E, "UPC_E"],\n    [Html5QrcodeSupportedFormats.UPC_EAN_EXTENSION, "UPC_EAN_EXTENSION"]\n]);\nvar DecodedTextType;\n(function (DecodedTextType) {\n    DecodedTextType[DecodedTextType["UNKNOWN"] = 0] = "UNKNOWN";\n    DecodedTextType[DecodedTextType["URL"] = 1] = "URL";\n})(DecodedTextType || (DecodedTextType = {}));\nfunction isValidHtml5QrcodeSupportedFormats(format) {\n    return Object.values(Html5QrcodeSupportedFormats).includes(format);\n}\nvar Html5QrcodeScanType;\n(function (Html5QrcodeScanType) {\n    Html5QrcodeScanType[Html5QrcodeScanType["SCAN_TYPE_CAMERA"] = 0] = "SCAN_TYPE_CAMERA";\n    Html5QrcodeScanType[Html5QrcodeScanType["SCAN_TYPE_FILE"] = 1] = "SCAN_TYPE_FILE";\n})(Html5QrcodeScanType || (Html5QrcodeScanType = {}));\nvar Html5QrcodeConstants = (function () {\n    function Html5QrcodeConstants() {\n    }\n    Html5QrcodeConstants.GITHUB_PROJECT_URL = "https://github.com/mebjas/html5-qrcode";\n    Html5QrcodeConstants.SCAN_DEFAULT_FPS = 2;\n    Html5QrcodeConstants.DEFAULT_DISABLE_FLIP = false;\n    Html5QrcodeConstants.DEFAULT_REMEMBER_LAST_CAMERA_USED = true;\n    Html5QrcodeConstants.DEFAULT_SUPPORTED_SCAN_TYPE = [\n        Html5QrcodeScanType.SCAN_TYPE_CAMERA,\n        Html5QrcodeScanType.SCAN_TYPE_FILE\n    ];\n    return Html5QrcodeConstants;\n}());\n\nvar QrcodeResultFormat = (function () {\n    function QrcodeResultFormat(format, formatName) {\n        this.format = format;\n        this.formatName = formatName;\n    }\n    QrcodeResultFormat.prototype.toString = function () {\n        return this.formatName;\n    };\n    QrcodeResultFormat.create = function (format) {\n        if (!html5QrcodeSupportedFormatsTextMap.has(format)) {\n            throw "".concat(format, " not in html5QrcodeSupportedFormatsTextMap");\n        }\n        return new QrcodeResultFormat(format, html5QrcodeSupportedFormatsTextMap.get(format));\n    };\n    return QrcodeResultFormat;\n}());\n\nvar Html5QrcodeResultFactory = (function () {\n    function Html5QrcodeResultFactory() {\n    }\n    Html5QrcodeResultFactory.createFromText = function (decodedText) {\n        var qrcodeResult = {\n            text: decodedText\n        };\n        return {\n            decodedText: decodedText,\n            result: qrcodeResult\n        };\n    };\n    Html5QrcodeResultFactory.createFromQrcodeResult = function (qrcodeResult) {\n        return {\n            decodedText: qrcodeResult.text,\n            result: qrcodeResult\n        };\n    };\n    return Html5QrcodeResultFactory;\n}());\n\nvar Html5QrcodeErrorTypes;\n(function (Html5QrcodeErrorTypes) {\n    Html5QrcodeErrorTypes[Html5QrcodeErrorTypes["UNKWOWN_ERROR"] = 0] = "UNKWOWN_ERROR";\n    Html5QrcodeErrorTypes[Html5QrcodeErrorTypes["IMPLEMENTATION_ERROR"] = 1] = "IMPLEMENTATION_ERROR";\n    Html5QrcodeErrorTypes[Html5QrcodeErrorTypes["NO_CODE_FOUND_ERROR"] = 2] = "NO_CODE_FOUND_ERROR";\n})(Html5QrcodeErrorTypes || (Html5QrcodeErrorTypes = {}));\nvar Html5QrcodeErrorFactory = (function () {\n    function Html5QrcodeErrorFactory() {\n    }\n    Html5QrcodeErrorFactory.createFrom = function (error) {\n        return {\n            errorMessage: error,\n            type: Html5QrcodeErrorTypes.UNKWOWN_ERROR\n        };\n    };\n    return Html5QrcodeErrorFactory;\n}());\n\nvar BaseLoggger = (function () {\n    function BaseLoggger(verbose) {\n        this.verbose = verbose;\n    }\n    BaseLoggger.prototype.log = function (message) {\n        if (this.verbose) {\n            console.log(message);\n        }\n    };\n    BaseLoggger.prototype.warn = function (message) {\n        if (this.verbose) {\n            console.warn(message);\n        }\n    };\n    BaseLoggger.prototype.logError = function (message, isExperimental) {\n        if (this.verbose || isExperimental === true) {\n            console.error(message);\n        }\n    };\n    BaseLoggger.prototype.logErrors = function (errors) {\n        if (errors.length === 0) {\n            throw "Logger#logError called without arguments";\n        }\n        if (this.verbose) {\n            console.error(errors);\n        }\n    };\n    return BaseLoggger;\n}());\n\nfunction isNullOrUndefined(obj) {\n    return (typeof obj === "undefined") || obj === null;\n}\nfunction clip(value, minValue, maxValue) {\n    if (value > maxValue) {\n        return maxValue;\n    }\n    if (value < minValue) {\n        return minValue;\n    }\n    return value;\n}\n//# sourceMappingURL=core.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/strings.js\nvar Html5QrcodeStrings = (function () {\n    function Html5QrcodeStrings() {\n    }\n    Html5QrcodeStrings.codeParseError = function (exception) {\n        return "QR code parse error, error = ".concat(exception);\n    };\n    Html5QrcodeStrings.errorGettingUserMedia = function (error) {\n        return "Error getting userMedia, error = ".concat(error);\n    };\n    Html5QrcodeStrings.onlyDeviceSupportedError = function () {\n        return "The device doesn\'t support navigator.mediaDevices , only "\n            + "supported cameraIdOrConfig in this case is deviceId parameter "\n            + "(string).";\n    };\n    Html5QrcodeStrings.cameraStreamingNotSupported = function () {\n        return "Camera streaming not supported by the browser.";\n    };\n    Html5QrcodeStrings.unableToQuerySupportedDevices = function () {\n        return "Unable to query supported devices, unknown error.";\n    };\n    Html5QrcodeStrings.insecureContextCameraQueryError = function () {\n        return "Camera access is only supported in secure context like https "\n            + "or localhost.";\n    };\n    Html5QrcodeStrings.scannerPaused = function () {\n        return "Scanner paused";\n    };\n    return Html5QrcodeStrings;\n}());\n\nvar Html5QrcodeScannerStrings = (function () {\n    function Html5QrcodeScannerStrings() {\n    }\n    Html5QrcodeScannerStrings.scanningStatus = function () {\n        return "Scanning";\n    };\n    Html5QrcodeScannerStrings.idleStatus = function () {\n        return "Idle";\n    };\n    Html5QrcodeScannerStrings.errorStatus = function () {\n        return "Error";\n    };\n    Html5QrcodeScannerStrings.permissionStatus = function () {\n        return "Permission";\n    };\n    Html5QrcodeScannerStrings.noCameraFoundErrorStatus = function () {\n        return "No Cameras";\n    };\n    Html5QrcodeScannerStrings.lastMatch = function (decodedText) {\n        return "Last Match: ".concat(decodedText);\n    };\n    Html5QrcodeScannerStrings.codeScannerTitle = function () {\n        return "Code Scanner";\n    };\n    Html5QrcodeScannerStrings.cameraPermissionTitle = function () {\n        return "Request Camera Permissions";\n    };\n    Html5QrcodeScannerStrings.cameraPermissionRequesting = function () {\n        return "Requesting camera permissions...";\n    };\n    Html5QrcodeScannerStrings.noCameraFound = function () {\n        return "No camera found";\n    };\n    Html5QrcodeScannerStrings.scanButtonStopScanningText = function () {\n        return "Stop Scanning";\n    };\n    Html5QrcodeScannerStrings.scanButtonStartScanningText = function () {\n        return "Start Scanning";\n    };\n    Html5QrcodeScannerStrings.torchOnButton = function () {\n        return "Switch On Torch";\n    };\n    Html5QrcodeScannerStrings.torchOffButton = function () {\n        return "Switch Off Torch";\n    };\n    Html5QrcodeScannerStrings.torchOnFailedMessage = function () {\n        return "Failed to turn on torch";\n    };\n    Html5QrcodeScannerStrings.torchOffFailedMessage = function () {\n        return "Failed to turn off torch";\n    };\n    Html5QrcodeScannerStrings.scanButtonScanningStarting = function () {\n        return "Launching Camera...";\n    };\n    Html5QrcodeScannerStrings.textIfCameraScanSelected = function () {\n        return "Scan an Image File";\n    };\n    Html5QrcodeScannerStrings.textIfFileScanSelected = function () {\n        return "Scan using camera directly";\n    };\n    Html5QrcodeScannerStrings.selectCamera = function () {\n        return "Select Camera";\n    };\n    Html5QrcodeScannerStrings.fileSelectionChooseImage = function () {\n        return "Choose Image";\n    };\n    Html5QrcodeScannerStrings.fileSelectionChooseAnother = function () {\n        return "Choose Another";\n    };\n    Html5QrcodeScannerStrings.fileSelectionNoImageSelected = function () {\n        return "No image choosen";\n    };\n    Html5QrcodeScannerStrings.anonymousCameraPrefix = function () {\n        return "Anonymous Camera";\n    };\n    Html5QrcodeScannerStrings.dragAndDropMessage = function () {\n        return "Or drop an image to scan";\n    };\n    Html5QrcodeScannerStrings.dragAndDropMessageOnlyImages = function () {\n        return "Or drop an image to scan (other files not supported)";\n    };\n    Html5QrcodeScannerStrings.zoom = function () {\n        return "zoom";\n    };\n    Html5QrcodeScannerStrings.loadingImage = function () {\n        return "Loading image...";\n    };\n    Html5QrcodeScannerStrings.cameraScanAltText = function () {\n        return "Camera based scan";\n    };\n    Html5QrcodeScannerStrings.fileScanAltText = function () {\n        return "Fule based scan";\n    };\n    return Html5QrcodeScannerStrings;\n}());\n\nvar LibraryInfoStrings = (function () {\n    function LibraryInfoStrings() {\n    }\n    LibraryInfoStrings.poweredBy = function () {\n        return "Powered by ";\n    };\n    LibraryInfoStrings.reportIssues = function () {\n        return "Report issues";\n    };\n    return LibraryInfoStrings;\n}());\n\n//# sourceMappingURL=strings.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/utils.js\nvar VideoConstraintsUtil = (function () {\n    function VideoConstraintsUtil() {\n    }\n    VideoConstraintsUtil.isMediaStreamConstraintsValid = function (videoConstraints, logger) {\n        if (typeof videoConstraints !== "object") {\n            var typeofVideoConstraints = typeof videoConstraints;\n            logger.logError("videoConstraints should be of type object, the "\n                + "object passed is of type ".concat(typeofVideoConstraints, "."), true);\n            return false;\n        }\n        var bannedKeys = [\n            "autoGainControl",\n            "channelCount",\n            "echoCancellation",\n            "latency",\n            "noiseSuppression",\n            "sampleRate",\n            "sampleSize",\n            "volume"\n        ];\n        var bannedkeysSet = new Set(bannedKeys);\n        var keysInVideoConstraints = Object.keys(videoConstraints);\n        for (var _i = 0, keysInVideoConstraints_1 = keysInVideoConstraints; _i < keysInVideoConstraints_1.length; _i++) {\n            var key = keysInVideoConstraints_1[_i];\n            if (bannedkeysSet.has(key)) {\n                logger.logError("".concat(key, " is not supported videoConstaints."), true);\n                return false;\n            }\n        }\n        return true;\n    };\n    return VideoConstraintsUtil;\n}());\n\n//# sourceMappingURL=utils.js.map\n// EXTERNAL MODULE: ./node_modules/html5-qrcode/third_party/zxing-js.umd.js\nvar zxing_js_umd = __webpack_require__(817);\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/zxing-html5-qrcode-decoder.js\n\n\nvar ZXingHtml5QrcodeDecoder = (function () {\n    function ZXingHtml5QrcodeDecoder(requestedFormats, verbose, logger) {\n        this.formatMap = new Map([\n            [Html5QrcodeSupportedFormats.QR_CODE, zxing_js_umd.BarcodeFormat.QR_CODE],\n            [Html5QrcodeSupportedFormats.AZTEC, zxing_js_umd.BarcodeFormat.AZTEC],\n            [Html5QrcodeSupportedFormats.CODABAR, zxing_js_umd.BarcodeFormat.CODABAR],\n            [Html5QrcodeSupportedFormats.CODE_39, zxing_js_umd.BarcodeFormat.CODE_39],\n            [Html5QrcodeSupportedFormats.CODE_93, zxing_js_umd.BarcodeFormat.CODE_93],\n            [\n                Html5QrcodeSupportedFormats.CODE_128,\n                zxing_js_umd.BarcodeFormat.CODE_128\n            ],\n            [\n                Html5QrcodeSupportedFormats.DATA_MATRIX,\n                zxing_js_umd.BarcodeFormat.DATA_MATRIX\n            ],\n            [\n                Html5QrcodeSupportedFormats.MAXICODE,\n                zxing_js_umd.BarcodeFormat.MAXICODE\n            ],\n            [Html5QrcodeSupportedFormats.ITF, zxing_js_umd.BarcodeFormat.ITF],\n            [Html5QrcodeSupportedFormats.EAN_13, zxing_js_umd.BarcodeFormat.EAN_13],\n            [Html5QrcodeSupportedFormats.EAN_8, zxing_js_umd.BarcodeFormat.EAN_8],\n            [Html5QrcodeSupportedFormats.PDF_417, zxing_js_umd.BarcodeFormat.PDF_417],\n            [Html5QrcodeSupportedFormats.RSS_14, zxing_js_umd.BarcodeFormat.RSS_14],\n            [\n                Html5QrcodeSupportedFormats.RSS_EXPANDED,\n                zxing_js_umd.BarcodeFormat.RSS_EXPANDED\n            ],\n            [Html5QrcodeSupportedFormats.UPC_A, zxing_js_umd.BarcodeFormat.UPC_A],\n            [Html5QrcodeSupportedFormats.UPC_E, zxing_js_umd.BarcodeFormat.UPC_E],\n            [\n                Html5QrcodeSupportedFormats.UPC_EAN_EXTENSION,\n                zxing_js_umd.BarcodeFormat.UPC_EAN_EXTENSION\n            ]\n        ]);\n        this.reverseFormatMap = this.createReverseFormatMap();\n        if (!zxing_js_umd) {\n            throw "Use html5qrcode.min.js without edit, ZXing not found.";\n        }\n        this.verbose = verbose;\n        this.logger = logger;\n        var formats = this.createZXingFormats(requestedFormats);\n        var hints = new Map();\n        hints.set(zxing_js_umd.DecodeHintType.POSSIBLE_FORMATS, formats);\n        hints.set(zxing_js_umd.DecodeHintType.TRY_HARDER, false);\n        this.hints = hints;\n    }\n    ZXingHtml5QrcodeDecoder.prototype.decodeAsync = function (canvas) {\n        var _this = this;\n        return new Promise(function (resolve, reject) {\n            try {\n                resolve(_this.decode(canvas));\n            }\n            catch (error) {\n                reject(error);\n            }\n        });\n    };\n    ZXingHtml5QrcodeDecoder.prototype.decode = function (canvas) {\n        var zxingDecoder = new zxing_js_umd.MultiFormatReader(this.verbose, this.hints);\n        var luminanceSource = new zxing_js_umd.HTMLCanvasElementLuminanceSource(canvas);\n        var binaryBitmap = new zxing_js_umd.BinaryBitmap(new zxing_js_umd.HybridBinarizer(luminanceSource));\n        var result = zxingDecoder.decode(binaryBitmap);\n        return {\n            text: result.text,\n            format: QrcodeResultFormat.create(this.toHtml5QrcodeSupportedFormats(result.format)),\n            debugData: this.createDebugData()\n        };\n    };\n    ZXingHtml5QrcodeDecoder.prototype.createReverseFormatMap = function () {\n        var result = new Map();\n        this.formatMap.forEach(function (value, key, _) {\n            result.set(value, key);\n        });\n        return result;\n    };\n    ZXingHtml5QrcodeDecoder.prototype.toHtml5QrcodeSupportedFormats = function (zxingFormat) {\n        if (!this.reverseFormatMap.has(zxingFormat)) {\n            throw "reverseFormatMap doesn\'t have ".concat(zxingFormat);\n        }\n        return this.reverseFormatMap.get(zxingFormat);\n    };\n    ZXingHtml5QrcodeDecoder.prototype.createZXingFormats = function (requestedFormats) {\n        var zxingFormats = [];\n        for (var _i = 0, requestedFormats_1 = requestedFormats; _i < requestedFormats_1.length; _i++) {\n            var requestedFormat = requestedFormats_1[_i];\n            if (this.formatMap.has(requestedFormat)) {\n                zxingFormats.push(this.formatMap.get(requestedFormat));\n            }\n            else {\n                this.logger.logError("".concat(requestedFormat, " is not supported by")\n                    + "ZXingHtml5QrcodeShim");\n            }\n        }\n        return zxingFormats;\n    };\n    ZXingHtml5QrcodeDecoder.prototype.createDebugData = function () {\n        return { decoderName: "zxing-js" };\n    };\n    return ZXingHtml5QrcodeDecoder;\n}());\n\n//# sourceMappingURL=zxing-html5-qrcode-decoder.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/native-bar-code-detector.js\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar __generator = (undefined && undefined.__generator) || function (thisArg, body) {\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;\n    function verb(n) { return function (v) { return step([n, v]); }; }\n    function step(op) {\n        if (f) throw new TypeError("Generator is already executing.");\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\n            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n            if (y = 0, t) op = [op[0] & 2, t.value];\n            switch (op[0]) {\n                case 0: case 1: t = op; break;\n                case 4: _.label++; return { value: op[1], done: false };\n                case 5: _.label++; y = op[1]; op = [0]; continue;\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\n                default:\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                    if (t[2]) _.ops.pop();\n                    _.trys.pop(); continue;\n            }\n            op = body.call(thisArg, _);\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n    }\n};\n\nvar BarcodeDetectorDelegate = (function () {\n    function BarcodeDetectorDelegate(requestedFormats, verbose, logger) {\n        this.formatMap = new Map([\n            [Html5QrcodeSupportedFormats.QR_CODE, "qr_code"],\n            [Html5QrcodeSupportedFormats.AZTEC, "aztec"],\n            [Html5QrcodeSupportedFormats.CODABAR, "codabar"],\n            [Html5QrcodeSupportedFormats.CODE_39, "code_39"],\n            [Html5QrcodeSupportedFormats.CODE_93, "code_93"],\n            [Html5QrcodeSupportedFormats.CODE_128, "code_128"],\n            [Html5QrcodeSupportedFormats.DATA_MATRIX, "data_matrix"],\n            [Html5QrcodeSupportedFormats.ITF, "itf"],\n            [Html5QrcodeSupportedFormats.EAN_13, "ean_13"],\n            [Html5QrcodeSupportedFormats.EAN_8, "ean_8"],\n            [Html5QrcodeSupportedFormats.PDF_417, "pdf417"],\n            [Html5QrcodeSupportedFormats.UPC_A, "upc_a"],\n            [Html5QrcodeSupportedFormats.UPC_E, "upc_e"]\n        ]);\n        this.reverseFormatMap = this.createReverseFormatMap();\n        if (!BarcodeDetectorDelegate.isSupported()) {\n            throw "Use html5qrcode.min.js without edit, Use "\n                + "BarcodeDetectorDelegate only if it isSupported();";\n        }\n        this.verbose = verbose;\n        this.logger = logger;\n        var formats = this.createBarcodeDetectorFormats(requestedFormats);\n        this.detector = new BarcodeDetector(formats);\n        if (!this.detector) {\n            throw "BarcodeDetector detector not supported";\n        }\n    }\n    BarcodeDetectorDelegate.isSupported = function () {\n        if (!("BarcodeDetector" in window)) {\n            return false;\n        }\n        var dummyDetector = new BarcodeDetector({ formats: ["qr_code"] });\n        return typeof dummyDetector !== "undefined";\n    };\n    BarcodeDetectorDelegate.prototype.decodeAsync = function (canvas) {\n        return __awaiter(this, void 0, void 0, function () {\n            var barcodes, largestBarcode;\n            return __generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0: return [4, this.detector.detect(canvas)];\n                    case 1:\n                        barcodes = _a.sent();\n                        if (!barcodes || barcodes.length === 0) {\n                            throw "No barcode or QR code detected.";\n                        }\n                        largestBarcode = this.selectLargestBarcode(barcodes);\n                        return [2, {\n                                text: largestBarcode.rawValue,\n                                format: QrcodeResultFormat.create(this.toHtml5QrcodeSupportedFormats(largestBarcode.format)),\n                                debugData: this.createDebugData()\n                            }];\n                }\n            });\n        });\n    };\n    BarcodeDetectorDelegate.prototype.selectLargestBarcode = function (barcodes) {\n        var largestBarcode = null;\n        var maxArea = 0;\n        for (var _i = 0, barcodes_1 = barcodes; _i < barcodes_1.length; _i++) {\n            var barcode = barcodes_1[_i];\n            var area = barcode.boundingBox.width * barcode.boundingBox.height;\n            if (area > maxArea) {\n                maxArea = area;\n                largestBarcode = barcode;\n            }\n        }\n        if (!largestBarcode) {\n            throw "No largest barcode found";\n        }\n        return largestBarcode;\n    };\n    BarcodeDetectorDelegate.prototype.createBarcodeDetectorFormats = function (requestedFormats) {\n        var formats = [];\n        for (var _i = 0, requestedFormats_1 = requestedFormats; _i < requestedFormats_1.length; _i++) {\n            var requestedFormat = requestedFormats_1[_i];\n            if (this.formatMap.has(requestedFormat)) {\n                formats.push(this.formatMap.get(requestedFormat));\n            }\n            else {\n                this.logger.warn("".concat(requestedFormat, " is not supported by")\n                    + "BarcodeDetectorDelegate");\n            }\n        }\n        return { formats: formats };\n    };\n    BarcodeDetectorDelegate.prototype.toHtml5QrcodeSupportedFormats = function (barcodeDetectorFormat) {\n        if (!this.reverseFormatMap.has(barcodeDetectorFormat)) {\n            throw "reverseFormatMap doesn\'t have ".concat(barcodeDetectorFormat);\n        }\n        return this.reverseFormatMap.get(barcodeDetectorFormat);\n    };\n    BarcodeDetectorDelegate.prototype.createReverseFormatMap = function () {\n        var result = new Map();\n        this.formatMap.forEach(function (value, key, _) {\n            result.set(value, key);\n        });\n        return result;\n    };\n    BarcodeDetectorDelegate.prototype.createDebugData = function () {\n        return { decoderName: "BarcodeDetector" };\n    };\n    return BarcodeDetectorDelegate;\n}());\n\n//# sourceMappingURL=native-bar-code-detector.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/code-decoder.js\nvar code_decoder_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar code_decoder_generator = (undefined && undefined.__generator) || function (thisArg, body) {\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;\n    function verb(n) { return function (v) { return step([n, v]); }; }\n    function step(op) {\n        if (f) throw new TypeError("Generator is already executing.");\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\n            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n            if (y = 0, t) op = [op[0] & 2, t.value];\n            switch (op[0]) {\n                case 0: case 1: t = op; break;\n                case 4: _.label++; return { value: op[1], done: false };\n                case 5: _.label++; y = op[1]; op = [0]; continue;\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\n                default:\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                    if (t[2]) _.ops.pop();\n                    _.trys.pop(); continue;\n            }\n            op = body.call(thisArg, _);\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n    }\n};\n\n\nvar Html5QrcodeShim = (function () {\n    function Html5QrcodeShim(requestedFormats, useBarCodeDetectorIfSupported, verbose, logger) {\n        this.EXECUTIONS_TO_REPORT_PERFORMANCE = 100;\n        this.executions = 0;\n        this.executionResults = [];\n        this.wasPrimaryDecoderUsedInLastDecode = false;\n        this.verbose = verbose;\n        if (useBarCodeDetectorIfSupported\n            && BarcodeDetectorDelegate.isSupported()) {\n            this.primaryDecoder = new BarcodeDetectorDelegate(requestedFormats, verbose, logger);\n            this.secondaryDecoder = new ZXingHtml5QrcodeDecoder(requestedFormats, verbose, logger);\n        }\n        else {\n            this.primaryDecoder = new ZXingHtml5QrcodeDecoder(requestedFormats, verbose, logger);\n        }\n    }\n    Html5QrcodeShim.prototype.decodeAsync = function (canvas) {\n        return code_decoder_awaiter(this, void 0, void 0, function () {\n            var startTime;\n            return code_decoder_generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0:\n                        startTime = performance.now();\n                        _a.label = 1;\n                    case 1:\n                        _a.trys.push([1, , 3, 4]);\n                        return [4, this.getDecoder().decodeAsync(canvas)];\n                    case 2: return [2, _a.sent()];\n                    case 3:\n                        this.possiblyLogPerformance(startTime);\n                        return [7];\n                    case 4: return [2];\n                }\n            });\n        });\n    };\n    Html5QrcodeShim.prototype.decodeRobustlyAsync = function (canvas) {\n        return code_decoder_awaiter(this, void 0, void 0, function () {\n            var startTime, error_1;\n            return code_decoder_generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0:\n                        startTime = performance.now();\n                        _a.label = 1;\n                    case 1:\n                        _a.trys.push([1, 3, 4, 5]);\n                        return [4, this.primaryDecoder.decodeAsync(canvas)];\n                    case 2: return [2, _a.sent()];\n                    case 3:\n                        error_1 = _a.sent();\n                        if (this.secondaryDecoder) {\n                            return [2, this.secondaryDecoder.decodeAsync(canvas)];\n                        }\n                        throw error_1;\n                    case 4:\n                        this.possiblyLogPerformance(startTime);\n                        return [7];\n                    case 5: return [2];\n                }\n            });\n        });\n    };\n    Html5QrcodeShim.prototype.getDecoder = function () {\n        if (!this.secondaryDecoder) {\n            return this.primaryDecoder;\n        }\n        if (this.wasPrimaryDecoderUsedInLastDecode === false) {\n            this.wasPrimaryDecoderUsedInLastDecode = true;\n            return this.primaryDecoder;\n        }\n        this.wasPrimaryDecoderUsedInLastDecode = false;\n        return this.secondaryDecoder;\n    };\n    Html5QrcodeShim.prototype.possiblyLogPerformance = function (startTime) {\n        if (!this.verbose) {\n            return;\n        }\n        var executionTime = performance.now() - startTime;\n        this.executionResults.push(executionTime);\n        this.executions++;\n        this.possiblyFlushPerformanceReport();\n    };\n    Html5QrcodeShim.prototype.possiblyFlushPerformanceReport = function () {\n        if (this.executions < this.EXECUTIONS_TO_REPORT_PERFORMANCE) {\n            return;\n        }\n        var sum = 0;\n        for (var _i = 0, _a = this.executionResults; _i < _a.length; _i++) {\n            var executionTime = _a[_i];\n            sum += executionTime;\n        }\n        var mean = sum / this.executionResults.length;\n        console.log("".concat(mean, " ms for ").concat(this.executionResults.length, " last runs."));\n        this.executions = 0;\n        this.executionResults = [];\n    };\n    return Html5QrcodeShim;\n}());\n\n//# sourceMappingURL=code-decoder.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/camera/core-impl.js\nvar __extends = (undefined && undefined.__extends) || (function () {\n    var extendStatics = function (d, b) {\n        extendStatics = Object.setPrototypeOf ||\n            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n        return extendStatics(d, b);\n    };\n    return function (d, b) {\n        if (typeof b !== "function" && b !== null)\n            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");\n        extendStatics(d, b);\n        function __() { this.constructor = d; }\n        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n    };\n})();\nvar core_impl_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar core_impl_generator = (undefined && undefined.__generator) || function (thisArg, body) {\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;\n    function verb(n) { return function (v) { return step([n, v]); }; }\n    function step(op) {\n        if (f) throw new TypeError("Generator is already executing.");\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\n            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n            if (y = 0, t) op = [op[0] & 2, t.value];\n            switch (op[0]) {\n                case 0: case 1: t = op; break;\n                case 4: _.label++; return { value: op[1], done: false };\n                case 5: _.label++; y = op[1]; op = [0]; continue;\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\n                default:\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                    if (t[2]) _.ops.pop();\n                    _.trys.pop(); continue;\n            }\n            op = body.call(thisArg, _);\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n    }\n};\nvar AbstractCameraCapability = (function () {\n    function AbstractCameraCapability(name, track) {\n        this.name = name;\n        this.track = track;\n    }\n    AbstractCameraCapability.prototype.isSupported = function () {\n        if (!this.track.getCapabilities) {\n            return false;\n        }\n        return this.name in this.track.getCapabilities();\n    };\n    AbstractCameraCapability.prototype.apply = function (value) {\n        var constraint = {};\n        constraint[this.name] = value;\n        var constraints = { advanced: [constraint] };\n        return this.track.applyConstraints(constraints);\n    };\n    AbstractCameraCapability.prototype.value = function () {\n        var settings = this.track.getSettings();\n        if (this.name in settings) {\n            var settingValue = settings[this.name];\n            return settingValue;\n        }\n        return null;\n    };\n    return AbstractCameraCapability;\n}());\nvar AbstractRangeCameraCapability = (function (_super) {\n    __extends(AbstractRangeCameraCapability, _super);\n    function AbstractRangeCameraCapability(name, track) {\n        return _super.call(this, name, track) || this;\n    }\n    AbstractRangeCameraCapability.prototype.min = function () {\n        return this.getCapabilities().min;\n    };\n    AbstractRangeCameraCapability.prototype.max = function () {\n        return this.getCapabilities().max;\n    };\n    AbstractRangeCameraCapability.prototype.step = function () {\n        return this.getCapabilities().step;\n    };\n    AbstractRangeCameraCapability.prototype.apply = function (value) {\n        var constraint = {};\n        constraint[this.name] = value;\n        var constraints = { advanced: [constraint] };\n        return this.track.applyConstraints(constraints);\n    };\n    AbstractRangeCameraCapability.prototype.getCapabilities = function () {\n        this.failIfNotSupported();\n        var capabilities = this.track.getCapabilities();\n        var capability = capabilities[this.name];\n        return {\n            min: capability.min,\n            max: capability.max,\n            step: capability.step,\n        };\n    };\n    AbstractRangeCameraCapability.prototype.failIfNotSupported = function () {\n        if (!this.isSupported()) {\n            throw new Error("".concat(this.name, " capability not supported"));\n        }\n    };\n    return AbstractRangeCameraCapability;\n}(AbstractCameraCapability));\nvar ZoomFeatureImpl = (function (_super) {\n    __extends(ZoomFeatureImpl, _super);\n    function ZoomFeatureImpl(track) {\n        return _super.call(this, "zoom", track) || this;\n    }\n    return ZoomFeatureImpl;\n}(AbstractRangeCameraCapability));\nvar TorchFeatureImpl = (function (_super) {\n    __extends(TorchFeatureImpl, _super);\n    function TorchFeatureImpl(track) {\n        return _super.call(this, "torch", track) || this;\n    }\n    return TorchFeatureImpl;\n}(AbstractCameraCapability));\nvar CameraCapabilitiesImpl = (function () {\n    function CameraCapabilitiesImpl(track) {\n        this.track = track;\n    }\n    CameraCapabilitiesImpl.prototype.zoomFeature = function () {\n        return new ZoomFeatureImpl(this.track);\n    };\n    CameraCapabilitiesImpl.prototype.torchFeature = function () {\n        return new TorchFeatureImpl(this.track);\n    };\n    return CameraCapabilitiesImpl;\n}());\nvar RenderedCameraImpl = (function () {\n    function RenderedCameraImpl(parentElement, mediaStream, callbacks) {\n        this.isClosed = false;\n        this.parentElement = parentElement;\n        this.mediaStream = mediaStream;\n        this.callbacks = callbacks;\n        this.surface = this.createVideoElement(this.parentElement.clientWidth);\n        parentElement.append(this.surface);\n    }\n    RenderedCameraImpl.prototype.createVideoElement = function (width) {\n        var videoElement = document.createElement("video");\n        videoElement.style.width = "".concat(width, "px");\n        videoElement.style.display = "block";\n        videoElement.muted = true;\n        videoElement.setAttribute("muted", "true");\n        videoElement.playsInline = true;\n        return videoElement;\n    };\n    RenderedCameraImpl.prototype.setupSurface = function () {\n        var _this = this;\n        this.surface.onabort = function () {\n            throw "RenderedCameraImpl video surface onabort() called";\n        };\n        this.surface.onerror = function () {\n            throw "RenderedCameraImpl video surface onerror() called";\n        };\n        var onVideoStart = function () {\n            var videoWidth = _this.surface.clientWidth;\n            var videoHeight = _this.surface.clientHeight;\n            _this.callbacks.onRenderSurfaceReady(videoWidth, videoHeight);\n            _this.surface.removeEventListener("playing", onVideoStart);\n        };\n        this.surface.addEventListener("playing", onVideoStart);\n        this.surface.srcObject = this.mediaStream;\n        this.surface.play();\n    };\n    RenderedCameraImpl.create = function (parentElement, mediaStream, options, callbacks) {\n        return core_impl_awaiter(this, void 0, void 0, function () {\n            var renderedCamera, aspectRatioConstraint;\n            return core_impl_generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0:\n                        renderedCamera = new RenderedCameraImpl(parentElement, mediaStream, callbacks);\n                        if (!options.aspectRatio) return [3, 2];\n                        aspectRatioConstraint = {\n                            aspectRatio: options.aspectRatio\n                        };\n                        return [4, renderedCamera.getFirstTrackOrFail().applyConstraints(aspectRatioConstraint)];\n                    case 1:\n                        _a.sent();\n                        _a.label = 2;\n                    case 2:\n                        renderedCamera.setupSurface();\n                        return [2, renderedCamera];\n                }\n            });\n        });\n    };\n    RenderedCameraImpl.prototype.failIfClosed = function () {\n        if (this.isClosed) {\n            throw "The RenderedCamera has already been closed.";\n        }\n    };\n    RenderedCameraImpl.prototype.getFirstTrackOrFail = function () {\n        this.failIfClosed();\n        if (this.mediaStream.getVideoTracks().length === 0) {\n            throw "No video tracks found";\n        }\n        return this.mediaStream.getVideoTracks()[0];\n    };\n    RenderedCameraImpl.prototype.pause = function () {\n        this.failIfClosed();\n        this.surface.pause();\n    };\n    RenderedCameraImpl.prototype.resume = function (onResumeCallback) {\n        this.failIfClosed();\n        var $this = this;\n        var onVideoResume = function () {\n            setTimeout(onResumeCallback, 200);\n            $this.surface.removeEventListener("playing", onVideoResume);\n        };\n        this.surface.addEventListener("playing", onVideoResume);\n        this.surface.play();\n    };\n    RenderedCameraImpl.prototype.isPaused = function () {\n        this.failIfClosed();\n        return this.surface.paused;\n    };\n    RenderedCameraImpl.prototype.getSurface = function () {\n        this.failIfClosed();\n        return this.surface;\n    };\n    RenderedCameraImpl.prototype.getRunningTrackCapabilities = function () {\n        return this.getFirstTrackOrFail().getCapabilities();\n    };\n    RenderedCameraImpl.prototype.getRunningTrackSettings = function () {\n        return this.getFirstTrackOrFail().getSettings();\n    };\n    RenderedCameraImpl.prototype.applyVideoConstraints = function (constraints) {\n        return core_impl_awaiter(this, void 0, void 0, function () {\n            return core_impl_generator(this, function (_a) {\n                if ("aspectRatio" in constraints) {\n                    throw "Changing \'aspectRatio\' in run-time is not yet supported.";\n                }\n                return [2, this.getFirstTrackOrFail().applyConstraints(constraints)];\n            });\n        });\n    };\n    RenderedCameraImpl.prototype.close = function () {\n        if (this.isClosed) {\n            return Promise.resolve();\n        }\n        var $this = this;\n        return new Promise(function (resolve, _) {\n            var tracks = $this.mediaStream.getVideoTracks();\n            var tracksToClose = tracks.length;\n            var tracksClosed = 0;\n            $this.mediaStream.getVideoTracks().forEach(function (videoTrack) {\n                $this.mediaStream.removeTrack(videoTrack);\n                videoTrack.stop();\n                ++tracksClosed;\n                if (tracksClosed >= tracksToClose) {\n                    $this.isClosed = true;\n                    $this.parentElement.removeChild($this.surface);\n                    resolve();\n                }\n            });\n        });\n    };\n    RenderedCameraImpl.prototype.getCapabilities = function () {\n        return new CameraCapabilitiesImpl(this.getFirstTrackOrFail());\n    };\n    return RenderedCameraImpl;\n}());\nvar CameraImpl = (function () {\n    function CameraImpl(mediaStream) {\n        this.mediaStream = mediaStream;\n    }\n    CameraImpl.prototype.render = function (parentElement, options, callbacks) {\n        return core_impl_awaiter(this, void 0, void 0, function () {\n            return core_impl_generator(this, function (_a) {\n                return [2, RenderedCameraImpl.create(parentElement, this.mediaStream, options, callbacks)];\n            });\n        });\n    };\n    CameraImpl.create = function (videoConstraints) {\n        return core_impl_awaiter(this, void 0, void 0, function () {\n            var constraints, mediaStream;\n            return core_impl_generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0:\n                        if (!navigator.mediaDevices) {\n                            throw "navigator.mediaDevices not supported";\n                        }\n                        constraints = {\n                            audio: false,\n                            video: videoConstraints\n                        };\n                        return [4, navigator.mediaDevices.getUserMedia(constraints)];\n                    case 1:\n                        mediaStream = _a.sent();\n                        return [2, new CameraImpl(mediaStream)];\n                }\n            });\n        });\n    };\n    return CameraImpl;\n}());\n\n//# sourceMappingURL=core-impl.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/camera/factories.js\nvar factories_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar factories_generator = (undefined && undefined.__generator) || function (thisArg, body) {\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;\n    function verb(n) { return function (v) { return step([n, v]); }; }\n    function step(op) {\n        if (f) throw new TypeError("Generator is already executing.");\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\n            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n            if (y = 0, t) op = [op[0] & 2, t.value];\n            switch (op[0]) {\n                case 0: case 1: t = op; break;\n                case 4: _.label++; return { value: op[1], done: false };\n                case 5: _.label++; y = op[1]; op = [0]; continue;\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\n                default:\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                    if (t[2]) _.ops.pop();\n                    _.trys.pop(); continue;\n            }\n            op = body.call(thisArg, _);\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n    }\n};\n\nvar CameraFactory = (function () {\n    function CameraFactory() {\n    }\n    CameraFactory.failIfNotSupported = function () {\n        return factories_awaiter(this, void 0, void 0, function () {\n            return factories_generator(this, function (_a) {\n                if (!navigator.mediaDevices) {\n                    throw "navigator.mediaDevices not supported";\n                }\n                return [2, new CameraFactory()];\n            });\n        });\n    };\n    CameraFactory.prototype.create = function (videoConstraints) {\n        return factories_awaiter(this, void 0, void 0, function () {\n            return factories_generator(this, function (_a) {\n                return [2, CameraImpl.create(videoConstraints)];\n            });\n        });\n    };\n    return CameraFactory;\n}());\n\n//# sourceMappingURL=factories.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/camera/retriever.js\nvar retriever_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar retriever_generator = (undefined && undefined.__generator) || function (thisArg, body) {\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;\n    function verb(n) { return function (v) { return step([n, v]); }; }\n    function step(op) {\n        if (f) throw new TypeError("Generator is already executing.");\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\n            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n            if (y = 0, t) op = [op[0] & 2, t.value];\n            switch (op[0]) {\n                case 0: case 1: t = op; break;\n                case 4: _.label++; return { value: op[1], done: false };\n                case 5: _.label++; y = op[1]; op = [0]; continue;\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\n                default:\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                    if (t[2]) _.ops.pop();\n                    _.trys.pop(); continue;\n            }\n            op = body.call(thisArg, _);\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n    }\n};\n\nvar CameraRetriever = (function () {\n    function CameraRetriever() {\n    }\n    CameraRetriever.retrieve = function () {\n        if (navigator.mediaDevices) {\n            return CameraRetriever.getCamerasFromMediaDevices();\n        }\n        var mst = MediaStreamTrack;\n        if (MediaStreamTrack && mst.getSources) {\n            return CameraRetriever.getCamerasFromMediaStreamTrack();\n        }\n        return CameraRetriever.rejectWithError();\n    };\n    CameraRetriever.rejectWithError = function () {\n        var errorMessage = Html5QrcodeStrings.unableToQuerySupportedDevices();\n        if (!CameraRetriever.isHttpsOrLocalhost()) {\n            errorMessage = Html5QrcodeStrings.insecureContextCameraQueryError();\n        }\n        return Promise.reject(errorMessage);\n    };\n    CameraRetriever.isHttpsOrLocalhost = function () {\n        if (location.protocol === "https:") {\n            return true;\n        }\n        var host = location.host.split(":")[0];\n        return host === "127.0.0.1" || host === "localhost";\n    };\n    CameraRetriever.getCamerasFromMediaDevices = function () {\n        return retriever_awaiter(this, void 0, void 0, function () {\n            var closeActiveStreams, mediaStream, devices, results, _i, devices_1, device;\n            return retriever_generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0:\n                        closeActiveStreams = function (stream) {\n                            var tracks = stream.getVideoTracks();\n                            for (var _i = 0, tracks_1 = tracks; _i < tracks_1.length; _i++) {\n                                var track = tracks_1[_i];\n                                track.enabled = false;\n                                track.stop();\n                                stream.removeTrack(track);\n                            }\n                        };\n                        return [4, navigator.mediaDevices.getUserMedia({ audio: false, video: true })];\n                    case 1:\n                        mediaStream = _a.sent();\n                        return [4, navigator.mediaDevices.enumerateDevices()];\n                    case 2:\n                        devices = _a.sent();\n                        results = [];\n                        for (_i = 0, devices_1 = devices; _i < devices_1.length; _i++) {\n                            device = devices_1[_i];\n                            if (device.kind === "videoinput") {\n                                results.push({\n                                    id: device.deviceId,\n                                    label: device.label\n                                });\n                            }\n                        }\n                        closeActiveStreams(mediaStream);\n                        return [2, results];\n                }\n            });\n        });\n    };\n    CameraRetriever.getCamerasFromMediaStreamTrack = function () {\n        return new Promise(function (resolve, _) {\n            var callback = function (sourceInfos) {\n                var results = [];\n                for (var _i = 0, sourceInfos_1 = sourceInfos; _i < sourceInfos_1.length; _i++) {\n                    var sourceInfo = sourceInfos_1[_i];\n                    if (sourceInfo.kind === "video") {\n                        results.push({\n                            id: sourceInfo.id,\n                            label: sourceInfo.label\n                        });\n                    }\n                }\n                resolve(results);\n            };\n            var mst = MediaStreamTrack;\n            mst.getSources(callback);\n        });\n    };\n    return CameraRetriever;\n}());\n\n//# sourceMappingURL=retriever.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/state-manager.js\nvar Html5QrcodeScannerState;\n(function (Html5QrcodeScannerState) {\n    Html5QrcodeScannerState[Html5QrcodeScannerState["UNKNOWN"] = 0] = "UNKNOWN";\n    Html5QrcodeScannerState[Html5QrcodeScannerState["NOT_STARTED"] = 1] = "NOT_STARTED";\n    Html5QrcodeScannerState[Html5QrcodeScannerState["SCANNING"] = 2] = "SCANNING";\n    Html5QrcodeScannerState[Html5QrcodeScannerState["PAUSED"] = 3] = "PAUSED";\n})(Html5QrcodeScannerState || (Html5QrcodeScannerState = {}));\nvar StateManagerImpl = (function () {\n    function StateManagerImpl() {\n        this.state = Html5QrcodeScannerState.NOT_STARTED;\n        this.onGoingTransactionNewState = Html5QrcodeScannerState.UNKNOWN;\n    }\n    StateManagerImpl.prototype.directTransition = function (newState) {\n        this.failIfTransitionOngoing();\n        this.validateTransition(newState);\n        this.state = newState;\n    };\n    StateManagerImpl.prototype.startTransition = function (newState) {\n        this.failIfTransitionOngoing();\n        this.validateTransition(newState);\n        this.onGoingTransactionNewState = newState;\n        return this;\n    };\n    StateManagerImpl.prototype.execute = function () {\n        if (this.onGoingTransactionNewState\n            === Html5QrcodeScannerState.UNKNOWN) {\n            throw "Transaction is already cancelled, cannot execute().";\n        }\n        var tempNewState = this.onGoingTransactionNewState;\n        this.onGoingTransactionNewState = Html5QrcodeScannerState.UNKNOWN;\n        this.directTransition(tempNewState);\n    };\n    StateManagerImpl.prototype.cancel = function () {\n        if (this.onGoingTransactionNewState\n            === Html5QrcodeScannerState.UNKNOWN) {\n            throw "Transaction is already cancelled, cannot cancel().";\n        }\n        this.onGoingTransactionNewState = Html5QrcodeScannerState.UNKNOWN;\n    };\n    StateManagerImpl.prototype.getState = function () {\n        return this.state;\n    };\n    StateManagerImpl.prototype.failIfTransitionOngoing = function () {\n        if (this.onGoingTransactionNewState\n            !== Html5QrcodeScannerState.UNKNOWN) {\n            throw "Cannot transition to a new state, already under transition";\n        }\n    };\n    StateManagerImpl.prototype.validateTransition = function (newState) {\n        switch (this.state) {\n            case Html5QrcodeScannerState.UNKNOWN:\n                throw "Transition from unknown is not allowed";\n            case Html5QrcodeScannerState.NOT_STARTED:\n                this.failIfNewStateIs(newState, [Html5QrcodeScannerState.PAUSED]);\n                break;\n            case Html5QrcodeScannerState.SCANNING:\n                break;\n            case Html5QrcodeScannerState.PAUSED:\n                break;\n        }\n    };\n    StateManagerImpl.prototype.failIfNewStateIs = function (newState, disallowedStatesToTransition) {\n        for (var _i = 0, disallowedStatesToTransition_1 = disallowedStatesToTransition; _i < disallowedStatesToTransition_1.length; _i++) {\n            var disallowedState = disallowedStatesToTransition_1[_i];\n            if (newState === disallowedState) {\n                throw "Cannot transition from ".concat(this.state, " to ").concat(newState);\n            }\n        }\n    };\n    return StateManagerImpl;\n}());\nvar StateManagerProxy = (function () {\n    function StateManagerProxy(stateManager) {\n        this.stateManager = stateManager;\n    }\n    StateManagerProxy.prototype.startTransition = function (newState) {\n        return this.stateManager.startTransition(newState);\n    };\n    StateManagerProxy.prototype.directTransition = function (newState) {\n        this.stateManager.directTransition(newState);\n    };\n    StateManagerProxy.prototype.getState = function () {\n        return this.stateManager.getState();\n    };\n    StateManagerProxy.prototype.canScanFile = function () {\n        return this.stateManager.getState() === Html5QrcodeScannerState.NOT_STARTED;\n    };\n    StateManagerProxy.prototype.isScanning = function () {\n        return this.stateManager.getState() !== Html5QrcodeScannerState.NOT_STARTED;\n    };\n    StateManagerProxy.prototype.isStrictlyScanning = function () {\n        return this.stateManager.getState() === Html5QrcodeScannerState.SCANNING;\n    };\n    StateManagerProxy.prototype.isPaused = function () {\n        return this.stateManager.getState() === Html5QrcodeScannerState.PAUSED;\n    };\n    return StateManagerProxy;\n}());\n\nvar StateManagerFactory = (function () {\n    function StateManagerFactory() {\n    }\n    StateManagerFactory.create = function () {\n        return new StateManagerProxy(new StateManagerImpl());\n    };\n    return StateManagerFactory;\n}());\n\n//# sourceMappingURL=state-manager.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/html5-qrcode.js\nvar html5_qrcode_extends = (undefined && undefined.__extends) || (function () {\n    var extendStatics = function (d, b) {\n        extendStatics = Object.setPrototypeOf ||\n            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n        return extendStatics(d, b);\n    };\n    return function (d, b) {\n        if (typeof b !== "function" && b !== null)\n            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");\n        extendStatics(d, b);\n        function __() { this.constructor = d; }\n        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n    };\n})();\n\n\n\n\n\n\n\nvar Constants = (function (_super) {\n    html5_qrcode_extends(Constants, _super);\n    function Constants() {\n        return _super !== null && _super.apply(this, arguments) || this;\n    }\n    Constants.DEFAULT_WIDTH = 300;\n    Constants.DEFAULT_WIDTH_OFFSET = 2;\n    Constants.FILE_SCAN_MIN_HEIGHT = 300;\n    Constants.FILE_SCAN_HIDDEN_CANVAS_PADDING = 100;\n    Constants.MIN_QR_BOX_SIZE = 50;\n    Constants.SHADED_LEFT = 1;\n    Constants.SHADED_RIGHT = 2;\n    Constants.SHADED_TOP = 3;\n    Constants.SHADED_BOTTOM = 4;\n    Constants.SHADED_REGION_ELEMENT_ID = "qr-shaded-region";\n    Constants.VERBOSE = false;\n    Constants.BORDER_SHADER_DEFAULT_COLOR = "#ffffff";\n    Constants.BORDER_SHADER_MATCH_COLOR = "rgb(90, 193, 56)";\n    return Constants;\n}(Html5QrcodeConstants));\nvar InternalHtml5QrcodeConfig = (function () {\n    function InternalHtml5QrcodeConfig(config, logger) {\n        this.logger = logger;\n        this.fps = Constants.SCAN_DEFAULT_FPS;\n        if (!config) {\n            this.disableFlip = Constants.DEFAULT_DISABLE_FLIP;\n        }\n        else {\n            if (config.fps) {\n                this.fps = config.fps;\n            }\n            this.disableFlip = config.disableFlip === true;\n            this.qrbox = config.qrbox;\n            this.aspectRatio = config.aspectRatio;\n            this.videoConstraints = config.videoConstraints;\n        }\n    }\n    InternalHtml5QrcodeConfig.prototype.isMediaStreamConstraintsValid = function () {\n        if (!this.videoConstraints) {\n            this.logger.logError("Empty videoConstraints", true);\n            return false;\n        }\n        return VideoConstraintsUtil.isMediaStreamConstraintsValid(this.videoConstraints, this.logger);\n    };\n    InternalHtml5QrcodeConfig.prototype.isShadedBoxEnabled = function () {\n        return !isNullOrUndefined(this.qrbox);\n    };\n    InternalHtml5QrcodeConfig.create = function (config, logger) {\n        return new InternalHtml5QrcodeConfig(config, logger);\n    };\n    return InternalHtml5QrcodeConfig;\n}());\nvar Html5Qrcode = (function () {\n    function Html5Qrcode(elementId, configOrVerbosityFlag) {\n        this.element = null;\n        this.canvasElement = null;\n        this.scannerPausedUiElement = null;\n        this.hasBorderShaders = null;\n        this.borderShaders = null;\n        this.qrMatch = null;\n        this.renderedCamera = null;\n        this.qrRegion = null;\n        this.context = null;\n        this.lastScanImageFile = null;\n        this.isScanning = false;\n        if (!document.getElementById(elementId)) {\n            throw "HTML Element with id=".concat(elementId, " not found");\n        }\n        this.elementId = elementId;\n        this.verbose = false;\n        var experimentalFeatureConfig;\n        var configObject;\n        if (typeof configOrVerbosityFlag == "boolean") {\n            this.verbose = configOrVerbosityFlag === true;\n        }\n        else if (configOrVerbosityFlag) {\n            configObject = configOrVerbosityFlag;\n            this.verbose = configObject.verbose === true;\n            experimentalFeatureConfig = configObject.experimentalFeatures;\n        }\n        this.logger = new BaseLoggger(this.verbose);\n        this.qrcode = new Html5QrcodeShim(this.getSupportedFormats(configOrVerbosityFlag), this.getUseBarCodeDetectorIfSupported(configObject), this.verbose, this.logger);\n        this.foreverScanTimeout;\n        this.shouldScan = true;\n        this.stateManagerProxy = StateManagerFactory.create();\n    }\n    Html5Qrcode.prototype.start = function (cameraIdOrConfig, configuration, qrCodeSuccessCallback, qrCodeErrorCallback) {\n        var _this = this;\n        if (!cameraIdOrConfig) {\n            throw "cameraIdOrConfig is required";\n        }\n        if (!qrCodeSuccessCallback\n            || typeof qrCodeSuccessCallback != "function") {\n            throw "qrCodeSuccessCallback is required and should be a function.";\n        }\n        var qrCodeErrorCallbackInternal;\n        if (qrCodeErrorCallback) {\n            qrCodeErrorCallbackInternal = qrCodeErrorCallback;\n        }\n        else {\n            qrCodeErrorCallbackInternal\n                = this.verbose ? this.logger.log : function () { };\n        }\n        var internalConfig = InternalHtml5QrcodeConfig.create(configuration, this.logger);\n        this.clearElement();\n        var videoConstraintsAvailableAndValid = false;\n        if (internalConfig.videoConstraints) {\n            if (!internalConfig.isMediaStreamConstraintsValid()) {\n                this.logger.logError("\'videoConstraints\' is not valid \'MediaStreamConstraints, "\n                    + "it will be ignored.\'", true);\n            }\n            else {\n                videoConstraintsAvailableAndValid = true;\n            }\n        }\n        var areVideoConstraintsEnabled = videoConstraintsAvailableAndValid;\n        var element = document.getElementById(this.elementId);\n        var rootElementWidth = element.clientWidth\n            ? element.clientWidth : Constants.DEFAULT_WIDTH;\n        element.style.position = "relative";\n        this.shouldScan = true;\n        this.element = element;\n        var $this = this;\n        var toScanningStateChangeTransaction = this.stateManagerProxy.startTransition(Html5QrcodeScannerState.SCANNING);\n        return new Promise(function (resolve, reject) {\n            var videoConstraints = areVideoConstraintsEnabled\n                ? internalConfig.videoConstraints\n                : $this.createVideoConstraints(cameraIdOrConfig);\n            if (!videoConstraints) {\n                toScanningStateChangeTransaction.cancel();\n                reject("videoConstraints should be defined");\n                return;\n            }\n            var cameraRenderingOptions = {};\n            if (!areVideoConstraintsEnabled || internalConfig.aspectRatio) {\n                cameraRenderingOptions.aspectRatio = internalConfig.aspectRatio;\n            }\n            var renderingCallbacks = {\n                onRenderSurfaceReady: function (viewfinderWidth, viewfinderHeight) {\n                    $this.setupUi(viewfinderWidth, viewfinderHeight, internalConfig);\n                    $this.isScanning = true;\n                    $this.foreverScan(internalConfig, qrCodeSuccessCallback, qrCodeErrorCallbackInternal);\n                }\n            };\n            CameraFactory.failIfNotSupported().then(function (factory) {\n                factory.create(videoConstraints).then(function (camera) {\n                    return camera.render(_this.element, cameraRenderingOptions, renderingCallbacks)\n                        .then(function (renderedCamera) {\n                        $this.renderedCamera = renderedCamera;\n                        toScanningStateChangeTransaction.execute();\n                        resolve(null);\n                    })\n                        .catch(function (error) {\n                        toScanningStateChangeTransaction.cancel();\n                        reject(error);\n                    });\n                }).catch(function (error) {\n                    toScanningStateChangeTransaction.cancel();\n                    reject(Html5QrcodeStrings.errorGettingUserMedia(error));\n                });\n            }).catch(function (_) {\n                toScanningStateChangeTransaction.cancel();\n                reject(Html5QrcodeStrings.cameraStreamingNotSupported());\n            });\n        });\n    };\n    Html5Qrcode.prototype.pause = function (shouldPauseVideo) {\n        if (!this.stateManagerProxy.isStrictlyScanning()) {\n            throw "Cannot pause, scanner is not scanning.";\n        }\n        this.stateManagerProxy.directTransition(Html5QrcodeScannerState.PAUSED);\n        this.showPausedState();\n        if (isNullOrUndefined(shouldPauseVideo) || shouldPauseVideo !== true) {\n            shouldPauseVideo = false;\n        }\n        if (shouldPauseVideo && this.renderedCamera) {\n            this.renderedCamera.pause();\n        }\n    };\n    Html5Qrcode.prototype.resume = function () {\n        if (!this.stateManagerProxy.isPaused()) {\n            throw "Cannot result, scanner is not paused.";\n        }\n        if (!this.renderedCamera) {\n            throw "renderedCamera doesn\'t exist while trying resume()";\n        }\n        var $this = this;\n        var transitionToScanning = function () {\n            $this.stateManagerProxy.directTransition(Html5QrcodeScannerState.SCANNING);\n            $this.hidePausedState();\n        };\n        if (!this.renderedCamera.isPaused()) {\n            transitionToScanning();\n            return;\n        }\n        this.renderedCamera.resume(function () {\n            transitionToScanning();\n        });\n    };\n    Html5Qrcode.prototype.getState = function () {\n        return this.stateManagerProxy.getState();\n    };\n    Html5Qrcode.prototype.stop = function () {\n        var _this = this;\n        if (!this.stateManagerProxy.isScanning()) {\n            throw "Cannot stop, scanner is not running or paused.";\n        }\n        var toStoppedStateTransaction = this.stateManagerProxy.startTransition(Html5QrcodeScannerState.NOT_STARTED);\n        this.shouldScan = false;\n        if (this.foreverScanTimeout) {\n            clearTimeout(this.foreverScanTimeout);\n        }\n        var removeQrRegion = function () {\n            if (!_this.element) {\n                return;\n            }\n            var childElement = document.getElementById(Constants.SHADED_REGION_ELEMENT_ID);\n            if (childElement) {\n                _this.element.removeChild(childElement);\n            }\n        };\n        var $this = this;\n        return this.renderedCamera.close().then(function () {\n            $this.renderedCamera = null;\n            if ($this.element) {\n                $this.element.removeChild($this.canvasElement);\n                $this.canvasElement = null;\n            }\n            removeQrRegion();\n            if ($this.qrRegion) {\n                $this.qrRegion = null;\n            }\n            if ($this.context) {\n                $this.context = null;\n            }\n            toStoppedStateTransaction.execute();\n            $this.hidePausedState();\n            $this.isScanning = false;\n            return Promise.resolve();\n        });\n    };\n    Html5Qrcode.prototype.scanFile = function (imageFile, showImage) {\n        return this.scanFileV2(imageFile, showImage)\n            .then(function (html5qrcodeResult) { return html5qrcodeResult.decodedText; });\n    };\n    Html5Qrcode.prototype.scanFileV2 = function (imageFile, showImage) {\n        var _this = this;\n        if (!imageFile || !(imageFile instanceof File)) {\n            throw "imageFile argument is mandatory and should be instance "\n                + "of File. Use \'event.target.files[0]\'.";\n        }\n        if (isNullOrUndefined(showImage)) {\n            showImage = true;\n        }\n        if (!this.stateManagerProxy.canScanFile()) {\n            throw "Cannot start file scan - ongoing camera scan";\n        }\n        return new Promise(function (resolve, reject) {\n            _this.possiblyCloseLastScanImageFile();\n            _this.clearElement();\n            _this.lastScanImageFile = URL.createObjectURL(imageFile);\n            var inputImage = new Image;\n            inputImage.onload = function () {\n                var imageWidth = inputImage.width;\n                var imageHeight = inputImage.height;\n                var element = document.getElementById(_this.elementId);\n                var containerWidth = element.clientWidth\n                    ? element.clientWidth : Constants.DEFAULT_WIDTH;\n                var containerHeight = Math.max(element.clientHeight ? element.clientHeight : imageHeight, Constants.FILE_SCAN_MIN_HEIGHT);\n                var config = _this.computeCanvasDrawConfig(imageWidth, imageHeight, containerWidth, containerHeight);\n                if (showImage) {\n                    var visibleCanvas = _this.createCanvasElement(containerWidth, containerHeight, "qr-canvas-visible");\n                    visibleCanvas.style.display = "inline-block";\n                    element.appendChild(visibleCanvas);\n                    var context_1 = visibleCanvas.getContext("2d");\n                    if (!context_1) {\n                        throw "Unable to get 2d context from canvas";\n                    }\n                    context_1.canvas.width = containerWidth;\n                    context_1.canvas.height = containerHeight;\n                    context_1.drawImage(inputImage, 0, 0, imageWidth, imageHeight, config.x, config.y, config.width, config.height);\n                }\n                var padding = Constants.FILE_SCAN_HIDDEN_CANVAS_PADDING;\n                var hiddenImageWidth = Math.max(inputImage.width, config.width);\n                var hiddenImageHeight = Math.max(inputImage.height, config.height);\n                var hiddenCanvasWidth = hiddenImageWidth + 2 * padding;\n                var hiddenCanvasHeight = hiddenImageHeight + 2 * padding;\n                var hiddenCanvas = _this.createCanvasElement(hiddenCanvasWidth, hiddenCanvasHeight);\n                element.appendChild(hiddenCanvas);\n                var context = hiddenCanvas.getContext("2d");\n                if (!context) {\n                    throw "Unable to get 2d context from canvas";\n                }\n                context.canvas.width = hiddenCanvasWidth;\n                context.canvas.height = hiddenCanvasHeight;\n                context.drawImage(inputImage, 0, 0, imageWidth, imageHeight, padding, padding, hiddenImageWidth, hiddenImageHeight);\n                try {\n                    _this.qrcode.decodeRobustlyAsync(hiddenCanvas)\n                        .then(function (result) {\n                        resolve(Html5QrcodeResultFactory.createFromQrcodeResult(result));\n                    })\n                        .catch(reject);\n                }\n                catch (exception) {\n                    reject("QR code parse error, error = ".concat(exception));\n                }\n            };\n            inputImage.onerror = reject;\n            inputImage.onabort = reject;\n            inputImage.onstalled = reject;\n            inputImage.onsuspend = reject;\n            inputImage.src = URL.createObjectURL(imageFile);\n        });\n    };\n    Html5Qrcode.prototype.clear = function () {\n        this.clearElement();\n    };\n    Html5Qrcode.getCameras = function () {\n        return CameraRetriever.retrieve();\n    };\n    Html5Qrcode.prototype.getRunningTrackCapabilities = function () {\n        return this.getRenderedCameraOrFail().getRunningTrackCapabilities();\n    };\n    Html5Qrcode.prototype.getRunningTrackSettings = function () {\n        return this.getRenderedCameraOrFail().getRunningTrackSettings();\n    };\n    Html5Qrcode.prototype.getRunningTrackCameraCapabilities = function () {\n        return this.getRenderedCameraOrFail().getCapabilities();\n    };\n    Html5Qrcode.prototype.applyVideoConstraints = function (videoConstaints) {\n        if (!videoConstaints) {\n            throw "videoConstaints is required argument.";\n        }\n        else if (!VideoConstraintsUtil.isMediaStreamConstraintsValid(videoConstaints, this.logger)) {\n            throw "invalid videoConstaints passed, check logs for more details";\n        }\n        return this.getRenderedCameraOrFail().applyVideoConstraints(videoConstaints);\n    };\n    Html5Qrcode.prototype.getRenderedCameraOrFail = function () {\n        if (this.renderedCamera == null) {\n            throw "Scanning is not in running state, call this API only when"\n                + " QR code scanning using camera is in running state.";\n        }\n        return this.renderedCamera;\n    };\n    Html5Qrcode.prototype.getSupportedFormats = function (configOrVerbosityFlag) {\n        var allFormats = [\n            Html5QrcodeSupportedFormats.QR_CODE,\n            Html5QrcodeSupportedFormats.AZTEC,\n            Html5QrcodeSupportedFormats.CODABAR,\n            Html5QrcodeSupportedFormats.CODE_39,\n            Html5QrcodeSupportedFormats.CODE_93,\n            Html5QrcodeSupportedFormats.CODE_128,\n            Html5QrcodeSupportedFormats.DATA_MATRIX,\n            Html5QrcodeSupportedFormats.MAXICODE,\n            Html5QrcodeSupportedFormats.ITF,\n            Html5QrcodeSupportedFormats.EAN_13,\n            Html5QrcodeSupportedFormats.EAN_8,\n            Html5QrcodeSupportedFormats.PDF_417,\n            Html5QrcodeSupportedFormats.RSS_14,\n            Html5QrcodeSupportedFormats.RSS_EXPANDED,\n            Html5QrcodeSupportedFormats.UPC_A,\n            Html5QrcodeSupportedFormats.UPC_E,\n            Html5QrcodeSupportedFormats.UPC_EAN_EXTENSION,\n        ];\n        if (!configOrVerbosityFlag\n            || typeof configOrVerbosityFlag == "boolean") {\n            return allFormats;\n        }\n        if (!configOrVerbosityFlag.formatsToSupport) {\n            return allFormats;\n        }\n        if (!Array.isArray(configOrVerbosityFlag.formatsToSupport)) {\n            throw "configOrVerbosityFlag.formatsToSupport should be undefined "\n                + "or an array.";\n        }\n        if (configOrVerbosityFlag.formatsToSupport.length === 0) {\n            throw "Atleast 1 formatsToSupport is needed.";\n        }\n        var supportedFormats = [];\n        for (var _i = 0, _a = configOrVerbosityFlag.formatsToSupport; _i < _a.length; _i++) {\n            var format = _a[_i];\n            if (isValidHtml5QrcodeSupportedFormats(format)) {\n                supportedFormats.push(format);\n            }\n            else {\n                this.logger.warn("Invalid format: ".concat(format, " passed in config, ignoring."));\n            }\n        }\n        if (supportedFormats.length === 0) {\n            throw "None of formatsToSupport match supported values.";\n        }\n        return supportedFormats;\n    };\n    Html5Qrcode.prototype.getUseBarCodeDetectorIfSupported = function (config) {\n        if (isNullOrUndefined(config)) {\n            return true;\n        }\n        if (!isNullOrUndefined(config.useBarCodeDetectorIfSupported)) {\n            return config.useBarCodeDetectorIfSupported !== false;\n        }\n        if (isNullOrUndefined(config.experimentalFeatures)) {\n            return true;\n        }\n        var experimentalFeatures = config.experimentalFeatures;\n        if (isNullOrUndefined(experimentalFeatures.useBarCodeDetectorIfSupported)) {\n            return true;\n        }\n        return experimentalFeatures.useBarCodeDetectorIfSupported !== false;\n    };\n    Html5Qrcode.prototype.validateQrboxSize = function (viewfinderWidth, viewfinderHeight, internalConfig) {\n        var _this = this;\n        var qrboxSize = internalConfig.qrbox;\n        this.validateQrboxConfig(qrboxSize);\n        var qrDimensions = this.toQrdimensions(viewfinderWidth, viewfinderHeight, qrboxSize);\n        var validateMinSize = function (size) {\n            if (size < Constants.MIN_QR_BOX_SIZE) {\n                throw "minimum size of \'config.qrbox\' dimension value is"\n                    + " ".concat(Constants.MIN_QR_BOX_SIZE, "px.");\n            }\n        };\n        var correctWidthBasedOnRootElementSize = function (configWidth) {\n            if (configWidth > viewfinderWidth) {\n                _this.logger.warn("`qrbox.width` or `qrbox` is larger than the"\n                    + " width of the root element. The width will be truncated"\n                    + " to the width of root element.");\n                configWidth = viewfinderWidth;\n            }\n            return configWidth;\n        };\n        validateMinSize(qrDimensions.width);\n        validateMinSize(qrDimensions.height);\n        qrDimensions.width = correctWidthBasedOnRootElementSize(qrDimensions.width);\n    };\n    Html5Qrcode.prototype.validateQrboxConfig = function (qrboxSize) {\n        if (typeof qrboxSize === "number") {\n            return;\n        }\n        if (typeof qrboxSize === "function") {\n            return;\n        }\n        if (qrboxSize.width === undefined || qrboxSize.height === undefined) {\n            throw "Invalid instance of QrDimensions passed for "\n                + "\'config.qrbox\'. Both \'width\' and \'height\' should be set.";\n        }\n    };\n    Html5Qrcode.prototype.toQrdimensions = function (viewfinderWidth, viewfinderHeight, qrboxSize) {\n        if (typeof qrboxSize === "number") {\n            return { width: qrboxSize, height: qrboxSize };\n        }\n        else if (typeof qrboxSize === "function") {\n            try {\n                return qrboxSize(viewfinderWidth, viewfinderHeight);\n            }\n            catch (error) {\n                throw new Error("qrbox config was passed as a function but it failed with "\n                    + "unknown error" + error);\n            }\n        }\n        return qrboxSize;\n    };\n    Html5Qrcode.prototype.setupUi = function (viewfinderWidth, viewfinderHeight, internalConfig) {\n        if (internalConfig.isShadedBoxEnabled()) {\n            this.validateQrboxSize(viewfinderWidth, viewfinderHeight, internalConfig);\n        }\n        var qrboxSize = isNullOrUndefined(internalConfig.qrbox) ?\n            { width: viewfinderWidth, height: viewfinderHeight } : internalConfig.qrbox;\n        this.validateQrboxConfig(qrboxSize);\n        var qrDimensions = this.toQrdimensions(viewfinderWidth, viewfinderHeight, qrboxSize);\n        if (qrDimensions.height > viewfinderHeight) {\n            this.logger.warn("[Html5Qrcode] config.qrbox has height that is"\n                + "greater than the height of the video stream. Shading will be"\n                + " ignored");\n        }\n        var shouldShadingBeApplied = internalConfig.isShadedBoxEnabled()\n            && qrDimensions.height <= viewfinderHeight;\n        var defaultQrRegion = {\n            x: 0,\n            y: 0,\n            width: viewfinderWidth,\n            height: viewfinderHeight\n        };\n        var qrRegion = shouldShadingBeApplied\n            ? this.getShadedRegionBounds(viewfinderWidth, viewfinderHeight, qrDimensions)\n            : defaultQrRegion;\n        var canvasElement = this.createCanvasElement(qrRegion.width, qrRegion.height);\n        var contextAttributes = { willReadFrequently: true };\n        var context = canvasElement.getContext("2d", contextAttributes);\n        context.canvas.width = qrRegion.width;\n        context.canvas.height = qrRegion.height;\n        this.element.append(canvasElement);\n        if (shouldShadingBeApplied) {\n            this.possiblyInsertShadingElement(this.element, viewfinderWidth, viewfinderHeight, qrDimensions);\n        }\n        this.createScannerPausedUiElement(this.element);\n        this.qrRegion = qrRegion;\n        this.context = context;\n        this.canvasElement = canvasElement;\n    };\n    Html5Qrcode.prototype.createScannerPausedUiElement = function (rootElement) {\n        var scannerPausedUiElement = document.createElement("div");\n        scannerPausedUiElement.innerText = Html5QrcodeStrings.scannerPaused();\n        scannerPausedUiElement.style.display = "none";\n        scannerPausedUiElement.style.position = "absolute";\n        scannerPausedUiElement.style.top = "0px";\n        scannerPausedUiElement.style.zIndex = "1";\n        scannerPausedUiElement.style.background = "rgba(9, 9, 9, 0.46)";\n        scannerPausedUiElement.style.color = "#FFECEC";\n        scannerPausedUiElement.style.textAlign = "center";\n        scannerPausedUiElement.style.width = "100%";\n        rootElement.appendChild(scannerPausedUiElement);\n        this.scannerPausedUiElement = scannerPausedUiElement;\n    };\n    Html5Qrcode.prototype.scanContext = function (qrCodeSuccessCallback, qrCodeErrorCallback) {\n        var _this = this;\n        if (this.stateManagerProxy.isPaused()) {\n            return Promise.resolve(false);\n        }\n        return this.qrcode.decodeAsync(this.canvasElement)\n            .then(function (result) {\n            qrCodeSuccessCallback(result.text, Html5QrcodeResultFactory.createFromQrcodeResult(result));\n            _this.possiblyUpdateShaders(true);\n            return true;\n        }).catch(function (error) {\n            _this.possiblyUpdateShaders(false);\n            var errorMessage = Html5QrcodeStrings.codeParseError(error);\n            qrCodeErrorCallback(errorMessage, Html5QrcodeErrorFactory.createFrom(errorMessage));\n            return false;\n        });\n    };\n    Html5Qrcode.prototype.foreverScan = function (internalConfig, qrCodeSuccessCallback, qrCodeErrorCallback) {\n        var _this = this;\n        if (!this.shouldScan) {\n            return;\n        }\n        if (!this.renderedCamera) {\n            return;\n        }\n        var videoElement = this.renderedCamera.getSurface();\n        var widthRatio = videoElement.videoWidth / videoElement.clientWidth;\n        var heightRatio = videoElement.videoHeight / videoElement.clientHeight;\n        if (!this.qrRegion) {\n            throw "qrRegion undefined when localMediaStream is ready.";\n        }\n        var sWidthOffset = this.qrRegion.width * widthRatio;\n        var sHeightOffset = this.qrRegion.height * heightRatio;\n        var sxOffset = this.qrRegion.x * widthRatio;\n        var syOffset = this.qrRegion.y * heightRatio;\n        this.context.drawImage(videoElement, sxOffset, syOffset, sWidthOffset, sHeightOffset, 0, 0, this.qrRegion.width, this.qrRegion.height);\n        var triggerNextScan = function () {\n            _this.foreverScanTimeout = setTimeout(function () {\n                _this.foreverScan(internalConfig, qrCodeSuccessCallback, qrCodeErrorCallback);\n            }, _this.getTimeoutFps(internalConfig.fps));\n        };\n        this.scanContext(qrCodeSuccessCallback, qrCodeErrorCallback)\n            .then(function (isSuccessfull) {\n            if (!isSuccessfull && internalConfig.disableFlip !== true) {\n                _this.context.translate(_this.context.canvas.width, 0);\n                _this.context.scale(-1, 1);\n                _this.scanContext(qrCodeSuccessCallback, qrCodeErrorCallback)\n                    .finally(function () {\n                    triggerNextScan();\n                });\n            }\n            else {\n                triggerNextScan();\n            }\n        }).catch(function (error) {\n            _this.logger.logError("Error happend while scanning context", error);\n            triggerNextScan();\n        });\n    };\n    Html5Qrcode.prototype.createVideoConstraints = function (cameraIdOrConfig) {\n        if (typeof cameraIdOrConfig == "string") {\n            return { deviceId: { exact: cameraIdOrConfig } };\n        }\n        else if (typeof cameraIdOrConfig == "object") {\n            var facingModeKey = "facingMode";\n            var deviceIdKey = "deviceId";\n            var allowedFacingModeValues_1 = { "user": true, "environment": true };\n            var exactKey = "exact";\n            var isValidFacingModeValue = function (value) {\n                if (value in allowedFacingModeValues_1) {\n                    return true;\n                }\n                else {\n                    throw "config has invalid \'facingMode\' value = "\n                        + "\'".concat(value, "\'");\n                }\n            };\n            var keys = Object.keys(cameraIdOrConfig);\n            if (keys.length !== 1) {\n                throw "\'cameraIdOrConfig\' object should have exactly 1 key,"\n                    + " if passed as an object, found ".concat(keys.length, " keys");\n            }\n            var key = Object.keys(cameraIdOrConfig)[0];\n            if (key !== facingModeKey && key !== deviceIdKey) {\n                throw "Only \'".concat(facingModeKey, "\' and \'").concat(deviceIdKey, "\' ")\n                    + " are supported for \'cameraIdOrConfig\'";\n            }\n            if (key === facingModeKey) {\n                var facingMode = cameraIdOrConfig.facingMode;\n                if (typeof facingMode == "string") {\n                    if (isValidFacingModeValue(facingMode)) {\n                        return { facingMode: facingMode };\n                    }\n                }\n                else if (typeof facingMode == "object") {\n                    if (exactKey in facingMode) {\n                        if (isValidFacingModeValue(facingMode["".concat(exactKey)])) {\n                            return {\n                                facingMode: {\n                                    exact: facingMode["".concat(exactKey)]\n                                }\n                            };\n                        }\n                    }\n                    else {\n                        throw "\'facingMode\' should be string or object with"\n                            + " ".concat(exactKey, " as key.");\n                    }\n                }\n                else {\n                    var type_1 = (typeof facingMode);\n                    throw "Invalid type of \'facingMode\' = ".concat(type_1);\n                }\n            }\n            else {\n                var deviceId = cameraIdOrConfig.deviceId;\n                if (typeof deviceId == "string") {\n                    return { deviceId: deviceId };\n                }\n                else if (typeof deviceId == "object") {\n                    if (exactKey in deviceId) {\n                        return {\n                            deviceId: { exact: deviceId["".concat(exactKey)] }\n                        };\n                    }\n                    else {\n                        throw "\'deviceId\' should be string or object with"\n                            + " ".concat(exactKey, " as key.");\n                    }\n                }\n                else {\n                    var type_2 = (typeof deviceId);\n                    throw "Invalid type of \'deviceId\' = ".concat(type_2);\n                }\n            }\n        }\n        var type = (typeof cameraIdOrConfig);\n        throw "Invalid type of \'cameraIdOrConfig\' = ".concat(type);\n    };\n    Html5Qrcode.prototype.computeCanvasDrawConfig = function (imageWidth, imageHeight, containerWidth, containerHeight) {\n        if (imageWidth <= containerWidth\n            && imageHeight <= containerHeight) {\n            var xoffset = (containerWidth - imageWidth) / 2;\n            var yoffset = (containerHeight - imageHeight) / 2;\n            return {\n                x: xoffset,\n                y: yoffset,\n                width: imageWidth,\n                height: imageHeight\n            };\n        }\n        else {\n            var formerImageWidth = imageWidth;\n            var formerImageHeight = imageHeight;\n            if (imageWidth > containerWidth) {\n                imageHeight = (containerWidth / imageWidth) * imageHeight;\n                imageWidth = containerWidth;\n            }\n            if (imageHeight > containerHeight) {\n                imageWidth = (containerHeight / imageHeight) * imageWidth;\n                imageHeight = containerHeight;\n            }\n            this.logger.log("Image downsampled from "\n                + "".concat(formerImageWidth, "X").concat(formerImageHeight)\n                + " to ".concat(imageWidth, "X").concat(imageHeight, "."));\n            return this.computeCanvasDrawConfig(imageWidth, imageHeight, containerWidth, containerHeight);\n        }\n    };\n    Html5Qrcode.prototype.clearElement = function () {\n        if (this.stateManagerProxy.isScanning()) {\n            throw "Cannot clear while scan is ongoing, close it first.";\n        }\n        var element = document.getElementById(this.elementId);\n        if (element) {\n            element.innerHTML = "";\n        }\n    };\n    Html5Qrcode.prototype.possiblyUpdateShaders = function (qrMatch) {\n        if (this.qrMatch === qrMatch) {\n            return;\n        }\n        if (this.hasBorderShaders\n            && this.borderShaders\n            && this.borderShaders.length) {\n            this.borderShaders.forEach(function (shader) {\n                shader.style.backgroundColor = qrMatch\n                    ? Constants.BORDER_SHADER_MATCH_COLOR\n                    : Constants.BORDER_SHADER_DEFAULT_COLOR;\n            });\n        }\n        this.qrMatch = qrMatch;\n    };\n    Html5Qrcode.prototype.possiblyCloseLastScanImageFile = function () {\n        if (this.lastScanImageFile) {\n            URL.revokeObjectURL(this.lastScanImageFile);\n            this.lastScanImageFile = null;\n        }\n    };\n    Html5Qrcode.prototype.createCanvasElement = function (width, height, customId) {\n        var canvasWidth = width;\n        var canvasHeight = height;\n        var canvasElement = document.createElement("canvas");\n        canvasElement.style.width = "".concat(canvasWidth, "px");\n        canvasElement.style.height = "".concat(canvasHeight, "px");\n        canvasElement.style.display = "none";\n        canvasElement.id = isNullOrUndefined(customId)\n            ? "qr-canvas" : customId;\n        return canvasElement;\n    };\n    Html5Qrcode.prototype.getShadedRegionBounds = function (width, height, qrboxSize) {\n        if (qrboxSize.width > width || qrboxSize.height > height) {\n            throw "\'config.qrbox\' dimensions should not be greater than the "\n                + "dimensions of the root HTML element.";\n        }\n        return {\n            x: (width - qrboxSize.width) / 2,\n            y: (height - qrboxSize.height) / 2,\n            width: qrboxSize.width,\n            height: qrboxSize.height\n        };\n    };\n    Html5Qrcode.prototype.possiblyInsertShadingElement = function (element, width, height, qrboxSize) {\n        if ((width - qrboxSize.width) < 1 || (height - qrboxSize.height) < 1) {\n            return;\n        }\n        var shadingElement = document.createElement("div");\n        shadingElement.style.position = "absolute";\n        var rightLeftBorderSize = (width - qrboxSize.width) / 2;\n        var topBottomBorderSize = (height - qrboxSize.height) / 2;\n        shadingElement.style.borderLeft\n            = "".concat(rightLeftBorderSize, "px solid rgba(0, 0, 0, 0.48)");\n        shadingElement.style.borderRight\n            = "".concat(rightLeftBorderSize, "px solid rgba(0, 0, 0, 0.48)");\n        shadingElement.style.borderTop\n            = "".concat(topBottomBorderSize, "px solid rgba(0, 0, 0, 0.48)");\n        shadingElement.style.borderBottom\n            = "".concat(topBottomBorderSize, "px solid rgba(0, 0, 0, 0.48)");\n        shadingElement.style.boxSizing = "border-box";\n        shadingElement.style.top = "0px";\n        shadingElement.style.bottom = "0px";\n        shadingElement.style.left = "0px";\n        shadingElement.style.right = "0px";\n        shadingElement.id = "".concat(Constants.SHADED_REGION_ELEMENT_ID);\n        if ((width - qrboxSize.width) < 11\n            || (height - qrboxSize.height) < 11) {\n            this.hasBorderShaders = false;\n        }\n        else {\n            var smallSize = 5;\n            var largeSize = 40;\n            this.insertShaderBorders(shadingElement, largeSize, smallSize, -smallSize, null, 0, true);\n            this.insertShaderBorders(shadingElement, largeSize, smallSize, -smallSize, null, 0, false);\n            this.insertShaderBorders(shadingElement, largeSize, smallSize, null, -smallSize, 0, true);\n            this.insertShaderBorders(shadingElement, largeSize, smallSize, null, -smallSize, 0, false);\n            this.insertShaderBorders(shadingElement, smallSize, largeSize + smallSize, -smallSize, null, -smallSize, true);\n            this.insertShaderBorders(shadingElement, smallSize, largeSize + smallSize, null, -smallSize, -smallSize, true);\n            this.insertShaderBorders(shadingElement, smallSize, largeSize + smallSize, -smallSize, null, -smallSize, false);\n            this.insertShaderBorders(shadingElement, smallSize, largeSize + smallSize, null, -smallSize, -smallSize, false);\n            this.hasBorderShaders = true;\n        }\n        element.append(shadingElement);\n    };\n    Html5Qrcode.prototype.insertShaderBorders = function (shaderElem, width, height, top, bottom, side, isLeft) {\n        var elem = document.createElement("div");\n        elem.style.position = "absolute";\n        elem.style.backgroundColor = Constants.BORDER_SHADER_DEFAULT_COLOR;\n        elem.style.width = "".concat(width, "px");\n        elem.style.height = "".concat(height, "px");\n        if (top !== null) {\n            elem.style.top = "".concat(top, "px");\n        }\n        if (bottom !== null) {\n            elem.style.bottom = "".concat(bottom, "px");\n        }\n        if (isLeft) {\n            elem.style.left = "".concat(side, "px");\n        }\n        else {\n            elem.style.right = "".concat(side, "px");\n        }\n        if (!this.borderShaders) {\n            this.borderShaders = [];\n        }\n        this.borderShaders.push(elem);\n        shaderElem.appendChild(elem);\n    };\n    Html5Qrcode.prototype.showPausedState = function () {\n        if (!this.scannerPausedUiElement) {\n            throw "[internal error] scanner paused UI element not found";\n        }\n        this.scannerPausedUiElement.style.display = "block";\n    };\n    Html5Qrcode.prototype.hidePausedState = function () {\n        if (!this.scannerPausedUiElement) {\n            throw "[internal error] scanner paused UI element not found";\n        }\n        this.scannerPausedUiElement.style.display = "none";\n    };\n    Html5Qrcode.prototype.getTimeoutFps = function (fps) {\n        return 1000 / fps;\n    };\n    return Html5Qrcode;\n}());\n\n//# sourceMappingURL=html5-qrcode.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/image-assets.js\nvar SVG_XML_PREFIX = "data:image/svg+xml;base64,";\nvar ASSET_CAMERA_SCAN = SVG_XML_PREFIX + "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzNzEuNjQzIDM3MS42NDMiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDM3MS42NDMgMzcxLjY0MyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBhdGggZD0iTTEwNS4wODQgMzguMjcxaDE2My43Njh2MjBIMTA1LjA4NHoiLz48cGF0aCBkPSJNMzExLjU5NiAxOTAuMTg5Yy03LjQ0MS05LjM0Ny0xOC40MDMtMTYuMjA2LTMyLjc0My0yMC41MjJWMzBjMC0xNi41NDItMTMuNDU4LTMwLTMwLTMwSDEyNS4wODRjLTE2LjU0MiAwLTMwIDEzLjQ1OC0zMCAzMHYxMjAuMTQzaC04LjI5NmMtMTYuNTQyIDAtMzAgMTMuNDU4LTMwIDMwdjEuMzMzYTI5LjgwNCAyOS44MDQgMCAwIDAgNC42MDMgMTUuOTM5Yy03LjM0IDUuNDc0LTEyLjEwMyAxNC4yMjEtMTIuMTAzIDI0LjA2MXYxLjMzM2MwIDkuODQgNC43NjMgMTguNTg3IDEyLjEwMyAyNC4wNjJhMjkuODEgMjkuODEgMCAwIDAtNC42MDMgMTUuOTM4djEuMzMzYzAgMTYuNTQyIDEzLjQ1OCAzMCAzMCAzMGg4LjMyNGMuNDI3IDExLjYzMSA3LjUwMyAyMS41ODcgMTcuNTM0IDI2LjE3Ny45MzEgMTAuNTAzIDQuMDg0IDMwLjE4NyAxNC43NjggNDUuNTM3YTkuOTg4IDkuOTg4IDAgMCAwIDguMjE2IDQuMjg4IDkuOTU4IDkuOTU4IDAgMCAwIDUuNzA0LTEuNzkzYzQuNTMzLTMuMTU1IDUuNjUtOS4zODggMi40OTUtMTMuOTIxLTYuNzk4LTkuNzY3LTkuNjAyLTIyLjYwOC0xMC43Ni0zMS40aDgyLjY4NWMuMjcyLjQxNC41NDUuODE4LjgxNSAxLjIxIDMuMTQyIDQuNTQxIDkuMzcyIDUuNjc5IDEzLjkxMyAyLjUzNCA0LjU0Mi0zLjE0MiA1LjY3Ny05LjM3MSAyLjUzNS0xMy45MTMtMTEuOTE5LTE3LjIyOS04Ljc4Ny0zNS44ODQgOS41ODEtNTcuMDEyIDMuMDY3LTIuNjUyIDEyLjMwNy0xMS43MzIgMTEuMjE3LTI0LjAzMy0uODI4LTkuMzQzLTcuMTA5LTE3LjE5NC0xOC42NjktMjMuMzM3YTkuODU3IDkuODU3IDAgMCAwLTEuMDYxLS40ODZjLS40NjYtLjE4Mi0xMS40MDMtNC41NzktOS43NDEtMTUuNzA2IDEuMDA3LTYuNzM3IDE0Ljc2OC04LjI3MyAyMy43NjYtNy42NjYgMjMuMTU2IDEuNTY5IDM5LjY5OCA3LjgwMyA0Ny44MzYgMTguMDI2IDUuNzUyIDcuMjI1IDcuNjA3IDE2LjYyMyA1LjY3MyAyOC43MzMtLjQxMyAyLjU4NS0uODI0IDUuMjQxLTEuMjQ1IDcuOTU5LTUuNzU2IDM3LjE5NC0xMi45MTkgODMuNDgzLTQ5Ljg3IDExNC42NjEtNC4yMjEgMy41NjEtNC43NTYgOS44Ny0xLjE5NCAxNC4wOTJhOS45OCA5Ljk4IDAgMCAwIDcuNjQ4IDMuNTUxIDkuOTU1IDkuOTU1IDAgMCAwIDYuNDQ0LTIuMzU4YzQyLjY3Mi0zNi4wMDUgNTAuODAyLTg4LjUzMyA1Ni43MzctMTI2Ljg4OC40MTUtMi42ODQuODIxLTUuMzA5IDEuMjI5LTcuODYzIDIuODM0LTE3LjcyMS0uNDU1LTMyLjY0MS05Ljc3Mi00NC4zNDV6bS0yMzIuMzA4IDQyLjYyYy01LjUxNCAwLTEwLTQuNDg2LTEwLTEwdi0xLjMzM2MwLTUuNTE0IDQuNDg2LTEwIDEwLTEwaDE1djIxLjMzM2gtMTV6bS0yLjUtNTIuNjY2YzAtNS41MTQgNC40ODYtMTAgMTAtMTBoNy41djIxLjMzM2gtNy41Yy01LjUxNCAwLTEwLTQuNDg2LTEwLTEwdi0xLjMzM3ptMTcuNSA5My45OTloLTcuNWMtNS41MTQgMC0xMC00LjQ4Ni0xMC0xMHYtMS4zMzNjMC01LjUxNCA0LjQ4Ni0xMCAxMC0xMGg3LjV2MjEuMzMzem0zMC43OTYgMjguODg3Yy01LjUxNCAwLTEwLTQuNDg2LTEwLTEwdi04LjI3MWg5MS40NTdjLS44NTEgNi42NjgtLjQzNyAxMi43ODcuNzMxIDE4LjI3MWgtODIuMTg4em03OS40ODItMTEzLjY5OGMtMy4xMjQgMjAuOTA2IDEyLjQyNyAzMy4xODQgMjEuNjI1IDM3LjA0IDUuNDQxIDIuOTY4IDcuNTUxIDUuNjQ3IDcuNzAxIDcuMTg4LjIxIDIuMTUtMi41NTMgNS42ODQtNC40NzcgNy4yNTEtLjQ4Mi4zNzgtLjkyOS44LTEuMzM1IDEuMjYxLTYuOTg3IDcuOTM2LTExLjk4MiAxNS41Mi0xNS40MzIgMjIuNjg4aC05Ny41NjRWMzBjMC01LjUxNCA0LjQ4Ni0xMCAxMC0xMGgxMjMuNzY5YzUuNTE0IDAgMTAgNC40ODYgMTAgMTB2MTM1LjU3OWMtMy4wMzItLjM4MS02LjE1LS42OTQtOS4zODktLjkxNC0yNS4xNTktMS42OTQtNDIuMzcgNy43NDgtNDQuODk4IDI0LjY2NnoiLz48cGF0aCBkPSJNMTc5LjEyOSA4My4xNjdoLTI0LjA2YTUgNSAwIDAgMC01IDV2MjQuMDYxYTUgNSAwIDAgMCA1IDVoMjQuMDZhNSA1IDAgMCAwIDUtNVY4OC4xNjdhNSA1IDAgMCAwLTUtNXpNMTcyLjYyOSAxNDIuODZoLTEyLjU2VjEzMC44YTUgNSAwIDEgMC0xMCAwdjE3LjA2MWE1IDUgMCAwIDAgNSA1aDE3LjU2YTUgNSAwIDEgMCAwLTEwLjAwMXpNMjE2LjU2OCA4My4xNjdoLTI0LjA2YTUgNSAwIDAgMC01IDV2MjQuMDYxYTUgNSAwIDAgMCA1IDVoMjQuMDZhNSA1IDAgMCAwIDUtNVY4OC4xNjdhNSA1IDAgMCAwLTUtNXptLTUgMjQuMDYxaC0xNC4wNlY5My4xNjdoMTQuMDZ2MTQuMDYxek0yMTEuNjY5IDEyNS45MzZIMTk3LjQxYTUgNSAwIDAgMC01IDV2MTQuMjU3YTUgNSAwIDAgMCA1IDVoMTQuMjU5YTUgNSAwIDAgMCA1LTV2LTE0LjI1N2E1IDUgMCAwIDAtNS01eiIvPjwvc3ZnPg==";\nvar ASSET_FILE_SCAN = SVG_XML_PREFIX + "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1OS4wMTggNTkuMDE4IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1OS4wMTggNTkuMDE4IiB4bWw6c3BhY2U9InByZXNlcnZlIj48cGF0aCBkPSJtNTguNzQxIDU0LjgwOS01Ljk2OS02LjI0NGExMC43NCAxMC43NCAwIDAgMCAyLjgyLTcuMjVjMC01Ljk1My00Ljg0My0xMC43OTYtMTAuNzk2LTEwLjc5NlMzNCAzNS4zNjEgMzQgNDEuMzE0IDM4Ljg0MyA1Mi4xMSA0NC43OTYgNTIuMTFjMi40NDEgMCA0LjY4OC0uODI0IDYuNDk5LTIuMTk2bDYuMDAxIDYuMjc3YS45OTguOTk4IDAgMCAwIDEuNDE0LjAzMiAxIDEgMCAwIDAgLjAzMS0xLjQxNHpNMzYgNDEuMzE0YzAtNC44NSAzLjk0Ni04Ljc5NiA4Ljc5Ni04Ljc5NnM4Ljc5NiAzLjk0NiA4Ljc5NiA4Ljc5Ni0zLjk0NiA4Ljc5Ni04Ljc5NiA4Ljc5NlMzNiA0Ni4xNjQgMzYgNDEuMzE0ek0xMC40MzEgMTYuMDg4YzAgMy4wNyAyLjQ5OCA1LjU2OCA1LjU2OSA1LjU2OHM1LjU2OS0yLjQ5OCA1LjU2OS01LjU2OGMwLTMuMDcxLTIuNDk4LTUuNTY5LTUuNTY5LTUuNTY5cy01LjU2OSAyLjQ5OC01LjU2OSA1LjU2OXptOS4xMzggMGMwIDEuOTY4LTEuNjAyIDMuNTY4LTMuNTY5IDMuNTY4cy0zLjU2OS0xLjYwMS0zLjU2OS0zLjU2OCAxLjYwMi0zLjU2OSAzLjU2OS0zLjU2OSAzLjU2OSAxLjYwMSAzLjU2OSAzLjU2OXoiLz48cGF0aCBkPSJtMzAuODgyIDI4Ljk4NyA5LjE4LTEwLjA1NCAxMS4yNjIgMTAuMzIzYTEgMSAwIDAgMCAxLjM1MS0xLjQ3NWwtMTItMTFhMSAxIDAgMCAwLTEuNDE0LjA2M2wtOS43OTQgMTAuNzI3LTQuNzQzLTQuNzQzYTEuMDAzIDEuMDAzIDAgMCAwLTEuMzY4LS4wNDRMNi4zMzkgMzcuNzY4YTEgMSAwIDEgMCAxLjMyMiAxLjUwMWwxNi4zMTMtMTQuMzYyIDcuMzE5IDcuMzE4YS45OTkuOTk5IDAgMSAwIDEuNDE0LTEuNDE0bC0xLjgyNS0xLjgyNHoiLz48cGF0aCBkPSJNMzAgNDYuNTE4SDJ2LTQyaDU0djI4YTEgMSAwIDEgMCAyIDB2LTI5YTEgMSAwIDAgMC0xLTFIMWExIDEgMCAwIDAtMSAxdjQ0YTEgMSAwIDAgMCAxIDFoMjlhMSAxIDAgMSAwIDAtMnoiLz48L3N2Zz4=";\nvar ASSET_INFO_ICON_16PX = SVG_XML_PREFIX + "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NjAgNDYwIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA0NjAgNDYwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48cGF0aCBkPSJNMjMwIDBDMTAyLjk3NSAwIDAgMTAyLjk3NSAwIDIzMHMxMDIuOTc1IDIzMCAyMzAgMjMwIDIzMC0xMDIuOTc0IDIzMC0yMzBTMzU3LjAyNSAwIDIzMCAwem0zOC4zMzMgMzc3LjM2YzAgOC42NzYtNy4wMzQgMTUuNzEtMTUuNzEgMTUuNzFoLTQzLjEwMWMtOC42NzYgMC0xNS43MS03LjAzNC0xNS43MS0xNS43MVYyMDIuNDc3YzAtOC42NzYgNy4wMzMtMTUuNzEgMTUuNzEtMTUuNzFoNDMuMTAxYzguNjc2IDAgMTUuNzEgNy4wMzMgMTUuNzEgMTUuNzFWMzc3LjM2ek0yMzAgMTU3Yy0yMS41MzkgMC0zOS0xNy40NjEtMzktMzlzMTcuNDYxLTM5IDM5LTM5IDM5IDE3LjQ2MSAzOSAzOS0xNy40NjEgMzktMzkgMzl6Ii8+PC9zdmc+";\nvar ASSET_CLOSE_ICON_16PX = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAQgAAAEIBarqQRAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAE1SURBVDiNfdI7S0NBEAXgLya1otFgpbYSbISAgpXYi6CmiH9KCAiChaVga6OiWPgfRDQ+0itaGVNosXtluWwcuMzePfM4M3sq8lbHBubwg1dc4m1E/J/N4ghDPOIsfk/4xiEao5KX0McFljN4C9d4QTPXuY99jP3DsIoDPGM6BY5i5yI5R7O4q+ImFkJY2DCh3cAH2klyB+9J1xUMMAG7eCh1a+Mr+k48b5diXrFVwwLuS+BJ9MfR7+G0FHOHhTHhnXNWS87VDF4pcnfQK4Ep7XScNLmPTZgURNKKYENYWDpzW1BhscS1WHS8CDgURFJQrWcoF3c13KKbgg1BYQfy8xZWEzTTw1QZbAoKu8FqJnktdu5hcVSHmchiILzzuaDQvjBzV2m8yohCE1jHfPx/xhU+y4G/D75ELlRJsSYAAAAASUVORK5CYII=";\n//# sourceMappingURL=image-assets.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/storage.js\nvar PersistedDataFactory = (function () {\n    function PersistedDataFactory() {\n    }\n    PersistedDataFactory.createDefault = function () {\n        return {\n            hasPermission: false,\n            lastUsedCameraId: null\n        };\n    };\n    return PersistedDataFactory;\n}());\nvar PersistedDataManager = (function () {\n    function PersistedDataManager() {\n        this.data = PersistedDataFactory.createDefault();\n        var data = localStorage.getItem(PersistedDataManager.LOCAL_STORAGE_KEY);\n        if (!data) {\n            this.reset();\n        }\n        else {\n            this.data = JSON.parse(data);\n        }\n    }\n    PersistedDataManager.prototype.hasCameraPermissions = function () {\n        return this.data.hasPermission;\n    };\n    PersistedDataManager.prototype.getLastUsedCameraId = function () {\n        return this.data.lastUsedCameraId;\n    };\n    PersistedDataManager.prototype.setHasPermission = function (hasPermission) {\n        this.data.hasPermission = hasPermission;\n        this.flush();\n    };\n    PersistedDataManager.prototype.setLastUsedCameraId = function (lastUsedCameraId) {\n        this.data.lastUsedCameraId = lastUsedCameraId;\n        this.flush();\n    };\n    PersistedDataManager.prototype.resetLastUsedCameraId = function () {\n        this.data.lastUsedCameraId = null;\n        this.flush();\n    };\n    PersistedDataManager.prototype.reset = function () {\n        this.data = PersistedDataFactory.createDefault();\n        this.flush();\n    };\n    PersistedDataManager.prototype.flush = function () {\n        localStorage.setItem(PersistedDataManager.LOCAL_STORAGE_KEY, JSON.stringify(this.data));\n    };\n    PersistedDataManager.LOCAL_STORAGE_KEY = "HTML5_QRCODE_DATA";\n    return PersistedDataManager;\n}());\n\n//# sourceMappingURL=storage.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/ui.js\n\n\nvar LibraryInfoDiv = (function () {\n    function LibraryInfoDiv() {\n        this.infoDiv = document.createElement("div");\n    }\n    LibraryInfoDiv.prototype.renderInto = function (parent) {\n        this.infoDiv.style.position = "absolute";\n        this.infoDiv.style.top = "10px";\n        this.infoDiv.style.right = "10px";\n        this.infoDiv.style.zIndex = "2";\n        this.infoDiv.style.display = "none";\n        this.infoDiv.style.padding = "5pt";\n        this.infoDiv.style.border = "1px solid #171717";\n        this.infoDiv.style.fontSize = "10pt";\n        this.infoDiv.style.background = "rgb(0 0 0 / 69%)";\n        this.infoDiv.style.borderRadius = "5px";\n        this.infoDiv.style.textAlign = "center";\n        this.infoDiv.style.fontWeight = "400";\n        this.infoDiv.style.color = "white";\n        this.infoDiv.innerText = LibraryInfoStrings.poweredBy();\n        var projectLink = document.createElement("a");\n        projectLink.innerText = "ScanApp";\n        projectLink.href = "https://scanapp.org";\n        projectLink.target = "new";\n        projectLink.style.color = "white";\n        this.infoDiv.appendChild(projectLink);\n        var breakElemFirst = document.createElement("br");\n        var breakElemSecond = document.createElement("br");\n        this.infoDiv.appendChild(breakElemFirst);\n        this.infoDiv.appendChild(breakElemSecond);\n        var reportIssueLink = document.createElement("a");\n        reportIssueLink.innerText = LibraryInfoStrings.reportIssues();\n        reportIssueLink.href = "https://github.com/mebjas/html5-qrcode/issues";\n        reportIssueLink.target = "new";\n        reportIssueLink.style.color = "white";\n        this.infoDiv.appendChild(reportIssueLink);\n        parent.appendChild(this.infoDiv);\n    };\n    LibraryInfoDiv.prototype.show = function () {\n        this.infoDiv.style.display = "block";\n    };\n    LibraryInfoDiv.prototype.hide = function () {\n        this.infoDiv.style.display = "none";\n    };\n    return LibraryInfoDiv;\n}());\nvar LibraryInfoIcon = (function () {\n    function LibraryInfoIcon(onTapIn, onTapOut) {\n        this.isShowingInfoIcon = true;\n        this.onTapIn = onTapIn;\n        this.onTapOut = onTapOut;\n        this.infoIcon = document.createElement("img");\n    }\n    LibraryInfoIcon.prototype.renderInto = function (parent) {\n        var _this = this;\n        this.infoIcon.alt = "Info icon";\n        this.infoIcon.src = ASSET_INFO_ICON_16PX;\n        this.infoIcon.style.position = "absolute";\n        this.infoIcon.style.top = "4px";\n        this.infoIcon.style.right = "4px";\n        this.infoIcon.style.opacity = "0.6";\n        this.infoIcon.style.cursor = "pointer";\n        this.infoIcon.style.zIndex = "2";\n        this.infoIcon.style.width = "16px";\n        this.infoIcon.style.height = "16px";\n        this.infoIcon.onmouseover = function (_) { return _this.onHoverIn(); };\n        this.infoIcon.onmouseout = function (_) { return _this.onHoverOut(); };\n        this.infoIcon.onclick = function (_) { return _this.onClick(); };\n        parent.appendChild(this.infoIcon);\n    };\n    LibraryInfoIcon.prototype.onHoverIn = function () {\n        if (this.isShowingInfoIcon) {\n            this.infoIcon.style.opacity = "1";\n        }\n    };\n    LibraryInfoIcon.prototype.onHoverOut = function () {\n        if (this.isShowingInfoIcon) {\n            this.infoIcon.style.opacity = "0.6";\n        }\n    };\n    LibraryInfoIcon.prototype.onClick = function () {\n        if (this.isShowingInfoIcon) {\n            this.isShowingInfoIcon = false;\n            this.onTapIn();\n            this.infoIcon.src = ASSET_CLOSE_ICON_16PX;\n            this.infoIcon.style.opacity = "1";\n        }\n        else {\n            this.isShowingInfoIcon = true;\n            this.onTapOut();\n            this.infoIcon.src = ASSET_INFO_ICON_16PX;\n            this.infoIcon.style.opacity = "0.6";\n        }\n    };\n    return LibraryInfoIcon;\n}());\nvar LibraryInfoContainer = (function () {\n    function LibraryInfoContainer() {\n        var _this = this;\n        this.infoDiv = new LibraryInfoDiv();\n        this.infoIcon = new LibraryInfoIcon(function () {\n            _this.infoDiv.show();\n        }, function () {\n            _this.infoDiv.hide();\n        });\n    }\n    LibraryInfoContainer.prototype.renderInto = function (parent) {\n        this.infoDiv.renderInto(parent);\n        this.infoIcon.renderInto(parent);\n    };\n    return LibraryInfoContainer;\n}());\n\n//# sourceMappingURL=ui.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/camera/permissions.js\nvar permissions_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar permissions_generator = (undefined && undefined.__generator) || function (thisArg, body) {\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;\n    function verb(n) { return function (v) { return step([n, v]); }; }\n    function step(op) {\n        if (f) throw new TypeError("Generator is already executing.");\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\n            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n            if (y = 0, t) op = [op[0] & 2, t.value];\n            switch (op[0]) {\n                case 0: case 1: t = op; break;\n                case 4: _.label++; return { value: op[1], done: false };\n                case 5: _.label++; y = op[1]; op = [0]; continue;\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\n                default:\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                    if (t[2]) _.ops.pop();\n                    _.trys.pop(); continue;\n            }\n            op = body.call(thisArg, _);\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n    }\n};\nvar CameraPermissions = (function () {\n    function CameraPermissions() {\n    }\n    CameraPermissions.hasPermissions = function () {\n        return permissions_awaiter(this, void 0, void 0, function () {\n            var devices, _i, devices_1, device;\n            return permissions_generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0: return [4, navigator.mediaDevices.enumerateDevices()];\n                    case 1:\n                        devices = _a.sent();\n                        for (_i = 0, devices_1 = devices; _i < devices_1.length; _i++) {\n                            device = devices_1[_i];\n                            if (device.kind === "videoinput" && device.label) {\n                                return [2, true];\n                            }\n                        }\n                        return [2, false];\n                }\n            });\n        });\n    };\n    return CameraPermissions;\n}());\n\n//# sourceMappingURL=permissions.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/ui/scanner/scan-type-selector.js\n\nvar ScanTypeSelector = (function () {\n    function ScanTypeSelector(supportedScanTypes) {\n        this.supportedScanTypes = this.validateAndReturnScanTypes(supportedScanTypes);\n    }\n    ScanTypeSelector.prototype.getDefaultScanType = function () {\n        return this.supportedScanTypes[0];\n    };\n    ScanTypeSelector.prototype.hasMoreThanOneScanType = function () {\n        return this.supportedScanTypes.length > 1;\n    };\n    ScanTypeSelector.prototype.isCameraScanRequired = function () {\n        for (var _i = 0, _a = this.supportedScanTypes; _i < _a.length; _i++) {\n            var scanType = _a[_i];\n            if (ScanTypeSelector.isCameraScanType(scanType)) {\n                return true;\n            }\n        }\n        return false;\n    };\n    ScanTypeSelector.isCameraScanType = function (scanType) {\n        return scanType === Html5QrcodeScanType.SCAN_TYPE_CAMERA;\n    };\n    ScanTypeSelector.isFileScanType = function (scanType) {\n        return scanType === Html5QrcodeScanType.SCAN_TYPE_FILE;\n    };\n    ScanTypeSelector.prototype.validateAndReturnScanTypes = function (supportedScanTypes) {\n        if (!supportedScanTypes || supportedScanTypes.length === 0) {\n            return Html5QrcodeConstants.DEFAULT_SUPPORTED_SCAN_TYPE;\n        }\n        var maxExpectedValues = Html5QrcodeConstants.DEFAULT_SUPPORTED_SCAN_TYPE.length;\n        if (supportedScanTypes.length > maxExpectedValues) {\n            throw "Max ".concat(maxExpectedValues, " values expected for ")\n                + "supportedScanTypes";\n        }\n        for (var _i = 0, supportedScanTypes_1 = supportedScanTypes; _i < supportedScanTypes_1.length; _i++) {\n            var scanType = supportedScanTypes_1[_i];\n            if (!Html5QrcodeConstants.DEFAULT_SUPPORTED_SCAN_TYPE.includes(scanType)) {\n                throw "Unsupported scan type ".concat(scanType);\n            }\n        }\n        return supportedScanTypes;\n    };\n    return ScanTypeSelector;\n}());\n\n//# sourceMappingURL=scan-type-selector.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/ui/scanner/base.js\nvar PublicUiElementIdAndClasses = (function () {\n    function PublicUiElementIdAndClasses() {\n    }\n    PublicUiElementIdAndClasses.ALL_ELEMENT_CLASS = "html5-qrcode-element";\n    PublicUiElementIdAndClasses.CAMERA_PERMISSION_BUTTON_ID = "html5-qrcode-button-camera-permission";\n    PublicUiElementIdAndClasses.CAMERA_START_BUTTON_ID = "html5-qrcode-button-camera-start";\n    PublicUiElementIdAndClasses.CAMERA_STOP_BUTTON_ID = "html5-qrcode-button-camera-stop";\n    PublicUiElementIdAndClasses.TORCH_BUTTON_ID = "html5-qrcode-button-torch";\n    PublicUiElementIdAndClasses.CAMERA_SELECTION_SELECT_ID = "html5-qrcode-select-camera";\n    PublicUiElementIdAndClasses.FILE_SELECTION_BUTTON_ID = "html5-qrcode-button-file-selection";\n    PublicUiElementIdAndClasses.ZOOM_SLIDER_ID = "html5-qrcode-input-range-zoom";\n    PublicUiElementIdAndClasses.SCAN_TYPE_CHANGE_ANCHOR_ID = "html5-qrcode-anchor-scan-type-change";\n    PublicUiElementIdAndClasses.TORCH_BUTTON_CLASS_TORCH_ON = "html5-qrcode-button-torch-on";\n    PublicUiElementIdAndClasses.TORCH_BUTTON_CLASS_TORCH_OFF = "html5-qrcode-button-torch-off";\n    return PublicUiElementIdAndClasses;\n}());\n\nvar BaseUiElementFactory = (function () {\n    function BaseUiElementFactory() {\n    }\n    BaseUiElementFactory.createElement = function (elementType, elementId) {\n        var element = (document.createElement(elementType));\n        element.id = elementId;\n        element.classList.add(PublicUiElementIdAndClasses.ALL_ELEMENT_CLASS);\n        if (elementType === "button") {\n            element.setAttribute("type", "button");\n        }\n        return element;\n    };\n    return BaseUiElementFactory;\n}());\n\n//# sourceMappingURL=base.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/ui/scanner/torch-button.js\nvar torch_button_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar torch_button_generator = (undefined && undefined.__generator) || function (thisArg, body) {\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;\n    function verb(n) { return function (v) { return step([n, v]); }; }\n    function step(op) {\n        if (f) throw new TypeError("Generator is already executing.");\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\n            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n            if (y = 0, t) op = [op[0] & 2, t.value];\n            switch (op[0]) {\n                case 0: case 1: t = op; break;\n                case 4: _.label++; return { value: op[1], done: false };\n                case 5: _.label++; y = op[1]; op = [0]; continue;\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\n                default:\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                    if (t[2]) _.ops.pop();\n                    _.trys.pop(); continue;\n            }\n            op = body.call(thisArg, _);\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n    }\n};\n\n\nvar TorchController = (function () {\n    function TorchController(torchCapability, buttonController, onTorchActionFailureCallback) {\n        this.isTorchOn = false;\n        this.torchCapability = torchCapability;\n        this.buttonController = buttonController;\n        this.onTorchActionFailureCallback = onTorchActionFailureCallback;\n    }\n    TorchController.prototype.isTorchEnabled = function () {\n        return this.isTorchOn;\n    };\n    TorchController.prototype.flipState = function () {\n        return torch_button_awaiter(this, void 0, void 0, function () {\n            var isTorchOnExpected, error_1;\n            return torch_button_generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0:\n                        this.buttonController.disable();\n                        isTorchOnExpected = !this.isTorchOn;\n                        _a.label = 1;\n                    case 1:\n                        _a.trys.push([1, 3, , 4]);\n                        return [4, this.torchCapability.apply(isTorchOnExpected)];\n                    case 2:\n                        _a.sent();\n                        this.updateUiBasedOnLatestSettings(this.torchCapability.value(), isTorchOnExpected);\n                        return [3, 4];\n                    case 3:\n                        error_1 = _a.sent();\n                        this.propagateFailure(isTorchOnExpected, error_1);\n                        this.buttonController.enable();\n                        return [3, 4];\n                    case 4: return [2];\n                }\n            });\n        });\n    };\n    TorchController.prototype.updateUiBasedOnLatestSettings = function (isTorchOn, isTorchOnExpected) {\n        if (isTorchOn === isTorchOnExpected) {\n            this.buttonController.setText(isTorchOnExpected\n                ? Html5QrcodeScannerStrings.torchOffButton()\n                : Html5QrcodeScannerStrings.torchOnButton());\n            this.isTorchOn = isTorchOnExpected;\n        }\n        else {\n            this.propagateFailure(isTorchOnExpected);\n        }\n        this.buttonController.enable();\n    };\n    TorchController.prototype.propagateFailure = function (isTorchOnExpected, error) {\n        var errorMessage = isTorchOnExpected\n            ? Html5QrcodeScannerStrings.torchOnFailedMessage()\n            : Html5QrcodeScannerStrings.torchOffFailedMessage();\n        if (error) {\n            errorMessage += "; Error = " + error;\n        }\n        this.onTorchActionFailureCallback(errorMessage);\n    };\n    TorchController.prototype.reset = function () {\n        this.isTorchOn = false;\n    };\n    return TorchController;\n}());\nvar TorchButton = (function () {\n    function TorchButton(torchCapability, onTorchActionFailureCallback) {\n        this.onTorchActionFailureCallback = onTorchActionFailureCallback;\n        this.torchButton\n            = BaseUiElementFactory.createElement("button", PublicUiElementIdAndClasses.TORCH_BUTTON_ID);\n        this.torchController = new TorchController(torchCapability, this, onTorchActionFailureCallback);\n    }\n    TorchButton.prototype.render = function (parentElement, torchButtonOptions) {\n        var _this = this;\n        this.torchButton.innerText\n            = Html5QrcodeScannerStrings.torchOnButton();\n        this.torchButton.style.display = torchButtonOptions.display;\n        this.torchButton.style.marginLeft = torchButtonOptions.marginLeft;\n        var $this = this;\n        this.torchButton.addEventListener("click", function (_) { return torch_button_awaiter(_this, void 0, void 0, function () {\n            return torch_button_generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0: return [4, $this.torchController.flipState()];\n                    case 1:\n                        _a.sent();\n                        if ($this.torchController.isTorchEnabled()) {\n                            $this.torchButton.classList.remove(PublicUiElementIdAndClasses.TORCH_BUTTON_CLASS_TORCH_OFF);\n                            $this.torchButton.classList.add(PublicUiElementIdAndClasses.TORCH_BUTTON_CLASS_TORCH_ON);\n                        }\n                        else {\n                            $this.torchButton.classList.remove(PublicUiElementIdAndClasses.TORCH_BUTTON_CLASS_TORCH_ON);\n                            $this.torchButton.classList.add(PublicUiElementIdAndClasses.TORCH_BUTTON_CLASS_TORCH_OFF);\n                        }\n                        return [2];\n                }\n            });\n        }); });\n        parentElement.appendChild(this.torchButton);\n    };\n    TorchButton.prototype.updateTorchCapability = function (torchCapability) {\n        this.torchController = new TorchController(torchCapability, this, this.onTorchActionFailureCallback);\n    };\n    TorchButton.prototype.getTorchButton = function () {\n        return this.torchButton;\n    };\n    TorchButton.prototype.hide = function () {\n        this.torchButton.style.display = "none";\n    };\n    TorchButton.prototype.show = function () {\n        this.torchButton.style.display = "inline-block";\n    };\n    TorchButton.prototype.disable = function () {\n        this.torchButton.disabled = true;\n    };\n    TorchButton.prototype.enable = function () {\n        this.torchButton.disabled = false;\n    };\n    TorchButton.prototype.setText = function (text) {\n        this.torchButton.innerText = text;\n    };\n    TorchButton.prototype.reset = function () {\n        this.torchButton.innerText = Html5QrcodeScannerStrings.torchOnButton();\n        this.torchController.reset();\n    };\n    TorchButton.create = function (parentElement, torchCapability, torchButtonOptions, onTorchActionFailureCallback) {\n        var button = new TorchButton(torchCapability, onTorchActionFailureCallback);\n        button.render(parentElement, torchButtonOptions);\n        return button;\n    };\n    return TorchButton;\n}());\n\n//# sourceMappingURL=torch-button.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/ui/scanner/file-selection-ui.js\n\n\nvar FileSelectionUi = (function () {\n    function FileSelectionUi(parentElement, showOnRender, onFileSelected) {\n        this.fileBasedScanRegion = this.createFileBasedScanRegion();\n        this.fileBasedScanRegion.style.display\n            = showOnRender ? "block" : "none";\n        parentElement.appendChild(this.fileBasedScanRegion);\n        var fileScanLabel = document.createElement("label");\n        fileScanLabel.setAttribute("for", this.getFileScanInputId());\n        fileScanLabel.style.display = "inline-block";\n        this.fileBasedScanRegion.appendChild(fileScanLabel);\n        this.fileSelectionButton\n            = BaseUiElementFactory.createElement("button", PublicUiElementIdAndClasses.FILE_SELECTION_BUTTON_ID);\n        this.setInitialValueToButton();\n        this.fileSelectionButton.addEventListener("click", function (_) {\n            fileScanLabel.click();\n        });\n        fileScanLabel.append(this.fileSelectionButton);\n        this.fileScanInput\n            = BaseUiElementFactory.createElement("input", this.getFileScanInputId());\n        this.fileScanInput.type = "file";\n        this.fileScanInput.accept = "image/*";\n        this.fileScanInput.style.display = "none";\n        fileScanLabel.appendChild(this.fileScanInput);\n        var $this = this;\n        this.fileScanInput.addEventListener("change", function (e) {\n            if (e == null || e.target == null) {\n                return;\n            }\n            var target = e.target;\n            if (target.files && target.files.length === 0) {\n                return;\n            }\n            var fileList = target.files;\n            var file = fileList[0];\n            var fileName = file.name;\n            $this.setImageNameToButton(fileName);\n            onFileSelected(file);\n        });\n        var dragAndDropMessage = this.createDragAndDropMessage();\n        this.fileBasedScanRegion.appendChild(dragAndDropMessage);\n        this.fileBasedScanRegion.addEventListener("dragenter", function (event) {\n            $this.fileBasedScanRegion.style.border\n                = $this.fileBasedScanRegionActiveBorder();\n            event.stopPropagation();\n            event.preventDefault();\n        });\n        this.fileBasedScanRegion.addEventListener("dragleave", function (event) {\n            $this.fileBasedScanRegion.style.border\n                = $this.fileBasedScanRegionDefaultBorder();\n            event.stopPropagation();\n            event.preventDefault();\n        });\n        this.fileBasedScanRegion.addEventListener("dragover", function (event) {\n            $this.fileBasedScanRegion.style.border\n                = $this.fileBasedScanRegionActiveBorder();\n            event.stopPropagation();\n            event.preventDefault();\n        });\n        this.fileBasedScanRegion.addEventListener("drop", function (event) {\n            event.stopPropagation();\n            event.preventDefault();\n            $this.fileBasedScanRegion.style.border\n                = $this.fileBasedScanRegionDefaultBorder();\n            var dataTransfer = event.dataTransfer;\n            if (dataTransfer) {\n                var files = dataTransfer.files;\n                if (!files || files.length === 0) {\n                    return;\n                }\n                var isAnyFileImage = false;\n                for (var i = 0; i < files.length; ++i) {\n                    var file = files.item(i);\n                    if (!file) {\n                        continue;\n                    }\n                    var imageType = /image.*/;\n                    if (!file.type.match(imageType)) {\n                        continue;\n                    }\n                    isAnyFileImage = true;\n                    var fileName = file.name;\n                    $this.setImageNameToButton(fileName);\n                    onFileSelected(file);\n                    dragAndDropMessage.innerText\n                        = Html5QrcodeScannerStrings.dragAndDropMessage();\n                    break;\n                }\n                if (!isAnyFileImage) {\n                    dragAndDropMessage.innerText\n                        = Html5QrcodeScannerStrings.dragAndDropMessageOnlyImages();\n                }\n            }\n        });\n    }\n    FileSelectionUi.prototype.hide = function () {\n        this.fileBasedScanRegion.style.display = "none";\n        this.fileScanInput.disabled = true;\n    };\n    FileSelectionUi.prototype.show = function () {\n        this.fileBasedScanRegion.style.display = "block";\n        this.fileScanInput.disabled = false;\n    };\n    FileSelectionUi.prototype.isShowing = function () {\n        return this.fileBasedScanRegion.style.display === "block";\n    };\n    FileSelectionUi.prototype.resetValue = function () {\n        this.fileScanInput.value = "";\n        this.setInitialValueToButton();\n    };\n    FileSelectionUi.prototype.createFileBasedScanRegion = function () {\n        var fileBasedScanRegion = document.createElement("div");\n        fileBasedScanRegion.style.textAlign = "center";\n        fileBasedScanRegion.style.margin = "auto";\n        fileBasedScanRegion.style.width = "80%";\n        fileBasedScanRegion.style.maxWidth = "600px";\n        fileBasedScanRegion.style.border\n            = this.fileBasedScanRegionDefaultBorder();\n        fileBasedScanRegion.style.padding = "10px";\n        fileBasedScanRegion.style.marginBottom = "10px";\n        return fileBasedScanRegion;\n    };\n    FileSelectionUi.prototype.fileBasedScanRegionDefaultBorder = function () {\n        return "6px dashed #ebebeb";\n    };\n    FileSelectionUi.prototype.fileBasedScanRegionActiveBorder = function () {\n        return "6px dashed rgb(153 151 151)";\n    };\n    FileSelectionUi.prototype.createDragAndDropMessage = function () {\n        var dragAndDropMessage = document.createElement("div");\n        dragAndDropMessage.innerText\n            = Html5QrcodeScannerStrings.dragAndDropMessage();\n        dragAndDropMessage.style.fontWeight = "400";\n        return dragAndDropMessage;\n    };\n    FileSelectionUi.prototype.setImageNameToButton = function (imageFileName) {\n        var MAX_CHARS = 20;\n        if (imageFileName.length > MAX_CHARS) {\n            var start8Chars = imageFileName.substring(0, 8);\n            var length_1 = imageFileName.length;\n            var last8Chars = imageFileName.substring(length_1 - 8, length_1);\n            imageFileName = "".concat(start8Chars, "....").concat(last8Chars);\n        }\n        var newText = Html5QrcodeScannerStrings.fileSelectionChooseAnother()\n            + " - "\n            + imageFileName;\n        this.fileSelectionButton.innerText = newText;\n    };\n    FileSelectionUi.prototype.setInitialValueToButton = function () {\n        var initialText = Html5QrcodeScannerStrings.fileSelectionChooseImage()\n            + " - "\n            + Html5QrcodeScannerStrings.fileSelectionNoImageSelected();\n        this.fileSelectionButton.innerText = initialText;\n    };\n    FileSelectionUi.prototype.getFileScanInputId = function () {\n        return "html5-qrcode-private-filescan-input";\n    };\n    FileSelectionUi.create = function (parentElement, showOnRender, onFileSelected) {\n        var button = new FileSelectionUi(parentElement, showOnRender, onFileSelected);\n        return button;\n    };\n    return FileSelectionUi;\n}());\n\n//# sourceMappingURL=file-selection-ui.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/ui/scanner/camera-selection-ui.js\n\n\nvar CameraSelectionUi = (function () {\n    function CameraSelectionUi(cameras) {\n        this.selectElement = BaseUiElementFactory.createElement("select", PublicUiElementIdAndClasses.CAMERA_SELECTION_SELECT_ID);\n        this.cameras = cameras;\n        this.options = [];\n    }\n    CameraSelectionUi.prototype.render = function (parentElement) {\n        var cameraSelectionContainer = document.createElement("span");\n        cameraSelectionContainer.style.marginRight = "10px";\n        var numCameras = this.cameras.length;\n        if (numCameras === 0) {\n            throw new Error("No cameras found");\n        }\n        if (numCameras === 1) {\n            cameraSelectionContainer.style.display = "none";\n        }\n        else {\n            var selectCameraString = Html5QrcodeScannerStrings.selectCamera();\n            cameraSelectionContainer.innerText\n                = "".concat(selectCameraString, " (").concat(this.cameras.length, ")  ");\n        }\n        var anonymousCameraId = 1;\n        for (var _i = 0, _a = this.cameras; _i < _a.length; _i++) {\n            var camera = _a[_i];\n            var value = camera.id;\n            var name_1 = camera.label == null ? value : camera.label;\n            if (!name_1 || name_1 === "") {\n                name_1 = [\n                    Html5QrcodeScannerStrings.anonymousCameraPrefix(),\n                    anonymousCameraId++\n                ].join(" ");\n            }\n            var option = document.createElement("option");\n            option.value = value;\n            option.innerText = name_1;\n            this.options.push(option);\n            this.selectElement.appendChild(option);\n        }\n        cameraSelectionContainer.appendChild(this.selectElement);\n        parentElement.appendChild(cameraSelectionContainer);\n    };\n    CameraSelectionUi.prototype.disable = function () {\n        this.selectElement.disabled = true;\n    };\n    CameraSelectionUi.prototype.isDisabled = function () {\n        return this.selectElement.disabled === true;\n    };\n    CameraSelectionUi.prototype.enable = function () {\n        this.selectElement.disabled = false;\n    };\n    CameraSelectionUi.prototype.getValue = function () {\n        return this.selectElement.value;\n    };\n    CameraSelectionUi.prototype.hasValue = function (value) {\n        for (var _i = 0, _a = this.options; _i < _a.length; _i++) {\n            var option = _a[_i];\n            if (option.value === value) {\n                return true;\n            }\n        }\n        return false;\n    };\n    CameraSelectionUi.prototype.setValue = function (value) {\n        if (!this.hasValue(value)) {\n            throw new Error("".concat(value, " is not present in the camera list."));\n        }\n        this.selectElement.value = value;\n    };\n    CameraSelectionUi.prototype.hasSingleItem = function () {\n        return this.cameras.length === 1;\n    };\n    CameraSelectionUi.prototype.numCameras = function () {\n        return this.cameras.length;\n    };\n    CameraSelectionUi.create = function (parentElement, cameras) {\n        var cameraSelectUi = new CameraSelectionUi(cameras);\n        cameraSelectUi.render(parentElement);\n        return cameraSelectUi;\n    };\n    return CameraSelectionUi;\n}());\n\n//# sourceMappingURL=camera-selection-ui.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/ui/scanner/camera-zoom-ui.js\n\n\nvar CameraZoomUi = (function () {\n    function CameraZoomUi() {\n        this.onChangeCallback = null;\n        this.zoomElementContainer = document.createElement("div");\n        this.rangeInput = BaseUiElementFactory.createElement("input", PublicUiElementIdAndClasses.ZOOM_SLIDER_ID);\n        this.rangeInput.type = "range";\n        this.rangeText = document.createElement("span");\n        this.rangeInput.min = "1";\n        this.rangeInput.max = "5";\n        this.rangeInput.value = "1";\n        this.rangeInput.step = "0.1";\n    }\n    CameraZoomUi.prototype.render = function (parentElement, renderOnCreate) {\n        this.zoomElementContainer.style.display\n            = renderOnCreate ? "block" : "none";\n        this.zoomElementContainer.style.padding = "5px 10px";\n        this.zoomElementContainer.style.textAlign = "center";\n        parentElement.appendChild(this.zoomElementContainer);\n        this.rangeInput.style.display = "inline-block";\n        this.rangeInput.style.width = "50%";\n        this.rangeInput.style.height = "5px";\n        this.rangeInput.style.background = "#d3d3d3";\n        this.rangeInput.style.outline = "none";\n        this.rangeInput.style.opacity = "0.7";\n        var zoomString = Html5QrcodeScannerStrings.zoom();\n        this.rangeText.innerText = "".concat(this.rangeInput.value, "x ").concat(zoomString);\n        this.rangeText.style.marginRight = "10px";\n        var $this = this;\n        this.rangeInput.addEventListener("input", function () { return $this.onValueChange(); });\n        this.rangeInput.addEventListener("change", function () { return $this.onValueChange(); });\n        this.zoomElementContainer.appendChild(this.rangeInput);\n        this.zoomElementContainer.appendChild(this.rangeText);\n    };\n    CameraZoomUi.prototype.onValueChange = function () {\n        var zoomString = Html5QrcodeScannerStrings.zoom();\n        this.rangeText.innerText = "".concat(this.rangeInput.value, "x ").concat(zoomString);\n        if (this.onChangeCallback) {\n            this.onChangeCallback(parseFloat(this.rangeInput.value));\n        }\n    };\n    CameraZoomUi.prototype.setValues = function (minValue, maxValue, defaultValue, step) {\n        this.rangeInput.min = minValue.toString();\n        this.rangeInput.max = maxValue.toString();\n        this.rangeInput.step = step.toString();\n        this.rangeInput.value = defaultValue.toString();\n        this.onValueChange();\n    };\n    CameraZoomUi.prototype.show = function () {\n        this.zoomElementContainer.style.display = "block";\n    };\n    CameraZoomUi.prototype.hide = function () {\n        this.zoomElementContainer.style.display = "none";\n    };\n    CameraZoomUi.prototype.setOnCameraZoomValueChangeCallback = function (onChangeCallback) {\n        this.onChangeCallback = onChangeCallback;\n    };\n    CameraZoomUi.prototype.removeOnCameraZoomValueChangeCallback = function () {\n        this.onChangeCallback = null;\n    };\n    CameraZoomUi.create = function (parentElement, renderOnCreate) {\n        var cameraZoomUi = new CameraZoomUi();\n        cameraZoomUi.render(parentElement, renderOnCreate);\n        return cameraZoomUi;\n    };\n    return CameraZoomUi;\n}());\n\n//# sourceMappingURL=camera-zoom-ui.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/html5-qrcode-scanner.js\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar Html5QrcodeScannerStatus;\n(function (Html5QrcodeScannerStatus) {\n    Html5QrcodeScannerStatus[Html5QrcodeScannerStatus["STATUS_DEFAULT"] = 0] = "STATUS_DEFAULT";\n    Html5QrcodeScannerStatus[Html5QrcodeScannerStatus["STATUS_SUCCESS"] = 1] = "STATUS_SUCCESS";\n    Html5QrcodeScannerStatus[Html5QrcodeScannerStatus["STATUS_WARNING"] = 2] = "STATUS_WARNING";\n    Html5QrcodeScannerStatus[Html5QrcodeScannerStatus["STATUS_REQUESTING_PERMISSION"] = 3] = "STATUS_REQUESTING_PERMISSION";\n})(Html5QrcodeScannerStatus || (Html5QrcodeScannerStatus = {}));\nfunction toHtml5QrcodeCameraScanConfig(config) {\n    return {\n        fps: config.fps,\n        qrbox: config.qrbox,\n        aspectRatio: config.aspectRatio,\n        disableFlip: config.disableFlip,\n        videoConstraints: config.videoConstraints\n    };\n}\nfunction toHtml5QrcodeFullConfig(config, verbose) {\n    return {\n        formatsToSupport: config.formatsToSupport,\n        useBarCodeDetectorIfSupported: config.useBarCodeDetectorIfSupported,\n        experimentalFeatures: config.experimentalFeatures,\n        verbose: verbose\n    };\n}\nvar Html5QrcodeScanner = (function () {\n    function Html5QrcodeScanner(elementId, config, verbose) {\n        this.lastMatchFound = null;\n        this.cameraScanImage = null;\n        this.fileScanImage = null;\n        this.fileSelectionUi = null;\n        this.elementId = elementId;\n        this.config = this.createConfig(config);\n        this.verbose = verbose === true;\n        if (!document.getElementById(elementId)) {\n            throw "HTML Element with id=".concat(elementId, " not found");\n        }\n        this.scanTypeSelector = new ScanTypeSelector(this.config.supportedScanTypes);\n        this.currentScanType = this.scanTypeSelector.getDefaultScanType();\n        this.sectionSwapAllowed = true;\n        this.logger = new BaseLoggger(this.verbose);\n        this.persistedDataManager = new PersistedDataManager();\n        if (config.rememberLastUsedCamera !== true) {\n            this.persistedDataManager.reset();\n        }\n    }\n    Html5QrcodeScanner.prototype.render = function (qrCodeSuccessCallback, qrCodeErrorCallback) {\n        var _this = this;\n        this.lastMatchFound = null;\n        this.qrCodeSuccessCallback\n            = function (decodedText, result) {\n                if (qrCodeSuccessCallback) {\n                    qrCodeSuccessCallback(decodedText, result);\n                }\n                else {\n                    if (_this.lastMatchFound === decodedText) {\n                        return;\n                    }\n                    _this.lastMatchFound = decodedText;\n                    _this.setHeaderMessage(Html5QrcodeScannerStrings.lastMatch(decodedText), Html5QrcodeScannerStatus.STATUS_SUCCESS);\n                }\n            };\n        this.qrCodeErrorCallback =\n            function (errorMessage, error) {\n                if (qrCodeErrorCallback) {\n                    qrCodeErrorCallback(errorMessage, error);\n                }\n            };\n        var container = document.getElementById(this.elementId);\n        if (!container) {\n            throw "HTML Element with id=".concat(this.elementId, " not found");\n        }\n        container.innerHTML = "";\n        this.createBasicLayout(container);\n        this.html5Qrcode = new Html5Qrcode(this.getScanRegionId(), toHtml5QrcodeFullConfig(this.config, this.verbose));\n    };\n    Html5QrcodeScanner.prototype.pause = function (shouldPauseVideo) {\n        if (isNullOrUndefined(shouldPauseVideo) || shouldPauseVideo !== true) {\n            shouldPauseVideo = false;\n        }\n        this.getHtml5QrcodeOrFail().pause(shouldPauseVideo);\n    };\n    Html5QrcodeScanner.prototype.resume = function () {\n        this.getHtml5QrcodeOrFail().resume();\n    };\n    Html5QrcodeScanner.prototype.getState = function () {\n        return this.getHtml5QrcodeOrFail().getState();\n    };\n    Html5QrcodeScanner.prototype.clear = function () {\n        var _this = this;\n        var emptyHtmlContainer = function () {\n            var mainContainer = document.getElementById(_this.elementId);\n            if (mainContainer) {\n                mainContainer.innerHTML = "";\n                _this.resetBasicLayout(mainContainer);\n            }\n        };\n        if (this.html5Qrcode) {\n            return new Promise(function (resolve, reject) {\n                if (!_this.html5Qrcode) {\n                    resolve();\n                    return;\n                }\n                if (_this.html5Qrcode.isScanning) {\n                    _this.html5Qrcode.stop().then(function (_) {\n                        if (!_this.html5Qrcode) {\n                            resolve();\n                            return;\n                        }\n                        _this.html5Qrcode.clear();\n                        emptyHtmlContainer();\n                        resolve();\n                    }).catch(function (error) {\n                        if (_this.verbose) {\n                            _this.logger.logError("Unable to stop qrcode scanner", error);\n                        }\n                        reject(error);\n                    });\n                }\n                else {\n                    _this.html5Qrcode.clear();\n                    emptyHtmlContainer();\n                    resolve();\n                }\n            });\n        }\n        return Promise.resolve();\n    };\n    Html5QrcodeScanner.prototype.getRunningTrackCapabilities = function () {\n        return this.getHtml5QrcodeOrFail().getRunningTrackCapabilities();\n    };\n    Html5QrcodeScanner.prototype.getRunningTrackSettings = function () {\n        return this.getHtml5QrcodeOrFail().getRunningTrackSettings();\n    };\n    Html5QrcodeScanner.prototype.applyVideoConstraints = function (videoConstaints) {\n        return this.getHtml5QrcodeOrFail().applyVideoConstraints(videoConstaints);\n    };\n    Html5QrcodeScanner.prototype.getHtml5QrcodeOrFail = function () {\n        if (!this.html5Qrcode) {\n            throw "Code scanner not initialized.";\n        }\n        return this.html5Qrcode;\n    };\n    Html5QrcodeScanner.prototype.createConfig = function (config) {\n        if (config) {\n            if (!config.fps) {\n                config.fps = Html5QrcodeConstants.SCAN_DEFAULT_FPS;\n            }\n            if (config.rememberLastUsedCamera !== (!Html5QrcodeConstants.DEFAULT_REMEMBER_LAST_CAMERA_USED)) {\n                config.rememberLastUsedCamera\n                    = Html5QrcodeConstants.DEFAULT_REMEMBER_LAST_CAMERA_USED;\n            }\n            if (!config.supportedScanTypes) {\n                config.supportedScanTypes\n                    = Html5QrcodeConstants.DEFAULT_SUPPORTED_SCAN_TYPE;\n            }\n            return config;\n        }\n        return {\n            fps: Html5QrcodeConstants.SCAN_DEFAULT_FPS,\n            rememberLastUsedCamera: Html5QrcodeConstants.DEFAULT_REMEMBER_LAST_CAMERA_USED,\n            supportedScanTypes: Html5QrcodeConstants.DEFAULT_SUPPORTED_SCAN_TYPE\n        };\n    };\n    Html5QrcodeScanner.prototype.createBasicLayout = function (parent) {\n        parent.style.position = "relative";\n        parent.style.padding = "0px";\n        parent.style.border = "1px solid silver";\n        this.createHeader(parent);\n        var qrCodeScanRegion = document.createElement("div");\n        var scanRegionId = this.getScanRegionId();\n        qrCodeScanRegion.id = scanRegionId;\n        qrCodeScanRegion.style.width = "100%";\n        qrCodeScanRegion.style.minHeight = "100px";\n        qrCodeScanRegion.style.textAlign = "center";\n        parent.appendChild(qrCodeScanRegion);\n        if (ScanTypeSelector.isCameraScanType(this.currentScanType)) {\n            this.insertCameraScanImageToScanRegion();\n        }\n        else {\n            this.insertFileScanImageToScanRegion();\n        }\n        var qrCodeDashboard = document.createElement("div");\n        var dashboardId = this.getDashboardId();\n        qrCodeDashboard.id = dashboardId;\n        qrCodeDashboard.style.width = "100%";\n        parent.appendChild(qrCodeDashboard);\n        this.setupInitialDashboard(qrCodeDashboard);\n    };\n    Html5QrcodeScanner.prototype.resetBasicLayout = function (mainContainer) {\n        mainContainer.style.border = "none";\n    };\n    Html5QrcodeScanner.prototype.setupInitialDashboard = function (dashboard) {\n        this.createSection(dashboard);\n        this.createSectionControlPanel();\n        if (this.scanTypeSelector.hasMoreThanOneScanType()) {\n            this.createSectionSwap();\n        }\n    };\n    Html5QrcodeScanner.prototype.createHeader = function (dashboard) {\n        var header = document.createElement("div");\n        header.style.textAlign = "left";\n        header.style.margin = "0px";\n        dashboard.appendChild(header);\n        var libraryInfo = new LibraryInfoContainer();\n        libraryInfo.renderInto(header);\n        var headerMessageContainer = document.createElement("div");\n        headerMessageContainer.id = this.getHeaderMessageContainerId();\n        headerMessageContainer.style.display = "none";\n        headerMessageContainer.style.textAlign = "center";\n        headerMessageContainer.style.fontSize = "14px";\n        headerMessageContainer.style.padding = "2px 10px";\n        headerMessageContainer.style.margin = "4px";\n        headerMessageContainer.style.borderTop = "1px solid #f6f6f6";\n        header.appendChild(headerMessageContainer);\n    };\n    Html5QrcodeScanner.prototype.createSection = function (dashboard) {\n        var section = document.createElement("div");\n        section.id = this.getDashboardSectionId();\n        section.style.width = "100%";\n        section.style.padding = "10px 0px 10px 0px";\n        section.style.textAlign = "left";\n        dashboard.appendChild(section);\n    };\n    Html5QrcodeScanner.prototype.createCameraListUi = function (scpCameraScanRegion, requestPermissionContainer, requestPermissionButton) {\n        var $this = this;\n        $this.showHideScanTypeSwapLink(false);\n        $this.setHeaderMessage(Html5QrcodeScannerStrings.cameraPermissionRequesting());\n        var createPermissionButtonIfNotExists = function () {\n            if (!requestPermissionButton) {\n                $this.createPermissionButton(scpCameraScanRegion, requestPermissionContainer);\n            }\n        };\n        Html5Qrcode.getCameras().then(function (cameras) {\n            $this.persistedDataManager.setHasPermission(true);\n            $this.showHideScanTypeSwapLink(true);\n            $this.resetHeaderMessage();\n            if (cameras && cameras.length > 0) {\n                scpCameraScanRegion.removeChild(requestPermissionContainer);\n                $this.renderCameraSelection(cameras);\n            }\n            else {\n                $this.setHeaderMessage(Html5QrcodeScannerStrings.noCameraFound(), Html5QrcodeScannerStatus.STATUS_WARNING);\n                createPermissionButtonIfNotExists();\n            }\n        }).catch(function (error) {\n            $this.persistedDataManager.setHasPermission(false);\n            if (requestPermissionButton) {\n                requestPermissionButton.disabled = false;\n            }\n            else {\n                createPermissionButtonIfNotExists();\n            }\n            $this.setHeaderMessage(error, Html5QrcodeScannerStatus.STATUS_WARNING);\n            $this.showHideScanTypeSwapLink(true);\n        });\n    };\n    Html5QrcodeScanner.prototype.createPermissionButton = function (scpCameraScanRegion, requestPermissionContainer) {\n        var $this = this;\n        var requestPermissionButton = BaseUiElementFactory.createElement("button", this.getCameraPermissionButtonId());\n        requestPermissionButton.innerText\n            = Html5QrcodeScannerStrings.cameraPermissionTitle();\n        requestPermissionButton.addEventListener("click", function () {\n            requestPermissionButton.disabled = true;\n            $this.createCameraListUi(scpCameraScanRegion, requestPermissionContainer, requestPermissionButton);\n        });\n        requestPermissionContainer.appendChild(requestPermissionButton);\n    };\n    Html5QrcodeScanner.prototype.createPermissionsUi = function (scpCameraScanRegion, requestPermissionContainer) {\n        var $this = this;\n        if (ScanTypeSelector.isCameraScanType(this.currentScanType)\n            && this.persistedDataManager.hasCameraPermissions()) {\n            CameraPermissions.hasPermissions().then(function (hasPermissions) {\n                if (hasPermissions) {\n                    $this.createCameraListUi(scpCameraScanRegion, requestPermissionContainer);\n                }\n                else {\n                    $this.persistedDataManager.setHasPermission(false);\n                    $this.createPermissionButton(scpCameraScanRegion, requestPermissionContainer);\n                }\n            }).catch(function (_) {\n                $this.persistedDataManager.setHasPermission(false);\n                $this.createPermissionButton(scpCameraScanRegion, requestPermissionContainer);\n            });\n            return;\n        }\n        this.createPermissionButton(scpCameraScanRegion, requestPermissionContainer);\n    };\n    Html5QrcodeScanner.prototype.createSectionControlPanel = function () {\n        var section = document.getElementById(this.getDashboardSectionId());\n        var sectionControlPanel = document.createElement("div");\n        section.appendChild(sectionControlPanel);\n        var scpCameraScanRegion = document.createElement("div");\n        scpCameraScanRegion.id = this.getDashboardSectionCameraScanRegionId();\n        scpCameraScanRegion.style.display\n            = ScanTypeSelector.isCameraScanType(this.currentScanType)\n                ? "block" : "none";\n        sectionControlPanel.appendChild(scpCameraScanRegion);\n        var requestPermissionContainer = document.createElement("div");\n        requestPermissionContainer.style.textAlign = "center";\n        scpCameraScanRegion.appendChild(requestPermissionContainer);\n        if (this.scanTypeSelector.isCameraScanRequired()) {\n            this.createPermissionsUi(scpCameraScanRegion, requestPermissionContainer);\n        }\n        this.renderFileScanUi(sectionControlPanel);\n    };\n    Html5QrcodeScanner.prototype.renderFileScanUi = function (parent) {\n        var showOnRender = ScanTypeSelector.isFileScanType(this.currentScanType);\n        var $this = this;\n        var onFileSelected = function (file) {\n            if (!$this.html5Qrcode) {\n                throw "html5Qrcode not defined";\n            }\n            if (!ScanTypeSelector.isFileScanType($this.currentScanType)) {\n                return;\n            }\n            $this.setHeaderMessage(Html5QrcodeScannerStrings.loadingImage());\n            $this.html5Qrcode.scanFileV2(file, true)\n                .then(function (html5qrcodeResult) {\n                $this.resetHeaderMessage();\n                $this.qrCodeSuccessCallback(html5qrcodeResult.decodedText, html5qrcodeResult);\n            })\n                .catch(function (error) {\n                $this.setHeaderMessage(error, Html5QrcodeScannerStatus.STATUS_WARNING);\n                $this.qrCodeErrorCallback(error, Html5QrcodeErrorFactory.createFrom(error));\n            });\n        };\n        this.fileSelectionUi = FileSelectionUi.create(parent, showOnRender, onFileSelected);\n    };\n    Html5QrcodeScanner.prototype.renderCameraSelection = function (cameras) {\n        var _this = this;\n        var $this = this;\n        var scpCameraScanRegion = document.getElementById(this.getDashboardSectionCameraScanRegionId());\n        scpCameraScanRegion.style.textAlign = "center";\n        var cameraZoomUi = CameraZoomUi.create(scpCameraScanRegion, false);\n        var renderCameraZoomUiIfSupported = function (cameraCapabilities) {\n            var zoomCapability = cameraCapabilities.zoomFeature();\n            if (!zoomCapability.isSupported()) {\n                return;\n            }\n            cameraZoomUi.setOnCameraZoomValueChangeCallback(function (zoomValue) {\n                zoomCapability.apply(zoomValue);\n            });\n            var defaultZoom = 1;\n            if (_this.config.defaultZoomValueIfSupported) {\n                defaultZoom = _this.config.defaultZoomValueIfSupported;\n            }\n            defaultZoom = clip(defaultZoom, zoomCapability.min(), zoomCapability.max());\n            cameraZoomUi.setValues(zoomCapability.min(), zoomCapability.max(), defaultZoom, zoomCapability.step());\n            cameraZoomUi.show();\n        };\n        var cameraSelectUi = CameraSelectionUi.create(scpCameraScanRegion, cameras);\n        var cameraActionContainer = document.createElement("span");\n        var cameraActionStartButton = BaseUiElementFactory.createElement("button", PublicUiElementIdAndClasses.CAMERA_START_BUTTON_ID);\n        cameraActionStartButton.innerText\n            = Html5QrcodeScannerStrings.scanButtonStartScanningText();\n        cameraActionContainer.appendChild(cameraActionStartButton);\n        var cameraActionStopButton = BaseUiElementFactory.createElement("button", PublicUiElementIdAndClasses.CAMERA_STOP_BUTTON_ID);\n        cameraActionStopButton.innerText\n            = Html5QrcodeScannerStrings.scanButtonStopScanningText();\n        cameraActionStopButton.style.display = "none";\n        cameraActionStopButton.disabled = true;\n        cameraActionContainer.appendChild(cameraActionStopButton);\n        var torchButton;\n        var createAndShowTorchButtonIfSupported = function (cameraCapabilities) {\n            if (!cameraCapabilities.torchFeature().isSupported()) {\n                if (torchButton) {\n                    torchButton.hide();\n                }\n                return;\n            }\n            if (!torchButton) {\n                torchButton = TorchButton.create(cameraActionContainer, cameraCapabilities.torchFeature(), { display: "none", marginLeft: "5px" }, function (errorMessage) {\n                    $this.setHeaderMessage(errorMessage, Html5QrcodeScannerStatus.STATUS_WARNING);\n                });\n            }\n            else {\n                torchButton.updateTorchCapability(cameraCapabilities.torchFeature());\n            }\n            torchButton.show();\n        };\n        scpCameraScanRegion.appendChild(cameraActionContainer);\n        var resetCameraActionStartButton = function (shouldShow) {\n            if (!shouldShow) {\n                cameraActionStartButton.style.display = "none";\n            }\n            cameraActionStartButton.innerText\n                = Html5QrcodeScannerStrings.scanButtonStartScanningText();\n            cameraActionStartButton.style.opacity = "1";\n            cameraActionStartButton.disabled = false;\n            if (shouldShow) {\n                cameraActionStartButton.style.display = "inline-block";\n            }\n        };\n        cameraActionStartButton.addEventListener("click", function (_) {\n            cameraActionStartButton.innerText\n                = Html5QrcodeScannerStrings.scanButtonScanningStarting();\n            cameraSelectUi.disable();\n            cameraActionStartButton.disabled = true;\n            cameraActionStartButton.style.opacity = "0.5";\n            if (_this.scanTypeSelector.hasMoreThanOneScanType()) {\n                $this.showHideScanTypeSwapLink(false);\n            }\n            $this.resetHeaderMessage();\n            var cameraId = cameraSelectUi.getValue();\n            $this.persistedDataManager.setLastUsedCameraId(cameraId);\n            $this.html5Qrcode.start(cameraId, toHtml5QrcodeCameraScanConfig($this.config), $this.qrCodeSuccessCallback, $this.qrCodeErrorCallback)\n                .then(function (_) {\n                cameraActionStopButton.disabled = false;\n                cameraActionStopButton.style.display = "inline-block";\n                resetCameraActionStartButton(false);\n                var cameraCapabilities = $this.html5Qrcode.getRunningTrackCameraCapabilities();\n                if (_this.config.showTorchButtonIfSupported === true) {\n                    createAndShowTorchButtonIfSupported(cameraCapabilities);\n                }\n                if (_this.config.showZoomSliderIfSupported === true) {\n                    renderCameraZoomUiIfSupported(cameraCapabilities);\n                }\n            })\n                .catch(function (error) {\n                $this.showHideScanTypeSwapLink(true);\n                cameraSelectUi.enable();\n                resetCameraActionStartButton(true);\n                $this.setHeaderMessage(error, Html5QrcodeScannerStatus.STATUS_WARNING);\n            });\n        });\n        if (cameraSelectUi.hasSingleItem()) {\n            cameraActionStartButton.click();\n        }\n        cameraActionStopButton.addEventListener("click", function (_) {\n            if (!$this.html5Qrcode) {\n                throw "html5Qrcode not defined";\n            }\n            cameraActionStopButton.disabled = true;\n            $this.html5Qrcode.stop()\n                .then(function (_) {\n                if (_this.scanTypeSelector.hasMoreThanOneScanType()) {\n                    $this.showHideScanTypeSwapLink(true);\n                }\n                cameraSelectUi.enable();\n                cameraActionStartButton.disabled = false;\n                cameraActionStopButton.style.display = "none";\n                cameraActionStartButton.style.display = "inline-block";\n                if (torchButton) {\n                    torchButton.reset();\n                    torchButton.hide();\n                }\n                cameraZoomUi.removeOnCameraZoomValueChangeCallback();\n                cameraZoomUi.hide();\n                $this.insertCameraScanImageToScanRegion();\n            }).catch(function (error) {\n                cameraActionStopButton.disabled = false;\n                $this.setHeaderMessage(error, Html5QrcodeScannerStatus.STATUS_WARNING);\n            });\n        });\n        if ($this.persistedDataManager.getLastUsedCameraId()) {\n            var cameraId = $this.persistedDataManager.getLastUsedCameraId();\n            if (cameraSelectUi.hasValue(cameraId)) {\n                cameraSelectUi.setValue(cameraId);\n                cameraActionStartButton.click();\n            }\n            else {\n                $this.persistedDataManager.resetLastUsedCameraId();\n            }\n        }\n    };\n    Html5QrcodeScanner.prototype.createSectionSwap = function () {\n        var $this = this;\n        var TEXT_IF_CAMERA_SCAN_SELECTED = Html5QrcodeScannerStrings.textIfCameraScanSelected();\n        var TEXT_IF_FILE_SCAN_SELECTED = Html5QrcodeScannerStrings.textIfFileScanSelected();\n        var section = document.getElementById(this.getDashboardSectionId());\n        var switchContainer = document.createElement("div");\n        switchContainer.style.textAlign = "center";\n        var switchScanTypeLink = BaseUiElementFactory.createElement("span", this.getDashboardSectionSwapLinkId());\n        switchScanTypeLink.style.textDecoration = "underline";\n        switchScanTypeLink.style.cursor = "pointer";\n        switchScanTypeLink.innerText\n            = ScanTypeSelector.isCameraScanType(this.currentScanType)\n                ? TEXT_IF_CAMERA_SCAN_SELECTED : TEXT_IF_FILE_SCAN_SELECTED;\n        switchScanTypeLink.addEventListener("click", function () {\n            if (!$this.sectionSwapAllowed) {\n                if ($this.verbose) {\n                    $this.logger.logError("Section swap called when not allowed");\n                }\n                return;\n            }\n            $this.resetHeaderMessage();\n            $this.fileSelectionUi.resetValue();\n            $this.sectionSwapAllowed = false;\n            if (ScanTypeSelector.isCameraScanType($this.currentScanType)) {\n                $this.clearScanRegion();\n                $this.getCameraScanRegion().style.display = "none";\n                $this.fileSelectionUi.show();\n                switchScanTypeLink.innerText = TEXT_IF_FILE_SCAN_SELECTED;\n                $this.currentScanType = Html5QrcodeScanType.SCAN_TYPE_FILE;\n                $this.insertFileScanImageToScanRegion();\n            }\n            else {\n                $this.clearScanRegion();\n                $this.getCameraScanRegion().style.display = "block";\n                $this.fileSelectionUi.hide();\n                switchScanTypeLink.innerText = TEXT_IF_CAMERA_SCAN_SELECTED;\n                $this.currentScanType = Html5QrcodeScanType.SCAN_TYPE_CAMERA;\n                $this.insertCameraScanImageToScanRegion();\n                $this.startCameraScanIfPermissionExistsOnSwap();\n            }\n            $this.sectionSwapAllowed = true;\n        });\n        switchContainer.appendChild(switchScanTypeLink);\n        section.appendChild(switchContainer);\n    };\n    Html5QrcodeScanner.prototype.startCameraScanIfPermissionExistsOnSwap = function () {\n        var _this = this;\n        var $this = this;\n        if (this.persistedDataManager.hasCameraPermissions()) {\n            CameraPermissions.hasPermissions().then(function (hasPermissions) {\n                if (hasPermissions) {\n                    var permissionButton = document.getElementById($this.getCameraPermissionButtonId());\n                    if (!permissionButton) {\n                        _this.logger.logError("Permission button not found, fail;");\n                        throw "Permission button not found";\n                    }\n                    permissionButton.click();\n                }\n                else {\n                    $this.persistedDataManager.setHasPermission(false);\n                }\n            }).catch(function (_) {\n                $this.persistedDataManager.setHasPermission(false);\n            });\n            return;\n        }\n    };\n    Html5QrcodeScanner.prototype.resetHeaderMessage = function () {\n        var messageDiv = document.getElementById(this.getHeaderMessageContainerId());\n        messageDiv.style.display = "none";\n    };\n    Html5QrcodeScanner.prototype.setHeaderMessage = function (messageText, scannerStatus) {\n        if (!scannerStatus) {\n            scannerStatus = Html5QrcodeScannerStatus.STATUS_DEFAULT;\n        }\n        var messageDiv = this.getHeaderMessageDiv();\n        messageDiv.innerText = messageText;\n        messageDiv.style.display = "block";\n        switch (scannerStatus) {\n            case Html5QrcodeScannerStatus.STATUS_SUCCESS:\n                messageDiv.style.background = "rgba(106, 175, 80, 0.26)";\n                messageDiv.style.color = "#477735";\n                break;\n            case Html5QrcodeScannerStatus.STATUS_WARNING:\n                messageDiv.style.background = "rgba(203, 36, 49, 0.14)";\n                messageDiv.style.color = "#cb2431";\n                break;\n            case Html5QrcodeScannerStatus.STATUS_DEFAULT:\n            default:\n                messageDiv.style.background = "rgba(0, 0, 0, 0)";\n                messageDiv.style.color = "rgb(17, 17, 17)";\n                break;\n        }\n    };\n    Html5QrcodeScanner.prototype.showHideScanTypeSwapLink = function (shouldDisplay) {\n        if (this.scanTypeSelector.hasMoreThanOneScanType()) {\n            if (shouldDisplay !== true) {\n                shouldDisplay = false;\n            }\n            this.sectionSwapAllowed = shouldDisplay;\n            this.getDashboardSectionSwapLink().style.display\n                = shouldDisplay ? "inline-block" : "none";\n        }\n    };\n    Html5QrcodeScanner.prototype.insertCameraScanImageToScanRegion = function () {\n        var $this = this;\n        var qrCodeScanRegion = document.getElementById(this.getScanRegionId());\n        if (this.cameraScanImage) {\n            qrCodeScanRegion.innerHTML = "<br>";\n            qrCodeScanRegion.appendChild(this.cameraScanImage);\n            return;\n        }\n        this.cameraScanImage = new Image;\n        this.cameraScanImage.onload = function (_) {\n            qrCodeScanRegion.innerHTML = "<br>";\n            qrCodeScanRegion.appendChild($this.cameraScanImage);\n        };\n        this.cameraScanImage.width = 64;\n        this.cameraScanImage.style.opacity = "0.8";\n        this.cameraScanImage.src = ASSET_CAMERA_SCAN;\n        this.cameraScanImage.alt = Html5QrcodeScannerStrings.cameraScanAltText();\n    };\n    Html5QrcodeScanner.prototype.insertFileScanImageToScanRegion = function () {\n        var $this = this;\n        var qrCodeScanRegion = document.getElementById(this.getScanRegionId());\n        if (this.fileScanImage) {\n            qrCodeScanRegion.innerHTML = "<br>";\n            qrCodeScanRegion.appendChild(this.fileScanImage);\n            return;\n        }\n        this.fileScanImage = new Image;\n        this.fileScanImage.onload = function (_) {\n            qrCodeScanRegion.innerHTML = "<br>";\n            qrCodeScanRegion.appendChild($this.fileScanImage);\n        };\n        this.fileScanImage.width = 64;\n        this.fileScanImage.style.opacity = "0.8";\n        this.fileScanImage.src = ASSET_FILE_SCAN;\n        this.fileScanImage.alt = Html5QrcodeScannerStrings.fileScanAltText();\n    };\n    Html5QrcodeScanner.prototype.clearScanRegion = function () {\n        var qrCodeScanRegion = document.getElementById(this.getScanRegionId());\n        qrCodeScanRegion.innerHTML = "";\n    };\n    Html5QrcodeScanner.prototype.getDashboardSectionId = function () {\n        return "".concat(this.elementId, "__dashboard_section");\n    };\n    Html5QrcodeScanner.prototype.getDashboardSectionCameraScanRegionId = function () {\n        return "".concat(this.elementId, "__dashboard_section_csr");\n    };\n    Html5QrcodeScanner.prototype.getDashboardSectionSwapLinkId = function () {\n        return PublicUiElementIdAndClasses.SCAN_TYPE_CHANGE_ANCHOR_ID;\n    };\n    Html5QrcodeScanner.prototype.getScanRegionId = function () {\n        return "".concat(this.elementId, "__scan_region");\n    };\n    Html5QrcodeScanner.prototype.getDashboardId = function () {\n        return "".concat(this.elementId, "__dashboard");\n    };\n    Html5QrcodeScanner.prototype.getHeaderMessageContainerId = function () {\n        return "".concat(this.elementId, "__header_message");\n    };\n    Html5QrcodeScanner.prototype.getCameraPermissionButtonId = function () {\n        return PublicUiElementIdAndClasses.CAMERA_PERMISSION_BUTTON_ID;\n    };\n    Html5QrcodeScanner.prototype.getCameraScanRegion = function () {\n        return document.getElementById(this.getDashboardSectionCameraScanRegionId());\n    };\n    Html5QrcodeScanner.prototype.getDashboardSectionSwapLink = function () {\n        return document.getElementById(this.getDashboardSectionSwapLinkId());\n    };\n    Html5QrcodeScanner.prototype.getHeaderMessageDiv = function () {\n        return document.getElementById(this.getHeaderMessageContainerId());\n    };\n    return Html5QrcodeScanner;\n}());\n\n//# sourceMappingURL=html5-qrcode-scanner.js.map\n;// CONCATENATED MODULE: ./node_modules/html5-qrcode/esm/index.js\n\n\n\n\n\n//# sourceMappingURL=index.js.map\n;// CONCATENATED MODULE: ./node_modules/@noble/hashes/esm/_assert.js\nfunction number(n) {\n    if (!Number.isSafeInteger(n) || n < 0)\n        throw new Error(`Wrong positive integer: ${n}`);\n}\nfunction bool(b) {\n    if (typeof b !== \'boolean\')\n        throw new Error(`Expected boolean, not ${b}`);\n}\nfunction bytes(b, ...lengths) {\n    if (!(b instanceof Uint8Array))\n        throw new TypeError(\'Expected Uint8Array\');\n    if (lengths.length > 0 && !lengths.includes(b.length))\n        throw new TypeError(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`);\n}\nfunction hash(hash) {\n    if (typeof hash !== \'function\' || typeof hash.create !== \'function\')\n        throw new Error(\'Hash should be wrapped by utils.wrapConstructor\');\n    number(hash.outputLen);\n    number(hash.blockLen);\n}\nfunction exists(instance, checkFinished = true) {\n    if (instance.destroyed)\n        throw new Error(\'Hash instance has been destroyed\');\n    if (checkFinished && instance.finished)\n        throw new Error(\'Hash#digest() has already been called\');\n}\nfunction output(out, instance) {\n    bytes(out);\n    const min = instance.outputLen;\n    if (out.length < min) {\n        throw new Error(`digestInto() expects output buffer of length at least ${min}`);\n    }\n}\nconst assert = {\n    number,\n    bool,\n    bytes,\n    hash,\n    exists,\n    output,\n};\n/* harmony default export */ const _assert = (assert);\n//# sourceMappingURL=_assert.js.map\n;// CONCATENATED MODULE: ./node_modules/@noble/hashes/esm/_u64.js\nconst U32_MASK64 = BigInt(2 ** 32 - 1);\nconst _32n = BigInt(32);\n// We are not using BigUint64Array, because they are extremely slow as per 2022\nfunction fromBig(n, le = false) {\n    if (le)\n        return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };\n    return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };\n}\nfunction split(lst, le = false) {\n    let Ah = new Uint32Array(lst.length);\n    let Al = new Uint32Array(lst.length);\n    for (let i = 0; i < lst.length; i++) {\n        const { h, l } = fromBig(lst[i], le);\n        [Ah[i], Al[i]] = [h, l];\n    }\n    return [Ah, Al];\n}\nconst toBig = (h, l) => (BigInt(h >>> 0) << _32n) | BigInt(l >>> 0);\n// for Shift in [0, 32)\nconst shrSH = (h, l, s) => h >>> s;\nconst shrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);\n// Right rotate for Shift in [1, 32)\nconst rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s));\nconst rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);\n// Right rotate for Shift in (32, 64), NOTE: 32 is special case.\nconst rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32));\nconst rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s));\n// Right rotate for shift===32 (just swaps l&h)\nconst rotr32H = (h, l) => l;\nconst rotr32L = (h, l) => h;\n// Left rotate for Shift in [1, 32)\nconst rotlSH = (h, l, s) => (h << s) | (l >>> (32 - s));\nconst rotlSL = (h, l, s) => (l << s) | (h >>> (32 - s));\n// Left rotate for Shift in (32, 64), NOTE: 32 is special case.\nconst rotlBH = (h, l, s) => (l << (s - 32)) | (h >>> (64 - s));\nconst rotlBL = (h, l, s) => (h << (s - 32)) | (l >>> (64 - s));\n// JS uses 32-bit signed integers for bitwise operations which means we cannot\n// simple take carry out of low bit sum by shift, we need to use division.\n// Removing "export" has 5% perf penalty -_-\nfunction add(Ah, Al, Bh, Bl) {\n    const l = (Al >>> 0) + (Bl >>> 0);\n    return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 };\n}\n// Addition with more than 2 elements\nconst add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);\nconst add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0;\nconst add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);\nconst add4H = (low, Ah, Bh, Ch, Dh) => (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0;\nconst add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);\nconst add5H = (low, Ah, Bh, Ch, Dh, Eh) => (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0;\n// prettier-ignore\nconst u64 = {\n    fromBig, split, toBig,\n    shrSH, shrSL,\n    rotrSH, rotrSL, rotrBH, rotrBL,\n    rotr32H, rotr32L,\n    rotlSH, rotlSL, rotlBH, rotlBL,\n    add, add3L, add3H, add4L, add4H, add5H, add5L,\n};\n/* harmony default export */ const _u64 = (u64);\n//# sourceMappingURL=_u64.js.map\n;// CONCATENATED MODULE: ./node_modules/@noble/hashes/esm/crypto.js\nconst crypto_crypto = typeof globalThis === \'object\' && \'crypto\' in globalThis ? globalThis.crypto : undefined;\n//# sourceMappingURL=crypto.js.map\n;// CONCATENATED MODULE: ./node_modules/@noble/hashes/esm/utils.js\n/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// We use `globalThis.crypto`, but node.js versions earlier than v19 don\'t\n// declare it in global scope. For node.js, package.json#exports field mapping\n// rewrites import from `crypto` to `cryptoNode`, which imports native module.\n// Makes the utils un-importable in browsers without a bundler.\n// Once node.js 18 is deprecated, we can just drop the import.\n\n// Cast array to different type\nconst u8 = (arr) => new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\nconst u32 = (arr) => new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));\n// Cast array to view\nconst createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);\n// The rotate right (circular right shift) operation for uint32\nconst rotr = (word, shift) => (word << (32 - shift)) | (word >>> shift);\n// big-endian hardware is rare. Just in case someone still decides to run hashes:\n// early-throw an error because we don\'t support BE yet.\nconst isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44;\nif (!isLE)\n    throw new Error(\'Non little-endian hardware is not supported\');\nconst hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, \'0\'));\n/**\n * @example bytesToHex(Uint8Array.from([0xde, 0xad, 0xbe, 0xef])) // \'deadbeef\'\n */\nfunction bytesToHex(uint8a) {\n    // pre-caching improves the speed 6x\n    if (!(uint8a instanceof Uint8Array))\n        throw new Error(\'Uint8Array expected\');\n    let hex = \'\';\n    for (let i = 0; i < uint8a.length; i++) {\n        hex += hexes[uint8a[i]];\n    }\n    return hex;\n}\n/**\n * @example hexToBytes(\'deadbeef\') // Uint8Array.from([0xde, 0xad, 0xbe, 0xef])\n */\nfunction hexToBytes(hex) {\n    if (typeof hex !== \'string\') {\n        throw new TypeError(\'hexToBytes: expected string, got \' + typeof hex);\n    }\n    if (hex.length % 2)\n        throw new Error(\'hexToBytes: received invalid unpadded hex\');\n    const array = new Uint8Array(hex.length / 2);\n    for (let i = 0; i < array.length; i++) {\n        const j = i * 2;\n        const hexByte = hex.slice(j, j + 2);\n        const byte = Number.parseInt(hexByte, 16);\n        if (Number.isNaN(byte) || byte < 0)\n            throw new Error(\'Invalid byte sequence\');\n        array[i] = byte;\n    }\n    return array;\n}\n// There is no setImmediate in browser and setTimeout is slow.\n// call of async fn will return Promise, which will be fullfiled only on\n// next scheduler queue processing step and this is exactly what we need.\nconst nextTick = async () => { };\n// Returns control to thread each \'tick\' ms to avoid blocking\nasync function asyncLoop(iters, tick, cb) {\n    let ts = Date.now();\n    for (let i = 0; i < iters; i++) {\n        cb(i);\n        // Date.now() is not monotonic, so in case if clock goes backwards we return return control too\n        const diff = Date.now() - ts;\n        if (diff >= 0 && diff < tick)\n            continue;\n        await nextTick();\n        ts += diff;\n    }\n}\nfunction utf8ToBytes(str) {\n    if (typeof str !== \'string\') {\n        throw new TypeError(`utf8ToBytes expected string, got ${typeof str}`);\n    }\n    return new TextEncoder().encode(str);\n}\nfunction toBytes(data) {\n    if (typeof data === \'string\')\n        data = utf8ToBytes(data);\n    if (!(data instanceof Uint8Array))\n        throw new TypeError(`Expected input type is Uint8Array (got ${typeof data})`);\n    return data;\n}\n/**\n * Concats Uint8Array-s into one; like `Buffer.concat([buf1, buf2])`\n * @example concatBytes(buf1, buf2)\n */\nfunction concatBytes(...arrays) {\n    if (!arrays.every((a) => a instanceof Uint8Array))\n        throw new Error(\'Uint8Array list expected\');\n    if (arrays.length === 1)\n        return arrays[0];\n    const length = arrays.reduce((a, arr) => a + arr.length, 0);\n    const result = new Uint8Array(length);\n    for (let i = 0, pad = 0; i < arrays.length; i++) {\n        const arr = arrays[i];\n        result.set(arr, pad);\n        pad += arr.length;\n    }\n    return result;\n}\n// For runtime check if class implements interface\nclass Hash {\n    // Safe version that clones internal state\n    clone() {\n        return this._cloneInto();\n    }\n}\n// Check if object doens\'t have custom constructor (like Uint8Array/Array)\nconst isPlainObject = (obj) => Object.prototype.toString.call(obj) === \'[object Object]\' && obj.constructor === Object;\nfunction checkOpts(defaults, opts) {\n    if (opts !== undefined && (typeof opts !== \'object\' || !isPlainObject(opts)))\n        throw new TypeError(\'Options should be object or undefined\');\n    const merged = Object.assign(defaults, opts);\n    return merged;\n}\nfunction wrapConstructor(hashConstructor) {\n    const hashC = (message) => hashConstructor().update(toBytes(message)).digest();\n    const tmp = hashConstructor();\n    hashC.outputLen = tmp.outputLen;\n    hashC.blockLen = tmp.blockLen;\n    hashC.create = () => hashConstructor();\n    return hashC;\n}\nfunction wrapConstructorWithOpts(hashCons) {\n    const hashC = (msg, opts) => hashCons(opts).update(toBytes(msg)).digest();\n    const tmp = hashCons({});\n    hashC.outputLen = tmp.outputLen;\n    hashC.blockLen = tmp.blockLen;\n    hashC.create = (opts) => hashCons(opts);\n    return hashC;\n}\n/**\n * Secure PRNG. Uses `globalThis.crypto` or node.js crypto module.\n */\nfunction randomBytes(bytesLength = 32) {\n    if (crypto_crypto && typeof crypto_crypto.getRandomValues === \'function\') {\n        return crypto_crypto.getRandomValues(new Uint8Array(bytesLength));\n    }\n    throw new Error(\'crypto.getRandomValues must be defined\');\n}\n//# sourceMappingURL=utils.js.map\n;// CONCATENATED MODULE: ./node_modules/@noble/hashes/esm/sha3.js\n\n\n\n// Various per round constants calculations\nconst [SHA3_PI, SHA3_ROTL, _SHA3_IOTA] = [[], [], []];\nconst _0n = BigInt(0);\nconst _1n = BigInt(1);\nconst _2n = BigInt(2);\nconst _7n = BigInt(7);\nconst _256n = BigInt(256);\nconst _0x71n = BigInt(0x71);\nfor (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) {\n    // Pi\n    [x, y] = [y, (2 * x + 3 * y) % 5];\n    SHA3_PI.push(2 * (5 * y + x));\n    // Rotational\n    SHA3_ROTL.push((((round + 1) * (round + 2)) / 2) % 64);\n    // Iota\n    let t = _0n;\n    for (let j = 0; j < 7; j++) {\n        R = ((R << _1n) ^ ((R >> _7n) * _0x71n)) % _256n;\n        if (R & _2n)\n            t ^= _1n << ((_1n << BigInt(j)) - _1n);\n    }\n    _SHA3_IOTA.push(t);\n}\nconst [SHA3_IOTA_H, SHA3_IOTA_L] = _u64.split(_SHA3_IOTA, true);\n// Left rotation (without 0, 32, 64)\nconst rotlH = (h, l, s) => s > 32 ? _u64.rotlBH(h, l, s) : _u64.rotlSH(h, l, s);\nconst rotlL = (h, l, s) => s > 32 ? _u64.rotlBL(h, l, s) : _u64.rotlSL(h, l, s);\n// Same as keccakf1600, but allows to skip some rounds\nfunction keccakP(s, rounds = 24) {\n    const B = new Uint32Array(5 * 2);\n    // NOTE: all indices are x2 since we store state as u32 instead of u64 (bigints to slow in js)\n    for (let round = 24 - rounds; round < 24; round++) {\n        // Theta θ\n        for (let x = 0; x < 10; x++)\n            B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];\n        for (let x = 0; x < 10; x += 2) {\n            const idx1 = (x + 8) % 10;\n            const idx0 = (x + 2) % 10;\n            const B0 = B[idx0];\n            const B1 = B[idx0 + 1];\n            const Th = rotlH(B0, B1, 1) ^ B[idx1];\n            const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1];\n            for (let y = 0; y < 50; y += 10) {\n                s[x + y] ^= Th;\n                s[x + y + 1] ^= Tl;\n            }\n        }\n        // Rho (ρ) and Pi (π)\n        let curH = s[2];\n        let curL = s[3];\n        for (let t = 0; t < 24; t++) {\n            const shift = SHA3_ROTL[t];\n            const Th = rotlH(curH, curL, shift);\n            const Tl = rotlL(curH, curL, shift);\n            const PI = SHA3_PI[t];\n            curH = s[PI];\n            curL = s[PI + 1];\n            s[PI] = Th;\n            s[PI + 1] = Tl;\n        }\n        // Chi (χ)\n        for (let y = 0; y < 50; y += 10) {\n            for (let x = 0; x < 10; x++)\n                B[x] = s[y + x];\n            for (let x = 0; x < 10; x++)\n                s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];\n        }\n        // Iota (ι)\n        s[0] ^= SHA3_IOTA_H[round];\n        s[1] ^= SHA3_IOTA_L[round];\n    }\n    B.fill(0);\n}\nclass Keccak extends Hash {\n    // NOTE: we accept arguments in bytes instead of bits here.\n    constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) {\n        super();\n        this.blockLen = blockLen;\n        this.suffix = suffix;\n        this.outputLen = outputLen;\n        this.enableXOF = enableXOF;\n        this.rounds = rounds;\n        this.pos = 0;\n        this.posOut = 0;\n        this.finished = false;\n        this.destroyed = false;\n        // Can be passed from user as dkLen\n        _assert.number(outputLen);\n        // 1600 = 5x5 matrix of 64bit.  1600 bits === 200 bytes\n        if (0 >= this.blockLen || this.blockLen >= 200)\n            throw new Error(\'Sha3 supports only keccak-f1600 function\');\n        this.state = new Uint8Array(200);\n        this.state32 = u32(this.state);\n    }\n    keccak() {\n        keccakP(this.state32, this.rounds);\n        this.posOut = 0;\n        this.pos = 0;\n    }\n    update(data) {\n        _assert.exists(this);\n        const { blockLen, state } = this;\n        data = toBytes(data);\n        const len = data.length;\n        for (let pos = 0; pos < len;) {\n            const take = Math.min(blockLen - this.pos, len - pos);\n            for (let i = 0; i < take; i++)\n                state[this.pos++] ^= data[pos++];\n            if (this.pos === blockLen)\n                this.keccak();\n        }\n        return this;\n    }\n    finish() {\n        if (this.finished)\n            return;\n        this.finished = true;\n        const { state, suffix, pos, blockLen } = this;\n        // Do the padding\n        state[pos] ^= suffix;\n        if ((suffix & 0x80) !== 0 && pos === blockLen - 1)\n            this.keccak();\n        state[blockLen - 1] ^= 0x80;\n        this.keccak();\n    }\n    writeInto(out) {\n        _assert.exists(this, false);\n        _assert.bytes(out);\n        this.finish();\n        const bufferOut = this.state;\n        const { blockLen } = this;\n        for (let pos = 0, len = out.length; pos < len;) {\n            if (this.posOut >= blockLen)\n                this.keccak();\n            const take = Math.min(blockLen - this.posOut, len - pos);\n            out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);\n            this.posOut += take;\n            pos += take;\n        }\n        return out;\n    }\n    xofInto(out) {\n        // Sha3/Keccak usage with XOF is probably mistake, only SHAKE instances can do XOF\n        if (!this.enableXOF)\n            throw new Error(\'XOF is not possible for this instance\');\n        return this.writeInto(out);\n    }\n    xof(bytes) {\n        _assert.number(bytes);\n        return this.xofInto(new Uint8Array(bytes));\n    }\n    digestInto(out) {\n        _assert.output(out, this);\n        if (this.finished)\n            throw new Error(\'digest() was already called\');\n        this.writeInto(out);\n        this.destroy();\n        return out;\n    }\n    digest() {\n        return this.digestInto(new Uint8Array(this.outputLen));\n    }\n    destroy() {\n        this.destroyed = true;\n        this.state.fill(0);\n    }\n    _cloneInto(to) {\n        const { blockLen, suffix, outputLen, rounds, enableXOF } = this;\n        to || (to = new Keccak(blockLen, suffix, outputLen, enableXOF, rounds));\n        to.state32.set(this.state32);\n        to.pos = this.pos;\n        to.posOut = this.posOut;\n        to.finished = this.finished;\n        to.rounds = rounds;\n        // Suffix can change in cSHAKE\n        to.suffix = suffix;\n        to.outputLen = outputLen;\n        to.enableXOF = enableXOF;\n        to.destroyed = this.destroyed;\n        return to;\n    }\n}\nconst gen = (suffix, blockLen, outputLen) => wrapConstructor(() => new Keccak(blockLen, suffix, outputLen));\nconst sha3_224 = gen(0x06, 144, 224 / 8);\n/**\n * SHA3-256 hash function\n * @param message - that would be hashed\n */\nconst sha3_256 = gen(0x06, 136, 256 / 8);\nconst sha3_384 = gen(0x06, 104, 384 / 8);\nconst sha3_512 = gen(0x06, 72, 512 / 8);\nconst keccak_224 = gen(0x01, 144, 224 / 8);\n/**\n * keccak-256 hash function. Different from SHA3-256.\n * @param message - that would be hashed\n */\nconst keccak_256 = gen(0x01, 136, 256 / 8);\nconst keccak_384 = gen(0x01, 104, 384 / 8);\nconst keccak_512 = gen(0x01, 72, 512 / 8);\nconst genShake = (suffix, blockLen, outputLen) => wrapConstructorWithOpts((opts = {}) => new Keccak(blockLen, suffix, opts.dkLen === undefined ? outputLen : opts.dkLen, true));\nconst shake128 = genShake(0x1f, 168, 128 / 8);\nconst shake256 = genShake(0x1f, 136, 256 / 8);\n//# sourceMappingURL=sha3.js.map\n;// CONCATENATED MODULE: ./node_modules/@noble/curves/esm/abstract/utils.js\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\nconst utils_0n = BigInt(0);\nconst utils_1n = BigInt(1);\nconst utils_2n = BigInt(2);\nconst u8a = (a) => a instanceof Uint8Array;\nconst utils_hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, \'0\'));\nfunction utils_bytesToHex(bytes) {\n    if (!u8a(bytes))\n        throw new Error(\'Uint8Array expected\');\n    // pre-caching improves the speed 6x\n    let hex = \'\';\n    for (let i = 0; i < bytes.length; i++) {\n        hex += utils_hexes[bytes[i]];\n    }\n    return hex;\n}\nfunction numberToHexUnpadded(num) {\n    const hex = num.toString(16);\n    return hex.length & 1 ? `0${hex}` : hex;\n}\nfunction hexToNumber(hex) {\n    if (typeof hex !== \'string\')\n        throw new Error(\'hex string expected, got \' + typeof hex);\n    // Big Endian\n    return BigInt(hex === \'\' ? \'0\' : `0x${hex}`);\n}\n// Caching slows it down 2-3x\nfunction utils_hexToBytes(hex) {\n    if (typeof hex !== \'string\')\n        throw new Error(\'hex string expected, got \' + typeof hex);\n    if (hex.length % 2)\n        throw new Error(\'hex string is invalid: unpadded \' + hex.length);\n    const array = new Uint8Array(hex.length / 2);\n    for (let i = 0; i < array.length; i++) {\n        const j = i * 2;\n        const hexByte = hex.slice(j, j + 2);\n        const byte = Number.parseInt(hexByte, 16);\n        if (Number.isNaN(byte) || byte < 0)\n            throw new Error(\'invalid byte sequence\');\n        array[i] = byte;\n    }\n    return array;\n}\n// Big Endian\nfunction utils_bytesToNumberBE(bytes) {\n    return hexToNumber(utils_bytesToHex(bytes));\n}\nfunction utils_bytesToNumberLE(bytes) {\n    if (!u8a(bytes))\n        throw new Error(\'Uint8Array expected\');\n    return hexToNumber(utils_bytesToHex(Uint8Array.from(bytes).reverse()));\n}\nconst numberToBytesBE = (n, len) => utils_hexToBytes(n.toString(16).padStart(len * 2, \'0\'));\nconst numberToBytesLE = (n, len) => numberToBytesBE(n, len).reverse();\n// Returns variable number bytes (minimal bigint encoding?)\nconst numberToVarBytesBE = (n) => utils_hexToBytes(numberToHexUnpadded(n));\nfunction utils_ensureBytes(title, hex, expectedLength) {\n    let res;\n    if (typeof hex === \'string\') {\n        try {\n            res = utils_hexToBytes(hex);\n        }\n        catch (e) {\n            throw new Error(`${title} must be valid hex string, got "${hex}". Cause: ${e}`);\n        }\n    }\n    else if (u8a(hex)) {\n        // Uint8Array.from() instead of hash.slice() because node.js Buffer\n        // is instance of Uint8Array, and its slice() creates **mutable** copy\n        res = Uint8Array.from(hex);\n    }\n    else {\n        throw new Error(`${title} must be hex string or Uint8Array`);\n    }\n    const len = res.length;\n    if (typeof expectedLength === \'number\' && len !== expectedLength)\n        throw new Error(`${title} expected ${expectedLength} bytes, got ${len}`);\n    return res;\n}\n// Copies several Uint8Arrays into one.\nfunction utils_concatBytes(...arrs) {\n    const r = new Uint8Array(arrs.reduce((sum, a) => sum + a.length, 0));\n    let pad = 0; // walk through each item, ensure they have proper type\n    arrs.forEach((a) => {\n        if (!u8a(a))\n            throw new Error(\'Uint8Array expected\');\n        r.set(a, pad);\n        pad += a.length;\n    });\n    return r;\n}\nfunction equalBytes(b1, b2) {\n    // We don\'t care about timing attacks here\n    if (b1.length !== b2.length)\n        return false;\n    for (let i = 0; i < b1.length; i++)\n        if (b1[i] !== b2[i])\n            return false;\n    return true;\n}\nfunction utils_utf8ToBytes(str) {\n    if (typeof str !== \'string\') {\n        throw new Error(`utf8ToBytes expected string, got ${typeof str}`);\n    }\n    return new TextEncoder().encode(str);\n}\n// Bit operations\n// Amount of bits inside bigint (Same as n.toString(2).length)\nfunction bitLen(n) {\n    let len;\n    for (len = 0; n > utils_0n; n >>= utils_1n, len += 1)\n        ;\n    return len;\n}\n// Gets single bit at position. NOTE: first bit position is 0 (same as arrays)\n// Same as !!+Array.from(n.toString(2)).reverse()[pos]\nconst bitGet = (n, pos) => (n >> BigInt(pos)) & utils_1n;\n// Sets single bit at position\nconst bitSet = (n, pos, value) => n | ((value ? utils_1n : utils_0n) << BigInt(pos));\n// Return mask for N bits (Same as BigInt(`0b${Array(i).fill(\'1\').join(\'\')}`))\n// Not using ** operator with bigints for old engines.\nconst bitMask = (n) => (utils_2n << BigInt(n - 1)) - utils_1n;\n// DRBG\nconst u8n = (data) => new Uint8Array(data); // creates Uint8Array\nconst u8fr = (arr) => Uint8Array.from(arr); // another shortcut\n/**\n * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.\n * @returns function that will call DRBG until 2nd arg returns something meaningful\n * @example\n *   const drbg = createHmacDRBG<Key>(32, 32, hmac);\n *   drbg(seed, bytesToKey); // bytesToKey must return Key or undefined\n */\nfunction createHmacDrbg(hashLen, qByteLen, hmacFn) {\n    if (typeof hashLen !== \'number\' || hashLen < 2)\n        throw new Error(\'hashLen must be a number\');\n    if (typeof qByteLen !== \'number\' || qByteLen < 2)\n        throw new Error(\'qByteLen must be a number\');\n    if (typeof hmacFn !== \'function\')\n        throw new Error(\'hmacFn must be a function\');\n    // Step B, Step C: set hashLen to 8*ceil(hlen/8)\n    let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.\n    let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same\n    let i = 0; // Iterations counter, will throw when over 1000\n    const reset = () => {\n        v.fill(1);\n        k.fill(0);\n        i = 0;\n    };\n    const h = (...b) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)\n    const reseed = (seed = u8n()) => {\n        // HMAC-DRBG reseed() function. Steps D-G\n        k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed)\n        v = h(); // v = hmac(k || v)\n        if (seed.length === 0)\n            return;\n        k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed)\n        v = h(); // v = hmac(k || v)\n    };\n    const gen = () => {\n        // HMAC-DRBG generate() function\n        if (i++ >= 1000)\n            throw new Error(\'drbg: tried 1000 values\');\n        let len = 0;\n        const out = [];\n        while (len < qByteLen) {\n            v = h();\n            const sl = v.slice();\n            out.push(sl);\n            len += v.length;\n        }\n        return utils_concatBytes(...out);\n    };\n    const genUntil = (seed, pred) => {\n        reset();\n        reseed(seed); // Steps D-G\n        let res = undefined; // Step H: grind until k is in [1..n-1]\n        while (!(res = pred(gen())))\n            reseed();\n        reset();\n        return res;\n    };\n    return genUntil;\n}\n// Validating curves and fields\nconst validatorFns = {\n    bigint: (val) => typeof val === \'bigint\',\n    function: (val) => typeof val === \'function\',\n    boolean: (val) => typeof val === \'boolean\',\n    string: (val) => typeof val === \'string\',\n    isSafeInteger: (val) => Number.isSafeInteger(val),\n    array: (val) => Array.isArray(val),\n    field: (val, object) => object.Fp.isValid(val),\n    hash: (val) => typeof val === \'function\' && Number.isSafeInteger(val.outputLen),\n};\n// type Record<K extends string | number | symbol, T> = { [P in K]: T; }\nfunction validateObject(object, validators, optValidators = {}) {\n    const checkField = (fieldName, type, isOptional) => {\n        const checkVal = validatorFns[type];\n        if (typeof checkVal !== \'function\')\n            throw new Error(`Invalid validator "${type}", expected function`);\n        const val = object[fieldName];\n        if (isOptional && val === undefined)\n            return;\n        if (!checkVal(val, object)) {\n            throw new Error(`Invalid param ${String(fieldName)}=${val} (${typeof val}), expected ${type}`);\n        }\n    };\n    for (const [fieldName, type] of Object.entries(validators))\n        checkField(fieldName, type, false);\n    for (const [fieldName, type] of Object.entries(optValidators))\n        checkField(fieldName, type, true);\n    return object;\n}\n// validate type tests\n// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 };\n// const z0 = validateObject(o, { a: \'isSafeInteger\' }, { c: \'bigint\' }); // Ok!\n// // Should fail type-check\n// const z1 = validateObject(o, { a: \'tmp\' }, { c: \'zz\' });\n// const z2 = validateObject(o, { a: \'isSafeInteger\' }, { c: \'zz\' });\n// const z3 = validateObject(o, { test: \'boolean\', z: \'bug\' });\n// const z4 = validateObject(o, { a: \'boolean\', z: \'bug\' });\n//# sourceMappingURL=utils.js.map\n;// CONCATENATED MODULE: ./node_modules/@noble/curves/esm/abstract/modular.js\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// Utilities for modular arithmetics and finite fields\n\n// prettier-ignore\nconst modular_0n = BigInt(0), modular_1n = BigInt(1), modular_2n = BigInt(2), _3n = BigInt(3);\n// prettier-ignore\nconst _4n = BigInt(4), _5n = BigInt(5), _8n = BigInt(8);\n// prettier-ignore\nconst _9n = BigInt(9), _16n = BigInt(16);\n// Calculates a modulo b\nfunction mod(a, b) {\n    const result = a % b;\n    return result >= modular_0n ? result : b + result;\n}\n/**\n * Efficiently exponentiate num to power and do modular division.\n * Unsafe in some contexts: uses ladder, so can expose bigint bits.\n * @example\n * powMod(2n, 6n, 11n) // 64n % 11n == 9n\n */\n// TODO: use field version && remove\nfunction pow(num, power, modulo) {\n    if (modulo <= modular_0n || power < modular_0n)\n        throw new Error(\'Expected power/modulo > 0\');\n    if (modulo === modular_1n)\n        return modular_0n;\n    let res = modular_1n;\n    while (power > modular_0n) {\n        if (power & modular_1n)\n            res = (res * num) % modulo;\n        num = (num * num) % modulo;\n        power >>= modular_1n;\n    }\n    return res;\n}\n// Does x ^ (2 ^ power) mod p. pow2(30, 4) == 30 ^ (2 ^ 4)\nfunction pow2(x, power, modulo) {\n    let res = x;\n    while (power-- > modular_0n) {\n        res *= res;\n        res %= modulo;\n    }\n    return res;\n}\n// Inverses number over modulo\nfunction invert(number, modulo) {\n    if (number === modular_0n || modulo <= modular_0n) {\n        throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`);\n    }\n    // Eucledian GCD https://brilliant.org/wiki/extended-euclidean-algorithm/\n    // Fermat\'s little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower.\n    let a = mod(number, modulo);\n    let b = modulo;\n    // prettier-ignore\n    let x = modular_0n, y = modular_1n, u = modular_1n, v = modular_0n;\n    while (a !== modular_0n) {\n        // JIT applies optimization if those two lines follow each other\n        const q = b / a;\n        const r = b % a;\n        const m = x - u * q;\n        const n = y - v * q;\n        // prettier-ignore\n        b = a, a = r, x = u, y = v, u = m, v = n;\n    }\n    const gcd = b;\n    if (gcd !== modular_1n)\n        throw new Error(\'invert: does not exist\');\n    return mod(x, modulo);\n}\n// Tonelli-Shanks algorithm\n// Paper 1: https://eprint.iacr.org/2012/685.pdf (page 12)\n// Paper 2: Square Roots from 1; 24, 51, 10 to Dan Shanks\nfunction tonelliShanks(P) {\n    // Legendre constant: used to calculate Legendre symbol (a | p),\n    // which denotes the value of a^((p-1)/2) (mod p).\n    // (a | p) ≡ 1    if a is a square (mod p)\n    // (a | p) ≡ -1   if a is not a square (mod p)\n    // (a | p) ≡ 0    if a ≡ 0 (mod p)\n    const legendreC = (P - modular_1n) / modular_2n;\n    let Q, S, Z;\n    // Step 1: By factoring out powers of 2 from p - 1,\n    // find q and s such that p - 1 = q*(2^s) with q odd\n    for (Q = P - modular_1n, S = 0; Q % modular_2n === modular_0n; Q /= modular_2n, S++)\n        ;\n    // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq\n    for (Z = modular_2n; Z < P && pow(Z, legendreC, P) !== P - modular_1n; Z++)\n        ;\n    // Fast-path\n    if (S === 1) {\n        const p1div4 = (P + modular_1n) / _4n;\n        return function tonelliFast(Fp, n) {\n            const root = Fp.pow(n, p1div4);\n            if (!Fp.eql(Fp.sqr(root), n))\n                throw new Error(\'Cannot find square root\');\n            return root;\n        };\n    }\n    // Slow-path\n    const Q1div2 = (Q + modular_1n) / modular_2n;\n    return function tonelliSlow(Fp, n) {\n        // Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1\n        if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE))\n            throw new Error(\'Cannot find square root\');\n        let r = S;\n        // TODO: will fail at Fp2/etc\n        let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q); // will update both x and b\n        let x = Fp.pow(n, Q1div2); // first guess at the square root\n        let b = Fp.pow(n, Q); // first guess at the fudge factor\n        while (!Fp.eql(b, Fp.ONE)) {\n            if (Fp.eql(b, Fp.ZERO))\n                return Fp.ZERO; // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0)\n            // Find m such b^(2^m)==1\n            let m = 1;\n            for (let t2 = Fp.sqr(b); m < r; m++) {\n                if (Fp.eql(t2, Fp.ONE))\n                    break;\n                t2 = Fp.sqr(t2); // t2 *= t2\n            }\n            // NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow\n            const ge = Fp.pow(g, modular_1n << BigInt(r - m - 1)); // ge = 2^(r-m-1)\n            g = Fp.sqr(ge); // g = ge * ge\n            x = Fp.mul(x, ge); // x *= ge\n            b = Fp.mul(b, g); // b *= g\n            r = m;\n        }\n        return x;\n    };\n}\nfunction FpSqrt(P) {\n    // NOTE: different algorithms can give different roots, it is up to user to decide which one they want.\n    // For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).\n    // P ≡ 3 (mod 4)\n    // √n = n^((P+1)/4)\n    if (P % _4n === _3n) {\n        // Not all roots possible!\n        // const ORDER =\n        //   0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn;\n        // const NUM = 72057594037927816n;\n        const p1div4 = (P + modular_1n) / _4n;\n        return function sqrt3mod4(Fp, n) {\n            const root = Fp.pow(n, p1div4);\n            // Throw if root**2 != n\n            if (!Fp.eql(Fp.sqr(root), n))\n                throw new Error(\'Cannot find square root\');\n            return root;\n        };\n    }\n    // Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10)\n    if (P % _8n === _5n) {\n        const c1 = (P - _5n) / _8n;\n        return function sqrt5mod8(Fp, n) {\n            const n2 = Fp.mul(n, modular_2n);\n            const v = Fp.pow(n2, c1);\n            const nv = Fp.mul(n, v);\n            const i = Fp.mul(Fp.mul(nv, modular_2n), v);\n            const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));\n            if (!Fp.eql(Fp.sqr(root), n))\n                throw new Error(\'Cannot find square root\');\n            return root;\n        };\n    }\n    // P ≡ 9 (mod 16)\n    if (P % _16n === _9n) {\n        // NOTE: tonelli is too slow for bls-Fp2 calculations even on start\n        // Means we cannot use sqrt for constants at all!\n        //\n        // const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); //  1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F\n        // const c2 = Fp.sqrt(c1);                //  2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F\n        // const c3 = Fp.sqrt(Fp.negate(c1));     //  3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F\n        // const c4 = (P + _7n) / _16n;           //  4. c4 = (q + 7) / 16        # Integer arithmetic\n        // sqrt = (x) => {\n        //   let tv1 = Fp.pow(x, c4);             //  1. tv1 = x^c4\n        //   let tv2 = Fp.mul(c1, tv1);           //  2. tv2 = c1 * tv1\n        //   const tv3 = Fp.mul(c2, tv1);         //  3. tv3 = c2 * tv1\n        //   let tv4 = Fp.mul(c3, tv1);           //  4. tv4 = c3 * tv1\n        //   const e1 = Fp.equals(Fp.square(tv2), x); //  5.  e1 = (tv2^2) == x\n        //   const e2 = Fp.equals(Fp.square(tv3), x); //  6.  e2 = (tv3^2) == x\n        //   tv1 = Fp.cmov(tv1, tv2, e1); //  7. tv1 = CMOV(tv1, tv2, e1)  # Select tv2 if (tv2^2) == x\n        //   tv2 = Fp.cmov(tv4, tv3, e2); //  8. tv2 = CMOV(tv4, tv3, e2)  # Select tv3 if (tv3^2) == x\n        //   const e3 = Fp.equals(Fp.square(tv2), x); //  9.  e3 = (tv2^2) == x\n        //   return Fp.cmov(tv1, tv2, e3); //  10.  z = CMOV(tv1, tv2, e3)  # Select the sqrt from tv1 and tv2\n        // }\n    }\n    // Other cases: Tonelli-Shanks algorithm\n    return tonelliShanks(P);\n}\n// Little-endian check for first LE bit (last BE bit);\nconst isNegativeLE = (num, modulo) => (mod(num, modulo) & modular_1n) === modular_1n;\n// prettier-ignore\nconst FIELD_FIELDS = [\n    \'create\', \'isValid\', \'is0\', \'neg\', \'inv\', \'sqrt\', \'sqr\',\n    \'eql\', \'add\', \'sub\', \'mul\', \'pow\', \'div\',\n    \'addN\', \'subN\', \'mulN\', \'sqrN\'\n];\nfunction validateField(field) {\n    const initial = {\n        ORDER: \'bigint\',\n        MASK: \'bigint\',\n        BYTES: \'isSafeInteger\',\n        BITS: \'isSafeInteger\',\n    };\n    const opts = FIELD_FIELDS.reduce((map, val) => {\n        map[val] = \'function\';\n        return map;\n    }, initial);\n    return validateObject(field, opts);\n}\n// Generic field functions\nfunction FpPow(f, num, power) {\n    // Should have same speed as pow for bigints\n    // TODO: benchmark!\n    if (power < modular_0n)\n        throw new Error(\'Expected power > 0\');\n    if (power === modular_0n)\n        return f.ONE;\n    if (power === modular_1n)\n        return num;\n    let p = f.ONE;\n    let d = num;\n    while (power > modular_0n) {\n        if (power & modular_1n)\n            p = f.mul(p, d);\n        d = f.sqr(d);\n        power >>= modular_1n;\n    }\n    return p;\n}\n// 0 is non-invertible: non-batched version will throw on 0\nfunction FpInvertBatch(f, nums) {\n    const tmp = new Array(nums.length);\n    // Walk from first to last, multiply them by each other MOD p\n    const lastMultiplied = nums.reduce((acc, num, i) => {\n        if (f.is0(num))\n            return acc;\n        tmp[i] = acc;\n        return f.mul(acc, num);\n    }, f.ONE);\n    // Invert last element\n    const inverted = f.inv(lastMultiplied);\n    // Walk from last to first, multiply them by inverted each other MOD p\n    nums.reduceRight((acc, num, i) => {\n        if (f.is0(num))\n            return acc;\n        tmp[i] = f.mul(acc, tmp[i]);\n        return f.mul(acc, num);\n    }, inverted);\n    return tmp;\n}\nfunction FpDiv(f, lhs, rhs) {\n    return f.mul(lhs, typeof rhs === \'bigint\' ? invert(rhs, f.ORDER) : f.inv(rhs));\n}\n// This function returns True whenever the value x is a square in the field F.\nfunction FpIsSquare(f) {\n    const legendreConst = (f.ORDER - modular_1n) / modular_2n; // Integer arithmetic\n    return (x) => {\n        const p = f.pow(x, legendreConst);\n        return f.eql(p, f.ZERO) || f.eql(p, f.ONE);\n    };\n}\n// CURVE.n lengths\nfunction nLength(n, nBitLength) {\n    // Bit size, byte size of CURVE.n\n    const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length;\n    const nByteLength = Math.ceil(_nBitLength / 8);\n    return { nBitLength: _nBitLength, nByteLength };\n}\n/**\n * Initializes a galois field over prime. Non-primes are not supported for now.\n * Do not init in loop: slow. Very fragile: always run a benchmark on change.\n * Major performance gains:\n * a) non-normalized operations like mulN instead of mul\n * b) `Object.freeze`\n * c) Same object shape: never add or remove keys\n * @param ORDER prime positive bigint\n * @param bitLen how many bits the field consumes\n * @param isLE (def: false) if encoding / decoding should be in little-endian\n * @param redef optional faster redefinitions of sqrt and other methods\n */\nfunction Field(ORDER, bitLen, isLE = false, redef = {}) {\n    if (ORDER <= modular_0n)\n        throw new Error(`Expected Fp ORDER > 0, got ${ORDER}`);\n    const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen);\n    if (BYTES > 2048)\n        throw new Error(\'Field lengths over 2048 bytes are not supported\');\n    const sqrtP = FpSqrt(ORDER);\n    const f = Object.freeze({\n        ORDER,\n        BITS,\n        BYTES,\n        MASK: bitMask(BITS),\n        ZERO: modular_0n,\n        ONE: modular_1n,\n        create: (num) => mod(num, ORDER),\n        isValid: (num) => {\n            if (typeof num !== \'bigint\')\n                throw new Error(`Invalid field element: expected bigint, got ${typeof num}`);\n            return modular_0n <= num && num < ORDER; // 0 is valid element, but it\'s not invertible\n        },\n        is0: (num) => num === modular_0n,\n        isOdd: (num) => (num & modular_1n) === modular_1n,\n        neg: (num) => mod(-num, ORDER),\n        eql: (lhs, rhs) => lhs === rhs,\n        sqr: (num) => mod(num * num, ORDER),\n        add: (lhs, rhs) => mod(lhs + rhs, ORDER),\n        sub: (lhs, rhs) => mod(lhs - rhs, ORDER),\n        mul: (lhs, rhs) => mod(lhs * rhs, ORDER),\n        pow: (num, power) => FpPow(f, num, power),\n        div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),\n        // Same as above, but doesn\'t normalize\n        sqrN: (num) => num * num,\n        addN: (lhs, rhs) => lhs + rhs,\n        subN: (lhs, rhs) => lhs - rhs,\n        mulN: (lhs, rhs) => lhs * rhs,\n        inv: (num) => invert(num, ORDER),\n        sqrt: redef.sqrt || ((n) => sqrtP(f, n)),\n        invertBatch: (lst) => FpInvertBatch(f, lst),\n        // TODO: do we really need constant cmov?\n        // We don\'t have const-time bigints anyway, so probably will be not very useful\n        cmov: (a, b, c) => (c ? b : a),\n        toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)),\n        fromBytes: (bytes) => {\n            if (bytes.length !== BYTES)\n                throw new Error(`Fp.fromBytes: expected ${BYTES}, got ${bytes.length}`);\n            return isLE ? utils_bytesToNumberLE(bytes) : utils_bytesToNumberBE(bytes);\n        },\n    });\n    return Object.freeze(f);\n}\nfunction FpSqrtOdd(Fp, elm) {\n    if (!Fp.isOdd)\n        throw new Error(`Field doesn\'t have isOdd`);\n    const root = Fp.sqrt(elm);\n    return Fp.isOdd(root) ? root : Fp.neg(root);\n}\nfunction FpSqrtEven(Fp, elm) {\n    if (!Fp.isOdd)\n        throw new Error(`Field doesn\'t have isOdd`);\n    const root = Fp.sqrt(elm);\n    return Fp.isOdd(root) ? Fp.neg(root) : root;\n}\n/**\n * FIPS 186 B.4.1-compliant "constant-time" private key generation utility.\n * Can take (n+8) or more bytes of uniform input e.g. from CSPRNG or KDF\n * and convert them into private scalar, with the modulo bias being neglible.\n * Needs at least 40 bytes of input for 32-byte private key.\n * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/\n * @param hash hash output from SHA3 or a similar function\n * @returns valid private scalar\n */\nfunction hashToPrivateScalar(hash, groupOrder, isLE = false) {\n    hash = ensureBytes(\'privateHash\', hash);\n    const hashLen = hash.length;\n    const minLen = nLength(groupOrder).nByteLength + 8;\n    if (minLen < 24 || hashLen < minLen || hashLen > 1024)\n        throw new Error(`hashToPrivateScalar: expected ${minLen}-1024 bytes of input, got ${hashLen}`);\n    const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash);\n    return mod(num, groupOrder - modular_1n) + modular_1n;\n}\n//# sourceMappingURL=modular.js.map\n;// CONCATENATED MODULE: ./node_modules/@noble/curves/esm/abstract/curve.js\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// Abelian group utilities\n\n\nconst curve_0n = BigInt(0);\nconst curve_1n = BigInt(1);\n// Elliptic curve multiplication of Point by scalar. Fragile.\n// Scalars should always be less than curve order: this should be checked inside of a curve itself.\n// Creates precomputation tables for fast multiplication:\n// - private scalar is split by fixed size windows of W bits\n// - every window point is collected from window\'s table & added to accumulator\n// - since windows are different, same point inside tables won\'t be accessed more than once per calc\n// - each multiplication is \'Math.ceil(CURVE_ORDER / 𝑊) + 1\' point additions (fixed for any scalar)\n// - +1 window is neccessary for wNAF\n// - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication\n// TODO: Research returning 2d JS array of windows, instead of a single window. This would allow\n// windows to be in different memory locations\nfunction wNAF(c, bits) {\n    const constTimeNegate = (condition, item) => {\n        const neg = item.negate();\n        return condition ? neg : item;\n    };\n    const opts = (W) => {\n        const windows = Math.ceil(bits / W) + 1; // +1, because\n        const windowSize = 2 ** (W - 1); // -1 because we skip zero\n        return { windows, windowSize };\n    };\n    return {\n        constTimeNegate,\n        // non-const time multiplication ladder\n        unsafeLadder(elm, n) {\n            let p = c.ZERO;\n            let d = elm;\n            while (n > curve_0n) {\n                if (n & curve_1n)\n                    p = p.add(d);\n                d = d.double();\n                n >>= curve_1n;\n            }\n            return p;\n        },\n        /**\n         * Creates a wNAF precomputation window. Used for caching.\n         * Default window size is set by `utils.precompute()` and is equal to 8.\n         * Number of precomputed points depends on the curve size:\n         * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:\n         * - 𝑊 is the window size\n         * - 𝑛 is the bitlength of the curve order.\n         * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.\n         * @returns precomputed point tables flattened to a single array\n         */\n        precomputeWindow(elm, W) {\n            const { windows, windowSize } = opts(W);\n            const points = [];\n            let p = elm;\n            let base = p;\n            for (let window = 0; window < windows; window++) {\n                base = p;\n                points.push(base);\n                // =1, because we skip zero\n                for (let i = 1; i < windowSize; i++) {\n                    base = base.add(p);\n                    points.push(base);\n                }\n                p = base.double();\n            }\n            return points;\n        },\n        /**\n         * Implements ec multiplication using precomputed tables and w-ary non-adjacent form.\n         * @param W window size\n         * @param precomputes precomputed tables\n         * @param n scalar (we don\'t check here, but should be less than curve order)\n         * @returns real and fake (for const-time) points\n         */\n        wNAF(W, precomputes, n) {\n            // TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise\n            // But need to carefully remove other checks before wNAF. ORDER == bits here\n            const { windows, windowSize } = opts(W);\n            let p = c.ZERO;\n            let f = c.BASE;\n            const mask = BigInt(2 ** W - 1); // Create mask with W ones: 0b1111 for W=4 etc.\n            const maxNumber = 2 ** W;\n            const shiftBy = BigInt(W);\n            for (let window = 0; window < windows; window++) {\n                const offset = window * windowSize;\n                // Extract W bits.\n                let wbits = Number(n & mask);\n                // Shift number by W bits.\n                n >>= shiftBy;\n                // If the bits are bigger than max size, we\'ll split those.\n                // +224 => 256 - 32\n                if (wbits > windowSize) {\n                    wbits -= maxNumber;\n                    n += curve_1n;\n                }\n                // This code was first written with assumption that \'f\' and \'p\' will never be infinity point:\n                // since each addition is multiplied by 2 ** W, it cannot cancel each other. However,\n                // there is negate now: it is possible that negated element from low value\n                // would be the same as high element, which will create carry into next window.\n                // It\'s not obvious how this can fail, but still worth investigating later.\n                // Check if we\'re onto Zero point.\n                // Add random point inside current window to f.\n                const offset1 = offset;\n                const offset2 = offset + Math.abs(wbits) - 1; // -1 because we skip zero\n                const cond1 = window % 2 !== 0;\n                const cond2 = wbits < 0;\n                if (wbits === 0) {\n                    // The most important part for const-time getPublicKey\n                    f = f.add(constTimeNegate(cond1, precomputes[offset1]));\n                }\n                else {\n                    p = p.add(constTimeNegate(cond2, precomputes[offset2]));\n                }\n            }\n            // JIT-compiler should not eliminate f here, since it will later be used in normalizeZ()\n            // Even if the variable is still unused, there are some checks which will\n            // throw an exception, so compiler needs to prove they won\'t happen, which is hard.\n            // At this point there is a way to F be infinity-point even if p is not,\n            // which makes it less const-time: around 1 bigint multiply.\n            return { p, f };\n        },\n        wNAFCached(P, precomputesMap, n, transform) {\n            // @ts-ignore\n            const W = P._WINDOW_SIZE || 1;\n            // Calculate precomputes on a first run, reuse them after\n            let comp = precomputesMap.get(P);\n            if (!comp) {\n                comp = this.precomputeWindow(P, W);\n                if (W !== 1) {\n                    precomputesMap.set(P, transform(comp));\n                }\n            }\n            return this.wNAF(W, comp, n);\n        },\n    };\n}\nfunction validateBasic(curve) {\n    validateField(curve.Fp);\n    validateObject(curve, {\n        n: \'bigint\',\n        h: \'bigint\',\n        Gx: \'field\',\n        Gy: \'field\',\n    }, {\n        nBitLength: \'isSafeInteger\',\n        nByteLength: \'isSafeInteger\',\n    });\n    // Set defaults\n    return Object.freeze({\n        ...nLength(curve.n, curve.nBitLength),\n        ...curve,\n        ...{ p: curve.Fp.ORDER },\n    });\n}\n//# sourceMappingURL=curve.js.map\n;// CONCATENATED MODULE: ./node_modules/@noble/curves/esm/abstract/edwards.js\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y²\n\n\n\n\n// Be friendly to bad ECMAScript parsers by not using bigint literals\n// prettier-ignore\nconst edwards_0n = BigInt(0), edwards_1n = BigInt(1), edwards_2n = BigInt(2), edwards_8n = BigInt(8);\n// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex:\nconst VERIFY_DEFAULT = { zip215: true };\nfunction validateOpts(curve) {\n    const opts = validateBasic(curve);\n    validateObject(curve, {\n        hash: \'function\',\n        a: \'bigint\',\n        d: \'bigint\',\n        randomBytes: \'function\',\n    }, {\n        adjustScalarBytes: \'function\',\n        domain: \'function\',\n        uvRatio: \'function\',\n        mapToCurve: \'function\',\n    });\n    // Set defaults\n    return Object.freeze({ ...opts });\n}\n// It is not generic twisted curve for now, but ed25519/ed448 generic implementation\nfunction twistedEdwards(curveDef) {\n    const CURVE = validateOpts(curveDef);\n    const { Fp, n: CURVE_ORDER, prehash: prehash, hash: cHash, randomBytes, nByteLength, h: cofactor, } = CURVE;\n    const MASK = edwards_2n ** BigInt(nByteLength * 8);\n    const modP = Fp.create; // Function overrides\n    // sqrt(u/v)\n    const uvRatio = CURVE.uvRatio ||\n        ((u, v) => {\n            try {\n                return { isValid: true, value: Fp.sqrt(u * Fp.inv(v)) };\n            }\n            catch (e) {\n                return { isValid: false, value: edwards_0n };\n            }\n        });\n    const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes) => bytes); // NOOP\n    const domain = CURVE.domain ||\n        ((data, ctx, phflag) => {\n            if (ctx.length || phflag)\n                throw new Error(\'Contexts/pre-hash are not supported\');\n            return data;\n        }); // NOOP\n    const inBig = (n) => typeof n === \'bigint\' && edwards_0n < n; // n in [1..]\n    const inRange = (n, max) => inBig(n) && inBig(max) && n < max; // n in [1..max-1]\n    const in0MaskRange = (n) => n === edwards_0n || inRange(n, MASK); // n in [0..MASK-1]\n    function assertInRange(n, max) {\n        // n in [1..max-1]\n        if (inRange(n, max))\n            return n;\n        throw new Error(`Expected valid scalar < ${max}, got ${typeof n} ${n}`);\n    }\n    function assertGE0(n) {\n        // n in [0..CURVE_ORDER-1]\n        return n === edwards_0n ? n : assertInRange(n, CURVE_ORDER); // GE = prime subgroup, not full group\n    }\n    const pointPrecomputes = new Map();\n    function isPoint(other) {\n        if (!(other instanceof Point))\n            throw new Error(\'ExtendedPoint expected\');\n    }\n    // Extended Point works in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z, t=xy).\n    // https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Extended_coordinates\n    class Point {\n        constructor(ex, ey, ez, et) {\n            this.ex = ex;\n            this.ey = ey;\n            this.ez = ez;\n            this.et = et;\n            if (!in0MaskRange(ex))\n                throw new Error(\'x required\');\n            if (!in0MaskRange(ey))\n                throw new Error(\'y required\');\n            if (!in0MaskRange(ez))\n                throw new Error(\'z required\');\n            if (!in0MaskRange(et))\n                throw new Error(\'t required\');\n        }\n        get x() {\n            return this.toAffine().x;\n        }\n        get y() {\n            return this.toAffine().y;\n        }\n        static fromAffine(p) {\n            if (p instanceof Point)\n                throw new Error(\'extended point not allowed\');\n            const { x, y } = p || {};\n            if (!in0MaskRange(x) || !in0MaskRange(y))\n                throw new Error(\'invalid affine point\');\n            return new Point(x, y, edwards_1n, modP(x * y));\n        }\n        static normalizeZ(points) {\n            const toInv = Fp.invertBatch(points.map((p) => p.ez));\n            return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);\n        }\n        // "Private method", don\'t use it directly\n        _setWindowSize(windowSize) {\n            this._WINDOW_SIZE = windowSize;\n            pointPrecomputes.delete(this);\n        }\n        // Not required for fromHex(), which always creates valid points.\n        // Could be useful for fromAffine().\n        assertValidity() {\n            const { a, d } = CURVE;\n            if (this.is0())\n                throw new Error(\'bad point: ZERO\'); // TODO: optimize, with vars below?\n            // Equation in affine coordinates: ax² + y² = 1 + dx²y²\n            // Equation in projective coordinates (X/Z, Y/Z, Z):  (aX² + Y²)Z² = Z⁴ + dX²Y²\n            const { ex: X, ey: Y, ez: Z, et: T } = this;\n            const X2 = modP(X * X); // X²\n            const Y2 = modP(Y * Y); // Y²\n            const Z2 = modP(Z * Z); // Z²\n            const Z4 = modP(Z2 * Z2); // Z⁴\n            const aX2 = modP(X2 * a); // aX²\n            const left = modP(Z2 * modP(aX2 + Y2)); // (aX² + Y²)Z²\n            const right = modP(Z4 + modP(d * modP(X2 * Y2))); // Z⁴ + dX²Y²\n            if (left !== right)\n                throw new Error(\'bad point: equation left != right (1)\');\n            // In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T\n            const XY = modP(X * Y);\n            const ZT = modP(Z * T);\n            if (XY !== ZT)\n                throw new Error(\'bad point: equation left != right (2)\');\n        }\n        // Compare one point to another.\n        equals(other) {\n            isPoint(other);\n            const { ex: X1, ey: Y1, ez: Z1 } = this;\n            const { ex: X2, ey: Y2, ez: Z2 } = other;\n            const X1Z2 = modP(X1 * Z2);\n            const X2Z1 = modP(X2 * Z1);\n            const Y1Z2 = modP(Y1 * Z2);\n            const Y2Z1 = modP(Y2 * Z1);\n            return X1Z2 === X2Z1 && Y1Z2 === Y2Z1;\n        }\n        is0() {\n            return this.equals(Point.ZERO);\n        }\n        negate() {\n            // Flips point sign to a negative one (-x, y in affine coords)\n            return new Point(modP(-this.ex), this.ey, this.ez, modP(-this.et));\n        }\n        // Fast algo for doubling Extended Point.\n        // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd\n        // Cost: 4M + 4S + 1*a + 6add + 1*2.\n        double() {\n            const { a } = CURVE;\n            const { ex: X1, ey: Y1, ez: Z1 } = this;\n            const A = modP(X1 * X1); // A = X12\n            const B = modP(Y1 * Y1); // B = Y12\n            const C = modP(edwards_2n * modP(Z1 * Z1)); // C = 2*Z12\n            const D = modP(a * A); // D = a*A\n            const x1y1 = X1 + Y1;\n            const E = modP(modP(x1y1 * x1y1) - A - B); // E = (X1+Y1)2-A-B\n            const G = D + B; // G = D+B\n            const F = G - C; // F = G-C\n            const H = D - B; // H = D-B\n            const X3 = modP(E * F); // X3 = E*F\n            const Y3 = modP(G * H); // Y3 = G*H\n            const T3 = modP(E * H); // T3 = E*H\n            const Z3 = modP(F * G); // Z3 = F*G\n            return new Point(X3, Y3, Z3, T3);\n        }\n        // Fast algo for adding 2 Extended Points.\n        // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd\n        // Cost: 9M + 1*a + 1*d + 7add.\n        add(other) {\n            isPoint(other);\n            const { a, d } = CURVE;\n            const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this;\n            const { ex: X2, ey: Y2, ez: Z2, et: T2 } = other;\n            // Faster algo for adding 2 Extended Points when curve\'s a=-1.\n            // http://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-4\n            // Cost: 8M + 8add + 2*2.\n            // Note: It does not check whether the `other` point is valid.\n            if (a === BigInt(-1)) {\n                const A = modP((Y1 - X1) * (Y2 + X2));\n                const B = modP((Y1 + X1) * (Y2 - X2));\n                const F = modP(B - A);\n                if (F === edwards_0n)\n                    return this.double(); // Same point. Tests say it doesn\'t affect timing\n                const C = modP(Z1 * edwards_2n * T2);\n                const D = modP(T1 * edwards_2n * Z2);\n                const E = D + C;\n                const G = B + A;\n                const H = D - C;\n                const X3 = modP(E * F);\n                const Y3 = modP(G * H);\n                const T3 = modP(E * H);\n                const Z3 = modP(F * G);\n                return new Point(X3, Y3, Z3, T3);\n            }\n            const A = modP(X1 * X2); // A = X1*X2\n            const B = modP(Y1 * Y2); // B = Y1*Y2\n            const C = modP(T1 * d * T2); // C = T1*d*T2\n            const D = modP(Z1 * Z2); // D = Z1*Z2\n            const E = modP((X1 + Y1) * (X2 + Y2) - A - B); // E = (X1+Y1)*(X2+Y2)-A-B\n            const F = D - C; // F = D-C\n            const G = D + C; // G = D+C\n            const H = modP(B - a * A); // H = B-a*A\n            const X3 = modP(E * F); // X3 = E*F\n            const Y3 = modP(G * H); // Y3 = G*H\n            const T3 = modP(E * H); // T3 = E*H\n            const Z3 = modP(F * G); // Z3 = F*G\n            return new Point(X3, Y3, Z3, T3);\n        }\n        subtract(other) {\n            return this.add(other.negate());\n        }\n        wNAF(n) {\n            return wnaf.wNAFCached(this, pointPrecomputes, n, Point.normalizeZ);\n        }\n        // Constant-time multiplication.\n        multiply(scalar) {\n            const { p, f } = this.wNAF(assertInRange(scalar, CURVE_ORDER));\n            return Point.normalizeZ([p, f])[0];\n        }\n        // Non-constant-time multiplication. Uses double-and-add algorithm.\n        // It\'s faster, but should only be used when you don\'t care about\n        // an exposed private key e.g. sig verification.\n        // Does NOT allow scalars higher than CURVE.n.\n        multiplyUnsafe(scalar) {\n            let n = assertGE0(scalar); // 0 <= scalar < CURVE.n\n            if (n === edwards_0n)\n                return I;\n            if (this.equals(I) || n === edwards_1n)\n                return this;\n            if (this.equals(G))\n                return this.wNAF(n).p;\n            return wnaf.unsafeLadder(this, n);\n        }\n        // Checks if point is of small order.\n        // If you add something to small order point, you will have "dirty"\n        // point with torsion component.\n        // Multiplies point by cofactor and checks if the result is 0.\n        isSmallOrder() {\n            return this.multiplyUnsafe(cofactor).is0();\n        }\n        // Multiplies point by curve order and checks if the result is 0.\n        // Returns `false` is the point is dirty.\n        isTorsionFree() {\n            return wnaf.unsafeLadder(this, CURVE_ORDER).is0();\n        }\n        // Converts Extended point to default (x, y) coordinates.\n        // Can accept precomputed Z^-1 - for example, from invertBatch.\n        toAffine(iz) {\n            const { ex: x, ey: y, ez: z } = this;\n            const is0 = this.is0();\n            if (iz == null)\n                iz = is0 ? edwards_8n : Fp.inv(z); // 8 was chosen arbitrarily\n            const ax = modP(x * iz);\n            const ay = modP(y * iz);\n            const zz = modP(z * iz);\n            if (is0)\n                return { x: edwards_0n, y: edwards_1n };\n            if (zz !== edwards_1n)\n                throw new Error(\'invZ was invalid\');\n            return { x: ax, y: ay };\n        }\n        clearCofactor() {\n            const { h: cofactor } = CURVE;\n            if (cofactor === edwards_1n)\n                return this;\n            return this.multiplyUnsafe(cofactor);\n        }\n        // Converts hash string or Uint8Array to Point.\n        // Uses algo from RFC8032 5.1.3.\n        static fromHex(hex, zip215 = false) {\n            const { d, a } = CURVE;\n            const len = Fp.BYTES;\n            hex = utils_ensureBytes(\'pointHex\', hex, len); // copy hex to a new array\n            const normed = hex.slice(); // copy again, we\'ll manipulate it\n            const lastByte = hex[len - 1]; // select last byte\n            normed[len - 1] = lastByte & ~0x80; // clear last bit\n            const y = utils_bytesToNumberLE(normed);\n            if (y === edwards_0n) {\n                // y=0 is allowed\n            }\n            else {\n                // RFC8032 prohibits >= p, but ZIP215 doesn\'t\n                if (zip215)\n                    assertInRange(y, MASK); // zip215=true [1..P-1] (2^255-19-1 for ed25519)\n                else\n                    assertInRange(y, Fp.ORDER); // zip215=false [1..MASK-1] (2^256-1 for ed25519)\n            }\n            // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case:\n            // ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a)\n            const y2 = modP(y * y); // denominator is always non-0 mod p.\n            const u = modP(y2 - edwards_1n); // u = y² - 1\n            const v = modP(d * y2 - a); // v = d y² + 1.\n            let { isValid, value: x } = uvRatio(u, v); // √(u/v)\n            if (!isValid)\n                throw new Error(\'Point.fromHex: invalid y coordinate\');\n            const isXOdd = (x & edwards_1n) === edwards_1n; // There are 2 square roots. Use x_0 bit to select proper\n            const isLastByteOdd = (lastByte & 0x80) !== 0; // if x=0 and x_0 = 1, fail\n            if (isLastByteOdd !== isXOdd)\n                x = modP(-x); // if x_0 != x mod 2, set x = p-x\n            return Point.fromAffine({ x, y });\n        }\n        static fromPrivateKey(privKey) {\n            return getExtendedPublicKey(privKey).point;\n        }\n        toRawBytes() {\n            const { x, y } = this.toAffine();\n            const bytes = numberToBytesLE(y, Fp.BYTES); // each y has 2 x values (x, -y)\n            bytes[bytes.length - 1] |= x & edwards_1n ? 0x80 : 0; // when compressing, it\'s enough to store y\n            return bytes; // and use the last byte to encode sign of x\n        }\n        toHex() {\n            return utils_bytesToHex(this.toRawBytes()); // Same as toRawBytes, but returns string.\n        }\n    }\n    Point.BASE = new Point(CURVE.Gx, CURVE.Gy, edwards_1n, modP(CURVE.Gx * CURVE.Gy));\n    Point.ZERO = new Point(edwards_0n, edwards_1n, edwards_1n, edwards_0n); // 0, 1, 1, 0\n    const { BASE: G, ZERO: I } = Point;\n    const wnaf = wNAF(Point, nByteLength * 8);\n    function modN(a) {\n        return mod(a, CURVE_ORDER);\n    }\n    // Little-endian SHA512 with modulo n\n    function modN_LE(hash) {\n        return modN(utils_bytesToNumberLE(hash));\n    }\n    /** Convenience method that creates public key and other stuff. RFC8032 5.1.5 */\n    function getExtendedPublicKey(key) {\n        const len = nByteLength;\n        key = utils_ensureBytes(\'private key\', key, len);\n        // Hash private key with curve\'s hash function to produce uniformingly random input\n        // Check byte lengths: ensure(64, h(ensure(32, key)))\n        const hashed = utils_ensureBytes(\'hashed private key\', cHash(key), 2 * len);\n        const head = adjustScalarBytes(hashed.slice(0, len)); // clear first half bits, produce FE\n        const prefix = hashed.slice(len, 2 * len); // second half is called key prefix (5.1.6)\n        const scalar = modN_LE(head); // The actual private scalar\n        const point = G.multiply(scalar); // Point on Edwards curve aka public key\n        const pointBytes = point.toRawBytes(); // Uint8Array representation\n        return { head, prefix, scalar, point, pointBytes };\n    }\n    // Calculates EdDSA pub key. RFC8032 5.1.5. Privkey is hashed. Use first half with 3 bits cleared\n    function getPublicKey(privKey) {\n        return getExtendedPublicKey(privKey).pointBytes;\n    }\n    // int(\'LE\', SHA512(dom2(F, C) || msgs)) mod N\n    function hashDomainToScalar(context = new Uint8Array(), ...msgs) {\n        const msg = utils_concatBytes(...msgs);\n        return modN_LE(cHash(domain(msg, utils_ensureBytes(\'context\', context), !!prehash)));\n    }\n    /** Signs message with privateKey. RFC8032 5.1.6 */\n    function sign(msg, privKey, options = {}) {\n        msg = utils_ensureBytes(\'message\', msg);\n        if (prehash)\n            msg = prehash(msg); // for ed25519ph etc.\n        const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey);\n        const r = hashDomainToScalar(options.context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)\n        const R = G.multiply(r).toRawBytes(); // R = rG\n        const k = hashDomainToScalar(options.context, R, pointBytes, msg); // R || A || PH(M)\n        const s = modN(r + k * scalar); // S = (r + k * s) mod L\n        assertGE0(s); // 0 <= s < l\n        const res = utils_concatBytes(R, numberToBytesLE(s, Fp.BYTES));\n        return utils_ensureBytes(\'result\', res, nByteLength * 2); // 64-byte signature\n    }\n    const verifyOpts = VERIFY_DEFAULT;\n    function verify(sig, msg, publicKey, options = verifyOpts) {\n        const { context, zip215 } = options;\n        const len = Fp.BYTES; // Verifies EdDSA signature against message and public key. RFC8032 5.1.7.\n        sig = utils_ensureBytes(\'signature\', sig, 2 * len); // An extended group equation is checked.\n        msg = utils_ensureBytes(\'message\', msg);\n        if (prehash)\n            msg = prehash(msg); // for ed25519ph, etc\n        const s = utils_bytesToNumberLE(sig.slice(len, 2 * len));\n        // zip215: true is good for consensus-critical apps and allows points < 2^256\n        // zip215: false follows RFC8032 / NIST186-5 and restricts points to CURVE.p\n        let A, R, SB;\n        try {\n            A = Point.fromHex(publicKey, zip215);\n            R = Point.fromHex(sig.slice(0, len), zip215);\n            SB = G.multiplyUnsafe(s); // 0 <= s < l is done inside\n        }\n        catch (error) {\n            return false;\n        }\n        const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg);\n        const RkA = R.add(A.multiplyUnsafe(k));\n        // [8][S]B = [8]R + [8][k]A\'\n        return RkA.subtract(SB).clearCofactor().equals(Point.ZERO);\n    }\n    G._setWindowSize(8); // Enable precomputes. Slows down first publicKey computation by 20ms.\n    const utils = {\n        getExtendedPublicKey,\n        // ed25519 private keys are uniform 32b. No need to check for modulo bias, like in secp256k1.\n        randomPrivateKey: () => randomBytes(Fp.BYTES),\n        /**\n         * We\'re doing scalar multiplication (used in getPublicKey etc) with precomputed BASE_POINT\n         * values. This slows down first getPublicKey() by milliseconds (see Speed section),\n         * but allows to speed-up subsequent getPublicKey() calls up to 20x.\n         * @param windowSize 2, 4, 8, 16\n         */\n        precompute(windowSize = 8, point = Point.BASE) {\n            point._setWindowSize(windowSize);\n            point.multiply(BigInt(3));\n            return point;\n        },\n    };\n    return {\n        CURVE,\n        getPublicKey,\n        sign,\n        verify,\n        ExtendedPoint: Point,\n        utils,\n    };\n}\n//# sourceMappingURL=edwards.js.map\n;// CONCATENATED MODULE: ./node_modules/@noble/curves/esm/abstract/montgomery.js\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n\n\nconst montgomery_0n = BigInt(0);\nconst montgomery_1n = BigInt(1);\nfunction montgomery_validateOpts(curve) {\n    validateObject(curve, {\n        a: \'bigint\',\n    }, {\n        montgomeryBits: \'isSafeInteger\',\n        nByteLength: \'isSafeInteger\',\n        adjustScalarBytes: \'function\',\n        domain: \'function\',\n        powPminus2: \'function\',\n        Gu: \'bigint\',\n    });\n    // Set defaults\n    return Object.freeze({ ...curve });\n}\n// NOTE: not really montgomery curve, just bunch of very specific methods for X25519/X448 (RFC 7748, https://www.rfc-editor.org/rfc/rfc7748)\n// Uses only one coordinate instead of two\nfunction montgomery(curveDef) {\n    const CURVE = montgomery_validateOpts(curveDef);\n    const { P } = CURVE;\n    const modP = (n) => mod(n, P);\n    const montgomeryBits = CURVE.montgomeryBits;\n    const montgomeryBytes = Math.ceil(montgomeryBits / 8);\n    const fieldLen = CURVE.nByteLength;\n    const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes) => bytes);\n    const powPminus2 = CURVE.powPminus2 || ((x) => pow(x, P - BigInt(2), P));\n    // cswap from RFC7748. But it is not from RFC7748!\n    /*\n      cswap(swap, x_2, x_3):\n           dummy = mask(swap) AND (x_2 XOR x_3)\n           x_2 = x_2 XOR dummy\n           x_3 = x_3 XOR dummy\n           Return (x_2, x_3)\n    Where mask(swap) is the all-1 or all-0 word of the same length as x_2\n     and x_3, computed, e.g., as mask(swap) = 0 - swap.\n    */\n    function cswap(swap, x_2, x_3) {\n        const dummy = modP(swap * (x_2 - x_3));\n        x_2 = modP(x_2 - dummy);\n        x_3 = modP(x_3 + dummy);\n        return [x_2, x_3];\n    }\n    // Accepts 0 as well\n    function assertFieldElement(n) {\n        if (typeof n === \'bigint\' && montgomery_0n <= n && n < P)\n            return n;\n        throw new Error(\'Expected valid scalar 0 < scalar < CURVE.P\');\n    }\n    // x25519 from 4\n    // The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519\n    const a24 = (CURVE.a - BigInt(2)) / BigInt(4);\n    /**\n     *\n     * @param pointU u coordinate (x) on Montgomery Curve 25519\n     * @param scalar by which the point would be multiplied\n     * @returns new Point on Montgomery curve\n     */\n    function montgomeryLadder(pointU, scalar) {\n        const u = assertFieldElement(pointU);\n        // Section 5: Implementations MUST accept non-canonical values and process them as\n        // if they had been reduced modulo the field prime.\n        const k = assertFieldElement(scalar);\n        const x_1 = u;\n        let x_2 = montgomery_1n;\n        let z_2 = montgomery_0n;\n        let x_3 = u;\n        let z_3 = montgomery_1n;\n        let swap = montgomery_0n;\n        let sw;\n        for (let t = BigInt(montgomeryBits - 1); t >= montgomery_0n; t--) {\n            const k_t = (k >> t) & montgomery_1n;\n            swap ^= k_t;\n            sw = cswap(swap, x_2, x_3);\n            x_2 = sw[0];\n            x_3 = sw[1];\n            sw = cswap(swap, z_2, z_3);\n            z_2 = sw[0];\n            z_3 = sw[1];\n            swap = k_t;\n            const A = x_2 + z_2;\n            const AA = modP(A * A);\n            const B = x_2 - z_2;\n            const BB = modP(B * B);\n            const E = AA - BB;\n            const C = x_3 + z_3;\n            const D = x_3 - z_3;\n            const DA = modP(D * A);\n            const CB = modP(C * B);\n            const dacb = DA + CB;\n            const da_cb = DA - CB;\n            x_3 = modP(dacb * dacb);\n            z_3 = modP(x_1 * modP(da_cb * da_cb));\n            x_2 = modP(AA * BB);\n            z_2 = modP(E * (AA + modP(a24 * E)));\n        }\n        // (x_2, x_3) = cswap(swap, x_2, x_3)\n        sw = cswap(swap, x_2, x_3);\n        x_2 = sw[0];\n        x_3 = sw[1];\n        // (z_2, z_3) = cswap(swap, z_2, z_3)\n        sw = cswap(swap, z_2, z_3);\n        z_2 = sw[0];\n        z_3 = sw[1];\n        // z_2^(p - 2)\n        const z2 = powPminus2(z_2);\n        // Return x_2 * (z_2^(p - 2))\n        return modP(x_2 * z2);\n    }\n    function encodeUCoordinate(u) {\n        return numberToBytesLE(modP(u), montgomeryBytes);\n    }\n    function decodeUCoordinate(uEnc) {\n        // Section 5: When receiving such an array, implementations of X25519\n        // MUST mask the most significant bit in the final byte.\n        // This is very ugly way, but it works because fieldLen-1 is outside of bounds for X448, so this becomes NOOP\n        // fieldLen - scalaryBytes = 1 for X448 and = 0 for X25519\n        const u = utils_ensureBytes(\'u coordinate\', uEnc, montgomeryBytes);\n        // u[fieldLen-1] crashes QuickJS (TypeError: out-of-bound numeric index)\n        if (fieldLen === montgomeryBytes)\n            u[fieldLen - 1] &= 127; // 0b0111_1111\n        return utils_bytesToNumberLE(u);\n    }\n    function decodeScalar(n) {\n        const bytes = utils_ensureBytes(\'scalar\', n);\n        if (bytes.length !== montgomeryBytes && bytes.length !== fieldLen)\n            throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${bytes.length}`);\n        return utils_bytesToNumberLE(adjustScalarBytes(bytes));\n    }\n    function scalarMult(scalar, u) {\n        const pointU = decodeUCoordinate(u);\n        const _scalar = decodeScalar(scalar);\n        const pu = montgomeryLadder(pointU, _scalar);\n        // The result was not contributory\n        // https://cr.yp.to/ecdh.html#validate\n        if (pu === montgomery_0n)\n            throw new Error(\'Invalid private or public key received\');\n        return encodeUCoordinate(pu);\n    }\n    // Computes public key from private. By doing scalar multiplication of base point.\n    const GuBytes = encodeUCoordinate(CURVE.Gu);\n    function scalarMultBase(scalar) {\n        return scalarMult(scalar, GuBytes);\n    }\n    return {\n        scalarMult,\n        scalarMultBase,\n        getSharedSecret: (privateKey, publicKey) => scalarMult(privateKey, publicKey),\n        getPublicKey: (privateKey) => scalarMultBase(privateKey),\n        utils: { randomPrivateKey: () => CURVE.randomBytes(CURVE.nByteLength) },\n        GuBytes: GuBytes,\n    };\n}\n//# sourceMappingURL=montgomery.js.map\n;// CONCATENATED MODULE: ./node_modules/@noble/curves/esm/abstract/hash-to-curve.js\n\n\nfunction validateDST(dst) {\n    if (dst instanceof Uint8Array)\n        return dst;\n    if (typeof dst === \'string\')\n        return utils_utf8ToBytes(dst);\n    throw new Error(\'DST must be Uint8Array or string\');\n}\n// Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE.\nconst os2ip = utils_bytesToNumberBE;\n// Integer to Octet Stream (numberToBytesBE)\nfunction i2osp(value, length) {\n    if (value < 0 || value >= 1 << (8 * length)) {\n        throw new Error(`bad I2OSP call: value=${value} length=${length}`);\n    }\n    const res = Array.from({ length }).fill(0);\n    for (let i = length - 1; i >= 0; i--) {\n        res[i] = value & 0xff;\n        value >>>= 8;\n    }\n    return new Uint8Array(res);\n}\nfunction strxor(a, b) {\n    const arr = new Uint8Array(a.length);\n    for (let i = 0; i < a.length; i++) {\n        arr[i] = a[i] ^ b[i];\n    }\n    return arr;\n}\nfunction isBytes(item) {\n    if (!(item instanceof Uint8Array))\n        throw new Error(\'Uint8Array expected\');\n}\nfunction isNum(item) {\n    if (!Number.isSafeInteger(item))\n        throw new Error(\'number expected\');\n}\n// Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits\n// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.4.1\nfunction expand_message_xmd(msg, DST, lenInBytes, H) {\n    isBytes(msg);\n    isBytes(DST);\n    isNum(lenInBytes);\n    // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3\n    if (DST.length > 255)\n        DST = H(utils_concatBytes(utils_utf8ToBytes(\'H2C-OVERSIZE-DST-\'), DST));\n    const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H;\n    const ell = Math.ceil(lenInBytes / b_in_bytes);\n    if (ell > 255)\n        throw new Error(\'Invalid xmd length\');\n    const DST_prime = utils_concatBytes(DST, i2osp(DST.length, 1));\n    const Z_pad = i2osp(0, r_in_bytes);\n    const l_i_b_str = i2osp(lenInBytes, 2); // len_in_bytes_str\n    const b = new Array(ell);\n    const b_0 = H(utils_concatBytes(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime));\n    b[0] = H(utils_concatBytes(b_0, i2osp(1, 1), DST_prime));\n    for (let i = 1; i <= ell; i++) {\n        const args = [strxor(b_0, b[i - 1]), i2osp(i + 1, 1), DST_prime];\n        b[i] = H(utils_concatBytes(...args));\n    }\n    const pseudo_random_bytes = utils_concatBytes(...b);\n    return pseudo_random_bytes.slice(0, lenInBytes);\n}\nfunction expand_message_xof(msg, DST, lenInBytes, k, H) {\n    isBytes(msg);\n    isBytes(DST);\n    isNum(lenInBytes);\n    // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3\n    // DST = H(\'H2C-OVERSIZE-DST-\' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));\n    if (DST.length > 255) {\n        const dkLen = Math.ceil((2 * k) / 8);\n        DST = H.create({ dkLen }).update(utils_utf8ToBytes(\'H2C-OVERSIZE-DST-\')).update(DST).digest();\n    }\n    if (lenInBytes > 65535 || DST.length > 255)\n        throw new Error(\'expand_message_xof: invalid lenInBytes\');\n    return (H.create({ dkLen: lenInBytes })\n        .update(msg)\n        .update(i2osp(lenInBytes, 2))\n        // 2. DST_prime = DST || I2OSP(len(DST), 1)\n        .update(DST)\n        .update(i2osp(DST.length, 1))\n        .digest());\n}\n/**\n * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F\n * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3\n * @param msg a byte string containing the message to hash\n * @param count the number of elements of F to output\n * @param options `{DST: string, p: bigint, m: number, k: number, expand: \'xmd\' | \'xof\', hash: H}`, see above\n * @returns [u_0, ..., u_(count - 1)], a list of field elements.\n */\nfunction hash_to_field(msg, count, options) {\n    validateObject(options, {\n        DST: \'string\',\n        p: \'bigint\',\n        m: \'isSafeInteger\',\n        k: \'isSafeInteger\',\n        hash: \'hash\',\n    });\n    const { p, k, m, hash, expand, DST: _DST } = options;\n    isBytes(msg);\n    isNum(count);\n    const DST = validateDST(_DST);\n    const log2p = p.toString(2).length;\n    const L = Math.ceil((log2p + k) / 8); // section 5.1 of ietf draft link above\n    const len_in_bytes = count * m * L;\n    let prb; // pseudo_random_bytes\n    if (expand === \'xmd\') {\n        prb = expand_message_xmd(msg, DST, len_in_bytes, hash);\n    }\n    else if (expand === \'xof\') {\n        prb = expand_message_xof(msg, DST, len_in_bytes, k, hash);\n    }\n    else if (expand === \'_internal_pass\') {\n        // for internal tests only\n        prb = msg;\n    }\n    else {\n        throw new Error(\'expand must be "xmd" or "xof"\');\n    }\n    const u = new Array(count);\n    for (let i = 0; i < count; i++) {\n        const e = new Array(m);\n        for (let j = 0; j < m; j++) {\n            const elm_offset = L * (j + i * m);\n            const tv = prb.subarray(elm_offset, elm_offset + L);\n            e[j] = mod(os2ip(tv), p);\n        }\n        u[i] = e;\n    }\n    return u;\n}\nfunction isogenyMap(field, map) {\n    // Make same order as in spec\n    const COEFF = map.map((i) => Array.from(i).reverse());\n    return (x, y) => {\n        const [xNum, xDen, yNum, yDen] = COEFF.map((val) => val.reduce((acc, i) => field.add(field.mul(acc, x), i)));\n        x = field.div(xNum, xDen); // xNum / xDen\n        y = field.mul(y, field.div(yNum, yDen)); // y * (yNum / yDev)\n        return { x, y };\n    };\n}\nfunction createHasher(Point, mapToCurve, def) {\n    if (typeof mapToCurve !== \'function\')\n        throw new Error(\'mapToCurve() must be defined\');\n    return {\n        // Encodes byte string to elliptic curve\n        // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3\n        hashToCurve(msg, options) {\n            const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options });\n            const u0 = Point.fromAffine(mapToCurve(u[0]));\n            const u1 = Point.fromAffine(mapToCurve(u[1]));\n            const P = u0.add(u1).clearCofactor();\n            P.assertValidity();\n            return P;\n        },\n        // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3\n        encodeToCurve(msg, options) {\n            const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options });\n            const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor();\n            P.assertValidity();\n            return P;\n        },\n    };\n}\n//# sourceMappingURL=hash-to-curve.js.map\n;// CONCATENATED MODULE: ./node_modules/@noble/curves/esm/ed448.js\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n\n\n\n\n\n\n/**\n * Edwards448 (not Ed448-Goldilocks) curve with following addons:\n * * X448 ECDH\n * Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2\n */\nconst shake256_114 = wrapConstructor(() => shake256.create({ dkLen: 114 }));\nconst shake256_64 = wrapConstructor(() => shake256.create({ dkLen: 64 }));\nconst ed448P = BigInt(\'726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439\');\n// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4.\n// Used for efficient square root calculation.\n// ((P-3)/4).toString(2) would produce bits [223x 1, 0, 222x 1]\nfunction ed448_pow_Pminus3div4(x) {\n    const P = ed448P;\n    // prettier-ignore\n    const _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _11n = BigInt(11);\n    // prettier-ignore\n    const _22n = BigInt(22), _44n = BigInt(44), _88n = BigInt(88), _223n = BigInt(223);\n    const b2 = (x * x * x) % P;\n    const b3 = (b2 * b2 * x) % P;\n    const b6 = (pow2(b3, _3n, P) * b3) % P;\n    const b9 = (pow2(b6, _3n, P) * b3) % P;\n    const b11 = (pow2(b9, _2n, P) * b2) % P;\n    const b22 = (pow2(b11, _11n, P) * b11) % P;\n    const b44 = (pow2(b22, _22n, P) * b22) % P;\n    const b88 = (pow2(b44, _44n, P) * b44) % P;\n    const b176 = (pow2(b88, _88n, P) * b88) % P;\n    const b220 = (pow2(b176, _44n, P) * b44) % P;\n    const b222 = (pow2(b220, _2n, P) * b2) % P;\n    const b223 = (pow2(b222, _1n, P) * x) % P;\n    return (pow2(b223, _223n, P) * b222) % P;\n}\nfunction adjustScalarBytes(bytes) {\n    // Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0, and the most\n    // significant bit of the last byte to 1.\n    bytes[0] &= 252; // 0b11111100\n    // and the most significant bit of the last byte to 1.\n    bytes[55] |= 128; // 0b10000000\n    // NOTE: is is NOOP for 56 bytes scalars (X25519/X448)\n    bytes[56] = 0; // Byte outside of group (456 buts vs 448 bits)\n    return bytes;\n}\nconst Fp = Field(ed448P, 456, true);\nconst ed448_4n = BigInt(4);\nconst ED448_DEF = {\n    // Param: a\n    a: BigInt(1),\n    // -39081. Negative number is P - number\n    d: BigInt(\'726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358\'),\n    // Finite field 𝔽p over which we\'ll do calculations; 2n ** 448n - 2n ** 224n - 1n\n    Fp,\n    // Subgroup order: how many points curve has;\n    // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n\n    n: BigInt(\'181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779\'),\n    nBitLength: 456,\n    // Cofactor\n    h: BigInt(4),\n    // Base point (x, y) aka generator point\n    Gx: BigInt(\'224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710\'),\n    Gy: BigInt(\'298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660\'),\n    // SHAKE256(dom4(phflag,context)||x, 114)\n    hash: shake256_114,\n    randomBytes: randomBytes,\n    adjustScalarBytes,\n    // dom4\n    domain: (data, ctx, phflag) => {\n        if (ctx.length > 255)\n            throw new Error(`Context is too big: ${ctx.length}`);\n        return concatBytes(utf8ToBytes(\'SigEd448\'), new Uint8Array([phflag ? 1 : 0, ctx.length]), ctx, data);\n    },\n    // Constant-time ratio of u to v. Allows to combine inversion and square root u/√v.\n    // Uses algo from RFC8032 5.1.3.\n    uvRatio: (u, v) => {\n        const P = ed448P;\n        // https://datatracker.ietf.org/doc/html/rfc8032#section-5.2.3\n        // To compute the square root of (u/v), the first step is to compute the\n        //   candidate root x = (u/v)^((p+1)/4).  This can be done using the\n        // following trick, to use a single modular powering for both the\n        // inversion of v and the square root:\n        // x = (u/v)^((p+1)/4)   = u³v(u⁵v³)^((p-3)/4)   (mod p)\n        const u2v = mod(u * u * v, P); // u²v\n        const u3v = mod(u2v * u, P); // u³v\n        const u5v3 = mod(u3v * u2v * v, P); // u⁵v³\n        const root = ed448_pow_Pminus3div4(u5v3);\n        const x = mod(u3v * root, P);\n        // Verify that root is exists\n        const x2 = mod(x * x, P); // x²\n        // If vx² = u, the recovered x-coordinate is x.  Otherwise, no\n        // square root exists, and the decoding fails.\n        return { isValid: mod(x2 * v, P) === u, value: x };\n    },\n};\nconst ed448 = twistedEdwards(ED448_DEF);\n// NOTE: there is no ed448ctx, since ed448 supports ctx by default\nconst ed448ph = twistedEdwards({ ...ED448_DEF, prehash: shake256_64 });\nconst x448 = montgomery({\n    a: BigInt(156326),\n    montgomeryBits: 448,\n    nByteLength: 57,\n    P: ed448P,\n    Gu: BigInt(5),\n    powPminus2: (x) => {\n        const P = ed448P;\n        const Pminus3div4 = ed448_pow_Pminus3div4(x);\n        const Pminus3 = pow2(Pminus3div4, BigInt(2), P);\n        return mod(Pminus3 * x, P); // Pminus3 * x = Pminus2\n    },\n    adjustScalarBytes,\n    randomBytes: randomBytes,\n});\n/**\n * Converts edwards448 public key to x448 public key. Uses formula:\n * * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)`\n * * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))`\n * @example\n *   const aPub = ed448.getPublicKey(utils.randomPrivateKey());\n *   x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub))\n */\nfunction edwardsToMontgomery(edwardsPub) {\n    const { y } = ed448.ExtendedPoint.fromHex(edwardsPub);\n    const _1n = BigInt(1);\n    return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n)));\n}\n// Hash To Curve Elligator2 Map\nconst ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4         # Integer arithmetic\nconst ELL2_J = BigInt(156326);\nfunction map_to_curve_elligator2_curve448(u) {\n    let tv1 = Fp.sqr(u); // 1.  tv1 = u^2\n    let e1 = Fp.eql(tv1, Fp.ONE); // 2.   e1 = tv1 == 1\n    tv1 = Fp.cmov(tv1, Fp.ZERO, e1); // 3.  tv1 = CMOV(tv1, 0, e1)  # If Z * u^2 == -1, set tv1 = 0\n    let xd = Fp.sub(Fp.ONE, tv1); // 4.   xd = 1 - tv1\n    let x1n = Fp.neg(ELL2_J); // 5.  x1n = -J\n    let tv2 = Fp.sqr(xd); // 6.  tv2 = xd^2\n    let gxd = Fp.mul(tv2, xd); // 7.  gxd = tv2 * xd          # gxd = xd^3\n    let gx1 = Fp.mul(tv1, Fp.neg(ELL2_J)); // 8.  gx1 = -J * tv1          # x1n + J * xd\n    gx1 = Fp.mul(gx1, x1n); // 9.  gx1 = gx1 * x1n         # x1n^2 + J * x1n * xd\n    gx1 = Fp.add(gx1, tv2); // 10. gx1 = gx1 + tv2         # x1n^2 + J * x1n * xd + xd^2\n    gx1 = Fp.mul(gx1, x1n); // 11. gx1 = gx1 * x1n         # x1n^3 + J * x1n^2 * xd + x1n * xd^2\n    let tv3 = Fp.sqr(gxd); // 12. tv3 = gxd^2\n    tv2 = Fp.mul(gx1, gxd); // 13. tv2 = gx1 * gxd         # gx1 * gxd\n    tv3 = Fp.mul(tv3, tv2); // 14. tv3 = tv3 * tv2         # gx1 * gxd^3\n    let y1 = Fp.pow(tv3, ELL2_C1); // 15.  y1 = tv3^c1            # (gx1 * gxd^3)^((p - 3) / 4)\n    y1 = Fp.mul(y1, tv2); // 16.  y1 = y1 * tv2          # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4)\n    let x2n = Fp.mul(x1n, Fp.neg(tv1)); // 17. x2n = -tv1 * x1n        # x2 = x2n / xd = -1 * u^2 * x1n / xd\n    let y2 = Fp.mul(y1, u); // 18.  y2 = y1 * u\n    y2 = Fp.cmov(y2, Fp.ZERO, e1); // 19.  y2 = CMOV(y2, 0, e1)\n    tv2 = Fp.sqr(y1); // 20. tv2 = y1^2\n    tv2 = Fp.mul(tv2, gxd); // 21. tv2 = tv2 * gxd\n    let e2 = Fp.eql(tv2, gx1); // 22.  e2 = tv2 == gx1\n    let xn = Fp.cmov(x2n, x1n, e2); // 23.  xn = CMOV(x2n, x1n, e2)  # If e2, x = x1, else x = x2\n    let y = Fp.cmov(y2, y1, e2); // 24.   y = CMOV(y2, y1, e2)    # If e2, y = y1, else y = y2\n    let e3 = Fp.isOdd(y); // 25.  e3 = sgn0(y) == 1        # Fix sign of y\n    y = Fp.cmov(y, Fp.neg(y), e2 !== e3); // 26.   y = CMOV(y, -y, e2 XOR e3)\n    return { xn, xd, yn: y, yd: Fp.ONE }; // 27. return (xn, xd, y, 1)\n}\nfunction map_to_curve_elligator2_edwards448(u) {\n    let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u); // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)\n    let xn2 = Fp.sqr(xn); // 2.  xn2 = xn^2\n    let xd2 = Fp.sqr(xd); // 3.  xd2 = xd^2\n    let xd4 = Fp.sqr(xd2); // 4.  xd4 = xd2^2\n    let yn2 = Fp.sqr(yn); // 5.  yn2 = yn^2\n    let yd2 = Fp.sqr(yd); // 6.  yd2 = yd^2\n    let xEn = Fp.sub(xn2, xd2); // 7.  xEn = xn2 - xd2\n    let tv2 = Fp.sub(xEn, xd2); // 8.  tv2 = xEn - xd2\n    xEn = Fp.mul(xEn, xd2); // 9.  xEn = xEn * xd2\n    xEn = Fp.mul(xEn, yd); // 10. xEn = xEn * yd\n    xEn = Fp.mul(xEn, yn); // 11. xEn = xEn * yn\n    xEn = Fp.mul(xEn, ed448_4n); // 12. xEn = xEn * 4\n    tv2 = Fp.mul(tv2, xn2); // 13. tv2 = tv2 * xn2\n    tv2 = Fp.mul(tv2, yd2); // 14. tv2 = tv2 * yd2\n    let tv3 = Fp.mul(yn2, ed448_4n); // 15. tv3 = 4 * yn2\n    let tv1 = Fp.add(tv3, yd2); // 16. tv1 = tv3 + yd2\n    tv1 = Fp.mul(tv1, xd4); // 17. tv1 = tv1 * xd4\n    let xEd = Fp.add(tv1, tv2); // 18. xEd = tv1 + tv2\n    tv2 = Fp.mul(tv2, xn); // 19. tv2 = tv2 * xn\n    let tv4 = Fp.mul(xn, xd4); // 20. tv4 = xn * xd4\n    let yEn = Fp.sub(tv3, yd2); // 21. yEn = tv3 - yd2\n    yEn = Fp.mul(yEn, tv4); // 22. yEn = yEn * tv4\n    yEn = Fp.sub(yEn, tv2); // 23. yEn = yEn - tv2\n    tv1 = Fp.add(xn2, xd2); // 24. tv1 = xn2 + xd2\n    tv1 = Fp.mul(tv1, xd2); // 25. tv1 = tv1 * xd2\n    tv1 = Fp.mul(tv1, xd); // 26. tv1 = tv1 * xd\n    tv1 = Fp.mul(tv1, yn2); // 27. tv1 = tv1 * yn2\n    tv1 = Fp.mul(tv1, BigInt(-2)); // 28. tv1 = -2 * tv1\n    let yEd = Fp.add(tv2, tv1); // 29. yEd = tv2 + tv1\n    tv4 = Fp.mul(tv4, yd2); // 30. tv4 = tv4 * yd2\n    yEd = Fp.add(yEd, tv4); // 31. yEd = yEd + tv4\n    tv1 = Fp.mul(xEd, yEd); // 32. tv1 = xEd * yEd\n    let e = Fp.eql(tv1, Fp.ZERO); // 33.   e = tv1 == 0\n    xEn = Fp.cmov(xEn, Fp.ZERO, e); // 34. xEn = CMOV(xEn, 0, e)\n    xEd = Fp.cmov(xEd, Fp.ONE, e); // 35. xEd = CMOV(xEd, 1, e)\n    yEn = Fp.cmov(yEn, Fp.ONE, e); // 36. yEn = CMOV(yEn, 1, e)\n    yEd = Fp.cmov(yEd, Fp.ONE, e); // 37. yEd = CMOV(yEd, 1, e)\n    const inv = Fp.invertBatch([xEd, yEd]); // batch division\n    return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) }; // 38. return (xEn, xEd, yEn, yEd)\n}\nconst { hashToCurve, encodeToCurve } = createHasher(ed448.ExtendedPoint, (scalars) => map_to_curve_elligator2_edwards448(scalars[0]), {\n    DST: \'edwards448_XOF:SHAKE256_ELL2_RO_\',\n    encodeDST: \'edwards448_XOF:SHAKE256_ELL2_NU_\',\n    p: Fp.ORDER,\n    m: 1,\n    k: 224,\n    expand: \'xof\',\n    hash: shake256,\n});\n\n//# sourceMappingURL=ed448.js.map\n// EXTERNAL MODULE: ./node_modules/buffer/index.js\nvar buffer = __webpack_require__(764);\n;// CONCATENATED MODULE: ./src/js/main.js\nfunction _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }\nfunction _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i["return"] && (_r = _i["return"](), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\nfunction _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return exports; }; var exports = {}, Op = Object.prototype, hasOwn = Op.hasOwnProperty, defineProperty = Object.defineProperty || function (obj, key, desc) { obj[key] = desc.value; }, $Symbol = "function" == typeof Symbol ? Symbol : {}, iteratorSymbol = $Symbol.iterator || "@@iterator", asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator", toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag"; function define(obj, key, value) { return Object.defineProperty(obj, key, { value: value, enumerable: !0, configurable: !0, writable: !0 }), obj[key]; } try { define({}, ""); } catch (err) { define = function define(obj, key, value) { return obj[key] = value; }; } function wrap(innerFn, outerFn, self, tryLocsList) { var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator, generator = Object.create(protoGenerator.prototype), context = new Context(tryLocsList || []); return defineProperty(generator, "_invoke", { value: makeInvokeMethod(innerFn, self, context) }), generator; } function tryCatch(fn, obj, arg) { try { return { type: "normal", arg: fn.call(obj, arg) }; } catch (err) { return { type: "throw", arg: err }; } } exports.wrap = wrap; var ContinueSentinel = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var IteratorPrototype = {}; define(IteratorPrototype, iteratorSymbol, function () { return this; }); var getProto = Object.getPrototypeOf, NativeIteratorPrototype = getProto && getProto(getProto(values([]))); NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype); var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype); function defineIteratorMethods(prototype) { ["next", "throw", "return"].forEach(function (method) { define(prototype, method, function (arg) { return this._invoke(method, arg); }); }); } function AsyncIterator(generator, PromiseImpl) { function invoke(method, arg, resolve, reject) { var record = tryCatch(generator[method], generator, arg); if ("throw" !== record.type) { var result = record.arg, value = result.value; return value && "object" == _typeof(value) && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) { invoke("next", value, resolve, reject); }, function (err) { invoke("throw", err, resolve, reject); }) : PromiseImpl.resolve(value).then(function (unwrapped) { result.value = unwrapped, resolve(result); }, function (error) { return invoke("throw", error, resolve, reject); }); } reject(record.arg); } var previousPromise; defineProperty(this, "_invoke", { value: function value(method, arg) { function callInvokeWithMethodAndArg() { return new PromiseImpl(function (resolve, reject) { invoke(method, arg, resolve, reject); }); } return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(innerFn, self, context) { var state = "suspendedStart"; return function (method, arg) { if ("executing" === state) throw new Error("Generator is already running"); if ("completed" === state) { if ("throw" === method) throw arg; return doneResult(); } for (context.method = method, context.arg = arg;;) { var delegate = context.delegate; if (delegate) { var delegateResult = maybeInvokeDelegate(delegate, context); if (delegateResult) { if (delegateResult === ContinueSentinel) continue; return delegateResult; } } if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) { if ("suspendedStart" === state) throw state = "completed", context.arg; context.dispatchException(context.arg); } else "return" === context.method && context.abrupt("return", context.arg); state = "executing"; var record = tryCatch(innerFn, self, context); if ("normal" === record.type) { if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue; return { value: record.arg, done: context.done }; } "throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg); } }; } function maybeInvokeDelegate(delegate, context) { var methodName = context.method, method = delegate.iterator[methodName]; if (undefined === method) return context.delegate = null, "throw" === methodName && delegate.iterator["return"] && (context.method = "return", context.arg = undefined, maybeInvokeDelegate(delegate, context), "throw" === context.method) || "return" !== methodName && (context.method = "throw", context.arg = new TypeError("The iterator does not provide a \'" + methodName + "\' method")), ContinueSentinel; var record = tryCatch(method, delegate.iterator, context.arg); if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel; var info = record.arg; return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, "return" !== context.method && (context.method = "next", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = "throw", context.arg = new TypeError("iterator result is not an object"), context.delegate = null, ContinueSentinel); } function pushTryEntry(locs) { var entry = { tryLoc: locs[0] }; 1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry); } function resetTryEntry(entry) { var record = entry.completion || {}; record.type = "normal", delete record.arg, entry.completion = record; } function Context(tryLocsList) { this.tryEntries = [{ tryLoc: "root" }], tryLocsList.forEach(pushTryEntry, this), this.reset(!0); } function values(iterable) { if (iterable) { var iteratorMethod = iterable[iteratorSymbol]; if (iteratorMethod) return iteratorMethod.call(iterable); if ("function" == typeof iterable.next) return iterable; if (!isNaN(iterable.length)) { var i = -1, next = function next() { for (; ++i < iterable.length;) if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next; return next.value = undefined, next.done = !0, next; }; return next.next = next; } } return { next: doneResult }; } function doneResult() { return { value: undefined, done: !0 }; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, defineProperty(Gp, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), defineProperty(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) { var ctor = "function" == typeof genFun && genFun.constructor; return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name)); }, exports.mark = function (genFun) { return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = Object.create(Gp), genFun; }, exports.awrap = function (arg) { return { __await: arg }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () { return this; }), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) { void 0 === PromiseImpl && (PromiseImpl = Promise); var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl); return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) { return result.done ? result.value : iter.next(); }); }, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () { return this; }), define(Gp, "toString", function () { return "[object Generator]"; }), exports.keys = function (val) { var object = Object(val), keys = []; for (var key in object) keys.push(key); return keys.reverse(), function next() { for (; keys.length;) { var key = keys.pop(); if (key in object) return next.value = key, next.done = !1, next; } return next.done = !0, next; }; }, exports.values = values, Context.prototype = { constructor: Context, reset: function reset(skipTempReset) { if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = "next", this.arg = undefined, this.tryEntries.forEach(resetTryEntry), !skipTempReset) for (var name in this) "t" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+name.slice(1)) && (this[name] = undefined); }, stop: function stop() { this.done = !0; var rootRecord = this.tryEntries[0].completion; if ("throw" === rootRecord.type) throw rootRecord.arg; return this.rval; }, dispatchException: function dispatchException(exception) { if (this.done) throw exception; var context = this; function handle(loc, caught) { return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught; } for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i], record = entry.completion; if ("root" === entry.tryLoc) return handle("end"); if (entry.tryLoc <= this.prev) { var hasCatch = hasOwn.call(entry, "catchLoc"), hasFinally = hasOwn.call(entry, "finallyLoc"); if (hasCatch && hasFinally) { if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0); if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc); } else if (hasCatch) { if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0); } else { if (!hasFinally) throw new Error("try statement without catch or finally"); if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc); } } } }, abrupt: function abrupt(type, arg) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) { var finallyEntry = entry; break; } } finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null); var record = finallyEntry ? finallyEntry.completion : {}; return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record); }, complete: function complete(record, afterLoc) { if ("throw" === record.type) throw record.arg; return "break" === record.type || "continue" === record.type ? this.next = record.arg : "return" === record.type ? (this.rval = this.arg = record.arg, this.method = "return", this.next = "end") : "normal" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel; }, finish: function finish(finallyLoc) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel; } }, "catch": function _catch(tryLoc) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.tryLoc === tryLoc) { var record = entry.completion; if ("throw" === record.type) { var thrown = record.arg; resetTryEntry(entry); } return thrown; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(iterable, resultName, nextLoc) { return this.delegate = { iterator: values(iterable), resultName: resultName, nextLoc: nextLoc }, "next" === this.method && (this.arg = undefined), ContinueSentinel; } }, exports; }\nfunction asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }\nfunction _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }\n\n\n\nvar currentlyAddingItemByTag = new Map();\nvar received_items = {};\nvar config;\nvar scanner = new Html5QrcodeScanner("reader", {\n  fps: 10,\n  qrbox: {\n    width: 250,\n    height: 250\n  },\n  showTorchButtonIfSupported: true,\n  formatsToSupport: [Html5QrcodeSupportedFormats.QR_CODE],\n  //there are many other types of codes on the labels we do not want\n  rememberLastUsedCamera: true\n});\nvar scanner_audio = new Audio("/beep.wav");\nscanner_audio.load();\nvar toastDiv = document.getElementById("bottomToast");\n\n/*\n * Helper functions\n */\nfunction htoa(h) {\n  return Uint8Array.from(buffer/* Buffer.from */.lW.from(h, "hex"));\n}\nfunction toast(title, message) {\n  toastDiv.children[0].children[0].innerHTML = title;\n  toastDiv.children[1].innerHTML = message;\n  toastDiv.classList.remove("hide");\n  toastDiv.classList.add("show");\n  toastDiv.classList.add("showing");\n  setTimeout(function () {\n    toastDiv.classList.remove("show");\n    toastDiv.classList.remove("showing");\n    toastDiv.classList.add("hide");\n  }, 3000);\n}\nfunction fetchWithAuth(_x, _x2) {\n  return _fetchWithAuth.apply(this, arguments);\n}\nfunction _fetchWithAuth() {\n  _fetchWithAuth = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(input, init) {\n    var response;\n    return _regeneratorRuntime().wrap(function _callee$(_context) {\n      while (1) switch (_context.prev = _context.next) {\n        case 0:\n          if (init == undefined || init == null) {\n            init = {};\n          }\n          if (init["headers"] == null) {\n            init["headers"] = {};\n          }\n          if (window.sessionStorage.getItem("access_token")) {\n            _context.next = 5;\n            break;\n          }\n          _context.next = 5;\n          return login();\n        case 5:\n          init["headers"]["Authorization"] = "Bearer " + window.sessionStorage.getItem("access_token");\n          _context.next = 8;\n          return fetch(input, init);\n        case 8:\n          response = _context.sent;\n        case 9:\n          if (!(response.status == 401)) {\n            _context.next = 19;\n            break;\n          }\n          console.log("Fetch with auth failed for", input);\n          _context.next = 13;\n          return login();\n        case 13:\n          init["headers"]["Authorization"] = "Bearer " + window.sessionStorage.getItem("access_token");\n          _context.next = 16;\n          return fetch(input, init);\n        case 16:\n          response = _context.sent;\n          _context.next = 9;\n          break;\n        case 19:\n          return _context.abrupt("return", response);\n        case 20:\n        case "end":\n          return _context.stop();\n      }\n    }, _callee);\n  }));\n  return _fetchWithAuth.apply(this, arguments);\n}\nfunction checkResponseForError(_x3, _x4) {\n  return _checkResponseForError.apply(this, arguments);\n}\nfunction _checkResponseForError() {\n  _checkResponseForError = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(response, message) {\n    var content;\n    return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n      while (1) switch (_context2.prev = _context2.next) {\n        case 0:\n          if (!(response.status !== 200)) {\n            _context2.next = 7;\n            break;\n          }\n          _context2.next = 3;\n          return response.text();\n        case 3:\n          content = _context2.sent;\n          console.log("Got Response Error:", message, response);\n          alert(message + "; Status: " + response.status + "; Content: " + content);\n          return _context2.abrupt("return", false);\n        case 7:\n          return _context2.abrupt("return", true);\n        case 8:\n        case "end":\n          return _context2.stop();\n      }\n    }, _callee2);\n  }));\n  return _checkResponseForError.apply(this, arguments);\n}\nfunction getConfig() {\n  return _getConfig.apply(this, arguments);\n}\nfunction _getConfig() {\n  _getConfig = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {\n    var config_request;\n    return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n      while (1) switch (_context3.prev = _context3.next) {\n        case 0:\n          if (!(config == undefined)) {\n            _context3.next = 12;\n            break;\n          }\n          _context3.next = 3;\n          return fetch("config.json");\n        case 3:\n          config_request = _context3.sent;\n          console.log("Loading config");\n          _context3.next = 7;\n          return checkResponseForError(config_request, "Could not load config");\n        case 7:\n          if (!_context3.sent) {\n            _context3.next = 12;\n            break;\n          }\n          _context3.next = 10;\n          return config_request.json();\n        case 10:\n          config = _context3.sent;\n          console.log("Loaded config");\n        case 12:\n        case "end":\n          return _context3.stop();\n      }\n    }, _callee3);\n  }));\n  return _getConfig.apply(this, arguments);\n}\nfunction login(_x5) {\n  return _login.apply(this, arguments);\n}\nfunction _login() {\n  _login = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(passwordToTry) {\n    var loginSuccess, password, form, response, result;\n    return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n      while (1) switch (_context4.prev = _context4.next) {\n        case 0:\n          console.log("Performing login");\n          loginSuccess = false;\n        case 2:\n          if (passwordToTry !== undefined) {\n            console.log("Using password to try from parameter");\n            password = passwordToTry;\n            passwordToTry = undefined;\n          } else {\n            console.log("Prompting user for shared secret.");\n            password = prompt("provide the shared secret");\n          }\n          form = new FormData();\n          form.append("grant_type", "password");\n          form.append("username", "worker");\n          form.append("password", password);\n          console.log("Requesting token.");\n          _context4.next = 10;\n          return fetch(config.backend_url + "/token", {\n            method: "POST",\n            body: form\n          });\n        case 10:\n          response = _context4.sent;\n          _context4.next = 13;\n          return checkResponseForError(response, "Login failed");\n        case 13:\n          if (!_context4.sent) {\n            _context4.next = 20;\n            break;\n          }\n          _context4.next = 16;\n          return response.json();\n        case 16:\n          result = _context4.sent;\n          console.log("Got token");\n          window.sessionStorage.setItem("access_token", result.access_token);\n          loginSuccess = true;\n        case 20:\n          if (!loginSuccess) {\n            _context4.next = 2;\n            break;\n          }\n        case 21:\n        case "end":\n          return _context4.stop();\n      }\n    }, _callee4);\n  }));\n  return _login.apply(this, arguments);\n}\nfunction updateItemsView() {\n  console.log("Updating items view");\n  var items = document.querySelector("#items");\n  items.innerHTML = "";\n  for (var item in received_items) {\n    var li = document.createElement("li");\n    console.log(item);\n    console.log(received_items[item]);\n    li.innerHTML = "<div id=\\"item_" + received_items[item].item.uuid + "\\" class=\\"alert alert-success\\" role=\\"alert\\">" + received_items[item].item.tag + " (" + received_items[item].item.addressee + ", " + received_items[item].item.team + ")" + "&emsp;<span class=\\"badge badge-light\\">" + received_items[item].num + "</span>" + "&emsp;<button class=\\"btn btn-primary\\" onclick=\\"lib.increaseItemCount(\'" + received_items[item].item.uuid + "\')\\">+</button>" + "&emsp;<button class=\\"btn btn-primary\\" onclick=\\"lib.decreaseItemCount(\'" + received_items[item].item.uuid + "\')\\">-</button></div>";\n    items.appendChild(li);\n  }\n}\n\n/*\n * various add Items functions\n */\n\nfunction onTagTextUpdate(_x6) {\n  return _onTagTextUpdate.apply(this, arguments);\n}\nfunction _onTagTextUpdate() {\n  _onTagTextUpdate = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(element) {\n    return _regeneratorRuntime().wrap(function _callee5$(_context5) {\n      while (1) switch (_context5.prev = _context5.next) {\n        case 0:\n          if (!(element.value.length == 0)) {\n            _context5.next = 5;\n            break;\n          }\n          element.setCustomValidity("");\n          element.classList.remove("is-invalid");\n          _context5.next = 12;\n          break;\n        case 5:\n          if (!(element.value.length != 6)) {\n            _context5.next = 11;\n            break;\n          }\n          element.setCustomValidity("Code must be 6 chars long.");\n          element.classList.add("is-invalid");\n          return _context5.abrupt("return");\n        case 11:\n          tagEntered(element);\n        case 12:\n        case "end":\n          return _context5.stop();\n      }\n    }, _callee5);\n  }));\n  return _onTagTextUpdate.apply(this, arguments);\n}\nfunction onTagInputChanged(_x7) {\n  return _onTagInputChanged.apply(this, arguments);\n}\nfunction _onTagInputChanged() {\n  _onTagInputChanged = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(element) {\n    return _regeneratorRuntime().wrap(function _callee6$(_context6) {\n      while (1) switch (_context6.prev = _context6.next) {\n        case 0:\n          // Element lost focus or user pressed enter\n          if (element.value.length == 6) {\n            tagEntered(element);\n          } else {\n            element.reportValidity();\n          }\n        case 1:\n        case "end":\n          return _context6.stop();\n      }\n    }, _callee6);\n  }));\n  return _onTagInputChanged.apply(this, arguments);\n}\nfunction tagEntered(_x8) {\n  return _tagEntered.apply(this, arguments);\n}\nfunction _tagEntered() {\n  _tagEntered = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(element) {\n    var tag, succ;\n    return _regeneratorRuntime().wrap(function _callee7$(_context7) {\n      while (1) switch (_context7.prev = _context7.next) {\n        case 0:\n          tag = element.value;\n          console.log("Tag Entered", tag);\n          if (!currentlyAddingItemByTag.has(tag)) {\n            _context7.next = 4;\n            break;\n          }\n          return _context7.abrupt("return");\n        case 4:\n          currentlyAddingItemByTag.set(tag, "");\n          _context7.next = 7;\n          return addItemByTag(element.value);\n        case 7:\n          succ = _context7.sent;\n          if (succ) {\n            element.classList.remove("is-invalid");\n            element.value = "";\n            element.setCustomValidity("");\n          } else {\n            element.setCustomValidity("Unknown item");\n            element.classList.add("is-invalid");\n          }\n          element.reportValidity();\n          currentlyAddingItemByTag["delete"](tag);\n        case 11:\n        case "end":\n          return _context7.stop();\n      }\n    }, _callee7);\n  }));\n  return _tagEntered.apply(this, arguments);\n}\nfunction addItemByTag(_x9) {\n  return _addItemByTag.apply(this, arguments);\n}\nfunction _addItemByTag() {\n  _addItemByTag = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(tag) {\n    var response, tracking_item;\n    return _regeneratorRuntime().wrap(function _callee8$(_context8) {\n      while (1) switch (_context8.prev = _context8.next) {\n        case 0:\n          if (!(tag.length != 6)) {\n            _context8.next = 2;\n            break;\n          }\n          throw "Internal Error: Tag not length 6.";\n        case 2:\n          tag = tag.toLowerCase();\n          console.log("Trying to add item by tag:", tag);\n          _context8.next = 6;\n          return fetchWithAuth(config.backend_url + "/tag/" + tag);\n        case 6:\n          response = _context8.sent;\n          if (!(response.status == 200)) {\n            _context8.next = 18;\n            break;\n          }\n          _context8.next = 10;\n          return response.json();\n        case 10:\n          tracking_item = _context8.sent;\n          if (tracking_item.uuid in received_items) {\n            received_items[tracking_item.uuid].num += 1;\n          } else {\n            received_items[tracking_item.uuid] = {\n              "num": 1,\n              "item": tracking_item\n            };\n          }\n          updateItemsView();\n          scanner_audio.play();\n          console.log("Added item by tag");\n          return _context8.abrupt("return", true);\n        case 18:\n          if (!(response.status == 404)) {\n            _context8.next = 23;\n            break;\n          }\n          console.log("Item not found");\n          return _context8.abrupt("return", false);\n        case 23:\n          checkResponseForError(response, "Failed to get item from backend");\n          return _context8.abrupt("return", false);\n        case 25:\n        case "end":\n          return _context8.stop();\n      }\n    }, _callee8);\n  }));\n  return _addItemByTag.apply(this, arguments);\n}\nfunction handleQrError(_x10, _x11) {\n  return _handleQrError.apply(this, arguments);\n}\nfunction _handleQrError() {\n  _handleQrError = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee9(msg, err) {\n    return _regeneratorRuntime().wrap(function _callee9$(_context9) {\n      while (1) switch (_context9.prev = _context9.next) {\n        case 0:\n          return _context9.abrupt("return");\n        case 1:\n        case "end":\n          return _context9.stop();\n      }\n    }, _callee9);\n  }));\n  return _handleQrError.apply(this, arguments);\n}\nfunction debounceScanner() {\n  if (scanner.getState() != Html5QrcodeScannerState.SCANNING) {\n    return;\n  }\n  scanner.pause(false);\n  setTimeout(function () {\n    if (scanner.getState() == Html5QrcodeScannerState.PAUSED) {\n      scanner.resume();\n    }\n  }, 1000);\n}\nfunction handleItemScanResult(_x12) {\n  return _handleItemScanResult.apply(this, arguments);\n}\nfunction _handleItemScanResult() {\n  _handleItemScanResult = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee10(item_uuid) {\n    var response, tracking_item;\n    return _regeneratorRuntime().wrap(function _callee10$(_context10) {\n      while (1) switch (_context10.prev = _context10.next) {\n        case 0:\n          debounceScanner();\n          if (!(item_uuid.length == 36)) {\n            _context10.next = 27;\n            break;\n          }\n          console.log("Trying to add item by uuid (scanned)");\n          if (!(item_uuid in received_items)) {\n            _context10.next = 10;\n            break;\n          }\n          received_items[item_uuid].num += 1;\n          console.log("Increased count of existing item uuid");\n          updateItemsView();\n          scanner_audio.play();\n          _context10.next = 25;\n          break;\n        case 10:\n          received_items[item_uuid] = {\n            "num": 1,\n            "item": null\n          };\n          _context10.next = 13;\n          return fetchWithAuth(config.backend_url + "/item/" + item_uuid);\n        case 13:\n          response = _context10.sent;\n          if (!(response.status == 200)) {\n            _context10.next = 24;\n            break;\n          }\n          _context10.next = 17;\n          return response.json();\n        case 17:\n          tracking_item = _context10.sent;\n          received_items[item_uuid] = {\n            "num": 1,\n            "item": tracking_item\n          };\n          updateItemsView();\n          scanner_audio.play();\n          console.log("Added item by uuid.");\n          _context10.next = 25;\n          break;\n        case 24:\n          if (response.status == 404) {\n            alert("Item not found");\n            console.log("Item not found");\n          } else {\n            checkResponseForError(response, "Failed to get item from backend");\n          }\n        case 25:\n          _context10.next = 28;\n          break;\n        case 27:\n          alert("QR Code is not a bgp checkin code.");\n        case 28:\n        case "end":\n          return _context10.stop();\n      }\n    }, _callee10);\n  }));\n  return _handleItemScanResult.apply(this, arguments);\n}\nfunction addItemScan() {\n  return _addItemScan.apply(this, arguments);\n}\nfunction _addItemScan() {\n  _addItemScan = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee11() {\n    return _regeneratorRuntime().wrap(function _callee11$(_context11) {\n      while (1) switch (_context11.prev = _context11.next) {\n        case 0:\n          console.log("Starting scanner");\n          scanner.render(handleItemScanResult, handleQrError);\n          document.getElementById("startScan").style.display = "none";\n          document.getElementById("stopScan").style.display = "inline-block";\n        case 4:\n        case "end":\n          return _context11.stop();\n      }\n    }, _callee11);\n  }));\n  return _addItemScan.apply(this, arguments);\n}\nfunction stopScanningItem() {\n  return _stopScanningItem.apply(this, arguments);\n}\nfunction _stopScanningItem() {\n  _stopScanningItem = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee12() {\n    return _regeneratorRuntime().wrap(function _callee12$(_context12) {\n      while (1) switch (_context12.prev = _context12.next) {\n        case 0:\n          console.log("Stopping scanner");\n          scanner.clear();\n          document.getElementById("startScan").style.display = "inline-block";\n          document.getElementById("stopScan").style.display = "none";\n        case 4:\n        case "end":\n          return _context12.stop();\n      }\n    }, _callee12);\n  }));\n  return _stopScanningItem.apply(this, arguments);\n}\nfunction addItemImage(_x13) {\n  return _addItemImage.apply(this, arguments);\n}\nfunction _addItemImage() {\n  _addItemImage = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee13(e) {\n    var form, response, tracking_item;\n    return _regeneratorRuntime().wrap(function _callee13$(_context13) {\n      while (1) switch (_context13.prev = _context13.next) {\n        case 0:\n          console.log("Adding item  by image");\n          form = new FormData();\n          form.append("image", e.files[0]);\n          _context13.next = 5;\n          return fetchWithAuth(config.backend_url + "/item/register", {\n            method: "POST",\n            body: form\n          });\n        case 5:\n          response = _context13.sent;\n          _context13.next = 8;\n          return checkResponseForError(response, "Failed to save item");\n        case 8:\n          if (!_context13.sent) {\n            _context13.next = 16;\n            break;\n          }\n          _context13.next = 11;\n          return response.json();\n        case 11:\n          tracking_item = _context13.sent;\n          received_items[tracking_item.uuid] = {\n            "num": 1,\n            "item": tracking_item\n          };\n          updateItemsView();\n          scanner_audio.play();\n          console.log("Added item by image.");\n        case 16:\n        case "end":\n          return _context13.stop();\n      }\n    }, _callee13);\n  }));\n  return _addItemImage.apply(this, arguments);\n}\nfunction decreaseItemCount(_x14) {\n  return _decreaseItemCount.apply(this, arguments);\n}\nfunction _decreaseItemCount() {\n  _decreaseItemCount = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee14(uuid) {\n    return _regeneratorRuntime().wrap(function _callee14$(_context14) {\n      while (1) switch (_context14.prev = _context14.next) {\n        case 0:\n          if (!(received_items[uuid] == null)) {\n            _context14.next = 3;\n            break;\n          }\n          console.log("Trying to decrease item count of unknown item", uuid);\n          return _context14.abrupt("return");\n        case 3:\n          console.log("Decreasing item count of", uuid);\n          received_items[uuid]["num"]--;\n          if (received_items[uuid]["num"] <= 0) {\n            delete received_items[uuid];\n          }\n          updateItemsView();\n        case 7:\n        case "end":\n          return _context14.stop();\n      }\n    }, _callee14);\n  }));\n  return _decreaseItemCount.apply(this, arguments);\n}\nfunction increaseItemCount(_x15) {\n  return _increaseItemCount.apply(this, arguments);\n}\n\n/*\n * Checkin the selected items\n */\nfunction _increaseItemCount() {\n  _increaseItemCount = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee15(uuid) {\n    return _regeneratorRuntime().wrap(function _callee15$(_context15) {\n      while (1) switch (_context15.prev = _context15.next) {\n        case 0:\n          if (!(received_items[uuid] == null)) {\n            _context15.next = 3;\n            break;\n          }\n          console.log("Trying to increase item count of unknown item", uuid);\n          return _context15.abrupt("return");\n        case 3:\n          console.log("Increasing item count of", uuid);\n          received_items[uuid]["num"]++;\n          updateItemsView();\n        case 6:\n        case "end":\n          return _context15.stop();\n      }\n    }, _callee15);\n  }));\n  return _increaseItemCount.apply(this, arguments);\n}\nfunction checkinItems() {\n  return _checkinItems.apply(this, arguments);\n}\nfunction _checkinItems() {\n  _checkinItems = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee16() {\n    var successfullCount, item, response, tracking_item;\n    return _regeneratorRuntime().wrap(function _callee16$(_context16) {\n      while (1) switch (_context16.prev = _context16.next) {\n        case 0:\n          console.log("Checking in items");\n          successfullCount = 0;\n          _context16.t0 = _regeneratorRuntime().keys(received_items);\n        case 3:\n          if ((_context16.t1 = _context16.t0()).done) {\n            _context16.next = 18;\n            break;\n          }\n          item = _context16.t1.value;\n          _context16.next = 7;\n          return fetchWithAuth(config.backend_url + "/checkin", {\n            method: "POST",\n            headers: {\n              "Content-Type": "application/json"\n            },\n            body: JSON.stringify({\n              "item_uuid": received_items[item].item.uuid,\n              "storage_name": document.querySelector("#storage_select").value,\n              "amount": received_items[item].num\n            })\n          });\n        case 7:\n          response = _context16.sent;\n          _context16.next = 10;\n          return checkResponseForError(response, "Failed to checkin item " + received_items[item].item.tag);\n        case 10:\n          if (!_context16.sent) {\n            _context16.next = 16;\n            break;\n          }\n          _context16.next = 13;\n          return response.json();\n        case 13:\n          tracking_item = _context16.sent;\n          // eslint-disable-line no-unused-vars\n          delete received_items[tracking_item.uuid];\n          successfullCount++;\n        case 16:\n          _context16.next = 3;\n          break;\n        case 18:\n          toast("Check-In successfull.", "The check-in of " + successfullCount + " items completed succesfully.");\n          updateItemsView();\n        case 20:\n        case "end":\n          return _context16.stop();\n      }\n    }, _callee16);\n  }));\n  return _checkinItems.apply(this, arguments);\n}\nfunction updateCheckoutItem(tracking_item) {\n  document.querySelector("#uuid").innerHTML = tracking_item.uuid;\n  document.querySelector("#tag").innerHTML = tracking_item.tag;\n  document.querySelector("#storage").innerHTML = tracking_item.storage;\n  document.querySelector("#addressee").innerHTML = tracking_item.addressee;\n  document.querySelector("#team").innerHTML = tracking_item.team;\n}\nfunction onRecevierScanSuccess(_x16) {\n  return _onRecevierScanSuccess.apply(this, arguments);\n}\nfunction _onRecevierScanSuccess() {\n  _onRecevierScanSuccess = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee17(scannedCode) {\n    var _scannedCode$split, _scannedCode$split2, uuid, signature, response, tracking_item;\n    return _regeneratorRuntime().wrap(function _callee17$(_context17) {\n      while (1) switch (_context17.prev = _context17.next) {\n        case 0:\n          debounceScanner();\n          _scannedCode$split = scannedCode.split("/"), _scannedCode$split2 = _slicedToArray(_scannedCode$split, 2), uuid = _scannedCode$split2[0], signature = _scannedCode$split2[1];\n          console.log("Receiver scan success");\n          scanner_audio.play();\n          _context17.next = 6;\n          return getConfig();\n        case 6:\n          _context17.next = 8;\n          return fetch(config.backend_url + "/item/" + uuid, {\n            headers: {}\n          });\n        case 8:\n          response = _context17.sent;\n          if (!(response.status == 200)) {\n            _context17.next = 26;\n            break;\n          }\n          _context17.next = 12;\n          return response.json();\n        case 12:\n          tracking_item = _context17.sent;\n          if (!ed448.verify(htoa(signature), new TextEncoder().encode(tracking_item.uuid), htoa(tracking_item.verification))) {\n            _context17.next = 22;\n            break;\n          }\n          if (!(tracking_item.storage == undefined || tracking_item.storage == null || tracking_item.storage.length == 0)) {\n            _context17.next = 18;\n            break;\n          }\n          alert("Item not yet received.");\n          console.log("Item not yet received.");\n          return _context17.abrupt("return");\n        case 18:\n          updateCheckoutItem(tracking_item);\n          console.log("Receiver verify success");\n          _context17.next = 24;\n          break;\n        case 22:\n          alert("Could not verify signature.");\n          console.log("Could not verify signature.");\n        case 24:\n          _context17.next = 27;\n          break;\n        case 26:\n          if (response.status == 404) {\n            alert("Item not found.");\n          } else {\n            checkResponseForError(response, "Failed to get item from backend.");\n          }\n        case 27:\n        case "end":\n          return _context17.stop();\n      }\n    }, _callee17);\n  }));\n  return _onRecevierScanSuccess.apply(this, arguments);\n}\nfunction scanReceiver() {\n  return _scanReceiver.apply(this, arguments);\n}\nfunction _scanReceiver() {\n  _scanReceiver = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee18() {\n    return _regeneratorRuntime().wrap(function _callee18$(_context18) {\n      while (1) switch (_context18.prev = _context18.next) {\n        case 0:\n          console.log("Scanning receiver.");\n          scanner.render(onRecevierScanSuccess, handleQrError);\n        case 2:\n        case "end":\n          return _context18.stop();\n      }\n    }, _callee18);\n  }));\n  return _scanReceiver.apply(this, arguments);\n}\nfunction loadStorages(_x17) {\n  return _loadStorages.apply(this, arguments);\n}\nfunction _loadStorages() {\n  _loadStorages = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee19(selectedStorage) {\n    var response, storages, select, i, option;\n    return _regeneratorRuntime().wrap(function _callee19$(_context19) {\n      while (1) switch (_context19.prev = _context19.next) {\n        case 0:\n          console.log("Retrieving storages");\n          _context19.next = 3;\n          return fetchWithAuth(config.backend_url + "/storages");\n        case 3:\n          response = _context19.sent;\n          _context19.next = 6;\n          return checkResponseForError(response, "Failed to load storages.");\n        case 6:\n          if (!_context19.sent) {\n            _context19.next = 13;\n            break;\n          }\n          _context19.next = 9;\n          return response.json();\n        case 9:\n          storages = _context19.sent;\n          select = document.querySelector("#storage_select");\n          console.log("Got storages");\n          for (i in storages) {\n            option = document.createElement("option");\n            option.textContent = storages[i].name;\n            option.value = storages[i].name;\n            select.appendChild(option);\n            if (selectedStorage == storages[i].name) {\n              select.value = selectedStorage;\n            }\n          }\n        case 13:\n        case "end":\n          return _context19.stop();\n      }\n    }, _callee19);\n  }));\n  return _loadStorages.apply(this, arguments);\n}\nfunction onPageLoad(_x18) {\n  return _onPageLoad.apply(this, arguments);\n}\nfunction _onPageLoad() {\n  _onPageLoad = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee20(doloadStorages) {\n    var pw;\n    return _regeneratorRuntime().wrap(function _callee20$(_context20) {\n      while (1) switch (_context20.prev = _context20.next) {\n        case 0:\n          _context20.next = 2;\n          return getConfig();\n        case 2:\n          pw = window.location.hash.substring(1);\n          if (!(pw.length > 1)) {\n            _context20.next = 8;\n            break;\n          }\n          _context20.next = 6;\n          return login(pw);\n        case 6:\n          _context20.next = 10;\n          break;\n        case 8:\n          _context20.next = 10;\n          return login();\n        case 10:\n          if (doloadStorages) {\n            loadStorages(document.location.search.substring(1));\n          }\n        case 11:\n        case "end":\n          return _context20.stop();\n      }\n    }, _callee20);\n  }));\n  return _onPageLoad.apply(this, arguments);\n}\nfunction checkoutByTag() {\n  return _checkoutByTag.apply(this, arguments);\n}\nfunction _checkoutByTag() {\n  _checkoutByTag = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee21() {\n    var el, response, tracking_item, confirmed;\n    return _regeneratorRuntime().wrap(function _callee21$(_context21) {\n      while (1) switch (_context21.prev = _context21.next) {\n        case 0:\n          console.log("Checkout by tag");\n          el = document.getElementById("checkoutByTag");\n          if (!(el.value.length != 6)) {\n            _context21.next = 6;\n            break;\n          }\n          alert("Not a BGP tag!");\n          console.log("Not a BGP tag");\n          return _context21.abrupt("return");\n        case 6:\n          _context21.next = 8;\n          return fetchWithAuth(config.backend_url + "/tag/" + el.value);\n        case 8:\n          response = _context21.sent;\n          if (!(response.status == 200)) {\n            _context21.next = 25;\n            break;\n          }\n          _context21.next = 12;\n          return response.json();\n        case 12:\n          tracking_item = _context21.sent;\n          confirmed = confirm("Did you make sure the recipient is really the right person?");\n          if (confirmed) {\n            _context21.next = 17;\n            break;\n          }\n          console.log("Recipient confirmation denied.");\n          return _context21.abrupt("return");\n        case 17:\n          if (!(tracking_item.storage == undefined || tracking_item.storage == null || tracking_item.storage.length == 0)) {\n            _context21.next = 21;\n            break;\n          }\n          alert("Item not yet received.");\n          console.log("Item not yet received.");\n          return _context21.abrupt("return");\n        case 21:\n          console.log("Checkout item by tag success.");\n          updateCheckoutItem(tracking_item);\n          _context21.next = 26;\n          break;\n        case 25:\n          if (response.status == 404) {\n            console.log("Item not found");\n            alert("Item not found!");\n          } else {\n            checkResponseForError(response, "Failed to get item from backend");\n          }\n        case 26:\n        case "end":\n          return _context21.stop();\n      }\n    }, _callee21);\n  }));\n  return _checkoutByTag.apply(this, arguments);\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMjQ0LmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUNsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeklBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdFRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2MEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1REE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3TUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuYUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3BOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9jb3JlLmpzPzRiM2IiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vc3RyaW5ncy5qcz8xNGEzIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL3V0aWxzLmpzPzYxNjQiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20venhpbmctaHRtbDUtcXJjb2RlLWRlY29kZXIuanM/NDMxZiIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9uYXRpdmUtYmFyLWNvZGUtZGV0ZWN0b3IuanM/ZGU5YyIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9jb2RlLWRlY29kZXIuanM/ZTgyNCIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9jYW1lcmEvY29yZS1pbXBsLmpzP2I3NmIiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vY2FtZXJhL2ZhY3Rvcmllcy5qcz83ZWM3Iiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL2NhbWVyYS9yZXRyaWV2ZXIuanM/NTMwMiIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9zdGF0ZS1tYW5hZ2VyLmpzP2Q5MWIiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vaHRtbDUtcXJjb2RlLmpzPzRjMjAiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vaW1hZ2UtYXNzZXRzLmpzPzFjOGQiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vc3RvcmFnZS5qcz83OTg0Iiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL3VpLmpzPzcxOWQiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vY2FtZXJhL3Blcm1pc3Npb25zLmpzPzcwMDkiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vdWkvc2Nhbm5lci9zY2FuLXR5cGUtc2VsZWN0b3IuanM/YWJlZSIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS9zY2FubmVyL2Jhc2UuanM/NDE0ZiIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS9zY2FubmVyL3RvcmNoLWJ1dHRvbi5qcz8zMzAzIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL3VpL3NjYW5uZXIvZmlsZS1zZWxlY3Rpb24tdWkuanM/OTVhZSIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS9zY2FubmVyL2NhbWVyYS1zZWxlY3Rpb24tdWkuanM/NzNkZCIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS9zY2FubmVyL2NhbWVyYS16b29tLXVpLmpzP2U2ZjEiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vaHRtbDUtcXJjb2RlLXNjYW5uZXIuanM/ODVkNSIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9pbmRleC5qcz83ODRlIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9Abm9ibGUvaGFzaGVzL2VzbS9fYXNzZXJ0LmpzPzc2MDAiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9oYXNoZXMvZXNtL191NjQuanM/YjYyYSIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvQG5vYmxlL2hhc2hlcy9lc20vY3J5cHRvLmpzPzE1MzAiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9oYXNoZXMvZXNtL3V0aWxzLmpzPzNmOTIiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9oYXNoZXMvZXNtL3NoYTMuanM/YWJjYiIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvQG5vYmxlL2N1cnZlcy9lc20vYWJzdHJhY3QvdXRpbHMuanM/MjkzYSIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvQG5vYmxlL2N1cnZlcy9lc20vYWJzdHJhY3QvbW9kdWxhci5qcz80YWQ0Iiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9Abm9ibGUvY3VydmVzL2VzbS9hYnN0cmFjdC9jdXJ2ZS5qcz8zOTk4Iiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9Abm9ibGUvY3VydmVzL2VzbS9hYnN0cmFjdC9lZHdhcmRzLmpzP2IxYWUiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9jdXJ2ZXMvZXNtL2Fic3RyYWN0L21vbnRnb21lcnkuanM/OWZlZCIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvQG5vYmxlL2N1cnZlcy9lc20vYWJzdHJhY3QvaGFzaC10by1jdXJ2ZS5qcz80NmQwIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9Abm9ibGUvY3VydmVzL2VzbS9lZDQ0OC5qcz8xYTJhIiwid2VicGFjazovL2xpYi8uL3NyYy9qcy9tYWluLmpzPzAwM2EiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHZhciBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHM7XG4oZnVuY3Rpb24gKEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cykge1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJRUl9DT0RFXCJdID0gMF0gPSBcIlFSX0NPREVcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiQVpURUNcIl0gPSAxXSA9IFwiQVpURUNcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiQ09EQUJBUlwiXSA9IDJdID0gXCJDT0RBQkFSXCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIkNPREVfMzlcIl0gPSAzXSA9IFwiQ09ERV8zOVwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJDT0RFXzkzXCJdID0gNF0gPSBcIkNPREVfOTNcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiQ09ERV8xMjhcIl0gPSA1XSA9IFwiQ09ERV8xMjhcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiREFUQV9NQVRSSVhcIl0gPSA2XSA9IFwiREFUQV9NQVRSSVhcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiTUFYSUNPREVcIl0gPSA3XSA9IFwiTUFYSUNPREVcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiSVRGXCJdID0gOF0gPSBcIklURlwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJFQU5fMTNcIl0gPSA5XSA9IFwiRUFOXzEzXCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIkVBTl84XCJdID0gMTBdID0gXCJFQU5fOFwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJQREZfNDE3XCJdID0gMTFdID0gXCJQREZfNDE3XCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIlJTU18xNFwiXSA9IDEyXSA9IFwiUlNTXzE0XCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIlJTU19FWFBBTkRFRFwiXSA9IDEzXSA9IFwiUlNTX0VYUEFOREVEXCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIlVQQ19BXCJdID0gMTRdID0gXCJVUENfQVwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJVUENfRVwiXSA9IDE1XSA9IFwiVVBDX0VcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiVVBDX0VBTl9FWFRFTlNJT05cIl0gPSAxNl0gPSBcIlVQQ19FQU5fRVhURU5TSU9OXCI7XG59KShIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMgfHwgKEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyA9IHt9KSk7XG52YXIgaHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzVGV4dE1hcCA9IG5ldyBNYXAoW1xuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUVJfQ09ERSwgXCJRUl9DT0RFXCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQVpURUMsIFwiQVpURUNcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RBQkFSLCBcIkNPREFCQVJcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzM5LCBcIkNPREVfMzlcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzkzLCBcIkNPREVfOTNcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzEyOCwgXCJDT0RFXzEyOFwiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkRBVEFfTUFUUklYLCBcIkRBVEFfTUFUUklYXCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuTUFYSUNPREUsIFwiTUFYSUNPREVcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5JVEYsIFwiSVRGXCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuRUFOXzEzLCBcIkVBTl8xM1wiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkVBTl84LCBcIkVBTl84XCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUERGXzQxNywgXCJQREZfNDE3XCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUlNTXzE0LCBcIlJTU18xNFwiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlJTU19FWFBBTkRFRCwgXCJSU1NfRVhQQU5ERURcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5VUENfQSwgXCJVUENfQVwiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlVQQ19FLCBcIlVQQ19FXCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0VBTl9FWFRFTlNJT04sIFwiVVBDX0VBTl9FWFRFTlNJT05cIl1cbl0pO1xuZXhwb3J0IHZhciBEZWNvZGVkVGV4dFR5cGU7XG4oZnVuY3Rpb24gKERlY29kZWRUZXh0VHlwZSkge1xuICAgIERlY29kZWRUZXh0VHlwZVtEZWNvZGVkVGV4dFR5cGVbXCJVTktOT1dOXCJdID0gMF0gPSBcIlVOS05PV05cIjtcbiAgICBEZWNvZGVkVGV4dFR5cGVbRGVjb2RlZFRleHRUeXBlW1wiVVJMXCJdID0gMV0gPSBcIlVSTFwiO1xufSkoRGVjb2RlZFRleHRUeXBlIHx8IChEZWNvZGVkVGV4dFR5cGUgPSB7fSkpO1xuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWRIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMoZm9ybWF0KSB7XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXMoSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzKS5pbmNsdWRlcyhmb3JtYXQpO1xufVxuZXhwb3J0IHZhciBIdG1sNVFyY29kZVNjYW5UeXBlO1xuKGZ1bmN0aW9uIChIdG1sNVFyY29kZVNjYW5UeXBlKSB7XG4gICAgSHRtbDVRcmNvZGVTY2FuVHlwZVtIdG1sNVFyY29kZVNjYW5UeXBlW1wiU0NBTl9UWVBFX0NBTUVSQVwiXSA9IDBdID0gXCJTQ0FOX1RZUEVfQ0FNRVJBXCI7XG4gICAgSHRtbDVRcmNvZGVTY2FuVHlwZVtIdG1sNVFyY29kZVNjYW5UeXBlW1wiU0NBTl9UWVBFX0ZJTEVcIl0gPSAxXSA9IFwiU0NBTl9UWVBFX0ZJTEVcIjtcbn0pKEh0bWw1UXJjb2RlU2NhblR5cGUgfHwgKEh0bWw1UXJjb2RlU2NhblR5cGUgPSB7fSkpO1xudmFyIEh0bWw1UXJjb2RlQ29uc3RhbnRzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBIdG1sNVFyY29kZUNvbnN0YW50cygpIHtcbiAgICB9XG4gICAgSHRtbDVRcmNvZGVDb25zdGFudHMuR0lUSFVCX1BST0pFQ1RfVVJMID0gXCJodHRwczovL2dpdGh1Yi5jb20vbWViamFzL2h0bWw1LXFyY29kZVwiO1xuICAgIEh0bWw1UXJjb2RlQ29uc3RhbnRzLlNDQU5fREVGQVVMVF9GUFMgPSAyO1xuICAgIEh0bWw1UXJjb2RlQ29uc3RhbnRzLkRFRkFVTFRfRElTQUJMRV9GTElQID0gZmFsc2U7XG4gICAgSHRtbDVRcmNvZGVDb25zdGFudHMuREVGQVVMVF9SRU1FTUJFUl9MQVNUX0NBTUVSQV9VU0VEID0gdHJ1ZTtcbiAgICBIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1NVUFBPUlRFRF9TQ0FOX1RZUEUgPSBbXG4gICAgICAgIEh0bWw1UXJjb2RlU2NhblR5cGUuU0NBTl9UWVBFX0NBTUVSQSxcbiAgICAgICAgSHRtbDVRcmNvZGVTY2FuVHlwZS5TQ0FOX1RZUEVfRklMRVxuICAgIF07XG4gICAgcmV0dXJuIEh0bWw1UXJjb2RlQ29uc3RhbnRzO1xufSgpKTtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlQ29uc3RhbnRzIH07XG52YXIgUXJjb2RlUmVzdWx0Rm9ybWF0ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBRcmNvZGVSZXN1bHRGb3JtYXQoZm9ybWF0LCBmb3JtYXROYW1lKSB7XG4gICAgICAgIHRoaXMuZm9ybWF0ID0gZm9ybWF0O1xuICAgICAgICB0aGlzLmZvcm1hdE5hbWUgPSBmb3JtYXROYW1lO1xuICAgIH1cbiAgICBRcmNvZGVSZXN1bHRGb3JtYXQucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5mb3JtYXROYW1lO1xuICAgIH07XG4gICAgUXJjb2RlUmVzdWx0Rm9ybWF0LmNyZWF0ZSA9IGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICAgICAgaWYgKCFodG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNUZXh0TWFwLmhhcyhmb3JtYXQpKSB7XG4gICAgICAgICAgICB0aHJvdyBcIlwiLmNvbmNhdChmb3JtYXQsIFwiIG5vdCBpbiBodG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNUZXh0TWFwXCIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgUXJjb2RlUmVzdWx0Rm9ybWF0KGZvcm1hdCwgaHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzVGV4dE1hcC5nZXQoZm9ybWF0KSk7XG4gICAgfTtcbiAgICByZXR1cm4gUXJjb2RlUmVzdWx0Rm9ybWF0O1xufSgpKTtcbmV4cG9ydCB7IFFyY29kZVJlc3VsdEZvcm1hdCB9O1xudmFyIEh0bWw1UXJjb2RlUmVzdWx0RmFjdG9yeSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gSHRtbDVRcmNvZGVSZXN1bHRGYWN0b3J5KCkge1xuICAgIH1cbiAgICBIdG1sNVFyY29kZVJlc3VsdEZhY3RvcnkuY3JlYXRlRnJvbVRleHQgPSBmdW5jdGlvbiAoZGVjb2RlZFRleHQpIHtcbiAgICAgICAgdmFyIHFyY29kZVJlc3VsdCA9IHtcbiAgICAgICAgICAgIHRleHQ6IGRlY29kZWRUZXh0XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBkZWNvZGVkVGV4dDogZGVjb2RlZFRleHQsXG4gICAgICAgICAgICByZXN1bHQ6IHFyY29kZVJlc3VsdFxuICAgICAgICB9O1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVSZXN1bHRGYWN0b3J5LmNyZWF0ZUZyb21RcmNvZGVSZXN1bHQgPSBmdW5jdGlvbiAocXJjb2RlUmVzdWx0KSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBkZWNvZGVkVGV4dDogcXJjb2RlUmVzdWx0LnRleHQsXG4gICAgICAgICAgICByZXN1bHQ6IHFyY29kZVJlc3VsdFxuICAgICAgICB9O1xuICAgIH07XG4gICAgcmV0dXJuIEh0bWw1UXJjb2RlUmVzdWx0RmFjdG9yeTtcbn0oKSk7XG5leHBvcnQgeyBIdG1sNVFyY29kZVJlc3VsdEZhY3RvcnkgfTtcbmV4cG9ydCB2YXIgSHRtbDVRcmNvZGVFcnJvclR5cGVzO1xuKGZ1bmN0aW9uIChIdG1sNVFyY29kZUVycm9yVHlwZXMpIHtcbiAgICBIdG1sNVFyY29kZUVycm9yVHlwZXNbSHRtbDVRcmNvZGVFcnJvclR5cGVzW1wiVU5LV09XTl9FUlJPUlwiXSA9IDBdID0gXCJVTktXT1dOX0VSUk9SXCI7XG4gICAgSHRtbDVRcmNvZGVFcnJvclR5cGVzW0h0bWw1UXJjb2RlRXJyb3JUeXBlc1tcIklNUExFTUVOVEFUSU9OX0VSUk9SXCJdID0gMV0gPSBcIklNUExFTUVOVEFUSU9OX0VSUk9SXCI7XG4gICAgSHRtbDVRcmNvZGVFcnJvclR5cGVzW0h0bWw1UXJjb2RlRXJyb3JUeXBlc1tcIk5PX0NPREVfRk9VTkRfRVJST1JcIl0gPSAyXSA9IFwiTk9fQ09ERV9GT1VORF9FUlJPUlwiO1xufSkoSHRtbDVRcmNvZGVFcnJvclR5cGVzIHx8IChIdG1sNVFyY29kZUVycm9yVHlwZXMgPSB7fSkpO1xudmFyIEh0bWw1UXJjb2RlRXJyb3JGYWN0b3J5ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBIdG1sNVFyY29kZUVycm9yRmFjdG9yeSgpIHtcbiAgICB9XG4gICAgSHRtbDVRcmNvZGVFcnJvckZhY3RvcnkuY3JlYXRlRnJvbSA9IGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBlcnJvcixcbiAgICAgICAgICAgIHR5cGU6IEh0bWw1UXJjb2RlRXJyb3JUeXBlcy5VTktXT1dOX0VSUk9SXG4gICAgICAgIH07XG4gICAgfTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGVFcnJvckZhY3Rvcnk7XG59KCkpO1xuZXhwb3J0IHsgSHRtbDVRcmNvZGVFcnJvckZhY3RvcnkgfTtcbnZhciBCYXNlTG9nZ2dlciA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQmFzZUxvZ2dnZXIodmVyYm9zZSkge1xuICAgICAgICB0aGlzLnZlcmJvc2UgPSB2ZXJib3NlO1xuICAgIH1cbiAgICBCYXNlTG9nZ2dlci5wcm90b3R5cGUubG9nID0gZnVuY3Rpb24gKG1lc3NhZ2UpIHtcbiAgICAgICAgaWYgKHRoaXMudmVyYm9zZSkge1xuICAgICAgICAgICAgY29uc29sZS5sb2cobWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEJhc2VMb2dnZ2VyLnByb3RvdHlwZS53YXJuID0gZnVuY3Rpb24gKG1lc3NhZ2UpIHtcbiAgICAgICAgaWYgKHRoaXMudmVyYm9zZSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBCYXNlTG9nZ2dlci5wcm90b3R5cGUubG9nRXJyb3IgPSBmdW5jdGlvbiAobWVzc2FnZSwgaXNFeHBlcmltZW50YWwpIHtcbiAgICAgICAgaWYgKHRoaXMudmVyYm9zZSB8fCBpc0V4cGVyaW1lbnRhbCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQmFzZUxvZ2dnZXIucHJvdG90eXBlLmxvZ0Vycm9ycyA9IGZ1bmN0aW9uIChlcnJvcnMpIHtcbiAgICAgICAgaWYgKGVycm9ycy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IFwiTG9nZ2VyI2xvZ0Vycm9yIGNhbGxlZCB3aXRob3V0IGFyZ3VtZW50c1wiO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnZlcmJvc2UpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3JzKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIEJhc2VMb2dnZ2VyO1xufSgpKTtcbmV4cG9ydCB7IEJhc2VMb2dnZ2VyIH07XG5leHBvcnQgZnVuY3Rpb24gaXNOdWxsT3JVbmRlZmluZWQob2JqKSB7XG4gICAgcmV0dXJuICh0eXBlb2Ygb2JqID09PSBcInVuZGVmaW5lZFwiKSB8fCBvYmogPT09IG51bGw7XG59XG5leHBvcnQgZnVuY3Rpb24gY2xpcCh2YWx1ZSwgbWluVmFsdWUsIG1heFZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID4gbWF4VmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIG1heFZhbHVlO1xuICAgIH1cbiAgICBpZiAodmFsdWUgPCBtaW5WYWx1ZSkge1xuICAgICAgICByZXR1cm4gbWluVmFsdWU7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZTtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWNvcmUuanMubWFwIiwidmFyIEh0bWw1UXJjb2RlU3RyaW5ncyA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gSHRtbDVRcmNvZGVTdHJpbmdzKCkge1xuICAgIH1cbiAgICBIdG1sNVFyY29kZVN0cmluZ3MuY29kZVBhcnNlRXJyb3IgPSBmdW5jdGlvbiAoZXhjZXB0aW9uKSB7XG4gICAgICAgIHJldHVybiBcIlFSIGNvZGUgcGFyc2UgZXJyb3IsIGVycm9yID0gXCIuY29uY2F0KGV4Y2VwdGlvbik7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVN0cmluZ3MuZXJyb3JHZXR0aW5nVXNlck1lZGlhID0gZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgIHJldHVybiBcIkVycm9yIGdldHRpbmcgdXNlck1lZGlhLCBlcnJvciA9IFwiLmNvbmNhdChlcnJvcik7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVN0cmluZ3Mub25seURldmljZVN1cHBvcnRlZEVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJUaGUgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzICwgb25seSBcIlxuICAgICAgICAgICAgKyBcInN1cHBvcnRlZCBjYW1lcmFJZE9yQ29uZmlnIGluIHRoaXMgY2FzZSBpcyBkZXZpY2VJZCBwYXJhbWV0ZXIgXCJcbiAgICAgICAgICAgICsgXCIoc3RyaW5nKS5cIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU3RyaW5ncy5jYW1lcmFTdHJlYW1pbmdOb3RTdXBwb3J0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkNhbWVyYSBzdHJlYW1pbmcgbm90IHN1cHBvcnRlZCBieSB0aGUgYnJvd3Nlci5cIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU3RyaW5ncy51bmFibGVUb1F1ZXJ5U3VwcG9ydGVkRGV2aWNlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiVW5hYmxlIHRvIHF1ZXJ5IHN1cHBvcnRlZCBkZXZpY2VzLCB1bmtub3duIGVycm9yLlwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTdHJpbmdzLmluc2VjdXJlQ29udGV4dENhbWVyYVF1ZXJ5RXJyb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkNhbWVyYSBhY2Nlc3MgaXMgb25seSBzdXBwb3J0ZWQgaW4gc2VjdXJlIGNvbnRleHQgbGlrZSBodHRwcyBcIlxuICAgICAgICAgICAgKyBcIm9yIGxvY2FsaG9zdC5cIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU3RyaW5ncy5zY2FubmVyUGF1c2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJTY2FubmVyIHBhdXNlZFwiO1xuICAgIH07XG4gICAgcmV0dXJuIEh0bWw1UXJjb2RlU3RyaW5ncztcbn0oKSk7XG5leHBvcnQgeyBIdG1sNVFyY29kZVN0cmluZ3MgfTtcbnZhciBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzKCkge1xuICAgIH1cbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnNjYW5uaW5nU3RhdHVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJTY2FubmluZ1wiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5pZGxlU3RhdHVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJJZGxlXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmVycm9yU3RhdHVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJFcnJvclwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5wZXJtaXNzaW9uU3RhdHVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJQZXJtaXNzaW9uXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLm5vQ2FtZXJhRm91bmRFcnJvclN0YXR1cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiTm8gQ2FtZXJhc1wiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5sYXN0TWF0Y2ggPSBmdW5jdGlvbiAoZGVjb2RlZFRleHQpIHtcbiAgICAgICAgcmV0dXJuIFwiTGFzdCBNYXRjaDogXCIuY29uY2F0KGRlY29kZWRUZXh0KTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuY29kZVNjYW5uZXJUaXRsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiQ29kZSBTY2FubmVyXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmNhbWVyYVBlcm1pc3Npb25UaXRsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiUmVxdWVzdCBDYW1lcmEgUGVybWlzc2lvbnNcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuY2FtZXJhUGVybWlzc2lvblJlcXVlc3RpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlJlcXVlc3RpbmcgY2FtZXJhIHBlcm1pc3Npb25zLi4uXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLm5vQ2FtZXJhRm91bmQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIk5vIGNhbWVyYSBmb3VuZFwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5zY2FuQnV0dG9uU3RvcFNjYW5uaW5nVGV4dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiU3RvcCBTY2FubmluZ1wiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5zY2FuQnV0dG9uU3RhcnRTY2FubmluZ1RleHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlN0YXJ0IFNjYW5uaW5nXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRvcmNoT25CdXR0b24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlN3aXRjaCBPbiBUb3JjaFwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50b3JjaE9mZkJ1dHRvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiU3dpdGNoIE9mZiBUb3JjaFwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50b3JjaE9uRmFpbGVkTWVzc2FnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiRmFpbGVkIHRvIHR1cm4gb24gdG9yY2hcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudG9yY2hPZmZGYWlsZWRNZXNzYWdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJGYWlsZWQgdG8gdHVybiBvZmYgdG9yY2hcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muc2NhbkJ1dHRvblNjYW5uaW5nU3RhcnRpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkxhdW5jaGluZyBDYW1lcmEuLi5cIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudGV4dElmQ2FtZXJhU2NhblNlbGVjdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJTY2FuIGFuIEltYWdlIEZpbGVcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudGV4dElmRmlsZVNjYW5TZWxlY3RlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiU2NhbiB1c2luZyBjYW1lcmEgZGlyZWN0bHlcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muc2VsZWN0Q2FtZXJhID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJTZWxlY3QgQ2FtZXJhXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmZpbGVTZWxlY3Rpb25DaG9vc2VJbWFnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiQ2hvb3NlIEltYWdlXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmZpbGVTZWxlY3Rpb25DaG9vc2VBbm90aGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJDaG9vc2UgQW5vdGhlclwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5maWxlU2VsZWN0aW9uTm9JbWFnZVNlbGVjdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJObyBpbWFnZSBjaG9vc2VuXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmFub255bW91c0NhbWVyYVByZWZpeCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiQW5vbnltb3VzIENhbWVyYVwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5kcmFnQW5kRHJvcE1lc3NhZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIk9yIGRyb3AgYW4gaW1hZ2UgdG8gc2NhblwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5kcmFnQW5kRHJvcE1lc3NhZ2VPbmx5SW1hZ2VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJPciBkcm9wIGFuIGltYWdlIHRvIHNjYW4gKG90aGVyIGZpbGVzIG5vdCBzdXBwb3J0ZWQpXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnpvb20gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcInpvb21cIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MubG9hZGluZ0ltYWdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJMb2FkaW5nIGltYWdlLi4uXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmNhbWVyYVNjYW5BbHRUZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJDYW1lcmEgYmFzZWQgc2NhblwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5maWxlU2NhbkFsdFRleHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkZ1bGUgYmFzZWQgc2NhblwiO1xuICAgIH07XG4gICAgcmV0dXJuIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3M7XG59KCkpO1xuZXhwb3J0IHsgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncyB9O1xudmFyIExpYnJhcnlJbmZvU3RyaW5ncyA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gTGlicmFyeUluZm9TdHJpbmdzKCkge1xuICAgIH1cbiAgICBMaWJyYXJ5SW5mb1N0cmluZ3MucG93ZXJlZEJ5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJQb3dlcmVkIGJ5IFwiO1xuICAgIH07XG4gICAgTGlicmFyeUluZm9TdHJpbmdzLnJlcG9ydElzc3VlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiUmVwb3J0IGlzc3Vlc1wiO1xuICAgIH07XG4gICAgcmV0dXJuIExpYnJhcnlJbmZvU3RyaW5ncztcbn0oKSk7XG5leHBvcnQgeyBMaWJyYXJ5SW5mb1N0cmluZ3MgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXN0cmluZ3MuanMubWFwIiwidmFyIFZpZGVvQ29uc3RyYWludHNVdGlsID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBWaWRlb0NvbnN0cmFpbnRzVXRpbCgpIHtcbiAgICB9XG4gICAgVmlkZW9Db25zdHJhaW50c1V0aWwuaXNNZWRpYVN0cmVhbUNvbnN0cmFpbnRzVmFsaWQgPSBmdW5jdGlvbiAodmlkZW9Db25zdHJhaW50cywgbG9nZ2VyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgdmlkZW9Db25zdHJhaW50cyAhPT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgdmFyIHR5cGVvZlZpZGVvQ29uc3RyYWludHMgPSB0eXBlb2YgdmlkZW9Db25zdHJhaW50cztcbiAgICAgICAgICAgIGxvZ2dlci5sb2dFcnJvcihcInZpZGVvQ29uc3RyYWludHMgc2hvdWxkIGJlIG9mIHR5cGUgb2JqZWN0LCB0aGUgXCJcbiAgICAgICAgICAgICAgICArIFwib2JqZWN0IHBhc3NlZCBpcyBvZiB0eXBlIFwiLmNvbmNhdCh0eXBlb2ZWaWRlb0NvbnN0cmFpbnRzLCBcIi5cIiksIHRydWUpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBiYW5uZWRLZXlzID0gW1xuICAgICAgICAgICAgXCJhdXRvR2FpbkNvbnRyb2xcIixcbiAgICAgICAgICAgIFwiY2hhbm5lbENvdW50XCIsXG4gICAgICAgICAgICBcImVjaG9DYW5jZWxsYXRpb25cIixcbiAgICAgICAgICAgIFwibGF0ZW5jeVwiLFxuICAgICAgICAgICAgXCJub2lzZVN1cHByZXNzaW9uXCIsXG4gICAgICAgICAgICBcInNhbXBsZVJhdGVcIixcbiAgICAgICAgICAgIFwic2FtcGxlU2l6ZVwiLFxuICAgICAgICAgICAgXCJ2b2x1bWVcIlxuICAgICAgICBdO1xuICAgICAgICB2YXIgYmFubmVka2V5c1NldCA9IG5ldyBTZXQoYmFubmVkS2V5cyk7XG4gICAgICAgIHZhciBrZXlzSW5WaWRlb0NvbnN0cmFpbnRzID0gT2JqZWN0LmtleXModmlkZW9Db25zdHJhaW50cyk7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwga2V5c0luVmlkZW9Db25zdHJhaW50c18xID0ga2V5c0luVmlkZW9Db25zdHJhaW50czsgX2kgPCBrZXlzSW5WaWRlb0NvbnN0cmFpbnRzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0ga2V5c0luVmlkZW9Db25zdHJhaW50c18xW19pXTtcbiAgICAgICAgICAgIGlmIChiYW5uZWRrZXlzU2V0LmhhcyhrZXkpKSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmxvZ0Vycm9yKFwiXCIuY29uY2F0KGtleSwgXCIgaXMgbm90IHN1cHBvcnRlZCB2aWRlb0NvbnN0YWludHMuXCIpLCB0cnVlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICByZXR1cm4gVmlkZW9Db25zdHJhaW50c1V0aWw7XG59KCkpO1xuZXhwb3J0IHsgVmlkZW9Db25zdHJhaW50c1V0aWwgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXV0aWxzLmpzLm1hcCIsImltcG9ydCAqIGFzIFpYaW5nIGZyb20gXCIuLi90aGlyZF9wYXJ0eS96eGluZy1qcy51bWRcIjtcbmltcG9ydCB7IFFyY29kZVJlc3VsdEZvcm1hdCwgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzIH0gZnJvbSBcIi4vY29yZVwiO1xudmFyIFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBaWGluZ0h0bWw1UXJjb2RlRGVjb2RlcihyZXF1ZXN0ZWRGb3JtYXRzLCB2ZXJib3NlLCBsb2dnZXIpIHtcbiAgICAgICAgdGhpcy5mb3JtYXRNYXAgPSBuZXcgTWFwKFtcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUVJfQ09ERSwgWlhpbmcuQmFyY29kZUZvcm1hdC5RUl9DT0RFXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQVpURUMsIFpYaW5nLkJhcmNvZGVGb3JtYXQuQVpURUNdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RBQkFSLCBaWGluZy5CYXJjb2RlRm9ybWF0LkNPREFCQVJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzM5LCBaWGluZy5CYXJjb2RlRm9ybWF0LkNPREVfMzldLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzkzLCBaWGluZy5CYXJjb2RlRm9ybWF0LkNPREVfOTNdLFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzEyOCxcbiAgICAgICAgICAgICAgICBaWGluZy5CYXJjb2RlRm9ybWF0LkNPREVfMTI4XG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5EQVRBX01BVFJJWCxcbiAgICAgICAgICAgICAgICBaWGluZy5CYXJjb2RlRm9ybWF0LkRBVEFfTUFUUklYXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5NQVhJQ09ERSxcbiAgICAgICAgICAgICAgICBaWGluZy5CYXJjb2RlRm9ybWF0Lk1BWElDT0RFXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5JVEYsIFpYaW5nLkJhcmNvZGVGb3JtYXQuSVRGXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuRUFOXzEzLCBaWGluZy5CYXJjb2RlRm9ybWF0LkVBTl8xM10sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkVBTl84LCBaWGluZy5CYXJjb2RlRm9ybWF0LkVBTl84XSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUERGXzQxNywgWlhpbmcuQmFyY29kZUZvcm1hdC5QREZfNDE3XSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUlNTXzE0LCBaWGluZy5CYXJjb2RlRm9ybWF0LlJTU18xNF0sXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlJTU19FWFBBTkRFRCxcbiAgICAgICAgICAgICAgICBaWGluZy5CYXJjb2RlRm9ybWF0LlJTU19FWFBBTkRFRFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0EsIFpYaW5nLkJhcmNvZGVGb3JtYXQuVVBDX0FdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5VUENfRSwgWlhpbmcuQmFyY29kZUZvcm1hdC5VUENfRV0sXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlVQQ19FQU5fRVhURU5TSU9OLFxuICAgICAgICAgICAgICAgIFpYaW5nLkJhcmNvZGVGb3JtYXQuVVBDX0VBTl9FWFRFTlNJT05cbiAgICAgICAgICAgIF1cbiAgICAgICAgXSk7XG4gICAgICAgIHRoaXMucmV2ZXJzZUZvcm1hdE1hcCA9IHRoaXMuY3JlYXRlUmV2ZXJzZUZvcm1hdE1hcCgpO1xuICAgICAgICBpZiAoIVpYaW5nKSB7XG4gICAgICAgICAgICB0aHJvdyBcIlVzZSBodG1sNXFyY29kZS5taW4uanMgd2l0aG91dCBlZGl0LCBaWGluZyBub3QgZm91bmQuXCI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy52ZXJib3NlID0gdmVyYm9zZTtcbiAgICAgICAgdGhpcy5sb2dnZXIgPSBsb2dnZXI7XG4gICAgICAgIHZhciBmb3JtYXRzID0gdGhpcy5jcmVhdGVaWGluZ0Zvcm1hdHMocmVxdWVzdGVkRm9ybWF0cyk7XG4gICAgICAgIHZhciBoaW50cyA9IG5ldyBNYXAoKTtcbiAgICAgICAgaGludHMuc2V0KFpYaW5nLkRlY29kZUhpbnRUeXBlLlBPU1NJQkxFX0ZPUk1BVFMsIGZvcm1hdHMpO1xuICAgICAgICBoaW50cy5zZXQoWlhpbmcuRGVjb2RlSGludFR5cGUuVFJZX0hBUkRFUiwgZmFsc2UpO1xuICAgICAgICB0aGlzLmhpbnRzID0gaGludHM7XG4gICAgfVxuICAgIFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyLnByb3RvdHlwZS5kZWNvZGVBc3luYyA9IGZ1bmN0aW9uIChjYW52YXMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShfdGhpcy5kZWNvZGUoY2FudmFzKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyLnByb3RvdHlwZS5kZWNvZGUgPSBmdW5jdGlvbiAoY2FudmFzKSB7XG4gICAgICAgIHZhciB6eGluZ0RlY29kZXIgPSBuZXcgWlhpbmcuTXVsdGlGb3JtYXRSZWFkZXIodGhpcy52ZXJib3NlLCB0aGlzLmhpbnRzKTtcbiAgICAgICAgdmFyIGx1bWluYW5jZVNvdXJjZSA9IG5ldyBaWGluZy5IVE1MQ2FudmFzRWxlbWVudEx1bWluYW5jZVNvdXJjZShjYW52YXMpO1xuICAgICAgICB2YXIgYmluYXJ5Qml0bWFwID0gbmV3IFpYaW5nLkJpbmFyeUJpdG1hcChuZXcgWlhpbmcuSHlicmlkQmluYXJpemVyKGx1bWluYW5jZVNvdXJjZSkpO1xuICAgICAgICB2YXIgcmVzdWx0ID0genhpbmdEZWNvZGVyLmRlY29kZShiaW5hcnlCaXRtYXApO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdGV4dDogcmVzdWx0LnRleHQsXG4gICAgICAgICAgICBmb3JtYXQ6IFFyY29kZVJlc3VsdEZvcm1hdC5jcmVhdGUodGhpcy50b0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyhyZXN1bHQuZm9ybWF0KSksXG4gICAgICAgICAgICBkZWJ1Z0RhdGE6IHRoaXMuY3JlYXRlRGVidWdEYXRhKClcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyLnByb3RvdHlwZS5jcmVhdGVSZXZlcnNlRm9ybWF0TWFwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLmZvcm1hdE1hcC5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZSwga2V5LCBfKSB7XG4gICAgICAgICAgICByZXN1bHQuc2V0KHZhbHVlLCBrZXkpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyLnByb3RvdHlwZS50b0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyA9IGZ1bmN0aW9uICh6eGluZ0Zvcm1hdCkge1xuICAgICAgICBpZiAoIXRoaXMucmV2ZXJzZUZvcm1hdE1hcC5oYXMoenhpbmdGb3JtYXQpKSB7XG4gICAgICAgICAgICB0aHJvdyBcInJldmVyc2VGb3JtYXRNYXAgZG9lc24ndCBoYXZlIFwiLmNvbmNhdCh6eGluZ0Zvcm1hdCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMucmV2ZXJzZUZvcm1hdE1hcC5nZXQoenhpbmdGb3JtYXQpO1xuICAgIH07XG4gICAgWlhpbmdIdG1sNVFyY29kZURlY29kZXIucHJvdG90eXBlLmNyZWF0ZVpYaW5nRm9ybWF0cyA9IGZ1bmN0aW9uIChyZXF1ZXN0ZWRGb3JtYXRzKSB7XG4gICAgICAgIHZhciB6eGluZ0Zvcm1hdHMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCByZXF1ZXN0ZWRGb3JtYXRzXzEgPSByZXF1ZXN0ZWRGb3JtYXRzOyBfaSA8IHJlcXVlc3RlZEZvcm1hdHNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciByZXF1ZXN0ZWRGb3JtYXQgPSByZXF1ZXN0ZWRGb3JtYXRzXzFbX2ldO1xuICAgICAgICAgICAgaWYgKHRoaXMuZm9ybWF0TWFwLmhhcyhyZXF1ZXN0ZWRGb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgenhpbmdGb3JtYXRzLnB1c2godGhpcy5mb3JtYXRNYXAuZ2V0KHJlcXVlc3RlZEZvcm1hdCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIubG9nRXJyb3IoXCJcIi5jb25jYXQocmVxdWVzdGVkRm9ybWF0LCBcIiBpcyBub3Qgc3VwcG9ydGVkIGJ5XCIpXG4gICAgICAgICAgICAgICAgICAgICsgXCJaWGluZ0h0bWw1UXJjb2RlU2hpbVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4genhpbmdGb3JtYXRzO1xuICAgIH07XG4gICAgWlhpbmdIdG1sNVFyY29kZURlY29kZXIucHJvdG90eXBlLmNyZWF0ZURlYnVnRGF0YSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHsgZGVjb2Rlck5hbWU6IFwienhpbmctanNcIiB9O1xuICAgIH07XG4gICAgcmV0dXJuIFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyO1xufSgpKTtcbmV4cG9ydCB7IFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD16eGluZy1odG1sNS1xcmNvZGUtZGVjb2Rlci5qcy5tYXAiLCJ2YXIgX19hd2FpdGVyID0gKHRoaXMgJiYgdGhpcy5fX2F3YWl0ZXIpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcbiAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH1cbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xuICAgIH0pO1xufTtcbnZhciBfX2dlbmVyYXRvciA9ICh0aGlzICYmIHRoaXMuX19nZW5lcmF0b3IpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBib2R5KSB7XG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZztcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cbiAgICBmdW5jdGlvbiBzdGVwKG9wKSB7XG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcbiAgICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHtcbiAgICAgICAgICAgIGlmIChmID0gMSwgeSAmJiAodCA9IG9wWzBdICYgMiA/IHlbXCJyZXR1cm5cIl0gOiBvcFswXSA/IHlbXCJ0aHJvd1wiXSB8fCAoKHQgPSB5W1wicmV0dXJuXCJdKSAmJiB0LmNhbGwoeSksIDApIDogeS5uZXh0KSAmJiAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKSByZXR1cm4gdDtcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xuICAgIH1cbn07XG5pbXBvcnQgeyBRcmNvZGVSZXN1bHRGb3JtYXQsIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyB9IGZyb20gXCIuL2NvcmVcIjtcbnZhciBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQmFyY29kZURldGVjdG9yRGVsZWdhdGUocmVxdWVzdGVkRm9ybWF0cywgdmVyYm9zZSwgbG9nZ2VyKSB7XG4gICAgICAgIHRoaXMuZm9ybWF0TWFwID0gbmV3IE1hcChbXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlFSX0NPREUsIFwicXJfY29kZVwiXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQVpURUMsIFwiYXp0ZWNcIl0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREFCQVIsIFwiY29kYWJhclwiXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQ09ERV8zOSwgXCJjb2RlXzM5XCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzkzLCBcImNvZGVfOTNcIl0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfMTI4LCBcImNvZGVfMTI4XCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5EQVRBX01BVFJJWCwgXCJkYXRhX21hdHJpeFwiXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuSVRGLCBcIml0ZlwiXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuRUFOXzEzLCBcImVhbl8xM1wiXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuRUFOXzgsIFwiZWFuXzhcIl0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlBERl80MTcsIFwicGRmNDE3XCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5VUENfQSwgXCJ1cGNfYVwiXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0UsIFwidXBjX2VcIl1cbiAgICAgICAgXSk7XG4gICAgICAgIHRoaXMucmV2ZXJzZUZvcm1hdE1hcCA9IHRoaXMuY3JlYXRlUmV2ZXJzZUZvcm1hdE1hcCgpO1xuICAgICAgICBpZiAoIUJhcmNvZGVEZXRlY3RvckRlbGVnYXRlLmlzU3VwcG9ydGVkKCkpIHtcbiAgICAgICAgICAgIHRocm93IFwiVXNlIGh0bWw1cXJjb2RlLm1pbi5qcyB3aXRob3V0IGVkaXQsIFVzZSBcIlxuICAgICAgICAgICAgICAgICsgXCJCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZSBvbmx5IGlmIGl0IGlzU3VwcG9ydGVkKCk7XCI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy52ZXJib3NlID0gdmVyYm9zZTtcbiAgICAgICAgdGhpcy5sb2dnZXIgPSBsb2dnZXI7XG4gICAgICAgIHZhciBmb3JtYXRzID0gdGhpcy5jcmVhdGVCYXJjb2RlRGV0ZWN0b3JGb3JtYXRzKHJlcXVlc3RlZEZvcm1hdHMpO1xuICAgICAgICB0aGlzLmRldGVjdG9yID0gbmV3IEJhcmNvZGVEZXRlY3Rvcihmb3JtYXRzKTtcbiAgICAgICAgaWYgKCF0aGlzLmRldGVjdG9yKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkJhcmNvZGVEZXRlY3RvciBkZXRlY3RvciBub3Qgc3VwcG9ydGVkXCI7XG4gICAgICAgIH1cbiAgICB9XG4gICAgQmFyY29kZURldGVjdG9yRGVsZWdhdGUuaXNTdXBwb3J0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghKFwiQmFyY29kZURldGVjdG9yXCIgaW4gd2luZG93KSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBkdW1teURldGVjdG9yID0gbmV3IEJhcmNvZGVEZXRlY3Rvcih7IGZvcm1hdHM6IFtcInFyX2NvZGVcIl0gfSk7XG4gICAgICAgIHJldHVybiB0eXBlb2YgZHVtbXlEZXRlY3RvciAhPT0gXCJ1bmRlZmluZWRcIjtcbiAgICB9O1xuICAgIEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlLnByb3RvdHlwZS5kZWNvZGVBc3luYyA9IGZ1bmN0aW9uIChjYW52YXMpIHtcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGJhcmNvZGVzLCBsYXJnZXN0QmFyY29kZTtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDogcmV0dXJuIFs0LCB0aGlzLmRldGVjdG9yLmRldGVjdChjYW52YXMpXTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgYmFyY29kZXMgPSBfYS5zZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWJhcmNvZGVzIHx8IGJhcmNvZGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFwiTm8gYmFyY29kZSBvciBRUiBjb2RlIGRldGVjdGVkLlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgbGFyZ2VzdEJhcmNvZGUgPSB0aGlzLnNlbGVjdExhcmdlc3RCYXJjb2RlKGJhcmNvZGVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0OiBsYXJnZXN0QmFyY29kZS5yYXdWYWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0OiBRcmNvZGVSZXN1bHRGb3JtYXQuY3JlYXRlKHRoaXMudG9IdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMobGFyZ2VzdEJhcmNvZGUuZm9ybWF0KSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlYnVnRGF0YTogdGhpcy5jcmVhdGVEZWJ1Z0RhdGEoKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1dO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlLnByb3RvdHlwZS5zZWxlY3RMYXJnZXN0QmFyY29kZSA9IGZ1bmN0aW9uIChiYXJjb2Rlcykge1xuICAgICAgICB2YXIgbGFyZ2VzdEJhcmNvZGUgPSBudWxsO1xuICAgICAgICB2YXIgbWF4QXJlYSA9IDA7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgYmFyY29kZXNfMSA9IGJhcmNvZGVzOyBfaSA8IGJhcmNvZGVzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgYmFyY29kZSA9IGJhcmNvZGVzXzFbX2ldO1xuICAgICAgICAgICAgdmFyIGFyZWEgPSBiYXJjb2RlLmJvdW5kaW5nQm94LndpZHRoICogYmFyY29kZS5ib3VuZGluZ0JveC5oZWlnaHQ7XG4gICAgICAgICAgICBpZiAoYXJlYSA+IG1heEFyZWEpIHtcbiAgICAgICAgICAgICAgICBtYXhBcmVhID0gYXJlYTtcbiAgICAgICAgICAgICAgICBsYXJnZXN0QmFyY29kZSA9IGJhcmNvZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFsYXJnZXN0QmFyY29kZSkge1xuICAgICAgICAgICAgdGhyb3cgXCJObyBsYXJnZXN0IGJhcmNvZGUgZm91bmRcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbGFyZ2VzdEJhcmNvZGU7XG4gICAgfTtcbiAgICBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZS5wcm90b3R5cGUuY3JlYXRlQmFyY29kZURldGVjdG9yRm9ybWF0cyA9IGZ1bmN0aW9uIChyZXF1ZXN0ZWRGb3JtYXRzKSB7XG4gICAgICAgIHZhciBmb3JtYXRzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgcmVxdWVzdGVkRm9ybWF0c18xID0gcmVxdWVzdGVkRm9ybWF0czsgX2kgPCByZXF1ZXN0ZWRGb3JtYXRzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgcmVxdWVzdGVkRm9ybWF0ID0gcmVxdWVzdGVkRm9ybWF0c18xW19pXTtcbiAgICAgICAgICAgIGlmICh0aGlzLmZvcm1hdE1hcC5oYXMocmVxdWVzdGVkRm9ybWF0KSkge1xuICAgICAgICAgICAgICAgIGZvcm1hdHMucHVzaCh0aGlzLmZvcm1hdE1hcC5nZXQocmVxdWVzdGVkRm9ybWF0KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci53YXJuKFwiXCIuY29uY2F0KHJlcXVlc3RlZEZvcm1hdCwgXCIgaXMgbm90IHN1cHBvcnRlZCBieVwiKVxuICAgICAgICAgICAgICAgICAgICArIFwiQmFyY29kZURldGVjdG9yRGVsZWdhdGVcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgZm9ybWF0czogZm9ybWF0cyB9O1xuICAgIH07XG4gICAgQmFyY29kZURldGVjdG9yRGVsZWdhdGUucHJvdG90eXBlLnRvSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzID0gZnVuY3Rpb24gKGJhcmNvZGVEZXRlY3RvckZvcm1hdCkge1xuICAgICAgICBpZiAoIXRoaXMucmV2ZXJzZUZvcm1hdE1hcC5oYXMoYmFyY29kZURldGVjdG9yRm9ybWF0KSkge1xuICAgICAgICAgICAgdGhyb3cgXCJyZXZlcnNlRm9ybWF0TWFwIGRvZXNuJ3QgaGF2ZSBcIi5jb25jYXQoYmFyY29kZURldGVjdG9yRm9ybWF0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5yZXZlcnNlRm9ybWF0TWFwLmdldChiYXJjb2RlRGV0ZWN0b3JGb3JtYXQpO1xuICAgIH07XG4gICAgQmFyY29kZURldGVjdG9yRGVsZWdhdGUucHJvdG90eXBlLmNyZWF0ZVJldmVyc2VGb3JtYXRNYXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMuZm9ybWF0TWFwLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlLCBrZXksIF8pIHtcbiAgICAgICAgICAgIHJlc3VsdC5zZXQodmFsdWUsIGtleSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgQmFyY29kZURldGVjdG9yRGVsZWdhdGUucHJvdG90eXBlLmNyZWF0ZURlYnVnRGF0YSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHsgZGVjb2Rlck5hbWU6IFwiQmFyY29kZURldGVjdG9yXCIgfTtcbiAgICB9O1xuICAgIHJldHVybiBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZTtcbn0oKSk7XG5leHBvcnQgeyBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZSB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9bmF0aXZlLWJhci1jb2RlLWRldGVjdG9yLmpzLm1hcCIsInZhciBfX2F3YWl0ZXIgPSAodGhpcyAmJiB0aGlzLl9fYXdhaXRlcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xuICAgIGZ1bmN0aW9uIGFkb3B0KHZhbHVlKSB7IHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUodmFsdWUpOyB9KTsgfVxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IGFkb3B0KHJlc3VsdC52YWx1ZSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XG4gICAgfSk7XG59O1xudmFyIF9fZ2VuZXJhdG9yID0gKHRoaXMgJiYgdGhpcy5fX2dlbmVyYXRvcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIGJvZHkpIHtcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xuICAgIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcbiAgICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xuICAgICAgICB3aGlsZSAoZyAmJiAoZyA9IDAsIG9wWzBdICYmIChfID0gMCkpLCBfKSB0cnkge1xuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xuICAgICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XG4gICAgfVxufTtcbmltcG9ydCB7IFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyIH0gZnJvbSBcIi4venhpbmctaHRtbDUtcXJjb2RlLWRlY29kZXJcIjtcbmltcG9ydCB7IEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlIH0gZnJvbSBcIi4vbmF0aXZlLWJhci1jb2RlLWRldGVjdG9yXCI7XG52YXIgSHRtbDVRcmNvZGVTaGltID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBIdG1sNVFyY29kZVNoaW0ocmVxdWVzdGVkRm9ybWF0cywgdXNlQmFyQ29kZURldGVjdG9ySWZTdXBwb3J0ZWQsIHZlcmJvc2UsIGxvZ2dlcikge1xuICAgICAgICB0aGlzLkVYRUNVVElPTlNfVE9fUkVQT1JUX1BFUkZPUk1BTkNFID0gMTAwO1xuICAgICAgICB0aGlzLmV4ZWN1dGlvbnMgPSAwO1xuICAgICAgICB0aGlzLmV4ZWN1dGlvblJlc3VsdHMgPSBbXTtcbiAgICAgICAgdGhpcy53YXNQcmltYXJ5RGVjb2RlclVzZWRJbkxhc3REZWNvZGUgPSBmYWxzZTtcbiAgICAgICAgdGhpcy52ZXJib3NlID0gdmVyYm9zZTtcbiAgICAgICAgaWYgKHVzZUJhckNvZGVEZXRlY3RvcklmU3VwcG9ydGVkXG4gICAgICAgICAgICAmJiBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZS5pc1N1cHBvcnRlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLnByaW1hcnlEZWNvZGVyID0gbmV3IEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlKHJlcXVlc3RlZEZvcm1hdHMsIHZlcmJvc2UsIGxvZ2dlcik7XG4gICAgICAgICAgICB0aGlzLnNlY29uZGFyeURlY29kZXIgPSBuZXcgWlhpbmdIdG1sNVFyY29kZURlY29kZXIocmVxdWVzdGVkRm9ybWF0cywgdmVyYm9zZSwgbG9nZ2VyKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucHJpbWFyeURlY29kZXIgPSBuZXcgWlhpbmdIdG1sNVFyY29kZURlY29kZXIocmVxdWVzdGVkRm9ybWF0cywgdmVyYm9zZSwgbG9nZ2VyKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBIdG1sNVFyY29kZVNoaW0ucHJvdG90eXBlLmRlY29kZUFzeW5jID0gZnVuY3Rpb24gKGNhbnZhcykge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc3RhcnRUaW1lO1xuICAgICAgICAgICAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoX2EubGFiZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfYS5sYWJlbCA9IDE7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLnRyeXMucHVzaChbMSwgLCAzLCA0XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQsIHRoaXMuZ2V0RGVjb2RlcigpLmRlY29kZUFzeW5jKGNhbnZhcyldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6IHJldHVybiBbMiwgX2Euc2VudCgpXTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wb3NzaWJseUxvZ1BlcmZvcm1hbmNlKHN0YXJ0VGltZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzddO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6IHJldHVybiBbMl07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTaGltLnByb3RvdHlwZS5kZWNvZGVSb2J1c3RseUFzeW5jID0gZnVuY3Rpb24gKGNhbnZhcykge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc3RhcnRUaW1lLCBlcnJvcl8xO1xuICAgICAgICAgICAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoX2EubGFiZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfYS5sYWJlbCA9IDE7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLnRyeXMucHVzaChbMSwgMywgNCwgNV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFs0LCB0aGlzLnByaW1hcnlEZWNvZGVyLmRlY29kZUFzeW5jKGNhbnZhcyldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6IHJldHVybiBbMiwgX2Euc2VudCgpXTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JfMSA9IF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlY29uZGFyeURlY29kZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIsIHRoaXMuc2Vjb25kYXJ5RGVjb2Rlci5kZWNvZGVBc3luYyhjYW52YXMpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGVycm9yXzE7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucG9zc2libHlMb2dQZXJmb3JtYW5jZShzdGFydFRpbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFs3XTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA1OiByZXR1cm4gWzJdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2hpbS5wcm90b3R5cGUuZ2V0RGVjb2RlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNlY29uZGFyeURlY29kZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnByaW1hcnlEZWNvZGVyO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLndhc1ByaW1hcnlEZWNvZGVyVXNlZEluTGFzdERlY29kZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHRoaXMud2FzUHJpbWFyeURlY29kZXJVc2VkSW5MYXN0RGVjb2RlID0gdHJ1ZTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnByaW1hcnlEZWNvZGVyO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMud2FzUHJpbWFyeURlY29kZXJVc2VkSW5MYXN0RGVjb2RlID0gZmFsc2U7XG4gICAgICAgIHJldHVybiB0aGlzLnNlY29uZGFyeURlY29kZXI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNoaW0ucHJvdG90eXBlLnBvc3NpYmx5TG9nUGVyZm9ybWFuY2UgPSBmdW5jdGlvbiAoc3RhcnRUaW1lKSB7XG4gICAgICAgIGlmICghdGhpcy52ZXJib3NlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGV4ZWN1dGlvblRpbWUgPSBwZXJmb3JtYW5jZS5ub3coKSAtIHN0YXJ0VGltZTtcbiAgICAgICAgdGhpcy5leGVjdXRpb25SZXN1bHRzLnB1c2goZXhlY3V0aW9uVGltZSk7XG4gICAgICAgIHRoaXMuZXhlY3V0aW9ucysrO1xuICAgICAgICB0aGlzLnBvc3NpYmx5Rmx1c2hQZXJmb3JtYW5jZVJlcG9ydCgpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTaGltLnByb3RvdHlwZS5wb3NzaWJseUZsdXNoUGVyZm9ybWFuY2VSZXBvcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmV4ZWN1dGlvbnMgPCB0aGlzLkVYRUNVVElPTlNfVE9fUkVQT1JUX1BFUkZPUk1BTkNFKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHN1bSA9IDA7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLmV4ZWN1dGlvblJlc3VsdHM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgZXhlY3V0aW9uVGltZSA9IF9hW19pXTtcbiAgICAgICAgICAgIHN1bSArPSBleGVjdXRpb25UaW1lO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtZWFuID0gc3VtIC8gdGhpcy5leGVjdXRpb25SZXN1bHRzLmxlbmd0aDtcbiAgICAgICAgY29uc29sZS5sb2coXCJcIi5jb25jYXQobWVhbiwgXCIgbXMgZm9yIFwiKS5jb25jYXQodGhpcy5leGVjdXRpb25SZXN1bHRzLmxlbmd0aCwgXCIgbGFzdCBydW5zLlwiKSk7XG4gICAgICAgIHRoaXMuZXhlY3V0aW9ucyA9IDA7XG4gICAgICAgIHRoaXMuZXhlY3V0aW9uUmVzdWx0cyA9IFtdO1xuICAgIH07XG4gICAgcmV0dXJuIEh0bWw1UXJjb2RlU2hpbTtcbn0oKSk7XG5leHBvcnQgeyBIdG1sNVFyY29kZVNoaW0gfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWNvZGUtZGVjb2Rlci5qcy5tYXAiLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcbiAgICB9KTtcbn07XG52YXIgX19nZW5lcmF0b3IgPSAodGhpcyAmJiB0aGlzLl9fZ2VuZXJhdG9yKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgYm9keSkge1xuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XG4gICAgICAgIHdoaWxlIChnICYmIChnID0gMCwgb3BbMF0gJiYgKF8gPSAwKSksIF8pIHRyeSB7XG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcbiAgICB9XG59O1xudmFyIEFic3RyYWN0Q2FtZXJhQ2FwYWJpbGl0eSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQWJzdHJhY3RDYW1lcmFDYXBhYmlsaXR5KG5hbWUsIHRyYWNrKSB7XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMudHJhY2sgPSB0cmFjaztcbiAgICB9XG4gICAgQWJzdHJhY3RDYW1lcmFDYXBhYmlsaXR5LnByb3RvdHlwZS5pc1N1cHBvcnRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnRyYWNrLmdldENhcGFiaWxpdGllcykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLm5hbWUgaW4gdGhpcy50cmFjay5nZXRDYXBhYmlsaXRpZXMoKTtcbiAgICB9O1xuICAgIEFic3RyYWN0Q2FtZXJhQ2FwYWJpbGl0eS5wcm90b3R5cGUuYXBwbHkgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgdmFyIGNvbnN0cmFpbnQgPSB7fTtcbiAgICAgICAgY29uc3RyYWludFt0aGlzLm5hbWVdID0gdmFsdWU7XG4gICAgICAgIHZhciBjb25zdHJhaW50cyA9IHsgYWR2YW5jZWQ6IFtjb25zdHJhaW50XSB9O1xuICAgICAgICByZXR1cm4gdGhpcy50cmFjay5hcHBseUNvbnN0cmFpbnRzKGNvbnN0cmFpbnRzKTtcbiAgICB9O1xuICAgIEFic3RyYWN0Q2FtZXJhQ2FwYWJpbGl0eS5wcm90b3R5cGUudmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzZXR0aW5ncyA9IHRoaXMudHJhY2suZ2V0U2V0dGluZ3MoKTtcbiAgICAgICAgaWYgKHRoaXMubmFtZSBpbiBzZXR0aW5ncykge1xuICAgICAgICAgICAgdmFyIHNldHRpbmdWYWx1ZSA9IHNldHRpbmdzW3RoaXMubmFtZV07XG4gICAgICAgICAgICByZXR1cm4gc2V0dGluZ1ZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgcmV0dXJuIEFic3RyYWN0Q2FtZXJhQ2FwYWJpbGl0eTtcbn0oKSk7XG52YXIgQWJzdHJhY3RSYW5nZUNhbWVyYUNhcGFiaWxpdHkgPSAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhBYnN0cmFjdFJhbmdlQ2FtZXJhQ2FwYWJpbGl0eSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBBYnN0cmFjdFJhbmdlQ2FtZXJhQ2FwYWJpbGl0eShuYW1lLCB0cmFjaykge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgbmFtZSwgdHJhY2spIHx8IHRoaXM7XG4gICAgfVxuICAgIEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5LnByb3RvdHlwZS5taW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENhcGFiaWxpdGllcygpLm1pbjtcbiAgICB9O1xuICAgIEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5LnByb3RvdHlwZS5tYXggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENhcGFiaWxpdGllcygpLm1heDtcbiAgICB9O1xuICAgIEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5LnByb3RvdHlwZS5zdGVwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRDYXBhYmlsaXRpZXMoKS5zdGVwO1xuICAgIH07XG4gICAgQWJzdHJhY3RSYW5nZUNhbWVyYUNhcGFiaWxpdHkucHJvdG90eXBlLmFwcGx5ID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHZhciBjb25zdHJhaW50ID0ge307XG4gICAgICAgIGNvbnN0cmFpbnRbdGhpcy5uYW1lXSA9IHZhbHVlO1xuICAgICAgICB2YXIgY29uc3RyYWludHMgPSB7IGFkdmFuY2VkOiBbY29uc3RyYWludF0gfTtcbiAgICAgICAgcmV0dXJuIHRoaXMudHJhY2suYXBwbHlDb25zdHJhaW50cyhjb25zdHJhaW50cyk7XG4gICAgfTtcbiAgICBBYnN0cmFjdFJhbmdlQ2FtZXJhQ2FwYWJpbGl0eS5wcm90b3R5cGUuZ2V0Q2FwYWJpbGl0aWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZhaWxJZk5vdFN1cHBvcnRlZCgpO1xuICAgICAgICB2YXIgY2FwYWJpbGl0aWVzID0gdGhpcy50cmFjay5nZXRDYXBhYmlsaXRpZXMoKTtcbiAgICAgICAgdmFyIGNhcGFiaWxpdHkgPSBjYXBhYmlsaXRpZXNbdGhpcy5uYW1lXTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG1pbjogY2FwYWJpbGl0eS5taW4sXG4gICAgICAgICAgICBtYXg6IGNhcGFiaWxpdHkubWF4LFxuICAgICAgICAgICAgc3RlcDogY2FwYWJpbGl0eS5zdGVwLFxuICAgICAgICB9O1xuICAgIH07XG4gICAgQWJzdHJhY3RSYW5nZUNhbWVyYUNhcGFiaWxpdHkucHJvdG90eXBlLmZhaWxJZk5vdFN1cHBvcnRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzU3VwcG9ydGVkKCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlwiLmNvbmNhdCh0aGlzLm5hbWUsIFwiIGNhcGFiaWxpdHkgbm90IHN1cHBvcnRlZFwiKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBBYnN0cmFjdFJhbmdlQ2FtZXJhQ2FwYWJpbGl0eTtcbn0oQWJzdHJhY3RDYW1lcmFDYXBhYmlsaXR5KSk7XG52YXIgWm9vbUZlYXR1cmVJbXBsID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoWm9vbUZlYXR1cmVJbXBsLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFpvb21GZWF0dXJlSW1wbCh0cmFjaykge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgXCJ6b29tXCIsIHRyYWNrKSB8fCB0aGlzO1xuICAgIH1cbiAgICByZXR1cm4gWm9vbUZlYXR1cmVJbXBsO1xufShBYnN0cmFjdFJhbmdlQ2FtZXJhQ2FwYWJpbGl0eSkpO1xudmFyIFRvcmNoRmVhdHVyZUltcGwgPSAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhUb3JjaEZlYXR1cmVJbXBsLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFRvcmNoRmVhdHVyZUltcGwodHJhY2spIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlci5jYWxsKHRoaXMsIFwidG9yY2hcIiwgdHJhY2spIHx8IHRoaXM7XG4gICAgfVxuICAgIHJldHVybiBUb3JjaEZlYXR1cmVJbXBsO1xufShBYnN0cmFjdENhbWVyYUNhcGFiaWxpdHkpKTtcbnZhciBDYW1lcmFDYXBhYmlsaXRpZXNJbXBsID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDYW1lcmFDYXBhYmlsaXRpZXNJbXBsKHRyYWNrKSB7XG4gICAgICAgIHRoaXMudHJhY2sgPSB0cmFjaztcbiAgICB9XG4gICAgQ2FtZXJhQ2FwYWJpbGl0aWVzSW1wbC5wcm90b3R5cGUuem9vbUZlYXR1cmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBuZXcgWm9vbUZlYXR1cmVJbXBsKHRoaXMudHJhY2spO1xuICAgIH07XG4gICAgQ2FtZXJhQ2FwYWJpbGl0aWVzSW1wbC5wcm90b3R5cGUudG9yY2hGZWF0dXJlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gbmV3IFRvcmNoRmVhdHVyZUltcGwodGhpcy50cmFjayk7XG4gICAgfTtcbiAgICByZXR1cm4gQ2FtZXJhQ2FwYWJpbGl0aWVzSW1wbDtcbn0oKSk7XG52YXIgUmVuZGVyZWRDYW1lcmFJbXBsID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBSZW5kZXJlZENhbWVyYUltcGwocGFyZW50RWxlbWVudCwgbWVkaWFTdHJlYW0sIGNhbGxiYWNrcykge1xuICAgICAgICB0aGlzLmlzQ2xvc2VkID0gZmFsc2U7XG4gICAgICAgIHRoaXMucGFyZW50RWxlbWVudCA9IHBhcmVudEVsZW1lbnQ7XG4gICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSBtZWRpYVN0cmVhbTtcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSBjYWxsYmFja3M7XG4gICAgICAgIHRoaXMuc3VyZmFjZSA9IHRoaXMuY3JlYXRlVmlkZW9FbGVtZW50KHRoaXMucGFyZW50RWxlbWVudC5jbGllbnRXaWR0aCk7XG4gICAgICAgIHBhcmVudEVsZW1lbnQuYXBwZW5kKHRoaXMuc3VyZmFjZSk7XG4gICAgfVxuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5wcm90b3R5cGUuY3JlYXRlVmlkZW9FbGVtZW50ID0gZnVuY3Rpb24gKHdpZHRoKSB7XG4gICAgICAgIHZhciB2aWRlb0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwidmlkZW9cIik7XG4gICAgICAgIHZpZGVvRWxlbWVudC5zdHlsZS53aWR0aCA9IFwiXCIuY29uY2F0KHdpZHRoLCBcInB4XCIpO1xuICAgICAgICB2aWRlb0VsZW1lbnQuc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIjtcbiAgICAgICAgdmlkZW9FbGVtZW50Lm11dGVkID0gdHJ1ZTtcbiAgICAgICAgdmlkZW9FbGVtZW50LnNldEF0dHJpYnV0ZShcIm11dGVkXCIsIFwidHJ1ZVwiKTtcbiAgICAgICAgdmlkZW9FbGVtZW50LnBsYXlzSW5saW5lID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHZpZGVvRWxlbWVudDtcbiAgICB9O1xuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5wcm90b3R5cGUuc2V0dXBTdXJmYWNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnN1cmZhY2Uub25hYm9ydCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRocm93IFwiUmVuZGVyZWRDYW1lcmFJbXBsIHZpZGVvIHN1cmZhY2Ugb25hYm9ydCgpIGNhbGxlZFwiO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnN1cmZhY2Uub25lcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRocm93IFwiUmVuZGVyZWRDYW1lcmFJbXBsIHZpZGVvIHN1cmZhY2Ugb25lcnJvcigpIGNhbGxlZFwiO1xuICAgICAgICB9O1xuICAgICAgICB2YXIgb25WaWRlb1N0YXJ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHZpZGVvV2lkdGggPSBfdGhpcy5zdXJmYWNlLmNsaWVudFdpZHRoO1xuICAgICAgICAgICAgdmFyIHZpZGVvSGVpZ2h0ID0gX3RoaXMuc3VyZmFjZS5jbGllbnRIZWlnaHQ7XG4gICAgICAgICAgICBfdGhpcy5jYWxsYmFja3Mub25SZW5kZXJTdXJmYWNlUmVhZHkodmlkZW9XaWR0aCwgdmlkZW9IZWlnaHQpO1xuICAgICAgICAgICAgX3RoaXMuc3VyZmFjZS5yZW1vdmVFdmVudExpc3RlbmVyKFwicGxheWluZ1wiLCBvblZpZGVvU3RhcnQpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnN1cmZhY2UuYWRkRXZlbnRMaXN0ZW5lcihcInBsYXlpbmdcIiwgb25WaWRlb1N0YXJ0KTtcbiAgICAgICAgdGhpcy5zdXJmYWNlLnNyY09iamVjdCA9IHRoaXMubWVkaWFTdHJlYW07XG4gICAgICAgIHRoaXMuc3VyZmFjZS5wbGF5KCk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwuY3JlYXRlID0gZnVuY3Rpb24gKHBhcmVudEVsZW1lbnQsIG1lZGlhU3RyZWFtLCBvcHRpb25zLCBjYWxsYmFja3MpIHtcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHJlbmRlcmVkQ2FtZXJhLCBhc3BlY3RSYXRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChfYS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJlZENhbWVyYSA9IG5ldyBSZW5kZXJlZENhbWVyYUltcGwocGFyZW50RWxlbWVudCwgbWVkaWFTdHJlYW0sIGNhbGxiYWNrcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW9wdGlvbnMuYXNwZWN0UmF0aW8pIHJldHVybiBbMywgMl07XG4gICAgICAgICAgICAgICAgICAgICAgICBhc3BlY3RSYXRpb0NvbnN0cmFpbnQgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNwZWN0UmF0aW86IG9wdGlvbnMuYXNwZWN0UmF0aW9cbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQsIHJlbmRlcmVkQ2FtZXJhLmdldEZpcnN0VHJhY2tPckZhaWwoKS5hcHBseUNvbnN0cmFpbnRzKGFzcGVjdFJhdGlvQ29uc3RyYWludCldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBfYS5zZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBfYS5sYWJlbCA9IDI7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQ2FtZXJhLnNldHVwU3VyZmFjZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyLCByZW5kZXJlZENhbWVyYV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUmVuZGVyZWRDYW1lcmFJbXBsLnByb3RvdHlwZS5mYWlsSWZDbG9zZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmlzQ2xvc2VkKSB7XG4gICAgICAgICAgICB0aHJvdyBcIlRoZSBSZW5kZXJlZENhbWVyYSBoYXMgYWxyZWFkeSBiZWVuIGNsb3NlZC5cIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUmVuZGVyZWRDYW1lcmFJbXBsLnByb3RvdHlwZS5nZXRGaXJzdFRyYWNrT3JGYWlsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZhaWxJZkNsb3NlZCgpO1xuICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgXCJObyB2aWRlbyB0cmFja3MgZm91bmRcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5tZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgIH07XG4gICAgUmVuZGVyZWRDYW1lcmFJbXBsLnByb3RvdHlwZS5wYXVzZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5mYWlsSWZDbG9zZWQoKTtcbiAgICAgICAgdGhpcy5zdXJmYWNlLnBhdXNlKCk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLnJlc3VtZSA9IGZ1bmN0aW9uIChvblJlc3VtZUNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMuZmFpbElmQ2xvc2VkKCk7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBvblZpZGVvUmVzdW1lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc2V0VGltZW91dChvblJlc3VtZUNhbGxiYWNrLCAyMDApO1xuICAgICAgICAgICAgJHRoaXMuc3VyZmFjZS5yZW1vdmVFdmVudExpc3RlbmVyKFwicGxheWluZ1wiLCBvblZpZGVvUmVzdW1lKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5zdXJmYWNlLmFkZEV2ZW50TGlzdGVuZXIoXCJwbGF5aW5nXCIsIG9uVmlkZW9SZXN1bWUpO1xuICAgICAgICB0aGlzLnN1cmZhY2UucGxheSgpO1xuICAgIH07XG4gICAgUmVuZGVyZWRDYW1lcmFJbXBsLnByb3RvdHlwZS5pc1BhdXNlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5mYWlsSWZDbG9zZWQoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3VyZmFjZS5wYXVzZWQ7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmdldFN1cmZhY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZmFpbElmQ2xvc2VkKCk7XG4gICAgICAgIHJldHVybiB0aGlzLnN1cmZhY2U7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmdldFJ1bm5pbmdUcmFja0NhcGFiaWxpdGllcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Rmlyc3RUcmFja09yRmFpbCgpLmdldENhcGFiaWxpdGllcygpO1xuICAgIH07XG4gICAgUmVuZGVyZWRDYW1lcmFJbXBsLnByb3RvdHlwZS5nZXRSdW5uaW5nVHJhY2tTZXR0aW5ncyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Rmlyc3RUcmFja09yRmFpbCgpLmdldFNldHRpbmdzKCk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmFwcGx5VmlkZW9Db25zdHJhaW50cyA9IGZ1bmN0aW9uIChjb25zdHJhaW50cykge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgaWYgKFwiYXNwZWN0UmF0aW9cIiBpbiBjb25zdHJhaW50cykge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBcIkNoYW5naW5nICdhc3BlY3RSYXRpbycgaW4gcnVuLXRpbWUgaXMgbm90IHlldCBzdXBwb3J0ZWQuXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBbMiwgdGhpcy5nZXRGaXJzdFRyYWNrT3JGYWlsKCkuYXBwbHlDb25zdHJhaW50cyhjb25zdHJhaW50cyldO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUmVuZGVyZWRDYW1lcmFJbXBsLnByb3RvdHlwZS5jbG9zZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNDbG9zZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIF8pIHtcbiAgICAgICAgICAgIHZhciB0cmFja3MgPSAkdGhpcy5tZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpO1xuICAgICAgICAgICAgdmFyIHRyYWNrc1RvQ2xvc2UgPSB0cmFja3MubGVuZ3RoO1xuICAgICAgICAgICAgdmFyIHRyYWNrc0Nsb3NlZCA9IDA7XG4gICAgICAgICAgICAkdGhpcy5tZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goZnVuY3Rpb24gKHZpZGVvVHJhY2spIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5tZWRpYVN0cmVhbS5yZW1vdmVUcmFjayh2aWRlb1RyYWNrKTtcbiAgICAgICAgICAgICAgICB2aWRlb1RyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICArK3RyYWNrc0Nsb3NlZDtcbiAgICAgICAgICAgICAgICBpZiAodHJhY2tzQ2xvc2VkID49IHRyYWNrc1RvQ2xvc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMuaXNDbG9zZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5wYXJlbnRFbGVtZW50LnJlbW92ZUNoaWxkKCR0aGlzLnN1cmZhY2UpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUmVuZGVyZWRDYW1lcmFJbXBsLnByb3RvdHlwZS5nZXRDYXBhYmlsaXRpZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBuZXcgQ2FtZXJhQ2FwYWJpbGl0aWVzSW1wbCh0aGlzLmdldEZpcnN0VHJhY2tPckZhaWwoKSk7XG4gICAgfTtcbiAgICByZXR1cm4gUmVuZGVyZWRDYW1lcmFJbXBsO1xufSgpKTtcbnZhciBDYW1lcmFJbXBsID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDYW1lcmFJbXBsKG1lZGlhU3RyZWFtKSB7XG4gICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSBtZWRpYVN0cmVhbTtcbiAgICB9XG4gICAgQ2FtZXJhSW1wbC5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHBhcmVudEVsZW1lbnQsIG9wdGlvbnMsIGNhbGxiYWNrcykge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFsyLCBSZW5kZXJlZENhbWVyYUltcGwuY3JlYXRlKHBhcmVudEVsZW1lbnQsIHRoaXMubWVkaWFTdHJlYW0sIG9wdGlvbnMsIGNhbGxiYWNrcyldO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ2FtZXJhSW1wbC5jcmVhdGUgPSBmdW5jdGlvbiAodmlkZW9Db25zdHJhaW50cykge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgY29uc3RyYWludHMsIG1lZGlhU3RyZWFtO1xuICAgICAgICAgICAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoX2EubGFiZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFuYXZpZ2F0b3IubWVkaWFEZXZpY2VzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgXCJuYXZpZ2F0b3IubWVkaWFEZXZpY2VzIG5vdCBzdXBwb3J0ZWRcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWRlbzogdmlkZW9Db25zdHJhaW50c1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbNCwgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoY29uc3RyYWludHMpXTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0gPSBfYS5zZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIsIG5ldyBDYW1lcmFJbXBsKG1lZGlhU3RyZWFtKV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgcmV0dXJuIENhbWVyYUltcGw7XG59KCkpO1xuZXhwb3J0IHsgQ2FtZXJhSW1wbCB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y29yZS1pbXBsLmpzLm1hcCIsInZhciBfX2F3YWl0ZXIgPSAodGhpcyAmJiB0aGlzLl9fYXdhaXRlcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xuICAgIGZ1bmN0aW9uIGFkb3B0KHZhbHVlKSB7IHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUodmFsdWUpOyB9KTsgfVxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IGFkb3B0KHJlc3VsdC52YWx1ZSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XG4gICAgfSk7XG59O1xudmFyIF9fZ2VuZXJhdG9yID0gKHRoaXMgJiYgdGhpcy5fX2dlbmVyYXRvcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIGJvZHkpIHtcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xuICAgIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcbiAgICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xuICAgICAgICB3aGlsZSAoZyAmJiAoZyA9IDAsIG9wWzBdICYmIChfID0gMCkpLCBfKSB0cnkge1xuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xuICAgICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XG4gICAgfVxufTtcbmltcG9ydCB7IENhbWVyYUltcGwgfSBmcm9tIFwiLi9jb3JlLWltcGxcIjtcbnZhciBDYW1lcmFGYWN0b3J5ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDYW1lcmFGYWN0b3J5KCkge1xuICAgIH1cbiAgICBDYW1lcmFGYWN0b3J5LmZhaWxJZk5vdFN1cHBvcnRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgIGlmICghbmF2aWdhdG9yLm1lZGlhRGV2aWNlcykge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBcIm5hdmlnYXRvci5tZWRpYURldmljZXMgbm90IHN1cHBvcnRlZFwiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gWzIsIG5ldyBDYW1lcmFGYWN0b3J5KCldO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ2FtZXJhRmFjdG9yeS5wcm90b3R5cGUuY3JlYXRlID0gZnVuY3Rpb24gKHZpZGVvQ29uc3RyYWludHMpIHtcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBbMiwgQ2FtZXJhSW1wbC5jcmVhdGUodmlkZW9Db25zdHJhaW50cyldO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgcmV0dXJuIENhbWVyYUZhY3Rvcnk7XG59KCkpO1xuZXhwb3J0IHsgQ2FtZXJhRmFjdG9yeSB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZmFjdG9yaWVzLmpzLm1hcCIsInZhciBfX2F3YWl0ZXIgPSAodGhpcyAmJiB0aGlzLl9fYXdhaXRlcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xuICAgIGZ1bmN0aW9uIGFkb3B0KHZhbHVlKSB7IHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUodmFsdWUpOyB9KTsgfVxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IGFkb3B0KHJlc3VsdC52YWx1ZSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XG4gICAgfSk7XG59O1xudmFyIF9fZ2VuZXJhdG9yID0gKHRoaXMgJiYgdGhpcy5fX2dlbmVyYXRvcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIGJvZHkpIHtcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xuICAgIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcbiAgICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xuICAgICAgICB3aGlsZSAoZyAmJiAoZyA9IDAsIG9wWzBdICYmIChfID0gMCkpLCBfKSB0cnkge1xuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xuICAgICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XG4gICAgfVxufTtcbmltcG9ydCB7IEh0bWw1UXJjb2RlU3RyaW5ncyB9IGZyb20gXCIuLi9zdHJpbmdzXCI7XG52YXIgQ2FtZXJhUmV0cmlldmVyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDYW1lcmFSZXRyaWV2ZXIoKSB7XG4gICAgfVxuICAgIENhbWVyYVJldHJpZXZlci5yZXRyaWV2ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKG5hdmlnYXRvci5tZWRpYURldmljZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBDYW1lcmFSZXRyaWV2ZXIuZ2V0Q2FtZXJhc0Zyb21NZWRpYURldmljZXMoKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbXN0ID0gTWVkaWFTdHJlYW1UcmFjaztcbiAgICAgICAgaWYgKE1lZGlhU3RyZWFtVHJhY2sgJiYgbXN0LmdldFNvdXJjZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBDYW1lcmFSZXRyaWV2ZXIuZ2V0Q2FtZXJhc0Zyb21NZWRpYVN0cmVhbVRyYWNrKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIENhbWVyYVJldHJpZXZlci5yZWplY3RXaXRoRXJyb3IoKTtcbiAgICB9O1xuICAgIENhbWVyYVJldHJpZXZlci5yZWplY3RXaXRoRXJyb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBlcnJvck1lc3NhZ2UgPSBIdG1sNVFyY29kZVN0cmluZ3MudW5hYmxlVG9RdWVyeVN1cHBvcnRlZERldmljZXMoKTtcbiAgICAgICAgaWYgKCFDYW1lcmFSZXRyaWV2ZXIuaXNIdHRwc09yTG9jYWxob3N0KCkpIHtcbiAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IEh0bWw1UXJjb2RlU3RyaW5ncy5pbnNlY3VyZUNvbnRleHRDYW1lcmFRdWVyeUVycm9yKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycm9yTWVzc2FnZSk7XG4gICAgfTtcbiAgICBDYW1lcmFSZXRyaWV2ZXIuaXNIdHRwc09yTG9jYWxob3N0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAobG9jYXRpb24ucHJvdG9jb2wgPT09IFwiaHR0cHM6XCIpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBob3N0ID0gbG9jYXRpb24uaG9zdC5zcGxpdChcIjpcIilbMF07XG4gICAgICAgIHJldHVybiBob3N0ID09PSBcIjEyNy4wLjAuMVwiIHx8IGhvc3QgPT09IFwibG9jYWxob3N0XCI7XG4gICAgfTtcbiAgICBDYW1lcmFSZXRyaWV2ZXIuZ2V0Q2FtZXJhc0Zyb21NZWRpYURldmljZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjbG9zZUFjdGl2ZVN0cmVhbXMsIG1lZGlhU3RyZWFtLCBkZXZpY2VzLCByZXN1bHRzLCBfaSwgZGV2aWNlc18xLCBkZXZpY2U7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChfYS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICBjbG9zZUFjdGl2ZVN0cmVhbXMgPSBmdW5jdGlvbiAoc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRyYWNrcyA9IHN0cmVhbS5nZXRWaWRlb1RyYWNrcygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgdHJhY2tzXzEgPSB0cmFja3M7IF9pIDwgdHJhY2tzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0cmFjayA9IHRyYWNrc18xW19pXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS5yZW1vdmVUcmFjayh0cmFjayk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbNCwgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoeyBhdWRpbzogZmFsc2UsIHZpZGVvOiB0cnVlIH0pXTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0gPSBfYS5zZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQsIG5hdmlnYXRvci5tZWRpYURldmljZXMuZW51bWVyYXRlRGV2aWNlcygpXTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgZGV2aWNlcyA9IF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoX2kgPSAwLCBkZXZpY2VzXzEgPSBkZXZpY2VzOyBfaSA8IGRldmljZXNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXZpY2UgPSBkZXZpY2VzXzFbX2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkZXZpY2Uua2luZCA9PT0gXCJ2aWRlb2lucHV0XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkOiBkZXZpY2UuZGV2aWNlSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbDogZGV2aWNlLmxhYmVsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGNsb3NlQWN0aXZlU3RyZWFtcyhtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIsIHJlc3VsdHNdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENhbWVyYVJldHJpZXZlci5nZXRDYW1lcmFzRnJvbU1lZGlhU3RyZWFtVHJhY2sgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgXykge1xuICAgICAgICAgICAgdmFyIGNhbGxiYWNrID0gZnVuY3Rpb24gKHNvdXJjZUluZm9zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdHMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBfaSA9IDAsIHNvdXJjZUluZm9zXzEgPSBzb3VyY2VJbmZvczsgX2kgPCBzb3VyY2VJbmZvc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgc291cmNlSW5mbyA9IHNvdXJjZUluZm9zXzFbX2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc291cmNlSW5mby5raW5kID09PSBcInZpZGVvXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IHNvdXJjZUluZm8uaWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWw6IHNvdXJjZUluZm8ubGFiZWxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmUocmVzdWx0cyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIG1zdCA9IE1lZGlhU3RyZWFtVHJhY2s7XG4gICAgICAgICAgICBtc3QuZ2V0U291cmNlcyhjYWxsYmFjayk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgcmV0dXJuIENhbWVyYVJldHJpZXZlcjtcbn0oKSk7XG5leHBvcnQgeyBDYW1lcmFSZXRyaWV2ZXIgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXJldHJpZXZlci5qcy5tYXAiLCJleHBvcnQgdmFyIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlO1xuKGZ1bmN0aW9uIChIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZSkge1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlW0h0bWw1UXJjb2RlU2Nhbm5lclN0YXRlW1wiVU5LTk9XTlwiXSA9IDBdID0gXCJVTktOT1dOXCI7XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGVbSHRtbDVRcmNvZGVTY2FubmVyU3RhdGVbXCJOT1RfU1RBUlRFRFwiXSA9IDFdID0gXCJOT1RfU1RBUlRFRFwiO1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlW0h0bWw1UXJjb2RlU2Nhbm5lclN0YXRlW1wiU0NBTk5JTkdcIl0gPSAyXSA9IFwiU0NBTk5JTkdcIjtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZVtIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZVtcIlBBVVNFRFwiXSA9IDNdID0gXCJQQVVTRURcIjtcbn0pKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlIHx8IChIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZSA9IHt9KSk7XG52YXIgU3RhdGVNYW5hZ2VySW1wbCA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gU3RhdGVNYW5hZ2VySW1wbCgpIHtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLk5PVF9TVEFSVEVEO1xuICAgICAgICB0aGlzLm9uR29pbmdUcmFuc2FjdGlvbk5ld1N0YXRlID0gSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuVU5LTk9XTjtcbiAgICB9XG4gICAgU3RhdGVNYW5hZ2VySW1wbC5wcm90b3R5cGUuZGlyZWN0VHJhbnNpdGlvbiA9IGZ1bmN0aW9uIChuZXdTdGF0ZSkge1xuICAgICAgICB0aGlzLmZhaWxJZlRyYW5zaXRpb25PbmdvaW5nKCk7XG4gICAgICAgIHRoaXMudmFsaWRhdGVUcmFuc2l0aW9uKG5ld1N0YXRlKTtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IG5ld1N0YXRlO1xuICAgIH07XG4gICAgU3RhdGVNYW5hZ2VySW1wbC5wcm90b3R5cGUuc3RhcnRUcmFuc2l0aW9uID0gZnVuY3Rpb24gKG5ld1N0YXRlKSB7XG4gICAgICAgIHRoaXMuZmFpbElmVHJhbnNpdGlvbk9uZ29pbmcoKTtcbiAgICAgICAgdGhpcy52YWxpZGF0ZVRyYW5zaXRpb24obmV3U3RhdGUpO1xuICAgICAgICB0aGlzLm9uR29pbmdUcmFuc2FjdGlvbk5ld1N0YXRlID0gbmV3U3RhdGU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgU3RhdGVNYW5hZ2VySW1wbC5wcm90b3R5cGUuZXhlY3V0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGVcbiAgICAgICAgICAgID09PSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOKSB7XG4gICAgICAgICAgICB0aHJvdyBcIlRyYW5zYWN0aW9uIGlzIGFscmVhZHkgY2FuY2VsbGVkLCBjYW5ub3QgZXhlY3V0ZSgpLlwiO1xuICAgICAgICB9XG4gICAgICAgIHZhciB0ZW1wTmV3U3RhdGUgPSB0aGlzLm9uR29pbmdUcmFuc2FjdGlvbk5ld1N0YXRlO1xuICAgICAgICB0aGlzLm9uR29pbmdUcmFuc2FjdGlvbk5ld1N0YXRlID0gSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuVU5LTk9XTjtcbiAgICAgICAgdGhpcy5kaXJlY3RUcmFuc2l0aW9uKHRlbXBOZXdTdGF0ZSk7XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5jYW5jZWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLm9uR29pbmdUcmFuc2FjdGlvbk5ld1N0YXRlXG4gICAgICAgICAgICA9PT0gSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuVU5LTk9XTikge1xuICAgICAgICAgICAgdGhyb3cgXCJUcmFuc2FjdGlvbiBpcyBhbHJlYWR5IGNhbmNlbGxlZCwgY2Fubm90IGNhbmNlbCgpLlwiO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGUgPSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOO1xuICAgIH07XG4gICAgU3RhdGVNYW5hZ2VySW1wbC5wcm90b3R5cGUuZ2V0U3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlO1xuICAgIH07XG4gICAgU3RhdGVNYW5hZ2VySW1wbC5wcm90b3R5cGUuZmFpbElmVHJhbnNpdGlvbk9uZ29pbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLm9uR29pbmdUcmFuc2FjdGlvbk5ld1N0YXRlXG4gICAgICAgICAgICAhPT0gSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuVU5LTk9XTikge1xuICAgICAgICAgICAgdGhyb3cgXCJDYW5ub3QgdHJhbnNpdGlvbiB0byBhIG5ldyBzdGF0ZSwgYWxyZWFkeSB1bmRlciB0cmFuc2l0aW9uXCI7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlckltcGwucHJvdG90eXBlLnZhbGlkYXRlVHJhbnNpdGlvbiA9IGZ1bmN0aW9uIChuZXdTdGF0ZSkge1xuICAgICAgICBzd2l0Y2ggKHRoaXMuc3RhdGUpIHtcbiAgICAgICAgICAgIGNhc2UgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuVU5LTk9XTjpcbiAgICAgICAgICAgICAgICB0aHJvdyBcIlRyYW5zaXRpb24gZnJvbSB1bmtub3duIGlzIG5vdCBhbGxvd2VkXCI7XG4gICAgICAgICAgICBjYXNlIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLk5PVF9TVEFSVEVEOlxuICAgICAgICAgICAgICAgIHRoaXMuZmFpbElmTmV3U3RhdGVJcyhuZXdTdGF0ZSwgW0h0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlBBVVNFRF0pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5TQ0FOTklORzpcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuUEFVU0VEOlxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5mYWlsSWZOZXdTdGF0ZUlzID0gZnVuY3Rpb24gKG5ld1N0YXRlLCBkaXNhbGxvd2VkU3RhdGVzVG9UcmFuc2l0aW9uKSB7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgZGlzYWxsb3dlZFN0YXRlc1RvVHJhbnNpdGlvbl8xID0gZGlzYWxsb3dlZFN0YXRlc1RvVHJhbnNpdGlvbjsgX2kgPCBkaXNhbGxvd2VkU3RhdGVzVG9UcmFuc2l0aW9uXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgZGlzYWxsb3dlZFN0YXRlID0gZGlzYWxsb3dlZFN0YXRlc1RvVHJhbnNpdGlvbl8xW19pXTtcbiAgICAgICAgICAgIGlmIChuZXdTdGF0ZSA9PT0gZGlzYWxsb3dlZFN0YXRlKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgXCJDYW5ub3QgdHJhbnNpdGlvbiBmcm9tIFwiLmNvbmNhdCh0aGlzLnN0YXRlLCBcIiB0byBcIikuY29uY2F0KG5ld1N0YXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIFN0YXRlTWFuYWdlckltcGw7XG59KCkpO1xudmFyIFN0YXRlTWFuYWdlclByb3h5ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBTdGF0ZU1hbmFnZXJQcm94eShzdGF0ZU1hbmFnZXIpIHtcbiAgICAgICAgdGhpcy5zdGF0ZU1hbmFnZXIgPSBzdGF0ZU1hbmFnZXI7XG4gICAgfVxuICAgIFN0YXRlTWFuYWdlclByb3h5LnByb3RvdHlwZS5zdGFydFRyYW5zaXRpb24gPSBmdW5jdGlvbiAobmV3U3RhdGUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGVNYW5hZ2VyLnN0YXJ0VHJhbnNpdGlvbihuZXdTdGF0ZSk7XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJQcm94eS5wcm90b3R5cGUuZGlyZWN0VHJhbnNpdGlvbiA9IGZ1bmN0aW9uIChuZXdTdGF0ZSkge1xuICAgICAgICB0aGlzLnN0YXRlTWFuYWdlci5kaXJlY3RUcmFuc2l0aW9uKG5ld1N0YXRlKTtcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlclByb3h5LnByb3RvdHlwZS5nZXRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGVNYW5hZ2VyLmdldFN0YXRlKCk7XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJQcm94eS5wcm90b3R5cGUuY2FuU2NhbkZpbGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlTWFuYWdlci5nZXRTdGF0ZSgpID09PSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5OT1RfU1RBUlRFRDtcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlclByb3h5LnByb3RvdHlwZS5pc1NjYW5uaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZU1hbmFnZXIuZ2V0U3RhdGUoKSAhPT0gSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuTk9UX1NUQVJURUQ7XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJQcm94eS5wcm90b3R5cGUuaXNTdHJpY3RseVNjYW5uaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZU1hbmFnZXIuZ2V0U3RhdGUoKSA9PT0gSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuU0NBTk5JTkc7XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJQcm94eS5wcm90b3R5cGUuaXNQYXVzZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlTWFuYWdlci5nZXRTdGF0ZSgpID09PSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5QQVVTRUQ7XG4gICAgfTtcbiAgICByZXR1cm4gU3RhdGVNYW5hZ2VyUHJveHk7XG59KCkpO1xuZXhwb3J0IHsgU3RhdGVNYW5hZ2VyUHJveHkgfTtcbnZhciBTdGF0ZU1hbmFnZXJGYWN0b3J5ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBTdGF0ZU1hbmFnZXJGYWN0b3J5KCkge1xuICAgIH1cbiAgICBTdGF0ZU1hbmFnZXJGYWN0b3J5LmNyZWF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBTdGF0ZU1hbmFnZXJQcm94eShuZXcgU3RhdGVNYW5hZ2VySW1wbCgpKTtcbiAgICB9O1xuICAgIHJldHVybiBTdGF0ZU1hbmFnZXJGYWN0b3J5O1xufSgpKTtcbmV4cG9ydCB7IFN0YXRlTWFuYWdlckZhY3RvcnkgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXN0YXRlLW1hbmFnZXIuanMubWFwIiwidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbmltcG9ydCB7IEJhc2VMb2dnZ2VyLCBIdG1sNVFyY29kZVJlc3VsdEZhY3RvcnksIEh0bWw1UXJjb2RlRXJyb3JGYWN0b3J5LCBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMsIGlzVmFsaWRIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMsIEh0bWw1UXJjb2RlQ29uc3RhbnRzLCBpc051bGxPclVuZGVmaW5lZCB9IGZyb20gXCIuL2NvcmVcIjtcbmltcG9ydCB7IEh0bWw1UXJjb2RlU3RyaW5ncyB9IGZyb20gXCIuL3N0cmluZ3NcIjtcbmltcG9ydCB7IFZpZGVvQ29uc3RyYWludHNVdGlsIH0gZnJvbSBcIi4vdXRpbHNcIjtcbmltcG9ydCB7IEh0bWw1UXJjb2RlU2hpbSB9IGZyb20gXCIuL2NvZGUtZGVjb2RlclwiO1xuaW1wb3J0IHsgQ2FtZXJhRmFjdG9yeSB9IGZyb20gXCIuL2NhbWVyYS9mYWN0b3JpZXNcIjtcbmltcG9ydCB7IENhbWVyYVJldHJpZXZlciB9IGZyb20gXCIuL2NhbWVyYS9yZXRyaWV2ZXJcIjtcbmltcG9ydCB7IFN0YXRlTWFuYWdlckZhY3RvcnksIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlIH0gZnJvbSBcIi4vc3RhdGUtbWFuYWdlclwiO1xudmFyIENvbnN0YW50cyA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKENvbnN0YW50cywgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBDb25zdGFudHMoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgQ29uc3RhbnRzLkRFRkFVTFRfV0lEVEggPSAzMDA7XG4gICAgQ29uc3RhbnRzLkRFRkFVTFRfV0lEVEhfT0ZGU0VUID0gMjtcbiAgICBDb25zdGFudHMuRklMRV9TQ0FOX01JTl9IRUlHSFQgPSAzMDA7XG4gICAgQ29uc3RhbnRzLkZJTEVfU0NBTl9ISURERU5fQ0FOVkFTX1BBRERJTkcgPSAxMDA7XG4gICAgQ29uc3RhbnRzLk1JTl9RUl9CT1hfU0laRSA9IDUwO1xuICAgIENvbnN0YW50cy5TSEFERURfTEVGVCA9IDE7XG4gICAgQ29uc3RhbnRzLlNIQURFRF9SSUdIVCA9IDI7XG4gICAgQ29uc3RhbnRzLlNIQURFRF9UT1AgPSAzO1xuICAgIENvbnN0YW50cy5TSEFERURfQk9UVE9NID0gNDtcbiAgICBDb25zdGFudHMuU0hBREVEX1JFR0lPTl9FTEVNRU5UX0lEID0gXCJxci1zaGFkZWQtcmVnaW9uXCI7XG4gICAgQ29uc3RhbnRzLlZFUkJPU0UgPSBmYWxzZTtcbiAgICBDb25zdGFudHMuQk9SREVSX1NIQURFUl9ERUZBVUxUX0NPTE9SID0gXCIjZmZmZmZmXCI7XG4gICAgQ29uc3RhbnRzLkJPUkRFUl9TSEFERVJfTUFUQ0hfQ09MT1IgPSBcInJnYig5MCwgMTkzLCA1NilcIjtcbiAgICByZXR1cm4gQ29uc3RhbnRzO1xufShIdG1sNVFyY29kZUNvbnN0YW50cykpO1xudmFyIEludGVybmFsSHRtbDVRcmNvZGVDb25maWcgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEludGVybmFsSHRtbDVRcmNvZGVDb25maWcoY29uZmlnLCBsb2dnZXIpIHtcbiAgICAgICAgdGhpcy5sb2dnZXIgPSBsb2dnZXI7XG4gICAgICAgIHRoaXMuZnBzID0gQ29uc3RhbnRzLlNDQU5fREVGQVVMVF9GUFM7XG4gICAgICAgIGlmICghY29uZmlnKSB7XG4gICAgICAgICAgICB0aGlzLmRpc2FibGVGbGlwID0gQ29uc3RhbnRzLkRFRkFVTFRfRElTQUJMRV9GTElQO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYgKGNvbmZpZy5mcHMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZwcyA9IGNvbmZpZy5mcHM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmRpc2FibGVGbGlwID0gY29uZmlnLmRpc2FibGVGbGlwID09PSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5xcmJveCA9IGNvbmZpZy5xcmJveDtcbiAgICAgICAgICAgIHRoaXMuYXNwZWN0UmF0aW8gPSBjb25maWcuYXNwZWN0UmF0aW87XG4gICAgICAgICAgICB0aGlzLnZpZGVvQ29uc3RyYWludHMgPSBjb25maWcudmlkZW9Db25zdHJhaW50cztcbiAgICAgICAgfVxuICAgIH1cbiAgICBJbnRlcm5hbEh0bWw1UXJjb2RlQ29uZmlnLnByb3RvdHlwZS5pc01lZGlhU3RyZWFtQ29uc3RyYWludHNWYWxpZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnZpZGVvQ29uc3RyYWludHMpIHtcbiAgICAgICAgICAgIHRoaXMubG9nZ2VyLmxvZ0Vycm9yKFwiRW1wdHkgdmlkZW9Db25zdHJhaW50c1wiLCB0cnVlKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gVmlkZW9Db25zdHJhaW50c1V0aWwuaXNNZWRpYVN0cmVhbUNvbnN0cmFpbnRzVmFsaWQodGhpcy52aWRlb0NvbnN0cmFpbnRzLCB0aGlzLmxvZ2dlcik7XG4gICAgfTtcbiAgICBJbnRlcm5hbEh0bWw1UXJjb2RlQ29uZmlnLnByb3RvdHlwZS5pc1NoYWRlZEJveEVuYWJsZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAhaXNOdWxsT3JVbmRlZmluZWQodGhpcy5xcmJveCk7XG4gICAgfTtcbiAgICBJbnRlcm5hbEh0bWw1UXJjb2RlQ29uZmlnLmNyZWF0ZSA9IGZ1bmN0aW9uIChjb25maWcsIGxvZ2dlcikge1xuICAgICAgICByZXR1cm4gbmV3IEludGVybmFsSHRtbDVRcmNvZGVDb25maWcoY29uZmlnLCBsb2dnZXIpO1xuICAgIH07XG4gICAgcmV0dXJuIEludGVybmFsSHRtbDVRcmNvZGVDb25maWc7XG59KCkpO1xudmFyIEh0bWw1UXJjb2RlID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBIdG1sNVFyY29kZShlbGVtZW50SWQsIGNvbmZpZ09yVmVyYm9zaXR5RmxhZykge1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSBudWxsO1xuICAgICAgICB0aGlzLmNhbnZhc0VsZW1lbnQgPSBudWxsO1xuICAgICAgICB0aGlzLnNjYW5uZXJQYXVzZWRVaUVsZW1lbnQgPSBudWxsO1xuICAgICAgICB0aGlzLmhhc0JvcmRlclNoYWRlcnMgPSBudWxsO1xuICAgICAgICB0aGlzLmJvcmRlclNoYWRlcnMgPSBudWxsO1xuICAgICAgICB0aGlzLnFyTWF0Y2ggPSBudWxsO1xuICAgICAgICB0aGlzLnJlbmRlcmVkQ2FtZXJhID0gbnVsbDtcbiAgICAgICAgdGhpcy5xclJlZ2lvbiA9IG51bGw7XG4gICAgICAgIHRoaXMuY29udGV4dCA9IG51bGw7XG4gICAgICAgIHRoaXMubGFzdFNjYW5JbWFnZUZpbGUgPSBudWxsO1xuICAgICAgICB0aGlzLmlzU2Nhbm5pbmcgPSBmYWxzZTtcbiAgICAgICAgaWYgKCFkb2N1bWVudC5nZXRFbGVtZW50QnlJZChlbGVtZW50SWQpKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkhUTUwgRWxlbWVudCB3aXRoIGlkPVwiLmNvbmNhdChlbGVtZW50SWQsIFwiIG5vdCBmb3VuZFwiKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmVsZW1lbnRJZCA9IGVsZW1lbnRJZDtcbiAgICAgICAgdGhpcy52ZXJib3NlID0gZmFsc2U7XG4gICAgICAgIHZhciBleHBlcmltZW50YWxGZWF0dXJlQ29uZmlnO1xuICAgICAgICB2YXIgY29uZmlnT2JqZWN0O1xuICAgICAgICBpZiAodHlwZW9mIGNvbmZpZ09yVmVyYm9zaXR5RmxhZyA9PSBcImJvb2xlYW5cIikge1xuICAgICAgICAgICAgdGhpcy52ZXJib3NlID0gY29uZmlnT3JWZXJib3NpdHlGbGFnID09PSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGNvbmZpZ09yVmVyYm9zaXR5RmxhZykge1xuICAgICAgICAgICAgY29uZmlnT2JqZWN0ID0gY29uZmlnT3JWZXJib3NpdHlGbGFnO1xuICAgICAgICAgICAgdGhpcy52ZXJib3NlID0gY29uZmlnT2JqZWN0LnZlcmJvc2UgPT09IHRydWU7XG4gICAgICAgICAgICBleHBlcmltZW50YWxGZWF0dXJlQ29uZmlnID0gY29uZmlnT2JqZWN0LmV4cGVyaW1lbnRhbEZlYXR1cmVzO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubG9nZ2VyID0gbmV3IEJhc2VMb2dnZ2VyKHRoaXMudmVyYm9zZSk7XG4gICAgICAgIHRoaXMucXJjb2RlID0gbmV3IEh0bWw1UXJjb2RlU2hpbSh0aGlzLmdldFN1cHBvcnRlZEZvcm1hdHMoY29uZmlnT3JWZXJib3NpdHlGbGFnKSwgdGhpcy5nZXRVc2VCYXJDb2RlRGV0ZWN0b3JJZlN1cHBvcnRlZChjb25maWdPYmplY3QpLCB0aGlzLnZlcmJvc2UsIHRoaXMubG9nZ2VyKTtcbiAgICAgICAgdGhpcy5mb3JldmVyU2NhblRpbWVvdXQ7XG4gICAgICAgIHRoaXMuc2hvdWxkU2NhbiA9IHRydWU7XG4gICAgICAgIHRoaXMuc3RhdGVNYW5hZ2VyUHJveHkgPSBTdGF0ZU1hbmFnZXJGYWN0b3J5LmNyZWF0ZSgpO1xuICAgIH1cbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuc3RhcnQgPSBmdW5jdGlvbiAoY2FtZXJhSWRPckNvbmZpZywgY29uZmlndXJhdGlvbiwgcXJDb2RlU3VjY2Vzc0NhbGxiYWNrLCBxckNvZGVFcnJvckNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghY2FtZXJhSWRPckNvbmZpZykge1xuICAgICAgICAgICAgdGhyb3cgXCJjYW1lcmFJZE9yQ29uZmlnIGlzIHJlcXVpcmVkXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFxckNvZGVTdWNjZXNzQ2FsbGJhY2tcbiAgICAgICAgICAgIHx8IHR5cGVvZiBxckNvZGVTdWNjZXNzQ2FsbGJhY2sgIT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICB0aHJvdyBcInFyQ29kZVN1Y2Nlc3NDYWxsYmFjayBpcyByZXF1aXJlZCBhbmQgc2hvdWxkIGJlIGEgZnVuY3Rpb24uXCI7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHFyQ29kZUVycm9yQ2FsbGJhY2tJbnRlcm5hbDtcbiAgICAgICAgaWYgKHFyQ29kZUVycm9yQ2FsbGJhY2spIHtcbiAgICAgICAgICAgIHFyQ29kZUVycm9yQ2FsbGJhY2tJbnRlcm5hbCA9IHFyQ29kZUVycm9yQ2FsbGJhY2s7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBxckNvZGVFcnJvckNhbGxiYWNrSW50ZXJuYWxcbiAgICAgICAgICAgICAgICA9IHRoaXMudmVyYm9zZSA/IHRoaXMubG9nZ2VyLmxvZyA6IGZ1bmN0aW9uICgpIHsgfTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaW50ZXJuYWxDb25maWcgPSBJbnRlcm5hbEh0bWw1UXJjb2RlQ29uZmlnLmNyZWF0ZShjb25maWd1cmF0aW9uLCB0aGlzLmxvZ2dlcik7XG4gICAgICAgIHRoaXMuY2xlYXJFbGVtZW50KCk7XG4gICAgICAgIHZhciB2aWRlb0NvbnN0cmFpbnRzQXZhaWxhYmxlQW5kVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgaWYgKGludGVybmFsQ29uZmlnLnZpZGVvQ29uc3RyYWludHMpIHtcbiAgICAgICAgICAgIGlmICghaW50ZXJuYWxDb25maWcuaXNNZWRpYVN0cmVhbUNvbnN0cmFpbnRzVmFsaWQoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLmxvZ0Vycm9yKFwiJ3ZpZGVvQ29uc3RyYWludHMnIGlzIG5vdCB2YWxpZCAnTWVkaWFTdHJlYW1Db25zdHJhaW50cywgXCJcbiAgICAgICAgICAgICAgICAgICAgKyBcIml0IHdpbGwgYmUgaWdub3JlZC4nXCIsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmlkZW9Db25zdHJhaW50c0F2YWlsYWJsZUFuZFZhbGlkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgYXJlVmlkZW9Db25zdHJhaW50c0VuYWJsZWQgPSB2aWRlb0NvbnN0cmFpbnRzQXZhaWxhYmxlQW5kVmFsaWQ7XG4gICAgICAgIHZhciBlbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5lbGVtZW50SWQpO1xuICAgICAgICB2YXIgcm9vdEVsZW1lbnRXaWR0aCA9IGVsZW1lbnQuY2xpZW50V2lkdGhcbiAgICAgICAgICAgID8gZWxlbWVudC5jbGllbnRXaWR0aCA6IENvbnN0YW50cy5ERUZBVUxUX1dJRFRIO1xuICAgICAgICBlbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gXCJyZWxhdGl2ZVwiO1xuICAgICAgICB0aGlzLnNob3VsZFNjYW4gPSB0cnVlO1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgdG9TY2FubmluZ1N0YXRlQ2hhbmdlVHJhbnNhY3Rpb24gPSB0aGlzLnN0YXRlTWFuYWdlclByb3h5LnN0YXJ0VHJhbnNpdGlvbihIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5TQ0FOTklORyk7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICAgICB2YXIgdmlkZW9Db25zdHJhaW50cyA9IGFyZVZpZGVvQ29uc3RyYWludHNFbmFibGVkXG4gICAgICAgICAgICAgICAgPyBpbnRlcm5hbENvbmZpZy52aWRlb0NvbnN0cmFpbnRzXG4gICAgICAgICAgICAgICAgOiAkdGhpcy5jcmVhdGVWaWRlb0NvbnN0cmFpbnRzKGNhbWVyYUlkT3JDb25maWcpO1xuICAgICAgICAgICAgaWYgKCF2aWRlb0NvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICAgICAgdG9TY2FubmluZ1N0YXRlQ2hhbmdlVHJhbnNhY3Rpb24uY2FuY2VsKCk7XG4gICAgICAgICAgICAgICAgcmVqZWN0KFwidmlkZW9Db25zdHJhaW50cyBzaG91bGQgYmUgZGVmaW5lZFwiKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgY2FtZXJhUmVuZGVyaW5nT3B0aW9ucyA9IHt9O1xuICAgICAgICAgICAgaWYgKCFhcmVWaWRlb0NvbnN0cmFpbnRzRW5hYmxlZCB8fCBpbnRlcm5hbENvbmZpZy5hc3BlY3RSYXRpbykge1xuICAgICAgICAgICAgICAgIGNhbWVyYVJlbmRlcmluZ09wdGlvbnMuYXNwZWN0UmF0aW8gPSBpbnRlcm5hbENvbmZpZy5hc3BlY3RSYXRpbztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciByZW5kZXJpbmdDYWxsYmFja3MgPSB7XG4gICAgICAgICAgICAgICAgb25SZW5kZXJTdXJmYWNlUmVhZHk6IGZ1bmN0aW9uICh2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMuc2V0dXBVaSh2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQsIGludGVybmFsQ29uZmlnKTtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMuaXNTY2FubmluZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICR0aGlzLmZvcmV2ZXJTY2FuKGludGVybmFsQ29uZmlnLCBxckNvZGVTdWNjZXNzQ2FsbGJhY2ssIHFyQ29kZUVycm9yQ2FsbGJhY2tJbnRlcm5hbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIENhbWVyYUZhY3RvcnkuZmFpbElmTm90U3VwcG9ydGVkKCkudGhlbihmdW5jdGlvbiAoZmFjdG9yeSkge1xuICAgICAgICAgICAgICAgIGZhY3RvcnkuY3JlYXRlKHZpZGVvQ29uc3RyYWludHMpLnRoZW4oZnVuY3Rpb24gKGNhbWVyYSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FtZXJhLnJlbmRlcihfdGhpcy5lbGVtZW50LCBjYW1lcmFSZW5kZXJpbmdPcHRpb25zLCByZW5kZXJpbmdDYWxsYmFja3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAudGhlbihmdW5jdGlvbiAocmVuZGVyZWRDYW1lcmEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLnJlbmRlcmVkQ2FtZXJhID0gcmVuZGVyZWRDYW1lcmE7XG4gICAgICAgICAgICAgICAgICAgICAgICB0b1NjYW5uaW5nU3RhdGVDaGFuZ2VUcmFuc2FjdGlvbi5leGVjdXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdG9TY2FubmluZ1N0YXRlQ2hhbmdlVHJhbnNhY3Rpb24uY2FuY2VsKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KS5jYXRjaChmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgdG9TY2FubmluZ1N0YXRlQ2hhbmdlVHJhbnNhY3Rpb24uY2FuY2VsKCk7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChIdG1sNVFyY29kZVN0cmluZ3MuZXJyb3JHZXR0aW5nVXNlck1lZGlhKGVycm9yKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KS5jYXRjaChmdW5jdGlvbiAoXykge1xuICAgICAgICAgICAgICAgIHRvU2Nhbm5pbmdTdGF0ZUNoYW5nZVRyYW5zYWN0aW9uLmNhbmNlbCgpO1xuICAgICAgICAgICAgICAgIHJlamVjdChIdG1sNVFyY29kZVN0cmluZ3MuY2FtZXJhU3RyZWFtaW5nTm90U3VwcG9ydGVkKCkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLnBhdXNlID0gZnVuY3Rpb24gKHNob3VsZFBhdXNlVmlkZW8pIHtcbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlTWFuYWdlclByb3h5LmlzU3RyaWN0bHlTY2FubmluZygpKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkNhbm5vdCBwYXVzZSwgc2Nhbm5lciBpcyBub3Qgc2Nhbm5pbmcuXCI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zdGF0ZU1hbmFnZXJQcm94eS5kaXJlY3RUcmFuc2l0aW9uKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlBBVVNFRCk7XG4gICAgICAgIHRoaXMuc2hvd1BhdXNlZFN0YXRlKCk7XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmaW5lZChzaG91bGRQYXVzZVZpZGVvKSB8fCBzaG91bGRQYXVzZVZpZGVvICE9PSB0cnVlKSB7XG4gICAgICAgICAgICBzaG91bGRQYXVzZVZpZGVvID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNob3VsZFBhdXNlVmlkZW8gJiYgdGhpcy5yZW5kZXJlZENhbWVyYSkge1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJlZENhbWVyYS5wYXVzZSgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUucmVzdW1lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuaXNQYXVzZWQoKSkge1xuICAgICAgICAgICAgdGhyb3cgXCJDYW5ub3QgcmVzdWx0LCBzY2FubmVyIGlzIG5vdCBwYXVzZWQuXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnJlbmRlcmVkQ2FtZXJhKSB7XG4gICAgICAgICAgICB0aHJvdyBcInJlbmRlcmVkQ2FtZXJhIGRvZXNuJ3QgZXhpc3Qgd2hpbGUgdHJ5aW5nIHJlc3VtZSgpXCI7XG4gICAgICAgIH1cbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHRyYW5zaXRpb25Ub1NjYW5uaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgJHRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuZGlyZWN0VHJhbnNpdGlvbihIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5TQ0FOTklORyk7XG4gICAgICAgICAgICAkdGhpcy5oaWRlUGF1c2VkU3RhdGUoKTtcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKCF0aGlzLnJlbmRlcmVkQ2FtZXJhLmlzUGF1c2VkKCkpIHtcbiAgICAgICAgICAgIHRyYW5zaXRpb25Ub1NjYW5uaW5nKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZW5kZXJlZENhbWVyYS5yZXN1bWUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdHJhbnNpdGlvblRvU2Nhbm5pbmcoKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuZ2V0U3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlTWFuYWdlclByb3h5LmdldFN0YXRlKCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuc3RvcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlTWFuYWdlclByb3h5LmlzU2Nhbm5pbmcoKSkge1xuICAgICAgICAgICAgdGhyb3cgXCJDYW5ub3Qgc3RvcCwgc2Nhbm5lciBpcyBub3QgcnVubmluZyBvciBwYXVzZWQuXCI7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRvU3RvcHBlZFN0YXRlVHJhbnNhY3Rpb24gPSB0aGlzLnN0YXRlTWFuYWdlclByb3h5LnN0YXJ0VHJhbnNpdGlvbihIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5OT1RfU1RBUlRFRCk7XG4gICAgICAgIHRoaXMuc2hvdWxkU2NhbiA9IGZhbHNlO1xuICAgICAgICBpZiAodGhpcy5mb3JldmVyU2NhblRpbWVvdXQpIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLmZvcmV2ZXJTY2FuVGltZW91dCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlbW92ZVFyUmVnaW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKCFfdGhpcy5lbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGNoaWxkRWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKENvbnN0YW50cy5TSEFERURfUkVHSU9OX0VMRU1FTlRfSUQpO1xuICAgICAgICAgICAgaWYgKGNoaWxkRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIF90aGlzLmVsZW1lbnQucmVtb3ZlQ2hpbGQoY2hpbGRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgcmV0dXJuIHRoaXMucmVuZGVyZWRDYW1lcmEuY2xvc2UoKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICR0aGlzLnJlbmRlcmVkQ2FtZXJhID0gbnVsbDtcbiAgICAgICAgICAgIGlmICgkdGhpcy5lbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuZWxlbWVudC5yZW1vdmVDaGlsZCgkdGhpcy5jYW52YXNFbGVtZW50KTtcbiAgICAgICAgICAgICAgICAkdGhpcy5jYW52YXNFbGVtZW50ID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlbW92ZVFyUmVnaW9uKCk7XG4gICAgICAgICAgICBpZiAoJHRoaXMucXJSZWdpb24pIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5xclJlZ2lvbiA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJHRoaXMuY29udGV4dCkge1xuICAgICAgICAgICAgICAgICR0aGlzLmNvbnRleHQgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdG9TdG9wcGVkU3RhdGVUcmFuc2FjdGlvbi5leGVjdXRlKCk7XG4gICAgICAgICAgICAkdGhpcy5oaWRlUGF1c2VkU3RhdGUoKTtcbiAgICAgICAgICAgICR0aGlzLmlzU2Nhbm5pbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuc2NhbkZpbGUgPSBmdW5jdGlvbiAoaW1hZ2VGaWxlLCBzaG93SW1hZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2NhbkZpbGVWMihpbWFnZUZpbGUsIHNob3dJbWFnZSlcbiAgICAgICAgICAgIC50aGVuKGZ1bmN0aW9uIChodG1sNXFyY29kZVJlc3VsdCkgeyByZXR1cm4gaHRtbDVxcmNvZGVSZXN1bHQuZGVjb2RlZFRleHQ7IH0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLnNjYW5GaWxlVjIgPSBmdW5jdGlvbiAoaW1hZ2VGaWxlLCBzaG93SW1hZ2UpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCFpbWFnZUZpbGUgfHwgIShpbWFnZUZpbGUgaW5zdGFuY2VvZiBGaWxlKSkge1xuICAgICAgICAgICAgdGhyb3cgXCJpbWFnZUZpbGUgYXJndW1lbnQgaXMgbWFuZGF0b3J5IGFuZCBzaG91bGQgYmUgaW5zdGFuY2UgXCJcbiAgICAgICAgICAgICAgICArIFwib2YgRmlsZS4gVXNlICdldmVudC50YXJnZXQuZmlsZXNbMF0nLlwiO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmaW5lZChzaG93SW1hZ2UpKSB7XG4gICAgICAgICAgICBzaG93SW1hZ2UgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5zdGF0ZU1hbmFnZXJQcm94eS5jYW5TY2FuRmlsZSgpKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkNhbm5vdCBzdGFydCBmaWxlIHNjYW4gLSBvbmdvaW5nIGNhbWVyYSBzY2FuXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgIF90aGlzLnBvc3NpYmx5Q2xvc2VMYXN0U2NhbkltYWdlRmlsZSgpO1xuICAgICAgICAgICAgX3RoaXMuY2xlYXJFbGVtZW50KCk7XG4gICAgICAgICAgICBfdGhpcy5sYXN0U2NhbkltYWdlRmlsZSA9IFVSTC5jcmVhdGVPYmplY3RVUkwoaW1hZ2VGaWxlKTtcbiAgICAgICAgICAgIHZhciBpbnB1dEltYWdlID0gbmV3IEltYWdlO1xuICAgICAgICAgICAgaW5wdXRJbWFnZS5vbmxvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGltYWdlV2lkdGggPSBpbnB1dEltYWdlLndpZHRoO1xuICAgICAgICAgICAgICAgIHZhciBpbWFnZUhlaWdodCA9IGlucHV0SW1hZ2UuaGVpZ2h0O1xuICAgICAgICAgICAgICAgIHZhciBlbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoX3RoaXMuZWxlbWVudElkKTtcbiAgICAgICAgICAgICAgICB2YXIgY29udGFpbmVyV2lkdGggPSBlbGVtZW50LmNsaWVudFdpZHRoXG4gICAgICAgICAgICAgICAgICAgID8gZWxlbWVudC5jbGllbnRXaWR0aCA6IENvbnN0YW50cy5ERUZBVUxUX1dJRFRIO1xuICAgICAgICAgICAgICAgIHZhciBjb250YWluZXJIZWlnaHQgPSBNYXRoLm1heChlbGVtZW50LmNsaWVudEhlaWdodCA/IGVsZW1lbnQuY2xpZW50SGVpZ2h0IDogaW1hZ2VIZWlnaHQsIENvbnN0YW50cy5GSUxFX1NDQU5fTUlOX0hFSUdIVCk7XG4gICAgICAgICAgICAgICAgdmFyIGNvbmZpZyA9IF90aGlzLmNvbXB1dGVDYW52YXNEcmF3Q29uZmlnKGltYWdlV2lkdGgsIGltYWdlSGVpZ2h0LCBjb250YWluZXJXaWR0aCwgY29udGFpbmVySGVpZ2h0KTtcbiAgICAgICAgICAgICAgICBpZiAoc2hvd0ltYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2aXNpYmxlQ2FudmFzID0gX3RoaXMuY3JlYXRlQ2FudmFzRWxlbWVudChjb250YWluZXJXaWR0aCwgY29udGFpbmVySGVpZ2h0LCBcInFyLWNhbnZhcy12aXNpYmxlXCIpO1xuICAgICAgICAgICAgICAgICAgICB2aXNpYmxlQ2FudmFzLnN0eWxlLmRpc3BsYXkgPSBcImlubGluZS1ibG9ja1wiO1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFwcGVuZENoaWxkKHZpc2libGVDYW52YXMpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgY29udGV4dF8xID0gdmlzaWJsZUNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XG4gICAgICAgICAgICAgICAgICAgIGlmICghY29udGV4dF8xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBcIlVuYWJsZSB0byBnZXQgMmQgY29udGV4dCBmcm9tIGNhbnZhc1wiO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHRfMS5jYW52YXMud2lkdGggPSBjb250YWluZXJXaWR0aDtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dF8xLmNhbnZhcy5oZWlnaHQgPSBjb250YWluZXJIZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHRfMS5kcmF3SW1hZ2UoaW5wdXRJbWFnZSwgMCwgMCwgaW1hZ2VXaWR0aCwgaW1hZ2VIZWlnaHQsIGNvbmZpZy54LCBjb25maWcueSwgY29uZmlnLndpZHRoLCBjb25maWcuaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIHBhZGRpbmcgPSBDb25zdGFudHMuRklMRV9TQ0FOX0hJRERFTl9DQU5WQVNfUEFERElORztcbiAgICAgICAgICAgICAgICB2YXIgaGlkZGVuSW1hZ2VXaWR0aCA9IE1hdGgubWF4KGlucHV0SW1hZ2Uud2lkdGgsIGNvbmZpZy53aWR0aCk7XG4gICAgICAgICAgICAgICAgdmFyIGhpZGRlbkltYWdlSGVpZ2h0ID0gTWF0aC5tYXgoaW5wdXRJbWFnZS5oZWlnaHQsIGNvbmZpZy5oZWlnaHQpO1xuICAgICAgICAgICAgICAgIHZhciBoaWRkZW5DYW52YXNXaWR0aCA9IGhpZGRlbkltYWdlV2lkdGggKyAyICogcGFkZGluZztcbiAgICAgICAgICAgICAgICB2YXIgaGlkZGVuQ2FudmFzSGVpZ2h0ID0gaGlkZGVuSW1hZ2VIZWlnaHQgKyAyICogcGFkZGluZztcbiAgICAgICAgICAgICAgICB2YXIgaGlkZGVuQ2FudmFzID0gX3RoaXMuY3JlYXRlQ2FudmFzRWxlbWVudChoaWRkZW5DYW52YXNXaWR0aCwgaGlkZGVuQ2FudmFzSGVpZ2h0KTtcbiAgICAgICAgICAgICAgICBlbGVtZW50LmFwcGVuZENoaWxkKGhpZGRlbkNhbnZhcyk7XG4gICAgICAgICAgICAgICAgdmFyIGNvbnRleHQgPSBoaWRkZW5DYW52YXMuZ2V0Q29udGV4dChcIjJkXCIpO1xuICAgICAgICAgICAgICAgIGlmICghY29udGV4dCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBcIlVuYWJsZSB0byBnZXQgMmQgY29udGV4dCBmcm9tIGNhbnZhc1wiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb250ZXh0LmNhbnZhcy53aWR0aCA9IGhpZGRlbkNhbnZhc1dpZHRoO1xuICAgICAgICAgICAgICAgIGNvbnRleHQuY2FudmFzLmhlaWdodCA9IGhpZGRlbkNhbnZhc0hlaWdodDtcbiAgICAgICAgICAgICAgICBjb250ZXh0LmRyYXdJbWFnZShpbnB1dEltYWdlLCAwLCAwLCBpbWFnZVdpZHRoLCBpbWFnZUhlaWdodCwgcGFkZGluZywgcGFkZGluZywgaGlkZGVuSW1hZ2VXaWR0aCwgaGlkZGVuSW1hZ2VIZWlnaHQpO1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnFyY29kZS5kZWNvZGVSb2J1c3RseUFzeW5jKGhpZGRlbkNhbnZhcylcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoSHRtbDVRcmNvZGVSZXN1bHRGYWN0b3J5LmNyZWF0ZUZyb21RcmNvZGVSZXN1bHQocmVzdWx0KSk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2gocmVqZWN0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKGV4Y2VwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoXCJRUiBjb2RlIHBhcnNlIGVycm9yLCBlcnJvciA9IFwiLmNvbmNhdChleGNlcHRpb24pKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaW5wdXRJbWFnZS5vbmVycm9yID0gcmVqZWN0O1xuICAgICAgICAgICAgaW5wdXRJbWFnZS5vbmFib3J0ID0gcmVqZWN0O1xuICAgICAgICAgICAgaW5wdXRJbWFnZS5vbnN0YWxsZWQgPSByZWplY3Q7XG4gICAgICAgICAgICBpbnB1dEltYWdlLm9uc3VzcGVuZCA9IHJlamVjdDtcbiAgICAgICAgICAgIGlucHV0SW1hZ2Uuc3JjID0gVVJMLmNyZWF0ZU9iamVjdFVSTChpbWFnZUZpbGUpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jbGVhckVsZW1lbnQoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLmdldENhbWVyYXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBDYW1lcmFSZXRyaWV2ZXIucmV0cmlldmUoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5nZXRSdW5uaW5nVHJhY2tDYXBhYmlsaXRpZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFJlbmRlcmVkQ2FtZXJhT3JGYWlsKCkuZ2V0UnVubmluZ1RyYWNrQ2FwYWJpbGl0aWVzKCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuZ2V0UnVubmluZ1RyYWNrU2V0dGluZ3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFJlbmRlcmVkQ2FtZXJhT3JGYWlsKCkuZ2V0UnVubmluZ1RyYWNrU2V0dGluZ3MoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5nZXRSdW5uaW5nVHJhY2tDYW1lcmFDYXBhYmlsaXRpZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFJlbmRlcmVkQ2FtZXJhT3JGYWlsKCkuZ2V0Q2FwYWJpbGl0aWVzKCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuYXBwbHlWaWRlb0NvbnN0cmFpbnRzID0gZnVuY3Rpb24gKHZpZGVvQ29uc3RhaW50cykge1xuICAgICAgICBpZiAoIXZpZGVvQ29uc3RhaW50cykge1xuICAgICAgICAgICAgdGhyb3cgXCJ2aWRlb0NvbnN0YWludHMgaXMgcmVxdWlyZWQgYXJndW1lbnQuXCI7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIVZpZGVvQ29uc3RyYWludHNVdGlsLmlzTWVkaWFTdHJlYW1Db25zdHJhaW50c1ZhbGlkKHZpZGVvQ29uc3RhaW50cywgdGhpcy5sb2dnZXIpKSB7XG4gICAgICAgICAgICB0aHJvdyBcImludmFsaWQgdmlkZW9Db25zdGFpbnRzIHBhc3NlZCwgY2hlY2sgbG9ncyBmb3IgbW9yZSBkZXRhaWxzXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVuZGVyZWRDYW1lcmFPckZhaWwoKS5hcHBseVZpZGVvQ29uc3RyYWludHModmlkZW9Db25zdGFpbnRzKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5nZXRSZW5kZXJlZENhbWVyYU9yRmFpbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMucmVuZGVyZWRDYW1lcmEgPT0gbnVsbCkge1xuICAgICAgICAgICAgdGhyb3cgXCJTY2FubmluZyBpcyBub3QgaW4gcnVubmluZyBzdGF0ZSwgY2FsbCB0aGlzIEFQSSBvbmx5IHdoZW5cIlxuICAgICAgICAgICAgICAgICsgXCIgUVIgY29kZSBzY2FubmluZyB1c2luZyBjYW1lcmEgaXMgaW4gcnVubmluZyBzdGF0ZS5cIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5yZW5kZXJlZENhbWVyYTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5nZXRTdXBwb3J0ZWRGb3JtYXRzID0gZnVuY3Rpb24gKGNvbmZpZ09yVmVyYm9zaXR5RmxhZykge1xuICAgICAgICB2YXIgYWxsRm9ybWF0cyA9IFtcbiAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5RUl9DT0RFLFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkFaVEVDLFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREFCQVIsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQ09ERV8zOSxcbiAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzkzLFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfMTI4LFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkRBVEFfTUFUUklYLFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLk1BWElDT0RFLFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLklURixcbiAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5FQU5fMTMsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuRUFOXzgsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUERGXzQxNyxcbiAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5SU1NfMTQsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUlNTX0VYUEFOREVELFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlVQQ19BLFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlVQQ19FLFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlVQQ19FQU5fRVhURU5TSU9OLFxuICAgICAgICBdO1xuICAgICAgICBpZiAoIWNvbmZpZ09yVmVyYm9zaXR5RmxhZ1xuICAgICAgICAgICAgfHwgdHlwZW9mIGNvbmZpZ09yVmVyYm9zaXR5RmxhZyA9PSBcImJvb2xlYW5cIikge1xuICAgICAgICAgICAgcmV0dXJuIGFsbEZvcm1hdHM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFjb25maWdPclZlcmJvc2l0eUZsYWcuZm9ybWF0c1RvU3VwcG9ydCkge1xuICAgICAgICAgICAgcmV0dXJuIGFsbEZvcm1hdHM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGNvbmZpZ09yVmVyYm9zaXR5RmxhZy5mb3JtYXRzVG9TdXBwb3J0KSkge1xuICAgICAgICAgICAgdGhyb3cgXCJjb25maWdPclZlcmJvc2l0eUZsYWcuZm9ybWF0c1RvU3VwcG9ydCBzaG91bGQgYmUgdW5kZWZpbmVkIFwiXG4gICAgICAgICAgICAgICAgKyBcIm9yIGFuIGFycmF5LlwiO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb25maWdPclZlcmJvc2l0eUZsYWcuZm9ybWF0c1RvU3VwcG9ydC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IFwiQXRsZWFzdCAxIGZvcm1hdHNUb1N1cHBvcnQgaXMgbmVlZGVkLlwiO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzdXBwb3J0ZWRGb3JtYXRzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBjb25maWdPclZlcmJvc2l0eUZsYWcuZm9ybWF0c1RvU3VwcG9ydDsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBmb3JtYXQgPSBfYVtfaV07XG4gICAgICAgICAgICBpZiAoaXNWYWxpZEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyhmb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgc3VwcG9ydGVkRm9ybWF0cy5wdXNoKGZvcm1hdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci53YXJuKFwiSW52YWxpZCBmb3JtYXQ6IFwiLmNvbmNhdChmb3JtYXQsIFwiIHBhc3NlZCBpbiBjb25maWcsIGlnbm9yaW5nLlwiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN1cHBvcnRlZEZvcm1hdHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICB0aHJvdyBcIk5vbmUgb2YgZm9ybWF0c1RvU3VwcG9ydCBtYXRjaCBzdXBwb3J0ZWQgdmFsdWVzLlwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdXBwb3J0ZWRGb3JtYXRzO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFVzZUJhckNvZGVEZXRlY3RvcklmU3VwcG9ydGVkID0gZnVuY3Rpb24gKGNvbmZpZykge1xuICAgICAgICBpZiAoaXNOdWxsT3JVbmRlZmluZWQoY29uZmlnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc051bGxPclVuZGVmaW5lZChjb25maWcudXNlQmFyQ29kZURldGVjdG9ySWZTdXBwb3J0ZWQpKSB7XG4gICAgICAgICAgICByZXR1cm4gY29uZmlnLnVzZUJhckNvZGVEZXRlY3RvcklmU3VwcG9ydGVkICE9PSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNOdWxsT3JVbmRlZmluZWQoY29uZmlnLmV4cGVyaW1lbnRhbEZlYXR1cmVzKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGV4cGVyaW1lbnRhbEZlYXR1cmVzID0gY29uZmlnLmV4cGVyaW1lbnRhbEZlYXR1cmVzO1xuICAgICAgICBpZiAoaXNOdWxsT3JVbmRlZmluZWQoZXhwZXJpbWVudGFsRmVhdHVyZXMudXNlQmFyQ29kZURldGVjdG9ySWZTdXBwb3J0ZWQpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZXhwZXJpbWVudGFsRmVhdHVyZXMudXNlQmFyQ29kZURldGVjdG9ySWZTdXBwb3J0ZWQgIT09IGZhbHNlO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLnZhbGlkYXRlUXJib3hTaXplID0gZnVuY3Rpb24gKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCwgaW50ZXJuYWxDb25maWcpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHFyYm94U2l6ZSA9IGludGVybmFsQ29uZmlnLnFyYm94O1xuICAgICAgICB0aGlzLnZhbGlkYXRlUXJib3hDb25maWcocXJib3hTaXplKTtcbiAgICAgICAgdmFyIHFyRGltZW5zaW9ucyA9IHRoaXMudG9RcmRpbWVuc2lvbnModmlld2ZpbmRlcldpZHRoLCB2aWV3ZmluZGVySGVpZ2h0LCBxcmJveFNpemUpO1xuICAgICAgICB2YXIgdmFsaWRhdGVNaW5TaXplID0gZnVuY3Rpb24gKHNpemUpIHtcbiAgICAgICAgICAgIGlmIChzaXplIDwgQ29uc3RhbnRzLk1JTl9RUl9CT1hfU0laRSkge1xuICAgICAgICAgICAgICAgIHRocm93IFwibWluaW11bSBzaXplIG9mICdjb25maWcucXJib3gnIGRpbWVuc2lvbiB2YWx1ZSBpc1wiXG4gICAgICAgICAgICAgICAgICAgICsgXCIgXCIuY29uY2F0KENvbnN0YW50cy5NSU5fUVJfQk9YX1NJWkUsIFwicHguXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgY29ycmVjdFdpZHRoQmFzZWRPblJvb3RFbGVtZW50U2l6ZSA9IGZ1bmN0aW9uIChjb25maWdXaWR0aCkge1xuICAgICAgICAgICAgaWYgKGNvbmZpZ1dpZHRoID4gdmlld2ZpbmRlcldpZHRoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMubG9nZ2VyLndhcm4oXCJgcXJib3gud2lkdGhgIG9yIGBxcmJveGAgaXMgbGFyZ2VyIHRoYW4gdGhlXCJcbiAgICAgICAgICAgICAgICAgICAgKyBcIiB3aWR0aCBvZiB0aGUgcm9vdCBlbGVtZW50LiBUaGUgd2lkdGggd2lsbCBiZSB0cnVuY2F0ZWRcIlxuICAgICAgICAgICAgICAgICAgICArIFwiIHRvIHRoZSB3aWR0aCBvZiByb290IGVsZW1lbnQuXCIpO1xuICAgICAgICAgICAgICAgIGNvbmZpZ1dpZHRoID0gdmlld2ZpbmRlcldpZHRoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGNvbmZpZ1dpZHRoO1xuICAgICAgICB9O1xuICAgICAgICB2YWxpZGF0ZU1pblNpemUocXJEaW1lbnNpb25zLndpZHRoKTtcbiAgICAgICAgdmFsaWRhdGVNaW5TaXplKHFyRGltZW5zaW9ucy5oZWlnaHQpO1xuICAgICAgICBxckRpbWVuc2lvbnMud2lkdGggPSBjb3JyZWN0V2lkdGhCYXNlZE9uUm9vdEVsZW1lbnRTaXplKHFyRGltZW5zaW9ucy53aWR0aCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUudmFsaWRhdGVRcmJveENvbmZpZyA9IGZ1bmN0aW9uIChxcmJveFNpemUpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBxcmJveFNpemUgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHFyYm94U2l6ZSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHFyYm94U2l6ZS53aWR0aCA9PT0gdW5kZWZpbmVkIHx8IHFyYm94U2l6ZS5oZWlnaHQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgXCJJbnZhbGlkIGluc3RhbmNlIG9mIFFyRGltZW5zaW9ucyBwYXNzZWQgZm9yIFwiXG4gICAgICAgICAgICAgICAgKyBcIidjb25maWcucXJib3gnLiBCb3RoICd3aWR0aCcgYW5kICdoZWlnaHQnIHNob3VsZCBiZSBzZXQuXCI7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS50b1FyZGltZW5zaW9ucyA9IGZ1bmN0aW9uICh2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQsIHFyYm94U2l6ZSkge1xuICAgICAgICBpZiAodHlwZW9mIHFyYm94U2l6ZSA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgcmV0dXJuIHsgd2lkdGg6IHFyYm94U2l6ZSwgaGVpZ2h0OiBxcmJveFNpemUgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgcXJib3hTaXplID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHFyYm94U2l6ZSh2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwicXJib3ggY29uZmlnIHdhcyBwYXNzZWQgYXMgYSBmdW5jdGlvbiBidXQgaXQgZmFpbGVkIHdpdGggXCJcbiAgICAgICAgICAgICAgICAgICAgKyBcInVua25vd24gZXJyb3JcIiArIGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcXJib3hTaXplO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLnNldHVwVWkgPSBmdW5jdGlvbiAodmlld2ZpbmRlcldpZHRoLCB2aWV3ZmluZGVySGVpZ2h0LCBpbnRlcm5hbENvbmZpZykge1xuICAgICAgICBpZiAoaW50ZXJuYWxDb25maWcuaXNTaGFkZWRCb3hFbmFibGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMudmFsaWRhdGVRcmJveFNpemUodmlld2ZpbmRlcldpZHRoLCB2aWV3ZmluZGVySGVpZ2h0LCBpbnRlcm5hbENvbmZpZyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHFyYm94U2l6ZSA9IGlzTnVsbE9yVW5kZWZpbmVkKGludGVybmFsQ29uZmlnLnFyYm94KSA/XG4gICAgICAgICAgICB7IHdpZHRoOiB2aWV3ZmluZGVyV2lkdGgsIGhlaWdodDogdmlld2ZpbmRlckhlaWdodCB9IDogaW50ZXJuYWxDb25maWcucXJib3g7XG4gICAgICAgIHRoaXMudmFsaWRhdGVRcmJveENvbmZpZyhxcmJveFNpemUpO1xuICAgICAgICB2YXIgcXJEaW1lbnNpb25zID0gdGhpcy50b1FyZGltZW5zaW9ucyh2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQsIHFyYm94U2l6ZSk7XG4gICAgICAgIGlmIChxckRpbWVuc2lvbnMuaGVpZ2h0ID4gdmlld2ZpbmRlckhlaWdodCkge1xuICAgICAgICAgICAgdGhpcy5sb2dnZXIud2FybihcIltIdG1sNVFyY29kZV0gY29uZmlnLnFyYm94IGhhcyBoZWlnaHQgdGhhdCBpc1wiXG4gICAgICAgICAgICAgICAgKyBcImdyZWF0ZXIgdGhhbiB0aGUgaGVpZ2h0IG9mIHRoZSB2aWRlbyBzdHJlYW0uIFNoYWRpbmcgd2lsbCBiZVwiXG4gICAgICAgICAgICAgICAgKyBcIiBpZ25vcmVkXCIpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzaG91bGRTaGFkaW5nQmVBcHBsaWVkID0gaW50ZXJuYWxDb25maWcuaXNTaGFkZWRCb3hFbmFibGVkKClcbiAgICAgICAgICAgICYmIHFyRGltZW5zaW9ucy5oZWlnaHQgPD0gdmlld2ZpbmRlckhlaWdodDtcbiAgICAgICAgdmFyIGRlZmF1bHRRclJlZ2lvbiA9IHtcbiAgICAgICAgICAgIHg6IDAsXG4gICAgICAgICAgICB5OiAwLFxuICAgICAgICAgICAgd2lkdGg6IHZpZXdmaW5kZXJXaWR0aCxcbiAgICAgICAgICAgIGhlaWdodDogdmlld2ZpbmRlckhlaWdodFxuICAgICAgICB9O1xuICAgICAgICB2YXIgcXJSZWdpb24gPSBzaG91bGRTaGFkaW5nQmVBcHBsaWVkXG4gICAgICAgICAgICA/IHRoaXMuZ2V0U2hhZGVkUmVnaW9uQm91bmRzKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCwgcXJEaW1lbnNpb25zKVxuICAgICAgICAgICAgOiBkZWZhdWx0UXJSZWdpb247XG4gICAgICAgIHZhciBjYW52YXNFbGVtZW50ID0gdGhpcy5jcmVhdGVDYW52YXNFbGVtZW50KHFyUmVnaW9uLndpZHRoLCBxclJlZ2lvbi5oZWlnaHQpO1xuICAgICAgICB2YXIgY29udGV4dEF0dHJpYnV0ZXMgPSB7IHdpbGxSZWFkRnJlcXVlbnRseTogdHJ1ZSB9O1xuICAgICAgICB2YXIgY29udGV4dCA9IGNhbnZhc0VsZW1lbnQuZ2V0Q29udGV4dChcIjJkXCIsIGNvbnRleHRBdHRyaWJ1dGVzKTtcbiAgICAgICAgY29udGV4dC5jYW52YXMud2lkdGggPSBxclJlZ2lvbi53aWR0aDtcbiAgICAgICAgY29udGV4dC5jYW52YXMuaGVpZ2h0ID0gcXJSZWdpb24uaGVpZ2h0O1xuICAgICAgICB0aGlzLmVsZW1lbnQuYXBwZW5kKGNhbnZhc0VsZW1lbnQpO1xuICAgICAgICBpZiAoc2hvdWxkU2hhZGluZ0JlQXBwbGllZCkge1xuICAgICAgICAgICAgdGhpcy5wb3NzaWJseUluc2VydFNoYWRpbmdFbGVtZW50KHRoaXMuZWxlbWVudCwgdmlld2ZpbmRlcldpZHRoLCB2aWV3ZmluZGVySGVpZ2h0LCBxckRpbWVuc2lvbnMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY3JlYXRlU2Nhbm5lclBhdXNlZFVpRWxlbWVudCh0aGlzLmVsZW1lbnQpO1xuICAgICAgICB0aGlzLnFyUmVnaW9uID0gcXJSZWdpb247XG4gICAgICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHQ7XG4gICAgICAgIHRoaXMuY2FudmFzRWxlbWVudCA9IGNhbnZhc0VsZW1lbnQ7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuY3JlYXRlU2Nhbm5lclBhdXNlZFVpRWxlbWVudCA9IGZ1bmN0aW9uIChyb290RWxlbWVudCkge1xuICAgICAgICB2YXIgc2Nhbm5lclBhdXNlZFVpRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHNjYW5uZXJQYXVzZWRVaUVsZW1lbnQuaW5uZXJUZXh0ID0gSHRtbDVRcmNvZGVTdHJpbmdzLnNjYW5uZXJQYXVzZWQoKTtcbiAgICAgICAgc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICAgIHNjYW5uZXJQYXVzZWRVaUVsZW1lbnQuc3R5bGUucG9zaXRpb24gPSBcImFic29sdXRlXCI7XG4gICAgICAgIHNjYW5uZXJQYXVzZWRVaUVsZW1lbnQuc3R5bGUudG9wID0gXCIwcHhcIjtcbiAgICAgICAgc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS56SW5kZXggPSBcIjFcIjtcbiAgICAgICAgc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS5iYWNrZ3JvdW5kID0gXCJyZ2JhKDksIDksIDksIDAuNDYpXCI7XG4gICAgICAgIHNjYW5uZXJQYXVzZWRVaUVsZW1lbnQuc3R5bGUuY29sb3IgPSBcIiNGRkVDRUNcIjtcbiAgICAgICAgc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS50ZXh0QWxpZ24gPSBcImNlbnRlclwiO1xuICAgICAgICBzY2FubmVyUGF1c2VkVWlFbGVtZW50LnN0eWxlLndpZHRoID0gXCIxMDAlXCI7XG4gICAgICAgIHJvb3RFbGVtZW50LmFwcGVuZENoaWxkKHNjYW5uZXJQYXVzZWRVaUVsZW1lbnQpO1xuICAgICAgICB0aGlzLnNjYW5uZXJQYXVzZWRVaUVsZW1lbnQgPSBzY2FubmVyUGF1c2VkVWlFbGVtZW50O1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLnNjYW5Db250ZXh0ID0gZnVuY3Rpb24gKHFyQ29kZVN1Y2Nlc3NDYWxsYmFjaywgcXJDb2RlRXJyb3JDYWxsYmFjaykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAodGhpcy5zdGF0ZU1hbmFnZXJQcm94eS5pc1BhdXNlZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5xcmNvZGUuZGVjb2RlQXN5bmModGhpcy5jYW52YXNFbGVtZW50KVxuICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgcXJDb2RlU3VjY2Vzc0NhbGxiYWNrKHJlc3VsdC50ZXh0LCBIdG1sNVFyY29kZVJlc3VsdEZhY3RvcnkuY3JlYXRlRnJvbVFyY29kZVJlc3VsdChyZXN1bHQpKTtcbiAgICAgICAgICAgIF90aGlzLnBvc3NpYmx5VXBkYXRlU2hhZGVycyh0cnVlKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KS5jYXRjaChmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgIF90aGlzLnBvc3NpYmx5VXBkYXRlU2hhZGVycyhmYWxzZSk7XG4gICAgICAgICAgICB2YXIgZXJyb3JNZXNzYWdlID0gSHRtbDVRcmNvZGVTdHJpbmdzLmNvZGVQYXJzZUVycm9yKGVycm9yKTtcbiAgICAgICAgICAgIHFyQ29kZUVycm9yQ2FsbGJhY2soZXJyb3JNZXNzYWdlLCBIdG1sNVFyY29kZUVycm9yRmFjdG9yeS5jcmVhdGVGcm9tKGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5mb3JldmVyU2NhbiA9IGZ1bmN0aW9uIChpbnRlcm5hbENvbmZpZywgcXJDb2RlU3VjY2Vzc0NhbGxiYWNrLCBxckNvZGVFcnJvckNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdGhpcy5zaG91bGRTY2FuKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnJlbmRlcmVkQ2FtZXJhKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHZpZGVvRWxlbWVudCA9IHRoaXMucmVuZGVyZWRDYW1lcmEuZ2V0U3VyZmFjZSgpO1xuICAgICAgICB2YXIgd2lkdGhSYXRpbyA9IHZpZGVvRWxlbWVudC52aWRlb1dpZHRoIC8gdmlkZW9FbGVtZW50LmNsaWVudFdpZHRoO1xuICAgICAgICB2YXIgaGVpZ2h0UmF0aW8gPSB2aWRlb0VsZW1lbnQudmlkZW9IZWlnaHQgLyB2aWRlb0VsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICAgICAgICBpZiAoIXRoaXMucXJSZWdpb24pIHtcbiAgICAgICAgICAgIHRocm93IFwicXJSZWdpb24gdW5kZWZpbmVkIHdoZW4gbG9jYWxNZWRpYVN0cmVhbSBpcyByZWFkeS5cIjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc1dpZHRoT2Zmc2V0ID0gdGhpcy5xclJlZ2lvbi53aWR0aCAqIHdpZHRoUmF0aW87XG4gICAgICAgIHZhciBzSGVpZ2h0T2Zmc2V0ID0gdGhpcy5xclJlZ2lvbi5oZWlnaHQgKiBoZWlnaHRSYXRpbztcbiAgICAgICAgdmFyIHN4T2Zmc2V0ID0gdGhpcy5xclJlZ2lvbi54ICogd2lkdGhSYXRpbztcbiAgICAgICAgdmFyIHN5T2Zmc2V0ID0gdGhpcy5xclJlZ2lvbi55ICogaGVpZ2h0UmF0aW87XG4gICAgICAgIHRoaXMuY29udGV4dC5kcmF3SW1hZ2UodmlkZW9FbGVtZW50LCBzeE9mZnNldCwgc3lPZmZzZXQsIHNXaWR0aE9mZnNldCwgc0hlaWdodE9mZnNldCwgMCwgMCwgdGhpcy5xclJlZ2lvbi53aWR0aCwgdGhpcy5xclJlZ2lvbi5oZWlnaHQpO1xuICAgICAgICB2YXIgdHJpZ2dlck5leHRTY2FuID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMuZm9yZXZlclNjYW5UaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZm9yZXZlclNjYW4oaW50ZXJuYWxDb25maWcsIHFyQ29kZVN1Y2Nlc3NDYWxsYmFjaywgcXJDb2RlRXJyb3JDYWxsYmFjayk7XG4gICAgICAgICAgICB9LCBfdGhpcy5nZXRUaW1lb3V0RnBzKGludGVybmFsQ29uZmlnLmZwcykpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnNjYW5Db250ZXh0KHFyQ29kZVN1Y2Nlc3NDYWxsYmFjaywgcXJDb2RlRXJyb3JDYWxsYmFjaylcbiAgICAgICAgICAgIC50aGVuKGZ1bmN0aW9uIChpc1N1Y2Nlc3NmdWxsKSB7XG4gICAgICAgICAgICBpZiAoIWlzU3VjY2Vzc2Z1bGwgJiYgaW50ZXJuYWxDb25maWcuZGlzYWJsZUZsaXAgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5jb250ZXh0LnRyYW5zbGF0ZShfdGhpcy5jb250ZXh0LmNhbnZhcy53aWR0aCwgMCk7XG4gICAgICAgICAgICAgICAgX3RoaXMuY29udGV4dC5zY2FsZSgtMSwgMSk7XG4gICAgICAgICAgICAgICAgX3RoaXMuc2NhbkNvbnRleHQocXJDb2RlU3VjY2Vzc0NhbGxiYWNrLCBxckNvZGVFcnJvckNhbGxiYWNrKVxuICAgICAgICAgICAgICAgICAgICAuZmluYWxseShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyaWdnZXJOZXh0U2NhbigpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdHJpZ2dlck5leHRTY2FuKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgX3RoaXMubG9nZ2VyLmxvZ0Vycm9yKFwiRXJyb3IgaGFwcGVuZCB3aGlsZSBzY2FubmluZyBjb250ZXh0XCIsIGVycm9yKTtcbiAgICAgICAgICAgIHRyaWdnZXJOZXh0U2NhbigpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5jcmVhdGVWaWRlb0NvbnN0cmFpbnRzID0gZnVuY3Rpb24gKGNhbWVyYUlkT3JDb25maWcpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBjYW1lcmFJZE9yQ29uZmlnID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIHJldHVybiB7IGRldmljZUlkOiB7IGV4YWN0OiBjYW1lcmFJZE9yQ29uZmlnIH0gfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgY2FtZXJhSWRPckNvbmZpZyA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICB2YXIgZmFjaW5nTW9kZUtleSA9IFwiZmFjaW5nTW9kZVwiO1xuICAgICAgICAgICAgdmFyIGRldmljZUlkS2V5ID0gXCJkZXZpY2VJZFwiO1xuICAgICAgICAgICAgdmFyIGFsbG93ZWRGYWNpbmdNb2RlVmFsdWVzXzEgPSB7IFwidXNlclwiOiB0cnVlLCBcImVudmlyb25tZW50XCI6IHRydWUgfTtcbiAgICAgICAgICAgIHZhciBleGFjdEtleSA9IFwiZXhhY3RcIjtcbiAgICAgICAgICAgIHZhciBpc1ZhbGlkRmFjaW5nTW9kZVZhbHVlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHZhbHVlIGluIGFsbG93ZWRGYWNpbmdNb2RlVmFsdWVzXzEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBcImNvbmZpZyBoYXMgaW52YWxpZCAnZmFjaW5nTW9kZScgdmFsdWUgPSBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgKyBcIidcIi5jb25jYXQodmFsdWUsIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhjYW1lcmFJZE9yQ29uZmlnKTtcbiAgICAgICAgICAgIGlmIChrZXlzLmxlbmd0aCAhPT0gMSkge1xuICAgICAgICAgICAgICAgIHRocm93IFwiJ2NhbWVyYUlkT3JDb25maWcnIG9iamVjdCBzaG91bGQgaGF2ZSBleGFjdGx5IDEga2V5LFwiXG4gICAgICAgICAgICAgICAgICAgICsgXCIgaWYgcGFzc2VkIGFzIGFuIG9iamVjdCwgZm91bmQgXCIuY29uY2F0KGtleXMubGVuZ3RoLCBcIiBrZXlzXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGtleSA9IE9iamVjdC5rZXlzKGNhbWVyYUlkT3JDb25maWcpWzBdO1xuICAgICAgICAgICAgaWYgKGtleSAhPT0gZmFjaW5nTW9kZUtleSAmJiBrZXkgIT09IGRldmljZUlkS2V5KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgXCJPbmx5ICdcIi5jb25jYXQoZmFjaW5nTW9kZUtleSwgXCInIGFuZCAnXCIpLmNvbmNhdChkZXZpY2VJZEtleSwgXCInIFwiKVxuICAgICAgICAgICAgICAgICAgICArIFwiIGFyZSBzdXBwb3J0ZWQgZm9yICdjYW1lcmFJZE9yQ29uZmlnJ1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGtleSA9PT0gZmFjaW5nTW9kZUtleSkge1xuICAgICAgICAgICAgICAgIHZhciBmYWNpbmdNb2RlID0gY2FtZXJhSWRPckNvbmZpZy5mYWNpbmdNb2RlO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZmFjaW5nTW9kZSA9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZhbGlkRmFjaW5nTW9kZVZhbHVlKGZhY2luZ01vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4geyBmYWNpbmdNb2RlOiBmYWNpbmdNb2RlIH07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIGZhY2luZ01vZGUgPT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXhhY3RLZXkgaW4gZmFjaW5nTW9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVmFsaWRGYWNpbmdNb2RlVmFsdWUoZmFjaW5nTW9kZVtcIlwiLmNvbmNhdChleGFjdEtleSldKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY2luZ01vZGU6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4YWN0OiBmYWNpbmdNb2RlW1wiXCIuY29uY2F0KGV4YWN0S2V5KV1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBcIidmYWNpbmdNb2RlJyBzaG91bGQgYmUgc3RyaW5nIG9yIG9iamVjdCB3aXRoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICArIFwiIFwiLmNvbmNhdChleGFjdEtleSwgXCIgYXMga2V5LlwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHR5cGVfMSA9ICh0eXBlb2YgZmFjaW5nTW9kZSk7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwiSW52YWxpZCB0eXBlIG9mICdmYWNpbmdNb2RlJyA9IFwiLmNvbmNhdCh0eXBlXzEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBkZXZpY2VJZCA9IGNhbWVyYUlkT3JDb25maWcuZGV2aWNlSWQ7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkZXZpY2VJZCA9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7IGRldmljZUlkOiBkZXZpY2VJZCB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2YgZGV2aWNlSWQgPT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXhhY3RLZXkgaW4gZGV2aWNlSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2aWNlSWQ6IHsgZXhhY3Q6IGRldmljZUlkW1wiXCIuY29uY2F0KGV4YWN0S2V5KV0gfVxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFwiJ2RldmljZUlkJyBzaG91bGQgYmUgc3RyaW5nIG9yIG9iamVjdCB3aXRoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICArIFwiIFwiLmNvbmNhdChleGFjdEtleSwgXCIgYXMga2V5LlwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHR5cGVfMiA9ICh0eXBlb2YgZGV2aWNlSWQpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBcIkludmFsaWQgdHlwZSBvZiAnZGV2aWNlSWQnID0gXCIuY29uY2F0KHR5cGVfMik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciB0eXBlID0gKHR5cGVvZiBjYW1lcmFJZE9yQ29uZmlnKTtcbiAgICAgICAgdGhyb3cgXCJJbnZhbGlkIHR5cGUgb2YgJ2NhbWVyYUlkT3JDb25maWcnID0gXCIuY29uY2F0KHR5cGUpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmNvbXB1dGVDYW52YXNEcmF3Q29uZmlnID0gZnVuY3Rpb24gKGltYWdlV2lkdGgsIGltYWdlSGVpZ2h0LCBjb250YWluZXJXaWR0aCwgY29udGFpbmVySGVpZ2h0KSB7XG4gICAgICAgIGlmIChpbWFnZVdpZHRoIDw9IGNvbnRhaW5lcldpZHRoXG4gICAgICAgICAgICAmJiBpbWFnZUhlaWdodCA8PSBjb250YWluZXJIZWlnaHQpIHtcbiAgICAgICAgICAgIHZhciB4b2Zmc2V0ID0gKGNvbnRhaW5lcldpZHRoIC0gaW1hZ2VXaWR0aCkgLyAyO1xuICAgICAgICAgICAgdmFyIHlvZmZzZXQgPSAoY29udGFpbmVySGVpZ2h0IC0gaW1hZ2VIZWlnaHQpIC8gMjtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgeDogeG9mZnNldCxcbiAgICAgICAgICAgICAgICB5OiB5b2Zmc2V0LFxuICAgICAgICAgICAgICAgIHdpZHRoOiBpbWFnZVdpZHRoLFxuICAgICAgICAgICAgICAgIGhlaWdodDogaW1hZ2VIZWlnaHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgZm9ybWVySW1hZ2VXaWR0aCA9IGltYWdlV2lkdGg7XG4gICAgICAgICAgICB2YXIgZm9ybWVySW1hZ2VIZWlnaHQgPSBpbWFnZUhlaWdodDtcbiAgICAgICAgICAgIGlmIChpbWFnZVdpZHRoID4gY29udGFpbmVyV2lkdGgpIHtcbiAgICAgICAgICAgICAgICBpbWFnZUhlaWdodCA9IChjb250YWluZXJXaWR0aCAvIGltYWdlV2lkdGgpICogaW1hZ2VIZWlnaHQ7XG4gICAgICAgICAgICAgICAgaW1hZ2VXaWR0aCA9IGNvbnRhaW5lcldpZHRoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGltYWdlSGVpZ2h0ID4gY29udGFpbmVySGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaW1hZ2VXaWR0aCA9IChjb250YWluZXJIZWlnaHQgLyBpbWFnZUhlaWdodCkgKiBpbWFnZVdpZHRoO1xuICAgICAgICAgICAgICAgIGltYWdlSGVpZ2h0ID0gY29udGFpbmVySGVpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5sb2dnZXIubG9nKFwiSW1hZ2UgZG93bnNhbXBsZWQgZnJvbSBcIlxuICAgICAgICAgICAgICAgICsgXCJcIi5jb25jYXQoZm9ybWVySW1hZ2VXaWR0aCwgXCJYXCIpLmNvbmNhdChmb3JtZXJJbWFnZUhlaWdodClcbiAgICAgICAgICAgICAgICArIFwiIHRvIFwiLmNvbmNhdChpbWFnZVdpZHRoLCBcIlhcIikuY29uY2F0KGltYWdlSGVpZ2h0LCBcIi5cIikpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29tcHV0ZUNhbnZhc0RyYXdDb25maWcoaW1hZ2VXaWR0aCwgaW1hZ2VIZWlnaHQsIGNvbnRhaW5lcldpZHRoLCBjb250YWluZXJIZWlnaHQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuY2xlYXJFbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5zdGF0ZU1hbmFnZXJQcm94eS5pc1NjYW5uaW5nKCkpIHtcbiAgICAgICAgICAgIHRocm93IFwiQ2Fubm90IGNsZWFyIHdoaWxlIHNjYW4gaXMgb25nb2luZywgY2xvc2UgaXQgZmlyc3QuXCI7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmVsZW1lbnRJZCk7XG4gICAgICAgIGlmIChlbGVtZW50KSB7XG4gICAgICAgICAgICBlbGVtZW50LmlubmVySFRNTCA9IFwiXCI7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5wb3NzaWJseVVwZGF0ZVNoYWRlcnMgPSBmdW5jdGlvbiAocXJNYXRjaCkge1xuICAgICAgICBpZiAodGhpcy5xck1hdGNoID09PSBxck1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaGFzQm9yZGVyU2hhZGVyc1xuICAgICAgICAgICAgJiYgdGhpcy5ib3JkZXJTaGFkZXJzXG4gICAgICAgICAgICAmJiB0aGlzLmJvcmRlclNoYWRlcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aGlzLmJvcmRlclNoYWRlcnMuZm9yRWFjaChmdW5jdGlvbiAoc2hhZGVyKSB7XG4gICAgICAgICAgICAgICAgc2hhZGVyLnN0eWxlLmJhY2tncm91bmRDb2xvciA9IHFyTWF0Y2hcbiAgICAgICAgICAgICAgICAgICAgPyBDb25zdGFudHMuQk9SREVSX1NIQURFUl9NQVRDSF9DT0xPUlxuICAgICAgICAgICAgICAgICAgICA6IENvbnN0YW50cy5CT1JERVJfU0hBREVSX0RFRkFVTFRfQ09MT1I7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnFyTWF0Y2ggPSBxck1hdGNoO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLnBvc3NpYmx5Q2xvc2VMYXN0U2NhbkltYWdlRmlsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMubGFzdFNjYW5JbWFnZUZpbGUpIHtcbiAgICAgICAgICAgIFVSTC5yZXZva2VPYmplY3RVUkwodGhpcy5sYXN0U2NhbkltYWdlRmlsZSk7XG4gICAgICAgICAgICB0aGlzLmxhc3RTY2FuSW1hZ2VGaWxlID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmNyZWF0ZUNhbnZhc0VsZW1lbnQgPSBmdW5jdGlvbiAod2lkdGgsIGhlaWdodCwgY3VzdG9tSWQpIHtcbiAgICAgICAgdmFyIGNhbnZhc1dpZHRoID0gd2lkdGg7XG4gICAgICAgIHZhciBjYW52YXNIZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgIHZhciBjYW52YXNFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKTtcbiAgICAgICAgY2FudmFzRWxlbWVudC5zdHlsZS53aWR0aCA9IFwiXCIuY29uY2F0KGNhbnZhc1dpZHRoLCBcInB4XCIpO1xuICAgICAgICBjYW52YXNFbGVtZW50LnN0eWxlLmhlaWdodCA9IFwiXCIuY29uY2F0KGNhbnZhc0hlaWdodCwgXCJweFwiKTtcbiAgICAgICAgY2FudmFzRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICAgIGNhbnZhc0VsZW1lbnQuaWQgPSBpc051bGxPclVuZGVmaW5lZChjdXN0b21JZClcbiAgICAgICAgICAgID8gXCJxci1jYW52YXNcIiA6IGN1c3RvbUlkO1xuICAgICAgICByZXR1cm4gY2FudmFzRWxlbWVudDtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5nZXRTaGFkZWRSZWdpb25Cb3VuZHMgPSBmdW5jdGlvbiAod2lkdGgsIGhlaWdodCwgcXJib3hTaXplKSB7XG4gICAgICAgIGlmIChxcmJveFNpemUud2lkdGggPiB3aWR0aCB8fCBxcmJveFNpemUuaGVpZ2h0ID4gaGVpZ2h0KSB7XG4gICAgICAgICAgICB0aHJvdyBcIidjb25maWcucXJib3gnIGRpbWVuc2lvbnMgc2hvdWxkIG5vdCBiZSBncmVhdGVyIHRoYW4gdGhlIFwiXG4gICAgICAgICAgICAgICAgKyBcImRpbWVuc2lvbnMgb2YgdGhlIHJvb3QgSFRNTCBlbGVtZW50LlwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4OiAod2lkdGggLSBxcmJveFNpemUud2lkdGgpIC8gMixcbiAgICAgICAgICAgIHk6IChoZWlnaHQgLSBxcmJveFNpemUuaGVpZ2h0KSAvIDIsXG4gICAgICAgICAgICB3aWR0aDogcXJib3hTaXplLndpZHRoLFxuICAgICAgICAgICAgaGVpZ2h0OiBxcmJveFNpemUuaGVpZ2h0XG4gICAgICAgIH07XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUucG9zc2libHlJbnNlcnRTaGFkaW5nRWxlbWVudCA9IGZ1bmN0aW9uIChlbGVtZW50LCB3aWR0aCwgaGVpZ2h0LCBxcmJveFNpemUpIHtcbiAgICAgICAgaWYgKCh3aWR0aCAtIHFyYm94U2l6ZS53aWR0aCkgPCAxIHx8IChoZWlnaHQgLSBxcmJveFNpemUuaGVpZ2h0KSA8IDEpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc2hhZGluZ0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS5wb3NpdGlvbiA9IFwiYWJzb2x1dGVcIjtcbiAgICAgICAgdmFyIHJpZ2h0TGVmdEJvcmRlclNpemUgPSAod2lkdGggLSBxcmJveFNpemUud2lkdGgpIC8gMjtcbiAgICAgICAgdmFyIHRvcEJvdHRvbUJvcmRlclNpemUgPSAoaGVpZ2h0IC0gcXJib3hTaXplLmhlaWdodCkgLyAyO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS5ib3JkZXJMZWZ0XG4gICAgICAgICAgICA9IFwiXCIuY29uY2F0KHJpZ2h0TGVmdEJvcmRlclNpemUsIFwicHggc29saWQgcmdiYSgwLCAwLCAwLCAwLjQ4KVwiKTtcbiAgICAgICAgc2hhZGluZ0VsZW1lbnQuc3R5bGUuYm9yZGVyUmlnaHRcbiAgICAgICAgICAgID0gXCJcIi5jb25jYXQocmlnaHRMZWZ0Qm9yZGVyU2l6ZSwgXCJweCBzb2xpZCByZ2JhKDAsIDAsIDAsIDAuNDgpXCIpO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS5ib3JkZXJUb3BcbiAgICAgICAgICAgID0gXCJcIi5jb25jYXQodG9wQm90dG9tQm9yZGVyU2l6ZSwgXCJweCBzb2xpZCByZ2JhKDAsIDAsIDAsIDAuNDgpXCIpO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS5ib3JkZXJCb3R0b21cbiAgICAgICAgICAgID0gXCJcIi5jb25jYXQodG9wQm90dG9tQm9yZGVyU2l6ZSwgXCJweCBzb2xpZCByZ2JhKDAsIDAsIDAsIDAuNDgpXCIpO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS5ib3hTaXppbmcgPSBcImJvcmRlci1ib3hcIjtcbiAgICAgICAgc2hhZGluZ0VsZW1lbnQuc3R5bGUudG9wID0gXCIwcHhcIjtcbiAgICAgICAgc2hhZGluZ0VsZW1lbnQuc3R5bGUuYm90dG9tID0gXCIwcHhcIjtcbiAgICAgICAgc2hhZGluZ0VsZW1lbnQuc3R5bGUubGVmdCA9IFwiMHB4XCI7XG4gICAgICAgIHNoYWRpbmdFbGVtZW50LnN0eWxlLnJpZ2h0ID0gXCIwcHhcIjtcbiAgICAgICAgc2hhZGluZ0VsZW1lbnQuaWQgPSBcIlwiLmNvbmNhdChDb25zdGFudHMuU0hBREVEX1JFR0lPTl9FTEVNRU5UX0lEKTtcbiAgICAgICAgaWYgKCh3aWR0aCAtIHFyYm94U2l6ZS53aWR0aCkgPCAxMVxuICAgICAgICAgICAgfHwgKGhlaWdodCAtIHFyYm94U2l6ZS5oZWlnaHQpIDwgMTEpIHtcbiAgICAgICAgICAgIHRoaXMuaGFzQm9yZGVyU2hhZGVycyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIHNtYWxsU2l6ZSA9IDU7XG4gICAgICAgICAgICB2YXIgbGFyZ2VTaXplID0gNDA7XG4gICAgICAgICAgICB0aGlzLmluc2VydFNoYWRlckJvcmRlcnMoc2hhZGluZ0VsZW1lbnQsIGxhcmdlU2l6ZSwgc21hbGxTaXplLCAtc21hbGxTaXplLCBudWxsLCAwLCB0cnVlKTtcbiAgICAgICAgICAgIHRoaXMuaW5zZXJ0U2hhZGVyQm9yZGVycyhzaGFkaW5nRWxlbWVudCwgbGFyZ2VTaXplLCBzbWFsbFNpemUsIC1zbWFsbFNpemUsIG51bGwsIDAsIGZhbHNlKTtcbiAgICAgICAgICAgIHRoaXMuaW5zZXJ0U2hhZGVyQm9yZGVycyhzaGFkaW5nRWxlbWVudCwgbGFyZ2VTaXplLCBzbWFsbFNpemUsIG51bGwsIC1zbWFsbFNpemUsIDAsIHRydWUpO1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRTaGFkZXJCb3JkZXJzKHNoYWRpbmdFbGVtZW50LCBsYXJnZVNpemUsIHNtYWxsU2l6ZSwgbnVsbCwgLXNtYWxsU2l6ZSwgMCwgZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRTaGFkZXJCb3JkZXJzKHNoYWRpbmdFbGVtZW50LCBzbWFsbFNpemUsIGxhcmdlU2l6ZSArIHNtYWxsU2l6ZSwgLXNtYWxsU2l6ZSwgbnVsbCwgLXNtYWxsU2l6ZSwgdHJ1ZSk7XG4gICAgICAgICAgICB0aGlzLmluc2VydFNoYWRlckJvcmRlcnMoc2hhZGluZ0VsZW1lbnQsIHNtYWxsU2l6ZSwgbGFyZ2VTaXplICsgc21hbGxTaXplLCBudWxsLCAtc21hbGxTaXplLCAtc21hbGxTaXplLCB0cnVlKTtcbiAgICAgICAgICAgIHRoaXMuaW5zZXJ0U2hhZGVyQm9yZGVycyhzaGFkaW5nRWxlbWVudCwgc21hbGxTaXplLCBsYXJnZVNpemUgKyBzbWFsbFNpemUsIC1zbWFsbFNpemUsIG51bGwsIC1zbWFsbFNpemUsIGZhbHNlKTtcbiAgICAgICAgICAgIHRoaXMuaW5zZXJ0U2hhZGVyQm9yZGVycyhzaGFkaW5nRWxlbWVudCwgc21hbGxTaXplLCBsYXJnZVNpemUgKyBzbWFsbFNpemUsIG51bGwsIC1zbWFsbFNpemUsIC1zbWFsbFNpemUsIGZhbHNlKTtcbiAgICAgICAgICAgIHRoaXMuaGFzQm9yZGVyU2hhZGVycyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxlbWVudC5hcHBlbmQoc2hhZGluZ0VsZW1lbnQpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmluc2VydFNoYWRlckJvcmRlcnMgPSBmdW5jdGlvbiAoc2hhZGVyRWxlbSwgd2lkdGgsIGhlaWdodCwgdG9wLCBib3R0b20sIHNpZGUsIGlzTGVmdCkge1xuICAgICAgICB2YXIgZWxlbSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIGVsZW0uc3R5bGUucG9zaXRpb24gPSBcImFic29sdXRlXCI7XG4gICAgICAgIGVsZW0uc3R5bGUuYmFja2dyb3VuZENvbG9yID0gQ29uc3RhbnRzLkJPUkRFUl9TSEFERVJfREVGQVVMVF9DT0xPUjtcbiAgICAgICAgZWxlbS5zdHlsZS53aWR0aCA9IFwiXCIuY29uY2F0KHdpZHRoLCBcInB4XCIpO1xuICAgICAgICBlbGVtLnN0eWxlLmhlaWdodCA9IFwiXCIuY29uY2F0KGhlaWdodCwgXCJweFwiKTtcbiAgICAgICAgaWYgKHRvcCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgZWxlbS5zdHlsZS50b3AgPSBcIlwiLmNvbmNhdCh0b3AsIFwicHhcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGJvdHRvbSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgZWxlbS5zdHlsZS5ib3R0b20gPSBcIlwiLmNvbmNhdChib3R0b20sIFwicHhcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzTGVmdCkge1xuICAgICAgICAgICAgZWxlbS5zdHlsZS5sZWZ0ID0gXCJcIi5jb25jYXQoc2lkZSwgXCJweFwiKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGVsZW0uc3R5bGUucmlnaHQgPSBcIlwiLmNvbmNhdChzaWRlLCBcInB4XCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5ib3JkZXJTaGFkZXJzKSB7XG4gICAgICAgICAgICB0aGlzLmJvcmRlclNoYWRlcnMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJvcmRlclNoYWRlcnMucHVzaChlbGVtKTtcbiAgICAgICAgc2hhZGVyRWxlbS5hcHBlbmRDaGlsZChlbGVtKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5zaG93UGF1c2VkU3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5zY2FubmVyUGF1c2VkVWlFbGVtZW50KSB7XG4gICAgICAgICAgICB0aHJvdyBcIltpbnRlcm5hbCBlcnJvcl0gc2Nhbm5lciBwYXVzZWQgVUkgZWxlbWVudCBub3QgZm91bmRcIjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNjYW5uZXJQYXVzZWRVaUVsZW1lbnQuc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5oaWRlUGF1c2VkU3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5zY2FubmVyUGF1c2VkVWlFbGVtZW50KSB7XG4gICAgICAgICAgICB0aHJvdyBcIltpbnRlcm5hbCBlcnJvcl0gc2Nhbm5lciBwYXVzZWQgVUkgZWxlbWVudCBub3QgZm91bmRcIjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNjYW5uZXJQYXVzZWRVaUVsZW1lbnQuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFRpbWVvdXRGcHMgPSBmdW5jdGlvbiAoZnBzKSB7XG4gICAgICAgIHJldHVybiAxMDAwIC8gZnBzO1xuICAgIH07XG4gICAgcmV0dXJuIEh0bWw1UXJjb2RlO1xufSgpKTtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1odG1sNS1xcmNvZGUuanMubWFwIiwidmFyIFNWR19YTUxfUFJFRklYID0gXCJkYXRhOmltYWdlL3N2Zyt4bWw7YmFzZTY0LFwiO1xuZXhwb3J0IHZhciBBU1NFVF9DQU1FUkFfU0NBTiA9IFNWR19YTUxfUFJFRklYICsgXCJQSE4yWnlCNGJXeHVjejBpYUhSMGNEb3ZMM2QzZHk1M015NXZjbWN2TWpBd01DOXpkbWNpSUhacFpYZENiM2c5SWpBZ01DQXpOekV1TmpReklETTNNUzQyTkRNaUlITjBlV3hsUFNKbGJtRmliR1V0WW1GamEyZHliM1Z1WkRwdVpYY2dNQ0F3SURNM01TNDJORE1nTXpjeExqWTBNeUlnZUcxc09uTndZV05sUFNKd2NtVnpaWEoyWlNJK1BIQmhkR2dnWkQwaVRURXdOUzR3T0RRZ016Z3VNamN4YURFMk15NDNOamgyTWpCSU1UQTFMakE0TkhvaUx6NDhjR0YwYUNCa1BTSk5NekV4TGpVNU5pQXhPVEF1TVRnNVl5MDNMalEwTVMwNUxqTTBOeTB4T0M0ME1ETXRNVFl1TWpBMkxUTXlMamMwTXkweU1DNDFNakpXTXpCak1DMHhOaTQxTkRJdE1UTXVORFU0TFRNd0xUTXdMVE13U0RFeU5TNHdPRFJqTFRFMkxqVTBNaUF3TFRNd0lERXpMalExT0Mwek1DQXpNSFl4TWpBdU1UUXphQzA0TGpJNU5tTXRNVFl1TlRReUlEQXRNekFnTVRNdU5EVTRMVE13SURNd2RqRXVNek16WVRJNUxqZ3dOQ0F5T1M0NE1EUWdNQ0F3SURBZ05DNDJNRE1nTVRVdU9UTTVZeTAzTGpNMElEVXVORGMwTFRFeUxqRXdNeUF4TkM0eU1qRXRNVEl1TVRBeklESTBMakEyTVhZeExqTXpNMk13SURrdU9EUWdOQzQzTmpNZ01UZ3VOVGczSURFeUxqRXdNeUF5TkM0d05qSmhNamt1T0RFZ01qa3VPREVnTUNBd0lEQXROQzQyTURNZ01UVXVPVE00ZGpFdU16TXpZekFnTVRZdU5UUXlJREV6TGpRMU9DQXpNQ0F6TUNBek1HZzRMak15TkdNdU5ESTNJREV4TGpZek1TQTNMalV3TXlBeU1TNDFPRGNnTVRjdU5UTTBJREkyTGpFM055NDVNekVnTVRBdU5UQXpJRFF1TURnMElETXdMakU0TnlBeE5DNDNOamdnTkRVdU5UTTNZVGt1T1RnNElEa3VPVGc0SURBZ01DQXdJRGd1TWpFMklEUXVNamc0SURrdU9UVTRJRGt1T1RVNElEQWdNQ0F3SURVdU56QTBMVEV1Tnprell6UXVOVE16TFRNdU1UVTFJRFV1TmpVdE9TNHpPRGdnTWk0ME9UVXRNVE11T1RJeExUWXVOems0TFRrdU56WTNMVGt1TmpBeUxUSXlMall3T0MweE1DNDNOaTB6TVM0MGFEZ3lMalk0TldNdU1qY3lMalF4TkM0MU5EVXVPREU0TGpneE5TQXhMakl4SURNdU1UUXlJRFF1TlRReElEa3VNemN5SURVdU5qYzVJREV6TGpreE15QXlMalV6TkNBMExqVTBNaTB6TGpFME1pQTFMalkzTnkwNUxqTTNNU0F5TGpVek5TMHhNeTQ1TVRNdE1URXVPVEU1TFRFM0xqSXlPUzA0TGpjNE55MHpOUzQ0T0RRZ09TNDFPREV0TlRjdU1ERXlJRE11TURZM0xUSXVOalV5SURFeUxqTXdOeTB4TVM0M016SWdNVEV1TWpFM0xUSTBMakF6TXkwdU9ESTRMVGt1TXpRekxUY3VNVEE1TFRFM0xqRTVOQzB4T0M0Mk5qa3RNak11TXpNM1lUa3VPRFUzSURrdU9EVTNJREFnTUNBd0xURXVNRFl4TFM0ME9EWmpMUzQwTmpZdExqRTRNaTB4TVM0ME1ETXROQzQxTnprdE9TNDNOREV0TVRVdU56QTJJREV1TURBM0xUWXVOek0zSURFMExqYzJPQzA0TGpJM015QXlNeTQzTmpZdE55NDJOallnTWpNdU1UVTJJREV1TlRZNUlETTVMalk1T0NBM0xqZ3dNeUEwTnk0NE16WWdNVGd1TURJMklEVXVOelV5SURjdU1qSTFJRGN1TmpBM0lERTJMall5TXlBMUxqWTNNeUF5T0M0M016TXRMalF4TXlBeUxqVTROUzB1T0RJMElEVXVNalF4TFRFdU1qUTFJRGN1T1RVNUxUVXVOelUySURNM0xqRTVOQzB4TWk0NU1Ua2dPRE11TkRnekxUUTVMamczSURFeE5DNDJOakV0TkM0eU1qRWdNeTQxTmpFdE5DNDNOVFlnT1M0NE55MHhMakU1TkNBeE5DNHdPVEpoT1M0NU9DQTVMams0SURBZ01DQXdJRGN1TmpRNElETXVOVFV4SURrdU9UVTFJRGt1T1RVMUlEQWdNQ0F3SURZdU5EUTBMVEl1TXpVNFl6UXlMalkzTWkwek5pNHdNRFVnTlRBdU9EQXlMVGc0TGpVek15QTFOaTQzTXpjdE1USTJMamc0T0M0ME1UVXRNaTQyT0RRdU9ESXhMVFV1TXpBNUlERXVNakk1TFRjdU9EWXpJREl1T0RNMExURTNMamN5TVMwdU5EVTFMVE15TGpZME1TMDVMamMzTWkwME5DNHpORFY2YlMweU16SXVNekE0SURReUxqWXlZeTAxTGpVeE5DQXdMVEV3TFRRdU5EZzJMVEV3TFRFd2RpMHhMak16TTJNd0xUVXVOVEUwSURRdU5EZzJMVEV3SURFd0xURXdhREUxZGpJeExqTXpNMmd0TVRWNmJTMHlMalV0TlRJdU5qWTJZekF0TlM0MU1UUWdOQzQwT0RZdE1UQWdNVEF0TVRCb055NDFkakl4TGpNek0yZ3ROeTQxWXkwMUxqVXhOQ0F3TFRFd0xUUXVORGcyTFRFd0xURXdkaTB4TGpNek0zcHRNVGN1TlNBNU15NDVPVGxvTFRjdU5XTXROUzQxTVRRZ01DMHhNQzAwTGpRNE5pMHhNQzB4TUhZdE1TNHpNek5qTUMwMUxqVXhOQ0EwTGpRNE5pMHhNQ0F4TUMweE1HZzNMalYyTWpFdU16TXplbTB6TUM0M09UWWdNamd1T0RnM1l5MDFMalV4TkNBd0xURXdMVFF1TkRnMkxURXdMVEV3ZGkwNExqSTNNV2c1TVM0ME5UZGpMUzQ0TlRFZ05pNDJOamd0TGpRek55QXhNaTQzT0RjdU56TXhJREU0TGpJM01XZ3RPREl1TVRnNGVtMDNPUzQwT0RJdE1URXpMalk1T0dNdE15NHhNalFnTWpBdU9UQTJJREV5TGpReU55QXpNeTR4T0RRZ01qRXVOakkxSURNM0xqQTBJRFV1TkRReElESXVPVFk0SURjdU5UVXhJRFV1TmpRM0lEY3VOekF4SURjdU1UZzRMakl4SURJdU1UVXRNaTQxTlRNZ05TNDJPRFF0TkM0ME56Y2dOeTR5TlRFdExqUTRNaTR6TnpndExqa3lPUzQ0TFRFdU16TTFJREV1TWpZeExUWXVPVGczSURjdU9UTTJMVEV4TGprNE1pQXhOUzQxTWkweE5TNDBNeklnTWpJdU5qZzRhQzA1Tnk0MU5qUldNekJqTUMwMUxqVXhOQ0EwTGpRNE5pMHhNQ0F4TUMweE1HZ3hNak11TnpZNVl6VXVOVEUwSURBZ01UQWdOQzQwT0RZZ01UQWdNVEIyTVRNMUxqVTNPV010TXk0d016SXRMak00TVMwMkxqRTFMUzQyT1RRdE9TNHpPRGt0TGpreE5DMHlOUzR4TlRrdE1TNDJPVFF0TkRJdU16Y2dOeTQzTkRndE5EUXVPRGs0SURJMExqWTJObm9pTHo0OGNHRjBhQ0JrUFNKTk1UYzVMakV5T1NBNE15NHhOamRvTFRJMExqQTJZVFVnTlNBd0lEQWdNQzAxSURWMk1qUXVNRFl4WVRVZ05TQXdJREFnTUNBMUlEVm9NalF1TURaaE5TQTFJREFnTUNBd0lEVXROVlk0T0M0eE5qZGhOU0ExSURBZ01DQXdMVFV0TlhwTk1UY3lMall5T1NBeE5ESXVPRFpvTFRFeUxqVTJWakV6TUM0NFlUVWdOU0F3SURFZ01DMHhNQ0F3ZGpFM0xqQTJNV0UxSURVZ01DQXdJREFnTlNBMWFERTNMalUyWVRVZ05TQXdJREVnTUNBd0xURXdMakF3TVhwTk1qRTJMalUyT0NBNE15NHhOamRvTFRJMExqQTJZVFVnTlNBd0lEQWdNQzAxSURWMk1qUXVNRFl4WVRVZ05TQXdJREFnTUNBMUlEVm9NalF1TURaaE5TQTFJREFnTUNBd0lEVXROVlk0T0M0eE5qZGhOU0ExSURBZ01DQXdMVFV0TlhwdExUVWdNalF1TURZeGFDMHhOQzR3TmxZNU15NHhOamRvTVRRdU1EWjJNVFF1TURZeGVrMHlNVEV1TmpZNUlERXlOUzQ1TXpaSU1UazNMalF4WVRVZ05TQXdJREFnTUMwMUlEVjJNVFF1TWpVM1lUVWdOU0F3SURBZ01DQTFJRFZvTVRRdU1qVTVZVFVnTlNBd0lEQWdNQ0ExTFRWMkxURTBMakkxTjJFMUlEVWdNQ0F3SURBdE5TMDFlaUl2UGp3dmMzWm5QZz09XCI7XG5leHBvcnQgdmFyIEFTU0VUX0ZJTEVfU0NBTiA9IFNWR19YTUxfUFJFRklYICsgXCJQSE4yWnlCNGJXeHVjejBpYUhSMGNEb3ZMM2QzZHk1M015NXZjbWN2TWpBd01DOXpkbWNpSUhacFpYZENiM2c5SWpBZ01DQTFPUzR3TVRnZ05Ua3VNREU0SWlCemRIbHNaVDBpWlc1aFlteGxMV0poWTJ0bmNtOTFibVE2Ym1WM0lEQWdNQ0ExT1M0d01UZ2dOVGt1TURFNElpQjRiV3c2YzNCaFkyVTlJbkJ5WlhObGNuWmxJajQ4Y0dGMGFDQmtQU0p0TlRndU56UXhJRFUwTGpnd09TMDFMamsyT1MwMkxqSTBOR0V4TUM0M05DQXhNQzQzTkNBd0lEQWdNQ0F5TGpneUxUY3VNalZqTUMwMUxqazFNeTAwTGpnME15MHhNQzQzT1RZdE1UQXVOemsyTFRFd0xqYzVObE16TkNBek5TNHpOakVnTXpRZ05ERXVNekUwSURNNExqZzBNeUExTWk0eE1TQTBOQzQzT1RZZ05USXVNVEZqTWk0ME5ERWdNQ0EwTGpZNE9DMHVPREkwSURZdU5EazVMVEl1TVRrMmJEWXVNREF4SURZdU1qYzNZUzQ1T1RndU9UazRJREFnTUNBd0lERXVOREUwTGpBek1pQXhJREVnTUNBd0lEQWdMakF6TVMweExqUXhOSHBOTXpZZ05ERXVNekUwWXpBdE5DNDROU0F6TGprME5pMDRMamM1TmlBNExqYzVOaTA0TGpjNU5uTTRMamM1TmlBekxqazBOaUE0TGpjNU5pQTRMamM1TmkwekxqazBOaUE0TGpjNU5pMDRMamM1TmlBNExqYzVObE16TmlBME5pNHhOalFnTXpZZ05ERXVNekUwZWsweE1DNDBNekVnTVRZdU1EZzRZekFnTXk0d055QXlMalE1T0NBMUxqVTJPQ0ExTGpVMk9TQTFMalUyT0hNMUxqVTJPUzB5TGpRNU9DQTFMalUyT1MwMUxqVTJPR013TFRNdU1EY3hMVEl1TkRrNExUVXVOVFk1TFRVdU5UWTVMVFV1TlRZNWN5MDFMalUyT1NBeUxqUTVPQzAxTGpVMk9TQTFMalUyT1hwdE9TNHhNemdnTUdNd0lERXVPVFk0TFRFdU5qQXlJRE11TlRZNExUTXVOVFk1SURNdU5UWTRjeTB6TGpVMk9TMHhMall3TVMwekxqVTJPUzB6TGpVMk9DQXhMall3TWkwekxqVTJPU0F6TGpVMk9TMHpMalUyT1NBekxqVTJPU0F4TGpZd01TQXpMalUyT1NBekxqVTJPWG9pTHo0OGNHRjBhQ0JrUFNKdE16QXVPRGd5SURJNExqazROeUE1TGpFNExURXdMakExTkNBeE1TNHlOaklnTVRBdU16SXpZVEVnTVNBd0lEQWdNQ0F4TGpNMU1TMHhMalEzTld3dE1USXRNVEZoTVNBeElEQWdNQ0F3TFRFdU5ERTBMakEyTTJ3dE9TNDNPVFFnTVRBdU56STNMVFF1TnpRekxUUXVOelF6WVRFdU1EQXpJREV1TURBeklEQWdNQ0F3TFRFdU16WTRMUzR3TkRSTU5pNHpNemtnTXpjdU56WTRZVEVnTVNBd0lERWdNQ0F4TGpNeU1pQXhMalV3TVd3eE5pNHpNVE10TVRRdU16WXlJRGN1TXpFNUlEY3VNekU0WVM0NU9Ua3VPVGs1SURBZ01TQXdJREV1TkRFMExURXVOREUwYkMweExqZ3lOUzB4TGpneU5Ib2lMejQ4Y0dGMGFDQmtQU0pOTXpBZ05EWXVOVEU0U0RKMkxUUXlhRFUwZGpJNFlURWdNU0F3SURFZ01DQXlJREIyTFRJNVlURWdNU0F3SURBZ01DMHhMVEZJTVdFeElERWdNQ0F3SURBdE1TQXhkalEwWVRFZ01TQXdJREFnTUNBeElERm9NamxoTVNBeElEQWdNU0F3SURBdE1ub2lMejQ4TDNOMlp6ND1cIjtcbmV4cG9ydCB2YXIgQVNTRVRfSU5GT19JQ09OXzE2UFggPSBTVkdfWE1MX1BSRUZJWCArIFwiUEhOMlp5QjRiV3h1Y3owaWFIUjBjRG92TDNkM2R5NTNNeTV2Y21jdk1qQXdNQzl6ZG1jaUlIWnBaWGRDYjNnOUlqQWdNQ0EwTmpBZ05EWXdJaUJ6ZEhsc1pUMGlaVzVoWW14bExXSmhZMnRuY205MWJtUTZibVYzSURBZ01DQTBOakFnTkRZd0lpQjRiV3c2YzNCaFkyVTlJbkJ5WlhObGNuWmxJajQ4Y0dGMGFDQmtQU0pOTWpNd0lEQkRNVEF5TGprM05TQXdJREFnTVRBeUxqazNOU0F3SURJek1ITXhNREl1T1RjMUlESXpNQ0F5TXpBZ01qTXdJREl6TUMweE1ESXVPVGMwSURJek1DMHlNekJUTXpVM0xqQXlOU0F3SURJek1DQXdlbTB6T0M0ek16TWdNemMzTGpNMll6QWdPQzQyTnpZdE55NHdNelFnTVRVdU56RXRNVFV1TnpFZ01UVXVOekZvTFRRekxqRXdNV010T0M0Mk56WWdNQzB4TlM0M01TMDNMakF6TkMweE5TNDNNUzB4TlM0M01WWXlNREl1TkRjM1l6QXRPQzQyTnpZZ055NHdNek10TVRVdU56RWdNVFV1TnpFdE1UVXVOekZvTkRNdU1UQXhZemd1TmpjMklEQWdNVFV1TnpFZ055NHdNek1nTVRVdU56RWdNVFV1TnpGV016YzNMak0yZWsweU16QWdNVFUzWXkweU1TNDFNemtnTUMwek9TMHhOeTQwTmpFdE16a3RNemx6TVRjdU5EWXhMVE01SURNNUxUTTVJRE01SURFM0xqUTJNU0F6T1NBek9TMHhOeTQwTmpFZ016a3RNemtnTXpsNklpOCtQQzl6ZG1jK1wiO1xuZXhwb3J0IHZhciBBU1NFVF9DTE9TRV9JQ09OXzE2UFggPSBcImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQkFBQUFBUUNBWUFBQUFmOC85aEFBQUFCSE5DU1ZRSUNBZ0lmQWhraUFBQUFBbHdTRmx6QUFBQVFnQUFBRUlCYXJxUVJBQUFBQmwwUlZoMFUyOW1kSGRoY21VQWQzZDNMbWx1YTNOallYQmxMbTl5WjV2dVBCb0FBQUUxU1VSQlZEaU5mZEk3UzBOQkVBWGdMeWExb3RGZ3BiWVNiSVNBZ3BYWWk2Q21pSDlLQ0FpQ2hhVmdhNk9pV1BnZlJEUSswaXRhR1ZOb3NYdGx1V3djdU16ZVBmTTRNM3NxOGxiSEJ1YndnMWRjNG0xRS9KL040Z2hEUE9Jc2ZrLzR4aUVhbzVLWDBNY0Zsak40QzlkNFFUUFh1WTk5alAzRHNJb0RQR002Qlk1aTV5STVSN080cStJbUZrSlkyRENoM2NBSDJrbHlCKzlKMXhVTU1BRzdlQ2gxYStNcitrNDhiNWRpWHJGVnd3THVTK0JKOU1mUjcrRzBGSE9IaFRIaG5YTldTODdWREY0cGNuZlFLNEVwN1hTY05MbVBUWmdVUk5LS1lFTllXRHB6VzFCaHNjUzFXSFM4Q0RnVVJGSlFyV2NvRjNjMTNLS2JnZzFCWVFmeTh4WldFelRUdzFRWmJBb0t1OEZxSm5rdGR1NWhjVlNIbWNoaUlMenp1YURRdmpCelYybTh5b2hDRTFqSGZQeC94aFUreTRHL0Q3NUVMbFJKc1NZQUFBQUFTVVZPUks1Q1lJST1cIjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWltYWdlLWFzc2V0cy5qcy5tYXAiLCJ2YXIgUGVyc2lzdGVkRGF0YUZhY3RvcnkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFBlcnNpc3RlZERhdGFGYWN0b3J5KCkge1xuICAgIH1cbiAgICBQZXJzaXN0ZWREYXRhRmFjdG9yeS5jcmVhdGVEZWZhdWx0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaGFzUGVybWlzc2lvbjogZmFsc2UsXG4gICAgICAgICAgICBsYXN0VXNlZENhbWVyYUlkOiBudWxsXG4gICAgICAgIH07XG4gICAgfTtcbiAgICByZXR1cm4gUGVyc2lzdGVkRGF0YUZhY3Rvcnk7XG59KCkpO1xudmFyIFBlcnNpc3RlZERhdGFNYW5hZ2VyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBQZXJzaXN0ZWREYXRhTWFuYWdlcigpIHtcbiAgICAgICAgdGhpcy5kYXRhID0gUGVyc2lzdGVkRGF0YUZhY3RvcnkuY3JlYXRlRGVmYXVsdCgpO1xuICAgICAgICB2YXIgZGF0YSA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKFBlcnNpc3RlZERhdGFNYW5hZ2VyLkxPQ0FMX1NUT1JBR0VfS0VZKTtcbiAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmRhdGEgPSBKU09OLnBhcnNlKGRhdGEpO1xuICAgICAgICB9XG4gICAgfVxuICAgIFBlcnNpc3RlZERhdGFNYW5hZ2VyLnByb3RvdHlwZS5oYXNDYW1lcmFQZXJtaXNzaW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF0YS5oYXNQZXJtaXNzaW9uO1xuICAgIH07XG4gICAgUGVyc2lzdGVkRGF0YU1hbmFnZXIucHJvdG90eXBlLmdldExhc3RVc2VkQ2FtZXJhSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRhdGEubGFzdFVzZWRDYW1lcmFJZDtcbiAgICB9O1xuICAgIFBlcnNpc3RlZERhdGFNYW5hZ2VyLnByb3RvdHlwZS5zZXRIYXNQZXJtaXNzaW9uID0gZnVuY3Rpb24gKGhhc1Blcm1pc3Npb24pIHtcbiAgICAgICAgdGhpcy5kYXRhLmhhc1Blcm1pc3Npb24gPSBoYXNQZXJtaXNzaW9uO1xuICAgICAgICB0aGlzLmZsdXNoKCk7XG4gICAgfTtcbiAgICBQZXJzaXN0ZWREYXRhTWFuYWdlci5wcm90b3R5cGUuc2V0TGFzdFVzZWRDYW1lcmFJZCA9IGZ1bmN0aW9uIChsYXN0VXNlZENhbWVyYUlkKSB7XG4gICAgICAgIHRoaXMuZGF0YS5sYXN0VXNlZENhbWVyYUlkID0gbGFzdFVzZWRDYW1lcmFJZDtcbiAgICAgICAgdGhpcy5mbHVzaCgpO1xuICAgIH07XG4gICAgUGVyc2lzdGVkRGF0YU1hbmFnZXIucHJvdG90eXBlLnJlc2V0TGFzdFVzZWRDYW1lcmFJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kYXRhLmxhc3RVc2VkQ2FtZXJhSWQgPSBudWxsO1xuICAgICAgICB0aGlzLmZsdXNoKCk7XG4gICAgfTtcbiAgICBQZXJzaXN0ZWREYXRhTWFuYWdlci5wcm90b3R5cGUucmVzZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZGF0YSA9IFBlcnNpc3RlZERhdGFGYWN0b3J5LmNyZWF0ZURlZmF1bHQoKTtcbiAgICAgICAgdGhpcy5mbHVzaCgpO1xuICAgIH07XG4gICAgUGVyc2lzdGVkRGF0YU1hbmFnZXIucHJvdG90eXBlLmZsdXNoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShQZXJzaXN0ZWREYXRhTWFuYWdlci5MT0NBTF9TVE9SQUdFX0tFWSwgSlNPTi5zdHJpbmdpZnkodGhpcy5kYXRhKSk7XG4gICAgfTtcbiAgICBQZXJzaXN0ZWREYXRhTWFuYWdlci5MT0NBTF9TVE9SQUdFX0tFWSA9IFwiSFRNTDVfUVJDT0RFX0RBVEFcIjtcbiAgICByZXR1cm4gUGVyc2lzdGVkRGF0YU1hbmFnZXI7XG59KCkpO1xuZXhwb3J0IHsgUGVyc2lzdGVkRGF0YU1hbmFnZXIgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXN0b3JhZ2UuanMubWFwIiwiaW1wb3J0IHsgQVNTRVRfQ0xPU0VfSUNPTl8xNlBYLCBBU1NFVF9JTkZPX0lDT05fMTZQWCB9IGZyb20gXCIuL2ltYWdlLWFzc2V0c1wiO1xuaW1wb3J0IHsgTGlicmFyeUluZm9TdHJpbmdzIH0gZnJvbSBcIi4vc3RyaW5nc1wiO1xudmFyIExpYnJhcnlJbmZvRGl2ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBMaWJyYXJ5SW5mb0RpdigpIHtcbiAgICAgICAgdGhpcy5pbmZvRGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICB9XG4gICAgTGlicmFyeUluZm9EaXYucHJvdG90eXBlLnJlbmRlckludG8gPSBmdW5jdGlvbiAocGFyZW50KSB7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5wb3NpdGlvbiA9IFwiYWJzb2x1dGVcIjtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLnRvcCA9IFwiMTBweFwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUucmlnaHQgPSBcIjEwcHhcIjtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLnpJbmRleCA9IFwiMlwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUucGFkZGluZyA9IFwiNXB0XCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5ib3JkZXIgPSBcIjFweCBzb2xpZCAjMTcxNzE3XCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5mb250U2l6ZSA9IFwiMTBwdFwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUuYmFja2dyb3VuZCA9IFwicmdiKDAgMCAwIC8gNjklKVwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUuYm9yZGVyUmFkaXVzID0gXCI1cHhcIjtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLnRleHRBbGlnbiA9IFwiY2VudGVyXCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5mb250V2VpZ2h0ID0gXCI0MDBcIjtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLmNvbG9yID0gXCJ3aGl0ZVwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuaW5uZXJUZXh0ID0gTGlicmFyeUluZm9TdHJpbmdzLnBvd2VyZWRCeSgpO1xuICAgICAgICB2YXIgcHJvamVjdExpbmsgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiYVwiKTtcbiAgICAgICAgcHJvamVjdExpbmsuaW5uZXJUZXh0ID0gXCJTY2FuQXBwXCI7XG4gICAgICAgIHByb2plY3RMaW5rLmhyZWYgPSBcImh0dHBzOi8vc2NhbmFwcC5vcmdcIjtcbiAgICAgICAgcHJvamVjdExpbmsudGFyZ2V0ID0gXCJuZXdcIjtcbiAgICAgICAgcHJvamVjdExpbmsuc3R5bGUuY29sb3IgPSBcIndoaXRlXCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5hcHBlbmRDaGlsZChwcm9qZWN0TGluayk7XG4gICAgICAgIHZhciBicmVha0VsZW1GaXJzdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJiclwiKTtcbiAgICAgICAgdmFyIGJyZWFrRWxlbVNlY29uZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJiclwiKTtcbiAgICAgICAgdGhpcy5pbmZvRGl2LmFwcGVuZENoaWxkKGJyZWFrRWxlbUZpcnN0KTtcbiAgICAgICAgdGhpcy5pbmZvRGl2LmFwcGVuZENoaWxkKGJyZWFrRWxlbVNlY29uZCk7XG4gICAgICAgIHZhciByZXBvcnRJc3N1ZUxpbmsgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiYVwiKTtcbiAgICAgICAgcmVwb3J0SXNzdWVMaW5rLmlubmVyVGV4dCA9IExpYnJhcnlJbmZvU3RyaW5ncy5yZXBvcnRJc3N1ZXMoKTtcbiAgICAgICAgcmVwb3J0SXNzdWVMaW5rLmhyZWYgPSBcImh0dHBzOi8vZ2l0aHViLmNvbS9tZWJqYXMvaHRtbDUtcXJjb2RlL2lzc3Vlc1wiO1xuICAgICAgICByZXBvcnRJc3N1ZUxpbmsudGFyZ2V0ID0gXCJuZXdcIjtcbiAgICAgICAgcmVwb3J0SXNzdWVMaW5rLnN0eWxlLmNvbG9yID0gXCJ3aGl0ZVwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuYXBwZW5kQ2hpbGQocmVwb3J0SXNzdWVMaW5rKTtcbiAgICAgICAgcGFyZW50LmFwcGVuZENoaWxkKHRoaXMuaW5mb0Rpdik7XG4gICAgfTtcbiAgICBMaWJyYXJ5SW5mb0Rpdi5wcm90b3R5cGUuc2hvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLmRpc3BsYXkgPSBcImJsb2NrXCI7XG4gICAgfTtcbiAgICBMaWJyYXJ5SW5mb0Rpdi5wcm90b3R5cGUuaGlkZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICB9O1xuICAgIHJldHVybiBMaWJyYXJ5SW5mb0Rpdjtcbn0oKSk7XG52YXIgTGlicmFyeUluZm9JY29uID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBMaWJyYXJ5SW5mb0ljb24ob25UYXBJbiwgb25UYXBPdXQpIHtcbiAgICAgICAgdGhpcy5pc1Nob3dpbmdJbmZvSWNvbiA9IHRydWU7XG4gICAgICAgIHRoaXMub25UYXBJbiA9IG9uVGFwSW47XG4gICAgICAgIHRoaXMub25UYXBPdXQgPSBvblRhcE91dDtcbiAgICAgICAgdGhpcy5pbmZvSWNvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJpbWdcIik7XG4gICAgfVxuICAgIExpYnJhcnlJbmZvSWNvbi5wcm90b3R5cGUucmVuZGVySW50byA9IGZ1bmN0aW9uIChwYXJlbnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5pbmZvSWNvbi5hbHQgPSBcIkluZm8gaWNvblwiO1xuICAgICAgICB0aGlzLmluZm9JY29uLnNyYyA9IEFTU0VUX0lORk9fSUNPTl8xNlBYO1xuICAgICAgICB0aGlzLmluZm9JY29uLnN0eWxlLnBvc2l0aW9uID0gXCJhYnNvbHV0ZVwiO1xuICAgICAgICB0aGlzLmluZm9JY29uLnN0eWxlLnRvcCA9IFwiNHB4XCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUucmlnaHQgPSBcIjRweFwiO1xuICAgICAgICB0aGlzLmluZm9JY29uLnN0eWxlLm9wYWNpdHkgPSBcIjAuNlwiO1xuICAgICAgICB0aGlzLmluZm9JY29uLnN0eWxlLmN1cnNvciA9IFwicG9pbnRlclwiO1xuICAgICAgICB0aGlzLmluZm9JY29uLnN0eWxlLnpJbmRleCA9IFwiMlwiO1xuICAgICAgICB0aGlzLmluZm9JY29uLnN0eWxlLndpZHRoID0gXCIxNnB4XCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUuaGVpZ2h0ID0gXCIxNnB4XCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24ub25tb3VzZW92ZXIgPSBmdW5jdGlvbiAoXykgeyByZXR1cm4gX3RoaXMub25Ib3ZlckluKCk7IH07XG4gICAgICAgIHRoaXMuaW5mb0ljb24ub25tb3VzZW91dCA9IGZ1bmN0aW9uIChfKSB7IHJldHVybiBfdGhpcy5vbkhvdmVyT3V0KCk7IH07XG4gICAgICAgIHRoaXMuaW5mb0ljb24ub25jbGljayA9IGZ1bmN0aW9uIChfKSB7IHJldHVybiBfdGhpcy5vbkNsaWNrKCk7IH07XG4gICAgICAgIHBhcmVudC5hcHBlbmRDaGlsZCh0aGlzLmluZm9JY29uKTtcbiAgICB9O1xuICAgIExpYnJhcnlJbmZvSWNvbi5wcm90b3R5cGUub25Ib3ZlckluID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pc1Nob3dpbmdJbmZvSWNvbikge1xuICAgICAgICAgICAgdGhpcy5pbmZvSWNvbi5zdHlsZS5vcGFjaXR5ID0gXCIxXCI7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIExpYnJhcnlJbmZvSWNvbi5wcm90b3R5cGUub25Ib3Zlck91dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNTaG93aW5nSW5mb0ljb24pIHtcbiAgICAgICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUub3BhY2l0eSA9IFwiMC42XCI7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIExpYnJhcnlJbmZvSWNvbi5wcm90b3R5cGUub25DbGljayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNTaG93aW5nSW5mb0ljb24pIHtcbiAgICAgICAgICAgIHRoaXMuaXNTaG93aW5nSW5mb0ljb24gPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMub25UYXBJbigpO1xuICAgICAgICAgICAgdGhpcy5pbmZvSWNvbi5zcmMgPSBBU1NFVF9DTE9TRV9JQ09OXzE2UFg7XG4gICAgICAgICAgICB0aGlzLmluZm9JY29uLnN0eWxlLm9wYWNpdHkgPSBcIjFcIjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuaXNTaG93aW5nSW5mb0ljb24gPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5vblRhcE91dCgpO1xuICAgICAgICAgICAgdGhpcy5pbmZvSWNvbi5zcmMgPSBBU1NFVF9JTkZPX0lDT05fMTZQWDtcbiAgICAgICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUub3BhY2l0eSA9IFwiMC42XCI7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBMaWJyYXJ5SW5mb0ljb247XG59KCkpO1xudmFyIExpYnJhcnlJbmZvQ29udGFpbmVyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBMaWJyYXJ5SW5mb0NvbnRhaW5lcigpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5pbmZvRGl2ID0gbmV3IExpYnJhcnlJbmZvRGl2KCk7XG4gICAgICAgIHRoaXMuaW5mb0ljb24gPSBuZXcgTGlicmFyeUluZm9JY29uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLmluZm9EaXYuc2hvdygpO1xuICAgICAgICB9LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5pbmZvRGl2LmhpZGUoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIExpYnJhcnlJbmZvQ29udGFpbmVyLnByb3RvdHlwZS5yZW5kZXJJbnRvID0gZnVuY3Rpb24gKHBhcmVudCkge1xuICAgICAgICB0aGlzLmluZm9EaXYucmVuZGVySW50byhwYXJlbnQpO1xuICAgICAgICB0aGlzLmluZm9JY29uLnJlbmRlckludG8ocGFyZW50KTtcbiAgICB9O1xuICAgIHJldHVybiBMaWJyYXJ5SW5mb0NvbnRhaW5lcjtcbn0oKSk7XG5leHBvcnQgeyBMaWJyYXJ5SW5mb0NvbnRhaW5lciB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dWkuanMubWFwIiwidmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcbiAgICB9KTtcbn07XG52YXIgX19nZW5lcmF0b3IgPSAodGhpcyAmJiB0aGlzLl9fZ2VuZXJhdG9yKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgYm9keSkge1xuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XG4gICAgICAgIHdoaWxlIChnICYmIChnID0gMCwgb3BbMF0gJiYgKF8gPSAwKSksIF8pIHRyeSB7XG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcbiAgICB9XG59O1xudmFyIENhbWVyYVBlcm1pc3Npb25zID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDYW1lcmFQZXJtaXNzaW9ucygpIHtcbiAgICB9XG4gICAgQ2FtZXJhUGVybWlzc2lvbnMuaGFzUGVybWlzc2lvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBkZXZpY2VzLCBfaSwgZGV2aWNlc18xLCBkZXZpY2U7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChfYS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6IHJldHVybiBbNCwgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXZpY2VzID0gX2Euc2VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChfaSA9IDAsIGRldmljZXNfMSA9IGRldmljZXM7IF9pIDwgZGV2aWNlc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldmljZSA9IGRldmljZXNfMVtfaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRldmljZS5raW5kID09PSBcInZpZGVvaW5wdXRcIiAmJiBkZXZpY2UubGFiZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyLCB0cnVlXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIsIGZhbHNlXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gQ2FtZXJhUGVybWlzc2lvbnM7XG59KCkpO1xuZXhwb3J0IHsgQ2FtZXJhUGVybWlzc2lvbnMgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXBlcm1pc3Npb25zLmpzLm1hcCIsImltcG9ydCB7IEh0bWw1UXJjb2RlU2NhblR5cGUsIEh0bWw1UXJjb2RlQ29uc3RhbnRzIH0gZnJvbSBcIi4uLy4uL2NvcmVcIjtcbnZhciBTY2FuVHlwZVNlbGVjdG9yID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBTY2FuVHlwZVNlbGVjdG9yKHN1cHBvcnRlZFNjYW5UeXBlcykge1xuICAgICAgICB0aGlzLnN1cHBvcnRlZFNjYW5UeXBlcyA9IHRoaXMudmFsaWRhdGVBbmRSZXR1cm5TY2FuVHlwZXMoc3VwcG9ydGVkU2NhblR5cGVzKTtcbiAgICB9XG4gICAgU2NhblR5cGVTZWxlY3Rvci5wcm90b3R5cGUuZ2V0RGVmYXVsdFNjYW5UeXBlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdXBwb3J0ZWRTY2FuVHlwZXNbMF07XG4gICAgfTtcbiAgICBTY2FuVHlwZVNlbGVjdG9yLnByb3RvdHlwZS5oYXNNb3JlVGhhbk9uZVNjYW5UeXBlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdXBwb3J0ZWRTY2FuVHlwZXMubGVuZ3RoID4gMTtcbiAgICB9O1xuICAgIFNjYW5UeXBlU2VsZWN0b3IucHJvdG90eXBlLmlzQ2FtZXJhU2NhblJlcXVpcmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5zdXBwb3J0ZWRTY2FuVHlwZXM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2NhblR5cGUgPSBfYVtfaV07XG4gICAgICAgICAgICBpZiAoU2NhblR5cGVTZWxlY3Rvci5pc0NhbWVyYVNjYW5UeXBlKHNjYW5UeXBlKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIFNjYW5UeXBlU2VsZWN0b3IuaXNDYW1lcmFTY2FuVHlwZSA9IGZ1bmN0aW9uIChzY2FuVHlwZSkge1xuICAgICAgICByZXR1cm4gc2NhblR5cGUgPT09IEh0bWw1UXJjb2RlU2NhblR5cGUuU0NBTl9UWVBFX0NBTUVSQTtcbiAgICB9O1xuICAgIFNjYW5UeXBlU2VsZWN0b3IuaXNGaWxlU2NhblR5cGUgPSBmdW5jdGlvbiAoc2NhblR5cGUpIHtcbiAgICAgICAgcmV0dXJuIHNjYW5UeXBlID09PSBIdG1sNVFyY29kZVNjYW5UeXBlLlNDQU5fVFlQRV9GSUxFO1xuICAgIH07XG4gICAgU2NhblR5cGVTZWxlY3Rvci5wcm90b3R5cGUudmFsaWRhdGVBbmRSZXR1cm5TY2FuVHlwZXMgPSBmdW5jdGlvbiAoc3VwcG9ydGVkU2NhblR5cGVzKSB7XG4gICAgICAgIGlmICghc3VwcG9ydGVkU2NhblR5cGVzIHx8IHN1cHBvcnRlZFNjYW5UeXBlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1NVUFBPUlRFRF9TQ0FOX1RZUEU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1heEV4cGVjdGVkVmFsdWVzID0gSHRtbDVRcmNvZGVDb25zdGFudHMuREVGQVVMVF9TVVBQT1JURURfU0NBTl9UWVBFLmxlbmd0aDtcbiAgICAgICAgaWYgKHN1cHBvcnRlZFNjYW5UeXBlcy5sZW5ndGggPiBtYXhFeHBlY3RlZFZhbHVlcykge1xuICAgICAgICAgICAgdGhyb3cgXCJNYXggXCIuY29uY2F0KG1heEV4cGVjdGVkVmFsdWVzLCBcIiB2YWx1ZXMgZXhwZWN0ZWQgZm9yIFwiKVxuICAgICAgICAgICAgICAgICsgXCJzdXBwb3J0ZWRTY2FuVHlwZXNcIjtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIHN1cHBvcnRlZFNjYW5UeXBlc18xID0gc3VwcG9ydGVkU2NhblR5cGVzOyBfaSA8IHN1cHBvcnRlZFNjYW5UeXBlc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHNjYW5UeXBlID0gc3VwcG9ydGVkU2NhblR5cGVzXzFbX2ldO1xuICAgICAgICAgICAgaWYgKCFIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1NVUFBPUlRFRF9TQ0FOX1RZUEVcbiAgICAgICAgICAgICAgICAuaW5jbHVkZXMoc2NhblR5cGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgXCJVbnN1cHBvcnRlZCBzY2FuIHR5cGUgXCIuY29uY2F0KHNjYW5UeXBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3VwcG9ydGVkU2NhblR5cGVzO1xuICAgIH07XG4gICAgcmV0dXJuIFNjYW5UeXBlU2VsZWN0b3I7XG59KCkpO1xuZXhwb3J0IHsgU2NhblR5cGVTZWxlY3RvciB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c2Nhbi10eXBlLXNlbGVjdG9yLmpzLm1hcCIsInZhciBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3NlcygpIHtcbiAgICB9XG4gICAgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkFMTF9FTEVNRU5UX0NMQVNTID0gXCJodG1sNS1xcmNvZGUtZWxlbWVudFwiO1xuICAgIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5DQU1FUkFfUEVSTUlTU0lPTl9CVVRUT05fSUQgPSBcImh0bWw1LXFyY29kZS1idXR0b24tY2FtZXJhLXBlcm1pc3Npb25cIjtcbiAgICBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuQ0FNRVJBX1NUQVJUX0JVVFRPTl9JRCA9IFwiaHRtbDUtcXJjb2RlLWJ1dHRvbi1jYW1lcmEtc3RhcnRcIjtcbiAgICBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuQ0FNRVJBX1NUT1BfQlVUVE9OX0lEID0gXCJodG1sNS1xcmNvZGUtYnV0dG9uLWNhbWVyYS1zdG9wXCI7XG4gICAgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlRPUkNIX0JVVFRPTl9JRCA9IFwiaHRtbDUtcXJjb2RlLWJ1dHRvbi10b3JjaFwiO1xuICAgIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5DQU1FUkFfU0VMRUNUSU9OX1NFTEVDVF9JRCA9IFwiaHRtbDUtcXJjb2RlLXNlbGVjdC1jYW1lcmFcIjtcbiAgICBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuRklMRV9TRUxFQ1RJT05fQlVUVE9OX0lEID0gXCJodG1sNS1xcmNvZGUtYnV0dG9uLWZpbGUtc2VsZWN0aW9uXCI7XG4gICAgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlpPT01fU0xJREVSX0lEID0gXCJodG1sNS1xcmNvZGUtaW5wdXQtcmFuZ2Utem9vbVwiO1xuICAgIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5TQ0FOX1RZUEVfQ0hBTkdFX0FOQ0hPUl9JRCA9IFwiaHRtbDUtcXJjb2RlLWFuY2hvci1zY2FuLXR5cGUtY2hhbmdlXCI7XG4gICAgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlRPUkNIX0JVVFRPTl9DTEFTU19UT1JDSF9PTiA9IFwiaHRtbDUtcXJjb2RlLWJ1dHRvbi10b3JjaC1vblwiO1xuICAgIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5UT1JDSF9CVVRUT05fQ0xBU1NfVE9SQ0hfT0ZGID0gXCJodG1sNS1xcmNvZGUtYnV0dG9uLXRvcmNoLW9mZlwiO1xuICAgIHJldHVybiBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXM7XG59KCkpO1xuZXhwb3J0IHsgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzIH07XG52YXIgQmFzZVVpRWxlbWVudEZhY3RvcnkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEJhc2VVaUVsZW1lbnRGYWN0b3J5KCkge1xuICAgIH1cbiAgICBCYXNlVWlFbGVtZW50RmFjdG9yeS5jcmVhdGVFbGVtZW50ID0gZnVuY3Rpb24gKGVsZW1lbnRUeXBlLCBlbGVtZW50SWQpIHtcbiAgICAgICAgdmFyIGVsZW1lbnQgPSAoZG9jdW1lbnQuY3JlYXRlRWxlbWVudChlbGVtZW50VHlwZSkpO1xuICAgICAgICBlbGVtZW50LmlkID0gZWxlbWVudElkO1xuICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5hZGQoUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkFMTF9FTEVNRU5UX0NMQVNTKTtcbiAgICAgICAgaWYgKGVsZW1lbnRUeXBlID09PSBcImJ1dHRvblwiKSB7XG4gICAgICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZShcInR5cGVcIiwgXCJidXR0b25cIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVsZW1lbnQ7XG4gICAgfTtcbiAgICByZXR1cm4gQmFzZVVpRWxlbWVudEZhY3Rvcnk7XG59KCkpO1xuZXhwb3J0IHsgQmFzZVVpRWxlbWVudEZhY3RvcnkgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWJhc2UuanMubWFwIiwidmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcbiAgICB9KTtcbn07XG52YXIgX19nZW5lcmF0b3IgPSAodGhpcyAmJiB0aGlzLl9fZ2VuZXJhdG9yKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgYm9keSkge1xuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XG4gICAgICAgIHdoaWxlIChnICYmIChnID0gMCwgb3BbMF0gJiYgKF8gPSAwKSksIF8pIHRyeSB7XG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcbiAgICB9XG59O1xuaW1wb3J0IHsgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncyB9IGZyb20gXCIuLi8uLi9zdHJpbmdzXCI7XG5pbXBvcnQgeyBCYXNlVWlFbGVtZW50RmFjdG9yeSwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzIH0gZnJvbSBcIi4vYmFzZVwiO1xudmFyIFRvcmNoQ29udHJvbGxlciA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gVG9yY2hDb250cm9sbGVyKHRvcmNoQ2FwYWJpbGl0eSwgYnV0dG9uQ29udHJvbGxlciwgb25Ub3JjaEFjdGlvbkZhaWx1cmVDYWxsYmFjaykge1xuICAgICAgICB0aGlzLmlzVG9yY2hPbiA9IGZhbHNlO1xuICAgICAgICB0aGlzLnRvcmNoQ2FwYWJpbGl0eSA9IHRvcmNoQ2FwYWJpbGl0eTtcbiAgICAgICAgdGhpcy5idXR0b25Db250cm9sbGVyID0gYnV0dG9uQ29udHJvbGxlcjtcbiAgICAgICAgdGhpcy5vblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrID0gb25Ub3JjaEFjdGlvbkZhaWx1cmVDYWxsYmFjaztcbiAgICB9XG4gICAgVG9yY2hDb250cm9sbGVyLnByb3RvdHlwZS5pc1RvcmNoRW5hYmxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNUb3JjaE9uO1xuICAgIH07XG4gICAgVG9yY2hDb250cm9sbGVyLnByb3RvdHlwZS5mbGlwU3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBpc1RvcmNoT25FeHBlY3RlZCwgZXJyb3JfMTtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnV0dG9uQ29udHJvbGxlci5kaXNhYmxlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc1RvcmNoT25FeHBlY3RlZCA9ICF0aGlzLmlzVG9yY2hPbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLmxhYmVsID0gMTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgX2EudHJ5cy5wdXNoKFsxLCAzLCAsIDRdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbNCwgdGhpcy50b3JjaENhcGFiaWxpdHkuYXBwbHkoaXNUb3JjaE9uRXhwZWN0ZWQpXTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgX2Euc2VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy51cGRhdGVVaUJhc2VkT25MYXRlc3RTZXR0aW5ncyh0aGlzLnRvcmNoQ2FwYWJpbGl0eS52YWx1ZSgpLCBpc1RvcmNoT25FeHBlY3RlZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzMsIDRdO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl8xID0gX2Euc2VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9wYWdhdGVGYWlsdXJlKGlzVG9yY2hPbkV4cGVjdGVkLCBlcnJvcl8xKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnV0dG9uQ29udHJvbGxlci5lbmFibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMywgNF07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDogcmV0dXJuIFsyXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBUb3JjaENvbnRyb2xsZXIucHJvdG90eXBlLnVwZGF0ZVVpQmFzZWRPbkxhdGVzdFNldHRpbmdzID0gZnVuY3Rpb24gKGlzVG9yY2hPbiwgaXNUb3JjaE9uRXhwZWN0ZWQpIHtcbiAgICAgICAgaWYgKGlzVG9yY2hPbiA9PT0gaXNUb3JjaE9uRXhwZWN0ZWQpIHtcbiAgICAgICAgICAgIHRoaXMuYnV0dG9uQ29udHJvbGxlci5zZXRUZXh0KGlzVG9yY2hPbkV4cGVjdGVkXG4gICAgICAgICAgICAgICAgPyBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRvcmNoT2ZmQnV0dG9uKClcbiAgICAgICAgICAgICAgICA6IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudG9yY2hPbkJ1dHRvbigpKTtcbiAgICAgICAgICAgIHRoaXMuaXNUb3JjaE9uID0gaXNUb3JjaE9uRXhwZWN0ZWQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnByb3BhZ2F0ZUZhaWx1cmUoaXNUb3JjaE9uRXhwZWN0ZWQpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYnV0dG9uQ29udHJvbGxlci5lbmFibGUoKTtcbiAgICB9O1xuICAgIFRvcmNoQ29udHJvbGxlci5wcm90b3R5cGUucHJvcGFnYXRlRmFpbHVyZSA9IGZ1bmN0aW9uIChpc1RvcmNoT25FeHBlY3RlZCwgZXJyb3IpIHtcbiAgICAgICAgdmFyIGVycm9yTWVzc2FnZSA9IGlzVG9yY2hPbkV4cGVjdGVkXG4gICAgICAgICAgICA/IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudG9yY2hPbkZhaWxlZE1lc3NhZ2UoKVxuICAgICAgICAgICAgOiBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRvcmNoT2ZmRmFpbGVkTWVzc2FnZSgpO1xuICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgIGVycm9yTWVzc2FnZSArPSBcIjsgRXJyb3IgPSBcIiArIGVycm9yO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub25Ub3JjaEFjdGlvbkZhaWx1cmVDYWxsYmFjayhlcnJvck1lc3NhZ2UpO1xuICAgIH07XG4gICAgVG9yY2hDb250cm9sbGVyLnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5pc1RvcmNoT24gPSBmYWxzZTtcbiAgICB9O1xuICAgIHJldHVybiBUb3JjaENvbnRyb2xsZXI7XG59KCkpO1xudmFyIFRvcmNoQnV0dG9uID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBUb3JjaEJ1dHRvbih0b3JjaENhcGFiaWxpdHksIG9uVG9yY2hBY3Rpb25GYWlsdXJlQ2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5vblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrID0gb25Ub3JjaEFjdGlvbkZhaWx1cmVDYWxsYmFjaztcbiAgICAgICAgdGhpcy50b3JjaEJ1dHRvblxuICAgICAgICAgICAgPSBCYXNlVWlFbGVtZW50RmFjdG9yeS5jcmVhdGVFbGVtZW50KFwiYnV0dG9uXCIsIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5UT1JDSF9CVVRUT05fSUQpO1xuICAgICAgICB0aGlzLnRvcmNoQ29udHJvbGxlciA9IG5ldyBUb3JjaENvbnRyb2xsZXIodG9yY2hDYXBhYmlsaXR5LCB0aGlzLCBvblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrKTtcbiAgICB9XG4gICAgVG9yY2hCdXR0b24ucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uIChwYXJlbnRFbGVtZW50LCB0b3JjaEJ1dHRvbk9wdGlvbnMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy50b3JjaEJ1dHRvbi5pbm5lclRleHRcbiAgICAgICAgICAgID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50b3JjaE9uQnV0dG9uKCk7XG4gICAgICAgIHRoaXMudG9yY2hCdXR0b24uc3R5bGUuZGlzcGxheSA9IHRvcmNoQnV0dG9uT3B0aW9ucy5kaXNwbGF5O1xuICAgICAgICB0aGlzLnRvcmNoQnV0dG9uLnN0eWxlLm1hcmdpbkxlZnQgPSB0b3JjaEJ1dHRvbk9wdGlvbnMubWFyZ2luTGVmdDtcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy50b3JjaEJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgZnVuY3Rpb24gKF8pIHsgcmV0dXJuIF9fYXdhaXRlcihfdGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDogcmV0dXJuIFs0LCAkdGhpcy50b3JjaENvbnRyb2xsZXIuZmxpcFN0YXRlKCldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBfYS5zZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJHRoaXMudG9yY2hDb250cm9sbGVyLmlzVG9yY2hFbmFibGVkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGhpcy50b3JjaEJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5UT1JDSF9CVVRUT05fQ0xBU1NfVE9SQ0hfT0ZGKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGhpcy50b3JjaEJ1dHRvbi5jbGFzc0xpc3QuYWRkKFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5UT1JDSF9CVVRUT05fQ0xBU1NfVE9SQ0hfT04pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMudG9yY2hCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuVE9SQ0hfQlVUVE9OX0NMQVNTX1RPUkNIX09OKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGhpcy50b3JjaEJ1dHRvbi5jbGFzc0xpc3QuYWRkKFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5UT1JDSF9CVVRUT05fQ0xBU1NfVE9SQ0hfT0ZGKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMl07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pOyB9KTtcbiAgICAgICAgcGFyZW50RWxlbWVudC5hcHBlbmRDaGlsZCh0aGlzLnRvcmNoQnV0dG9uKTtcbiAgICB9O1xuICAgIFRvcmNoQnV0dG9uLnByb3RvdHlwZS51cGRhdGVUb3JjaENhcGFiaWxpdHkgPSBmdW5jdGlvbiAodG9yY2hDYXBhYmlsaXR5KSB7XG4gICAgICAgIHRoaXMudG9yY2hDb250cm9sbGVyID0gbmV3IFRvcmNoQ29udHJvbGxlcih0b3JjaENhcGFiaWxpdHksIHRoaXMsIHRoaXMub25Ub3JjaEFjdGlvbkZhaWx1cmVDYWxsYmFjayk7XG4gICAgfTtcbiAgICBUb3JjaEJ1dHRvbi5wcm90b3R5cGUuZ2V0VG9yY2hCdXR0b24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRvcmNoQnV0dG9uO1xuICAgIH07XG4gICAgVG9yY2hCdXR0b24ucHJvdG90eXBlLmhpZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudG9yY2hCdXR0b24uc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgIH07XG4gICAgVG9yY2hCdXR0b24ucHJvdG90eXBlLnNob3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudG9yY2hCdXR0b24uc3R5bGUuZGlzcGxheSA9IFwiaW5saW5lLWJsb2NrXCI7XG4gICAgfTtcbiAgICBUb3JjaEJ1dHRvbi5wcm90b3R5cGUuZGlzYWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy50b3JjaEJ1dHRvbi5kaXNhYmxlZCA9IHRydWU7XG4gICAgfTtcbiAgICBUb3JjaEJ1dHRvbi5wcm90b3R5cGUuZW5hYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnRvcmNoQnV0dG9uLmRpc2FibGVkID0gZmFsc2U7XG4gICAgfTtcbiAgICBUb3JjaEJ1dHRvbi5wcm90b3R5cGUuc2V0VGV4dCA9IGZ1bmN0aW9uICh0ZXh0KSB7XG4gICAgICAgIHRoaXMudG9yY2hCdXR0b24uaW5uZXJUZXh0ID0gdGV4dDtcbiAgICB9O1xuICAgIFRvcmNoQnV0dG9uLnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy50b3JjaEJ1dHRvbi5pbm5lclRleHQgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRvcmNoT25CdXR0b24oKTtcbiAgICAgICAgdGhpcy50b3JjaENvbnRyb2xsZXIucmVzZXQoKTtcbiAgICB9O1xuICAgIFRvcmNoQnV0dG9uLmNyZWF0ZSA9IGZ1bmN0aW9uIChwYXJlbnRFbGVtZW50LCB0b3JjaENhcGFiaWxpdHksIHRvcmNoQnV0dG9uT3B0aW9ucywgb25Ub3JjaEFjdGlvbkZhaWx1cmVDYWxsYmFjaykge1xuICAgICAgICB2YXIgYnV0dG9uID0gbmV3IFRvcmNoQnV0dG9uKHRvcmNoQ2FwYWJpbGl0eSwgb25Ub3JjaEFjdGlvbkZhaWx1cmVDYWxsYmFjayk7XG4gICAgICAgIGJ1dHRvbi5yZW5kZXIocGFyZW50RWxlbWVudCwgdG9yY2hCdXR0b25PcHRpb25zKTtcbiAgICAgICAgcmV0dXJuIGJ1dHRvbjtcbiAgICB9O1xuICAgIHJldHVybiBUb3JjaEJ1dHRvbjtcbn0oKSk7XG5leHBvcnQgeyBUb3JjaEJ1dHRvbiB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dG9yY2gtYnV0dG9uLmpzLm1hcCIsImltcG9ydCB7IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MgfSBmcm9tIFwiLi4vLi4vc3RyaW5nc1wiO1xuaW1wb3J0IHsgQmFzZVVpRWxlbWVudEZhY3RvcnksIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3NlcyB9IGZyb20gXCIuL2Jhc2VcIjtcbnZhciBGaWxlU2VsZWN0aW9uVWkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEZpbGVTZWxlY3Rpb25VaShwYXJlbnRFbGVtZW50LCBzaG93T25SZW5kZXIsIG9uRmlsZVNlbGVjdGVkKSB7XG4gICAgICAgIHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbiA9IHRoaXMuY3JlYXRlRmlsZUJhc2VkU2NhblJlZ2lvbigpO1xuICAgICAgICB0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb24uc3R5bGUuZGlzcGxheVxuICAgICAgICAgICAgPSBzaG93T25SZW5kZXIgPyBcImJsb2NrXCIgOiBcIm5vbmVcIjtcbiAgICAgICAgcGFyZW50RWxlbWVudC5hcHBlbmRDaGlsZCh0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb24pO1xuICAgICAgICB2YXIgZmlsZVNjYW5MYWJlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJsYWJlbFwiKTtcbiAgICAgICAgZmlsZVNjYW5MYWJlbC5zZXRBdHRyaWJ1dGUoXCJmb3JcIiwgdGhpcy5nZXRGaWxlU2NhbklucHV0SWQoKSk7XG4gICAgICAgIGZpbGVTY2FuTGFiZWwuc3R5bGUuZGlzcGxheSA9IFwiaW5saW5lLWJsb2NrXCI7XG4gICAgICAgIHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5hcHBlbmRDaGlsZChmaWxlU2NhbkxhYmVsKTtcbiAgICAgICAgdGhpcy5maWxlU2VsZWN0aW9uQnV0dG9uXG4gICAgICAgICAgICA9IEJhc2VVaUVsZW1lbnRGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoXCJidXR0b25cIiwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkZJTEVfU0VMRUNUSU9OX0JVVFRPTl9JRCk7XG4gICAgICAgIHRoaXMuc2V0SW5pdGlhbFZhbHVlVG9CdXR0b24oKTtcbiAgICAgICAgdGhpcy5maWxlU2VsZWN0aW9uQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBmdW5jdGlvbiAoXykge1xuICAgICAgICAgICAgZmlsZVNjYW5MYWJlbC5jbGljaygpO1xuICAgICAgICB9KTtcbiAgICAgICAgZmlsZVNjYW5MYWJlbC5hcHBlbmQodGhpcy5maWxlU2VsZWN0aW9uQnV0dG9uKTtcbiAgICAgICAgdGhpcy5maWxlU2NhbklucHV0XG4gICAgICAgICAgICA9IEJhc2VVaUVsZW1lbnRGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoXCJpbnB1dFwiLCB0aGlzLmdldEZpbGVTY2FuSW5wdXRJZCgpKTtcbiAgICAgICAgdGhpcy5maWxlU2NhbklucHV0LnR5cGUgPSBcImZpbGVcIjtcbiAgICAgICAgdGhpcy5maWxlU2NhbklucHV0LmFjY2VwdCA9IFwiaW1hZ2UvKlwiO1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW5wdXQuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICBmaWxlU2NhbkxhYmVsLmFwcGVuZENoaWxkKHRoaXMuZmlsZVNjYW5JbnB1dCk7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbnB1dC5hZGRFdmVudExpc3RlbmVyKFwiY2hhbmdlXCIsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBpZiAoZSA9PSBudWxsIHx8IGUudGFyZ2V0ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgdGFyZ2V0ID0gZS50YXJnZXQ7XG4gICAgICAgICAgICBpZiAodGFyZ2V0LmZpbGVzICYmIHRhcmdldC5maWxlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZmlsZUxpc3QgPSB0YXJnZXQuZmlsZXM7XG4gICAgICAgICAgICB2YXIgZmlsZSA9IGZpbGVMaXN0WzBdO1xuICAgICAgICAgICAgdmFyIGZpbGVOYW1lID0gZmlsZS5uYW1lO1xuICAgICAgICAgICAgJHRoaXMuc2V0SW1hZ2VOYW1lVG9CdXR0b24oZmlsZU5hbWUpO1xuICAgICAgICAgICAgb25GaWxlU2VsZWN0ZWQoZmlsZSk7XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgZHJhZ0FuZERyb3BNZXNzYWdlID0gdGhpcy5jcmVhdGVEcmFnQW5kRHJvcE1lc3NhZ2UoKTtcbiAgICAgICAgdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLmFwcGVuZENoaWxkKGRyYWdBbmREcm9wTWVzc2FnZSk7XG4gICAgICAgIHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5hZGRFdmVudExpc3RlbmVyKFwiZHJhZ2VudGVyXCIsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgJHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5ib3JkZXJcbiAgICAgICAgICAgICAgICA9ICR0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb25BY3RpdmVCb3JkZXIoKTtcbiAgICAgICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5hZGRFdmVudExpc3RlbmVyKFwiZHJhZ2xlYXZlXCIsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgJHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5ib3JkZXJcbiAgICAgICAgICAgICAgICA9ICR0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb25EZWZhdWx0Qm9yZGVyKCk7XG4gICAgICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb24uYWRkRXZlbnRMaXN0ZW5lcihcImRyYWdvdmVyXCIsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgJHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5ib3JkZXJcbiAgICAgICAgICAgICAgICA9ICR0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb25BY3RpdmVCb3JkZXIoKTtcbiAgICAgICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5hZGRFdmVudExpc3RlbmVyKFwiZHJvcFwiLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICR0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb24uc3R5bGUuYm9yZGVyXG4gICAgICAgICAgICAgICAgPSAkdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uRGVmYXVsdEJvcmRlcigpO1xuICAgICAgICAgICAgdmFyIGRhdGFUcmFuc2ZlciA9IGV2ZW50LmRhdGFUcmFuc2ZlcjtcbiAgICAgICAgICAgIGlmIChkYXRhVHJhbnNmZXIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZmlsZXMgPSBkYXRhVHJhbnNmZXIuZmlsZXM7XG4gICAgICAgICAgICAgICAgaWYgKCFmaWxlcyB8fCBmaWxlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgaXNBbnlGaWxlSW1hZ2UgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGZpbGVzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmaWxlID0gZmlsZXMuaXRlbShpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFmaWxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgaW1hZ2VUeXBlID0gL2ltYWdlLiovO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWZpbGUudHlwZS5tYXRjaChpbWFnZVR5cGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpc0FueUZpbGVJbWFnZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmaWxlTmFtZSA9IGZpbGUubmFtZTtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMuc2V0SW1hZ2VOYW1lVG9CdXR0b24oZmlsZU5hbWUpO1xuICAgICAgICAgICAgICAgICAgICBvbkZpbGVTZWxlY3RlZChmaWxlKTtcbiAgICAgICAgICAgICAgICAgICAgZHJhZ0FuZERyb3BNZXNzYWdlLmlubmVyVGV4dFxuICAgICAgICAgICAgICAgICAgICAgICAgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmRyYWdBbmREcm9wTWVzc2FnZSgpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCFpc0FueUZpbGVJbWFnZSkge1xuICAgICAgICAgICAgICAgICAgICBkcmFnQW5kRHJvcE1lc3NhZ2UuaW5uZXJUZXh0XG4gICAgICAgICAgICAgICAgICAgICAgICA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZHJhZ0FuZERyb3BNZXNzYWdlT25seUltYWdlcygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIEZpbGVTZWxlY3Rpb25VaS5wcm90b3R5cGUuaGlkZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgdGhpcy5maWxlU2NhbklucHV0LmRpc2FibGVkID0gdHJ1ZTtcbiAgICB9O1xuICAgIEZpbGVTZWxlY3Rpb25VaS5wcm90b3R5cGUuc2hvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLmRpc3BsYXkgPSBcImJsb2NrXCI7XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbnB1dC5kaXNhYmxlZCA9IGZhbHNlO1xuICAgIH07XG4gICAgRmlsZVNlbGVjdGlvblVpLnByb3RvdHlwZS5pc1Nob3dpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb24uc3R5bGUuZGlzcGxheSA9PT0gXCJibG9ja1wiO1xuICAgIH07XG4gICAgRmlsZVNlbGVjdGlvblVpLnByb3RvdHlwZS5yZXNldFZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW5wdXQudmFsdWUgPSBcIlwiO1xuICAgICAgICB0aGlzLnNldEluaXRpYWxWYWx1ZVRvQnV0dG9uKCk7XG4gICAgfTtcbiAgICBGaWxlU2VsZWN0aW9uVWkucHJvdG90eXBlLmNyZWF0ZUZpbGVCYXNlZFNjYW5SZWdpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBmaWxlQmFzZWRTY2FuUmVnaW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS50ZXh0QWxpZ24gPSBcImNlbnRlclwiO1xuICAgICAgICBmaWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLm1hcmdpbiA9IFwiYXV0b1wiO1xuICAgICAgICBmaWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLndpZHRoID0gXCI4MCVcIjtcbiAgICAgICAgZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5tYXhXaWR0aCA9IFwiNjAwcHhcIjtcbiAgICAgICAgZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5ib3JkZXJcbiAgICAgICAgICAgID0gdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uRGVmYXVsdEJvcmRlcigpO1xuICAgICAgICBmaWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLnBhZGRpbmcgPSBcIjEwcHhcIjtcbiAgICAgICAgZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5tYXJnaW5Cb3R0b20gPSBcIjEwcHhcIjtcbiAgICAgICAgcmV0dXJuIGZpbGVCYXNlZFNjYW5SZWdpb247XG4gICAgfTtcbiAgICBGaWxlU2VsZWN0aW9uVWkucHJvdG90eXBlLmZpbGVCYXNlZFNjYW5SZWdpb25EZWZhdWx0Qm9yZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCI2cHggZGFzaGVkICNlYmViZWJcIjtcbiAgICB9O1xuICAgIEZpbGVTZWxlY3Rpb25VaS5wcm90b3R5cGUuZmlsZUJhc2VkU2NhblJlZ2lvbkFjdGl2ZUJvcmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiNnB4IGRhc2hlZCByZ2IoMTUzIDE1MSAxNTEpXCI7XG4gICAgfTtcbiAgICBGaWxlU2VsZWN0aW9uVWkucHJvdG90eXBlLmNyZWF0ZURyYWdBbmREcm9wTWVzc2FnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGRyYWdBbmREcm9wTWVzc2FnZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIGRyYWdBbmREcm9wTWVzc2FnZS5pbm5lclRleHRcbiAgICAgICAgICAgID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5kcmFnQW5kRHJvcE1lc3NhZ2UoKTtcbiAgICAgICAgZHJhZ0FuZERyb3BNZXNzYWdlLnN0eWxlLmZvbnRXZWlnaHQgPSBcIjQwMFwiO1xuICAgICAgICByZXR1cm4gZHJhZ0FuZERyb3BNZXNzYWdlO1xuICAgIH07XG4gICAgRmlsZVNlbGVjdGlvblVpLnByb3RvdHlwZS5zZXRJbWFnZU5hbWVUb0J1dHRvbiA9IGZ1bmN0aW9uIChpbWFnZUZpbGVOYW1lKSB7XG4gICAgICAgIHZhciBNQVhfQ0hBUlMgPSAyMDtcbiAgICAgICAgaWYgKGltYWdlRmlsZU5hbWUubGVuZ3RoID4gTUFYX0NIQVJTKSB7XG4gICAgICAgICAgICB2YXIgc3RhcnQ4Q2hhcnMgPSBpbWFnZUZpbGVOYW1lLnN1YnN0cmluZygwLCA4KTtcbiAgICAgICAgICAgIHZhciBsZW5ndGhfMSA9IGltYWdlRmlsZU5hbWUubGVuZ3RoO1xuICAgICAgICAgICAgdmFyIGxhc3Q4Q2hhcnMgPSBpbWFnZUZpbGVOYW1lLnN1YnN0cmluZyhsZW5ndGhfMSAtIDgsIGxlbmd0aF8xKTtcbiAgICAgICAgICAgIGltYWdlRmlsZU5hbWUgPSBcIlwiLmNvbmNhdChzdGFydDhDaGFycywgXCIuLi4uXCIpLmNvbmNhdChsYXN0OENoYXJzKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbmV3VGV4dCA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZmlsZVNlbGVjdGlvbkNob29zZUFub3RoZXIoKVxuICAgICAgICAgICAgKyBcIiAtIFwiXG4gICAgICAgICAgICArIGltYWdlRmlsZU5hbWU7XG4gICAgICAgIHRoaXMuZmlsZVNlbGVjdGlvbkJ1dHRvbi5pbm5lclRleHQgPSBuZXdUZXh0O1xuICAgIH07XG4gICAgRmlsZVNlbGVjdGlvblVpLnByb3RvdHlwZS5zZXRJbml0aWFsVmFsdWVUb0J1dHRvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGluaXRpYWxUZXh0ID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5maWxlU2VsZWN0aW9uQ2hvb3NlSW1hZ2UoKVxuICAgICAgICAgICAgKyBcIiAtIFwiXG4gICAgICAgICAgICArIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZmlsZVNlbGVjdGlvbk5vSW1hZ2VTZWxlY3RlZCgpO1xuICAgICAgICB0aGlzLmZpbGVTZWxlY3Rpb25CdXR0b24uaW5uZXJUZXh0ID0gaW5pdGlhbFRleHQ7XG4gICAgfTtcbiAgICBGaWxlU2VsZWN0aW9uVWkucHJvdG90eXBlLmdldEZpbGVTY2FuSW5wdXRJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiaHRtbDUtcXJjb2RlLXByaXZhdGUtZmlsZXNjYW4taW5wdXRcIjtcbiAgICB9O1xuICAgIEZpbGVTZWxlY3Rpb25VaS5jcmVhdGUgPSBmdW5jdGlvbiAocGFyZW50RWxlbWVudCwgc2hvd09uUmVuZGVyLCBvbkZpbGVTZWxlY3RlZCkge1xuICAgICAgICB2YXIgYnV0dG9uID0gbmV3IEZpbGVTZWxlY3Rpb25VaShwYXJlbnRFbGVtZW50LCBzaG93T25SZW5kZXIsIG9uRmlsZVNlbGVjdGVkKTtcbiAgICAgICAgcmV0dXJuIGJ1dHRvbjtcbiAgICB9O1xuICAgIHJldHVybiBGaWxlU2VsZWN0aW9uVWk7XG59KCkpO1xuZXhwb3J0IHsgRmlsZVNlbGVjdGlvblVpIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1maWxlLXNlbGVjdGlvbi11aS5qcy5tYXAiLCJpbXBvcnQgeyBCYXNlVWlFbGVtZW50RmFjdG9yeSwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzIH0gZnJvbSBcIi4vYmFzZVwiO1xuaW1wb3J0IHsgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncyB9IGZyb20gXCIuLi8uLi9zdHJpbmdzXCI7XG52YXIgQ2FtZXJhU2VsZWN0aW9uVWkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYVNlbGVjdGlvblVpKGNhbWVyYXMpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RFbGVtZW50ID0gQmFzZVVpRWxlbWVudEZhY3RvcnlcbiAgICAgICAgICAgIC5jcmVhdGVFbGVtZW50KFwic2VsZWN0XCIsIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5DQU1FUkFfU0VMRUNUSU9OX1NFTEVDVF9JRCk7XG4gICAgICAgIHRoaXMuY2FtZXJhcyA9IGNhbWVyYXM7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IFtdO1xuICAgIH1cbiAgICBDYW1lcmFTZWxlY3Rpb25VaS5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHBhcmVudEVsZW1lbnQpIHtcbiAgICAgICAgdmFyIGNhbWVyYVNlbGVjdGlvbkNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIpO1xuICAgICAgICBjYW1lcmFTZWxlY3Rpb25Db250YWluZXIuc3R5bGUubWFyZ2luUmlnaHQgPSBcIjEwcHhcIjtcbiAgICAgICAgdmFyIG51bUNhbWVyYXMgPSB0aGlzLmNhbWVyYXMubGVuZ3RoO1xuICAgICAgICBpZiAobnVtQ2FtZXJhcyA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gY2FtZXJhcyBmb3VuZFwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobnVtQ2FtZXJhcyA9PT0gMSkge1xuICAgICAgICAgICAgY2FtZXJhU2VsZWN0aW9uQ29udGFpbmVyLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBzZWxlY3RDYW1lcmFTdHJpbmcgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnNlbGVjdENhbWVyYSgpO1xuICAgICAgICAgICAgY2FtZXJhU2VsZWN0aW9uQ29udGFpbmVyLmlubmVyVGV4dFxuICAgICAgICAgICAgICAgID0gXCJcIi5jb25jYXQoc2VsZWN0Q2FtZXJhU3RyaW5nLCBcIiAoXCIpLmNvbmNhdCh0aGlzLmNhbWVyYXMubGVuZ3RoLCBcIikgIFwiKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYW5vbnltb3VzQ2FtZXJhSWQgPSAxO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5jYW1lcmFzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIGNhbWVyYSA9IF9hW19pXTtcbiAgICAgICAgICAgIHZhciB2YWx1ZSA9IGNhbWVyYS5pZDtcbiAgICAgICAgICAgIHZhciBuYW1lXzEgPSBjYW1lcmEubGFiZWwgPT0gbnVsbCA/IHZhbHVlIDogY2FtZXJhLmxhYmVsO1xuICAgICAgICAgICAgaWYgKCFuYW1lXzEgfHwgbmFtZV8xID09PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgbmFtZV8xID0gW1xuICAgICAgICAgICAgICAgICAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmFub255bW91c0NhbWVyYVByZWZpeCgpLFxuICAgICAgICAgICAgICAgICAgICBhbm9ueW1vdXNDYW1lcmFJZCsrXG4gICAgICAgICAgICAgICAgXS5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBvcHRpb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwib3B0aW9uXCIpO1xuICAgICAgICAgICAgb3B0aW9uLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICBvcHRpb24uaW5uZXJUZXh0ID0gbmFtZV8xO1xuICAgICAgICAgICAgdGhpcy5vcHRpb25zLnB1c2gob3B0aW9uKTtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0RWxlbWVudC5hcHBlbmRDaGlsZChvcHRpb24pO1xuICAgICAgICB9XG4gICAgICAgIGNhbWVyYVNlbGVjdGlvbkNvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLnNlbGVjdEVsZW1lbnQpO1xuICAgICAgICBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKGNhbWVyYVNlbGVjdGlvbkNvbnRhaW5lcik7XG4gICAgfTtcbiAgICBDYW1lcmFTZWxlY3Rpb25VaS5wcm90b3R5cGUuZGlzYWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RFbGVtZW50LmRpc2FibGVkID0gdHJ1ZTtcbiAgICB9O1xuICAgIENhbWVyYVNlbGVjdGlvblVpLnByb3RvdHlwZS5pc0Rpc2FibGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZWxlY3RFbGVtZW50LmRpc2FibGVkID09PSB0cnVlO1xuICAgIH07XG4gICAgQ2FtZXJhU2VsZWN0aW9uVWkucHJvdG90eXBlLmVuYWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RFbGVtZW50LmRpc2FibGVkID0gZmFsc2U7XG4gICAgfTtcbiAgICBDYW1lcmFTZWxlY3Rpb25VaS5wcm90b3R5cGUuZ2V0VmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlbGVjdEVsZW1lbnQudmFsdWU7XG4gICAgfTtcbiAgICBDYW1lcmFTZWxlY3Rpb25VaS5wcm90b3R5cGUuaGFzVmFsdWUgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMub3B0aW9uczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBvcHRpb24gPSBfYVtfaV07XG4gICAgICAgICAgICBpZiAob3B0aW9uLnZhbHVlID09PSB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIENhbWVyYVNlbGVjdGlvblVpLnByb3RvdHlwZS5zZXRWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICBpZiAoIXRoaXMuaGFzVmFsdWUodmFsdWUpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJcIi5jb25jYXQodmFsdWUsIFwiIGlzIG5vdCBwcmVzZW50IGluIHRoZSBjYW1lcmEgbGlzdC5cIikpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2VsZWN0RWxlbWVudC52YWx1ZSA9IHZhbHVlO1xuICAgIH07XG4gICAgQ2FtZXJhU2VsZWN0aW9uVWkucHJvdG90eXBlLmhhc1NpbmdsZUl0ZW0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbWVyYXMubGVuZ3RoID09PSAxO1xuICAgIH07XG4gICAgQ2FtZXJhU2VsZWN0aW9uVWkucHJvdG90eXBlLm51bUNhbWVyYXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbWVyYXMubGVuZ3RoO1xuICAgIH07XG4gICAgQ2FtZXJhU2VsZWN0aW9uVWkuY3JlYXRlID0gZnVuY3Rpb24gKHBhcmVudEVsZW1lbnQsIGNhbWVyYXMpIHtcbiAgICAgICAgdmFyIGNhbWVyYVNlbGVjdFVpID0gbmV3IENhbWVyYVNlbGVjdGlvblVpKGNhbWVyYXMpO1xuICAgICAgICBjYW1lcmFTZWxlY3RVaS5yZW5kZXIocGFyZW50RWxlbWVudCk7XG4gICAgICAgIHJldHVybiBjYW1lcmFTZWxlY3RVaTtcbiAgICB9O1xuICAgIHJldHVybiBDYW1lcmFTZWxlY3Rpb25VaTtcbn0oKSk7XG5leHBvcnQgeyBDYW1lcmFTZWxlY3Rpb25VaSB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y2FtZXJhLXNlbGVjdGlvbi11aS5qcy5tYXAiLCJpbXBvcnQgeyBCYXNlVWlFbGVtZW50RmFjdG9yeSwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzIH0gZnJvbSBcIi4vYmFzZVwiO1xuaW1wb3J0IHsgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncyB9IGZyb20gXCIuLi8uLi9zdHJpbmdzXCI7XG52YXIgQ2FtZXJhWm9vbVVpID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDYW1lcmFab29tVWkoKSB7XG4gICAgICAgIHRoaXMub25DaGFuZ2VDYWxsYmFjayA9IG51bGw7XG4gICAgICAgIHRoaXMuem9vbUVsZW1lbnRDb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQgPSBCYXNlVWlFbGVtZW50RmFjdG9yeS5jcmVhdGVFbGVtZW50KFwiaW5wdXRcIiwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlpPT01fU0xJREVSX0lEKTtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnR5cGUgPSBcInJhbmdlXCI7XG4gICAgICAgIHRoaXMucmFuZ2VUZXh0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNwYW5cIik7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dC5taW4gPSBcIjFcIjtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0Lm1heCA9IFwiNVwiO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQudmFsdWUgPSBcIjFcIjtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnN0ZXAgPSBcIjAuMVwiO1xuICAgIH1cbiAgICBDYW1lcmFab29tVWkucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uIChwYXJlbnRFbGVtZW50LCByZW5kZXJPbkNyZWF0ZSkge1xuICAgICAgICB0aGlzLnpvb21FbGVtZW50Q29udGFpbmVyLnN0eWxlLmRpc3BsYXlcbiAgICAgICAgICAgID0gcmVuZGVyT25DcmVhdGUgPyBcImJsb2NrXCIgOiBcIm5vbmVcIjtcbiAgICAgICAgdGhpcy56b29tRWxlbWVudENvbnRhaW5lci5zdHlsZS5wYWRkaW5nID0gXCI1cHggMTBweFwiO1xuICAgICAgICB0aGlzLnpvb21FbGVtZW50Q29udGFpbmVyLnN0eWxlLnRleHRBbGlnbiA9IFwiY2VudGVyXCI7XG4gICAgICAgIHBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQodGhpcy56b29tRWxlbWVudENvbnRhaW5lcik7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dC5zdHlsZS5kaXNwbGF5ID0gXCJpbmxpbmUtYmxvY2tcIjtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnN0eWxlLndpZHRoID0gXCI1MCVcIjtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnN0eWxlLmhlaWdodCA9IFwiNXB4XCI7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dC5zdHlsZS5iYWNrZ3JvdW5kID0gXCIjZDNkM2QzXCI7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dC5zdHlsZS5vdXRsaW5lID0gXCJub25lXCI7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dC5zdHlsZS5vcGFjaXR5ID0gXCIwLjdcIjtcbiAgICAgICAgdmFyIHpvb21TdHJpbmcgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnpvb20oKTtcbiAgICAgICAgdGhpcy5yYW5nZVRleHQuaW5uZXJUZXh0ID0gXCJcIi5jb25jYXQodGhpcy5yYW5nZUlucHV0LnZhbHVlLCBcInggXCIpLmNvbmNhdCh6b29tU3RyaW5nKTtcbiAgICAgICAgdGhpcy5yYW5nZVRleHQuc3R5bGUubWFyZ2luUmlnaHQgPSBcIjEwcHhcIjtcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LmFkZEV2ZW50TGlzdGVuZXIoXCJpbnB1dFwiLCBmdW5jdGlvbiAoKSB7IHJldHVybiAkdGhpcy5vblZhbHVlQ2hhbmdlKCk7IH0pO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQuYWRkRXZlbnRMaXN0ZW5lcihcImNoYW5nZVwiLCBmdW5jdGlvbiAoKSB7IHJldHVybiAkdGhpcy5vblZhbHVlQ2hhbmdlKCk7IH0pO1xuICAgICAgICB0aGlzLnpvb21FbGVtZW50Q29udGFpbmVyLmFwcGVuZENoaWxkKHRoaXMucmFuZ2VJbnB1dCk7XG4gICAgICAgIHRoaXMuem9vbUVsZW1lbnRDb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5yYW5nZVRleHQpO1xuICAgIH07XG4gICAgQ2FtZXJhWm9vbVVpLnByb3RvdHlwZS5vblZhbHVlQ2hhbmdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgem9vbVN0cmluZyA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muem9vbSgpO1xuICAgICAgICB0aGlzLnJhbmdlVGV4dC5pbm5lclRleHQgPSBcIlwiLmNvbmNhdCh0aGlzLnJhbmdlSW5wdXQudmFsdWUsIFwieCBcIikuY29uY2F0KHpvb21TdHJpbmcpO1xuICAgICAgICBpZiAodGhpcy5vbkNoYW5nZUNhbGxiYWNrKSB7XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlQ2FsbGJhY2socGFyc2VGbG9hdCh0aGlzLnJhbmdlSW5wdXQudmFsdWUpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2FtZXJhWm9vbVVpLnByb3RvdHlwZS5zZXRWYWx1ZXMgPSBmdW5jdGlvbiAobWluVmFsdWUsIG1heFZhbHVlLCBkZWZhdWx0VmFsdWUsIHN0ZXApIHtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0Lm1pbiA9IG1pblZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dC5tYXggPSBtYXhWYWx1ZS50b1N0cmluZygpO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQuc3RlcCA9IHN0ZXAudG9TdHJpbmcoKTtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnZhbHVlID0gZGVmYXVsdFZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgIHRoaXMub25WYWx1ZUNoYW5nZSgpO1xuICAgIH07XG4gICAgQ2FtZXJhWm9vbVVpLnByb3RvdHlwZS5zaG93ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnpvb21FbGVtZW50Q29udGFpbmVyLnN0eWxlLmRpc3BsYXkgPSBcImJsb2NrXCI7XG4gICAgfTtcbiAgICBDYW1lcmFab29tVWkucHJvdG90eXBlLmhpZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuem9vbUVsZW1lbnRDb250YWluZXIuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgIH07XG4gICAgQ2FtZXJhWm9vbVVpLnByb3RvdHlwZS5zZXRPbkNhbWVyYVpvb21WYWx1ZUNoYW5nZUNhbGxiYWNrID0gZnVuY3Rpb24gKG9uQ2hhbmdlQ2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5vbkNoYW5nZUNhbGxiYWNrID0gb25DaGFuZ2VDYWxsYmFjaztcbiAgICB9O1xuICAgIENhbWVyYVpvb21VaS5wcm90b3R5cGUucmVtb3ZlT25DYW1lcmFab29tVmFsdWVDaGFuZ2VDYWxsYmFjayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5vbkNoYW5nZUNhbGxiYWNrID0gbnVsbDtcbiAgICB9O1xuICAgIENhbWVyYVpvb21VaS5jcmVhdGUgPSBmdW5jdGlvbiAocGFyZW50RWxlbWVudCwgcmVuZGVyT25DcmVhdGUpIHtcbiAgICAgICAgdmFyIGNhbWVyYVpvb21VaSA9IG5ldyBDYW1lcmFab29tVWkoKTtcbiAgICAgICAgY2FtZXJhWm9vbVVpLnJlbmRlcihwYXJlbnRFbGVtZW50LCByZW5kZXJPbkNyZWF0ZSk7XG4gICAgICAgIHJldHVybiBjYW1lcmFab29tVWk7XG4gICAgfTtcbiAgICByZXR1cm4gQ2FtZXJhWm9vbVVpO1xufSgpKTtcbmV4cG9ydCB7IENhbWVyYVpvb21VaSB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y2FtZXJhLXpvb20tdWkuanMubWFwIiwiaW1wb3J0IHsgSHRtbDVRcmNvZGVDb25zdGFudHMsIEh0bWw1UXJjb2RlU2NhblR5cGUsIEh0bWw1UXJjb2RlRXJyb3JGYWN0b3J5LCBCYXNlTG9nZ2dlciwgaXNOdWxsT3JVbmRlZmluZWQsIGNsaXAsIH0gZnJvbSBcIi4vY29yZVwiO1xuaW1wb3J0IHsgSHRtbDVRcmNvZGUsIH0gZnJvbSBcIi4vaHRtbDUtcXJjb2RlXCI7XG5pbXBvcnQgeyBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLCB9IGZyb20gXCIuL3N0cmluZ3NcIjtcbmltcG9ydCB7IEFTU0VUX0ZJTEVfU0NBTiwgQVNTRVRfQ0FNRVJBX1NDQU4sIH0gZnJvbSBcIi4vaW1hZ2UtYXNzZXRzXCI7XG5pbXBvcnQgeyBQZXJzaXN0ZWREYXRhTWFuYWdlciB9IGZyb20gXCIuL3N0b3JhZ2VcIjtcbmltcG9ydCB7IExpYnJhcnlJbmZvQ29udGFpbmVyIH0gZnJvbSBcIi4vdWlcIjtcbmltcG9ydCB7IENhbWVyYVBlcm1pc3Npb25zIH0gZnJvbSBcIi4vY2FtZXJhL3Blcm1pc3Npb25zXCI7XG5pbXBvcnQgeyBTY2FuVHlwZVNlbGVjdG9yIH0gZnJvbSBcIi4vdWkvc2Nhbm5lci9zY2FuLXR5cGUtc2VsZWN0b3JcIjtcbmltcG9ydCB7IFRvcmNoQnV0dG9uIH0gZnJvbSBcIi4vdWkvc2Nhbm5lci90b3JjaC1idXR0b25cIjtcbmltcG9ydCB7IEZpbGVTZWxlY3Rpb25VaSB9IGZyb20gXCIuL3VpL3NjYW5uZXIvZmlsZS1zZWxlY3Rpb24tdWlcIjtcbmltcG9ydCB7IEJhc2VVaUVsZW1lbnRGYWN0b3J5LCBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMgfSBmcm9tIFwiLi91aS9zY2FubmVyL2Jhc2VcIjtcbmltcG9ydCB7IENhbWVyYVNlbGVjdGlvblVpIH0gZnJvbSBcIi4vdWkvc2Nhbm5lci9jYW1lcmEtc2VsZWN0aW9uLXVpXCI7XG5pbXBvcnQgeyBDYW1lcmFab29tVWkgfSBmcm9tIFwiLi91aS9zY2FubmVyL2NhbWVyYS16b29tLXVpXCI7XG52YXIgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzO1xuKGZ1bmN0aW9uIChIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMpIHtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXNbSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzW1wiU1RBVFVTX0RFRkFVTFRcIl0gPSAwXSA9IFwiU1RBVFVTX0RFRkFVTFRcIjtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXNbSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzW1wiU1RBVFVTX1NVQ0NFU1NcIl0gPSAxXSA9IFwiU1RBVFVTX1NVQ0NFU1NcIjtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXNbSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzW1wiU1RBVFVTX1dBUk5JTkdcIl0gPSAyXSA9IFwiU1RBVFVTX1dBUk5JTkdcIjtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXNbSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzW1wiU1RBVFVTX1JFUVVFU1RJTkdfUEVSTUlTU0lPTlwiXSA9IDNdID0gXCJTVEFUVVNfUkVRVUVTVElOR19QRVJNSVNTSU9OXCI7XG59KShIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMgfHwgKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cyA9IHt9KSk7XG5mdW5jdGlvbiB0b0h0bWw1UXJjb2RlQ2FtZXJhU2NhbkNvbmZpZyhjb25maWcpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBmcHM6IGNvbmZpZy5mcHMsXG4gICAgICAgIHFyYm94OiBjb25maWcucXJib3gsXG4gICAgICAgIGFzcGVjdFJhdGlvOiBjb25maWcuYXNwZWN0UmF0aW8sXG4gICAgICAgIGRpc2FibGVGbGlwOiBjb25maWcuZGlzYWJsZUZsaXAsXG4gICAgICAgIHZpZGVvQ29uc3RyYWludHM6IGNvbmZpZy52aWRlb0NvbnN0cmFpbnRzXG4gICAgfTtcbn1cbmZ1bmN0aW9uIHRvSHRtbDVRcmNvZGVGdWxsQ29uZmlnKGNvbmZpZywgdmVyYm9zZSkge1xuICAgIHJldHVybiB7XG4gICAgICAgIGZvcm1hdHNUb1N1cHBvcnQ6IGNvbmZpZy5mb3JtYXRzVG9TdXBwb3J0LFxuICAgICAgICB1c2VCYXJDb2RlRGV0ZWN0b3JJZlN1cHBvcnRlZDogY29uZmlnLnVzZUJhckNvZGVEZXRlY3RvcklmU3VwcG9ydGVkLFxuICAgICAgICBleHBlcmltZW50YWxGZWF0dXJlczogY29uZmlnLmV4cGVyaW1lbnRhbEZlYXR1cmVzLFxuICAgICAgICB2ZXJib3NlOiB2ZXJib3NlXG4gICAgfTtcbn1cbnZhciBIdG1sNVFyY29kZVNjYW5uZXIgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEh0bWw1UXJjb2RlU2Nhbm5lcihlbGVtZW50SWQsIGNvbmZpZywgdmVyYm9zZSkge1xuICAgICAgICB0aGlzLmxhc3RNYXRjaEZvdW5kID0gbnVsbDtcbiAgICAgICAgdGhpcy5jYW1lcmFTY2FuSW1hZ2UgPSBudWxsO1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW1hZ2UgPSBudWxsO1xuICAgICAgICB0aGlzLmZpbGVTZWxlY3Rpb25VaSA9IG51bGw7XG4gICAgICAgIHRoaXMuZWxlbWVudElkID0gZWxlbWVudElkO1xuICAgICAgICB0aGlzLmNvbmZpZyA9IHRoaXMuY3JlYXRlQ29uZmlnKGNvbmZpZyk7XG4gICAgICAgIHRoaXMudmVyYm9zZSA9IHZlcmJvc2UgPT09IHRydWU7XG4gICAgICAgIGlmICghZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZWxlbWVudElkKSkge1xuICAgICAgICAgICAgdGhyb3cgXCJIVE1MIEVsZW1lbnQgd2l0aCBpZD1cIi5jb25jYXQoZWxlbWVudElkLCBcIiBub3QgZm91bmRcIik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zY2FuVHlwZVNlbGVjdG9yID0gbmV3IFNjYW5UeXBlU2VsZWN0b3IodGhpcy5jb25maWcuc3VwcG9ydGVkU2NhblR5cGVzKTtcbiAgICAgICAgdGhpcy5jdXJyZW50U2NhblR5cGUgPSB0aGlzLnNjYW5UeXBlU2VsZWN0b3IuZ2V0RGVmYXVsdFNjYW5UeXBlKCk7XG4gICAgICAgIHRoaXMuc2VjdGlvblN3YXBBbGxvd2VkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5sb2dnZXIgPSBuZXcgQmFzZUxvZ2dnZXIodGhpcy52ZXJib3NlKTtcbiAgICAgICAgdGhpcy5wZXJzaXN0ZWREYXRhTWFuYWdlciA9IG5ldyBQZXJzaXN0ZWREYXRhTWFuYWdlcigpO1xuICAgICAgICBpZiAoY29uZmlnLnJlbWVtYmVyTGFzdFVzZWRDYW1lcmEgIT09IHRydWUpIHtcbiAgICAgICAgICAgIHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIucmVzZXQoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uIChxckNvZGVTdWNjZXNzQ2FsbGJhY2ssIHFyQ29kZUVycm9yQ2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5sYXN0TWF0Y2hGb3VuZCA9IG51bGw7XG4gICAgICAgIHRoaXMucXJDb2RlU3VjY2Vzc0NhbGxiYWNrXG4gICAgICAgICAgICA9IGZ1bmN0aW9uIChkZWNvZGVkVGV4dCwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHFyQ29kZVN1Y2Nlc3NDYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICBxckNvZGVTdWNjZXNzQ2FsbGJhY2soZGVjb2RlZFRleHQsIHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMubGFzdE1hdGNoRm91bmQgPT09IGRlY29kZWRUZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgX3RoaXMubGFzdE1hdGNoRm91bmQgPSBkZWNvZGVkVGV4dDtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc2V0SGVhZGVyTWVzc2FnZShIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmxhc3RNYXRjaChkZWNvZGVkVGV4dCksIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cy5TVEFUVVNfU1VDQ0VTUyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgdGhpcy5xckNvZGVFcnJvckNhbGxiYWNrID1cbiAgICAgICAgICAgIGZ1bmN0aW9uIChlcnJvck1lc3NhZ2UsIGVycm9yKSB7XG4gICAgICAgICAgICAgICAgaWYgKHFyQ29kZUVycm9yQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgcXJDb2RlRXJyb3JDYWxsYmFjayhlcnJvck1lc3NhZ2UsIGVycm9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB2YXIgY29udGFpbmVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5lbGVtZW50SWQpO1xuICAgICAgICBpZiAoIWNvbnRhaW5lcikge1xuICAgICAgICAgICAgdGhyb3cgXCJIVE1MIEVsZW1lbnQgd2l0aCBpZD1cIi5jb25jYXQodGhpcy5lbGVtZW50SWQsIFwiIG5vdCBmb3VuZFwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb250YWluZXIuaW5uZXJIVE1MID0gXCJcIjtcbiAgICAgICAgdGhpcy5jcmVhdGVCYXNpY0xheW91dChjb250YWluZXIpO1xuICAgICAgICB0aGlzLmh0bWw1UXJjb2RlID0gbmV3IEh0bWw1UXJjb2RlKHRoaXMuZ2V0U2NhblJlZ2lvbklkKCksIHRvSHRtbDVRcmNvZGVGdWxsQ29uZmlnKHRoaXMuY29uZmlnLCB0aGlzLnZlcmJvc2UpKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUucGF1c2UgPSBmdW5jdGlvbiAoc2hvdWxkUGF1c2VWaWRlbykge1xuICAgICAgICBpZiAoaXNOdWxsT3JVbmRlZmluZWQoc2hvdWxkUGF1c2VWaWRlbykgfHwgc2hvdWxkUGF1c2VWaWRlbyAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgc2hvdWxkUGF1c2VWaWRlbyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZ2V0SHRtbDVRcmNvZGVPckZhaWwoKS5wYXVzZShzaG91bGRQYXVzZVZpZGVvKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUucmVzdW1lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmdldEh0bWw1UXJjb2RlT3JGYWlsKCkucmVzdW1lKCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmdldFN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRIdG1sNVFyY29kZU9yRmFpbCgpLmdldFN0YXRlKCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZW1wdHlIdG1sQ29udGFpbmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIG1haW5Db250YWluZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChfdGhpcy5lbGVtZW50SWQpO1xuICAgICAgICAgICAgaWYgKG1haW5Db250YWluZXIpIHtcbiAgICAgICAgICAgICAgICBtYWluQ29udGFpbmVyLmlubmVySFRNTCA9IFwiXCI7XG4gICAgICAgICAgICAgICAgX3RoaXMucmVzZXRCYXNpY0xheW91dChtYWluQ29udGFpbmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHRoaXMuaHRtbDVRcmNvZGUpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5odG1sNVFyY29kZSkge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmh0bWw1UXJjb2RlLmlzU2Nhbm5pbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuaHRtbDVRcmNvZGUuc3RvcCgpLnRoZW4oZnVuY3Rpb24gKF8pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghX3RoaXMuaHRtbDVRcmNvZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuaHRtbDVRcmNvZGUuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVtcHR5SHRtbENvbnRhaW5lcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy52ZXJib3NlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMubG9nZ2VyLmxvZ0Vycm9yKFwiVW5hYmxlIHRvIHN0b3AgcXJjb2RlIHNjYW5uZXJcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5odG1sNVFyY29kZS5jbGVhcigpO1xuICAgICAgICAgICAgICAgICAgICBlbXB0eUh0bWxDb250YWluZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuZ2V0UnVubmluZ1RyYWNrQ2FwYWJpbGl0aWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRIdG1sNVFyY29kZU9yRmFpbCgpLmdldFJ1bm5pbmdUcmFja0NhcGFiaWxpdGllcygpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXRSdW5uaW5nVHJhY2tTZXR0aW5ncyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0SHRtbDVRcmNvZGVPckZhaWwoKS5nZXRSdW5uaW5nVHJhY2tTZXR0aW5ncygpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5hcHBseVZpZGVvQ29uc3RyYWludHMgPSBmdW5jdGlvbiAodmlkZW9Db25zdGFpbnRzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEh0bWw1UXJjb2RlT3JGYWlsKCkuYXBwbHlWaWRlb0NvbnN0cmFpbnRzKHZpZGVvQ29uc3RhaW50cyk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmdldEh0bWw1UXJjb2RlT3JGYWlsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuaHRtbDVRcmNvZGUpIHtcbiAgICAgICAgICAgIHRocm93IFwiQ29kZSBzY2FubmVyIG5vdCBpbml0aWFsaXplZC5cIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5odG1sNVFyY29kZTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuY3JlYXRlQ29uZmlnID0gZnVuY3Rpb24gKGNvbmZpZykge1xuICAgICAgICBpZiAoY29uZmlnKSB7XG4gICAgICAgICAgICBpZiAoIWNvbmZpZy5mcHMpIHtcbiAgICAgICAgICAgICAgICBjb25maWcuZnBzID0gSHRtbDVRcmNvZGVDb25zdGFudHMuU0NBTl9ERUZBVUxUX0ZQUztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjb25maWcucmVtZW1iZXJMYXN0VXNlZENhbWVyYSAhPT0gKCFIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1JFTUVNQkVSX0xBU1RfQ0FNRVJBX1VTRUQpKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLnJlbWVtYmVyTGFzdFVzZWRDYW1lcmFcbiAgICAgICAgICAgICAgICAgICAgPSBIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1JFTUVNQkVSX0xBU1RfQ0FNRVJBX1VTRUQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWNvbmZpZy5zdXBwb3J0ZWRTY2FuVHlwZXMpIHtcbiAgICAgICAgICAgICAgICBjb25maWcuc3VwcG9ydGVkU2NhblR5cGVzXG4gICAgICAgICAgICAgICAgICAgID0gSHRtbDVRcmNvZGVDb25zdGFudHMuREVGQVVMVF9TVVBQT1JURURfU0NBTl9UWVBFO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGNvbmZpZztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZnBzOiBIdG1sNVFyY29kZUNvbnN0YW50cy5TQ0FOX0RFRkFVTFRfRlBTLFxuICAgICAgICAgICAgcmVtZW1iZXJMYXN0VXNlZENhbWVyYTogSHRtbDVRcmNvZGVDb25zdGFudHMuREVGQVVMVF9SRU1FTUJFUl9MQVNUX0NBTUVSQV9VU0VELFxuICAgICAgICAgICAgc3VwcG9ydGVkU2NhblR5cGVzOiBIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1NVUFBPUlRFRF9TQ0FOX1RZUEVcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuY3JlYXRlQmFzaWNMYXlvdXQgPSBmdW5jdGlvbiAocGFyZW50KSB7XG4gICAgICAgIHBhcmVudC5zdHlsZS5wb3NpdGlvbiA9IFwicmVsYXRpdmVcIjtcbiAgICAgICAgcGFyZW50LnN0eWxlLnBhZGRpbmcgPSBcIjBweFwiO1xuICAgICAgICBwYXJlbnQuc3R5bGUuYm9yZGVyID0gXCIxcHggc29saWQgc2lsdmVyXCI7XG4gICAgICAgIHRoaXMuY3JlYXRlSGVhZGVyKHBhcmVudCk7XG4gICAgICAgIHZhciBxckNvZGVTY2FuUmVnaW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgdmFyIHNjYW5SZWdpb25JZCA9IHRoaXMuZ2V0U2NhblJlZ2lvbklkKCk7XG4gICAgICAgIHFyQ29kZVNjYW5SZWdpb24uaWQgPSBzY2FuUmVnaW9uSWQ7XG4gICAgICAgIHFyQ29kZVNjYW5SZWdpb24uc3R5bGUud2lkdGggPSBcIjEwMCVcIjtcbiAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5zdHlsZS5taW5IZWlnaHQgPSBcIjEwMHB4XCI7XG4gICAgICAgIHFyQ29kZVNjYW5SZWdpb24uc3R5bGUudGV4dEFsaWduID0gXCJjZW50ZXJcIjtcbiAgICAgICAgcGFyZW50LmFwcGVuZENoaWxkKHFyQ29kZVNjYW5SZWdpb24pO1xuICAgICAgICBpZiAoU2NhblR5cGVTZWxlY3Rvci5pc0NhbWVyYVNjYW5UeXBlKHRoaXMuY3VycmVudFNjYW5UeXBlKSkge1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRDYW1lcmFTY2FuSW1hZ2VUb1NjYW5SZWdpb24oKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuaW5zZXJ0RmlsZVNjYW5JbWFnZVRvU2NhblJlZ2lvbigpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBxckNvZGVEYXNoYm9hcmQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICB2YXIgZGFzaGJvYXJkSWQgPSB0aGlzLmdldERhc2hib2FyZElkKCk7XG4gICAgICAgIHFyQ29kZURhc2hib2FyZC5pZCA9IGRhc2hib2FyZElkO1xuICAgICAgICBxckNvZGVEYXNoYm9hcmQuc3R5bGUud2lkdGggPSBcIjEwMCVcIjtcbiAgICAgICAgcGFyZW50LmFwcGVuZENoaWxkKHFyQ29kZURhc2hib2FyZCk7XG4gICAgICAgIHRoaXMuc2V0dXBJbml0aWFsRGFzaGJvYXJkKHFyQ29kZURhc2hib2FyZCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLnJlc2V0QmFzaWNMYXlvdXQgPSBmdW5jdGlvbiAobWFpbkNvbnRhaW5lcikge1xuICAgICAgICBtYWluQ29udGFpbmVyLnN0eWxlLmJvcmRlciA9IFwibm9uZVwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5zZXR1cEluaXRpYWxEYXNoYm9hcmQgPSBmdW5jdGlvbiAoZGFzaGJvYXJkKSB7XG4gICAgICAgIHRoaXMuY3JlYXRlU2VjdGlvbihkYXNoYm9hcmQpO1xuICAgICAgICB0aGlzLmNyZWF0ZVNlY3Rpb25Db250cm9sUGFuZWwoKTtcbiAgICAgICAgaWYgKHRoaXMuc2NhblR5cGVTZWxlY3Rvci5oYXNNb3JlVGhhbk9uZVNjYW5UeXBlKCkpIHtcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlU2VjdGlvblN3YXAoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5jcmVhdGVIZWFkZXIgPSBmdW5jdGlvbiAoZGFzaGJvYXJkKSB7XG4gICAgICAgIHZhciBoZWFkZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICBoZWFkZXIuc3R5bGUudGV4dEFsaWduID0gXCJsZWZ0XCI7XG4gICAgICAgIGhlYWRlci5zdHlsZS5tYXJnaW4gPSBcIjBweFwiO1xuICAgICAgICBkYXNoYm9hcmQuYXBwZW5kQ2hpbGQoaGVhZGVyKTtcbiAgICAgICAgdmFyIGxpYnJhcnlJbmZvID0gbmV3IExpYnJhcnlJbmZvQ29udGFpbmVyKCk7XG4gICAgICAgIGxpYnJhcnlJbmZvLnJlbmRlckludG8oaGVhZGVyKTtcbiAgICAgICAgdmFyIGhlYWRlck1lc3NhZ2VDb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICBoZWFkZXJNZXNzYWdlQ29udGFpbmVyLmlkID0gdGhpcy5nZXRIZWFkZXJNZXNzYWdlQ29udGFpbmVySWQoKTtcbiAgICAgICAgaGVhZGVyTWVzc2FnZUNvbnRhaW5lci5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICAgIGhlYWRlck1lc3NhZ2VDb250YWluZXIuc3R5bGUudGV4dEFsaWduID0gXCJjZW50ZXJcIjtcbiAgICAgICAgaGVhZGVyTWVzc2FnZUNvbnRhaW5lci5zdHlsZS5mb250U2l6ZSA9IFwiMTRweFwiO1xuICAgICAgICBoZWFkZXJNZXNzYWdlQ29udGFpbmVyLnN0eWxlLnBhZGRpbmcgPSBcIjJweCAxMHB4XCI7XG4gICAgICAgIGhlYWRlck1lc3NhZ2VDb250YWluZXIuc3R5bGUubWFyZ2luID0gXCI0cHhcIjtcbiAgICAgICAgaGVhZGVyTWVzc2FnZUNvbnRhaW5lci5zdHlsZS5ib3JkZXJUb3AgPSBcIjFweCBzb2xpZCAjZjZmNmY2XCI7XG4gICAgICAgIGhlYWRlci5hcHBlbmRDaGlsZChoZWFkZXJNZXNzYWdlQ29udGFpbmVyKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuY3JlYXRlU2VjdGlvbiA9IGZ1bmN0aW9uIChkYXNoYm9hcmQpIHtcbiAgICAgICAgdmFyIHNlY3Rpb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICBzZWN0aW9uLmlkID0gdGhpcy5nZXREYXNoYm9hcmRTZWN0aW9uSWQoKTtcbiAgICAgICAgc2VjdGlvbi5zdHlsZS53aWR0aCA9IFwiMTAwJVwiO1xuICAgICAgICBzZWN0aW9uLnN0eWxlLnBhZGRpbmcgPSBcIjEwcHggMHB4IDEwcHggMHB4XCI7XG4gICAgICAgIHNlY3Rpb24uc3R5bGUudGV4dEFsaWduID0gXCJsZWZ0XCI7XG4gICAgICAgIGRhc2hib2FyZC5hcHBlbmRDaGlsZChzZWN0aW9uKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuY3JlYXRlQ2FtZXJhTGlzdFVpID0gZnVuY3Rpb24gKHNjcENhbWVyYVNjYW5SZWdpb24sIHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyLCByZXF1ZXN0UGVybWlzc2lvbkJ1dHRvbikge1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICAkdGhpcy5zaG93SGlkZVNjYW5UeXBlU3dhcExpbmsoZmFsc2UpO1xuICAgICAgICAkdGhpcy5zZXRIZWFkZXJNZXNzYWdlKEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuY2FtZXJhUGVybWlzc2lvblJlcXVlc3RpbmcoKSk7XG4gICAgICAgIHZhciBjcmVhdGVQZXJtaXNzaW9uQnV0dG9uSWZOb3RFeGlzdHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoIXJlcXVlc3RQZXJtaXNzaW9uQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuY3JlYXRlUGVybWlzc2lvbkJ1dHRvbihzY3BDYW1lcmFTY2FuUmVnaW9uLCByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIEh0bWw1UXJjb2RlLmdldENhbWVyYXMoKS50aGVuKGZ1bmN0aW9uIChjYW1lcmFzKSB7XG4gICAgICAgICAgICAkdGhpcy5wZXJzaXN0ZWREYXRhTWFuYWdlci5zZXRIYXNQZXJtaXNzaW9uKHRydWUpO1xuICAgICAgICAgICAgJHRoaXMuc2hvd0hpZGVTY2FuVHlwZVN3YXBMaW5rKHRydWUpO1xuICAgICAgICAgICAgJHRoaXMucmVzZXRIZWFkZXJNZXNzYWdlKCk7XG4gICAgICAgICAgICBpZiAoY2FtZXJhcyAmJiBjYW1lcmFzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBzY3BDYW1lcmFTY2FuUmVnaW9uLnJlbW92ZUNoaWxkKHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyKTtcbiAgICAgICAgICAgICAgICAkdGhpcy5yZW5kZXJDYW1lcmFTZWxlY3Rpb24oY2FtZXJhcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5zZXRIZWFkZXJNZXNzYWdlKEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Mubm9DYW1lcmFGb3VuZCgpLCBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMuU1RBVFVTX1dBUk5JTkcpO1xuICAgICAgICAgICAgICAgIGNyZWF0ZVBlcm1pc3Npb25CdXR0b25JZk5vdEV4aXN0cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KS5jYXRjaChmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgICR0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLnNldEhhc1Blcm1pc3Npb24oZmFsc2UpO1xuICAgICAgICAgICAgaWYgKHJlcXVlc3RQZXJtaXNzaW9uQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgcmVxdWVzdFBlcm1pc3Npb25CdXR0b24uZGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNyZWF0ZVBlcm1pc3Npb25CdXR0b25JZk5vdEV4aXN0cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJHRoaXMuc2V0SGVhZGVyTWVzc2FnZShlcnJvciwgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19XQVJOSU5HKTtcbiAgICAgICAgICAgICR0aGlzLnNob3dIaWRlU2NhblR5cGVTd2FwTGluayh0cnVlKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmNyZWF0ZVBlcm1pc3Npb25CdXR0b24gPSBmdW5jdGlvbiAoc2NwQ2FtZXJhU2NhblJlZ2lvbiwgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIpIHtcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHJlcXVlc3RQZXJtaXNzaW9uQnV0dG9uID0gQmFzZVVpRWxlbWVudEZhY3RvcnlcbiAgICAgICAgICAgIC5jcmVhdGVFbGVtZW50KFwiYnV0dG9uXCIsIHRoaXMuZ2V0Q2FtZXJhUGVybWlzc2lvbkJ1dHRvbklkKCkpO1xuICAgICAgICByZXF1ZXN0UGVybWlzc2lvbkJ1dHRvbi5pbm5lclRleHRcbiAgICAgICAgICAgID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5jYW1lcmFQZXJtaXNzaW9uVGl0bGUoKTtcbiAgICAgICAgcmVxdWVzdFBlcm1pc3Npb25CdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJlcXVlc3RQZXJtaXNzaW9uQnV0dG9uLmRpc2FibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICR0aGlzLmNyZWF0ZUNhbWVyYUxpc3RVaShzY3BDYW1lcmFTY2FuUmVnaW9uLCByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lciwgcmVxdWVzdFBlcm1pc3Npb25CdXR0b24pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIuYXBwZW5kQ2hpbGQocmVxdWVzdFBlcm1pc3Npb25CdXR0b24pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5jcmVhdGVQZXJtaXNzaW9uc1VpID0gZnVuY3Rpb24gKHNjcENhbWVyYVNjYW5SZWdpb24sIHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyKSB7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmIChTY2FuVHlwZVNlbGVjdG9yLmlzQ2FtZXJhU2NhblR5cGUodGhpcy5jdXJyZW50U2NhblR5cGUpXG4gICAgICAgICAgICAmJiB0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLmhhc0NhbWVyYVBlcm1pc3Npb25zKCkpIHtcbiAgICAgICAgICAgIENhbWVyYVBlcm1pc3Npb25zLmhhc1Blcm1pc3Npb25zKCkudGhlbihmdW5jdGlvbiAoaGFzUGVybWlzc2lvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGVybWlzc2lvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMuY3JlYXRlQ2FtZXJhTGlzdFVpKHNjcENhbWVyYVNjYW5SZWdpb24sIHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICR0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLnNldEhhc1Blcm1pc3Npb24oZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5jcmVhdGVQZXJtaXNzaW9uQnV0dG9uKHNjcENhbWVyYVNjYW5SZWdpb24sIHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYXRjaChmdW5jdGlvbiAoXykge1xuICAgICAgICAgICAgICAgICR0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLnNldEhhc1Blcm1pc3Npb24oZmFsc2UpO1xuICAgICAgICAgICAgICAgICR0aGlzLmNyZWF0ZVBlcm1pc3Npb25CdXR0b24oc2NwQ2FtZXJhU2NhblJlZ2lvbiwgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jcmVhdGVQZXJtaXNzaW9uQnV0dG9uKHNjcENhbWVyYVNjYW5SZWdpb24sIHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuY3JlYXRlU2VjdGlvbkNvbnRyb2xQYW5lbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNlY3Rpb24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmdldERhc2hib2FyZFNlY3Rpb25JZCgpKTtcbiAgICAgICAgdmFyIHNlY3Rpb25Db250cm9sUGFuZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICBzZWN0aW9uLmFwcGVuZENoaWxkKHNlY3Rpb25Db250cm9sUGFuZWwpO1xuICAgICAgICB2YXIgc2NwQ2FtZXJhU2NhblJlZ2lvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHNjcENhbWVyYVNjYW5SZWdpb24uaWQgPSB0aGlzLmdldERhc2hib2FyZFNlY3Rpb25DYW1lcmFTY2FuUmVnaW9uSWQoKTtcbiAgICAgICAgc2NwQ2FtZXJhU2NhblJlZ2lvbi5zdHlsZS5kaXNwbGF5XG4gICAgICAgICAgICA9IFNjYW5UeXBlU2VsZWN0b3IuaXNDYW1lcmFTY2FuVHlwZSh0aGlzLmN1cnJlbnRTY2FuVHlwZSlcbiAgICAgICAgICAgICAgICA/IFwiYmxvY2tcIiA6IFwibm9uZVwiO1xuICAgICAgICBzZWN0aW9uQ29udHJvbFBhbmVsLmFwcGVuZENoaWxkKHNjcENhbWVyYVNjYW5SZWdpb24pO1xuICAgICAgICB2YXIgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lci5zdHlsZS50ZXh0QWxpZ24gPSBcImNlbnRlclwiO1xuICAgICAgICBzY3BDYW1lcmFTY2FuUmVnaW9uLmFwcGVuZENoaWxkKHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyKTtcbiAgICAgICAgaWYgKHRoaXMuc2NhblR5cGVTZWxlY3Rvci5pc0NhbWVyYVNjYW5SZXF1aXJlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVBlcm1pc3Npb25zVWkoc2NwQ2FtZXJhU2NhblJlZ2lvbiwgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVuZGVyRmlsZVNjYW5VaShzZWN0aW9uQ29udHJvbFBhbmVsKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUucmVuZGVyRmlsZVNjYW5VaSA9IGZ1bmN0aW9uIChwYXJlbnQpIHtcbiAgICAgICAgdmFyIHNob3dPblJlbmRlciA9IFNjYW5UeXBlU2VsZWN0b3IuaXNGaWxlU2NhblR5cGUodGhpcy5jdXJyZW50U2NhblR5cGUpO1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgb25GaWxlU2VsZWN0ZWQgPSBmdW5jdGlvbiAoZmlsZSkge1xuICAgICAgICAgICAgaWYgKCEkdGhpcy5odG1sNVFyY29kZSkge1xuICAgICAgICAgICAgICAgIHRocm93IFwiaHRtbDVRcmNvZGUgbm90IGRlZmluZWRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghU2NhblR5cGVTZWxlY3Rvci5pc0ZpbGVTY2FuVHlwZSgkdGhpcy5jdXJyZW50U2NhblR5cGUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJHRoaXMuc2V0SGVhZGVyTWVzc2FnZShIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmxvYWRpbmdJbWFnZSgpKTtcbiAgICAgICAgICAgICR0aGlzLmh0bWw1UXJjb2RlLnNjYW5GaWxlVjIoZmlsZSwgdHJ1ZSlcbiAgICAgICAgICAgICAgICAudGhlbihmdW5jdGlvbiAoaHRtbDVxcmNvZGVSZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5yZXNldEhlYWRlck1lc3NhZ2UoKTtcbiAgICAgICAgICAgICAgICAkdGhpcy5xckNvZGVTdWNjZXNzQ2FsbGJhY2soaHRtbDVxcmNvZGVSZXN1bHQuZGVjb2RlZFRleHQsIGh0bWw1cXJjb2RlUmVzdWx0KTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgICAgICR0aGlzLnNldEhlYWRlck1lc3NhZ2UoZXJyb3IsIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cy5TVEFUVVNfV0FSTklORyk7XG4gICAgICAgICAgICAgICAgJHRoaXMucXJDb2RlRXJyb3JDYWxsYmFjayhlcnJvciwgSHRtbDVRcmNvZGVFcnJvckZhY3RvcnkuY3JlYXRlRnJvbShlcnJvcikpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZmlsZVNlbGVjdGlvblVpID0gRmlsZVNlbGVjdGlvblVpLmNyZWF0ZShwYXJlbnQsIHNob3dPblJlbmRlciwgb25GaWxlU2VsZWN0ZWQpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5yZW5kZXJDYW1lcmFTZWxlY3Rpb24gPSBmdW5jdGlvbiAoY2FtZXJhcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgc2NwQ2FtZXJhU2NhblJlZ2lvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZ2V0RGFzaGJvYXJkU2VjdGlvbkNhbWVyYVNjYW5SZWdpb25JZCgpKTtcbiAgICAgICAgc2NwQ2FtZXJhU2NhblJlZ2lvbi5zdHlsZS50ZXh0QWxpZ24gPSBcImNlbnRlclwiO1xuICAgICAgICB2YXIgY2FtZXJhWm9vbVVpID0gQ2FtZXJhWm9vbVVpLmNyZWF0ZShzY3BDYW1lcmFTY2FuUmVnaW9uLCBmYWxzZSk7XG4gICAgICAgIHZhciByZW5kZXJDYW1lcmFab29tVWlJZlN1cHBvcnRlZCA9IGZ1bmN0aW9uIChjYW1lcmFDYXBhYmlsaXRpZXMpIHtcbiAgICAgICAgICAgIHZhciB6b29tQ2FwYWJpbGl0eSA9IGNhbWVyYUNhcGFiaWxpdGllcy56b29tRmVhdHVyZSgpO1xuICAgICAgICAgICAgaWYgKCF6b29tQ2FwYWJpbGl0eS5pc1N1cHBvcnRlZCgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FtZXJhWm9vbVVpLnNldE9uQ2FtZXJhWm9vbVZhbHVlQ2hhbmdlQ2FsbGJhY2soZnVuY3Rpb24gKHpvb21WYWx1ZSkge1xuICAgICAgICAgICAgICAgIHpvb21DYXBhYmlsaXR5LmFwcGx5KHpvb21WYWx1ZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciBkZWZhdWx0Wm9vbSA9IDE7XG4gICAgICAgICAgICBpZiAoX3RoaXMuY29uZmlnLmRlZmF1bHRab29tVmFsdWVJZlN1cHBvcnRlZCkge1xuICAgICAgICAgICAgICAgIGRlZmF1bHRab29tID0gX3RoaXMuY29uZmlnLmRlZmF1bHRab29tVmFsdWVJZlN1cHBvcnRlZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlZmF1bHRab29tID0gY2xpcChkZWZhdWx0Wm9vbSwgem9vbUNhcGFiaWxpdHkubWluKCksIHpvb21DYXBhYmlsaXR5Lm1heCgpKTtcbiAgICAgICAgICAgIGNhbWVyYVpvb21VaS5zZXRWYWx1ZXMoem9vbUNhcGFiaWxpdHkubWluKCksIHpvb21DYXBhYmlsaXR5Lm1heCgpLCBkZWZhdWx0Wm9vbSwgem9vbUNhcGFiaWxpdHkuc3RlcCgpKTtcbiAgICAgICAgICAgIGNhbWVyYVpvb21VaS5zaG93KCk7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBjYW1lcmFTZWxlY3RVaSA9IENhbWVyYVNlbGVjdGlvblVpLmNyZWF0ZShzY3BDYW1lcmFTY2FuUmVnaW9uLCBjYW1lcmFzKTtcbiAgICAgICAgdmFyIGNhbWVyYUFjdGlvbkNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIpO1xuICAgICAgICB2YXIgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24gPSBCYXNlVWlFbGVtZW50RmFjdG9yeS5jcmVhdGVFbGVtZW50KFwiYnV0dG9uXCIsIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5DQU1FUkFfU1RBUlRfQlVUVE9OX0lEKTtcbiAgICAgICAgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24uaW5uZXJUZXh0XG4gICAgICAgICAgICA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muc2NhbkJ1dHRvblN0YXJ0U2Nhbm5pbmdUZXh0KCk7XG4gICAgICAgIGNhbWVyYUFjdGlvbkNvbnRhaW5lci5hcHBlbmRDaGlsZChjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbik7XG4gICAgICAgIHZhciBjYW1lcmFBY3Rpb25TdG9wQnV0dG9uID0gQmFzZVVpRWxlbWVudEZhY3RvcnkuY3JlYXRlRWxlbWVudChcImJ1dHRvblwiLCBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuQ0FNRVJBX1NUT1BfQlVUVE9OX0lEKTtcbiAgICAgICAgY2FtZXJhQWN0aW9uU3RvcEJ1dHRvbi5pbm5lclRleHRcbiAgICAgICAgICAgID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5zY2FuQnV0dG9uU3RvcFNjYW5uaW5nVGV4dCgpO1xuICAgICAgICBjYW1lcmFBY3Rpb25TdG9wQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgY2FtZXJhQWN0aW9uU3RvcEJ1dHRvbi5kaXNhYmxlZCA9IHRydWU7XG4gICAgICAgIGNhbWVyYUFjdGlvbkNvbnRhaW5lci5hcHBlbmRDaGlsZChjYW1lcmFBY3Rpb25TdG9wQnV0dG9uKTtcbiAgICAgICAgdmFyIHRvcmNoQnV0dG9uO1xuICAgICAgICB2YXIgY3JlYXRlQW5kU2hvd1RvcmNoQnV0dG9uSWZTdXBwb3J0ZWQgPSBmdW5jdGlvbiAoY2FtZXJhQ2FwYWJpbGl0aWVzKSB7XG4gICAgICAgICAgICBpZiAoIWNhbWVyYUNhcGFiaWxpdGllcy50b3JjaEZlYXR1cmUoKS5pc1N1cHBvcnRlZCgpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRvcmNoQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRvcmNoQnV0dG9uLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0b3JjaEJ1dHRvbikge1xuICAgICAgICAgICAgICAgIHRvcmNoQnV0dG9uID0gVG9yY2hCdXR0b24uY3JlYXRlKGNhbWVyYUFjdGlvbkNvbnRhaW5lciwgY2FtZXJhQ2FwYWJpbGl0aWVzLnRvcmNoRmVhdHVyZSgpLCB7IGRpc3BsYXk6IFwibm9uZVwiLCBtYXJnaW5MZWZ0OiBcIjVweFwiIH0sIGZ1bmN0aW9uIChlcnJvck1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMuc2V0SGVhZGVyTWVzc2FnZShlcnJvck1lc3NhZ2UsIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cy5TVEFUVVNfV0FSTklORyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0b3JjaEJ1dHRvbi51cGRhdGVUb3JjaENhcGFiaWxpdHkoY2FtZXJhQ2FwYWJpbGl0aWVzLnRvcmNoRmVhdHVyZSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRvcmNoQnV0dG9uLnNob3coKTtcbiAgICAgICAgfTtcbiAgICAgICAgc2NwQ2FtZXJhU2NhblJlZ2lvbi5hcHBlbmRDaGlsZChjYW1lcmFBY3Rpb25Db250YWluZXIpO1xuICAgICAgICB2YXIgcmVzZXRDYW1lcmFBY3Rpb25TdGFydEJ1dHRvbiA9IGZ1bmN0aW9uIChzaG91bGRTaG93KSB7XG4gICAgICAgICAgICBpZiAoIXNob3VsZFNob3cpIHtcbiAgICAgICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5pbm5lclRleHRcbiAgICAgICAgICAgICAgICA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3NcbiAgICAgICAgICAgICAgICAgICAgLnNjYW5CdXR0b25TdGFydFNjYW5uaW5nVGV4dCgpO1xuICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24uc3R5bGUub3BhY2l0eSA9IFwiMVwiO1xuICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24uZGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChzaG91bGRTaG93KSB7XG4gICAgICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24uc3R5bGUuZGlzcGxheSA9IFwiaW5saW5lLWJsb2NrXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBmdW5jdGlvbiAoXykge1xuICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24uaW5uZXJUZXh0XG4gICAgICAgICAgICAgICAgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnNjYW5CdXR0b25TY2FubmluZ1N0YXJ0aW5nKCk7XG4gICAgICAgICAgICBjYW1lcmFTZWxlY3RVaS5kaXNhYmxlKCk7XG4gICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5kaXNhYmxlZCA9IHRydWU7XG4gICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5zdHlsZS5vcGFjaXR5ID0gXCIwLjVcIjtcbiAgICAgICAgICAgIGlmIChfdGhpcy5zY2FuVHlwZVNlbGVjdG9yLmhhc01vcmVUaGFuT25lU2NhblR5cGUoKSkge1xuICAgICAgICAgICAgICAgICR0aGlzLnNob3dIaWRlU2NhblR5cGVTd2FwTGluayhmYWxzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkdGhpcy5yZXNldEhlYWRlck1lc3NhZ2UoKTtcbiAgICAgICAgICAgIHZhciBjYW1lcmFJZCA9IGNhbWVyYVNlbGVjdFVpLmdldFZhbHVlKCk7XG4gICAgICAgICAgICAkdGhpcy5wZXJzaXN0ZWREYXRhTWFuYWdlci5zZXRMYXN0VXNlZENhbWVyYUlkKGNhbWVyYUlkKTtcbiAgICAgICAgICAgICR0aGlzLmh0bWw1UXJjb2RlLnN0YXJ0KGNhbWVyYUlkLCB0b0h0bWw1UXJjb2RlQ2FtZXJhU2NhbkNvbmZpZygkdGhpcy5jb25maWcpLCAkdGhpcy5xckNvZGVTdWNjZXNzQ2FsbGJhY2ssICR0aGlzLnFyQ29kZUVycm9yQ2FsbGJhY2spXG4gICAgICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKF8pIHtcbiAgICAgICAgICAgICAgICBjYW1lcmFBY3Rpb25TdG9wQnV0dG9uLmRpc2FibGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RvcEJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gXCJpbmxpbmUtYmxvY2tcIjtcbiAgICAgICAgICAgICAgICByZXNldENhbWVyYUFjdGlvblN0YXJ0QnV0dG9uKGZhbHNlKTtcbiAgICAgICAgICAgICAgICB2YXIgY2FtZXJhQ2FwYWJpbGl0aWVzID0gJHRoaXMuaHRtbDVRcmNvZGUuZ2V0UnVubmluZ1RyYWNrQ2FtZXJhQ2FwYWJpbGl0aWVzKCk7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmNvbmZpZy5zaG93VG9yY2hCdXR0b25JZlN1cHBvcnRlZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICBjcmVhdGVBbmRTaG93VG9yY2hCdXR0b25JZlN1cHBvcnRlZChjYW1lcmFDYXBhYmlsaXRpZXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuY29uZmlnLnNob3dab29tU2xpZGVySWZTdXBwb3J0ZWQgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyQ2FtZXJhWm9vbVVpSWZTdXBwb3J0ZWQoY2FtZXJhQ2FwYWJpbGl0aWVzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5zaG93SGlkZVNjYW5UeXBlU3dhcExpbmsodHJ1ZSk7XG4gICAgICAgICAgICAgICAgY2FtZXJhU2VsZWN0VWkuZW5hYmxlKCk7XG4gICAgICAgICAgICAgICAgcmVzZXRDYW1lcmFBY3Rpb25TdGFydEJ1dHRvbih0cnVlKTtcbiAgICAgICAgICAgICAgICAkdGhpcy5zZXRIZWFkZXJNZXNzYWdlKGVycm9yLCBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMuU1RBVFVTX1dBUk5JTkcpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoY2FtZXJhU2VsZWN0VWkuaGFzU2luZ2xlSXRlbSgpKSB7XG4gICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5jbGljaygpO1xuICAgICAgICB9XG4gICAgICAgIGNhbWVyYUFjdGlvblN0b3BCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICBpZiAoISR0aGlzLmh0bWw1UXJjb2RlKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgXCJodG1sNVFyY29kZSBub3QgZGVmaW5lZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RvcEJ1dHRvbi5kaXNhYmxlZCA9IHRydWU7XG4gICAgICAgICAgICAkdGhpcy5odG1sNVFyY29kZS5zdG9wKClcbiAgICAgICAgICAgICAgICAudGhlbihmdW5jdGlvbiAoXykge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5zY2FuVHlwZVNlbGVjdG9yLmhhc01vcmVUaGFuT25lU2NhblR5cGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5zaG93SGlkZVNjYW5UeXBlU3dhcExpbmsodHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbWVyYVNlbGVjdFVpLmVuYWJsZSgpO1xuICAgICAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLmRpc2FibGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RvcEJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24uc3R5bGUuZGlzcGxheSA9IFwiaW5saW5lLWJsb2NrXCI7XG4gICAgICAgICAgICAgICAgaWYgKHRvcmNoQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRvcmNoQnV0dG9uLnJlc2V0KCk7XG4gICAgICAgICAgICAgICAgICAgIHRvcmNoQnV0dG9uLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FtZXJhWm9vbVVpLnJlbW92ZU9uQ2FtZXJhWm9vbVZhbHVlQ2hhbmdlQ2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICBjYW1lcmFab29tVWkuaGlkZSgpO1xuICAgICAgICAgICAgICAgICR0aGlzLmluc2VydENhbWVyYVNjYW5JbWFnZVRvU2NhblJlZ2lvbigpO1xuICAgICAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RvcEJ1dHRvbi5kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICR0aGlzLnNldEhlYWRlck1lc3NhZ2UoZXJyb3IsIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cy5TVEFUVVNfV0FSTklORyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICgkdGhpcy5wZXJzaXN0ZWREYXRhTWFuYWdlci5nZXRMYXN0VXNlZENhbWVyYUlkKCkpIHtcbiAgICAgICAgICAgIHZhciBjYW1lcmFJZCA9ICR0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLmdldExhc3RVc2VkQ2FtZXJhSWQoKTtcbiAgICAgICAgICAgIGlmIChjYW1lcmFTZWxlY3RVaS5oYXNWYWx1ZShjYW1lcmFJZCkpIHtcbiAgICAgICAgICAgICAgICBjYW1lcmFTZWxlY3RVaS5zZXRWYWx1ZShjYW1lcmFJZCk7XG4gICAgICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24uY2xpY2soKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICR0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLnJlc2V0TGFzdFVzZWRDYW1lcmFJZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmNyZWF0ZVNlY3Rpb25Td2FwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgVEVYVF9JRl9DQU1FUkFfU0NBTl9TRUxFQ1RFRCA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudGV4dElmQ2FtZXJhU2NhblNlbGVjdGVkKCk7XG4gICAgICAgIHZhciBURVhUX0lGX0ZJTEVfU0NBTl9TRUxFQ1RFRCA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudGV4dElmRmlsZVNjYW5TZWxlY3RlZCgpO1xuICAgICAgICB2YXIgc2VjdGlvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZ2V0RGFzaGJvYXJkU2VjdGlvbklkKCkpO1xuICAgICAgICB2YXIgc3dpdGNoQ29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgc3dpdGNoQ29udGFpbmVyLnN0eWxlLnRleHRBbGlnbiA9IFwiY2VudGVyXCI7XG4gICAgICAgIHZhciBzd2l0Y2hTY2FuVHlwZUxpbmsgPSBCYXNlVWlFbGVtZW50RmFjdG9yeS5jcmVhdGVFbGVtZW50KFwic3BhblwiLCB0aGlzLmdldERhc2hib2FyZFNlY3Rpb25Td2FwTGlua0lkKCkpO1xuICAgICAgICBzd2l0Y2hTY2FuVHlwZUxpbmsuc3R5bGUudGV4dERlY29yYXRpb24gPSBcInVuZGVybGluZVwiO1xuICAgICAgICBzd2l0Y2hTY2FuVHlwZUxpbmsuc3R5bGUuY3Vyc29yID0gXCJwb2ludGVyXCI7XG4gICAgICAgIHN3aXRjaFNjYW5UeXBlTGluay5pbm5lclRleHRcbiAgICAgICAgICAgID0gU2NhblR5cGVTZWxlY3Rvci5pc0NhbWVyYVNjYW5UeXBlKHRoaXMuY3VycmVudFNjYW5UeXBlKVxuICAgICAgICAgICAgICAgID8gVEVYVF9JRl9DQU1FUkFfU0NBTl9TRUxFQ1RFRCA6IFRFWFRfSUZfRklMRV9TQ0FOX1NFTEVDVEVEO1xuICAgICAgICBzd2l0Y2hTY2FuVHlwZUxpbmsuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICghJHRoaXMuc2VjdGlvblN3YXBBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgaWYgKCR0aGlzLnZlcmJvc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMubG9nZ2VyLmxvZ0Vycm9yKFwiU2VjdGlvbiBzd2FwIGNhbGxlZCB3aGVuIG5vdCBhbGxvd2VkXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkdGhpcy5yZXNldEhlYWRlck1lc3NhZ2UoKTtcbiAgICAgICAgICAgICR0aGlzLmZpbGVTZWxlY3Rpb25VaS5yZXNldFZhbHVlKCk7XG4gICAgICAgICAgICAkdGhpcy5zZWN0aW9uU3dhcEFsbG93ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChTY2FuVHlwZVNlbGVjdG9yLmlzQ2FtZXJhU2NhblR5cGUoJHRoaXMuY3VycmVudFNjYW5UeXBlKSkge1xuICAgICAgICAgICAgICAgICR0aGlzLmNsZWFyU2NhblJlZ2lvbigpO1xuICAgICAgICAgICAgICAgICR0aGlzLmdldENhbWVyYVNjYW5SZWdpb24oKS5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICAgICAgICAgICAgJHRoaXMuZmlsZVNlbGVjdGlvblVpLnNob3coKTtcbiAgICAgICAgICAgICAgICBzd2l0Y2hTY2FuVHlwZUxpbmsuaW5uZXJUZXh0ID0gVEVYVF9JRl9GSUxFX1NDQU5fU0VMRUNURUQ7XG4gICAgICAgICAgICAgICAgJHRoaXMuY3VycmVudFNjYW5UeXBlID0gSHRtbDVRcmNvZGVTY2FuVHlwZS5TQ0FOX1RZUEVfRklMRTtcbiAgICAgICAgICAgICAgICAkdGhpcy5pbnNlcnRGaWxlU2NhbkltYWdlVG9TY2FuUmVnaW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5jbGVhclNjYW5SZWdpb24oKTtcbiAgICAgICAgICAgICAgICAkdGhpcy5nZXRDYW1lcmFTY2FuUmVnaW9uKCkuc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIjtcbiAgICAgICAgICAgICAgICAkdGhpcy5maWxlU2VsZWN0aW9uVWkuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHN3aXRjaFNjYW5UeXBlTGluay5pbm5lclRleHQgPSBURVhUX0lGX0NBTUVSQV9TQ0FOX1NFTEVDVEVEO1xuICAgICAgICAgICAgICAgICR0aGlzLmN1cnJlbnRTY2FuVHlwZSA9IEh0bWw1UXJjb2RlU2NhblR5cGUuU0NBTl9UWVBFX0NBTUVSQTtcbiAgICAgICAgICAgICAgICAkdGhpcy5pbnNlcnRDYW1lcmFTY2FuSW1hZ2VUb1NjYW5SZWdpb24oKTtcbiAgICAgICAgICAgICAgICAkdGhpcy5zdGFydENhbWVyYVNjYW5JZlBlcm1pc3Npb25FeGlzdHNPblN3YXAoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICR0aGlzLnNlY3Rpb25Td2FwQWxsb3dlZCA9IHRydWU7XG4gICAgICAgIH0pO1xuICAgICAgICBzd2l0Y2hDb250YWluZXIuYXBwZW5kQ2hpbGQoc3dpdGNoU2NhblR5cGVMaW5rKTtcbiAgICAgICAgc2VjdGlvbi5hcHBlbmRDaGlsZChzd2l0Y2hDb250YWluZXIpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5zdGFydENhbWVyYVNjYW5JZlBlcm1pc3Npb25FeGlzdHNPblN3YXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICh0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLmhhc0NhbWVyYVBlcm1pc3Npb25zKCkpIHtcbiAgICAgICAgICAgIENhbWVyYVBlcm1pc3Npb25zLmhhc1Blcm1pc3Npb25zKCkudGhlbihmdW5jdGlvbiAoaGFzUGVybWlzc2lvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGVybWlzc2lvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBlcm1pc3Npb25CdXR0b24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgkdGhpcy5nZXRDYW1lcmFQZXJtaXNzaW9uQnV0dG9uSWQoKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghcGVybWlzc2lvbkJ1dHRvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMubG9nZ2VyLmxvZ0Vycm9yKFwiUGVybWlzc2lvbiBidXR0b24gbm90IGZvdW5kLCBmYWlsO1wiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFwiUGVybWlzc2lvbiBidXR0b24gbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcGVybWlzc2lvbkJ1dHRvbi5jbGljaygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuc2V0SGFzUGVybWlzc2lvbihmYWxzZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKF8pIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5wZXJzaXN0ZWREYXRhTWFuYWdlci5zZXRIYXNQZXJtaXNzaW9uKGZhbHNlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLnJlc2V0SGVhZGVyTWVzc2FnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG1lc3NhZ2VEaXYgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmdldEhlYWRlck1lc3NhZ2VDb250YWluZXJJZCgpKTtcbiAgICAgICAgbWVzc2FnZURpdi5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLnNldEhlYWRlck1lc3NhZ2UgPSBmdW5jdGlvbiAobWVzc2FnZVRleHQsIHNjYW5uZXJTdGF0dXMpIHtcbiAgICAgICAgaWYgKCFzY2FubmVyU3RhdHVzKSB7XG4gICAgICAgICAgICBzY2FubmVyU3RhdHVzID0gSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19ERUZBVUxUO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtZXNzYWdlRGl2ID0gdGhpcy5nZXRIZWFkZXJNZXNzYWdlRGl2KCk7XG4gICAgICAgIG1lc3NhZ2VEaXYuaW5uZXJUZXh0ID0gbWVzc2FnZVRleHQ7XG4gICAgICAgIG1lc3NhZ2VEaXYuc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIjtcbiAgICAgICAgc3dpdGNoIChzY2FubmVyU3RhdHVzKSB7XG4gICAgICAgICAgICBjYXNlIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cy5TVEFUVVNfU1VDQ0VTUzpcbiAgICAgICAgICAgICAgICBtZXNzYWdlRGl2LnN0eWxlLmJhY2tncm91bmQgPSBcInJnYmEoMTA2LCAxNzUsIDgwLCAwLjI2KVwiO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2VEaXYuc3R5bGUuY29sb3IgPSBcIiM0Nzc3MzVcIjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19XQVJOSU5HOlxuICAgICAgICAgICAgICAgIG1lc3NhZ2VEaXYuc3R5bGUuYmFja2dyb3VuZCA9IFwicmdiYSgyMDMsIDM2LCA0OSwgMC4xNClcIjtcbiAgICAgICAgICAgICAgICBtZXNzYWdlRGl2LnN0eWxlLmNvbG9yID0gXCIjY2IyNDMxXCI7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cy5TVEFUVVNfREVGQVVMVDpcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgbWVzc2FnZURpdi5zdHlsZS5iYWNrZ3JvdW5kID0gXCJyZ2JhKDAsIDAsIDAsIDApXCI7XG4gICAgICAgICAgICAgICAgbWVzc2FnZURpdi5zdHlsZS5jb2xvciA9IFwicmdiKDE3LCAxNywgMTcpXCI7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuc2hvd0hpZGVTY2FuVHlwZVN3YXBMaW5rID0gZnVuY3Rpb24gKHNob3VsZERpc3BsYXkpIHtcbiAgICAgICAgaWYgKHRoaXMuc2NhblR5cGVTZWxlY3Rvci5oYXNNb3JlVGhhbk9uZVNjYW5UeXBlKCkpIHtcbiAgICAgICAgICAgIGlmIChzaG91bGREaXNwbGF5ICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgc2hvdWxkRGlzcGxheSA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zZWN0aW9uU3dhcEFsbG93ZWQgPSBzaG91bGREaXNwbGF5O1xuICAgICAgICAgICAgdGhpcy5nZXREYXNoYm9hcmRTZWN0aW9uU3dhcExpbmsoKS5zdHlsZS5kaXNwbGF5XG4gICAgICAgICAgICAgICAgPSBzaG91bGREaXNwbGF5ID8gXCJpbmxpbmUtYmxvY2tcIiA6IFwibm9uZVwiO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmluc2VydENhbWVyYVNjYW5JbWFnZVRvU2NhblJlZ2lvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHFyQ29kZVNjYW5SZWdpb24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmdldFNjYW5SZWdpb25JZCgpKTtcbiAgICAgICAgaWYgKHRoaXMuY2FtZXJhU2NhbkltYWdlKSB7XG4gICAgICAgICAgICBxckNvZGVTY2FuUmVnaW9uLmlubmVySFRNTCA9IFwiPGJyPlwiO1xuICAgICAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5hcHBlbmRDaGlsZCh0aGlzLmNhbWVyYVNjYW5JbWFnZSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jYW1lcmFTY2FuSW1hZ2UgPSBuZXcgSW1hZ2U7XG4gICAgICAgIHRoaXMuY2FtZXJhU2NhbkltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICBxckNvZGVTY2FuUmVnaW9uLmlubmVySFRNTCA9IFwiPGJyPlwiO1xuICAgICAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5hcHBlbmRDaGlsZCgkdGhpcy5jYW1lcmFTY2FuSW1hZ2UpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmNhbWVyYVNjYW5JbWFnZS53aWR0aCA9IDY0O1xuICAgICAgICB0aGlzLmNhbWVyYVNjYW5JbWFnZS5zdHlsZS5vcGFjaXR5ID0gXCIwLjhcIjtcbiAgICAgICAgdGhpcy5jYW1lcmFTY2FuSW1hZ2Uuc3JjID0gQVNTRVRfQ0FNRVJBX1NDQU47XG4gICAgICAgIHRoaXMuY2FtZXJhU2NhbkltYWdlLmFsdCA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuY2FtZXJhU2NhbkFsdFRleHQoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuaW5zZXJ0RmlsZVNjYW5JbWFnZVRvU2NhblJlZ2lvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHFyQ29kZVNjYW5SZWdpb24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmdldFNjYW5SZWdpb25JZCgpKTtcbiAgICAgICAgaWYgKHRoaXMuZmlsZVNjYW5JbWFnZSkge1xuICAgICAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5pbm5lckhUTUwgPSBcIjxicj5cIjtcbiAgICAgICAgICAgIHFyQ29kZVNjYW5SZWdpb24uYXBwZW5kQ2hpbGQodGhpcy5maWxlU2NhbkltYWdlKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmZpbGVTY2FuSW1hZ2UgPSBuZXcgSW1hZ2U7XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbWFnZS5vbmxvYWQgPSBmdW5jdGlvbiAoXykge1xuICAgICAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5pbm5lckhUTUwgPSBcIjxicj5cIjtcbiAgICAgICAgICAgIHFyQ29kZVNjYW5SZWdpb24uYXBwZW5kQ2hpbGQoJHRoaXMuZmlsZVNjYW5JbWFnZSk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbWFnZS53aWR0aCA9IDY0O1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW1hZ2Uuc3R5bGUub3BhY2l0eSA9IFwiMC44XCI7XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbWFnZS5zcmMgPSBBU1NFVF9GSUxFX1NDQU47XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbWFnZS5hbHQgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmZpbGVTY2FuQWx0VGV4dCgpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5jbGVhclNjYW5SZWdpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBxckNvZGVTY2FuUmVnaW9uID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5nZXRTY2FuUmVnaW9uSWQoKSk7XG4gICAgICAgIHFyQ29kZVNjYW5SZWdpb24uaW5uZXJIVE1MID0gXCJcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuZ2V0RGFzaGJvYXJkU2VjdGlvbklkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJcIi5jb25jYXQodGhpcy5lbGVtZW50SWQsIFwiX19kYXNoYm9hcmRfc2VjdGlvblwiKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuZ2V0RGFzaGJvYXJkU2VjdGlvbkNhbWVyYVNjYW5SZWdpb25JZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiXCIuY29uY2F0KHRoaXMuZWxlbWVudElkLCBcIl9fZGFzaGJvYXJkX3NlY3Rpb25fY3NyXCIpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXREYXNoYm9hcmRTZWN0aW9uU3dhcExpbmtJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5TQ0FOX1RZUEVfQ0hBTkdFX0FOQ0hPUl9JRDtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuZ2V0U2NhblJlZ2lvbklkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJcIi5jb25jYXQodGhpcy5lbGVtZW50SWQsIFwiX19zY2FuX3JlZ2lvblwiKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuZ2V0RGFzaGJvYXJkSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlwiLmNvbmNhdCh0aGlzLmVsZW1lbnRJZCwgXCJfX2Rhc2hib2FyZFwiKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuZ2V0SGVhZGVyTWVzc2FnZUNvbnRhaW5lcklkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJcIi5jb25jYXQodGhpcy5lbGVtZW50SWQsIFwiX19oZWFkZXJfbWVzc2FnZVwiKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuZ2V0Q2FtZXJhUGVybWlzc2lvbkJ1dHRvbklkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkNBTUVSQV9QRVJNSVNTSU9OX0JVVFRPTl9JRDtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuZ2V0Q2FtZXJhU2NhblJlZ2lvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZ2V0RGFzaGJvYXJkU2VjdGlvbkNhbWVyYVNjYW5SZWdpb25JZCgpKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuZ2V0RGFzaGJvYXJkU2VjdGlvblN3YXBMaW5rID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5nZXREYXNoYm9hcmRTZWN0aW9uU3dhcExpbmtJZCgpKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuZ2V0SGVhZGVyTWVzc2FnZURpdiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZ2V0SGVhZGVyTWVzc2FnZUNvbnRhaW5lcklkKCkpO1xuICAgIH07XG4gICAgcmV0dXJuIEh0bWw1UXJjb2RlU2Nhbm5lcjtcbn0oKSk7XG5leHBvcnQgeyBIdG1sNVFyY29kZVNjYW5uZXIgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWh0bWw1LXFyY29kZS1zY2FubmVyLmpzLm1hcCIsImV4cG9ydCB7IEh0bWw1UXJjb2RlIH0gZnJvbSBcIi4vaHRtbDUtcXJjb2RlXCI7XG5leHBvcnQgeyBIdG1sNVFyY29kZVNjYW5uZXIgfSBmcm9tIFwiLi9odG1sNS1xcmNvZGUtc2Nhbm5lclwiO1xuZXhwb3J0IHsgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzIH0gZnJvbSBcIi4vY29yZVwiO1xuZXhwb3J0IHsgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUgfSBmcm9tIFwiLi9zdGF0ZS1tYW5hZ2VyXCI7XG5leHBvcnQgeyBIdG1sNVFyY29kZVNjYW5UeXBlIH0gZnJvbSBcIi4vY29yZVwiO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW5kZXguanMubWFwIiwiZXhwb3J0IGZ1bmN0aW9uIG51bWJlcihuKSB7XG4gICAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcihuKSB8fCBuIDwgMClcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBXcm9uZyBwb3NpdGl2ZSBpbnRlZ2VyOiAke259YCk7XG59XG5leHBvcnQgZnVuY3Rpb24gYm9vbChiKSB7XG4gICAgaWYgKHR5cGVvZiBiICE9PSAnYm9vbGVhbicpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgYm9vbGVhbiwgbm90ICR7Yn1gKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBieXRlcyhiLCAuLi5sZW5ndGhzKSB7XG4gICAgaWYgKCEoYiBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdFeHBlY3RlZCBVaW50OEFycmF5Jyk7XG4gICAgaWYgKGxlbmd0aHMubGVuZ3RoID4gMCAmJiAhbGVuZ3Rocy5pbmNsdWRlcyhiLmxlbmd0aCkpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYEV4cGVjdGVkIFVpbnQ4QXJyYXkgb2YgbGVuZ3RoICR7bGVuZ3Roc30sIG5vdCBvZiBsZW5ndGg9JHtiLmxlbmd0aH1gKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBoYXNoKGhhc2gpIHtcbiAgICBpZiAodHlwZW9mIGhhc2ggIT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIGhhc2guY3JlYXRlICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0hhc2ggc2hvdWxkIGJlIHdyYXBwZWQgYnkgdXRpbHMud3JhcENvbnN0cnVjdG9yJyk7XG4gICAgbnVtYmVyKGhhc2gub3V0cHV0TGVuKTtcbiAgICBudW1iZXIoaGFzaC5ibG9ja0xlbik7XG59XG5leHBvcnQgZnVuY3Rpb24gZXhpc3RzKGluc3RhbmNlLCBjaGVja0ZpbmlzaGVkID0gdHJ1ZSkge1xuICAgIGlmIChpbnN0YW5jZS5kZXN0cm95ZWQpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSGFzaCBpbnN0YW5jZSBoYXMgYmVlbiBkZXN0cm95ZWQnKTtcbiAgICBpZiAoY2hlY2tGaW5pc2hlZCAmJiBpbnN0YW5jZS5maW5pc2hlZClcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdIYXNoI2RpZ2VzdCgpIGhhcyBhbHJlYWR5IGJlZW4gY2FsbGVkJyk7XG59XG5leHBvcnQgZnVuY3Rpb24gb3V0cHV0KG91dCwgaW5zdGFuY2UpIHtcbiAgICBieXRlcyhvdXQpO1xuICAgIGNvbnN0IG1pbiA9IGluc3RhbmNlLm91dHB1dExlbjtcbiAgICBpZiAob3V0Lmxlbmd0aCA8IG1pbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGRpZ2VzdEludG8oKSBleHBlY3RzIG91dHB1dCBidWZmZXIgb2YgbGVuZ3RoIGF0IGxlYXN0ICR7bWlufWApO1xuICAgIH1cbn1cbmNvbnN0IGFzc2VydCA9IHtcbiAgICBudW1iZXIsXG4gICAgYm9vbCxcbiAgICBieXRlcyxcbiAgICBoYXNoLFxuICAgIGV4aXN0cyxcbiAgICBvdXRwdXQsXG59O1xuZXhwb3J0IGRlZmF1bHQgYXNzZXJ0O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9X2Fzc2VydC5qcy5tYXAiLCJjb25zdCBVMzJfTUFTSzY0ID0gQmlnSW50KDIgKiogMzIgLSAxKTtcbmNvbnN0IF8zMm4gPSBCaWdJbnQoMzIpO1xuLy8gV2UgYXJlIG5vdCB1c2luZyBCaWdVaW50NjRBcnJheSwgYmVjYXVzZSB0aGV5IGFyZSBleHRyZW1lbHkgc2xvdyBhcyBwZXIgMjAyMlxuZXhwb3J0IGZ1bmN0aW9uIGZyb21CaWcobiwgbGUgPSBmYWxzZSkge1xuICAgIGlmIChsZSlcbiAgICAgICAgcmV0dXJuIHsgaDogTnVtYmVyKG4gJiBVMzJfTUFTSzY0KSwgbDogTnVtYmVyKChuID4+IF8zMm4pICYgVTMyX01BU0s2NCkgfTtcbiAgICByZXR1cm4geyBoOiBOdW1iZXIoKG4gPj4gXzMybikgJiBVMzJfTUFTSzY0KSB8IDAsIGw6IE51bWJlcihuICYgVTMyX01BU0s2NCkgfCAwIH07XG59XG5leHBvcnQgZnVuY3Rpb24gc3BsaXQobHN0LCBsZSA9IGZhbHNlKSB7XG4gICAgbGV0IEFoID0gbmV3IFVpbnQzMkFycmF5KGxzdC5sZW5ndGgpO1xuICAgIGxldCBBbCA9IG5ldyBVaW50MzJBcnJheShsc3QubGVuZ3RoKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCB7IGgsIGwgfSA9IGZyb21CaWcobHN0W2ldLCBsZSk7XG4gICAgICAgIFtBaFtpXSwgQWxbaV1dID0gW2gsIGxdO1xuICAgIH1cbiAgICByZXR1cm4gW0FoLCBBbF07XG59XG5leHBvcnQgY29uc3QgdG9CaWcgPSAoaCwgbCkgPT4gKEJpZ0ludChoID4+PiAwKSA8PCBfMzJuKSB8IEJpZ0ludChsID4+PiAwKTtcbi8vIGZvciBTaGlmdCBpbiBbMCwgMzIpXG5jb25zdCBzaHJTSCA9IChoLCBsLCBzKSA9PiBoID4+PiBzO1xuY29uc3Qgc2hyU0wgPSAoaCwgbCwgcykgPT4gKGggPDwgKDMyIC0gcykpIHwgKGwgPj4+IHMpO1xuLy8gUmlnaHQgcm90YXRlIGZvciBTaGlmdCBpbiBbMSwgMzIpXG5jb25zdCByb3RyU0ggPSAoaCwgbCwgcykgPT4gKGggPj4+IHMpIHwgKGwgPDwgKDMyIC0gcykpO1xuY29uc3Qgcm90clNMID0gKGgsIGwsIHMpID0+IChoIDw8ICgzMiAtIHMpKSB8IChsID4+PiBzKTtcbi8vIFJpZ2h0IHJvdGF0ZSBmb3IgU2hpZnQgaW4gKDMyLCA2NCksIE5PVEU6IDMyIGlzIHNwZWNpYWwgY2FzZS5cbmNvbnN0IHJvdHJCSCA9IChoLCBsLCBzKSA9PiAoaCA8PCAoNjQgLSBzKSkgfCAobCA+Pj4gKHMgLSAzMikpO1xuY29uc3Qgcm90ckJMID0gKGgsIGwsIHMpID0+IChoID4+PiAocyAtIDMyKSkgfCAobCA8PCAoNjQgLSBzKSk7XG4vLyBSaWdodCByb3RhdGUgZm9yIHNoaWZ0PT09MzIgKGp1c3Qgc3dhcHMgbCZoKVxuY29uc3Qgcm90cjMySCA9IChoLCBsKSA9PiBsO1xuY29uc3Qgcm90cjMyTCA9IChoLCBsKSA9PiBoO1xuLy8gTGVmdCByb3RhdGUgZm9yIFNoaWZ0IGluIFsxLCAzMilcbmNvbnN0IHJvdGxTSCA9IChoLCBsLCBzKSA9PiAoaCA8PCBzKSB8IChsID4+PiAoMzIgLSBzKSk7XG5jb25zdCByb3RsU0wgPSAoaCwgbCwgcykgPT4gKGwgPDwgcykgfCAoaCA+Pj4gKDMyIC0gcykpO1xuLy8gTGVmdCByb3RhdGUgZm9yIFNoaWZ0IGluICgzMiwgNjQpLCBOT1RFOiAzMiBpcyBzcGVjaWFsIGNhc2UuXG5jb25zdCByb3RsQkggPSAoaCwgbCwgcykgPT4gKGwgPDwgKHMgLSAzMikpIHwgKGggPj4+ICg2NCAtIHMpKTtcbmNvbnN0IHJvdGxCTCA9IChoLCBsLCBzKSA9PiAoaCA8PCAocyAtIDMyKSkgfCAobCA+Pj4gKDY0IC0gcykpO1xuLy8gSlMgdXNlcyAzMi1iaXQgc2lnbmVkIGludGVnZXJzIGZvciBiaXR3aXNlIG9wZXJhdGlvbnMgd2hpY2ggbWVhbnMgd2UgY2Fubm90XG4vLyBzaW1wbGUgdGFrZSBjYXJyeSBvdXQgb2YgbG93IGJpdCBzdW0gYnkgc2hpZnQsIHdlIG5lZWQgdG8gdXNlIGRpdmlzaW9uLlxuLy8gUmVtb3ZpbmcgXCJleHBvcnRcIiBoYXMgNSUgcGVyZiBwZW5hbHR5IC1fLVxuZXhwb3J0IGZ1bmN0aW9uIGFkZChBaCwgQWwsIEJoLCBCbCkge1xuICAgIGNvbnN0IGwgPSAoQWwgPj4+IDApICsgKEJsID4+PiAwKTtcbiAgICByZXR1cm4geyBoOiAoQWggKyBCaCArICgobCAvIDIgKiogMzIpIHwgMCkpIHwgMCwgbDogbCB8IDAgfTtcbn1cbi8vIEFkZGl0aW9uIHdpdGggbW9yZSB0aGFuIDIgZWxlbWVudHNcbmNvbnN0IGFkZDNMID0gKEFsLCBCbCwgQ2wpID0+IChBbCA+Pj4gMCkgKyAoQmwgPj4+IDApICsgKENsID4+PiAwKTtcbmNvbnN0IGFkZDNIID0gKGxvdywgQWgsIEJoLCBDaCkgPT4gKEFoICsgQmggKyBDaCArICgobG93IC8gMiAqKiAzMikgfCAwKSkgfCAwO1xuY29uc3QgYWRkNEwgPSAoQWwsIEJsLCBDbCwgRGwpID0+IChBbCA+Pj4gMCkgKyAoQmwgPj4+IDApICsgKENsID4+PiAwKSArIChEbCA+Pj4gMCk7XG5jb25zdCBhZGQ0SCA9IChsb3csIEFoLCBCaCwgQ2gsIERoKSA9PiAoQWggKyBCaCArIENoICsgRGggKyAoKGxvdyAvIDIgKiogMzIpIHwgMCkpIHwgMDtcbmNvbnN0IGFkZDVMID0gKEFsLCBCbCwgQ2wsIERsLCBFbCkgPT4gKEFsID4+PiAwKSArIChCbCA+Pj4gMCkgKyAoQ2wgPj4+IDApICsgKERsID4+PiAwKSArIChFbCA+Pj4gMCk7XG5jb25zdCBhZGQ1SCA9IChsb3csIEFoLCBCaCwgQ2gsIERoLCBFaCkgPT4gKEFoICsgQmggKyBDaCArIERoICsgRWggKyAoKGxvdyAvIDIgKiogMzIpIHwgMCkpIHwgMDtcbi8vIHByZXR0aWVyLWlnbm9yZVxuY29uc3QgdTY0ID0ge1xuICAgIGZyb21CaWcsIHNwbGl0LCB0b0JpZyxcbiAgICBzaHJTSCwgc2hyU0wsXG4gICAgcm90clNILCByb3RyU0wsIHJvdHJCSCwgcm90ckJMLFxuICAgIHJvdHIzMkgsIHJvdHIzMkwsXG4gICAgcm90bFNILCByb3RsU0wsIHJvdGxCSCwgcm90bEJMLFxuICAgIGFkZCwgYWRkM0wsIGFkZDNILCBhZGQ0TCwgYWRkNEgsIGFkZDVILCBhZGQ1TCxcbn07XG5leHBvcnQgZGVmYXVsdCB1NjQ7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1fdTY0LmpzLm1hcCIsImV4cG9ydCBjb25zdCBjcnlwdG8gPSB0eXBlb2YgZ2xvYmFsVGhpcyA9PT0gJ29iamVjdCcgJiYgJ2NyeXB0bycgaW4gZ2xvYmFsVGhpcyA/IGdsb2JhbFRoaXMuY3J5cHRvIDogdW5kZWZpbmVkO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y3J5cHRvLmpzLm1hcCIsIi8qISBub2JsZS1oYXNoZXMgLSBNSVQgTGljZW5zZSAoYykgMjAyMiBQYXVsIE1pbGxlciAocGF1bG1pbGxyLmNvbSkgKi9cbi8vIFdlIHVzZSBgZ2xvYmFsVGhpcy5jcnlwdG9gLCBidXQgbm9kZS5qcyB2ZXJzaW9ucyBlYXJsaWVyIHRoYW4gdjE5IGRvbid0XG4vLyBkZWNsYXJlIGl0IGluIGdsb2JhbCBzY29wZS4gRm9yIG5vZGUuanMsIHBhY2thZ2UuanNvbiNleHBvcnRzIGZpZWxkIG1hcHBpbmdcbi8vIHJld3JpdGVzIGltcG9ydCBmcm9tIGBjcnlwdG9gIHRvIGBjcnlwdG9Ob2RlYCwgd2hpY2ggaW1wb3J0cyBuYXRpdmUgbW9kdWxlLlxuLy8gTWFrZXMgdGhlIHV0aWxzIHVuLWltcG9ydGFibGUgaW4gYnJvd3NlcnMgd2l0aG91dCBhIGJ1bmRsZXIuXG4vLyBPbmNlIG5vZGUuanMgMTggaXMgZGVwcmVjYXRlZCwgd2UgY2FuIGp1c3QgZHJvcCB0aGUgaW1wb3J0LlxuaW1wb3J0IHsgY3J5cHRvIH0gZnJvbSAnQG5vYmxlL2hhc2hlcy9jcnlwdG8nO1xuLy8gQ2FzdCBhcnJheSB0byBkaWZmZXJlbnQgdHlwZVxuZXhwb3J0IGNvbnN0IHU4ID0gKGFycikgPT4gbmV3IFVpbnQ4QXJyYXkoYXJyLmJ1ZmZlciwgYXJyLmJ5dGVPZmZzZXQsIGFyci5ieXRlTGVuZ3RoKTtcbmV4cG9ydCBjb25zdCB1MzIgPSAoYXJyKSA9PiBuZXcgVWludDMyQXJyYXkoYXJyLmJ1ZmZlciwgYXJyLmJ5dGVPZmZzZXQsIE1hdGguZmxvb3IoYXJyLmJ5dGVMZW5ndGggLyA0KSk7XG4vLyBDYXN0IGFycmF5IHRvIHZpZXdcbmV4cG9ydCBjb25zdCBjcmVhdGVWaWV3ID0gKGFycikgPT4gbmV3IERhdGFWaWV3KGFyci5idWZmZXIsIGFyci5ieXRlT2Zmc2V0LCBhcnIuYnl0ZUxlbmd0aCk7XG4vLyBUaGUgcm90YXRlIHJpZ2h0IChjaXJjdWxhciByaWdodCBzaGlmdCkgb3BlcmF0aW9uIGZvciB1aW50MzJcbmV4cG9ydCBjb25zdCByb3RyID0gKHdvcmQsIHNoaWZ0KSA9PiAod29yZCA8PCAoMzIgLSBzaGlmdCkpIHwgKHdvcmQgPj4+IHNoaWZ0KTtcbi8vIGJpZy1lbmRpYW4gaGFyZHdhcmUgaXMgcmFyZS4gSnVzdCBpbiBjYXNlIHNvbWVvbmUgc3RpbGwgZGVjaWRlcyB0byBydW4gaGFzaGVzOlxuLy8gZWFybHktdGhyb3cgYW4gZXJyb3IgYmVjYXVzZSB3ZSBkb24ndCBzdXBwb3J0IEJFIHlldC5cbmV4cG9ydCBjb25zdCBpc0xFID0gbmV3IFVpbnQ4QXJyYXkobmV3IFVpbnQzMkFycmF5KFsweDExMjIzMzQ0XSkuYnVmZmVyKVswXSA9PT0gMHg0NDtcbmlmICghaXNMRSlcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05vbiBsaXR0bGUtZW5kaWFuIGhhcmR3YXJlIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbmNvbnN0IGhleGVzID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogMjU2IH0sICh2LCBpKSA9PiBpLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCAnMCcpKTtcbi8qKlxuICogQGV4YW1wbGUgYnl0ZXNUb0hleChVaW50OEFycmF5LmZyb20oWzB4ZGUsIDB4YWQsIDB4YmUsIDB4ZWZdKSkgLy8gJ2RlYWRiZWVmJ1xuICovXG5leHBvcnQgZnVuY3Rpb24gYnl0ZXNUb0hleCh1aW50OGEpIHtcbiAgICAvLyBwcmUtY2FjaGluZyBpbXByb3ZlcyB0aGUgc3BlZWQgNnhcbiAgICBpZiAoISh1aW50OGEgaW5zdGFuY2VvZiBVaW50OEFycmF5KSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVaW50OEFycmF5IGV4cGVjdGVkJyk7XG4gICAgbGV0IGhleCA9ICcnO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdWludDhhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGhleCArPSBoZXhlc1t1aW50OGFbaV1dO1xuICAgIH1cbiAgICByZXR1cm4gaGV4O1xufVxuLyoqXG4gKiBAZXhhbXBsZSBoZXhUb0J5dGVzKCdkZWFkYmVlZicpIC8vIFVpbnQ4QXJyYXkuZnJvbShbMHhkZSwgMHhhZCwgMHhiZSwgMHhlZl0pXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoZXhUb0J5dGVzKGhleCkge1xuICAgIGlmICh0eXBlb2YgaGV4ICE9PSAnc3RyaW5nJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdoZXhUb0J5dGVzOiBleHBlY3RlZCBzdHJpbmcsIGdvdCAnICsgdHlwZW9mIGhleCk7XG4gICAgfVxuICAgIGlmIChoZXgubGVuZ3RoICUgMilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdoZXhUb0J5dGVzOiByZWNlaXZlZCBpbnZhbGlkIHVucGFkZGVkIGhleCcpO1xuICAgIGNvbnN0IGFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoaGV4Lmxlbmd0aCAvIDIpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgaiA9IGkgKiAyO1xuICAgICAgICBjb25zdCBoZXhCeXRlID0gaGV4LnNsaWNlKGosIGogKyAyKTtcbiAgICAgICAgY29uc3QgYnl0ZSA9IE51bWJlci5wYXJzZUludChoZXhCeXRlLCAxNik7XG4gICAgICAgIGlmIChOdW1iZXIuaXNOYU4oYnl0ZSkgfHwgYnl0ZSA8IDApXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgYnl0ZSBzZXF1ZW5jZScpO1xuICAgICAgICBhcnJheVtpXSA9IGJ5dGU7XG4gICAgfVxuICAgIHJldHVybiBhcnJheTtcbn1cbi8vIFRoZXJlIGlzIG5vIHNldEltbWVkaWF0ZSBpbiBicm93c2VyIGFuZCBzZXRUaW1lb3V0IGlzIHNsb3cuXG4vLyBjYWxsIG9mIGFzeW5jIGZuIHdpbGwgcmV0dXJuIFByb21pc2UsIHdoaWNoIHdpbGwgYmUgZnVsbGZpbGVkIG9ubHkgb25cbi8vIG5leHQgc2NoZWR1bGVyIHF1ZXVlIHByb2Nlc3Npbmcgc3RlcCBhbmQgdGhpcyBpcyBleGFjdGx5IHdoYXQgd2UgbmVlZC5cbmV4cG9ydCBjb25zdCBuZXh0VGljayA9IGFzeW5jICgpID0+IHsgfTtcbi8vIFJldHVybnMgY29udHJvbCB0byB0aHJlYWQgZWFjaCAndGljaycgbXMgdG8gYXZvaWQgYmxvY2tpbmdcbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhc3luY0xvb3AoaXRlcnMsIHRpY2ssIGNiKSB7XG4gICAgbGV0IHRzID0gRGF0ZS5ub3coKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGl0ZXJzOyBpKyspIHtcbiAgICAgICAgY2IoaSk7XG4gICAgICAgIC8vIERhdGUubm93KCkgaXMgbm90IG1vbm90b25pYywgc28gaW4gY2FzZSBpZiBjbG9jayBnb2VzIGJhY2t3YXJkcyB3ZSByZXR1cm4gcmV0dXJuIGNvbnRyb2wgdG9vXG4gICAgICAgIGNvbnN0IGRpZmYgPSBEYXRlLm5vdygpIC0gdHM7XG4gICAgICAgIGlmIChkaWZmID49IDAgJiYgZGlmZiA8IHRpY2spXG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgYXdhaXQgbmV4dFRpY2soKTtcbiAgICAgICAgdHMgKz0gZGlmZjtcbiAgICB9XG59XG5leHBvcnQgZnVuY3Rpb24gdXRmOFRvQnl0ZXMoc3RyKSB7XG4gICAgaWYgKHR5cGVvZiBzdHIgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYHV0ZjhUb0J5dGVzIGV4cGVjdGVkIHN0cmluZywgZ290ICR7dHlwZW9mIHN0cn1gKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzdHIpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHRvQnl0ZXMoZGF0YSkge1xuICAgIGlmICh0eXBlb2YgZGF0YSA9PT0gJ3N0cmluZycpXG4gICAgICAgIGRhdGEgPSB1dGY4VG9CeXRlcyhkYXRhKTtcbiAgICBpZiAoIShkYXRhIGluc3RhbmNlb2YgVWludDhBcnJheSkpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYEV4cGVjdGVkIGlucHV0IHR5cGUgaXMgVWludDhBcnJheSAoZ290ICR7dHlwZW9mIGRhdGF9KWApO1xuICAgIHJldHVybiBkYXRhO1xufVxuLyoqXG4gKiBDb25jYXRzIFVpbnQ4QXJyYXktcyBpbnRvIG9uZTsgbGlrZSBgQnVmZmVyLmNvbmNhdChbYnVmMSwgYnVmMl0pYFxuICogQGV4YW1wbGUgY29uY2F0Qnl0ZXMoYnVmMSwgYnVmMilcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbmNhdEJ5dGVzKC4uLmFycmF5cykge1xuICAgIGlmICghYXJyYXlzLmV2ZXJ5KChhKSA9PiBhIGluc3RhbmNlb2YgVWludDhBcnJheSkpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVWludDhBcnJheSBsaXN0IGV4cGVjdGVkJyk7XG4gICAgaWYgKGFycmF5cy5sZW5ndGggPT09IDEpXG4gICAgICAgIHJldHVybiBhcnJheXNbMF07XG4gICAgY29uc3QgbGVuZ3RoID0gYXJyYXlzLnJlZHVjZSgoYSwgYXJyKSA9PiBhICsgYXJyLmxlbmd0aCwgMCk7XG4gICAgY29uc3QgcmVzdWx0ID0gbmV3IFVpbnQ4QXJyYXkobGVuZ3RoKTtcbiAgICBmb3IgKGxldCBpID0gMCwgcGFkID0gMDsgaSA8IGFycmF5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBhcnIgPSBhcnJheXNbaV07XG4gICAgICAgIHJlc3VsdC5zZXQoYXJyLCBwYWQpO1xuICAgICAgICBwYWQgKz0gYXJyLmxlbmd0aDtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbi8vIEZvciBydW50aW1lIGNoZWNrIGlmIGNsYXNzIGltcGxlbWVudHMgaW50ZXJmYWNlXG5leHBvcnQgY2xhc3MgSGFzaCB7XG4gICAgLy8gU2FmZSB2ZXJzaW9uIHRoYXQgY2xvbmVzIGludGVybmFsIHN0YXRlXG4gICAgY2xvbmUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jbG9uZUludG8oKTtcbiAgICB9XG59XG4vLyBDaGVjayBpZiBvYmplY3QgZG9lbnMndCBoYXZlIGN1c3RvbSBjb25zdHJ1Y3RvciAobGlrZSBVaW50OEFycmF5L0FycmF5KVxuY29uc3QgaXNQbGFpbk9iamVjdCA9IChvYmopID0+IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmopID09PSAnW29iamVjdCBPYmplY3RdJyAmJiBvYmouY29uc3RydWN0b3IgPT09IE9iamVjdDtcbmV4cG9ydCBmdW5jdGlvbiBjaGVja09wdHMoZGVmYXVsdHMsIG9wdHMpIHtcbiAgICBpZiAob3B0cyAhPT0gdW5kZWZpbmVkICYmICh0eXBlb2Ygb3B0cyAhPT0gJ29iamVjdCcgfHwgIWlzUGxhaW5PYmplY3Qob3B0cykpKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdPcHRpb25zIHNob3VsZCBiZSBvYmplY3Qgb3IgdW5kZWZpbmVkJyk7XG4gICAgY29uc3QgbWVyZ2VkID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgb3B0cyk7XG4gICAgcmV0dXJuIG1lcmdlZDtcbn1cbmV4cG9ydCBmdW5jdGlvbiB3cmFwQ29uc3RydWN0b3IoaGFzaENvbnN0cnVjdG9yKSB7XG4gICAgY29uc3QgaGFzaEMgPSAobWVzc2FnZSkgPT4gaGFzaENvbnN0cnVjdG9yKCkudXBkYXRlKHRvQnl0ZXMobWVzc2FnZSkpLmRpZ2VzdCgpO1xuICAgIGNvbnN0IHRtcCA9IGhhc2hDb25zdHJ1Y3RvcigpO1xuICAgIGhhc2hDLm91dHB1dExlbiA9IHRtcC5vdXRwdXRMZW47XG4gICAgaGFzaEMuYmxvY2tMZW4gPSB0bXAuYmxvY2tMZW47XG4gICAgaGFzaEMuY3JlYXRlID0gKCkgPT4gaGFzaENvbnN0cnVjdG9yKCk7XG4gICAgcmV0dXJuIGhhc2hDO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHdyYXBDb25zdHJ1Y3RvcldpdGhPcHRzKGhhc2hDb25zKSB7XG4gICAgY29uc3QgaGFzaEMgPSAobXNnLCBvcHRzKSA9PiBoYXNoQ29ucyhvcHRzKS51cGRhdGUodG9CeXRlcyhtc2cpKS5kaWdlc3QoKTtcbiAgICBjb25zdCB0bXAgPSBoYXNoQ29ucyh7fSk7XG4gICAgaGFzaEMub3V0cHV0TGVuID0gdG1wLm91dHB1dExlbjtcbiAgICBoYXNoQy5ibG9ja0xlbiA9IHRtcC5ibG9ja0xlbjtcbiAgICBoYXNoQy5jcmVhdGUgPSAob3B0cykgPT4gaGFzaENvbnMob3B0cyk7XG4gICAgcmV0dXJuIGhhc2hDO1xufVxuLyoqXG4gKiBTZWN1cmUgUFJORy4gVXNlcyBgZ2xvYmFsVGhpcy5jcnlwdG9gIG9yIG5vZGUuanMgY3J5cHRvIG1vZHVsZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJhbmRvbUJ5dGVzKGJ5dGVzTGVuZ3RoID0gMzIpIHtcbiAgICBpZiAoY3J5cHRvICYmIHR5cGVvZiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKG5ldyBVaW50OEFycmF5KGJ5dGVzTGVuZ3RoKSk7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcignY3J5cHRvLmdldFJhbmRvbVZhbHVlcyBtdXN0IGJlIGRlZmluZWQnKTtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXV0aWxzLmpzLm1hcCIsImltcG9ydCBhc3NlcnQgZnJvbSAnLi9fYXNzZXJ0LmpzJztcbmltcG9ydCB1NjQgZnJvbSAnLi9fdTY0LmpzJztcbmltcG9ydCB7IEhhc2gsIHUzMiwgdG9CeXRlcywgd3JhcENvbnN0cnVjdG9yLCB3cmFwQ29uc3RydWN0b3JXaXRoT3B0cywgfSBmcm9tICcuL3V0aWxzLmpzJztcbi8vIFZhcmlvdXMgcGVyIHJvdW5kIGNvbnN0YW50cyBjYWxjdWxhdGlvbnNcbmNvbnN0IFtTSEEzX1BJLCBTSEEzX1JPVEwsIF9TSEEzX0lPVEFdID0gW1tdLCBbXSwgW11dO1xuY29uc3QgXzBuID0gQmlnSW50KDApO1xuY29uc3QgXzFuID0gQmlnSW50KDEpO1xuY29uc3QgXzJuID0gQmlnSW50KDIpO1xuY29uc3QgXzduID0gQmlnSW50KDcpO1xuY29uc3QgXzI1Nm4gPSBCaWdJbnQoMjU2KTtcbmNvbnN0IF8weDcxbiA9IEJpZ0ludCgweDcxKTtcbmZvciAobGV0IHJvdW5kID0gMCwgUiA9IF8xbiwgeCA9IDEsIHkgPSAwOyByb3VuZCA8IDI0OyByb3VuZCsrKSB7XG4gICAgLy8gUGlcbiAgICBbeCwgeV0gPSBbeSwgKDIgKiB4ICsgMyAqIHkpICUgNV07XG4gICAgU0hBM19QSS5wdXNoKDIgKiAoNSAqIHkgKyB4KSk7XG4gICAgLy8gUm90YXRpb25hbFxuICAgIFNIQTNfUk9UTC5wdXNoKCgoKHJvdW5kICsgMSkgKiAocm91bmQgKyAyKSkgLyAyKSAlIDY0KTtcbiAgICAvLyBJb3RhXG4gICAgbGV0IHQgPSBfMG47XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCA3OyBqKyspIHtcbiAgICAgICAgUiA9ICgoUiA8PCBfMW4pIF4gKChSID4+IF83bikgKiBfMHg3MW4pKSAlIF8yNTZuO1xuICAgICAgICBpZiAoUiAmIF8ybilcbiAgICAgICAgICAgIHQgXj0gXzFuIDw8ICgoXzFuIDw8IEJpZ0ludChqKSkgLSBfMW4pO1xuICAgIH1cbiAgICBfU0hBM19JT1RBLnB1c2godCk7XG59XG5jb25zdCBbU0hBM19JT1RBX0gsIFNIQTNfSU9UQV9MXSA9IHU2NC5zcGxpdChfU0hBM19JT1RBLCB0cnVlKTtcbi8vIExlZnQgcm90YXRpb24gKHdpdGhvdXQgMCwgMzIsIDY0KVxuY29uc3Qgcm90bEggPSAoaCwgbCwgcykgPT4gcyA+IDMyID8gdTY0LnJvdGxCSChoLCBsLCBzKSA6IHU2NC5yb3RsU0goaCwgbCwgcyk7XG5jb25zdCByb3RsTCA9IChoLCBsLCBzKSA9PiBzID4gMzIgPyB1NjQucm90bEJMKGgsIGwsIHMpIDogdTY0LnJvdGxTTChoLCBsLCBzKTtcbi8vIFNhbWUgYXMga2VjY2FrZjE2MDAsIGJ1dCBhbGxvd3MgdG8gc2tpcCBzb21lIHJvdW5kc1xuZXhwb3J0IGZ1bmN0aW9uIGtlY2Nha1Aocywgcm91bmRzID0gMjQpIHtcbiAgICBjb25zdCBCID0gbmV3IFVpbnQzMkFycmF5KDUgKiAyKTtcbiAgICAvLyBOT1RFOiBhbGwgaW5kaWNlcyBhcmUgeDIgc2luY2Ugd2Ugc3RvcmUgc3RhdGUgYXMgdTMyIGluc3RlYWQgb2YgdTY0IChiaWdpbnRzIHRvIHNsb3cgaW4ganMpXG4gICAgZm9yIChsZXQgcm91bmQgPSAyNCAtIHJvdW5kczsgcm91bmQgPCAyNDsgcm91bmQrKykge1xuICAgICAgICAvLyBUaGV0YSDOuFxuICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IDEwOyB4KyspXG4gICAgICAgICAgICBCW3hdID0gc1t4XSBeIHNbeCArIDEwXSBeIHNbeCArIDIwXSBeIHNbeCArIDMwXSBeIHNbeCArIDQwXTtcbiAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCAxMDsgeCArPSAyKSB7XG4gICAgICAgICAgICBjb25zdCBpZHgxID0gKHggKyA4KSAlIDEwO1xuICAgICAgICAgICAgY29uc3QgaWR4MCA9ICh4ICsgMikgJSAxMDtcbiAgICAgICAgICAgIGNvbnN0IEIwID0gQltpZHgwXTtcbiAgICAgICAgICAgIGNvbnN0IEIxID0gQltpZHgwICsgMV07XG4gICAgICAgICAgICBjb25zdCBUaCA9IHJvdGxIKEIwLCBCMSwgMSkgXiBCW2lkeDFdO1xuICAgICAgICAgICAgY29uc3QgVGwgPSByb3RsTChCMCwgQjEsIDEpIF4gQltpZHgxICsgMV07XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IDUwOyB5ICs9IDEwKSB7XG4gICAgICAgICAgICAgICAgc1t4ICsgeV0gXj0gVGg7XG4gICAgICAgICAgICAgICAgc1t4ICsgeSArIDFdIF49IFRsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIFJobyAoz4EpIGFuZCBQaSAoz4ApXG4gICAgICAgIGxldCBjdXJIID0gc1syXTtcbiAgICAgICAgbGV0IGN1ckwgPSBzWzNdO1xuICAgICAgICBmb3IgKGxldCB0ID0gMDsgdCA8IDI0OyB0KyspIHtcbiAgICAgICAgICAgIGNvbnN0IHNoaWZ0ID0gU0hBM19ST1RMW3RdO1xuICAgICAgICAgICAgY29uc3QgVGggPSByb3RsSChjdXJILCBjdXJMLCBzaGlmdCk7XG4gICAgICAgICAgICBjb25zdCBUbCA9IHJvdGxMKGN1ckgsIGN1ckwsIHNoaWZ0KTtcbiAgICAgICAgICAgIGNvbnN0IFBJID0gU0hBM19QSVt0XTtcbiAgICAgICAgICAgIGN1ckggPSBzW1BJXTtcbiAgICAgICAgICAgIGN1ckwgPSBzW1BJICsgMV07XG4gICAgICAgICAgICBzW1BJXSA9IFRoO1xuICAgICAgICAgICAgc1tQSSArIDFdID0gVGw7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ2hpICjPhylcbiAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCA1MDsgeSArPSAxMCkge1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCAxMDsgeCsrKVxuICAgICAgICAgICAgICAgIEJbeF0gPSBzW3kgKyB4XTtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgMTA7IHgrKylcbiAgICAgICAgICAgICAgICBzW3kgKyB4XSBePSB+QlsoeCArIDIpICUgMTBdICYgQlsoeCArIDQpICUgMTBdO1xuICAgICAgICB9XG4gICAgICAgIC8vIElvdGEgKM65KVxuICAgICAgICBzWzBdIF49IFNIQTNfSU9UQV9IW3JvdW5kXTtcbiAgICAgICAgc1sxXSBePSBTSEEzX0lPVEFfTFtyb3VuZF07XG4gICAgfVxuICAgIEIuZmlsbCgwKTtcbn1cbmV4cG9ydCBjbGFzcyBLZWNjYWsgZXh0ZW5kcyBIYXNoIHtcbiAgICAvLyBOT1RFOiB3ZSBhY2NlcHQgYXJndW1lbnRzIGluIGJ5dGVzIGluc3RlYWQgb2YgYml0cyBoZXJlLlxuICAgIGNvbnN0cnVjdG9yKGJsb2NrTGVuLCBzdWZmaXgsIG91dHB1dExlbiwgZW5hYmxlWE9GID0gZmFsc2UsIHJvdW5kcyA9IDI0KSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuYmxvY2tMZW4gPSBibG9ja0xlbjtcbiAgICAgICAgdGhpcy5zdWZmaXggPSBzdWZmaXg7XG4gICAgICAgIHRoaXMub3V0cHV0TGVuID0gb3V0cHV0TGVuO1xuICAgICAgICB0aGlzLmVuYWJsZVhPRiA9IGVuYWJsZVhPRjtcbiAgICAgICAgdGhpcy5yb3VuZHMgPSByb3VuZHM7XG4gICAgICAgIHRoaXMucG9zID0gMDtcbiAgICAgICAgdGhpcy5wb3NPdXQgPSAwO1xuICAgICAgICB0aGlzLmZpbmlzaGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZGVzdHJveWVkID0gZmFsc2U7XG4gICAgICAgIC8vIENhbiBiZSBwYXNzZWQgZnJvbSB1c2VyIGFzIGRrTGVuXG4gICAgICAgIGFzc2VydC5udW1iZXIob3V0cHV0TGVuKTtcbiAgICAgICAgLy8gMTYwMCA9IDV4NSBtYXRyaXggb2YgNjRiaXQuICAxNjAwIGJpdHMgPT09IDIwMCBieXRlc1xuICAgICAgICBpZiAoMCA+PSB0aGlzLmJsb2NrTGVuIHx8IHRoaXMuYmxvY2tMZW4gPj0gMjAwKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTaGEzIHN1cHBvcnRzIG9ubHkga2VjY2FrLWYxNjAwIGZ1bmN0aW9uJyk7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBuZXcgVWludDhBcnJheSgyMDApO1xuICAgICAgICB0aGlzLnN0YXRlMzIgPSB1MzIodGhpcy5zdGF0ZSk7XG4gICAgfVxuICAgIGtlY2NhaygpIHtcbiAgICAgICAga2VjY2FrUCh0aGlzLnN0YXRlMzIsIHRoaXMucm91bmRzKTtcbiAgICAgICAgdGhpcy5wb3NPdXQgPSAwO1xuICAgICAgICB0aGlzLnBvcyA9IDA7XG4gICAgfVxuICAgIHVwZGF0ZShkYXRhKSB7XG4gICAgICAgIGFzc2VydC5leGlzdHModGhpcyk7XG4gICAgICAgIGNvbnN0IHsgYmxvY2tMZW4sIHN0YXRlIH0gPSB0aGlzO1xuICAgICAgICBkYXRhID0gdG9CeXRlcyhkYXRhKTtcbiAgICAgICAgY29uc3QgbGVuID0gZGF0YS5sZW5ndGg7XG4gICAgICAgIGZvciAobGV0IHBvcyA9IDA7IHBvcyA8IGxlbjspIHtcbiAgICAgICAgICAgIGNvbnN0IHRha2UgPSBNYXRoLm1pbihibG9ja0xlbiAtIHRoaXMucG9zLCBsZW4gLSBwb3MpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0YWtlOyBpKyspXG4gICAgICAgICAgICAgICAgc3RhdGVbdGhpcy5wb3MrK10gXj0gZGF0YVtwb3MrK107XG4gICAgICAgICAgICBpZiAodGhpcy5wb3MgPT09IGJsb2NrTGVuKVxuICAgICAgICAgICAgICAgIHRoaXMua2VjY2FrKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIGZpbmlzaCgpIHtcbiAgICAgICAgaWYgKHRoaXMuZmluaXNoZWQpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIHRoaXMuZmluaXNoZWQgPSB0cnVlO1xuICAgICAgICBjb25zdCB7IHN0YXRlLCBzdWZmaXgsIHBvcywgYmxvY2tMZW4gfSA9IHRoaXM7XG4gICAgICAgIC8vIERvIHRoZSBwYWRkaW5nXG4gICAgICAgIHN0YXRlW3Bvc10gXj0gc3VmZml4O1xuICAgICAgICBpZiAoKHN1ZmZpeCAmIDB4ODApICE9PSAwICYmIHBvcyA9PT0gYmxvY2tMZW4gLSAxKVxuICAgICAgICAgICAgdGhpcy5rZWNjYWsoKTtcbiAgICAgICAgc3RhdGVbYmxvY2tMZW4gLSAxXSBePSAweDgwO1xuICAgICAgICB0aGlzLmtlY2NhaygpO1xuICAgIH1cbiAgICB3cml0ZUludG8ob3V0KSB7XG4gICAgICAgIGFzc2VydC5leGlzdHModGhpcywgZmFsc2UpO1xuICAgICAgICBhc3NlcnQuYnl0ZXMob3V0KTtcbiAgICAgICAgdGhpcy5maW5pc2goKTtcbiAgICAgICAgY29uc3QgYnVmZmVyT3V0ID0gdGhpcy5zdGF0ZTtcbiAgICAgICAgY29uc3QgeyBibG9ja0xlbiB9ID0gdGhpcztcbiAgICAgICAgZm9yIChsZXQgcG9zID0gMCwgbGVuID0gb3V0Lmxlbmd0aDsgcG9zIDwgbGVuOykge1xuICAgICAgICAgICAgaWYgKHRoaXMucG9zT3V0ID49IGJsb2NrTGVuKVxuICAgICAgICAgICAgICAgIHRoaXMua2VjY2FrKCk7XG4gICAgICAgICAgICBjb25zdCB0YWtlID0gTWF0aC5taW4oYmxvY2tMZW4gLSB0aGlzLnBvc091dCwgbGVuIC0gcG9zKTtcbiAgICAgICAgICAgIG91dC5zZXQoYnVmZmVyT3V0LnN1YmFycmF5KHRoaXMucG9zT3V0LCB0aGlzLnBvc091dCArIHRha2UpLCBwb3MpO1xuICAgICAgICAgICAgdGhpcy5wb3NPdXQgKz0gdGFrZTtcbiAgICAgICAgICAgIHBvcyArPSB0YWtlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfVxuICAgIHhvZkludG8ob3V0KSB7XG4gICAgICAgIC8vIFNoYTMvS2VjY2FrIHVzYWdlIHdpdGggWE9GIGlzIHByb2JhYmx5IG1pc3Rha2UsIG9ubHkgU0hBS0UgaW5zdGFuY2VzIGNhbiBkbyBYT0ZcbiAgICAgICAgaWYgKCF0aGlzLmVuYWJsZVhPRilcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignWE9GIGlzIG5vdCBwb3NzaWJsZSBmb3IgdGhpcyBpbnN0YW5jZScpO1xuICAgICAgICByZXR1cm4gdGhpcy53cml0ZUludG8ob3V0KTtcbiAgICB9XG4gICAgeG9mKGJ5dGVzKSB7XG4gICAgICAgIGFzc2VydC5udW1iZXIoYnl0ZXMpO1xuICAgICAgICByZXR1cm4gdGhpcy54b2ZJbnRvKG5ldyBVaW50OEFycmF5KGJ5dGVzKSk7XG4gICAgfVxuICAgIGRpZ2VzdEludG8ob3V0KSB7XG4gICAgICAgIGFzc2VydC5vdXRwdXQob3V0LCB0aGlzKTtcbiAgICAgICAgaWYgKHRoaXMuZmluaXNoZWQpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2RpZ2VzdCgpIHdhcyBhbHJlYWR5IGNhbGxlZCcpO1xuICAgICAgICB0aGlzLndyaXRlSW50byhvdXQpO1xuICAgICAgICB0aGlzLmRlc3Ryb3koKTtcbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9XG4gICAgZGlnZXN0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kaWdlc3RJbnRvKG5ldyBVaW50OEFycmF5KHRoaXMub3V0cHV0TGVuKSk7XG4gICAgfVxuICAgIGRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMuZGVzdHJveWVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zdGF0ZS5maWxsKDApO1xuICAgIH1cbiAgICBfY2xvbmVJbnRvKHRvKSB7XG4gICAgICAgIGNvbnN0IHsgYmxvY2tMZW4sIHN1ZmZpeCwgb3V0cHV0TGVuLCByb3VuZHMsIGVuYWJsZVhPRiB9ID0gdGhpcztcbiAgICAgICAgdG8gfHwgKHRvID0gbmV3IEtlY2NhayhibG9ja0xlbiwgc3VmZml4LCBvdXRwdXRMZW4sIGVuYWJsZVhPRiwgcm91bmRzKSk7XG4gICAgICAgIHRvLnN0YXRlMzIuc2V0KHRoaXMuc3RhdGUzMik7XG4gICAgICAgIHRvLnBvcyA9IHRoaXMucG9zO1xuICAgICAgICB0by5wb3NPdXQgPSB0aGlzLnBvc091dDtcbiAgICAgICAgdG8uZmluaXNoZWQgPSB0aGlzLmZpbmlzaGVkO1xuICAgICAgICB0by5yb3VuZHMgPSByb3VuZHM7XG4gICAgICAgIC8vIFN1ZmZpeCBjYW4gY2hhbmdlIGluIGNTSEFLRVxuICAgICAgICB0by5zdWZmaXggPSBzdWZmaXg7XG4gICAgICAgIHRvLm91dHB1dExlbiA9IG91dHB1dExlbjtcbiAgICAgICAgdG8uZW5hYmxlWE9GID0gZW5hYmxlWE9GO1xuICAgICAgICB0by5kZXN0cm95ZWQgPSB0aGlzLmRlc3Ryb3llZDtcbiAgICAgICAgcmV0dXJuIHRvO1xuICAgIH1cbn1cbmNvbnN0IGdlbiA9IChzdWZmaXgsIGJsb2NrTGVuLCBvdXRwdXRMZW4pID0+IHdyYXBDb25zdHJ1Y3RvcigoKSA9PiBuZXcgS2VjY2FrKGJsb2NrTGVuLCBzdWZmaXgsIG91dHB1dExlbikpO1xuZXhwb3J0IGNvbnN0IHNoYTNfMjI0ID0gZ2VuKDB4MDYsIDE0NCwgMjI0IC8gOCk7XG4vKipcbiAqIFNIQTMtMjU2IGhhc2ggZnVuY3Rpb25cbiAqIEBwYXJhbSBtZXNzYWdlIC0gdGhhdCB3b3VsZCBiZSBoYXNoZWRcbiAqL1xuZXhwb3J0IGNvbnN0IHNoYTNfMjU2ID0gZ2VuKDB4MDYsIDEzNiwgMjU2IC8gOCk7XG5leHBvcnQgY29uc3Qgc2hhM18zODQgPSBnZW4oMHgwNiwgMTA0LCAzODQgLyA4KTtcbmV4cG9ydCBjb25zdCBzaGEzXzUxMiA9IGdlbigweDA2LCA3MiwgNTEyIC8gOCk7XG5leHBvcnQgY29uc3Qga2VjY2FrXzIyNCA9IGdlbigweDAxLCAxNDQsIDIyNCAvIDgpO1xuLyoqXG4gKiBrZWNjYWstMjU2IGhhc2ggZnVuY3Rpb24uIERpZmZlcmVudCBmcm9tIFNIQTMtMjU2LlxuICogQHBhcmFtIG1lc3NhZ2UgLSB0aGF0IHdvdWxkIGJlIGhhc2hlZFxuICovXG5leHBvcnQgY29uc3Qga2VjY2FrXzI1NiA9IGdlbigweDAxLCAxMzYsIDI1NiAvIDgpO1xuZXhwb3J0IGNvbnN0IGtlY2Nha18zODQgPSBnZW4oMHgwMSwgMTA0LCAzODQgLyA4KTtcbmV4cG9ydCBjb25zdCBrZWNjYWtfNTEyID0gZ2VuKDB4MDEsIDcyLCA1MTIgLyA4KTtcbmNvbnN0IGdlblNoYWtlID0gKHN1ZmZpeCwgYmxvY2tMZW4sIG91dHB1dExlbikgPT4gd3JhcENvbnN0cnVjdG9yV2l0aE9wdHMoKG9wdHMgPSB7fSkgPT4gbmV3IEtlY2NhayhibG9ja0xlbiwgc3VmZml4LCBvcHRzLmRrTGVuID09PSB1bmRlZmluZWQgPyBvdXRwdXRMZW4gOiBvcHRzLmRrTGVuLCB0cnVlKSk7XG5leHBvcnQgY29uc3Qgc2hha2UxMjggPSBnZW5TaGFrZSgweDFmLCAxNjgsIDEyOCAvIDgpO1xuZXhwb3J0IGNvbnN0IHNoYWtlMjU2ID0gZ2VuU2hha2UoMHgxZiwgMTM2LCAyNTYgLyA4KTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXNoYTMuanMubWFwIiwiLyohIG5vYmxlLWN1cnZlcyAtIE1JVCBMaWNlbnNlIChjKSAyMDIyIFBhdWwgTWlsbGVyIChwYXVsbWlsbHIuY29tKSAqL1xuY29uc3QgXzBuID0gQmlnSW50KDApO1xuY29uc3QgXzFuID0gQmlnSW50KDEpO1xuY29uc3QgXzJuID0gQmlnSW50KDIpO1xuY29uc3QgdThhID0gKGEpID0+IGEgaW5zdGFuY2VvZiBVaW50OEFycmF5O1xuY29uc3QgaGV4ZXMgPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiAyNTYgfSwgKHYsIGkpID0+IGkudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDIsICcwJykpO1xuZXhwb3J0IGZ1bmN0aW9uIGJ5dGVzVG9IZXgoYnl0ZXMpIHtcbiAgICBpZiAoIXU4YShieXRlcykpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVWludDhBcnJheSBleHBlY3RlZCcpO1xuICAgIC8vIHByZS1jYWNoaW5nIGltcHJvdmVzIHRoZSBzcGVlZCA2eFxuICAgIGxldCBoZXggPSAnJztcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJ5dGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGhleCArPSBoZXhlc1tieXRlc1tpXV07XG4gICAgfVxuICAgIHJldHVybiBoZXg7XG59XG5leHBvcnQgZnVuY3Rpb24gbnVtYmVyVG9IZXhVbnBhZGRlZChudW0pIHtcbiAgICBjb25zdCBoZXggPSBudW0udG9TdHJpbmcoMTYpO1xuICAgIHJldHVybiBoZXgubGVuZ3RoICYgMSA/IGAwJHtoZXh9YCA6IGhleDtcbn1cbmV4cG9ydCBmdW5jdGlvbiBoZXhUb051bWJlcihoZXgpIHtcbiAgICBpZiAodHlwZW9mIGhleCAhPT0gJ3N0cmluZycpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaGV4IHN0cmluZyBleHBlY3RlZCwgZ290ICcgKyB0eXBlb2YgaGV4KTtcbiAgICAvLyBCaWcgRW5kaWFuXG4gICAgcmV0dXJuIEJpZ0ludChoZXggPT09ICcnID8gJzAnIDogYDB4JHtoZXh9YCk7XG59XG4vLyBDYWNoaW5nIHNsb3dzIGl0IGRvd24gMi0zeFxuZXhwb3J0IGZ1bmN0aW9uIGhleFRvQnl0ZXMoaGV4KSB7XG4gICAgaWYgKHR5cGVvZiBoZXggIT09ICdzdHJpbmcnKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2hleCBzdHJpbmcgZXhwZWN0ZWQsIGdvdCAnICsgdHlwZW9mIGhleCk7XG4gICAgaWYgKGhleC5sZW5ndGggJSAyKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2hleCBzdHJpbmcgaXMgaW52YWxpZDogdW5wYWRkZWQgJyArIGhleC5sZW5ndGgpO1xuICAgIGNvbnN0IGFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoaGV4Lmxlbmd0aCAvIDIpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgaiA9IGkgKiAyO1xuICAgICAgICBjb25zdCBoZXhCeXRlID0gaGV4LnNsaWNlKGosIGogKyAyKTtcbiAgICAgICAgY29uc3QgYnl0ZSA9IE51bWJlci5wYXJzZUludChoZXhCeXRlLCAxNik7XG4gICAgICAgIGlmIChOdW1iZXIuaXNOYU4oYnl0ZSkgfHwgYnl0ZSA8IDApXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgYnl0ZSBzZXF1ZW5jZScpO1xuICAgICAgICBhcnJheVtpXSA9IGJ5dGU7XG4gICAgfVxuICAgIHJldHVybiBhcnJheTtcbn1cbi8vIEJpZyBFbmRpYW5cbmV4cG9ydCBmdW5jdGlvbiBieXRlc1RvTnVtYmVyQkUoYnl0ZXMpIHtcbiAgICByZXR1cm4gaGV4VG9OdW1iZXIoYnl0ZXNUb0hleChieXRlcykpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGJ5dGVzVG9OdW1iZXJMRShieXRlcykge1xuICAgIGlmICghdThhKGJ5dGVzKSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVaW50OEFycmF5IGV4cGVjdGVkJyk7XG4gICAgcmV0dXJuIGhleFRvTnVtYmVyKGJ5dGVzVG9IZXgoVWludDhBcnJheS5mcm9tKGJ5dGVzKS5yZXZlcnNlKCkpKTtcbn1cbmV4cG9ydCBjb25zdCBudW1iZXJUb0J5dGVzQkUgPSAobiwgbGVuKSA9PiBoZXhUb0J5dGVzKG4udG9TdHJpbmcoMTYpLnBhZFN0YXJ0KGxlbiAqIDIsICcwJykpO1xuZXhwb3J0IGNvbnN0IG51bWJlclRvQnl0ZXNMRSA9IChuLCBsZW4pID0+IG51bWJlclRvQnl0ZXNCRShuLCBsZW4pLnJldmVyc2UoKTtcbi8vIFJldHVybnMgdmFyaWFibGUgbnVtYmVyIGJ5dGVzIChtaW5pbWFsIGJpZ2ludCBlbmNvZGluZz8pXG5leHBvcnQgY29uc3QgbnVtYmVyVG9WYXJCeXRlc0JFID0gKG4pID0+IGhleFRvQnl0ZXMobnVtYmVyVG9IZXhVbnBhZGRlZChuKSk7XG5leHBvcnQgZnVuY3Rpb24gZW5zdXJlQnl0ZXModGl0bGUsIGhleCwgZXhwZWN0ZWRMZW5ndGgpIHtcbiAgICBsZXQgcmVzO1xuICAgIGlmICh0eXBlb2YgaGV4ID09PSAnc3RyaW5nJykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmVzID0gaGV4VG9CeXRlcyhoZXgpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7dGl0bGV9IG11c3QgYmUgdmFsaWQgaGV4IHN0cmluZywgZ290IFwiJHtoZXh9XCIuIENhdXNlOiAke2V9YCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAodThhKGhleCkpIHtcbiAgICAgICAgLy8gVWludDhBcnJheS5mcm9tKCkgaW5zdGVhZCBvZiBoYXNoLnNsaWNlKCkgYmVjYXVzZSBub2RlLmpzIEJ1ZmZlclxuICAgICAgICAvLyBpcyBpbnN0YW5jZSBvZiBVaW50OEFycmF5LCBhbmQgaXRzIHNsaWNlKCkgY3JlYXRlcyAqKm11dGFibGUqKiBjb3B5XG4gICAgICAgIHJlcyA9IFVpbnQ4QXJyYXkuZnJvbShoZXgpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3RpdGxlfSBtdXN0IGJlIGhleCBzdHJpbmcgb3IgVWludDhBcnJheWApO1xuICAgIH1cbiAgICBjb25zdCBsZW4gPSByZXMubGVuZ3RoO1xuICAgIGlmICh0eXBlb2YgZXhwZWN0ZWRMZW5ndGggPT09ICdudW1iZXInICYmIGxlbiAhPT0gZXhwZWN0ZWRMZW5ndGgpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0aXRsZX0gZXhwZWN0ZWQgJHtleHBlY3RlZExlbmd0aH0gYnl0ZXMsIGdvdCAke2xlbn1gKTtcbiAgICByZXR1cm4gcmVzO1xufVxuLy8gQ29waWVzIHNldmVyYWwgVWludDhBcnJheXMgaW50byBvbmUuXG5leHBvcnQgZnVuY3Rpb24gY29uY2F0Qnl0ZXMoLi4uYXJycykge1xuICAgIGNvbnN0IHIgPSBuZXcgVWludDhBcnJheShhcnJzLnJlZHVjZSgoc3VtLCBhKSA9PiBzdW0gKyBhLmxlbmd0aCwgMCkpO1xuICAgIGxldCBwYWQgPSAwOyAvLyB3YWxrIHRocm91Z2ggZWFjaCBpdGVtLCBlbnN1cmUgdGhleSBoYXZlIHByb3BlciB0eXBlXG4gICAgYXJycy5mb3JFYWNoKChhKSA9PiB7XG4gICAgICAgIGlmICghdThhKGEpKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVaW50OEFycmF5IGV4cGVjdGVkJyk7XG4gICAgICAgIHIuc2V0KGEsIHBhZCk7XG4gICAgICAgIHBhZCArPSBhLmxlbmd0aDtcbiAgICB9KTtcbiAgICByZXR1cm4gcjtcbn1cbmV4cG9ydCBmdW5jdGlvbiBlcXVhbEJ5dGVzKGIxLCBiMikge1xuICAgIC8vIFdlIGRvbid0IGNhcmUgYWJvdXQgdGltaW5nIGF0dGFja3MgaGVyZVxuICAgIGlmIChiMS5sZW5ndGggIT09IGIyLmxlbmd0aClcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYjEubGVuZ3RoOyBpKyspXG4gICAgICAgIGlmIChiMVtpXSAhPT0gYjJbaV0pXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIHRydWU7XG59XG5leHBvcnQgZnVuY3Rpb24gdXRmOFRvQnl0ZXMoc3RyKSB7XG4gICAgaWYgKHR5cGVvZiBzdHIgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdXRmOFRvQnl0ZXMgZXhwZWN0ZWQgc3RyaW5nLCBnb3QgJHt0eXBlb2Ygc3RyfWApO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHN0cik7XG59XG4vLyBCaXQgb3BlcmF0aW9uc1xuLy8gQW1vdW50IG9mIGJpdHMgaW5zaWRlIGJpZ2ludCAoU2FtZSBhcyBuLnRvU3RyaW5nKDIpLmxlbmd0aClcbmV4cG9ydCBmdW5jdGlvbiBiaXRMZW4obikge1xuICAgIGxldCBsZW47XG4gICAgZm9yIChsZW4gPSAwOyBuID4gXzBuOyBuID4+PSBfMW4sIGxlbiArPSAxKVxuICAgICAgICA7XG4gICAgcmV0dXJuIGxlbjtcbn1cbi8vIEdldHMgc2luZ2xlIGJpdCBhdCBwb3NpdGlvbi4gTk9URTogZmlyc3QgYml0IHBvc2l0aW9uIGlzIDAgKHNhbWUgYXMgYXJyYXlzKVxuLy8gU2FtZSBhcyAhIStBcnJheS5mcm9tKG4udG9TdHJpbmcoMikpLnJldmVyc2UoKVtwb3NdXG5leHBvcnQgY29uc3QgYml0R2V0ID0gKG4sIHBvcykgPT4gKG4gPj4gQmlnSW50KHBvcykpICYgXzFuO1xuLy8gU2V0cyBzaW5nbGUgYml0IGF0IHBvc2l0aW9uXG5leHBvcnQgY29uc3QgYml0U2V0ID0gKG4sIHBvcywgdmFsdWUpID0+IG4gfCAoKHZhbHVlID8gXzFuIDogXzBuKSA8PCBCaWdJbnQocG9zKSk7XG4vLyBSZXR1cm4gbWFzayBmb3IgTiBiaXRzIChTYW1lIGFzIEJpZ0ludChgMGIke0FycmF5KGkpLmZpbGwoJzEnKS5qb2luKCcnKX1gKSlcbi8vIE5vdCB1c2luZyAqKiBvcGVyYXRvciB3aXRoIGJpZ2ludHMgZm9yIG9sZCBlbmdpbmVzLlxuZXhwb3J0IGNvbnN0IGJpdE1hc2sgPSAobikgPT4gKF8ybiA8PCBCaWdJbnQobiAtIDEpKSAtIF8xbjtcbi8vIERSQkdcbmNvbnN0IHU4biA9IChkYXRhKSA9PiBuZXcgVWludDhBcnJheShkYXRhKTsgLy8gY3JlYXRlcyBVaW50OEFycmF5XG5jb25zdCB1OGZyID0gKGFycikgPT4gVWludDhBcnJheS5mcm9tKGFycik7IC8vIGFub3RoZXIgc2hvcnRjdXRcbi8qKlxuICogTWluaW1hbCBITUFDLURSQkcgZnJvbSBOSVNUIDgwMC05MCBmb3IgUkZDNjk3OSBzaWdzLlxuICogQHJldHVybnMgZnVuY3Rpb24gdGhhdCB3aWxsIGNhbGwgRFJCRyB1bnRpbCAybmQgYXJnIHJldHVybnMgc29tZXRoaW5nIG1lYW5pbmdmdWxcbiAqIEBleGFtcGxlXG4gKiAgIGNvbnN0IGRyYmcgPSBjcmVhdGVIbWFjRFJCRzxLZXk+KDMyLCAzMiwgaG1hYyk7XG4gKiAgIGRyYmcoc2VlZCwgYnl0ZXNUb0tleSk7IC8vIGJ5dGVzVG9LZXkgbXVzdCByZXR1cm4gS2V5IG9yIHVuZGVmaW5lZFxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlSG1hY0RyYmcoaGFzaExlbiwgcUJ5dGVMZW4sIGhtYWNGbikge1xuICAgIGlmICh0eXBlb2YgaGFzaExlbiAhPT0gJ251bWJlcicgfHwgaGFzaExlbiA8IDIpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaGFzaExlbiBtdXN0IGJlIGEgbnVtYmVyJyk7XG4gICAgaWYgKHR5cGVvZiBxQnl0ZUxlbiAhPT0gJ251bWJlcicgfHwgcUJ5dGVMZW4gPCAyKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3FCeXRlTGVuIG11c3QgYmUgYSBudW1iZXInKTtcbiAgICBpZiAodHlwZW9mIGhtYWNGbiAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdobWFjRm4gbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gICAgLy8gU3RlcCBCLCBTdGVwIEM6IHNldCBoYXNoTGVuIHRvIDgqY2VpbChobGVuLzgpXG4gICAgbGV0IHYgPSB1OG4oaGFzaExlbik7IC8vIE1pbmltYWwgbm9uLWZ1bGwtc3BlYyBITUFDLURSQkcgZnJvbSBOSVNUIDgwMC05MCBmb3IgUkZDNjk3OSBzaWdzLlxuICAgIGxldCBrID0gdThuKGhhc2hMZW4pOyAvLyBTdGVwcyBCIGFuZCBDIG9mIFJGQzY5NzkgMy4yOiBzZXQgaGFzaExlbiwgaW4gb3VyIGNhc2UgYWx3YXlzIHNhbWVcbiAgICBsZXQgaSA9IDA7IC8vIEl0ZXJhdGlvbnMgY291bnRlciwgd2lsbCB0aHJvdyB3aGVuIG92ZXIgMTAwMFxuICAgIGNvbnN0IHJlc2V0ID0gKCkgPT4ge1xuICAgICAgICB2LmZpbGwoMSk7XG4gICAgICAgIGsuZmlsbCgwKTtcbiAgICAgICAgaSA9IDA7XG4gICAgfTtcbiAgICBjb25zdCBoID0gKC4uLmIpID0+IGhtYWNGbihrLCB2LCAuLi5iKTsgLy8gaG1hYyhrKSh2LCAuLi52YWx1ZXMpXG4gICAgY29uc3QgcmVzZWVkID0gKHNlZWQgPSB1OG4oKSkgPT4ge1xuICAgICAgICAvLyBITUFDLURSQkcgcmVzZWVkKCkgZnVuY3Rpb24uIFN0ZXBzIEQtR1xuICAgICAgICBrID0gaCh1OGZyKFsweDAwXSksIHNlZWQpOyAvLyBrID0gaG1hYyhrIHx8IHYgfHwgMHgwMCB8fCBzZWVkKVxuICAgICAgICB2ID0gaCgpOyAvLyB2ID0gaG1hYyhrIHx8IHYpXG4gICAgICAgIGlmIChzZWVkLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgayA9IGgodThmcihbMHgwMV0pLCBzZWVkKTsgLy8gayA9IGhtYWMoayB8fCB2IHx8IDB4MDEgfHwgc2VlZClcbiAgICAgICAgdiA9IGgoKTsgLy8gdiA9IGhtYWMoayB8fCB2KVxuICAgIH07XG4gICAgY29uc3QgZ2VuID0gKCkgPT4ge1xuICAgICAgICAvLyBITUFDLURSQkcgZ2VuZXJhdGUoKSBmdW5jdGlvblxuICAgICAgICBpZiAoaSsrID49IDEwMDApXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2RyYmc6IHRyaWVkIDEwMDAgdmFsdWVzJyk7XG4gICAgICAgIGxldCBsZW4gPSAwO1xuICAgICAgICBjb25zdCBvdXQgPSBbXTtcbiAgICAgICAgd2hpbGUgKGxlbiA8IHFCeXRlTGVuKSB7XG4gICAgICAgICAgICB2ID0gaCgpO1xuICAgICAgICAgICAgY29uc3Qgc2wgPSB2LnNsaWNlKCk7XG4gICAgICAgICAgICBvdXQucHVzaChzbCk7XG4gICAgICAgICAgICBsZW4gKz0gdi5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvbmNhdEJ5dGVzKC4uLm91dCk7XG4gICAgfTtcbiAgICBjb25zdCBnZW5VbnRpbCA9IChzZWVkLCBwcmVkKSA9PiB7XG4gICAgICAgIHJlc2V0KCk7XG4gICAgICAgIHJlc2VlZChzZWVkKTsgLy8gU3RlcHMgRC1HXG4gICAgICAgIGxldCByZXMgPSB1bmRlZmluZWQ7IC8vIFN0ZXAgSDogZ3JpbmQgdW50aWwgayBpcyBpbiBbMS4ubi0xXVxuICAgICAgICB3aGlsZSAoIShyZXMgPSBwcmVkKGdlbigpKSkpXG4gICAgICAgICAgICByZXNlZWQoKTtcbiAgICAgICAgcmVzZXQoKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIHJldHVybiBnZW5VbnRpbDtcbn1cbi8vIFZhbGlkYXRpbmcgY3VydmVzIGFuZCBmaWVsZHNcbmNvbnN0IHZhbGlkYXRvckZucyA9IHtcbiAgICBiaWdpbnQ6ICh2YWwpID0+IHR5cGVvZiB2YWwgPT09ICdiaWdpbnQnLFxuICAgIGZ1bmN0aW9uOiAodmFsKSA9PiB0eXBlb2YgdmFsID09PSAnZnVuY3Rpb24nLFxuICAgIGJvb2xlYW46ICh2YWwpID0+IHR5cGVvZiB2YWwgPT09ICdib29sZWFuJyxcbiAgICBzdHJpbmc6ICh2YWwpID0+IHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnLFxuICAgIGlzU2FmZUludGVnZXI6ICh2YWwpID0+IE51bWJlci5pc1NhZmVJbnRlZ2VyKHZhbCksXG4gICAgYXJyYXk6ICh2YWwpID0+IEFycmF5LmlzQXJyYXkodmFsKSxcbiAgICBmaWVsZDogKHZhbCwgb2JqZWN0KSA9PiBvYmplY3QuRnAuaXNWYWxpZCh2YWwpLFxuICAgIGhhc2g6ICh2YWwpID0+IHR5cGVvZiB2YWwgPT09ICdmdW5jdGlvbicgJiYgTnVtYmVyLmlzU2FmZUludGVnZXIodmFsLm91dHB1dExlbiksXG59O1xuLy8gdHlwZSBSZWNvcmQ8SyBleHRlbmRzIHN0cmluZyB8IG51bWJlciB8IHN5bWJvbCwgVD4gPSB7IFtQIGluIEtdOiBUOyB9XG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVPYmplY3Qob2JqZWN0LCB2YWxpZGF0b3JzLCBvcHRWYWxpZGF0b3JzID0ge30pIHtcbiAgICBjb25zdCBjaGVja0ZpZWxkID0gKGZpZWxkTmFtZSwgdHlwZSwgaXNPcHRpb25hbCkgPT4ge1xuICAgICAgICBjb25zdCBjaGVja1ZhbCA9IHZhbGlkYXRvckZuc1t0eXBlXTtcbiAgICAgICAgaWYgKHR5cGVvZiBjaGVja1ZhbCAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB2YWxpZGF0b3IgXCIke3R5cGV9XCIsIGV4cGVjdGVkIGZ1bmN0aW9uYCk7XG4gICAgICAgIGNvbnN0IHZhbCA9IG9iamVjdFtmaWVsZE5hbWVdO1xuICAgICAgICBpZiAoaXNPcHRpb25hbCAmJiB2YWwgPT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgaWYgKCFjaGVja1ZhbCh2YWwsIG9iamVjdCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBwYXJhbSAke1N0cmluZyhmaWVsZE5hbWUpfT0ke3ZhbH0gKCR7dHlwZW9mIHZhbH0pLCBleHBlY3RlZCAke3R5cGV9YCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGZvciAoY29uc3QgW2ZpZWxkTmFtZSwgdHlwZV0gb2YgT2JqZWN0LmVudHJpZXModmFsaWRhdG9ycykpXG4gICAgICAgIGNoZWNrRmllbGQoZmllbGROYW1lLCB0eXBlLCBmYWxzZSk7XG4gICAgZm9yIChjb25zdCBbZmllbGROYW1lLCB0eXBlXSBvZiBPYmplY3QuZW50cmllcyhvcHRWYWxpZGF0b3JzKSlcbiAgICAgICAgY2hlY2tGaWVsZChmaWVsZE5hbWUsIHR5cGUsIHRydWUpO1xuICAgIHJldHVybiBvYmplY3Q7XG59XG4vLyB2YWxpZGF0ZSB0eXBlIHRlc3RzXG4vLyBjb25zdCBvOiB7IGE6IG51bWJlcjsgYjogbnVtYmVyOyBjOiBudW1iZXIgfSA9IHsgYTogMSwgYjogNSwgYzogNiB9O1xuLy8gY29uc3QgejAgPSB2YWxpZGF0ZU9iamVjdChvLCB7IGE6ICdpc1NhZmVJbnRlZ2VyJyB9LCB7IGM6ICdiaWdpbnQnIH0pOyAvLyBPayFcbi8vIC8vIFNob3VsZCBmYWlsIHR5cGUtY2hlY2tcbi8vIGNvbnN0IHoxID0gdmFsaWRhdGVPYmplY3QobywgeyBhOiAndG1wJyB9LCB7IGM6ICd6eicgfSk7XG4vLyBjb25zdCB6MiA9IHZhbGlkYXRlT2JqZWN0KG8sIHsgYTogJ2lzU2FmZUludGVnZXInIH0sIHsgYzogJ3p6JyB9KTtcbi8vIGNvbnN0IHozID0gdmFsaWRhdGVPYmplY3QobywgeyB0ZXN0OiAnYm9vbGVhbicsIHo6ICdidWcnIH0pO1xuLy8gY29uc3QgejQgPSB2YWxpZGF0ZU9iamVjdChvLCB7IGE6ICdib29sZWFuJywgejogJ2J1ZycgfSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD11dGlscy5qcy5tYXAiLCIvKiEgbm9ibGUtY3VydmVzIC0gTUlUIExpY2Vuc2UgKGMpIDIwMjIgUGF1bCBNaWxsZXIgKHBhdWxtaWxsci5jb20pICovXG4vLyBVdGlsaXRpZXMgZm9yIG1vZHVsYXIgYXJpdGhtZXRpY3MgYW5kIGZpbml0ZSBmaWVsZHNcbmltcG9ydCB7IGJpdE1hc2ssIG51bWJlclRvQnl0ZXNCRSwgbnVtYmVyVG9CeXRlc0xFLCBieXRlc1RvTnVtYmVyQkUsIGJ5dGVzVG9OdW1iZXJMRSwgZW5zdXJlQnl0ZXMsIHZhbGlkYXRlT2JqZWN0LCB9IGZyb20gJy4vdXRpbHMuanMnO1xuLy8gcHJldHRpZXItaWdub3JlXG5jb25zdCBfMG4gPSBCaWdJbnQoMCksIF8xbiA9IEJpZ0ludCgxKSwgXzJuID0gQmlnSW50KDIpLCBfM24gPSBCaWdJbnQoMyk7XG4vLyBwcmV0dGllci1pZ25vcmVcbmNvbnN0IF80biA9IEJpZ0ludCg0KSwgXzVuID0gQmlnSW50KDUpLCBfOG4gPSBCaWdJbnQoOCk7XG4vLyBwcmV0dGllci1pZ25vcmVcbmNvbnN0IF85biA9IEJpZ0ludCg5KSwgXzE2biA9IEJpZ0ludCgxNik7XG4vLyBDYWxjdWxhdGVzIGEgbW9kdWxvIGJcbmV4cG9ydCBmdW5jdGlvbiBtb2QoYSwgYikge1xuICAgIGNvbnN0IHJlc3VsdCA9IGEgJSBiO1xuICAgIHJldHVybiByZXN1bHQgPj0gXzBuID8gcmVzdWx0IDogYiArIHJlc3VsdDtcbn1cbi8qKlxuICogRWZmaWNpZW50bHkgZXhwb25lbnRpYXRlIG51bSB0byBwb3dlciBhbmQgZG8gbW9kdWxhciBkaXZpc2lvbi5cbiAqIFVuc2FmZSBpbiBzb21lIGNvbnRleHRzOiB1c2VzIGxhZGRlciwgc28gY2FuIGV4cG9zZSBiaWdpbnQgYml0cy5cbiAqIEBleGFtcGxlXG4gKiBwb3dNb2QoMm4sIDZuLCAxMW4pIC8vIDY0biAlIDExbiA9PSA5blxuICovXG4vLyBUT0RPOiB1c2UgZmllbGQgdmVyc2lvbiAmJiByZW1vdmVcbmV4cG9ydCBmdW5jdGlvbiBwb3cobnVtLCBwb3dlciwgbW9kdWxvKSB7XG4gICAgaWYgKG1vZHVsbyA8PSBfMG4gfHwgcG93ZXIgPCBfMG4pXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0ZWQgcG93ZXIvbW9kdWxvID4gMCcpO1xuICAgIGlmIChtb2R1bG8gPT09IF8xbilcbiAgICAgICAgcmV0dXJuIF8wbjtcbiAgICBsZXQgcmVzID0gXzFuO1xuICAgIHdoaWxlIChwb3dlciA+IF8wbikge1xuICAgICAgICBpZiAocG93ZXIgJiBfMW4pXG4gICAgICAgICAgICByZXMgPSAocmVzICogbnVtKSAlIG1vZHVsbztcbiAgICAgICAgbnVtID0gKG51bSAqIG51bSkgJSBtb2R1bG87XG4gICAgICAgIHBvd2VyID4+PSBfMW47XG4gICAgfVxuICAgIHJldHVybiByZXM7XG59XG4vLyBEb2VzIHggXiAoMiBeIHBvd2VyKSBtb2QgcC4gcG93MigzMCwgNCkgPT0gMzAgXiAoMiBeIDQpXG5leHBvcnQgZnVuY3Rpb24gcG93Mih4LCBwb3dlciwgbW9kdWxvKSB7XG4gICAgbGV0IHJlcyA9IHg7XG4gICAgd2hpbGUgKHBvd2VyLS0gPiBfMG4pIHtcbiAgICAgICAgcmVzICo9IHJlcztcbiAgICAgICAgcmVzICU9IG1vZHVsbztcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cbi8vIEludmVyc2VzIG51bWJlciBvdmVyIG1vZHVsb1xuZXhwb3J0IGZ1bmN0aW9uIGludmVydChudW1iZXIsIG1vZHVsbykge1xuICAgIGlmIChudW1iZXIgPT09IF8wbiB8fCBtb2R1bG8gPD0gXzBuKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgaW52ZXJ0OiBleHBlY3RlZCBwb3NpdGl2ZSBpbnRlZ2VycywgZ290IG49JHtudW1iZXJ9IG1vZD0ke21vZHVsb31gKTtcbiAgICB9XG4gICAgLy8gRXVjbGVkaWFuIEdDRCBodHRwczovL2JyaWxsaWFudC5vcmcvd2lraS9leHRlbmRlZC1ldWNsaWRlYW4tYWxnb3JpdGhtL1xuICAgIC8vIEZlcm1hdCdzIGxpdHRsZSB0aGVvcmVtIFwiQ1QtbGlrZVwiIHZlcnNpb24gaW52KG4pID0gbl4obS0yKSBtb2QgbSBpcyAzMHggc2xvd2VyLlxuICAgIGxldCBhID0gbW9kKG51bWJlciwgbW9kdWxvKTtcbiAgICBsZXQgYiA9IG1vZHVsbztcbiAgICAvLyBwcmV0dGllci1pZ25vcmVcbiAgICBsZXQgeCA9IF8wbiwgeSA9IF8xbiwgdSA9IF8xbiwgdiA9IF8wbjtcbiAgICB3aGlsZSAoYSAhPT0gXzBuKSB7XG4gICAgICAgIC8vIEpJVCBhcHBsaWVzIG9wdGltaXphdGlvbiBpZiB0aG9zZSB0d28gbGluZXMgZm9sbG93IGVhY2ggb3RoZXJcbiAgICAgICAgY29uc3QgcSA9IGIgLyBhO1xuICAgICAgICBjb25zdCByID0gYiAlIGE7XG4gICAgICAgIGNvbnN0IG0gPSB4IC0gdSAqIHE7XG4gICAgICAgIGNvbnN0IG4gPSB5IC0gdiAqIHE7XG4gICAgICAgIC8vIHByZXR0aWVyLWlnbm9yZVxuICAgICAgICBiID0gYSwgYSA9IHIsIHggPSB1LCB5ID0gdiwgdSA9IG0sIHYgPSBuO1xuICAgIH1cbiAgICBjb25zdCBnY2QgPSBiO1xuICAgIGlmIChnY2QgIT09IF8xbilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZlcnQ6IGRvZXMgbm90IGV4aXN0Jyk7XG4gICAgcmV0dXJuIG1vZCh4LCBtb2R1bG8pO1xufVxuLy8gVG9uZWxsaS1TaGFua3MgYWxnb3JpdGhtXG4vLyBQYXBlciAxOiBodHRwczovL2VwcmludC5pYWNyLm9yZy8yMDEyLzY4NS5wZGYgKHBhZ2UgMTIpXG4vLyBQYXBlciAyOiBTcXVhcmUgUm9vdHMgZnJvbSAxOyAyNCwgNTEsIDEwIHRvIERhbiBTaGFua3NcbmV4cG9ydCBmdW5jdGlvbiB0b25lbGxpU2hhbmtzKFApIHtcbiAgICAvLyBMZWdlbmRyZSBjb25zdGFudDogdXNlZCB0byBjYWxjdWxhdGUgTGVnZW5kcmUgc3ltYm9sIChhIHwgcCksXG4gICAgLy8gd2hpY2ggZGVub3RlcyB0aGUgdmFsdWUgb2YgYV4oKHAtMSkvMikgKG1vZCBwKS5cbiAgICAvLyAoYSB8IHApIOKJoSAxICAgIGlmIGEgaXMgYSBzcXVhcmUgKG1vZCBwKVxuICAgIC8vIChhIHwgcCkg4omhIC0xICAgaWYgYSBpcyBub3QgYSBzcXVhcmUgKG1vZCBwKVxuICAgIC8vIChhIHwgcCkg4omhIDAgICAgaWYgYSDiiaEgMCAobW9kIHApXG4gICAgY29uc3QgbGVnZW5kcmVDID0gKFAgLSBfMW4pIC8gXzJuO1xuICAgIGxldCBRLCBTLCBaO1xuICAgIC8vIFN0ZXAgMTogQnkgZmFjdG9yaW5nIG91dCBwb3dlcnMgb2YgMiBmcm9tIHAgLSAxLFxuICAgIC8vIGZpbmQgcSBhbmQgcyBzdWNoIHRoYXQgcCAtIDEgPSBxKigyXnMpIHdpdGggcSBvZGRcbiAgICBmb3IgKFEgPSBQIC0gXzFuLCBTID0gMDsgUSAlIF8ybiA9PT0gXzBuOyBRIC89IF8ybiwgUysrKVxuICAgICAgICA7XG4gICAgLy8gU3RlcCAyOiBTZWxlY3QgYSBub24tc3F1YXJlIHogc3VjaCB0aGF0ICh6IHwgcCkg4omhIC0xIGFuZCBzZXQgYyDiiaEgenFcbiAgICBmb3IgKFogPSBfMm47IFogPCBQICYmIHBvdyhaLCBsZWdlbmRyZUMsIFApICE9PSBQIC0gXzFuOyBaKyspXG4gICAgICAgIDtcbiAgICAvLyBGYXN0LXBhdGhcbiAgICBpZiAoUyA9PT0gMSkge1xuICAgICAgICBjb25zdCBwMWRpdjQgPSAoUCArIF8xbikgLyBfNG47XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiB0b25lbGxpRmFzdChGcCwgbikge1xuICAgICAgICAgICAgY29uc3Qgcm9vdCA9IEZwLnBvdyhuLCBwMWRpdjQpO1xuICAgICAgICAgICAgaWYgKCFGcC5lcWwoRnAuc3FyKHJvb3QpLCBuKSlcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBmaW5kIHNxdWFyZSByb290Jyk7XG4gICAgICAgICAgICByZXR1cm4gcm9vdDtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLy8gU2xvdy1wYXRoXG4gICAgY29uc3QgUTFkaXYyID0gKFEgKyBfMW4pIC8gXzJuO1xuICAgIHJldHVybiBmdW5jdGlvbiB0b25lbGxpU2xvdyhGcCwgbikge1xuICAgICAgICAvLyBTdGVwIDA6IENoZWNrIHRoYXQgbiBpcyBpbmRlZWQgYSBzcXVhcmU6IChuIHwgcCkgc2hvdWxkIG5vdCBiZSDiiaEgLTFcbiAgICAgICAgaWYgKEZwLnBvdyhuLCBsZWdlbmRyZUMpID09PSBGcC5uZWcoRnAuT05FKSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGZpbmQgc3F1YXJlIHJvb3QnKTtcbiAgICAgICAgbGV0IHIgPSBTO1xuICAgICAgICAvLyBUT0RPOiB3aWxsIGZhaWwgYXQgRnAyL2V0Y1xuICAgICAgICBsZXQgZyA9IEZwLnBvdyhGcC5tdWwoRnAuT05FLCBaKSwgUSk7IC8vIHdpbGwgdXBkYXRlIGJvdGggeCBhbmQgYlxuICAgICAgICBsZXQgeCA9IEZwLnBvdyhuLCBRMWRpdjIpOyAvLyBmaXJzdCBndWVzcyBhdCB0aGUgc3F1YXJlIHJvb3RcbiAgICAgICAgbGV0IGIgPSBGcC5wb3cobiwgUSk7IC8vIGZpcnN0IGd1ZXNzIGF0IHRoZSBmdWRnZSBmYWN0b3JcbiAgICAgICAgd2hpbGUgKCFGcC5lcWwoYiwgRnAuT05FKSkge1xuICAgICAgICAgICAgaWYgKEZwLmVxbChiLCBGcC5aRVJPKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gRnAuWkVSTzsgLy8gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvVG9uZWxsaSVFMiU4MCU5M1NoYW5rc19hbGdvcml0aG0gKDQuIElmIHQgPSAwLCByZXR1cm4gciA9IDApXG4gICAgICAgICAgICAvLyBGaW5kIG0gc3VjaCBiXigyXm0pPT0xXG4gICAgICAgICAgICBsZXQgbSA9IDE7XG4gICAgICAgICAgICBmb3IgKGxldCB0MiA9IEZwLnNxcihiKTsgbSA8IHI7IG0rKykge1xuICAgICAgICAgICAgICAgIGlmIChGcC5lcWwodDIsIEZwLk9ORSkpXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIHQyID0gRnAuc3FyKHQyKTsgLy8gdDIgKj0gdDJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE5PVEU6IHItbS0xIGNhbiBiZSBiaWdnZXIgdGhhbiAzMiwgbmVlZCB0byBjb252ZXJ0IHRvIGJpZ2ludCBiZWZvcmUgc2hpZnQsIG90aGVyd2lzZSB0aGVyZSB3aWxsIGJlIG92ZXJmbG93XG4gICAgICAgICAgICBjb25zdCBnZSA9IEZwLnBvdyhnLCBfMW4gPDwgQmlnSW50KHIgLSBtIC0gMSkpOyAvLyBnZSA9IDJeKHItbS0xKVxuICAgICAgICAgICAgZyA9IEZwLnNxcihnZSk7IC8vIGcgPSBnZSAqIGdlXG4gICAgICAgICAgICB4ID0gRnAubXVsKHgsIGdlKTsgLy8geCAqPSBnZVxuICAgICAgICAgICAgYiA9IEZwLm11bChiLCBnKTsgLy8gYiAqPSBnXG4gICAgICAgICAgICByID0gbTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geDtcbiAgICB9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIEZwU3FydChQKSB7XG4gICAgLy8gTk9URTogZGlmZmVyZW50IGFsZ29yaXRobXMgY2FuIGdpdmUgZGlmZmVyZW50IHJvb3RzLCBpdCBpcyB1cCB0byB1c2VyIHRvIGRlY2lkZSB3aGljaCBvbmUgdGhleSB3YW50LlxuICAgIC8vIEZvciBleGFtcGxlIHRoZXJlIGlzIEZwU3FydE9kZC9GcFNxcnRFdmVuIHRvIGNob2ljZSByb290IGJhc2VkIG9uIG9kZG5lc3MgKHVzZWQgZm9yIGhhc2gtdG8tY3VydmUpLlxuICAgIC8vIFAg4omhIDMgKG1vZCA0KVxuICAgIC8vIOKImm4gPSBuXigoUCsxKS80KVxuICAgIGlmIChQICUgXzRuID09PSBfM24pIHtcbiAgICAgICAgLy8gTm90IGFsbCByb290cyBwb3NzaWJsZSFcbiAgICAgICAgLy8gY29uc3QgT1JERVIgPVxuICAgICAgICAvLyAgIDB4MWEwMTExZWEzOTdmZTY5YTRiMWJhN2I2NDM0YmFjZDc2NDc3NGI4NGYzODUxMmJmNjczMGQyYTBmNmIwZjYyNDFlYWJmZmZlYjE1M2ZmZmZiOWZlZmZmZmZmZmZhYWFibjtcbiAgICAgICAgLy8gY29uc3QgTlVNID0gNzIwNTc1OTQwMzc5Mjc4MTZuO1xuICAgICAgICBjb25zdCBwMWRpdjQgPSAoUCArIF8xbikgLyBfNG47XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBzcXJ0M21vZDQoRnAsIG4pIHtcbiAgICAgICAgICAgIGNvbnN0IHJvb3QgPSBGcC5wb3cobiwgcDFkaXY0KTtcbiAgICAgICAgICAgIC8vIFRocm93IGlmIHJvb3QqKjIgIT0gblxuICAgICAgICAgICAgaWYgKCFGcC5lcWwoRnAuc3FyKHJvb3QpLCBuKSlcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBmaW5kIHNxdWFyZSByb290Jyk7XG4gICAgICAgICAgICByZXR1cm4gcm9vdDtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLy8gQXRraW4gYWxnb3JpdGhtIGZvciBxIOKJoSA1IChtb2QgOCksIGh0dHBzOi8vZXByaW50LmlhY3Iub3JnLzIwMTIvNjg1LnBkZiAocGFnZSAxMClcbiAgICBpZiAoUCAlIF84biA9PT0gXzVuKSB7XG4gICAgICAgIGNvbnN0IGMxID0gKFAgLSBfNW4pIC8gXzhuO1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gc3FydDVtb2Q4KEZwLCBuKSB7XG4gICAgICAgICAgICBjb25zdCBuMiA9IEZwLm11bChuLCBfMm4pO1xuICAgICAgICAgICAgY29uc3QgdiA9IEZwLnBvdyhuMiwgYzEpO1xuICAgICAgICAgICAgY29uc3QgbnYgPSBGcC5tdWwobiwgdik7XG4gICAgICAgICAgICBjb25zdCBpID0gRnAubXVsKEZwLm11bChudiwgXzJuKSwgdik7XG4gICAgICAgICAgICBjb25zdCByb290ID0gRnAubXVsKG52LCBGcC5zdWIoaSwgRnAuT05FKSk7XG4gICAgICAgICAgICBpZiAoIUZwLmVxbChGcC5zcXIocm9vdCksIG4pKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGZpbmQgc3F1YXJlIHJvb3QnKTtcbiAgICAgICAgICAgIHJldHVybiByb290O1xuICAgICAgICB9O1xuICAgIH1cbiAgICAvLyBQIOKJoSA5IChtb2QgMTYpXG4gICAgaWYgKFAgJSBfMTZuID09PSBfOW4pIHtcbiAgICAgICAgLy8gTk9URTogdG9uZWxsaSBpcyB0b28gc2xvdyBmb3IgYmxzLUZwMiBjYWxjdWxhdGlvbnMgZXZlbiBvbiBzdGFydFxuICAgICAgICAvLyBNZWFucyB3ZSBjYW5ub3QgdXNlIHNxcnQgZm9yIGNvbnN0YW50cyBhdCBhbGwhXG4gICAgICAgIC8vXG4gICAgICAgIC8vIGNvbnN0IGMxID0gRnAuc3FydChGcC5uZWdhdGUoRnAuT05FKSk7IC8vICAxLiBjMSA9IHNxcnQoLTEpIGluIEYsIGkuZS4sIChjMV4yKSA9PSAtMSBpbiBGXG4gICAgICAgIC8vIGNvbnN0IGMyID0gRnAuc3FydChjMSk7ICAgICAgICAgICAgICAgIC8vICAyLiBjMiA9IHNxcnQoYzEpIGluIEYsIGkuZS4sIChjMl4yKSA9PSBjMSBpbiBGXG4gICAgICAgIC8vIGNvbnN0IGMzID0gRnAuc3FydChGcC5uZWdhdGUoYzEpKTsgICAgIC8vICAzLiBjMyA9IHNxcnQoLWMxKSBpbiBGLCBpLmUuLCAoYzNeMikgPT0gLWMxIGluIEZcbiAgICAgICAgLy8gY29uc3QgYzQgPSAoUCArIF83bikgLyBfMTZuOyAgICAgICAgICAgLy8gIDQuIGM0ID0gKHEgKyA3KSAvIDE2ICAgICAgICAjIEludGVnZXIgYXJpdGhtZXRpY1xuICAgICAgICAvLyBzcXJ0ID0gKHgpID0+IHtcbiAgICAgICAgLy8gICBsZXQgdHYxID0gRnAucG93KHgsIGM0KTsgICAgICAgICAgICAgLy8gIDEuIHR2MSA9IHheYzRcbiAgICAgICAgLy8gICBsZXQgdHYyID0gRnAubXVsKGMxLCB0djEpOyAgICAgICAgICAgLy8gIDIuIHR2MiA9IGMxICogdHYxXG4gICAgICAgIC8vICAgY29uc3QgdHYzID0gRnAubXVsKGMyLCB0djEpOyAgICAgICAgIC8vICAzLiB0djMgPSBjMiAqIHR2MVxuICAgICAgICAvLyAgIGxldCB0djQgPSBGcC5tdWwoYzMsIHR2MSk7ICAgICAgICAgICAvLyAgNC4gdHY0ID0gYzMgKiB0djFcbiAgICAgICAgLy8gICBjb25zdCBlMSA9IEZwLmVxdWFscyhGcC5zcXVhcmUodHYyKSwgeCk7IC8vICA1LiAgZTEgPSAodHYyXjIpID09IHhcbiAgICAgICAgLy8gICBjb25zdCBlMiA9IEZwLmVxdWFscyhGcC5zcXVhcmUodHYzKSwgeCk7IC8vICA2LiAgZTIgPSAodHYzXjIpID09IHhcbiAgICAgICAgLy8gICB0djEgPSBGcC5jbW92KHR2MSwgdHYyLCBlMSk7IC8vICA3LiB0djEgPSBDTU9WKHR2MSwgdHYyLCBlMSkgICMgU2VsZWN0IHR2MiBpZiAodHYyXjIpID09IHhcbiAgICAgICAgLy8gICB0djIgPSBGcC5jbW92KHR2NCwgdHYzLCBlMik7IC8vICA4LiB0djIgPSBDTU9WKHR2NCwgdHYzLCBlMikgICMgU2VsZWN0IHR2MyBpZiAodHYzXjIpID09IHhcbiAgICAgICAgLy8gICBjb25zdCBlMyA9IEZwLmVxdWFscyhGcC5zcXVhcmUodHYyKSwgeCk7IC8vICA5LiAgZTMgPSAodHYyXjIpID09IHhcbiAgICAgICAgLy8gICByZXR1cm4gRnAuY21vdih0djEsIHR2MiwgZTMpOyAvLyAgMTAuICB6ID0gQ01PVih0djEsIHR2MiwgZTMpICAjIFNlbGVjdCB0aGUgc3FydCBmcm9tIHR2MSBhbmQgdHYyXG4gICAgICAgIC8vIH1cbiAgICB9XG4gICAgLy8gT3RoZXIgY2FzZXM6IFRvbmVsbGktU2hhbmtzIGFsZ29yaXRobVxuICAgIHJldHVybiB0b25lbGxpU2hhbmtzKFApO1xufVxuLy8gTGl0dGxlLWVuZGlhbiBjaGVjayBmb3IgZmlyc3QgTEUgYml0IChsYXN0IEJFIGJpdCk7XG5leHBvcnQgY29uc3QgaXNOZWdhdGl2ZUxFID0gKG51bSwgbW9kdWxvKSA9PiAobW9kKG51bSwgbW9kdWxvKSAmIF8xbikgPT09IF8xbjtcbi8vIHByZXR0aWVyLWlnbm9yZVxuY29uc3QgRklFTERfRklFTERTID0gW1xuICAgICdjcmVhdGUnLCAnaXNWYWxpZCcsICdpczAnLCAnbmVnJywgJ2ludicsICdzcXJ0JywgJ3NxcicsXG4gICAgJ2VxbCcsICdhZGQnLCAnc3ViJywgJ211bCcsICdwb3cnLCAnZGl2JyxcbiAgICAnYWRkTicsICdzdWJOJywgJ211bE4nLCAnc3FyTidcbl07XG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVGaWVsZChmaWVsZCkge1xuICAgIGNvbnN0IGluaXRpYWwgPSB7XG4gICAgICAgIE9SREVSOiAnYmlnaW50JyxcbiAgICAgICAgTUFTSzogJ2JpZ2ludCcsXG4gICAgICAgIEJZVEVTOiAnaXNTYWZlSW50ZWdlcicsXG4gICAgICAgIEJJVFM6ICdpc1NhZmVJbnRlZ2VyJyxcbiAgICB9O1xuICAgIGNvbnN0IG9wdHMgPSBGSUVMRF9GSUVMRFMucmVkdWNlKChtYXAsIHZhbCkgPT4ge1xuICAgICAgICBtYXBbdmFsXSA9ICdmdW5jdGlvbic7XG4gICAgICAgIHJldHVybiBtYXA7XG4gICAgfSwgaW5pdGlhbCk7XG4gICAgcmV0dXJuIHZhbGlkYXRlT2JqZWN0KGZpZWxkLCBvcHRzKTtcbn1cbi8vIEdlbmVyaWMgZmllbGQgZnVuY3Rpb25zXG5leHBvcnQgZnVuY3Rpb24gRnBQb3coZiwgbnVtLCBwb3dlcikge1xuICAgIC8vIFNob3VsZCBoYXZlIHNhbWUgc3BlZWQgYXMgcG93IGZvciBiaWdpbnRzXG4gICAgLy8gVE9ETzogYmVuY2htYXJrIVxuICAgIGlmIChwb3dlciA8IF8wbilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3RlZCBwb3dlciA+IDAnKTtcbiAgICBpZiAocG93ZXIgPT09IF8wbilcbiAgICAgICAgcmV0dXJuIGYuT05FO1xuICAgIGlmIChwb3dlciA9PT0gXzFuKVxuICAgICAgICByZXR1cm4gbnVtO1xuICAgIGxldCBwID0gZi5PTkU7XG4gICAgbGV0IGQgPSBudW07XG4gICAgd2hpbGUgKHBvd2VyID4gXzBuKSB7XG4gICAgICAgIGlmIChwb3dlciAmIF8xbilcbiAgICAgICAgICAgIHAgPSBmLm11bChwLCBkKTtcbiAgICAgICAgZCA9IGYuc3FyKGQpO1xuICAgICAgICBwb3dlciA+Pj0gXzFuO1xuICAgIH1cbiAgICByZXR1cm4gcDtcbn1cbi8vIDAgaXMgbm9uLWludmVydGlibGU6IG5vbi1iYXRjaGVkIHZlcnNpb24gd2lsbCB0aHJvdyBvbiAwXG5leHBvcnQgZnVuY3Rpb24gRnBJbnZlcnRCYXRjaChmLCBudW1zKSB7XG4gICAgY29uc3QgdG1wID0gbmV3IEFycmF5KG51bXMubGVuZ3RoKTtcbiAgICAvLyBXYWxrIGZyb20gZmlyc3QgdG8gbGFzdCwgbXVsdGlwbHkgdGhlbSBieSBlYWNoIG90aGVyIE1PRCBwXG4gICAgY29uc3QgbGFzdE11bHRpcGxpZWQgPSBudW1zLnJlZHVjZSgoYWNjLCBudW0sIGkpID0+IHtcbiAgICAgICAgaWYgKGYuaXMwKG51bSkpXG4gICAgICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgICB0bXBbaV0gPSBhY2M7XG4gICAgICAgIHJldHVybiBmLm11bChhY2MsIG51bSk7XG4gICAgfSwgZi5PTkUpO1xuICAgIC8vIEludmVydCBsYXN0IGVsZW1lbnRcbiAgICBjb25zdCBpbnZlcnRlZCA9IGYuaW52KGxhc3RNdWx0aXBsaWVkKTtcbiAgICAvLyBXYWxrIGZyb20gbGFzdCB0byBmaXJzdCwgbXVsdGlwbHkgdGhlbSBieSBpbnZlcnRlZCBlYWNoIG90aGVyIE1PRCBwXG4gICAgbnVtcy5yZWR1Y2VSaWdodCgoYWNjLCBudW0sIGkpID0+IHtcbiAgICAgICAgaWYgKGYuaXMwKG51bSkpXG4gICAgICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgICB0bXBbaV0gPSBmLm11bChhY2MsIHRtcFtpXSk7XG4gICAgICAgIHJldHVybiBmLm11bChhY2MsIG51bSk7XG4gICAgfSwgaW52ZXJ0ZWQpO1xuICAgIHJldHVybiB0bXA7XG59XG5leHBvcnQgZnVuY3Rpb24gRnBEaXYoZiwgbGhzLCByaHMpIHtcbiAgICByZXR1cm4gZi5tdWwobGhzLCB0eXBlb2YgcmhzID09PSAnYmlnaW50JyA/IGludmVydChyaHMsIGYuT1JERVIpIDogZi5pbnYocmhzKSk7XG59XG4vLyBUaGlzIGZ1bmN0aW9uIHJldHVybnMgVHJ1ZSB3aGVuZXZlciB0aGUgdmFsdWUgeCBpcyBhIHNxdWFyZSBpbiB0aGUgZmllbGQgRi5cbmV4cG9ydCBmdW5jdGlvbiBGcElzU3F1YXJlKGYpIHtcbiAgICBjb25zdCBsZWdlbmRyZUNvbnN0ID0gKGYuT1JERVIgLSBfMW4pIC8gXzJuOyAvLyBJbnRlZ2VyIGFyaXRobWV0aWNcbiAgICByZXR1cm4gKHgpID0+IHtcbiAgICAgICAgY29uc3QgcCA9IGYucG93KHgsIGxlZ2VuZHJlQ29uc3QpO1xuICAgICAgICByZXR1cm4gZi5lcWwocCwgZi5aRVJPKSB8fCBmLmVxbChwLCBmLk9ORSk7XG4gICAgfTtcbn1cbi8vIENVUlZFLm4gbGVuZ3Roc1xuZXhwb3J0IGZ1bmN0aW9uIG5MZW5ndGgobiwgbkJpdExlbmd0aCkge1xuICAgIC8vIEJpdCBzaXplLCBieXRlIHNpemUgb2YgQ1VSVkUublxuICAgIGNvbnN0IF9uQml0TGVuZ3RoID0gbkJpdExlbmd0aCAhPT0gdW5kZWZpbmVkID8gbkJpdExlbmd0aCA6IG4udG9TdHJpbmcoMikubGVuZ3RoO1xuICAgIGNvbnN0IG5CeXRlTGVuZ3RoID0gTWF0aC5jZWlsKF9uQml0TGVuZ3RoIC8gOCk7XG4gICAgcmV0dXJuIHsgbkJpdExlbmd0aDogX25CaXRMZW5ndGgsIG5CeXRlTGVuZ3RoIH07XG59XG4vKipcbiAqIEluaXRpYWxpemVzIGEgZ2Fsb2lzIGZpZWxkIG92ZXIgcHJpbWUuIE5vbi1wcmltZXMgYXJlIG5vdCBzdXBwb3J0ZWQgZm9yIG5vdy5cbiAqIERvIG5vdCBpbml0IGluIGxvb3A6IHNsb3cuIFZlcnkgZnJhZ2lsZTogYWx3YXlzIHJ1biBhIGJlbmNobWFyayBvbiBjaGFuZ2UuXG4gKiBNYWpvciBwZXJmb3JtYW5jZSBnYWluczpcbiAqIGEpIG5vbi1ub3JtYWxpemVkIG9wZXJhdGlvbnMgbGlrZSBtdWxOIGluc3RlYWQgb2YgbXVsXG4gKiBiKSBgT2JqZWN0LmZyZWV6ZWBcbiAqIGMpIFNhbWUgb2JqZWN0IHNoYXBlOiBuZXZlciBhZGQgb3IgcmVtb3ZlIGtleXNcbiAqIEBwYXJhbSBPUkRFUiBwcmltZSBwb3NpdGl2ZSBiaWdpbnRcbiAqIEBwYXJhbSBiaXRMZW4gaG93IG1hbnkgYml0cyB0aGUgZmllbGQgY29uc3VtZXNcbiAqIEBwYXJhbSBpc0xFIChkZWY6IGZhbHNlKSBpZiBlbmNvZGluZyAvIGRlY29kaW5nIHNob3VsZCBiZSBpbiBsaXR0bGUtZW5kaWFuXG4gKiBAcGFyYW0gcmVkZWYgb3B0aW9uYWwgZmFzdGVyIHJlZGVmaW5pdGlvbnMgb2Ygc3FydCBhbmQgb3RoZXIgbWV0aG9kc1xuICovXG5leHBvcnQgZnVuY3Rpb24gRmllbGQoT1JERVIsIGJpdExlbiwgaXNMRSA9IGZhbHNlLCByZWRlZiA9IHt9KSB7XG4gICAgaWYgKE9SREVSIDw9IF8wbilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBGcCBPUkRFUiA+IDAsIGdvdCAke09SREVSfWApO1xuICAgIGNvbnN0IHsgbkJpdExlbmd0aDogQklUUywgbkJ5dGVMZW5ndGg6IEJZVEVTIH0gPSBuTGVuZ3RoKE9SREVSLCBiaXRMZW4pO1xuICAgIGlmIChCWVRFUyA+IDIwNDgpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRmllbGQgbGVuZ3RocyBvdmVyIDIwNDggYnl0ZXMgYXJlIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICBjb25zdCBzcXJ0UCA9IEZwU3FydChPUkRFUik7XG4gICAgY29uc3QgZiA9IE9iamVjdC5mcmVlemUoe1xuICAgICAgICBPUkRFUixcbiAgICAgICAgQklUUyxcbiAgICAgICAgQllURVMsXG4gICAgICAgIE1BU0s6IGJpdE1hc2soQklUUyksXG4gICAgICAgIFpFUk86IF8wbixcbiAgICAgICAgT05FOiBfMW4sXG4gICAgICAgIGNyZWF0ZTogKG51bSkgPT4gbW9kKG51bSwgT1JERVIpLFxuICAgICAgICBpc1ZhbGlkOiAobnVtKSA9PiB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG51bSAhPT0gJ2JpZ2ludCcpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGZpZWxkIGVsZW1lbnQ6IGV4cGVjdGVkIGJpZ2ludCwgZ290ICR7dHlwZW9mIG51bX1gKTtcbiAgICAgICAgICAgIHJldHVybiBfMG4gPD0gbnVtICYmIG51bSA8IE9SREVSOyAvLyAwIGlzIHZhbGlkIGVsZW1lbnQsIGJ1dCBpdCdzIG5vdCBpbnZlcnRpYmxlXG4gICAgICAgIH0sXG4gICAgICAgIGlzMDogKG51bSkgPT4gbnVtID09PSBfMG4sXG4gICAgICAgIGlzT2RkOiAobnVtKSA9PiAobnVtICYgXzFuKSA9PT0gXzFuLFxuICAgICAgICBuZWc6IChudW0pID0+IG1vZCgtbnVtLCBPUkRFUiksXG4gICAgICAgIGVxbDogKGxocywgcmhzKSA9PiBsaHMgPT09IHJocyxcbiAgICAgICAgc3FyOiAobnVtKSA9PiBtb2QobnVtICogbnVtLCBPUkRFUiksXG4gICAgICAgIGFkZDogKGxocywgcmhzKSA9PiBtb2QobGhzICsgcmhzLCBPUkRFUiksXG4gICAgICAgIHN1YjogKGxocywgcmhzKSA9PiBtb2QobGhzIC0gcmhzLCBPUkRFUiksXG4gICAgICAgIG11bDogKGxocywgcmhzKSA9PiBtb2QobGhzICogcmhzLCBPUkRFUiksXG4gICAgICAgIHBvdzogKG51bSwgcG93ZXIpID0+IEZwUG93KGYsIG51bSwgcG93ZXIpLFxuICAgICAgICBkaXY6IChsaHMsIHJocykgPT4gbW9kKGxocyAqIGludmVydChyaHMsIE9SREVSKSwgT1JERVIpLFxuICAgICAgICAvLyBTYW1lIGFzIGFib3ZlLCBidXQgZG9lc24ndCBub3JtYWxpemVcbiAgICAgICAgc3FyTjogKG51bSkgPT4gbnVtICogbnVtLFxuICAgICAgICBhZGROOiAobGhzLCByaHMpID0+IGxocyArIHJocyxcbiAgICAgICAgc3ViTjogKGxocywgcmhzKSA9PiBsaHMgLSByaHMsXG4gICAgICAgIG11bE46IChsaHMsIHJocykgPT4gbGhzICogcmhzLFxuICAgICAgICBpbnY6IChudW0pID0+IGludmVydChudW0sIE9SREVSKSxcbiAgICAgICAgc3FydDogcmVkZWYuc3FydCB8fCAoKG4pID0+IHNxcnRQKGYsIG4pKSxcbiAgICAgICAgaW52ZXJ0QmF0Y2g6IChsc3QpID0+IEZwSW52ZXJ0QmF0Y2goZiwgbHN0KSxcbiAgICAgICAgLy8gVE9ETzogZG8gd2UgcmVhbGx5IG5lZWQgY29uc3RhbnQgY21vdj9cbiAgICAgICAgLy8gV2UgZG9uJ3QgaGF2ZSBjb25zdC10aW1lIGJpZ2ludHMgYW55d2F5LCBzbyBwcm9iYWJseSB3aWxsIGJlIG5vdCB2ZXJ5IHVzZWZ1bFxuICAgICAgICBjbW92OiAoYSwgYiwgYykgPT4gKGMgPyBiIDogYSksXG4gICAgICAgIHRvQnl0ZXM6IChudW0pID0+IChpc0xFID8gbnVtYmVyVG9CeXRlc0xFKG51bSwgQllURVMpIDogbnVtYmVyVG9CeXRlc0JFKG51bSwgQllURVMpKSxcbiAgICAgICAgZnJvbUJ5dGVzOiAoYnl0ZXMpID0+IHtcbiAgICAgICAgICAgIGlmIChieXRlcy5sZW5ndGggIT09IEJZVEVTKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRnAuZnJvbUJ5dGVzOiBleHBlY3RlZCAke0JZVEVTfSwgZ290ICR7Ynl0ZXMubGVuZ3RofWApO1xuICAgICAgICAgICAgcmV0dXJuIGlzTEUgPyBieXRlc1RvTnVtYmVyTEUoYnl0ZXMpIDogYnl0ZXNUb051bWJlckJFKGJ5dGVzKTtcbiAgICAgICAgfSxcbiAgICB9KTtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShmKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBGcFNxcnRPZGQoRnAsIGVsbSkge1xuICAgIGlmICghRnAuaXNPZGQpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRmllbGQgZG9lc24ndCBoYXZlIGlzT2RkYCk7XG4gICAgY29uc3Qgcm9vdCA9IEZwLnNxcnQoZWxtKTtcbiAgICByZXR1cm4gRnAuaXNPZGQocm9vdCkgPyByb290IDogRnAubmVnKHJvb3QpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIEZwU3FydEV2ZW4oRnAsIGVsbSkge1xuICAgIGlmICghRnAuaXNPZGQpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRmllbGQgZG9lc24ndCBoYXZlIGlzT2RkYCk7XG4gICAgY29uc3Qgcm9vdCA9IEZwLnNxcnQoZWxtKTtcbiAgICByZXR1cm4gRnAuaXNPZGQocm9vdCkgPyBGcC5uZWcocm9vdCkgOiByb290O1xufVxuLyoqXG4gKiBGSVBTIDE4NiBCLjQuMS1jb21wbGlhbnQgXCJjb25zdGFudC10aW1lXCIgcHJpdmF0ZSBrZXkgZ2VuZXJhdGlvbiB1dGlsaXR5LlxuICogQ2FuIHRha2UgKG4rOCkgb3IgbW9yZSBieXRlcyBvZiB1bmlmb3JtIGlucHV0IGUuZy4gZnJvbSBDU1BSTkcgb3IgS0RGXG4gKiBhbmQgY29udmVydCB0aGVtIGludG8gcHJpdmF0ZSBzY2FsYXIsIHdpdGggdGhlIG1vZHVsbyBiaWFzIGJlaW5nIG5lZ2xpYmxlLlxuICogTmVlZHMgYXQgbGVhc3QgNDAgYnl0ZXMgb2YgaW5wdXQgZm9yIDMyLWJ5dGUgcHJpdmF0ZSBrZXkuXG4gKiBodHRwczovL3Jlc2VhcmNoLmt1ZGVsc2tpc2VjdXJpdHkuY29tLzIwMjAvMDcvMjgvdGhlLWRlZmluaXRpdmUtZ3VpZGUtdG8tbW9kdWxvLWJpYXMtYW5kLWhvdy10by1hdm9pZC1pdC9cbiAqIEBwYXJhbSBoYXNoIGhhc2ggb3V0cHV0IGZyb20gU0hBMyBvciBhIHNpbWlsYXIgZnVuY3Rpb25cbiAqIEByZXR1cm5zIHZhbGlkIHByaXZhdGUgc2NhbGFyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNoVG9Qcml2YXRlU2NhbGFyKGhhc2gsIGdyb3VwT3JkZXIsIGlzTEUgPSBmYWxzZSkge1xuICAgIGhhc2ggPSBlbnN1cmVCeXRlcygncHJpdmF0ZUhhc2gnLCBoYXNoKTtcbiAgICBjb25zdCBoYXNoTGVuID0gaGFzaC5sZW5ndGg7XG4gICAgY29uc3QgbWluTGVuID0gbkxlbmd0aChncm91cE9yZGVyKS5uQnl0ZUxlbmd0aCArIDg7XG4gICAgaWYgKG1pbkxlbiA8IDI0IHx8IGhhc2hMZW4gPCBtaW5MZW4gfHwgaGFzaExlbiA+IDEwMjQpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgaGFzaFRvUHJpdmF0ZVNjYWxhcjogZXhwZWN0ZWQgJHttaW5MZW59LTEwMjQgYnl0ZXMgb2YgaW5wdXQsIGdvdCAke2hhc2hMZW59YCk7XG4gICAgY29uc3QgbnVtID0gaXNMRSA/IGJ5dGVzVG9OdW1iZXJMRShoYXNoKSA6IGJ5dGVzVG9OdW1iZXJCRShoYXNoKTtcbiAgICByZXR1cm4gbW9kKG51bSwgZ3JvdXBPcmRlciAtIF8xbikgKyBfMW47XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1tb2R1bGFyLmpzLm1hcCIsIi8qISBub2JsZS1jdXJ2ZXMgLSBNSVQgTGljZW5zZSAoYykgMjAyMiBQYXVsIE1pbGxlciAocGF1bG1pbGxyLmNvbSkgKi9cbi8vIEFiZWxpYW4gZ3JvdXAgdXRpbGl0aWVzXG5pbXBvcnQgeyB2YWxpZGF0ZUZpZWxkLCBuTGVuZ3RoIH0gZnJvbSAnLi9tb2R1bGFyLmpzJztcbmltcG9ydCB7IHZhbGlkYXRlT2JqZWN0IH0gZnJvbSAnLi91dGlscy5qcyc7XG5jb25zdCBfMG4gPSBCaWdJbnQoMCk7XG5jb25zdCBfMW4gPSBCaWdJbnQoMSk7XG4vLyBFbGxpcHRpYyBjdXJ2ZSBtdWx0aXBsaWNhdGlvbiBvZiBQb2ludCBieSBzY2FsYXIuIEZyYWdpbGUuXG4vLyBTY2FsYXJzIHNob3VsZCBhbHdheXMgYmUgbGVzcyB0aGFuIGN1cnZlIG9yZGVyOiB0aGlzIHNob3VsZCBiZSBjaGVja2VkIGluc2lkZSBvZiBhIGN1cnZlIGl0c2VsZi5cbi8vIENyZWF0ZXMgcHJlY29tcHV0YXRpb24gdGFibGVzIGZvciBmYXN0IG11bHRpcGxpY2F0aW9uOlxuLy8gLSBwcml2YXRlIHNjYWxhciBpcyBzcGxpdCBieSBmaXhlZCBzaXplIHdpbmRvd3Mgb2YgVyBiaXRzXG4vLyAtIGV2ZXJ5IHdpbmRvdyBwb2ludCBpcyBjb2xsZWN0ZWQgZnJvbSB3aW5kb3cncyB0YWJsZSAmIGFkZGVkIHRvIGFjY3VtdWxhdG9yXG4vLyAtIHNpbmNlIHdpbmRvd3MgYXJlIGRpZmZlcmVudCwgc2FtZSBwb2ludCBpbnNpZGUgdGFibGVzIHdvbid0IGJlIGFjY2Vzc2VkIG1vcmUgdGhhbiBvbmNlIHBlciBjYWxjXG4vLyAtIGVhY2ggbXVsdGlwbGljYXRpb24gaXMgJ01hdGguY2VpbChDVVJWRV9PUkRFUiAvIPCdkYopICsgMScgcG9pbnQgYWRkaXRpb25zIChmaXhlZCBmb3IgYW55IHNjYWxhcilcbi8vIC0gKzEgd2luZG93IGlzIG5lY2Nlc3NhcnkgZm9yIHdOQUZcbi8vIC0gd05BRiByZWR1Y2VzIHRhYmxlIHNpemU6IDJ4IGxlc3MgbWVtb3J5ICsgMnggZmFzdGVyIGdlbmVyYXRpb24sIGJ1dCAxMCUgc2xvd2VyIG11bHRpcGxpY2F0aW9uXG4vLyBUT0RPOiBSZXNlYXJjaCByZXR1cm5pbmcgMmQgSlMgYXJyYXkgb2Ygd2luZG93cywgaW5zdGVhZCBvZiBhIHNpbmdsZSB3aW5kb3cuIFRoaXMgd291bGQgYWxsb3dcbi8vIHdpbmRvd3MgdG8gYmUgaW4gZGlmZmVyZW50IG1lbW9yeSBsb2NhdGlvbnNcbmV4cG9ydCBmdW5jdGlvbiB3TkFGKGMsIGJpdHMpIHtcbiAgICBjb25zdCBjb25zdFRpbWVOZWdhdGUgPSAoY29uZGl0aW9uLCBpdGVtKSA9PiB7XG4gICAgICAgIGNvbnN0IG5lZyA9IGl0ZW0ubmVnYXRlKCk7XG4gICAgICAgIHJldHVybiBjb25kaXRpb24gPyBuZWcgOiBpdGVtO1xuICAgIH07XG4gICAgY29uc3Qgb3B0cyA9IChXKSA9PiB7XG4gICAgICAgIGNvbnN0IHdpbmRvd3MgPSBNYXRoLmNlaWwoYml0cyAvIFcpICsgMTsgLy8gKzEsIGJlY2F1c2VcbiAgICAgICAgY29uc3Qgd2luZG93U2l6ZSA9IDIgKiogKFcgLSAxKTsgLy8gLTEgYmVjYXVzZSB3ZSBza2lwIHplcm9cbiAgICAgICAgcmV0dXJuIHsgd2luZG93cywgd2luZG93U2l6ZSB9O1xuICAgIH07XG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29uc3RUaW1lTmVnYXRlLFxuICAgICAgICAvLyBub24tY29uc3QgdGltZSBtdWx0aXBsaWNhdGlvbiBsYWRkZXJcbiAgICAgICAgdW5zYWZlTGFkZGVyKGVsbSwgbikge1xuICAgICAgICAgICAgbGV0IHAgPSBjLlpFUk87XG4gICAgICAgICAgICBsZXQgZCA9IGVsbTtcbiAgICAgICAgICAgIHdoaWxlIChuID4gXzBuKSB7XG4gICAgICAgICAgICAgICAgaWYgKG4gJiBfMW4pXG4gICAgICAgICAgICAgICAgICAgIHAgPSBwLmFkZChkKTtcbiAgICAgICAgICAgICAgICBkID0gZC5kb3VibGUoKTtcbiAgICAgICAgICAgICAgICBuID4+PSBfMW47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcDtcbiAgICAgICAgfSxcbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSB3TkFGIHByZWNvbXB1dGF0aW9uIHdpbmRvdy4gVXNlZCBmb3IgY2FjaGluZy5cbiAgICAgICAgICogRGVmYXVsdCB3aW5kb3cgc2l6ZSBpcyBzZXQgYnkgYHV0aWxzLnByZWNvbXB1dGUoKWAgYW5kIGlzIGVxdWFsIHRvIDguXG4gICAgICAgICAqIE51bWJlciBvZiBwcmVjb21wdXRlZCBwb2ludHMgZGVwZW5kcyBvbiB0aGUgY3VydmUgc2l6ZTpcbiAgICAgICAgICogMl4o8J2RiuKIkjEpICogKE1hdGguY2VpbCjwnZGbIC8g8J2RiikgKyAxKSwgd2hlcmU6XG4gICAgICAgICAqIC0g8J2RiiBpcyB0aGUgd2luZG93IHNpemVcbiAgICAgICAgICogLSDwnZGbIGlzIHRoZSBiaXRsZW5ndGggb2YgdGhlIGN1cnZlIG9yZGVyLlxuICAgICAgICAgKiBGb3IgYSAyNTYtYml0IGN1cnZlIGFuZCB3aW5kb3cgc2l6ZSA4LCB0aGUgbnVtYmVyIG9mIHByZWNvbXB1dGVkIHBvaW50cyBpcyAxMjggKiAzMyA9IDQyMjQuXG4gICAgICAgICAqIEByZXR1cm5zIHByZWNvbXB1dGVkIHBvaW50IHRhYmxlcyBmbGF0dGVuZWQgdG8gYSBzaW5nbGUgYXJyYXlcbiAgICAgICAgICovXG4gICAgICAgIHByZWNvbXB1dGVXaW5kb3coZWxtLCBXKSB7XG4gICAgICAgICAgICBjb25zdCB7IHdpbmRvd3MsIHdpbmRvd1NpemUgfSA9IG9wdHMoVyk7XG4gICAgICAgICAgICBjb25zdCBwb2ludHMgPSBbXTtcbiAgICAgICAgICAgIGxldCBwID0gZWxtO1xuICAgICAgICAgICAgbGV0IGJhc2UgPSBwO1xuICAgICAgICAgICAgZm9yIChsZXQgd2luZG93ID0gMDsgd2luZG93IDwgd2luZG93czsgd2luZG93KyspIHtcbiAgICAgICAgICAgICAgICBiYXNlID0gcDtcbiAgICAgICAgICAgICAgICBwb2ludHMucHVzaChiYXNlKTtcbiAgICAgICAgICAgICAgICAvLyA9MSwgYmVjYXVzZSB3ZSBza2lwIHplcm9cbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHdpbmRvd1NpemU7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBiYXNlID0gYmFzZS5hZGQocCk7XG4gICAgICAgICAgICAgICAgICAgIHBvaW50cy5wdXNoKGJhc2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwID0gYmFzZS5kb3VibGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBwb2ludHM7XG4gICAgICAgIH0sXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJbXBsZW1lbnRzIGVjIG11bHRpcGxpY2F0aW9uIHVzaW5nIHByZWNvbXB1dGVkIHRhYmxlcyBhbmQgdy1hcnkgbm9uLWFkamFjZW50IGZvcm0uXG4gICAgICAgICAqIEBwYXJhbSBXIHdpbmRvdyBzaXplXG4gICAgICAgICAqIEBwYXJhbSBwcmVjb21wdXRlcyBwcmVjb21wdXRlZCB0YWJsZXNcbiAgICAgICAgICogQHBhcmFtIG4gc2NhbGFyICh3ZSBkb24ndCBjaGVjayBoZXJlLCBidXQgc2hvdWxkIGJlIGxlc3MgdGhhbiBjdXJ2ZSBvcmRlcilcbiAgICAgICAgICogQHJldHVybnMgcmVhbCBhbmQgZmFrZSAoZm9yIGNvbnN0LXRpbWUpIHBvaW50c1xuICAgICAgICAgKi9cbiAgICAgICAgd05BRihXLCBwcmVjb21wdXRlcywgbikge1xuICAgICAgICAgICAgLy8gVE9ETzogbWF5YmUgY2hlY2sgdGhhdCBzY2FsYXIgaXMgbGVzcyB0aGFuIGdyb3VwIG9yZGVyPyB3TkFGIGJlaGF2aW91cyBpcyB1bmRlZmluZWQgb3RoZXJ3aXNlXG4gICAgICAgICAgICAvLyBCdXQgbmVlZCB0byBjYXJlZnVsbHkgcmVtb3ZlIG90aGVyIGNoZWNrcyBiZWZvcmUgd05BRi4gT1JERVIgPT0gYml0cyBoZXJlXG4gICAgICAgICAgICBjb25zdCB7IHdpbmRvd3MsIHdpbmRvd1NpemUgfSA9IG9wdHMoVyk7XG4gICAgICAgICAgICBsZXQgcCA9IGMuWkVSTztcbiAgICAgICAgICAgIGxldCBmID0gYy5CQVNFO1xuICAgICAgICAgICAgY29uc3QgbWFzayA9IEJpZ0ludCgyICoqIFcgLSAxKTsgLy8gQ3JlYXRlIG1hc2sgd2l0aCBXIG9uZXM6IDBiMTExMSBmb3IgVz00IGV0Yy5cbiAgICAgICAgICAgIGNvbnN0IG1heE51bWJlciA9IDIgKiogVztcbiAgICAgICAgICAgIGNvbnN0IHNoaWZ0QnkgPSBCaWdJbnQoVyk7XG4gICAgICAgICAgICBmb3IgKGxldCB3aW5kb3cgPSAwOyB3aW5kb3cgPCB3aW5kb3dzOyB3aW5kb3crKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHdpbmRvdyAqIHdpbmRvd1NpemU7XG4gICAgICAgICAgICAgICAgLy8gRXh0cmFjdCBXIGJpdHMuXG4gICAgICAgICAgICAgICAgbGV0IHdiaXRzID0gTnVtYmVyKG4gJiBtYXNrKTtcbiAgICAgICAgICAgICAgICAvLyBTaGlmdCBudW1iZXIgYnkgVyBiaXRzLlxuICAgICAgICAgICAgICAgIG4gPj49IHNoaWZ0Qnk7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIGJpdHMgYXJlIGJpZ2dlciB0aGFuIG1heCBzaXplLCB3ZSdsbCBzcGxpdCB0aG9zZS5cbiAgICAgICAgICAgICAgICAvLyArMjI0ID0+IDI1NiAtIDMyXG4gICAgICAgICAgICAgICAgaWYgKHdiaXRzID4gd2luZG93U2l6ZSkge1xuICAgICAgICAgICAgICAgICAgICB3Yml0cyAtPSBtYXhOdW1iZXI7XG4gICAgICAgICAgICAgICAgICAgIG4gKz0gXzFuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBUaGlzIGNvZGUgd2FzIGZpcnN0IHdyaXR0ZW4gd2l0aCBhc3N1bXB0aW9uIHRoYXQgJ2YnIGFuZCAncCcgd2lsbCBuZXZlciBiZSBpbmZpbml0eSBwb2ludDpcbiAgICAgICAgICAgICAgICAvLyBzaW5jZSBlYWNoIGFkZGl0aW9uIGlzIG11bHRpcGxpZWQgYnkgMiAqKiBXLCBpdCBjYW5ub3QgY2FuY2VsIGVhY2ggb3RoZXIuIEhvd2V2ZXIsXG4gICAgICAgICAgICAgICAgLy8gdGhlcmUgaXMgbmVnYXRlIG5vdzogaXQgaXMgcG9zc2libGUgdGhhdCBuZWdhdGVkIGVsZW1lbnQgZnJvbSBsb3cgdmFsdWVcbiAgICAgICAgICAgICAgICAvLyB3b3VsZCBiZSB0aGUgc2FtZSBhcyBoaWdoIGVsZW1lbnQsIHdoaWNoIHdpbGwgY3JlYXRlIGNhcnJ5IGludG8gbmV4dCB3aW5kb3cuXG4gICAgICAgICAgICAgICAgLy8gSXQncyBub3Qgb2J2aW91cyBob3cgdGhpcyBjYW4gZmFpbCwgYnV0IHN0aWxsIHdvcnRoIGludmVzdGlnYXRpbmcgbGF0ZXIuXG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgd2UncmUgb250byBaZXJvIHBvaW50LlxuICAgICAgICAgICAgICAgIC8vIEFkZCByYW5kb20gcG9pbnQgaW5zaWRlIGN1cnJlbnQgd2luZG93IHRvIGYuXG4gICAgICAgICAgICAgICAgY29uc3Qgb2Zmc2V0MSA9IG9mZnNldDtcbiAgICAgICAgICAgICAgICBjb25zdCBvZmZzZXQyID0gb2Zmc2V0ICsgTWF0aC5hYnMod2JpdHMpIC0gMTsgLy8gLTEgYmVjYXVzZSB3ZSBza2lwIHplcm9cbiAgICAgICAgICAgICAgICBjb25zdCBjb25kMSA9IHdpbmRvdyAlIDIgIT09IDA7XG4gICAgICAgICAgICAgICAgY29uc3QgY29uZDIgPSB3Yml0cyA8IDA7XG4gICAgICAgICAgICAgICAgaWYgKHdiaXRzID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSBtb3N0IGltcG9ydGFudCBwYXJ0IGZvciBjb25zdC10aW1lIGdldFB1YmxpY0tleVxuICAgICAgICAgICAgICAgICAgICBmID0gZi5hZGQoY29uc3RUaW1lTmVnYXRlKGNvbmQxLCBwcmVjb21wdXRlc1tvZmZzZXQxXSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcCA9IHAuYWRkKGNvbnN0VGltZU5lZ2F0ZShjb25kMiwgcHJlY29tcHV0ZXNbb2Zmc2V0Ml0pKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBKSVQtY29tcGlsZXIgc2hvdWxkIG5vdCBlbGltaW5hdGUgZiBoZXJlLCBzaW5jZSBpdCB3aWxsIGxhdGVyIGJlIHVzZWQgaW4gbm9ybWFsaXplWigpXG4gICAgICAgICAgICAvLyBFdmVuIGlmIHRoZSB2YXJpYWJsZSBpcyBzdGlsbCB1bnVzZWQsIHRoZXJlIGFyZSBzb21lIGNoZWNrcyB3aGljaCB3aWxsXG4gICAgICAgICAgICAvLyB0aHJvdyBhbiBleGNlcHRpb24sIHNvIGNvbXBpbGVyIG5lZWRzIHRvIHByb3ZlIHRoZXkgd29uJ3QgaGFwcGVuLCB3aGljaCBpcyBoYXJkLlxuICAgICAgICAgICAgLy8gQXQgdGhpcyBwb2ludCB0aGVyZSBpcyBhIHdheSB0byBGIGJlIGluZmluaXR5LXBvaW50IGV2ZW4gaWYgcCBpcyBub3QsXG4gICAgICAgICAgICAvLyB3aGljaCBtYWtlcyBpdCBsZXNzIGNvbnN0LXRpbWU6IGFyb3VuZCAxIGJpZ2ludCBtdWx0aXBseS5cbiAgICAgICAgICAgIHJldHVybiB7IHAsIGYgfTtcbiAgICAgICAgfSxcbiAgICAgICAgd05BRkNhY2hlZChQLCBwcmVjb21wdXRlc01hcCwgbiwgdHJhbnNmb3JtKSB7XG4gICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICBjb25zdCBXID0gUC5fV0lORE9XX1NJWkUgfHwgMTtcbiAgICAgICAgICAgIC8vIENhbGN1bGF0ZSBwcmVjb21wdXRlcyBvbiBhIGZpcnN0IHJ1biwgcmV1c2UgdGhlbSBhZnRlclxuICAgICAgICAgICAgbGV0IGNvbXAgPSBwcmVjb21wdXRlc01hcC5nZXQoUCk7XG4gICAgICAgICAgICBpZiAoIWNvbXApIHtcbiAgICAgICAgICAgICAgICBjb21wID0gdGhpcy5wcmVjb21wdXRlV2luZG93KFAsIFcpO1xuICAgICAgICAgICAgICAgIGlmIChXICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHByZWNvbXB1dGVzTWFwLnNldChQLCB0cmFuc2Zvcm0oY29tcCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLndOQUYoVywgY29tcCwgbik7XG4gICAgICAgIH0sXG4gICAgfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUJhc2ljKGN1cnZlKSB7XG4gICAgdmFsaWRhdGVGaWVsZChjdXJ2ZS5GcCk7XG4gICAgdmFsaWRhdGVPYmplY3QoY3VydmUsIHtcbiAgICAgICAgbjogJ2JpZ2ludCcsXG4gICAgICAgIGg6ICdiaWdpbnQnLFxuICAgICAgICBHeDogJ2ZpZWxkJyxcbiAgICAgICAgR3k6ICdmaWVsZCcsXG4gICAgfSwge1xuICAgICAgICBuQml0TGVuZ3RoOiAnaXNTYWZlSW50ZWdlcicsXG4gICAgICAgIG5CeXRlTGVuZ3RoOiAnaXNTYWZlSW50ZWdlcicsXG4gICAgfSk7XG4gICAgLy8gU2V0IGRlZmF1bHRzXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoe1xuICAgICAgICAuLi5uTGVuZ3RoKGN1cnZlLm4sIGN1cnZlLm5CaXRMZW5ndGgpLFxuICAgICAgICAuLi5jdXJ2ZSxcbiAgICAgICAgLi4ueyBwOiBjdXJ2ZS5GcC5PUkRFUiB9LFxuICAgIH0pO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y3VydmUuanMubWFwIiwiLyohIG5vYmxlLWN1cnZlcyAtIE1JVCBMaWNlbnNlIChjKSAyMDIyIFBhdWwgTWlsbGVyIChwYXVsbWlsbHIuY29tKSAqL1xuLy8gVHdpc3RlZCBFZHdhcmRzIGN1cnZlLiBUaGUgZm9ybXVsYSBpczogYXjCsiArIHnCsiA9IDEgKyBkeMKyecKyXG5pbXBvcnQgeyBtb2QgfSBmcm9tICcuL21vZHVsYXIuanMnO1xuaW1wb3J0ICogYXMgdXQgZnJvbSAnLi91dGlscy5qcyc7XG5pbXBvcnQgeyBlbnN1cmVCeXRlcyB9IGZyb20gJy4vdXRpbHMuanMnO1xuaW1wb3J0IHsgd05BRiwgdmFsaWRhdGVCYXNpYyB9IGZyb20gJy4vY3VydmUuanMnO1xuLy8gQmUgZnJpZW5kbHkgdG8gYmFkIEVDTUFTY3JpcHQgcGFyc2VycyBieSBub3QgdXNpbmcgYmlnaW50IGxpdGVyYWxzXG4vLyBwcmV0dGllci1pZ25vcmVcbmNvbnN0IF8wbiA9IEJpZ0ludCgwKSwgXzFuID0gQmlnSW50KDEpLCBfMm4gPSBCaWdJbnQoMiksIF84biA9IEJpZ0ludCg4KTtcbi8vIHZlcmlmaWNhdGlvbiBydWxlIGlzIGVpdGhlciB6aXAyMTUgb3IgcmZjODAzMiAvIG5pc3QxODYtNS4gQ29uc3VsdCBmcm9tSGV4OlxuY29uc3QgVkVSSUZZX0RFRkFVTFQgPSB7IHppcDIxNTogdHJ1ZSB9O1xuZnVuY3Rpb24gdmFsaWRhdGVPcHRzKGN1cnZlKSB7XG4gICAgY29uc3Qgb3B0cyA9IHZhbGlkYXRlQmFzaWMoY3VydmUpO1xuICAgIHV0LnZhbGlkYXRlT2JqZWN0KGN1cnZlLCB7XG4gICAgICAgIGhhc2g6ICdmdW5jdGlvbicsXG4gICAgICAgIGE6ICdiaWdpbnQnLFxuICAgICAgICBkOiAnYmlnaW50JyxcbiAgICAgICAgcmFuZG9tQnl0ZXM6ICdmdW5jdGlvbicsXG4gICAgfSwge1xuICAgICAgICBhZGp1c3RTY2FsYXJCeXRlczogJ2Z1bmN0aW9uJyxcbiAgICAgICAgZG9tYWluOiAnZnVuY3Rpb24nLFxuICAgICAgICB1dlJhdGlvOiAnZnVuY3Rpb24nLFxuICAgICAgICBtYXBUb0N1cnZlOiAnZnVuY3Rpb24nLFxuICAgIH0pO1xuICAgIC8vIFNldCBkZWZhdWx0c1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKHsgLi4ub3B0cyB9KTtcbn1cbi8vIEl0IGlzIG5vdCBnZW5lcmljIHR3aXN0ZWQgY3VydmUgZm9yIG5vdywgYnV0IGVkMjU1MTkvZWQ0NDggZ2VuZXJpYyBpbXBsZW1lbnRhdGlvblxuZXhwb3J0IGZ1bmN0aW9uIHR3aXN0ZWRFZHdhcmRzKGN1cnZlRGVmKSB7XG4gICAgY29uc3QgQ1VSVkUgPSB2YWxpZGF0ZU9wdHMoY3VydmVEZWYpO1xuICAgIGNvbnN0IHsgRnAsIG46IENVUlZFX09SREVSLCBwcmVoYXNoOiBwcmVoYXNoLCBoYXNoOiBjSGFzaCwgcmFuZG9tQnl0ZXMsIG5CeXRlTGVuZ3RoLCBoOiBjb2ZhY3RvciwgfSA9IENVUlZFO1xuICAgIGNvbnN0IE1BU0sgPSBfMm4gKiogQmlnSW50KG5CeXRlTGVuZ3RoICogOCk7XG4gICAgY29uc3QgbW9kUCA9IEZwLmNyZWF0ZTsgLy8gRnVuY3Rpb24gb3ZlcnJpZGVzXG4gICAgLy8gc3FydCh1L3YpXG4gICAgY29uc3QgdXZSYXRpbyA9IENVUlZFLnV2UmF0aW8gfHxcbiAgICAgICAgKCh1LCB2KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IGlzVmFsaWQ6IHRydWUsIHZhbHVlOiBGcC5zcXJ0KHUgKiBGcC5pbnYodikpIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IGlzVmFsaWQ6IGZhbHNlLCB2YWx1ZTogXzBuIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIGNvbnN0IGFkanVzdFNjYWxhckJ5dGVzID0gQ1VSVkUuYWRqdXN0U2NhbGFyQnl0ZXMgfHwgKChieXRlcykgPT4gYnl0ZXMpOyAvLyBOT09QXG4gICAgY29uc3QgZG9tYWluID0gQ1VSVkUuZG9tYWluIHx8XG4gICAgICAgICgoZGF0YSwgY3R4LCBwaGZsYWcpID0+IHtcbiAgICAgICAgICAgIGlmIChjdHgubGVuZ3RoIHx8IHBoZmxhZylcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvbnRleHRzL3ByZS1oYXNoIGFyZSBub3Qgc3VwcG9ydGVkJyk7XG4gICAgICAgICAgICByZXR1cm4gZGF0YTtcbiAgICAgICAgfSk7IC8vIE5PT1BcbiAgICBjb25zdCBpbkJpZyA9IChuKSA9PiB0eXBlb2YgbiA9PT0gJ2JpZ2ludCcgJiYgXzBuIDwgbjsgLy8gbiBpbiBbMS4uXVxuICAgIGNvbnN0IGluUmFuZ2UgPSAobiwgbWF4KSA9PiBpbkJpZyhuKSAmJiBpbkJpZyhtYXgpICYmIG4gPCBtYXg7IC8vIG4gaW4gWzEuLm1heC0xXVxuICAgIGNvbnN0IGluME1hc2tSYW5nZSA9IChuKSA9PiBuID09PSBfMG4gfHwgaW5SYW5nZShuLCBNQVNLKTsgLy8gbiBpbiBbMC4uTUFTSy0xXVxuICAgIGZ1bmN0aW9uIGFzc2VydEluUmFuZ2UobiwgbWF4KSB7XG4gICAgICAgIC8vIG4gaW4gWzEuLm1heC0xXVxuICAgICAgICBpZiAoaW5SYW5nZShuLCBtYXgpKVxuICAgICAgICAgICAgcmV0dXJuIG47XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgdmFsaWQgc2NhbGFyIDwgJHttYXh9LCBnb3QgJHt0eXBlb2Ygbn0gJHtufWApO1xuICAgIH1cbiAgICBmdW5jdGlvbiBhc3NlcnRHRTAobikge1xuICAgICAgICAvLyBuIGluIFswLi5DVVJWRV9PUkRFUi0xXVxuICAgICAgICByZXR1cm4gbiA9PT0gXzBuID8gbiA6IGFzc2VydEluUmFuZ2UobiwgQ1VSVkVfT1JERVIpOyAvLyBHRSA9IHByaW1lIHN1Ymdyb3VwLCBub3QgZnVsbCBncm91cFxuICAgIH1cbiAgICBjb25zdCBwb2ludFByZWNvbXB1dGVzID0gbmV3IE1hcCgpO1xuICAgIGZ1bmN0aW9uIGlzUG9pbnQob3RoZXIpIHtcbiAgICAgICAgaWYgKCEob3RoZXIgaW5zdGFuY2VvZiBQb2ludCkpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4dGVuZGVkUG9pbnQgZXhwZWN0ZWQnKTtcbiAgICB9XG4gICAgLy8gRXh0ZW5kZWQgUG9pbnQgd29ya3MgaW4gZXh0ZW5kZWQgY29vcmRpbmF0ZXM6ICh4LCB5LCB6LCB0KSDiiIsgKHg9eC96LCB5PXkveiwgdD14eSkuXG4gICAgLy8gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvVHdpc3RlZF9FZHdhcmRzX2N1cnZlI0V4dGVuZGVkX2Nvb3JkaW5hdGVzXG4gICAgY2xhc3MgUG9pbnQge1xuICAgICAgICBjb25zdHJ1Y3RvcihleCwgZXksIGV6LCBldCkge1xuICAgICAgICAgICAgdGhpcy5leCA9IGV4O1xuICAgICAgICAgICAgdGhpcy5leSA9IGV5O1xuICAgICAgICAgICAgdGhpcy5leiA9IGV6O1xuICAgICAgICAgICAgdGhpcy5ldCA9IGV0O1xuICAgICAgICAgICAgaWYgKCFpbjBNYXNrUmFuZ2UoZXgpKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigneCByZXF1aXJlZCcpO1xuICAgICAgICAgICAgaWYgKCFpbjBNYXNrUmFuZ2UoZXkpKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigneSByZXF1aXJlZCcpO1xuICAgICAgICAgICAgaWYgKCFpbjBNYXNrUmFuZ2UoZXopKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigneiByZXF1aXJlZCcpO1xuICAgICAgICAgICAgaWYgKCFpbjBNYXNrUmFuZ2UoZXQpKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigndCByZXF1aXJlZCcpO1xuICAgICAgICB9XG4gICAgICAgIGdldCB4KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9BZmZpbmUoKS54O1xuICAgICAgICB9XG4gICAgICAgIGdldCB5KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9BZmZpbmUoKS55O1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBmcm9tQWZmaW5lKHApIHtcbiAgICAgICAgICAgIGlmIChwIGluc3RhbmNlb2YgUG9pbnQpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdleHRlbmRlZCBwb2ludCBub3QgYWxsb3dlZCcpO1xuICAgICAgICAgICAgY29uc3QgeyB4LCB5IH0gPSBwIHx8IHt9O1xuICAgICAgICAgICAgaWYgKCFpbjBNYXNrUmFuZ2UoeCkgfHwgIWluME1hc2tSYW5nZSh5KSlcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgYWZmaW5lIHBvaW50Jyk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFBvaW50KHgsIHksIF8xbiwgbW9kUCh4ICogeSkpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBub3JtYWxpemVaKHBvaW50cykge1xuICAgICAgICAgICAgY29uc3QgdG9JbnYgPSBGcC5pbnZlcnRCYXRjaChwb2ludHMubWFwKChwKSA9PiBwLmV6KSk7XG4gICAgICAgICAgICByZXR1cm4gcG9pbnRzLm1hcCgocCwgaSkgPT4gcC50b0FmZmluZSh0b0ludltpXSkpLm1hcChQb2ludC5mcm9tQWZmaW5lKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBcIlByaXZhdGUgbWV0aG9kXCIsIGRvbid0IHVzZSBpdCBkaXJlY3RseVxuICAgICAgICBfc2V0V2luZG93U2l6ZSh3aW5kb3dTaXplKSB7XG4gICAgICAgICAgICB0aGlzLl9XSU5ET1dfU0laRSA9IHdpbmRvd1NpemU7XG4gICAgICAgICAgICBwb2ludFByZWNvbXB1dGVzLmRlbGV0ZSh0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBOb3QgcmVxdWlyZWQgZm9yIGZyb21IZXgoKSwgd2hpY2ggYWx3YXlzIGNyZWF0ZXMgdmFsaWQgcG9pbnRzLlxuICAgICAgICAvLyBDb3VsZCBiZSB1c2VmdWwgZm9yIGZyb21BZmZpbmUoKS5cbiAgICAgICAgYXNzZXJ0VmFsaWRpdHkoKSB7XG4gICAgICAgICAgICBjb25zdCB7IGEsIGQgfSA9IENVUlZFO1xuICAgICAgICAgICAgaWYgKHRoaXMuaXMwKCkpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdiYWQgcG9pbnQ6IFpFUk8nKTsgLy8gVE9ETzogb3B0aW1pemUsIHdpdGggdmFycyBiZWxvdz9cbiAgICAgICAgICAgIC8vIEVxdWF0aW9uIGluIGFmZmluZSBjb29yZGluYXRlczogYXjCsiArIHnCsiA9IDEgKyBkeMKyecKyXG4gICAgICAgICAgICAvLyBFcXVhdGlvbiBpbiBwcm9qZWN0aXZlIGNvb3JkaW5hdGVzIChYL1osIFkvWiwgWik6ICAoYVjCsiArIFnCsilawrIgPSBa4oG0ICsgZFjCslnCslxuICAgICAgICAgICAgY29uc3QgeyBleDogWCwgZXk6IFksIGV6OiBaLCBldDogVCB9ID0gdGhpcztcbiAgICAgICAgICAgIGNvbnN0IFgyID0gbW9kUChYICogWCk7IC8vIFjCslxuICAgICAgICAgICAgY29uc3QgWTIgPSBtb2RQKFkgKiBZKTsgLy8gWcKyXG4gICAgICAgICAgICBjb25zdCBaMiA9IG1vZFAoWiAqIFopOyAvLyBawrJcbiAgICAgICAgICAgIGNvbnN0IFo0ID0gbW9kUChaMiAqIFoyKTsgLy8gWuKBtFxuICAgICAgICAgICAgY29uc3QgYVgyID0gbW9kUChYMiAqIGEpOyAvLyBhWMKyXG4gICAgICAgICAgICBjb25zdCBsZWZ0ID0gbW9kUChaMiAqIG1vZFAoYVgyICsgWTIpKTsgLy8gKGFYwrIgKyBZwrIpWsKyXG4gICAgICAgICAgICBjb25zdCByaWdodCA9IG1vZFAoWjQgKyBtb2RQKGQgKiBtb2RQKFgyICogWTIpKSk7IC8vIFrigbQgKyBkWMKyWcKyXG4gICAgICAgICAgICBpZiAobGVmdCAhPT0gcmlnaHQpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdiYWQgcG9pbnQ6IGVxdWF0aW9uIGxlZnQgIT0gcmlnaHQgKDEpJyk7XG4gICAgICAgICAgICAvLyBJbiBFeHRlbmRlZCBjb29yZGluYXRlcyB3ZSBhbHNvIGhhdmUgVCwgd2hpY2ggaXMgeCp5PVQvWjogY2hlY2sgWCpZID09IFoqVFxuICAgICAgICAgICAgY29uc3QgWFkgPSBtb2RQKFggKiBZKTtcbiAgICAgICAgICAgIGNvbnN0IFpUID0gbW9kUChaICogVCk7XG4gICAgICAgICAgICBpZiAoWFkgIT09IFpUKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignYmFkIHBvaW50OiBlcXVhdGlvbiBsZWZ0ICE9IHJpZ2h0ICgyKScpO1xuICAgICAgICB9XG4gICAgICAgIC8vIENvbXBhcmUgb25lIHBvaW50IHRvIGFub3RoZXIuXG4gICAgICAgIGVxdWFscyhvdGhlcikge1xuICAgICAgICAgICAgaXNQb2ludChvdGhlcik7XG4gICAgICAgICAgICBjb25zdCB7IGV4OiBYMSwgZXk6IFkxLCBlejogWjEgfSA9IHRoaXM7XG4gICAgICAgICAgICBjb25zdCB7IGV4OiBYMiwgZXk6IFkyLCBlejogWjIgfSA9IG90aGVyO1xuICAgICAgICAgICAgY29uc3QgWDFaMiA9IG1vZFAoWDEgKiBaMik7XG4gICAgICAgICAgICBjb25zdCBYMloxID0gbW9kUChYMiAqIFoxKTtcbiAgICAgICAgICAgIGNvbnN0IFkxWjIgPSBtb2RQKFkxICogWjIpO1xuICAgICAgICAgICAgY29uc3QgWTJaMSA9IG1vZFAoWTIgKiBaMSk7XG4gICAgICAgICAgICByZXR1cm4gWDFaMiA9PT0gWDJaMSAmJiBZMVoyID09PSBZMloxO1xuICAgICAgICB9XG4gICAgICAgIGlzMCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVxdWFscyhQb2ludC5aRVJPKTtcbiAgICAgICAgfVxuICAgICAgICBuZWdhdGUoKSB7XG4gICAgICAgICAgICAvLyBGbGlwcyBwb2ludCBzaWduIHRvIGEgbmVnYXRpdmUgb25lICgteCwgeSBpbiBhZmZpbmUgY29vcmRzKVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBQb2ludChtb2RQKC10aGlzLmV4KSwgdGhpcy5leSwgdGhpcy5leiwgbW9kUCgtdGhpcy5ldCkpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEZhc3QgYWxnbyBmb3IgZG91YmxpbmcgRXh0ZW5kZWQgUG9pbnQuXG4gICAgICAgIC8vIGh0dHBzOi8vaHlwZXJlbGxpcHRpYy5vcmcvRUZEL2cxcC9hdXRvLXR3aXN0ZWQtZXh0ZW5kZWQuaHRtbCNkb3VibGluZy1kYmwtMjAwOC1od2NkXG4gICAgICAgIC8vIENvc3Q6IDRNICsgNFMgKyAxKmEgKyA2YWRkICsgMSoyLlxuICAgICAgICBkb3VibGUoKSB7XG4gICAgICAgICAgICBjb25zdCB7IGEgfSA9IENVUlZFO1xuICAgICAgICAgICAgY29uc3QgeyBleDogWDEsIGV5OiBZMSwgZXo6IFoxIH0gPSB0aGlzO1xuICAgICAgICAgICAgY29uc3QgQSA9IG1vZFAoWDEgKiBYMSk7IC8vIEEgPSBYMTJcbiAgICAgICAgICAgIGNvbnN0IEIgPSBtb2RQKFkxICogWTEpOyAvLyBCID0gWTEyXG4gICAgICAgICAgICBjb25zdCBDID0gbW9kUChfMm4gKiBtb2RQKFoxICogWjEpKTsgLy8gQyA9IDIqWjEyXG4gICAgICAgICAgICBjb25zdCBEID0gbW9kUChhICogQSk7IC8vIEQgPSBhKkFcbiAgICAgICAgICAgIGNvbnN0IHgxeTEgPSBYMSArIFkxO1xuICAgICAgICAgICAgY29uc3QgRSA9IG1vZFAobW9kUCh4MXkxICogeDF5MSkgLSBBIC0gQik7IC8vIEUgPSAoWDErWTEpMi1BLUJcbiAgICAgICAgICAgIGNvbnN0IEcgPSBEICsgQjsgLy8gRyA9IEQrQlxuICAgICAgICAgICAgY29uc3QgRiA9IEcgLSBDOyAvLyBGID0gRy1DXG4gICAgICAgICAgICBjb25zdCBIID0gRCAtIEI7IC8vIEggPSBELUJcbiAgICAgICAgICAgIGNvbnN0IFgzID0gbW9kUChFICogRik7IC8vIFgzID0gRSpGXG4gICAgICAgICAgICBjb25zdCBZMyA9IG1vZFAoRyAqIEgpOyAvLyBZMyA9IEcqSFxuICAgICAgICAgICAgY29uc3QgVDMgPSBtb2RQKEUgKiBIKTsgLy8gVDMgPSBFKkhcbiAgICAgICAgICAgIGNvbnN0IFozID0gbW9kUChGICogRyk7IC8vIFozID0gRipHXG4gICAgICAgICAgICByZXR1cm4gbmV3IFBvaW50KFgzLCBZMywgWjMsIFQzKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBGYXN0IGFsZ28gZm9yIGFkZGluZyAyIEV4dGVuZGVkIFBvaW50cy5cbiAgICAgICAgLy8gaHR0cHM6Ly9oeXBlcmVsbGlwdGljLm9yZy9FRkQvZzFwL2F1dG8tdHdpc3RlZC1leHRlbmRlZC5odG1sI2FkZGl0aW9uLWFkZC0yMDA4LWh3Y2RcbiAgICAgICAgLy8gQ29zdDogOU0gKyAxKmEgKyAxKmQgKyA3YWRkLlxuICAgICAgICBhZGQob3RoZXIpIHtcbiAgICAgICAgICAgIGlzUG9pbnQob3RoZXIpO1xuICAgICAgICAgICAgY29uc3QgeyBhLCBkIH0gPSBDVVJWRTtcbiAgICAgICAgICAgIGNvbnN0IHsgZXg6IFgxLCBleTogWTEsIGV6OiBaMSwgZXQ6IFQxIH0gPSB0aGlzO1xuICAgICAgICAgICAgY29uc3QgeyBleDogWDIsIGV5OiBZMiwgZXo6IFoyLCBldDogVDIgfSA9IG90aGVyO1xuICAgICAgICAgICAgLy8gRmFzdGVyIGFsZ28gZm9yIGFkZGluZyAyIEV4dGVuZGVkIFBvaW50cyB3aGVuIGN1cnZlJ3MgYT0tMS5cbiAgICAgICAgICAgIC8vIGh0dHA6Ly9oeXBlcmVsbGlwdGljLm9yZy9FRkQvZzFwL2F1dG8tdHdpc3RlZC1leHRlbmRlZC0xLmh0bWwjYWRkaXRpb24tYWRkLTIwMDgtaHdjZC00XG4gICAgICAgICAgICAvLyBDb3N0OiA4TSArIDhhZGQgKyAyKjIuXG4gICAgICAgICAgICAvLyBOb3RlOiBJdCBkb2VzIG5vdCBjaGVjayB3aGV0aGVyIHRoZSBgb3RoZXJgIHBvaW50IGlzIHZhbGlkLlxuICAgICAgICAgICAgaWYgKGEgPT09IEJpZ0ludCgtMSkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBBID0gbW9kUCgoWTEgLSBYMSkgKiAoWTIgKyBYMikpO1xuICAgICAgICAgICAgICAgIGNvbnN0IEIgPSBtb2RQKChZMSArIFgxKSAqIChZMiAtIFgyKSk7XG4gICAgICAgICAgICAgICAgY29uc3QgRiA9IG1vZFAoQiAtIEEpO1xuICAgICAgICAgICAgICAgIGlmIChGID09PSBfMG4pXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRvdWJsZSgpOyAvLyBTYW1lIHBvaW50LiBUZXN0cyBzYXkgaXQgZG9lc24ndCBhZmZlY3QgdGltaW5nXG4gICAgICAgICAgICAgICAgY29uc3QgQyA9IG1vZFAoWjEgKiBfMm4gKiBUMik7XG4gICAgICAgICAgICAgICAgY29uc3QgRCA9IG1vZFAoVDEgKiBfMm4gKiBaMik7XG4gICAgICAgICAgICAgICAgY29uc3QgRSA9IEQgKyBDO1xuICAgICAgICAgICAgICAgIGNvbnN0IEcgPSBCICsgQTtcbiAgICAgICAgICAgICAgICBjb25zdCBIID0gRCAtIEM7XG4gICAgICAgICAgICAgICAgY29uc3QgWDMgPSBtb2RQKEUgKiBGKTtcbiAgICAgICAgICAgICAgICBjb25zdCBZMyA9IG1vZFAoRyAqIEgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IFQzID0gbW9kUChFICogSCk7XG4gICAgICAgICAgICAgICAgY29uc3QgWjMgPSBtb2RQKEYgKiBHKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFBvaW50KFgzLCBZMywgWjMsIFQzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IEEgPSBtb2RQKFgxICogWDIpOyAvLyBBID0gWDEqWDJcbiAgICAgICAgICAgIGNvbnN0IEIgPSBtb2RQKFkxICogWTIpOyAvLyBCID0gWTEqWTJcbiAgICAgICAgICAgIGNvbnN0IEMgPSBtb2RQKFQxICogZCAqIFQyKTsgLy8gQyA9IFQxKmQqVDJcbiAgICAgICAgICAgIGNvbnN0IEQgPSBtb2RQKFoxICogWjIpOyAvLyBEID0gWjEqWjJcbiAgICAgICAgICAgIGNvbnN0IEUgPSBtb2RQKChYMSArIFkxKSAqIChYMiArIFkyKSAtIEEgLSBCKTsgLy8gRSA9IChYMStZMSkqKFgyK1kyKS1BLUJcbiAgICAgICAgICAgIGNvbnN0IEYgPSBEIC0gQzsgLy8gRiA9IEQtQ1xuICAgICAgICAgICAgY29uc3QgRyA9IEQgKyBDOyAvLyBHID0gRCtDXG4gICAgICAgICAgICBjb25zdCBIID0gbW9kUChCIC0gYSAqIEEpOyAvLyBIID0gQi1hKkFcbiAgICAgICAgICAgIGNvbnN0IFgzID0gbW9kUChFICogRik7IC8vIFgzID0gRSpGXG4gICAgICAgICAgICBjb25zdCBZMyA9IG1vZFAoRyAqIEgpOyAvLyBZMyA9IEcqSFxuICAgICAgICAgICAgY29uc3QgVDMgPSBtb2RQKEUgKiBIKTsgLy8gVDMgPSBFKkhcbiAgICAgICAgICAgIGNvbnN0IFozID0gbW9kUChGICogRyk7IC8vIFozID0gRipHXG4gICAgICAgICAgICByZXR1cm4gbmV3IFBvaW50KFgzLCBZMywgWjMsIFQzKTtcbiAgICAgICAgfVxuICAgICAgICBzdWJ0cmFjdChvdGhlcikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRkKG90aGVyLm5lZ2F0ZSgpKTtcbiAgICAgICAgfVxuICAgICAgICB3TkFGKG4pIHtcbiAgICAgICAgICAgIHJldHVybiB3bmFmLndOQUZDYWNoZWQodGhpcywgcG9pbnRQcmVjb21wdXRlcywgbiwgUG9pbnQubm9ybWFsaXplWik7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ29uc3RhbnQtdGltZSBtdWx0aXBsaWNhdGlvbi5cbiAgICAgICAgbXVsdGlwbHkoc2NhbGFyKSB7XG4gICAgICAgICAgICBjb25zdCB7IHAsIGYgfSA9IHRoaXMud05BRihhc3NlcnRJblJhbmdlKHNjYWxhciwgQ1VSVkVfT1JERVIpKTtcbiAgICAgICAgICAgIHJldHVybiBQb2ludC5ub3JtYWxpemVaKFtwLCBmXSlbMF07XG4gICAgICAgIH1cbiAgICAgICAgLy8gTm9uLWNvbnN0YW50LXRpbWUgbXVsdGlwbGljYXRpb24uIFVzZXMgZG91YmxlLWFuZC1hZGQgYWxnb3JpdGhtLlxuICAgICAgICAvLyBJdCdzIGZhc3RlciwgYnV0IHNob3VsZCBvbmx5IGJlIHVzZWQgd2hlbiB5b3UgZG9uJ3QgY2FyZSBhYm91dFxuICAgICAgICAvLyBhbiBleHBvc2VkIHByaXZhdGUga2V5IGUuZy4gc2lnIHZlcmlmaWNhdGlvbi5cbiAgICAgICAgLy8gRG9lcyBOT1QgYWxsb3cgc2NhbGFycyBoaWdoZXIgdGhhbiBDVVJWRS5uLlxuICAgICAgICBtdWx0aXBseVVuc2FmZShzY2FsYXIpIHtcbiAgICAgICAgICAgIGxldCBuID0gYXNzZXJ0R0UwKHNjYWxhcik7IC8vIDAgPD0gc2NhbGFyIDwgQ1VSVkUublxuICAgICAgICAgICAgaWYgKG4gPT09IF8wbilcbiAgICAgICAgICAgICAgICByZXR1cm4gSTtcbiAgICAgICAgICAgIGlmICh0aGlzLmVxdWFscyhJKSB8fCBuID09PSBfMW4pXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICBpZiAodGhpcy5lcXVhbHMoRykpXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMud05BRihuKS5wO1xuICAgICAgICAgICAgcmV0dXJuIHduYWYudW5zYWZlTGFkZGVyKHRoaXMsIG4pO1xuICAgICAgICB9XG4gICAgICAgIC8vIENoZWNrcyBpZiBwb2ludCBpcyBvZiBzbWFsbCBvcmRlci5cbiAgICAgICAgLy8gSWYgeW91IGFkZCBzb21ldGhpbmcgdG8gc21hbGwgb3JkZXIgcG9pbnQsIHlvdSB3aWxsIGhhdmUgXCJkaXJ0eVwiXG4gICAgICAgIC8vIHBvaW50IHdpdGggdG9yc2lvbiBjb21wb25lbnQuXG4gICAgICAgIC8vIE11bHRpcGxpZXMgcG9pbnQgYnkgY29mYWN0b3IgYW5kIGNoZWNrcyBpZiB0aGUgcmVzdWx0IGlzIDAuXG4gICAgICAgIGlzU21hbGxPcmRlcigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm11bHRpcGx5VW5zYWZlKGNvZmFjdG9yKS5pczAoKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBNdWx0aXBsaWVzIHBvaW50IGJ5IGN1cnZlIG9yZGVyIGFuZCBjaGVja3MgaWYgdGhlIHJlc3VsdCBpcyAwLlxuICAgICAgICAvLyBSZXR1cm5zIGBmYWxzZWAgaXMgdGhlIHBvaW50IGlzIGRpcnR5LlxuICAgICAgICBpc1RvcnNpb25GcmVlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHduYWYudW5zYWZlTGFkZGVyKHRoaXMsIENVUlZFX09SREVSKS5pczAoKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBDb252ZXJ0cyBFeHRlbmRlZCBwb2ludCB0byBkZWZhdWx0ICh4LCB5KSBjb29yZGluYXRlcy5cbiAgICAgICAgLy8gQ2FuIGFjY2VwdCBwcmVjb21wdXRlZCBaXi0xIC0gZm9yIGV4YW1wbGUsIGZyb20gaW52ZXJ0QmF0Y2guXG4gICAgICAgIHRvQWZmaW5lKGl6KSB7XG4gICAgICAgICAgICBjb25zdCB7IGV4OiB4LCBleTogeSwgZXo6IHogfSA9IHRoaXM7XG4gICAgICAgICAgICBjb25zdCBpczAgPSB0aGlzLmlzMCgpO1xuICAgICAgICAgICAgaWYgKGl6ID09IG51bGwpXG4gICAgICAgICAgICAgICAgaXogPSBpczAgPyBfOG4gOiBGcC5pbnYoeik7IC8vIDggd2FzIGNob3NlbiBhcmJpdHJhcmlseVxuICAgICAgICAgICAgY29uc3QgYXggPSBtb2RQKHggKiBpeik7XG4gICAgICAgICAgICBjb25zdCBheSA9IG1vZFAoeSAqIGl6KTtcbiAgICAgICAgICAgIGNvbnN0IHp6ID0gbW9kUCh6ICogaXopO1xuICAgICAgICAgICAgaWYgKGlzMClcbiAgICAgICAgICAgICAgICByZXR1cm4geyB4OiBfMG4sIHk6IF8xbiB9O1xuICAgICAgICAgICAgaWYgKHp6ICE9PSBfMW4pXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZaIHdhcyBpbnZhbGlkJyk7XG4gICAgICAgICAgICByZXR1cm4geyB4OiBheCwgeTogYXkgfTtcbiAgICAgICAgfVxuICAgICAgICBjbGVhckNvZmFjdG9yKCkge1xuICAgICAgICAgICAgY29uc3QgeyBoOiBjb2ZhY3RvciB9ID0gQ1VSVkU7XG4gICAgICAgICAgICBpZiAoY29mYWN0b3IgPT09IF8xbilcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm11bHRpcGx5VW5zYWZlKGNvZmFjdG9yKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBDb252ZXJ0cyBoYXNoIHN0cmluZyBvciBVaW50OEFycmF5IHRvIFBvaW50LlxuICAgICAgICAvLyBVc2VzIGFsZ28gZnJvbSBSRkM4MDMyIDUuMS4zLlxuICAgICAgICBzdGF0aWMgZnJvbUhleChoZXgsIHppcDIxNSA9IGZhbHNlKSB7XG4gICAgICAgICAgICBjb25zdCB7IGQsIGEgfSA9IENVUlZFO1xuICAgICAgICAgICAgY29uc3QgbGVuID0gRnAuQllURVM7XG4gICAgICAgICAgICBoZXggPSBlbnN1cmVCeXRlcygncG9pbnRIZXgnLCBoZXgsIGxlbik7IC8vIGNvcHkgaGV4IHRvIGEgbmV3IGFycmF5XG4gICAgICAgICAgICBjb25zdCBub3JtZWQgPSBoZXguc2xpY2UoKTsgLy8gY29weSBhZ2Fpbiwgd2UnbGwgbWFuaXB1bGF0ZSBpdFxuICAgICAgICAgICAgY29uc3QgbGFzdEJ5dGUgPSBoZXhbbGVuIC0gMV07IC8vIHNlbGVjdCBsYXN0IGJ5dGVcbiAgICAgICAgICAgIG5vcm1lZFtsZW4gLSAxXSA9IGxhc3RCeXRlICYgfjB4ODA7IC8vIGNsZWFyIGxhc3QgYml0XG4gICAgICAgICAgICBjb25zdCB5ID0gdXQuYnl0ZXNUb051bWJlckxFKG5vcm1lZCk7XG4gICAgICAgICAgICBpZiAoeSA9PT0gXzBuKSB7XG4gICAgICAgICAgICAgICAgLy8geT0wIGlzIGFsbG93ZWRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFJGQzgwMzIgcHJvaGliaXRzID49IHAsIGJ1dCBaSVAyMTUgZG9lc24ndFxuICAgICAgICAgICAgICAgIGlmICh6aXAyMTUpXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydEluUmFuZ2UoeSwgTUFTSyk7IC8vIHppcDIxNT10cnVlIFsxLi5QLTFdICgyXjI1NS0xOS0xIGZvciBlZDI1NTE5KVxuICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0SW5SYW5nZSh5LCBGcC5PUkRFUik7IC8vIHppcDIxNT1mYWxzZSBbMS4uTUFTSy0xXSAoMl4yNTYtMSBmb3IgZWQyNTUxOSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEVkMjU1MTk6IHjCsiA9ICh5wrItMSkvKGR5wrIrMSkgbW9kIHAuIEVkNDQ4OiB4wrIgPSAoecKyLTEpLyhkecKyLTEpIG1vZCBwLiBHZW5lcmljIGNhc2U6XG4gICAgICAgICAgICAvLyBheMKyK3nCsj0xK2R4wrJ5wrIgPT4gecKyLTE9ZHjCsnnCsi1heMKyID0+IHnCsi0xPXjCsihkecKyLWEpID0+IHjCsj0oecKyLTEpLyhkecKyLWEpXG4gICAgICAgICAgICBjb25zdCB5MiA9IG1vZFAoeSAqIHkpOyAvLyBkZW5vbWluYXRvciBpcyBhbHdheXMgbm9uLTAgbW9kIHAuXG4gICAgICAgICAgICBjb25zdCB1ID0gbW9kUCh5MiAtIF8xbik7IC8vIHUgPSB5wrIgLSAxXG4gICAgICAgICAgICBjb25zdCB2ID0gbW9kUChkICogeTIgLSBhKTsgLy8gdiA9IGQgecKyICsgMS5cbiAgICAgICAgICAgIGxldCB7IGlzVmFsaWQsIHZhbHVlOiB4IH0gPSB1dlJhdGlvKHUsIHYpOyAvLyDiiJoodS92KVxuICAgICAgICAgICAgaWYgKCFpc1ZhbGlkKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUG9pbnQuZnJvbUhleDogaW52YWxpZCB5IGNvb3JkaW5hdGUnKTtcbiAgICAgICAgICAgIGNvbnN0IGlzWE9kZCA9ICh4ICYgXzFuKSA9PT0gXzFuOyAvLyBUaGVyZSBhcmUgMiBzcXVhcmUgcm9vdHMuIFVzZSB4XzAgYml0IHRvIHNlbGVjdCBwcm9wZXJcbiAgICAgICAgICAgIGNvbnN0IGlzTGFzdEJ5dGVPZGQgPSAobGFzdEJ5dGUgJiAweDgwKSAhPT0gMDsgLy8gaWYgeD0wIGFuZCB4XzAgPSAxLCBmYWlsXG4gICAgICAgICAgICBpZiAoaXNMYXN0Qnl0ZU9kZCAhPT0gaXNYT2RkKVxuICAgICAgICAgICAgICAgIHggPSBtb2RQKC14KTsgLy8gaWYgeF8wICE9IHggbW9kIDIsIHNldCB4ID0gcC14XG4gICAgICAgICAgICByZXR1cm4gUG9pbnQuZnJvbUFmZmluZSh7IHgsIHkgfSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGZyb21Qcml2YXRlS2V5KHByaXZLZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBnZXRFeHRlbmRlZFB1YmxpY0tleShwcml2S2V5KS5wb2ludDtcbiAgICAgICAgfVxuICAgICAgICB0b1Jhd0J5dGVzKCkge1xuICAgICAgICAgICAgY29uc3QgeyB4LCB5IH0gPSB0aGlzLnRvQWZmaW5lKCk7XG4gICAgICAgICAgICBjb25zdCBieXRlcyA9IHV0Lm51bWJlclRvQnl0ZXNMRSh5LCBGcC5CWVRFUyk7IC8vIGVhY2ggeSBoYXMgMiB4IHZhbHVlcyAoeCwgLXkpXG4gICAgICAgICAgICBieXRlc1tieXRlcy5sZW5ndGggLSAxXSB8PSB4ICYgXzFuID8gMHg4MCA6IDA7IC8vIHdoZW4gY29tcHJlc3NpbmcsIGl0J3MgZW5vdWdoIHRvIHN0b3JlIHlcbiAgICAgICAgICAgIHJldHVybiBieXRlczsgLy8gYW5kIHVzZSB0aGUgbGFzdCBieXRlIHRvIGVuY29kZSBzaWduIG9mIHhcbiAgICAgICAgfVxuICAgICAgICB0b0hleCgpIHtcbiAgICAgICAgICAgIHJldHVybiB1dC5ieXRlc1RvSGV4KHRoaXMudG9SYXdCeXRlcygpKTsgLy8gU2FtZSBhcyB0b1Jhd0J5dGVzLCBidXQgcmV0dXJucyBzdHJpbmcuXG4gICAgICAgIH1cbiAgICB9XG4gICAgUG9pbnQuQkFTRSA9IG5ldyBQb2ludChDVVJWRS5HeCwgQ1VSVkUuR3ksIF8xbiwgbW9kUChDVVJWRS5HeCAqIENVUlZFLkd5KSk7XG4gICAgUG9pbnQuWkVSTyA9IG5ldyBQb2ludChfMG4sIF8xbiwgXzFuLCBfMG4pOyAvLyAwLCAxLCAxLCAwXG4gICAgY29uc3QgeyBCQVNFOiBHLCBaRVJPOiBJIH0gPSBQb2ludDtcbiAgICBjb25zdCB3bmFmID0gd05BRihQb2ludCwgbkJ5dGVMZW5ndGggKiA4KTtcbiAgICBmdW5jdGlvbiBtb2ROKGEpIHtcbiAgICAgICAgcmV0dXJuIG1vZChhLCBDVVJWRV9PUkRFUik7XG4gICAgfVxuICAgIC8vIExpdHRsZS1lbmRpYW4gU0hBNTEyIHdpdGggbW9kdWxvIG5cbiAgICBmdW5jdGlvbiBtb2ROX0xFKGhhc2gpIHtcbiAgICAgICAgcmV0dXJuIG1vZE4odXQuYnl0ZXNUb051bWJlckxFKGhhc2gpKTtcbiAgICB9XG4gICAgLyoqIENvbnZlbmllbmNlIG1ldGhvZCB0aGF0IGNyZWF0ZXMgcHVibGljIGtleSBhbmQgb3RoZXIgc3R1ZmYuIFJGQzgwMzIgNS4xLjUgKi9cbiAgICBmdW5jdGlvbiBnZXRFeHRlbmRlZFB1YmxpY0tleShrZXkpIHtcbiAgICAgICAgY29uc3QgbGVuID0gbkJ5dGVMZW5ndGg7XG4gICAgICAgIGtleSA9IGVuc3VyZUJ5dGVzKCdwcml2YXRlIGtleScsIGtleSwgbGVuKTtcbiAgICAgICAgLy8gSGFzaCBwcml2YXRlIGtleSB3aXRoIGN1cnZlJ3MgaGFzaCBmdW5jdGlvbiB0byBwcm9kdWNlIHVuaWZvcm1pbmdseSByYW5kb20gaW5wdXRcbiAgICAgICAgLy8gQ2hlY2sgYnl0ZSBsZW5ndGhzOiBlbnN1cmUoNjQsIGgoZW5zdXJlKDMyLCBrZXkpKSlcbiAgICAgICAgY29uc3QgaGFzaGVkID0gZW5zdXJlQnl0ZXMoJ2hhc2hlZCBwcml2YXRlIGtleScsIGNIYXNoKGtleSksIDIgKiBsZW4pO1xuICAgICAgICBjb25zdCBoZWFkID0gYWRqdXN0U2NhbGFyQnl0ZXMoaGFzaGVkLnNsaWNlKDAsIGxlbikpOyAvLyBjbGVhciBmaXJzdCBoYWxmIGJpdHMsIHByb2R1Y2UgRkVcbiAgICAgICAgY29uc3QgcHJlZml4ID0gaGFzaGVkLnNsaWNlKGxlbiwgMiAqIGxlbik7IC8vIHNlY29uZCBoYWxmIGlzIGNhbGxlZCBrZXkgcHJlZml4ICg1LjEuNilcbiAgICAgICAgY29uc3Qgc2NhbGFyID0gbW9kTl9MRShoZWFkKTsgLy8gVGhlIGFjdHVhbCBwcml2YXRlIHNjYWxhclxuICAgICAgICBjb25zdCBwb2ludCA9IEcubXVsdGlwbHkoc2NhbGFyKTsgLy8gUG9pbnQgb24gRWR3YXJkcyBjdXJ2ZSBha2EgcHVibGljIGtleVxuICAgICAgICBjb25zdCBwb2ludEJ5dGVzID0gcG9pbnQudG9SYXdCeXRlcygpOyAvLyBVaW50OEFycmF5IHJlcHJlc2VudGF0aW9uXG4gICAgICAgIHJldHVybiB7IGhlYWQsIHByZWZpeCwgc2NhbGFyLCBwb2ludCwgcG9pbnRCeXRlcyB9O1xuICAgIH1cbiAgICAvLyBDYWxjdWxhdGVzIEVkRFNBIHB1YiBrZXkuIFJGQzgwMzIgNS4xLjUuIFByaXZrZXkgaXMgaGFzaGVkLiBVc2UgZmlyc3QgaGFsZiB3aXRoIDMgYml0cyBjbGVhcmVkXG4gICAgZnVuY3Rpb24gZ2V0UHVibGljS2V5KHByaXZLZXkpIHtcbiAgICAgICAgcmV0dXJuIGdldEV4dGVuZGVkUHVibGljS2V5KHByaXZLZXkpLnBvaW50Qnl0ZXM7XG4gICAgfVxuICAgIC8vIGludCgnTEUnLCBTSEE1MTIoZG9tMihGLCBDKSB8fCBtc2dzKSkgbW9kIE5cbiAgICBmdW5jdGlvbiBoYXNoRG9tYWluVG9TY2FsYXIoY29udGV4dCA9IG5ldyBVaW50OEFycmF5KCksIC4uLm1zZ3MpIHtcbiAgICAgICAgY29uc3QgbXNnID0gdXQuY29uY2F0Qnl0ZXMoLi4ubXNncyk7XG4gICAgICAgIHJldHVybiBtb2ROX0xFKGNIYXNoKGRvbWFpbihtc2csIGVuc3VyZUJ5dGVzKCdjb250ZXh0JywgY29udGV4dCksICEhcHJlaGFzaCkpKTtcbiAgICB9XG4gICAgLyoqIFNpZ25zIG1lc3NhZ2Ugd2l0aCBwcml2YXRlS2V5LiBSRkM4MDMyIDUuMS42ICovXG4gICAgZnVuY3Rpb24gc2lnbihtc2csIHByaXZLZXksIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICBtc2cgPSBlbnN1cmVCeXRlcygnbWVzc2FnZScsIG1zZyk7XG4gICAgICAgIGlmIChwcmVoYXNoKVxuICAgICAgICAgICAgbXNnID0gcHJlaGFzaChtc2cpOyAvLyBmb3IgZWQyNTUxOXBoIGV0Yy5cbiAgICAgICAgY29uc3QgeyBwcmVmaXgsIHNjYWxhciwgcG9pbnRCeXRlcyB9ID0gZ2V0RXh0ZW5kZWRQdWJsaWNLZXkocHJpdktleSk7XG4gICAgICAgIGNvbnN0IHIgPSBoYXNoRG9tYWluVG9TY2FsYXIob3B0aW9ucy5jb250ZXh0LCBwcmVmaXgsIG1zZyk7IC8vIHIgPSBkb20yKEYsIEMpIHx8IHByZWZpeCB8fCBQSChNKVxuICAgICAgICBjb25zdCBSID0gRy5tdWx0aXBseShyKS50b1Jhd0J5dGVzKCk7IC8vIFIgPSByR1xuICAgICAgICBjb25zdCBrID0gaGFzaERvbWFpblRvU2NhbGFyKG9wdGlvbnMuY29udGV4dCwgUiwgcG9pbnRCeXRlcywgbXNnKTsgLy8gUiB8fCBBIHx8IFBIKE0pXG4gICAgICAgIGNvbnN0IHMgPSBtb2ROKHIgKyBrICogc2NhbGFyKTsgLy8gUyA9IChyICsgayAqIHMpIG1vZCBMXG4gICAgICAgIGFzc2VydEdFMChzKTsgLy8gMCA8PSBzIDwgbFxuICAgICAgICBjb25zdCByZXMgPSB1dC5jb25jYXRCeXRlcyhSLCB1dC5udW1iZXJUb0J5dGVzTEUocywgRnAuQllURVMpKTtcbiAgICAgICAgcmV0dXJuIGVuc3VyZUJ5dGVzKCdyZXN1bHQnLCByZXMsIG5CeXRlTGVuZ3RoICogMik7IC8vIDY0LWJ5dGUgc2lnbmF0dXJlXG4gICAgfVxuICAgIGNvbnN0IHZlcmlmeU9wdHMgPSBWRVJJRllfREVGQVVMVDtcbiAgICBmdW5jdGlvbiB2ZXJpZnkoc2lnLCBtc2csIHB1YmxpY0tleSwgb3B0aW9ucyA9IHZlcmlmeU9wdHMpIHtcbiAgICAgICAgY29uc3QgeyBjb250ZXh0LCB6aXAyMTUgfSA9IG9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGxlbiA9IEZwLkJZVEVTOyAvLyBWZXJpZmllcyBFZERTQSBzaWduYXR1cmUgYWdhaW5zdCBtZXNzYWdlIGFuZCBwdWJsaWMga2V5LiBSRkM4MDMyIDUuMS43LlxuICAgICAgICBzaWcgPSBlbnN1cmVCeXRlcygnc2lnbmF0dXJlJywgc2lnLCAyICogbGVuKTsgLy8gQW4gZXh0ZW5kZWQgZ3JvdXAgZXF1YXRpb24gaXMgY2hlY2tlZC5cbiAgICAgICAgbXNnID0gZW5zdXJlQnl0ZXMoJ21lc3NhZ2UnLCBtc2cpO1xuICAgICAgICBpZiAocHJlaGFzaClcbiAgICAgICAgICAgIG1zZyA9IHByZWhhc2gobXNnKTsgLy8gZm9yIGVkMjU1MTlwaCwgZXRjXG4gICAgICAgIGNvbnN0IHMgPSB1dC5ieXRlc1RvTnVtYmVyTEUoc2lnLnNsaWNlKGxlbiwgMiAqIGxlbikpO1xuICAgICAgICAvLyB6aXAyMTU6IHRydWUgaXMgZ29vZCBmb3IgY29uc2Vuc3VzLWNyaXRpY2FsIGFwcHMgYW5kIGFsbG93cyBwb2ludHMgPCAyXjI1NlxuICAgICAgICAvLyB6aXAyMTU6IGZhbHNlIGZvbGxvd3MgUkZDODAzMiAvIE5JU1QxODYtNSBhbmQgcmVzdHJpY3RzIHBvaW50cyB0byBDVVJWRS5wXG4gICAgICAgIGxldCBBLCBSLCBTQjtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIEEgPSBQb2ludC5mcm9tSGV4KHB1YmxpY0tleSwgemlwMjE1KTtcbiAgICAgICAgICAgIFIgPSBQb2ludC5mcm9tSGV4KHNpZy5zbGljZSgwLCBsZW4pLCB6aXAyMTUpO1xuICAgICAgICAgICAgU0IgPSBHLm11bHRpcGx5VW5zYWZlKHMpOyAvLyAwIDw9IHMgPCBsIGlzIGRvbmUgaW5zaWRlXG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgayA9IGhhc2hEb21haW5Ub1NjYWxhcihjb250ZXh0LCBSLnRvUmF3Qnl0ZXMoKSwgQS50b1Jhd0J5dGVzKCksIG1zZyk7XG4gICAgICAgIGNvbnN0IFJrQSA9IFIuYWRkKEEubXVsdGlwbHlVbnNhZmUoaykpO1xuICAgICAgICAvLyBbOF1bU11CID0gWzhdUiArIFs4XVtrXUEnXG4gICAgICAgIHJldHVybiBSa0Euc3VidHJhY3QoU0IpLmNsZWFyQ29mYWN0b3IoKS5lcXVhbHMoUG9pbnQuWkVSTyk7XG4gICAgfVxuICAgIEcuX3NldFdpbmRvd1NpemUoOCk7IC8vIEVuYWJsZSBwcmVjb21wdXRlcy4gU2xvd3MgZG93biBmaXJzdCBwdWJsaWNLZXkgY29tcHV0YXRpb24gYnkgMjBtcy5cbiAgICBjb25zdCB1dGlscyA9IHtcbiAgICAgICAgZ2V0RXh0ZW5kZWRQdWJsaWNLZXksXG4gICAgICAgIC8vIGVkMjU1MTkgcHJpdmF0ZSBrZXlzIGFyZSB1bmlmb3JtIDMyYi4gTm8gbmVlZCB0byBjaGVjayBmb3IgbW9kdWxvIGJpYXMsIGxpa2UgaW4gc2VjcDI1NmsxLlxuICAgICAgICByYW5kb21Qcml2YXRlS2V5OiAoKSA9PiByYW5kb21CeXRlcyhGcC5CWVRFUyksXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXZSdyZSBkb2luZyBzY2FsYXIgbXVsdGlwbGljYXRpb24gKHVzZWQgaW4gZ2V0UHVibGljS2V5IGV0Yykgd2l0aCBwcmVjb21wdXRlZCBCQVNFX1BPSU5UXG4gICAgICAgICAqIHZhbHVlcy4gVGhpcyBzbG93cyBkb3duIGZpcnN0IGdldFB1YmxpY0tleSgpIGJ5IG1pbGxpc2Vjb25kcyAoc2VlIFNwZWVkIHNlY3Rpb24pLFxuICAgICAgICAgKiBidXQgYWxsb3dzIHRvIHNwZWVkLXVwIHN1YnNlcXVlbnQgZ2V0UHVibGljS2V5KCkgY2FsbHMgdXAgdG8gMjB4LlxuICAgICAgICAgKiBAcGFyYW0gd2luZG93U2l6ZSAyLCA0LCA4LCAxNlxuICAgICAgICAgKi9cbiAgICAgICAgcHJlY29tcHV0ZSh3aW5kb3dTaXplID0gOCwgcG9pbnQgPSBQb2ludC5CQVNFKSB7XG4gICAgICAgICAgICBwb2ludC5fc2V0V2luZG93U2l6ZSh3aW5kb3dTaXplKTtcbiAgICAgICAgICAgIHBvaW50Lm11bHRpcGx5KEJpZ0ludCgzKSk7XG4gICAgICAgICAgICByZXR1cm4gcG9pbnQ7XG4gICAgICAgIH0sXG4gICAgfTtcbiAgICByZXR1cm4ge1xuICAgICAgICBDVVJWRSxcbiAgICAgICAgZ2V0UHVibGljS2V5LFxuICAgICAgICBzaWduLFxuICAgICAgICB2ZXJpZnksXG4gICAgICAgIEV4dGVuZGVkUG9pbnQ6IFBvaW50LFxuICAgICAgICB1dGlscyxcbiAgICB9O1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZWR3YXJkcy5qcy5tYXAiLCIvKiEgbm9ibGUtY3VydmVzIC0gTUlUIExpY2Vuc2UgKGMpIDIwMjIgUGF1bCBNaWxsZXIgKHBhdWxtaWxsci5jb20pICovXG5pbXBvcnQgeyBtb2QsIHBvdyB9IGZyb20gJy4vbW9kdWxhci5qcyc7XG5pbXBvcnQgeyBieXRlc1RvTnVtYmVyTEUsIGVuc3VyZUJ5dGVzLCBudW1iZXJUb0J5dGVzTEUsIHZhbGlkYXRlT2JqZWN0IH0gZnJvbSAnLi91dGlscy5qcyc7XG5jb25zdCBfMG4gPSBCaWdJbnQoMCk7XG5jb25zdCBfMW4gPSBCaWdJbnQoMSk7XG5mdW5jdGlvbiB2YWxpZGF0ZU9wdHMoY3VydmUpIHtcbiAgICB2YWxpZGF0ZU9iamVjdChjdXJ2ZSwge1xuICAgICAgICBhOiAnYmlnaW50JyxcbiAgICB9LCB7XG4gICAgICAgIG1vbnRnb21lcnlCaXRzOiAnaXNTYWZlSW50ZWdlcicsXG4gICAgICAgIG5CeXRlTGVuZ3RoOiAnaXNTYWZlSW50ZWdlcicsXG4gICAgICAgIGFkanVzdFNjYWxhckJ5dGVzOiAnZnVuY3Rpb24nLFxuICAgICAgICBkb21haW46ICdmdW5jdGlvbicsXG4gICAgICAgIHBvd1BtaW51czI6ICdmdW5jdGlvbicsXG4gICAgICAgIEd1OiAnYmlnaW50JyxcbiAgICB9KTtcbiAgICAvLyBTZXQgZGVmYXVsdHNcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh7IC4uLmN1cnZlIH0pO1xufVxuLy8gTk9URTogbm90IHJlYWxseSBtb250Z29tZXJ5IGN1cnZlLCBqdXN0IGJ1bmNoIG9mIHZlcnkgc3BlY2lmaWMgbWV0aG9kcyBmb3IgWDI1NTE5L1g0NDggKFJGQyA3NzQ4LCBodHRwczovL3d3dy5yZmMtZWRpdG9yLm9yZy9yZmMvcmZjNzc0OClcbi8vIFVzZXMgb25seSBvbmUgY29vcmRpbmF0ZSBpbnN0ZWFkIG9mIHR3b1xuZXhwb3J0IGZ1bmN0aW9uIG1vbnRnb21lcnkoY3VydmVEZWYpIHtcbiAgICBjb25zdCBDVVJWRSA9IHZhbGlkYXRlT3B0cyhjdXJ2ZURlZik7XG4gICAgY29uc3QgeyBQIH0gPSBDVVJWRTtcbiAgICBjb25zdCBtb2RQID0gKG4pID0+IG1vZChuLCBQKTtcbiAgICBjb25zdCBtb250Z29tZXJ5Qml0cyA9IENVUlZFLm1vbnRnb21lcnlCaXRzO1xuICAgIGNvbnN0IG1vbnRnb21lcnlCeXRlcyA9IE1hdGguY2VpbChtb250Z29tZXJ5Qml0cyAvIDgpO1xuICAgIGNvbnN0IGZpZWxkTGVuID0gQ1VSVkUubkJ5dGVMZW5ndGg7XG4gICAgY29uc3QgYWRqdXN0U2NhbGFyQnl0ZXMgPSBDVVJWRS5hZGp1c3RTY2FsYXJCeXRlcyB8fCAoKGJ5dGVzKSA9PiBieXRlcyk7XG4gICAgY29uc3QgcG93UG1pbnVzMiA9IENVUlZFLnBvd1BtaW51czIgfHwgKCh4KSA9PiBwb3coeCwgUCAtIEJpZ0ludCgyKSwgUCkpO1xuICAgIC8vIGNzd2FwIGZyb20gUkZDNzc0OC4gQnV0IGl0IGlzIG5vdCBmcm9tIFJGQzc3NDghXG4gICAgLypcbiAgICAgIGNzd2FwKHN3YXAsIHhfMiwgeF8zKTpcbiAgICAgICAgICAgZHVtbXkgPSBtYXNrKHN3YXApIEFORCAoeF8yIFhPUiB4XzMpXG4gICAgICAgICAgIHhfMiA9IHhfMiBYT1IgZHVtbXlcbiAgICAgICAgICAgeF8zID0geF8zIFhPUiBkdW1teVxuICAgICAgICAgICBSZXR1cm4gKHhfMiwgeF8zKVxuICAgIFdoZXJlIG1hc2soc3dhcCkgaXMgdGhlIGFsbC0xIG9yIGFsbC0wIHdvcmQgb2YgdGhlIHNhbWUgbGVuZ3RoIGFzIHhfMlxuICAgICBhbmQgeF8zLCBjb21wdXRlZCwgZS5nLiwgYXMgbWFzayhzd2FwKSA9IDAgLSBzd2FwLlxuICAgICovXG4gICAgZnVuY3Rpb24gY3N3YXAoc3dhcCwgeF8yLCB4XzMpIHtcbiAgICAgICAgY29uc3QgZHVtbXkgPSBtb2RQKHN3YXAgKiAoeF8yIC0geF8zKSk7XG4gICAgICAgIHhfMiA9IG1vZFAoeF8yIC0gZHVtbXkpO1xuICAgICAgICB4XzMgPSBtb2RQKHhfMyArIGR1bW15KTtcbiAgICAgICAgcmV0dXJuIFt4XzIsIHhfM107XG4gICAgfVxuICAgIC8vIEFjY2VwdHMgMCBhcyB3ZWxsXG4gICAgZnVuY3Rpb24gYXNzZXJ0RmllbGRFbGVtZW50KG4pIHtcbiAgICAgICAgaWYgKHR5cGVvZiBuID09PSAnYmlnaW50JyAmJiBfMG4gPD0gbiAmJiBuIDwgUClcbiAgICAgICAgICAgIHJldHVybiBuO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGVjdGVkIHZhbGlkIHNjYWxhciAwIDwgc2NhbGFyIDwgQ1VSVkUuUCcpO1xuICAgIH1cbiAgICAvLyB4MjU1MTkgZnJvbSA0XG4gICAgLy8gVGhlIGNvbnN0YW50IGEyNCBpcyAoNDg2NjYyIC0gMikgLyA0ID0gMTIxNjY1IGZvciBjdXJ2ZTI1NTE5L1gyNTUxOVxuICAgIGNvbnN0IGEyNCA9IChDVVJWRS5hIC0gQmlnSW50KDIpKSAvIEJpZ0ludCg0KTtcbiAgICAvKipcbiAgICAgKlxuICAgICAqIEBwYXJhbSBwb2ludFUgdSBjb29yZGluYXRlICh4KSBvbiBNb250Z29tZXJ5IEN1cnZlIDI1NTE5XG4gICAgICogQHBhcmFtIHNjYWxhciBieSB3aGljaCB0aGUgcG9pbnQgd291bGQgYmUgbXVsdGlwbGllZFxuICAgICAqIEByZXR1cm5zIG5ldyBQb2ludCBvbiBNb250Z29tZXJ5IGN1cnZlXG4gICAgICovXG4gICAgZnVuY3Rpb24gbW9udGdvbWVyeUxhZGRlcihwb2ludFUsIHNjYWxhcikge1xuICAgICAgICBjb25zdCB1ID0gYXNzZXJ0RmllbGRFbGVtZW50KHBvaW50VSk7XG4gICAgICAgIC8vIFNlY3Rpb24gNTogSW1wbGVtZW50YXRpb25zIE1VU1QgYWNjZXB0IG5vbi1jYW5vbmljYWwgdmFsdWVzIGFuZCBwcm9jZXNzIHRoZW0gYXNcbiAgICAgICAgLy8gaWYgdGhleSBoYWQgYmVlbiByZWR1Y2VkIG1vZHVsbyB0aGUgZmllbGQgcHJpbWUuXG4gICAgICAgIGNvbnN0IGsgPSBhc3NlcnRGaWVsZEVsZW1lbnQoc2NhbGFyKTtcbiAgICAgICAgY29uc3QgeF8xID0gdTtcbiAgICAgICAgbGV0IHhfMiA9IF8xbjtcbiAgICAgICAgbGV0IHpfMiA9IF8wbjtcbiAgICAgICAgbGV0IHhfMyA9IHU7XG4gICAgICAgIGxldCB6XzMgPSBfMW47XG4gICAgICAgIGxldCBzd2FwID0gXzBuO1xuICAgICAgICBsZXQgc3c7XG4gICAgICAgIGZvciAobGV0IHQgPSBCaWdJbnQobW9udGdvbWVyeUJpdHMgLSAxKTsgdCA+PSBfMG47IHQtLSkge1xuICAgICAgICAgICAgY29uc3Qga190ID0gKGsgPj4gdCkgJiBfMW47XG4gICAgICAgICAgICBzd2FwIF49IGtfdDtcbiAgICAgICAgICAgIHN3ID0gY3N3YXAoc3dhcCwgeF8yLCB4XzMpO1xuICAgICAgICAgICAgeF8yID0gc3dbMF07XG4gICAgICAgICAgICB4XzMgPSBzd1sxXTtcbiAgICAgICAgICAgIHN3ID0gY3N3YXAoc3dhcCwgel8yLCB6XzMpO1xuICAgICAgICAgICAgel8yID0gc3dbMF07XG4gICAgICAgICAgICB6XzMgPSBzd1sxXTtcbiAgICAgICAgICAgIHN3YXAgPSBrX3Q7XG4gICAgICAgICAgICBjb25zdCBBID0geF8yICsgel8yO1xuICAgICAgICAgICAgY29uc3QgQUEgPSBtb2RQKEEgKiBBKTtcbiAgICAgICAgICAgIGNvbnN0IEIgPSB4XzIgLSB6XzI7XG4gICAgICAgICAgICBjb25zdCBCQiA9IG1vZFAoQiAqIEIpO1xuICAgICAgICAgICAgY29uc3QgRSA9IEFBIC0gQkI7XG4gICAgICAgICAgICBjb25zdCBDID0geF8zICsgel8zO1xuICAgICAgICAgICAgY29uc3QgRCA9IHhfMyAtIHpfMztcbiAgICAgICAgICAgIGNvbnN0IERBID0gbW9kUChEICogQSk7XG4gICAgICAgICAgICBjb25zdCBDQiA9IG1vZFAoQyAqIEIpO1xuICAgICAgICAgICAgY29uc3QgZGFjYiA9IERBICsgQ0I7XG4gICAgICAgICAgICBjb25zdCBkYV9jYiA9IERBIC0gQ0I7XG4gICAgICAgICAgICB4XzMgPSBtb2RQKGRhY2IgKiBkYWNiKTtcbiAgICAgICAgICAgIHpfMyA9IG1vZFAoeF8xICogbW9kUChkYV9jYiAqIGRhX2NiKSk7XG4gICAgICAgICAgICB4XzIgPSBtb2RQKEFBICogQkIpO1xuICAgICAgICAgICAgel8yID0gbW9kUChFICogKEFBICsgbW9kUChhMjQgKiBFKSkpO1xuICAgICAgICB9XG4gICAgICAgIC8vICh4XzIsIHhfMykgPSBjc3dhcChzd2FwLCB4XzIsIHhfMylcbiAgICAgICAgc3cgPSBjc3dhcChzd2FwLCB4XzIsIHhfMyk7XG4gICAgICAgIHhfMiA9IHN3WzBdO1xuICAgICAgICB4XzMgPSBzd1sxXTtcbiAgICAgICAgLy8gKHpfMiwgel8zKSA9IGNzd2FwKHN3YXAsIHpfMiwgel8zKVxuICAgICAgICBzdyA9IGNzd2FwKHN3YXAsIHpfMiwgel8zKTtcbiAgICAgICAgel8yID0gc3dbMF07XG4gICAgICAgIHpfMyA9IHN3WzFdO1xuICAgICAgICAvLyB6XzJeKHAgLSAyKVxuICAgICAgICBjb25zdCB6MiA9IHBvd1BtaW51czIoel8yKTtcbiAgICAgICAgLy8gUmV0dXJuIHhfMiAqICh6XzJeKHAgLSAyKSlcbiAgICAgICAgcmV0dXJuIG1vZFAoeF8yICogejIpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBlbmNvZGVVQ29vcmRpbmF0ZSh1KSB7XG4gICAgICAgIHJldHVybiBudW1iZXJUb0J5dGVzTEUobW9kUCh1KSwgbW9udGdvbWVyeUJ5dGVzKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZGVjb2RlVUNvb3JkaW5hdGUodUVuYykge1xuICAgICAgICAvLyBTZWN0aW9uIDU6IFdoZW4gcmVjZWl2aW5nIHN1Y2ggYW4gYXJyYXksIGltcGxlbWVudGF0aW9ucyBvZiBYMjU1MTlcbiAgICAgICAgLy8gTVVTVCBtYXNrIHRoZSBtb3N0IHNpZ25pZmljYW50IGJpdCBpbiB0aGUgZmluYWwgYnl0ZS5cbiAgICAgICAgLy8gVGhpcyBpcyB2ZXJ5IHVnbHkgd2F5LCBidXQgaXQgd29ya3MgYmVjYXVzZSBmaWVsZExlbi0xIGlzIG91dHNpZGUgb2YgYm91bmRzIGZvciBYNDQ4LCBzbyB0aGlzIGJlY29tZXMgTk9PUFxuICAgICAgICAvLyBmaWVsZExlbiAtIHNjYWxhcnlCeXRlcyA9IDEgZm9yIFg0NDggYW5kID0gMCBmb3IgWDI1NTE5XG4gICAgICAgIGNvbnN0IHUgPSBlbnN1cmVCeXRlcygndSBjb29yZGluYXRlJywgdUVuYywgbW9udGdvbWVyeUJ5dGVzKTtcbiAgICAgICAgLy8gdVtmaWVsZExlbi0xXSBjcmFzaGVzIFF1aWNrSlMgKFR5cGVFcnJvcjogb3V0LW9mLWJvdW5kIG51bWVyaWMgaW5kZXgpXG4gICAgICAgIGlmIChmaWVsZExlbiA9PT0gbW9udGdvbWVyeUJ5dGVzKVxuICAgICAgICAgICAgdVtmaWVsZExlbiAtIDFdICY9IDEyNzsgLy8gMGIwMTExXzExMTFcbiAgICAgICAgcmV0dXJuIGJ5dGVzVG9OdW1iZXJMRSh1KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZGVjb2RlU2NhbGFyKG4pIHtcbiAgICAgICAgY29uc3QgYnl0ZXMgPSBlbnN1cmVCeXRlcygnc2NhbGFyJywgbik7XG4gICAgICAgIGlmIChieXRlcy5sZW5ndGggIT09IG1vbnRnb21lcnlCeXRlcyAmJiBieXRlcy5sZW5ndGggIT09IGZpZWxkTGVuKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCAke21vbnRnb21lcnlCeXRlc30gb3IgJHtmaWVsZExlbn0gYnl0ZXMsIGdvdCAke2J5dGVzLmxlbmd0aH1gKTtcbiAgICAgICAgcmV0dXJuIGJ5dGVzVG9OdW1iZXJMRShhZGp1c3RTY2FsYXJCeXRlcyhieXRlcykpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBzY2FsYXJNdWx0KHNjYWxhciwgdSkge1xuICAgICAgICBjb25zdCBwb2ludFUgPSBkZWNvZGVVQ29vcmRpbmF0ZSh1KTtcbiAgICAgICAgY29uc3QgX3NjYWxhciA9IGRlY29kZVNjYWxhcihzY2FsYXIpO1xuICAgICAgICBjb25zdCBwdSA9IG1vbnRnb21lcnlMYWRkZXIocG9pbnRVLCBfc2NhbGFyKTtcbiAgICAgICAgLy8gVGhlIHJlc3VsdCB3YXMgbm90IGNvbnRyaWJ1dG9yeVxuICAgICAgICAvLyBodHRwczovL2NyLnlwLnRvL2VjZGguaHRtbCN2YWxpZGF0ZVxuICAgICAgICBpZiAocHUgPT09IF8wbilcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBwcml2YXRlIG9yIHB1YmxpYyBrZXkgcmVjZWl2ZWQnKTtcbiAgICAgICAgcmV0dXJuIGVuY29kZVVDb29yZGluYXRlKHB1KTtcbiAgICB9XG4gICAgLy8gQ29tcHV0ZXMgcHVibGljIGtleSBmcm9tIHByaXZhdGUuIEJ5IGRvaW5nIHNjYWxhciBtdWx0aXBsaWNhdGlvbiBvZiBiYXNlIHBvaW50LlxuICAgIGNvbnN0IEd1Qnl0ZXMgPSBlbmNvZGVVQ29vcmRpbmF0ZShDVVJWRS5HdSk7XG4gICAgZnVuY3Rpb24gc2NhbGFyTXVsdEJhc2Uoc2NhbGFyKSB7XG4gICAgICAgIHJldHVybiBzY2FsYXJNdWx0KHNjYWxhciwgR3VCeXRlcyk7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIHNjYWxhck11bHQsXG4gICAgICAgIHNjYWxhck11bHRCYXNlLFxuICAgICAgICBnZXRTaGFyZWRTZWNyZXQ6IChwcml2YXRlS2V5LCBwdWJsaWNLZXkpID0+IHNjYWxhck11bHQocHJpdmF0ZUtleSwgcHVibGljS2V5KSxcbiAgICAgICAgZ2V0UHVibGljS2V5OiAocHJpdmF0ZUtleSkgPT4gc2NhbGFyTXVsdEJhc2UocHJpdmF0ZUtleSksXG4gICAgICAgIHV0aWxzOiB7IHJhbmRvbVByaXZhdGVLZXk6ICgpID0+IENVUlZFLnJhbmRvbUJ5dGVzKENVUlZFLm5CeXRlTGVuZ3RoKSB9LFxuICAgICAgICBHdUJ5dGVzOiBHdUJ5dGVzLFxuICAgIH07XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1tb250Z29tZXJ5LmpzLm1hcCIsImltcG9ydCB7IG1vZCB9IGZyb20gJy4vbW9kdWxhci5qcyc7XG5pbXBvcnQgeyBieXRlc1RvTnVtYmVyQkUsIGNvbmNhdEJ5dGVzLCB1dGY4VG9CeXRlcywgdmFsaWRhdGVPYmplY3QgfSBmcm9tICcuL3V0aWxzLmpzJztcbmZ1bmN0aW9uIHZhbGlkYXRlRFNUKGRzdCkge1xuICAgIGlmIChkc3QgaW5zdGFuY2VvZiBVaW50OEFycmF5KVxuICAgICAgICByZXR1cm4gZHN0O1xuICAgIGlmICh0eXBlb2YgZHN0ID09PSAnc3RyaW5nJylcbiAgICAgICAgcmV0dXJuIHV0ZjhUb0J5dGVzKGRzdCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdEU1QgbXVzdCBiZSBVaW50OEFycmF5IG9yIHN0cmluZycpO1xufVxuLy8gT2N0ZXQgU3RyZWFtIHRvIEludGVnZXIuIFwic3BlY1wiIGltcGxlbWVudGF0aW9uIG9mIG9zMmlwIGlzIDIuNXggc2xvd2VyIHZzIGJ5dGVzVG9OdW1iZXJCRS5cbmNvbnN0IG9zMmlwID0gYnl0ZXNUb051bWJlckJFO1xuLy8gSW50ZWdlciB0byBPY3RldCBTdHJlYW0gKG51bWJlclRvQnl0ZXNCRSlcbmZ1bmN0aW9uIGkyb3NwKHZhbHVlLCBsZW5ndGgpIHtcbiAgICBpZiAodmFsdWUgPCAwIHx8IHZhbHVlID49IDEgPDwgKDggKiBsZW5ndGgpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgYmFkIEkyT1NQIGNhbGw6IHZhbHVlPSR7dmFsdWV9IGxlbmd0aD0ke2xlbmd0aH1gKTtcbiAgICB9XG4gICAgY29uc3QgcmVzID0gQXJyYXkuZnJvbSh7IGxlbmd0aCB9KS5maWxsKDApO1xuICAgIGZvciAobGV0IGkgPSBsZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICByZXNbaV0gPSB2YWx1ZSAmIDB4ZmY7XG4gICAgICAgIHZhbHVlID4+Pj0gODtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KHJlcyk7XG59XG5mdW5jdGlvbiBzdHJ4b3IoYSwgYikge1xuICAgIGNvbnN0IGFyciA9IG5ldyBVaW50OEFycmF5KGEubGVuZ3RoKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXJyW2ldID0gYVtpXSBeIGJbaV07XG4gICAgfVxuICAgIHJldHVybiBhcnI7XG59XG5mdW5jdGlvbiBpc0J5dGVzKGl0ZW0pIHtcbiAgICBpZiAoIShpdGVtIGluc3RhbmNlb2YgVWludDhBcnJheSkpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVWludDhBcnJheSBleHBlY3RlZCcpO1xufVxuZnVuY3Rpb24gaXNOdW0oaXRlbSkge1xuICAgIGlmICghTnVtYmVyLmlzU2FmZUludGVnZXIoaXRlbSkpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignbnVtYmVyIGV4cGVjdGVkJyk7XG59XG4vLyBQcm9kdWNlcyBhIHVuaWZvcm1seSByYW5kb20gYnl0ZSBzdHJpbmcgdXNpbmcgYSBjcnlwdG9ncmFwaGljIGhhc2ggZnVuY3Rpb24gSCB0aGF0IG91dHB1dHMgYiBiaXRzXG4vLyBodHRwczovL2RhdGF0cmFja2VyLmlldGYub3JnL2RvYy9odG1sL2RyYWZ0LWlydGYtY2ZyZy1oYXNoLXRvLWN1cnZlLTExI3NlY3Rpb24tNS40LjFcbmV4cG9ydCBmdW5jdGlvbiBleHBhbmRfbWVzc2FnZV94bWQobXNnLCBEU1QsIGxlbkluQnl0ZXMsIEgpIHtcbiAgICBpc0J5dGVzKG1zZyk7XG4gICAgaXNCeXRlcyhEU1QpO1xuICAgIGlzTnVtKGxlbkluQnl0ZXMpO1xuICAgIC8vIGh0dHBzOi8vZGF0YXRyYWNrZXIuaWV0Zi5vcmcvZG9jL2h0bWwvZHJhZnQtaXJ0Zi1jZnJnLWhhc2gtdG8tY3VydmUtMTYjc2VjdGlvbi01LjMuM1xuICAgIGlmIChEU1QubGVuZ3RoID4gMjU1KVxuICAgICAgICBEU1QgPSBIKGNvbmNhdEJ5dGVzKHV0ZjhUb0J5dGVzKCdIMkMtT1ZFUlNJWkUtRFNULScpLCBEU1QpKTtcbiAgICBjb25zdCB7IG91dHB1dExlbjogYl9pbl9ieXRlcywgYmxvY2tMZW46IHJfaW5fYnl0ZXMgfSA9IEg7XG4gICAgY29uc3QgZWxsID0gTWF0aC5jZWlsKGxlbkluQnl0ZXMgLyBiX2luX2J5dGVzKTtcbiAgICBpZiAoZWxsID4gMjU1KVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgeG1kIGxlbmd0aCcpO1xuICAgIGNvbnN0IERTVF9wcmltZSA9IGNvbmNhdEJ5dGVzKERTVCwgaTJvc3AoRFNULmxlbmd0aCwgMSkpO1xuICAgIGNvbnN0IFpfcGFkID0gaTJvc3AoMCwgcl9pbl9ieXRlcyk7XG4gICAgY29uc3QgbF9pX2Jfc3RyID0gaTJvc3AobGVuSW5CeXRlcywgMik7IC8vIGxlbl9pbl9ieXRlc19zdHJcbiAgICBjb25zdCBiID0gbmV3IEFycmF5KGVsbCk7XG4gICAgY29uc3QgYl8wID0gSChjb25jYXRCeXRlcyhaX3BhZCwgbXNnLCBsX2lfYl9zdHIsIGkyb3NwKDAsIDEpLCBEU1RfcHJpbWUpKTtcbiAgICBiWzBdID0gSChjb25jYXRCeXRlcyhiXzAsIGkyb3NwKDEsIDEpLCBEU1RfcHJpbWUpKTtcbiAgICBmb3IgKGxldCBpID0gMTsgaSA8PSBlbGw7IGkrKykge1xuICAgICAgICBjb25zdCBhcmdzID0gW3N0cnhvcihiXzAsIGJbaSAtIDFdKSwgaTJvc3AoaSArIDEsIDEpLCBEU1RfcHJpbWVdO1xuICAgICAgICBiW2ldID0gSChjb25jYXRCeXRlcyguLi5hcmdzKSk7XG4gICAgfVxuICAgIGNvbnN0IHBzZXVkb19yYW5kb21fYnl0ZXMgPSBjb25jYXRCeXRlcyguLi5iKTtcbiAgICByZXR1cm4gcHNldWRvX3JhbmRvbV9ieXRlcy5zbGljZSgwLCBsZW5JbkJ5dGVzKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBleHBhbmRfbWVzc2FnZV94b2YobXNnLCBEU1QsIGxlbkluQnl0ZXMsIGssIEgpIHtcbiAgICBpc0J5dGVzKG1zZyk7XG4gICAgaXNCeXRlcyhEU1QpO1xuICAgIGlzTnVtKGxlbkluQnl0ZXMpO1xuICAgIC8vIGh0dHBzOi8vZGF0YXRyYWNrZXIuaWV0Zi5vcmcvZG9jL2h0bWwvZHJhZnQtaXJ0Zi1jZnJnLWhhc2gtdG8tY3VydmUtMTYjc2VjdGlvbi01LjMuM1xuICAgIC8vIERTVCA9IEgoJ0gyQy1PVkVSU0laRS1EU1QtJyB8fCBhX3ZlcnlfbG9uZ19EU1QsIE1hdGguY2VpbCgobGVuSW5CeXRlcyAqIGspIC8gOCkpO1xuICAgIGlmIChEU1QubGVuZ3RoID4gMjU1KSB7XG4gICAgICAgIGNvbnN0IGRrTGVuID0gTWF0aC5jZWlsKCgyICogaykgLyA4KTtcbiAgICAgICAgRFNUID0gSC5jcmVhdGUoeyBka0xlbiB9KS51cGRhdGUodXRmOFRvQnl0ZXMoJ0gyQy1PVkVSU0laRS1EU1QtJykpLnVwZGF0ZShEU1QpLmRpZ2VzdCgpO1xuICAgIH1cbiAgICBpZiAobGVuSW5CeXRlcyA+IDY1NTM1IHx8IERTVC5sZW5ndGggPiAyNTUpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZXhwYW5kX21lc3NhZ2VfeG9mOiBpbnZhbGlkIGxlbkluQnl0ZXMnKTtcbiAgICByZXR1cm4gKEguY3JlYXRlKHsgZGtMZW46IGxlbkluQnl0ZXMgfSlcbiAgICAgICAgLnVwZGF0ZShtc2cpXG4gICAgICAgIC51cGRhdGUoaTJvc3AobGVuSW5CeXRlcywgMikpXG4gICAgICAgIC8vIDIuIERTVF9wcmltZSA9IERTVCB8fCBJMk9TUChsZW4oRFNUKSwgMSlcbiAgICAgICAgLnVwZGF0ZShEU1QpXG4gICAgICAgIC51cGRhdGUoaTJvc3AoRFNULmxlbmd0aCwgMSkpXG4gICAgICAgIC5kaWdlc3QoKSk7XG59XG4vKipcbiAqIEhhc2hlcyBhcmJpdHJhcnktbGVuZ3RoIGJ5dGUgc3RyaW5ncyB0byBhIGxpc3Qgb2Ygb25lIG9yIG1vcmUgZWxlbWVudHMgb2YgYSBmaW5pdGUgZmllbGQgRlxuICogaHR0cHM6Ly9kYXRhdHJhY2tlci5pZXRmLm9yZy9kb2MvaHRtbC9kcmFmdC1pcnRmLWNmcmctaGFzaC10by1jdXJ2ZS0xMSNzZWN0aW9uLTUuM1xuICogQHBhcmFtIG1zZyBhIGJ5dGUgc3RyaW5nIGNvbnRhaW5pbmcgdGhlIG1lc3NhZ2UgdG8gaGFzaFxuICogQHBhcmFtIGNvdW50IHRoZSBudW1iZXIgb2YgZWxlbWVudHMgb2YgRiB0byBvdXRwdXRcbiAqIEBwYXJhbSBvcHRpb25zIGB7RFNUOiBzdHJpbmcsIHA6IGJpZ2ludCwgbTogbnVtYmVyLCBrOiBudW1iZXIsIGV4cGFuZDogJ3htZCcgfCAneG9mJywgaGFzaDogSH1gLCBzZWUgYWJvdmVcbiAqIEByZXR1cm5zIFt1XzAsIC4uLiwgdV8oY291bnQgLSAxKV0sIGEgbGlzdCBvZiBmaWVsZCBlbGVtZW50cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc2hfdG9fZmllbGQobXNnLCBjb3VudCwgb3B0aW9ucykge1xuICAgIHZhbGlkYXRlT2JqZWN0KG9wdGlvbnMsIHtcbiAgICAgICAgRFNUOiAnc3RyaW5nJyxcbiAgICAgICAgcDogJ2JpZ2ludCcsXG4gICAgICAgIG06ICdpc1NhZmVJbnRlZ2VyJyxcbiAgICAgICAgazogJ2lzU2FmZUludGVnZXInLFxuICAgICAgICBoYXNoOiAnaGFzaCcsXG4gICAgfSk7XG4gICAgY29uc3QgeyBwLCBrLCBtLCBoYXNoLCBleHBhbmQsIERTVDogX0RTVCB9ID0gb3B0aW9ucztcbiAgICBpc0J5dGVzKG1zZyk7XG4gICAgaXNOdW0oY291bnQpO1xuICAgIGNvbnN0IERTVCA9IHZhbGlkYXRlRFNUKF9EU1QpO1xuICAgIGNvbnN0IGxvZzJwID0gcC50b1N0cmluZygyKS5sZW5ndGg7XG4gICAgY29uc3QgTCA9IE1hdGguY2VpbCgobG9nMnAgKyBrKSAvIDgpOyAvLyBzZWN0aW9uIDUuMSBvZiBpZXRmIGRyYWZ0IGxpbmsgYWJvdmVcbiAgICBjb25zdCBsZW5faW5fYnl0ZXMgPSBjb3VudCAqIG0gKiBMO1xuICAgIGxldCBwcmI7IC8vIHBzZXVkb19yYW5kb21fYnl0ZXNcbiAgICBpZiAoZXhwYW5kID09PSAneG1kJykge1xuICAgICAgICBwcmIgPSBleHBhbmRfbWVzc2FnZV94bWQobXNnLCBEU1QsIGxlbl9pbl9ieXRlcywgaGFzaCk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGV4cGFuZCA9PT0gJ3hvZicpIHtcbiAgICAgICAgcHJiID0gZXhwYW5kX21lc3NhZ2VfeG9mKG1zZywgRFNULCBsZW5faW5fYnl0ZXMsIGssIGhhc2gpO1xuICAgIH1cbiAgICBlbHNlIGlmIChleHBhbmQgPT09ICdfaW50ZXJuYWxfcGFzcycpIHtcbiAgICAgICAgLy8gZm9yIGludGVybmFsIHRlc3RzIG9ubHlcbiAgICAgICAgcHJiID0gbXNnO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdleHBhbmQgbXVzdCBiZSBcInhtZFwiIG9yIFwieG9mXCInKTtcbiAgICB9XG4gICAgY29uc3QgdSA9IG5ldyBBcnJheShjb3VudCk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGUgPSBuZXcgQXJyYXkobSk7XG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgbTsgaisrKSB7XG4gICAgICAgICAgICBjb25zdCBlbG1fb2Zmc2V0ID0gTCAqIChqICsgaSAqIG0pO1xuICAgICAgICAgICAgY29uc3QgdHYgPSBwcmIuc3ViYXJyYXkoZWxtX29mZnNldCwgZWxtX29mZnNldCArIEwpO1xuICAgICAgICAgICAgZVtqXSA9IG1vZChvczJpcCh0diksIHApO1xuICAgICAgICB9XG4gICAgICAgIHVbaV0gPSBlO1xuICAgIH1cbiAgICByZXR1cm4gdTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBpc29nZW55TWFwKGZpZWxkLCBtYXApIHtcbiAgICAvLyBNYWtlIHNhbWUgb3JkZXIgYXMgaW4gc3BlY1xuICAgIGNvbnN0IENPRUZGID0gbWFwLm1hcCgoaSkgPT4gQXJyYXkuZnJvbShpKS5yZXZlcnNlKCkpO1xuICAgIHJldHVybiAoeCwgeSkgPT4ge1xuICAgICAgICBjb25zdCBbeE51bSwgeERlbiwgeU51bSwgeURlbl0gPSBDT0VGRi5tYXAoKHZhbCkgPT4gdmFsLnJlZHVjZSgoYWNjLCBpKSA9PiBmaWVsZC5hZGQoZmllbGQubXVsKGFjYywgeCksIGkpKSk7XG4gICAgICAgIHggPSBmaWVsZC5kaXYoeE51bSwgeERlbik7IC8vIHhOdW0gLyB4RGVuXG4gICAgICAgIHkgPSBmaWVsZC5tdWwoeSwgZmllbGQuZGl2KHlOdW0sIHlEZW4pKTsgLy8geSAqICh5TnVtIC8geURldilcbiAgICAgICAgcmV0dXJuIHsgeCwgeSB9O1xuICAgIH07XG59XG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlSGFzaGVyKFBvaW50LCBtYXBUb0N1cnZlLCBkZWYpIHtcbiAgICBpZiAodHlwZW9mIG1hcFRvQ3VydmUgIT09ICdmdW5jdGlvbicpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignbWFwVG9DdXJ2ZSgpIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIHJldHVybiB7XG4gICAgICAgIC8vIEVuY29kZXMgYnl0ZSBzdHJpbmcgdG8gZWxsaXB0aWMgY3VydmVcbiAgICAgICAgLy8gaHR0cHM6Ly9kYXRhdHJhY2tlci5pZXRmLm9yZy9kb2MvaHRtbC9kcmFmdC1pcnRmLWNmcmctaGFzaC10by1jdXJ2ZS0xNiNzZWN0aW9uLTNcbiAgICAgICAgaGFzaFRvQ3VydmUobXNnLCBvcHRpb25zKSB7XG4gICAgICAgICAgICBjb25zdCB1ID0gaGFzaF90b19maWVsZChtc2csIDIsIHsgLi4uZGVmLCBEU1Q6IGRlZi5EU1QsIC4uLm9wdGlvbnMgfSk7XG4gICAgICAgICAgICBjb25zdCB1MCA9IFBvaW50LmZyb21BZmZpbmUobWFwVG9DdXJ2ZSh1WzBdKSk7XG4gICAgICAgICAgICBjb25zdCB1MSA9IFBvaW50LmZyb21BZmZpbmUobWFwVG9DdXJ2ZSh1WzFdKSk7XG4gICAgICAgICAgICBjb25zdCBQID0gdTAuYWRkKHUxKS5jbGVhckNvZmFjdG9yKCk7XG4gICAgICAgICAgICBQLmFzc2VydFZhbGlkaXR5KCk7XG4gICAgICAgICAgICByZXR1cm4gUDtcbiAgICAgICAgfSxcbiAgICAgICAgLy8gaHR0cHM6Ly9kYXRhdHJhY2tlci5pZXRmLm9yZy9kb2MvaHRtbC9kcmFmdC1pcnRmLWNmcmctaGFzaC10by1jdXJ2ZS0xNiNzZWN0aW9uLTNcbiAgICAgICAgZW5jb2RlVG9DdXJ2ZShtc2csIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGNvbnN0IHUgPSBoYXNoX3RvX2ZpZWxkKG1zZywgMSwgeyAuLi5kZWYsIERTVDogZGVmLmVuY29kZURTVCwgLi4ub3B0aW9ucyB9KTtcbiAgICAgICAgICAgIGNvbnN0IFAgPSBQb2ludC5mcm9tQWZmaW5lKG1hcFRvQ3VydmUodVswXSkpLmNsZWFyQ29mYWN0b3IoKTtcbiAgICAgICAgICAgIFAuYXNzZXJ0VmFsaWRpdHkoKTtcbiAgICAgICAgICAgIHJldHVybiBQO1xuICAgICAgICB9LFxuICAgIH07XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1oYXNoLXRvLWN1cnZlLmpzLm1hcCIsIi8qISBub2JsZS1jdXJ2ZXMgLSBNSVQgTGljZW5zZSAoYykgMjAyMiBQYXVsIE1pbGxlciAocGF1bG1pbGxyLmNvbSkgKi9cbmltcG9ydCB7IHNoYWtlMjU2IH0gZnJvbSAnQG5vYmxlL2hhc2hlcy9zaGEzJztcbmltcG9ydCB7IGNvbmNhdEJ5dGVzLCByYW5kb21CeXRlcywgdXRmOFRvQnl0ZXMsIHdyYXBDb25zdHJ1Y3RvciB9IGZyb20gJ0Bub2JsZS9oYXNoZXMvdXRpbHMnO1xuaW1wb3J0IHsgdHdpc3RlZEVkd2FyZHMgfSBmcm9tICcuL2Fic3RyYWN0L2Vkd2FyZHMuanMnO1xuaW1wb3J0IHsgbW9kLCBwb3cyLCBGaWVsZCB9IGZyb20gJy4vYWJzdHJhY3QvbW9kdWxhci5qcyc7XG5pbXBvcnQgeyBtb250Z29tZXJ5IH0gZnJvbSAnLi9hYnN0cmFjdC9tb250Z29tZXJ5LmpzJztcbmltcG9ydCAqIGFzIGh0ZiBmcm9tICcuL2Fic3RyYWN0L2hhc2gtdG8tY3VydmUuanMnO1xuLyoqXG4gKiBFZHdhcmRzNDQ4IChub3QgRWQ0NDgtR29sZGlsb2NrcykgY3VydmUgd2l0aCBmb2xsb3dpbmcgYWRkb25zOlxuICogKiBYNDQ4IEVDREhcbiAqIENvbmZvcm1zIHRvIFJGQyA4MDMyIGh0dHBzOi8vd3d3LnJmYy1lZGl0b3Iub3JnL3JmYy9yZmM4MDMyLmh0bWwjc2VjdGlvbi01LjJcbiAqL1xuY29uc3Qgc2hha2UyNTZfMTE0ID0gd3JhcENvbnN0cnVjdG9yKCgpID0+IHNoYWtlMjU2LmNyZWF0ZSh7IGRrTGVuOiAxMTQgfSkpO1xuY29uc3Qgc2hha2UyNTZfNjQgPSB3cmFwQ29uc3RydWN0b3IoKCkgPT4gc2hha2UyNTYuY3JlYXRlKHsgZGtMZW46IDY0IH0pKTtcbmNvbnN0IGVkNDQ4UCA9IEJpZ0ludCgnNzI2ODM4NzI0Mjk1NjA2ODkwNTQ5MzIzODA3ODg4MDA0NTM0MzUzNjQxMzYwNjg3MzE4MDYwMjgxNDkwMTk5MTgwNjEyMzI4MTY2NzMwNzcyNjg2Mzk2MzgzNjk4Njc2NTQ1OTMwMDg4ODg0NDYxODQzNjM3MzYxMDUzNDk4MDE4MzY1NDM5Jyk7XG4vLyBwb3dQbWludXMzZGl2NCBjYWxjdWxhdGVzIHogPSB4XmsgbW9kIHAsIHdoZXJlIGsgPSAocC0zKS80LlxuLy8gVXNlZCBmb3IgZWZmaWNpZW50IHNxdWFyZSByb290IGNhbGN1bGF0aW9uLlxuLy8gKChQLTMpLzQpLnRvU3RyaW5nKDIpIHdvdWxkIHByb2R1Y2UgYml0cyBbMjIzeCAxLCAwLCAyMjJ4IDFdXG5mdW5jdGlvbiBlZDQ0OF9wb3dfUG1pbnVzM2RpdjQoeCkge1xuICAgIGNvbnN0IFAgPSBlZDQ0OFA7XG4gICAgLy8gcHJldHRpZXItaWdub3JlXG4gICAgY29uc3QgXzFuID0gQmlnSW50KDEpLCBfMm4gPSBCaWdJbnQoMiksIF8zbiA9IEJpZ0ludCgzKSwgXzExbiA9IEJpZ0ludCgxMSk7XG4gICAgLy8gcHJldHRpZXItaWdub3JlXG4gICAgY29uc3QgXzIybiA9IEJpZ0ludCgyMiksIF80NG4gPSBCaWdJbnQoNDQpLCBfODhuID0gQmlnSW50KDg4KSwgXzIyM24gPSBCaWdJbnQoMjIzKTtcbiAgICBjb25zdCBiMiA9ICh4ICogeCAqIHgpICUgUDtcbiAgICBjb25zdCBiMyA9IChiMiAqIGIyICogeCkgJSBQO1xuICAgIGNvbnN0IGI2ID0gKHBvdzIoYjMsIF8zbiwgUCkgKiBiMykgJSBQO1xuICAgIGNvbnN0IGI5ID0gKHBvdzIoYjYsIF8zbiwgUCkgKiBiMykgJSBQO1xuICAgIGNvbnN0IGIxMSA9IChwb3cyKGI5LCBfMm4sIFApICogYjIpICUgUDtcbiAgICBjb25zdCBiMjIgPSAocG93MihiMTEsIF8xMW4sIFApICogYjExKSAlIFA7XG4gICAgY29uc3QgYjQ0ID0gKHBvdzIoYjIyLCBfMjJuLCBQKSAqIGIyMikgJSBQO1xuICAgIGNvbnN0IGI4OCA9IChwb3cyKGI0NCwgXzQ0biwgUCkgKiBiNDQpICUgUDtcbiAgICBjb25zdCBiMTc2ID0gKHBvdzIoYjg4LCBfODhuLCBQKSAqIGI4OCkgJSBQO1xuICAgIGNvbnN0IGIyMjAgPSAocG93MihiMTc2LCBfNDRuLCBQKSAqIGI0NCkgJSBQO1xuICAgIGNvbnN0IGIyMjIgPSAocG93MihiMjIwLCBfMm4sIFApICogYjIpICUgUDtcbiAgICBjb25zdCBiMjIzID0gKHBvdzIoYjIyMiwgXzFuLCBQKSAqIHgpICUgUDtcbiAgICByZXR1cm4gKHBvdzIoYjIyMywgXzIyM24sIFApICogYjIyMikgJSBQO1xufVxuZnVuY3Rpb24gYWRqdXN0U2NhbGFyQnl0ZXMoYnl0ZXMpIHtcbiAgICAvLyBTZWN0aW9uIDU6IExpa2V3aXNlLCBmb3IgWDQ0OCwgc2V0IHRoZSB0d28gbGVhc3Qgc2lnbmlmaWNhbnQgYml0cyBvZiB0aGUgZmlyc3QgYnl0ZSB0byAwLCBhbmQgdGhlIG1vc3RcbiAgICAvLyBzaWduaWZpY2FudCBiaXQgb2YgdGhlIGxhc3QgYnl0ZSB0byAxLlxuICAgIGJ5dGVzWzBdICY9IDI1MjsgLy8gMGIxMTExMTEwMFxuICAgIC8vIGFuZCB0aGUgbW9zdCBzaWduaWZpY2FudCBiaXQgb2YgdGhlIGxhc3QgYnl0ZSB0byAxLlxuICAgIGJ5dGVzWzU1XSB8PSAxMjg7IC8vIDBiMTAwMDAwMDBcbiAgICAvLyBOT1RFOiBpcyBpcyBOT09QIGZvciA1NiBieXRlcyBzY2FsYXJzIChYMjU1MTkvWDQ0OClcbiAgICBieXRlc1s1Nl0gPSAwOyAvLyBCeXRlIG91dHNpZGUgb2YgZ3JvdXAgKDQ1NiBidXRzIHZzIDQ0OCBiaXRzKVxuICAgIHJldHVybiBieXRlcztcbn1cbmNvbnN0IEZwID0gRmllbGQoZWQ0NDhQLCA0NTYsIHRydWUpO1xuY29uc3QgXzRuID0gQmlnSW50KDQpO1xuY29uc3QgRUQ0NDhfREVGID0ge1xuICAgIC8vIFBhcmFtOiBhXG4gICAgYTogQmlnSW50KDEpLFxuICAgIC8vIC0zOTA4MS4gTmVnYXRpdmUgbnVtYmVyIGlzIFAgLSBudW1iZXJcbiAgICBkOiBCaWdJbnQoJzcyNjgzODcyNDI5NTYwNjg5MDU0OTMyMzgwNzg4ODAwNDUzNDM1MzY0MTM2MDY4NzMxODA2MDI4MTQ5MDE5OTE4MDYxMjMyODE2NjczMDc3MjY4NjM5NjM4MzY5ODY3NjU0NTkzMDA4ODg4NDQ2MTg0MzYzNzM2MTA1MzQ5ODAxODMyNjM1OCcpLFxuICAgIC8vIEZpbml0ZSBmaWVsZCDwnZS9cCBvdmVyIHdoaWNoIHdlJ2xsIGRvIGNhbGN1bGF0aW9uczsgMm4gKiogNDQ4biAtIDJuICoqIDIyNG4gLSAxblxuICAgIEZwLFxuICAgIC8vIFN1Ymdyb3VwIG9yZGVyOiBob3cgbWFueSBwb2ludHMgY3VydmUgaGFzO1xuICAgIC8vIDJuKio0NDZuIC0gMTM4MTgwNjY4MDk4OTUxMTUzNTIwMDczODY3NDg1MTU0MjY4ODAzMzY2OTI0NzQ4ODIxNzg2MDk4OTQ1NDc1MDM4ODVuXG4gICAgbjogQmlnSW50KCcxODE3MDk2ODEwNzM5MDE3MjI2MzczMzA5NTE5NzIwMDExMzM1ODg0MTAzNDAxNzE4Mjk1MTUwNzAzNzI1NDk3OTUxNDYwMDM5NjE1Mzk1ODU3MTYxOTU3NTUyOTE2OTIzNzU5NjMzMTAyOTM3MDkwOTE2NjIzMDQ3NzM3NTU4NTk2NDk3NzknKSxcbiAgICBuQml0TGVuZ3RoOiA0NTYsXG4gICAgLy8gQ29mYWN0b3JcbiAgICBoOiBCaWdJbnQoNCksXG4gICAgLy8gQmFzZSBwb2ludCAoeCwgeSkgYWthIGdlbmVyYXRvciBwb2ludFxuICAgIEd4OiBCaWdJbnQoJzIyNDU4MDA0MDI5NTkyNDMwMDE4NzYwNDMzNDA5OTg5NjAzNjI0Njc4OTY0MTYzMjU2NDEzNDI0NjEyNTQ2MTY4Njk1MDQxNTQ2NzQwNjAzMjkwOTAyOTE5Mjg2OTM1Nzk1MzI4MjU3ODAzMjA3NTE0NjQ0NjE3MzY3NDYwMjYzNTI0NzcxMCcpLFxuICAgIEd5OiBCaWdJbnQoJzI5ODgxOTIxMDA3ODQ4MTQ5MjY3NjAxNzkzMDQ0MzkzMDY3MzQzNzU0NDA0MDE1NDA4MDI0MjA5NTkyODI0MTM3MjMzMTUwNjE4OTgzNTg3NjAwMzUzNjg3ODY1NTQxODc4NDczMzk4MjMwMzIzMzUwMzQ2MjUwMDUzMTU0NTA2MjgzMjY2MCcpLFxuICAgIC8vIFNIQUtFMjU2KGRvbTQocGhmbGFnLGNvbnRleHQpfHx4LCAxMTQpXG4gICAgaGFzaDogc2hha2UyNTZfMTE0LFxuICAgIHJhbmRvbUJ5dGVzLFxuICAgIGFkanVzdFNjYWxhckJ5dGVzLFxuICAgIC8vIGRvbTRcbiAgICBkb21haW46IChkYXRhLCBjdHgsIHBoZmxhZykgPT4ge1xuICAgICAgICBpZiAoY3R4Lmxlbmd0aCA+IDI1NSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ29udGV4dCBpcyB0b28gYmlnOiAke2N0eC5sZW5ndGh9YCk7XG4gICAgICAgIHJldHVybiBjb25jYXRCeXRlcyh1dGY4VG9CeXRlcygnU2lnRWQ0NDgnKSwgbmV3IFVpbnQ4QXJyYXkoW3BoZmxhZyA/IDEgOiAwLCBjdHgubGVuZ3RoXSksIGN0eCwgZGF0YSk7XG4gICAgfSxcbiAgICAvLyBDb25zdGFudC10aW1lIHJhdGlvIG9mIHUgdG8gdi4gQWxsb3dzIHRvIGNvbWJpbmUgaW52ZXJzaW9uIGFuZCBzcXVhcmUgcm9vdCB1L+KImnYuXG4gICAgLy8gVXNlcyBhbGdvIGZyb20gUkZDODAzMiA1LjEuMy5cbiAgICB1dlJhdGlvOiAodSwgdikgPT4ge1xuICAgICAgICBjb25zdCBQID0gZWQ0NDhQO1xuICAgICAgICAvLyBodHRwczovL2RhdGF0cmFja2VyLmlldGYub3JnL2RvYy9odG1sL3JmYzgwMzIjc2VjdGlvbi01LjIuM1xuICAgICAgICAvLyBUbyBjb21wdXRlIHRoZSBzcXVhcmUgcm9vdCBvZiAodS92KSwgdGhlIGZpcnN0IHN0ZXAgaXMgdG8gY29tcHV0ZSB0aGVcbiAgICAgICAgLy8gICBjYW5kaWRhdGUgcm9vdCB4ID0gKHUvdileKChwKzEpLzQpLiAgVGhpcyBjYW4gYmUgZG9uZSB1c2luZyB0aGVcbiAgICAgICAgLy8gZm9sbG93aW5nIHRyaWNrLCB0byB1c2UgYSBzaW5nbGUgbW9kdWxhciBwb3dlcmluZyBmb3IgYm90aCB0aGVcbiAgICAgICAgLy8gaW52ZXJzaW9uIG9mIHYgYW5kIHRoZSBzcXVhcmUgcm9vdDpcbiAgICAgICAgLy8geCA9ICh1L3YpXigocCsxKS80KSAgID0gdcKzdih14oG1dsKzKV4oKHAtMykvNCkgICAobW9kIHApXG4gICAgICAgIGNvbnN0IHUydiA9IG1vZCh1ICogdSAqIHYsIFApOyAvLyB1wrJ2XG4gICAgICAgIGNvbnN0IHUzdiA9IG1vZCh1MnYgKiB1LCBQKTsgLy8gdcKzdlxuICAgICAgICBjb25zdCB1NXYzID0gbW9kKHUzdiAqIHUydiAqIHYsIFApOyAvLyB14oG1dsKzXG4gICAgICAgIGNvbnN0IHJvb3QgPSBlZDQ0OF9wb3dfUG1pbnVzM2RpdjQodTV2Myk7XG4gICAgICAgIGNvbnN0IHggPSBtb2QodTN2ICogcm9vdCwgUCk7XG4gICAgICAgIC8vIFZlcmlmeSB0aGF0IHJvb3QgaXMgZXhpc3RzXG4gICAgICAgIGNvbnN0IHgyID0gbW9kKHggKiB4LCBQKTsgLy8geMKyXG4gICAgICAgIC8vIElmIHZ4wrIgPSB1LCB0aGUgcmVjb3ZlcmVkIHgtY29vcmRpbmF0ZSBpcyB4LiAgT3RoZXJ3aXNlLCBub1xuICAgICAgICAvLyBzcXVhcmUgcm9vdCBleGlzdHMsIGFuZCB0aGUgZGVjb2RpbmcgZmFpbHMuXG4gICAgICAgIHJldHVybiB7IGlzVmFsaWQ6IG1vZCh4MiAqIHYsIFApID09PSB1LCB2YWx1ZTogeCB9O1xuICAgIH0sXG59O1xuZXhwb3J0IGNvbnN0IGVkNDQ4ID0gdHdpc3RlZEVkd2FyZHMoRUQ0NDhfREVGKTtcbi8vIE5PVEU6IHRoZXJlIGlzIG5vIGVkNDQ4Y3R4LCBzaW5jZSBlZDQ0OCBzdXBwb3J0cyBjdHggYnkgZGVmYXVsdFxuZXhwb3J0IGNvbnN0IGVkNDQ4cGggPSB0d2lzdGVkRWR3YXJkcyh7IC4uLkVENDQ4X0RFRiwgcHJlaGFzaDogc2hha2UyNTZfNjQgfSk7XG5leHBvcnQgY29uc3QgeDQ0OCA9IG1vbnRnb21lcnkoe1xuICAgIGE6IEJpZ0ludCgxNTYzMjYpLFxuICAgIG1vbnRnb21lcnlCaXRzOiA0NDgsXG4gICAgbkJ5dGVMZW5ndGg6IDU3LFxuICAgIFA6IGVkNDQ4UCxcbiAgICBHdTogQmlnSW50KDUpLFxuICAgIHBvd1BtaW51czI6ICh4KSA9PiB7XG4gICAgICAgIGNvbnN0IFAgPSBlZDQ0OFA7XG4gICAgICAgIGNvbnN0IFBtaW51czNkaXY0ID0gZWQ0NDhfcG93X1BtaW51czNkaXY0KHgpO1xuICAgICAgICBjb25zdCBQbWludXMzID0gcG93MihQbWludXMzZGl2NCwgQmlnSW50KDIpLCBQKTtcbiAgICAgICAgcmV0dXJuIG1vZChQbWludXMzICogeCwgUCk7IC8vIFBtaW51czMgKiB4ID0gUG1pbnVzMlxuICAgIH0sXG4gICAgYWRqdXN0U2NhbGFyQnl0ZXMsXG4gICAgcmFuZG9tQnl0ZXMsXG59KTtcbi8qKlxuICogQ29udmVydHMgZWR3YXJkczQ0OCBwdWJsaWMga2V5IHRvIHg0NDggcHVibGljIGtleS4gVXNlcyBmb3JtdWxhOlxuICogKiBgKHUsIHYpID0gKCh5LTEpLyh5KzEpLCBzcXJ0KDE1NjMyNCkqdS94KWBcbiAqICogYCh4LCB5KSA9IChzcXJ0KDE1NjMyNCkqdS92LCAoMSt1KS8oMS11KSlgXG4gKiBAZXhhbXBsZVxuICogICBjb25zdCBhUHViID0gZWQ0NDguZ2V0UHVibGljS2V5KHV0aWxzLnJhbmRvbVByaXZhdGVLZXkoKSk7XG4gKiAgIHg0NDguZ2V0U2hhcmVkU2VjcmV0KGVkd2FyZHNUb01vbnRnb21lcnkoYVB1YiksIGVkd2FyZHNUb01vbnRnb21lcnkoc29tZW9uZXNQdWIpKVxuICovXG5leHBvcnQgZnVuY3Rpb24gZWR3YXJkc1RvTW9udGdvbWVyeShlZHdhcmRzUHViKSB7XG4gICAgY29uc3QgeyB5IH0gPSBlZDQ0OC5FeHRlbmRlZFBvaW50LmZyb21IZXgoZWR3YXJkc1B1Yik7XG4gICAgY29uc3QgXzFuID0gQmlnSW50KDEpO1xuICAgIHJldHVybiBGcC50b0J5dGVzKEZwLmNyZWF0ZSgoeSAtIF8xbikgKiBGcC5pbnYoeSArIF8xbikpKTtcbn1cbi8vIEhhc2ggVG8gQ3VydmUgRWxsaWdhdG9yMiBNYXBcbmNvbnN0IEVMTDJfQzEgPSAoRnAuT1JERVIgLSBCaWdJbnQoMykpIC8gQmlnSW50KDQpOyAvLyAxLiBjMSA9IChxIC0gMykgLyA0ICAgICAgICAgIyBJbnRlZ2VyIGFyaXRobWV0aWNcbmNvbnN0IEVMTDJfSiA9IEJpZ0ludCgxNTYzMjYpO1xuZnVuY3Rpb24gbWFwX3RvX2N1cnZlX2VsbGlnYXRvcjJfY3VydmU0NDgodSkge1xuICAgIGxldCB0djEgPSBGcC5zcXIodSk7IC8vIDEuICB0djEgPSB1XjJcbiAgICBsZXQgZTEgPSBGcC5lcWwodHYxLCBGcC5PTkUpOyAvLyAyLiAgIGUxID0gdHYxID09IDFcbiAgICB0djEgPSBGcC5jbW92KHR2MSwgRnAuWkVSTywgZTEpOyAvLyAzLiAgdHYxID0gQ01PVih0djEsIDAsIGUxKSAgIyBJZiBaICogdV4yID09IC0xLCBzZXQgdHYxID0gMFxuICAgIGxldCB4ZCA9IEZwLnN1YihGcC5PTkUsIHR2MSk7IC8vIDQuICAgeGQgPSAxIC0gdHYxXG4gICAgbGV0IHgxbiA9IEZwLm5lZyhFTEwyX0opOyAvLyA1LiAgeDFuID0gLUpcbiAgICBsZXQgdHYyID0gRnAuc3FyKHhkKTsgLy8gNi4gIHR2MiA9IHhkXjJcbiAgICBsZXQgZ3hkID0gRnAubXVsKHR2MiwgeGQpOyAvLyA3LiAgZ3hkID0gdHYyICogeGQgICAgICAgICAgIyBneGQgPSB4ZF4zXG4gICAgbGV0IGd4MSA9IEZwLm11bCh0djEsIEZwLm5lZyhFTEwyX0opKTsgLy8gOC4gIGd4MSA9IC1KICogdHYxICAgICAgICAgICMgeDFuICsgSiAqIHhkXG4gICAgZ3gxID0gRnAubXVsKGd4MSwgeDFuKTsgLy8gOS4gIGd4MSA9IGd4MSAqIHgxbiAgICAgICAgICMgeDFuXjIgKyBKICogeDFuICogeGRcbiAgICBneDEgPSBGcC5hZGQoZ3gxLCB0djIpOyAvLyAxMC4gZ3gxID0gZ3gxICsgdHYyICAgICAgICAgIyB4MW5eMiArIEogKiB4MW4gKiB4ZCArIHhkXjJcbiAgICBneDEgPSBGcC5tdWwoZ3gxLCB4MW4pOyAvLyAxMS4gZ3gxID0gZ3gxICogeDFuICAgICAgICAgIyB4MW5eMyArIEogKiB4MW5eMiAqIHhkICsgeDFuICogeGReMlxuICAgIGxldCB0djMgPSBGcC5zcXIoZ3hkKTsgLy8gMTIuIHR2MyA9IGd4ZF4yXG4gICAgdHYyID0gRnAubXVsKGd4MSwgZ3hkKTsgLy8gMTMuIHR2MiA9IGd4MSAqIGd4ZCAgICAgICAgICMgZ3gxICogZ3hkXG4gICAgdHYzID0gRnAubXVsKHR2MywgdHYyKTsgLy8gMTQuIHR2MyA9IHR2MyAqIHR2MiAgICAgICAgICMgZ3gxICogZ3hkXjNcbiAgICBsZXQgeTEgPSBGcC5wb3codHYzLCBFTEwyX0MxKTsgLy8gMTUuICB5MSA9IHR2M15jMSAgICAgICAgICAgICMgKGd4MSAqIGd4ZF4zKV4oKHAgLSAzKSAvIDQpXG4gICAgeTEgPSBGcC5tdWwoeTEsIHR2Mik7IC8vIDE2LiAgeTEgPSB5MSAqIHR2MiAgICAgICAgICAjIGd4MSAqIGd4ZCAqIChneDEgKiBneGReMyleKChwIC0gMykgLyA0KVxuICAgIGxldCB4Mm4gPSBGcC5tdWwoeDFuLCBGcC5uZWcodHYxKSk7IC8vIDE3LiB4Mm4gPSAtdHYxICogeDFuICAgICAgICAjIHgyID0geDJuIC8geGQgPSAtMSAqIHVeMiAqIHgxbiAvIHhkXG4gICAgbGV0IHkyID0gRnAubXVsKHkxLCB1KTsgLy8gMTguICB5MiA9IHkxICogdVxuICAgIHkyID0gRnAuY21vdih5MiwgRnAuWkVSTywgZTEpOyAvLyAxOS4gIHkyID0gQ01PVih5MiwgMCwgZTEpXG4gICAgdHYyID0gRnAuc3FyKHkxKTsgLy8gMjAuIHR2MiA9IHkxXjJcbiAgICB0djIgPSBGcC5tdWwodHYyLCBneGQpOyAvLyAyMS4gdHYyID0gdHYyICogZ3hkXG4gICAgbGV0IGUyID0gRnAuZXFsKHR2MiwgZ3gxKTsgLy8gMjIuICBlMiA9IHR2MiA9PSBneDFcbiAgICBsZXQgeG4gPSBGcC5jbW92KHgybiwgeDFuLCBlMik7IC8vIDIzLiAgeG4gPSBDTU9WKHgybiwgeDFuLCBlMikgICMgSWYgZTIsIHggPSB4MSwgZWxzZSB4ID0geDJcbiAgICBsZXQgeSA9IEZwLmNtb3YoeTIsIHkxLCBlMik7IC8vIDI0LiAgIHkgPSBDTU9WKHkyLCB5MSwgZTIpICAgICMgSWYgZTIsIHkgPSB5MSwgZWxzZSB5ID0geTJcbiAgICBsZXQgZTMgPSBGcC5pc09kZCh5KTsgLy8gMjUuICBlMyA9IHNnbjAoeSkgPT0gMSAgICAgICAgIyBGaXggc2lnbiBvZiB5XG4gICAgeSA9IEZwLmNtb3YoeSwgRnAubmVnKHkpLCBlMiAhPT0gZTMpOyAvLyAyNi4gICB5ID0gQ01PVih5LCAteSwgZTIgWE9SIGUzKVxuICAgIHJldHVybiB7IHhuLCB4ZCwgeW46IHksIHlkOiBGcC5PTkUgfTsgLy8gMjcuIHJldHVybiAoeG4sIHhkLCB5LCAxKVxufVxuZnVuY3Rpb24gbWFwX3RvX2N1cnZlX2VsbGlnYXRvcjJfZWR3YXJkczQ0OCh1KSB7XG4gICAgbGV0IHsgeG4sIHhkLCB5biwgeWQgfSA9IG1hcF90b19jdXJ2ZV9lbGxpZ2F0b3IyX2N1cnZlNDQ4KHUpOyAvLyAxLiAoeG4sIHhkLCB5biwgeWQpID0gbWFwX3RvX2N1cnZlX2VsbGlnYXRvcjJfY3VydmU0NDgodSlcbiAgICBsZXQgeG4yID0gRnAuc3FyKHhuKTsgLy8gMi4gIHhuMiA9IHhuXjJcbiAgICBsZXQgeGQyID0gRnAuc3FyKHhkKTsgLy8gMy4gIHhkMiA9IHhkXjJcbiAgICBsZXQgeGQ0ID0gRnAuc3FyKHhkMik7IC8vIDQuICB4ZDQgPSB4ZDJeMlxuICAgIGxldCB5bjIgPSBGcC5zcXIoeW4pOyAvLyA1LiAgeW4yID0geW5eMlxuICAgIGxldCB5ZDIgPSBGcC5zcXIoeWQpOyAvLyA2LiAgeWQyID0geWReMlxuICAgIGxldCB4RW4gPSBGcC5zdWIoeG4yLCB4ZDIpOyAvLyA3LiAgeEVuID0geG4yIC0geGQyXG4gICAgbGV0IHR2MiA9IEZwLnN1Yih4RW4sIHhkMik7IC8vIDguICB0djIgPSB4RW4gLSB4ZDJcbiAgICB4RW4gPSBGcC5tdWwoeEVuLCB4ZDIpOyAvLyA5LiAgeEVuID0geEVuICogeGQyXG4gICAgeEVuID0gRnAubXVsKHhFbiwgeWQpOyAvLyAxMC4geEVuID0geEVuICogeWRcbiAgICB4RW4gPSBGcC5tdWwoeEVuLCB5bik7IC8vIDExLiB4RW4gPSB4RW4gKiB5blxuICAgIHhFbiA9IEZwLm11bCh4RW4sIF80bik7IC8vIDEyLiB4RW4gPSB4RW4gKiA0XG4gICAgdHYyID0gRnAubXVsKHR2MiwgeG4yKTsgLy8gMTMuIHR2MiA9IHR2MiAqIHhuMlxuICAgIHR2MiA9IEZwLm11bCh0djIsIHlkMik7IC8vIDE0LiB0djIgPSB0djIgKiB5ZDJcbiAgICBsZXQgdHYzID0gRnAubXVsKHluMiwgXzRuKTsgLy8gMTUuIHR2MyA9IDQgKiB5bjJcbiAgICBsZXQgdHYxID0gRnAuYWRkKHR2MywgeWQyKTsgLy8gMTYuIHR2MSA9IHR2MyArIHlkMlxuICAgIHR2MSA9IEZwLm11bCh0djEsIHhkNCk7IC8vIDE3LiB0djEgPSB0djEgKiB4ZDRcbiAgICBsZXQgeEVkID0gRnAuYWRkKHR2MSwgdHYyKTsgLy8gMTguIHhFZCA9IHR2MSArIHR2MlxuICAgIHR2MiA9IEZwLm11bCh0djIsIHhuKTsgLy8gMTkuIHR2MiA9IHR2MiAqIHhuXG4gICAgbGV0IHR2NCA9IEZwLm11bCh4biwgeGQ0KTsgLy8gMjAuIHR2NCA9IHhuICogeGQ0XG4gICAgbGV0IHlFbiA9IEZwLnN1Yih0djMsIHlkMik7IC8vIDIxLiB5RW4gPSB0djMgLSB5ZDJcbiAgICB5RW4gPSBGcC5tdWwoeUVuLCB0djQpOyAvLyAyMi4geUVuID0geUVuICogdHY0XG4gICAgeUVuID0gRnAuc3ViKHlFbiwgdHYyKTsgLy8gMjMuIHlFbiA9IHlFbiAtIHR2MlxuICAgIHR2MSA9IEZwLmFkZCh4bjIsIHhkMik7IC8vIDI0LiB0djEgPSB4bjIgKyB4ZDJcbiAgICB0djEgPSBGcC5tdWwodHYxLCB4ZDIpOyAvLyAyNS4gdHYxID0gdHYxICogeGQyXG4gICAgdHYxID0gRnAubXVsKHR2MSwgeGQpOyAvLyAyNi4gdHYxID0gdHYxICogeGRcbiAgICB0djEgPSBGcC5tdWwodHYxLCB5bjIpOyAvLyAyNy4gdHYxID0gdHYxICogeW4yXG4gICAgdHYxID0gRnAubXVsKHR2MSwgQmlnSW50KC0yKSk7IC8vIDI4LiB0djEgPSAtMiAqIHR2MVxuICAgIGxldCB5RWQgPSBGcC5hZGQodHYyLCB0djEpOyAvLyAyOS4geUVkID0gdHYyICsgdHYxXG4gICAgdHY0ID0gRnAubXVsKHR2NCwgeWQyKTsgLy8gMzAuIHR2NCA9IHR2NCAqIHlkMlxuICAgIHlFZCA9IEZwLmFkZCh5RWQsIHR2NCk7IC8vIDMxLiB5RWQgPSB5RWQgKyB0djRcbiAgICB0djEgPSBGcC5tdWwoeEVkLCB5RWQpOyAvLyAzMi4gdHYxID0geEVkICogeUVkXG4gICAgbGV0IGUgPSBGcC5lcWwodHYxLCBGcC5aRVJPKTsgLy8gMzMuICAgZSA9IHR2MSA9PSAwXG4gICAgeEVuID0gRnAuY21vdih4RW4sIEZwLlpFUk8sIGUpOyAvLyAzNC4geEVuID0gQ01PVih4RW4sIDAsIGUpXG4gICAgeEVkID0gRnAuY21vdih4RWQsIEZwLk9ORSwgZSk7IC8vIDM1LiB4RWQgPSBDTU9WKHhFZCwgMSwgZSlcbiAgICB5RW4gPSBGcC5jbW92KHlFbiwgRnAuT05FLCBlKTsgLy8gMzYuIHlFbiA9IENNT1YoeUVuLCAxLCBlKVxuICAgIHlFZCA9IEZwLmNtb3YoeUVkLCBGcC5PTkUsIGUpOyAvLyAzNy4geUVkID0gQ01PVih5RWQsIDEsIGUpXG4gICAgY29uc3QgaW52ID0gRnAuaW52ZXJ0QmF0Y2goW3hFZCwgeUVkXSk7IC8vIGJhdGNoIGRpdmlzaW9uXG4gICAgcmV0dXJuIHsgeDogRnAubXVsKHhFbiwgaW52WzBdKSwgeTogRnAubXVsKHlFbiwgaW52WzFdKSB9OyAvLyAzOC4gcmV0dXJuICh4RW4sIHhFZCwgeUVuLCB5RWQpXG59XG5jb25zdCB7IGhhc2hUb0N1cnZlLCBlbmNvZGVUb0N1cnZlIH0gPSBodGYuY3JlYXRlSGFzaGVyKGVkNDQ4LkV4dGVuZGVkUG9pbnQsIChzY2FsYXJzKSA9PiBtYXBfdG9fY3VydmVfZWxsaWdhdG9yMl9lZHdhcmRzNDQ4KHNjYWxhcnNbMF0pLCB7XG4gICAgRFNUOiAnZWR3YXJkczQ0OF9YT0Y6U0hBS0UyNTZfRUxMMl9ST18nLFxuICAgIGVuY29kZURTVDogJ2Vkd2FyZHM0NDhfWE9GOlNIQUtFMjU2X0VMTDJfTlVfJyxcbiAgICBwOiBGcC5PUkRFUixcbiAgICBtOiAxLFxuICAgIGs6IDIyNCxcbiAgICBleHBhbmQ6ICd4b2YnLFxuICAgIGhhc2g6IHNoYWtlMjU2LFxufSk7XG5leHBvcnQgeyBoYXNoVG9DdXJ2ZSwgZW5jb2RlVG9DdXJ2ZSB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZWQ0NDguanMubWFwIiwiZnVuY3Rpb24gX3R5cGVvZihvYmopIHsgXCJAYmFiZWwvaGVscGVycyAtIHR5cGVvZlwiOyByZXR1cm4gX3R5cGVvZiA9IFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgU3ltYm9sICYmIFwic3ltYm9sXCIgPT0gdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA/IGZ1bmN0aW9uIChvYmopIHsgcmV0dXJuIHR5cGVvZiBvYmo7IH0gOiBmdW5jdGlvbiAob2JqKSB7IHJldHVybiBvYmogJiYgXCJmdW5jdGlvblwiID09IHR5cGVvZiBTeW1ib2wgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgJiYgb2JqICE9PSBTeW1ib2wucHJvdG90eXBlID8gXCJzeW1ib2xcIiA6IHR5cGVvZiBvYmo7IH0sIF90eXBlb2Yob2JqKTsgfVxuZnVuY3Rpb24gX3NsaWNlZFRvQXJyYXkoYXJyLCBpKSB7IHJldHVybiBfYXJyYXlXaXRoSG9sZXMoYXJyKSB8fCBfaXRlcmFibGVUb0FycmF5TGltaXQoYXJyLCBpKSB8fCBfdW5zdXBwb3J0ZWRJdGVyYWJsZVRvQXJyYXkoYXJyLCBpKSB8fCBfbm9uSXRlcmFibGVSZXN0KCk7IH1cbmZ1bmN0aW9uIF9ub25JdGVyYWJsZVJlc3QoKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIGF0dGVtcHQgdG8gZGVzdHJ1Y3R1cmUgbm9uLWl0ZXJhYmxlIGluc3RhbmNlLlxcbkluIG9yZGVyIHRvIGJlIGl0ZXJhYmxlLCBub24tYXJyYXkgb2JqZWN0cyBtdXN0IGhhdmUgYSBbU3ltYm9sLml0ZXJhdG9yXSgpIG1ldGhvZC5cIik7IH1cbmZ1bmN0aW9uIF91bnN1cHBvcnRlZEl0ZXJhYmxlVG9BcnJheShvLCBtaW5MZW4pIHsgaWYgKCFvKSByZXR1cm47IGlmICh0eXBlb2YgbyA9PT0gXCJzdHJpbmdcIikgcmV0dXJuIF9hcnJheUxpa2VUb0FycmF5KG8sIG1pbkxlbik7IHZhciBuID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG8pLnNsaWNlKDgsIC0xKTsgaWYgKG4gPT09IFwiT2JqZWN0XCIgJiYgby5jb25zdHJ1Y3RvcikgbiA9IG8uY29uc3RydWN0b3IubmFtZTsgaWYgKG4gPT09IFwiTWFwXCIgfHwgbiA9PT0gXCJTZXRcIikgcmV0dXJuIEFycmF5LmZyb20obyk7IGlmIChuID09PSBcIkFyZ3VtZW50c1wiIHx8IC9eKD86VWl8SSludCg/Ojh8MTZ8MzIpKD86Q2xhbXBlZCk/QXJyYXkkLy50ZXN0KG4pKSByZXR1cm4gX2FycmF5TGlrZVRvQXJyYXkobywgbWluTGVuKTsgfVxuZnVuY3Rpb24gX2FycmF5TGlrZVRvQXJyYXkoYXJyLCBsZW4pIHsgaWYgKGxlbiA9PSBudWxsIHx8IGxlbiA+IGFyci5sZW5ndGgpIGxlbiA9IGFyci5sZW5ndGg7IGZvciAodmFyIGkgPSAwLCBhcnIyID0gbmV3IEFycmF5KGxlbik7IGkgPCBsZW47IGkrKykgYXJyMltpXSA9IGFycltpXTsgcmV0dXJuIGFycjI7IH1cbmZ1bmN0aW9uIF9pdGVyYWJsZVRvQXJyYXlMaW1pdChhcnIsIGkpIHsgdmFyIF9pID0gbnVsbCA9PSBhcnIgPyBudWxsIDogXCJ1bmRlZmluZWRcIiAhPSB0eXBlb2YgU3ltYm9sICYmIGFycltTeW1ib2wuaXRlcmF0b3JdIHx8IGFycltcIkBAaXRlcmF0b3JcIl07IGlmIChudWxsICE9IF9pKSB7IHZhciBfcywgX2UsIF94LCBfciwgX2FyciA9IFtdLCBfbiA9ICEwLCBfZCA9ICExOyB0cnkgeyBpZiAoX3ggPSAoX2kgPSBfaS5jYWxsKGFycikpLm5leHQsIDAgPT09IGkpIHsgaWYgKE9iamVjdChfaSkgIT09IF9pKSByZXR1cm47IF9uID0gITE7IH0gZWxzZSBmb3IgKDsgIShfbiA9IChfcyA9IF94LmNhbGwoX2kpKS5kb25lKSAmJiAoX2Fyci5wdXNoKF9zLnZhbHVlKSwgX2Fyci5sZW5ndGggIT09IGkpOyBfbiA9ICEwKTsgfSBjYXRjaCAoZXJyKSB7IF9kID0gITAsIF9lID0gZXJyOyB9IGZpbmFsbHkgeyB0cnkgeyBpZiAoIV9uICYmIG51bGwgIT0gX2lbXCJyZXR1cm5cIl0gJiYgKF9yID0gX2lbXCJyZXR1cm5cIl0oKSwgT2JqZWN0KF9yKSAhPT0gX3IpKSByZXR1cm47IH0gZmluYWxseSB7IGlmIChfZCkgdGhyb3cgX2U7IH0gfSByZXR1cm4gX2FycjsgfSB9XG5mdW5jdGlvbiBfYXJyYXlXaXRoSG9sZXMoYXJyKSB7IGlmIChBcnJheS5pc0FycmF5KGFycikpIHJldHVybiBhcnI7IH1cbmZ1bmN0aW9uIF9yZWdlbmVyYXRvclJ1bnRpbWUoKSB7IFwidXNlIHN0cmljdFwiOyAvKiEgcmVnZW5lcmF0b3ItcnVudGltZSAtLSBDb3B5cmlnaHQgKGMpIDIwMTQtcHJlc2VudCwgRmFjZWJvb2ssIEluYy4gLS0gbGljZW5zZSAoTUlUKTogaHR0cHM6Ly9naXRodWIuY29tL2ZhY2Vib29rL3JlZ2VuZXJhdG9yL2Jsb2IvbWFpbi9MSUNFTlNFICovIF9yZWdlbmVyYXRvclJ1bnRpbWUgPSBmdW5jdGlvbiBfcmVnZW5lcmF0b3JSdW50aW1lKCkgeyByZXR1cm4gZXhwb3J0czsgfTsgdmFyIGV4cG9ydHMgPSB7fSwgT3AgPSBPYmplY3QucHJvdG90eXBlLCBoYXNPd24gPSBPcC5oYXNPd25Qcm9wZXJ0eSwgZGVmaW5lUHJvcGVydHkgPSBPYmplY3QuZGVmaW5lUHJvcGVydHkgfHwgZnVuY3Rpb24gKG9iaiwga2V5LCBkZXNjKSB7IG9ialtrZXldID0gZGVzYy52YWx1ZTsgfSwgJFN5bWJvbCA9IFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgU3ltYm9sID8gU3ltYm9sIDoge30sIGl0ZXJhdG9yU3ltYm9sID0gJFN5bWJvbC5pdGVyYXRvciB8fCBcIkBAaXRlcmF0b3JcIiwgYXN5bmNJdGVyYXRvclN5bWJvbCA9ICRTeW1ib2wuYXN5bmNJdGVyYXRvciB8fCBcIkBAYXN5bmNJdGVyYXRvclwiLCB0b1N0cmluZ1RhZ1N5bWJvbCA9ICRTeW1ib2wudG9TdHJpbmdUYWcgfHwgXCJAQHRvU3RyaW5nVGFnXCI7IGZ1bmN0aW9uIGRlZmluZShvYmosIGtleSwgdmFsdWUpIHsgcmV0dXJuIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIGtleSwgeyB2YWx1ZTogdmFsdWUsIGVudW1lcmFibGU6ICEwLCBjb25maWd1cmFibGU6ICEwLCB3cml0YWJsZTogITAgfSksIG9ialtrZXldOyB9IHRyeSB7IGRlZmluZSh7fSwgXCJcIik7IH0gY2F0Y2ggKGVycikgeyBkZWZpbmUgPSBmdW5jdGlvbiBkZWZpbmUob2JqLCBrZXksIHZhbHVlKSB7IHJldHVybiBvYmpba2V5XSA9IHZhbHVlOyB9OyB9IGZ1bmN0aW9uIHdyYXAoaW5uZXJGbiwgb3V0ZXJGbiwgc2VsZiwgdHJ5TG9jc0xpc3QpIHsgdmFyIHByb3RvR2VuZXJhdG9yID0gb3V0ZXJGbiAmJiBvdXRlckZuLnByb3RvdHlwZSBpbnN0YW5jZW9mIEdlbmVyYXRvciA/IG91dGVyRm4gOiBHZW5lcmF0b3IsIGdlbmVyYXRvciA9IE9iamVjdC5jcmVhdGUocHJvdG9HZW5lcmF0b3IucHJvdG90eXBlKSwgY29udGV4dCA9IG5ldyBDb250ZXh0KHRyeUxvY3NMaXN0IHx8IFtdKTsgcmV0dXJuIGRlZmluZVByb3BlcnR5KGdlbmVyYXRvciwgXCJfaW52b2tlXCIsIHsgdmFsdWU6IG1ha2VJbnZva2VNZXRob2QoaW5uZXJGbiwgc2VsZiwgY29udGV4dCkgfSksIGdlbmVyYXRvcjsgfSBmdW5jdGlvbiB0cnlDYXRjaChmbiwgb2JqLCBhcmcpIHsgdHJ5IHsgcmV0dXJuIHsgdHlwZTogXCJub3JtYWxcIiwgYXJnOiBmbi5jYWxsKG9iaiwgYXJnKSB9OyB9IGNhdGNoIChlcnIpIHsgcmV0dXJuIHsgdHlwZTogXCJ0aHJvd1wiLCBhcmc6IGVyciB9OyB9IH0gZXhwb3J0cy53cmFwID0gd3JhcDsgdmFyIENvbnRpbnVlU2VudGluZWwgPSB7fTsgZnVuY3Rpb24gR2VuZXJhdG9yKCkge30gZnVuY3Rpb24gR2VuZXJhdG9yRnVuY3Rpb24oKSB7fSBmdW5jdGlvbiBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZSgpIHt9IHZhciBJdGVyYXRvclByb3RvdHlwZSA9IHt9OyBkZWZpbmUoSXRlcmF0b3JQcm90b3R5cGUsIGl0ZXJhdG9yU3ltYm9sLCBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9KTsgdmFyIGdldFByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mLCBOYXRpdmVJdGVyYXRvclByb3RvdHlwZSA9IGdldFByb3RvICYmIGdldFByb3RvKGdldFByb3RvKHZhbHVlcyhbXSkpKTsgTmF0aXZlSXRlcmF0b3JQcm90b3R5cGUgJiYgTmF0aXZlSXRlcmF0b3JQcm90b3R5cGUgIT09IE9wICYmIGhhc093bi5jYWxsKE5hdGl2ZUl0ZXJhdG9yUHJvdG90eXBlLCBpdGVyYXRvclN5bWJvbCkgJiYgKEl0ZXJhdG9yUHJvdG90eXBlID0gTmF0aXZlSXRlcmF0b3JQcm90b3R5cGUpOyB2YXIgR3AgPSBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZS5wcm90b3R5cGUgPSBHZW5lcmF0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShJdGVyYXRvclByb3RvdHlwZSk7IGZ1bmN0aW9uIGRlZmluZUl0ZXJhdG9yTWV0aG9kcyhwcm90b3R5cGUpIHsgW1wibmV4dFwiLCBcInRocm93XCIsIFwicmV0dXJuXCJdLmZvckVhY2goZnVuY3Rpb24gKG1ldGhvZCkgeyBkZWZpbmUocHJvdG90eXBlLCBtZXRob2QsIGZ1bmN0aW9uIChhcmcpIHsgcmV0dXJuIHRoaXMuX2ludm9rZShtZXRob2QsIGFyZyk7IH0pOyB9KTsgfSBmdW5jdGlvbiBBc3luY0l0ZXJhdG9yKGdlbmVyYXRvciwgUHJvbWlzZUltcGwpIHsgZnVuY3Rpb24gaW52b2tlKG1ldGhvZCwgYXJnLCByZXNvbHZlLCByZWplY3QpIHsgdmFyIHJlY29yZCA9IHRyeUNhdGNoKGdlbmVyYXRvclttZXRob2RdLCBnZW5lcmF0b3IsIGFyZyk7IGlmIChcInRocm93XCIgIT09IHJlY29yZC50eXBlKSB7IHZhciByZXN1bHQgPSByZWNvcmQuYXJnLCB2YWx1ZSA9IHJlc3VsdC52YWx1ZTsgcmV0dXJuIHZhbHVlICYmIFwib2JqZWN0XCIgPT0gX3R5cGVvZih2YWx1ZSkgJiYgaGFzT3duLmNhbGwodmFsdWUsIFwiX19hd2FpdFwiKSA/IFByb21pc2VJbXBsLnJlc29sdmUodmFsdWUuX19hd2FpdCkudGhlbihmdW5jdGlvbiAodmFsdWUpIHsgaW52b2tlKFwibmV4dFwiLCB2YWx1ZSwgcmVzb2x2ZSwgcmVqZWN0KTsgfSwgZnVuY3Rpb24gKGVycikgeyBpbnZva2UoXCJ0aHJvd1wiLCBlcnIsIHJlc29sdmUsIHJlamVjdCk7IH0pIDogUHJvbWlzZUltcGwucmVzb2x2ZSh2YWx1ZSkudGhlbihmdW5jdGlvbiAodW53cmFwcGVkKSB7IHJlc3VsdC52YWx1ZSA9IHVud3JhcHBlZCwgcmVzb2x2ZShyZXN1bHQpOyB9LCBmdW5jdGlvbiAoZXJyb3IpIHsgcmV0dXJuIGludm9rZShcInRocm93XCIsIGVycm9yLCByZXNvbHZlLCByZWplY3QpOyB9KTsgfSByZWplY3QocmVjb3JkLmFyZyk7IH0gdmFyIHByZXZpb3VzUHJvbWlzZTsgZGVmaW5lUHJvcGVydHkodGhpcywgXCJfaW52b2tlXCIsIHsgdmFsdWU6IGZ1bmN0aW9uIHZhbHVlKG1ldGhvZCwgYXJnKSB7IGZ1bmN0aW9uIGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnKCkgeyByZXR1cm4gbmV3IFByb21pc2VJbXBsKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsgaW52b2tlKG1ldGhvZCwgYXJnLCByZXNvbHZlLCByZWplY3QpOyB9KTsgfSByZXR1cm4gcHJldmlvdXNQcm9taXNlID0gcHJldmlvdXNQcm9taXNlID8gcHJldmlvdXNQcm9taXNlLnRoZW4oY2FsbEludm9rZVdpdGhNZXRob2RBbmRBcmcsIGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnKSA6IGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnKCk7IH0gfSk7IH0gZnVuY3Rpb24gbWFrZUludm9rZU1ldGhvZChpbm5lckZuLCBzZWxmLCBjb250ZXh0KSB7IHZhciBzdGF0ZSA9IFwic3VzcGVuZGVkU3RhcnRcIjsgcmV0dXJuIGZ1bmN0aW9uIChtZXRob2QsIGFyZykgeyBpZiAoXCJleGVjdXRpbmdcIiA9PT0gc3RhdGUpIHRocm93IG5ldyBFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IHJ1bm5pbmdcIik7IGlmIChcImNvbXBsZXRlZFwiID09PSBzdGF0ZSkgeyBpZiAoXCJ0aHJvd1wiID09PSBtZXRob2QpIHRocm93IGFyZzsgcmV0dXJuIGRvbmVSZXN1bHQoKTsgfSBmb3IgKGNvbnRleHQubWV0aG9kID0gbWV0aG9kLCBjb250ZXh0LmFyZyA9IGFyZzs7KSB7IHZhciBkZWxlZ2F0ZSA9IGNvbnRleHQuZGVsZWdhdGU7IGlmIChkZWxlZ2F0ZSkgeyB2YXIgZGVsZWdhdGVSZXN1bHQgPSBtYXliZUludm9rZURlbGVnYXRlKGRlbGVnYXRlLCBjb250ZXh0KTsgaWYgKGRlbGVnYXRlUmVzdWx0KSB7IGlmIChkZWxlZ2F0ZVJlc3VsdCA9PT0gQ29udGludWVTZW50aW5lbCkgY29udGludWU7IHJldHVybiBkZWxlZ2F0ZVJlc3VsdDsgfSB9IGlmIChcIm5leHRcIiA9PT0gY29udGV4dC5tZXRob2QpIGNvbnRleHQuc2VudCA9IGNvbnRleHQuX3NlbnQgPSBjb250ZXh0LmFyZztlbHNlIGlmIChcInRocm93XCIgPT09IGNvbnRleHQubWV0aG9kKSB7IGlmIChcInN1c3BlbmRlZFN0YXJ0XCIgPT09IHN0YXRlKSB0aHJvdyBzdGF0ZSA9IFwiY29tcGxldGVkXCIsIGNvbnRleHQuYXJnOyBjb250ZXh0LmRpc3BhdGNoRXhjZXB0aW9uKGNvbnRleHQuYXJnKTsgfSBlbHNlIFwicmV0dXJuXCIgPT09IGNvbnRleHQubWV0aG9kICYmIGNvbnRleHQuYWJydXB0KFwicmV0dXJuXCIsIGNvbnRleHQuYXJnKTsgc3RhdGUgPSBcImV4ZWN1dGluZ1wiOyB2YXIgcmVjb3JkID0gdHJ5Q2F0Y2goaW5uZXJGbiwgc2VsZiwgY29udGV4dCk7IGlmIChcIm5vcm1hbFwiID09PSByZWNvcmQudHlwZSkgeyBpZiAoc3RhdGUgPSBjb250ZXh0LmRvbmUgPyBcImNvbXBsZXRlZFwiIDogXCJzdXNwZW5kZWRZaWVsZFwiLCByZWNvcmQuYXJnID09PSBDb250aW51ZVNlbnRpbmVsKSBjb250aW51ZTsgcmV0dXJuIHsgdmFsdWU6IHJlY29yZC5hcmcsIGRvbmU6IGNvbnRleHQuZG9uZSB9OyB9IFwidGhyb3dcIiA9PT0gcmVjb3JkLnR5cGUgJiYgKHN0YXRlID0gXCJjb21wbGV0ZWRcIiwgY29udGV4dC5tZXRob2QgPSBcInRocm93XCIsIGNvbnRleHQuYXJnID0gcmVjb3JkLmFyZyk7IH0gfTsgfSBmdW5jdGlvbiBtYXliZUludm9rZURlbGVnYXRlKGRlbGVnYXRlLCBjb250ZXh0KSB7IHZhciBtZXRob2ROYW1lID0gY29udGV4dC5tZXRob2QsIG1ldGhvZCA9IGRlbGVnYXRlLml0ZXJhdG9yW21ldGhvZE5hbWVdOyBpZiAodW5kZWZpbmVkID09PSBtZXRob2QpIHJldHVybiBjb250ZXh0LmRlbGVnYXRlID0gbnVsbCwgXCJ0aHJvd1wiID09PSBtZXRob2ROYW1lICYmIGRlbGVnYXRlLml0ZXJhdG9yW1wicmV0dXJuXCJdICYmIChjb250ZXh0Lm1ldGhvZCA9IFwicmV0dXJuXCIsIGNvbnRleHQuYXJnID0gdW5kZWZpbmVkLCBtYXliZUludm9rZURlbGVnYXRlKGRlbGVnYXRlLCBjb250ZXh0KSwgXCJ0aHJvd1wiID09PSBjb250ZXh0Lm1ldGhvZCkgfHwgXCJyZXR1cm5cIiAhPT0gbWV0aG9kTmFtZSAmJiAoY29udGV4dC5tZXRob2QgPSBcInRocm93XCIsIGNvbnRleHQuYXJnID0gbmV3IFR5cGVFcnJvcihcIlRoZSBpdGVyYXRvciBkb2VzIG5vdCBwcm92aWRlIGEgJ1wiICsgbWV0aG9kTmFtZSArIFwiJyBtZXRob2RcIikpLCBDb250aW51ZVNlbnRpbmVsOyB2YXIgcmVjb3JkID0gdHJ5Q2F0Y2gobWV0aG9kLCBkZWxlZ2F0ZS5pdGVyYXRvciwgY29udGV4dC5hcmcpOyBpZiAoXCJ0aHJvd1wiID09PSByZWNvcmQudHlwZSkgcmV0dXJuIGNvbnRleHQubWV0aG9kID0gXCJ0aHJvd1wiLCBjb250ZXh0LmFyZyA9IHJlY29yZC5hcmcsIGNvbnRleHQuZGVsZWdhdGUgPSBudWxsLCBDb250aW51ZVNlbnRpbmVsOyB2YXIgaW5mbyA9IHJlY29yZC5hcmc7IHJldHVybiBpbmZvID8gaW5mby5kb25lID8gKGNvbnRleHRbZGVsZWdhdGUucmVzdWx0TmFtZV0gPSBpbmZvLnZhbHVlLCBjb250ZXh0Lm5leHQgPSBkZWxlZ2F0ZS5uZXh0TG9jLCBcInJldHVyblwiICE9PSBjb250ZXh0Lm1ldGhvZCAmJiAoY29udGV4dC5tZXRob2QgPSBcIm5leHRcIiwgY29udGV4dC5hcmcgPSB1bmRlZmluZWQpLCBjb250ZXh0LmRlbGVnYXRlID0gbnVsbCwgQ29udGludWVTZW50aW5lbCkgOiBpbmZvIDogKGNvbnRleHQubWV0aG9kID0gXCJ0aHJvd1wiLCBjb250ZXh0LmFyZyA9IG5ldyBUeXBlRXJyb3IoXCJpdGVyYXRvciByZXN1bHQgaXMgbm90IGFuIG9iamVjdFwiKSwgY29udGV4dC5kZWxlZ2F0ZSA9IG51bGwsIENvbnRpbnVlU2VudGluZWwpOyB9IGZ1bmN0aW9uIHB1c2hUcnlFbnRyeShsb2NzKSB7IHZhciBlbnRyeSA9IHsgdHJ5TG9jOiBsb2NzWzBdIH07IDEgaW4gbG9jcyAmJiAoZW50cnkuY2F0Y2hMb2MgPSBsb2NzWzFdKSwgMiBpbiBsb2NzICYmIChlbnRyeS5maW5hbGx5TG9jID0gbG9jc1syXSwgZW50cnkuYWZ0ZXJMb2MgPSBsb2NzWzNdKSwgdGhpcy50cnlFbnRyaWVzLnB1c2goZW50cnkpOyB9IGZ1bmN0aW9uIHJlc2V0VHJ5RW50cnkoZW50cnkpIHsgdmFyIHJlY29yZCA9IGVudHJ5LmNvbXBsZXRpb24gfHwge307IHJlY29yZC50eXBlID0gXCJub3JtYWxcIiwgZGVsZXRlIHJlY29yZC5hcmcsIGVudHJ5LmNvbXBsZXRpb24gPSByZWNvcmQ7IH0gZnVuY3Rpb24gQ29udGV4dCh0cnlMb2NzTGlzdCkgeyB0aGlzLnRyeUVudHJpZXMgPSBbeyB0cnlMb2M6IFwicm9vdFwiIH1dLCB0cnlMb2NzTGlzdC5mb3JFYWNoKHB1c2hUcnlFbnRyeSwgdGhpcyksIHRoaXMucmVzZXQoITApOyB9IGZ1bmN0aW9uIHZhbHVlcyhpdGVyYWJsZSkgeyBpZiAoaXRlcmFibGUpIHsgdmFyIGl0ZXJhdG9yTWV0aG9kID0gaXRlcmFibGVbaXRlcmF0b3JTeW1ib2xdOyBpZiAoaXRlcmF0b3JNZXRob2QpIHJldHVybiBpdGVyYXRvck1ldGhvZC5jYWxsKGl0ZXJhYmxlKTsgaWYgKFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgaXRlcmFibGUubmV4dCkgcmV0dXJuIGl0ZXJhYmxlOyBpZiAoIWlzTmFOKGl0ZXJhYmxlLmxlbmd0aCkpIHsgdmFyIGkgPSAtMSwgbmV4dCA9IGZ1bmN0aW9uIG5leHQoKSB7IGZvciAoOyArK2kgPCBpdGVyYWJsZS5sZW5ndGg7KSBpZiAoaGFzT3duLmNhbGwoaXRlcmFibGUsIGkpKSByZXR1cm4gbmV4dC52YWx1ZSA9IGl0ZXJhYmxlW2ldLCBuZXh0LmRvbmUgPSAhMSwgbmV4dDsgcmV0dXJuIG5leHQudmFsdWUgPSB1bmRlZmluZWQsIG5leHQuZG9uZSA9ICEwLCBuZXh0OyB9OyByZXR1cm4gbmV4dC5uZXh0ID0gbmV4dDsgfSB9IHJldHVybiB7IG5leHQ6IGRvbmVSZXN1bHQgfTsgfSBmdW5jdGlvbiBkb25lUmVzdWx0KCkgeyByZXR1cm4geyB2YWx1ZTogdW5kZWZpbmVkLCBkb25lOiAhMCB9OyB9IHJldHVybiBHZW5lcmF0b3JGdW5jdGlvbi5wcm90b3R5cGUgPSBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZSwgZGVmaW5lUHJvcGVydHkoR3AsIFwiY29uc3RydWN0b3JcIiwgeyB2YWx1ZTogR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUsIGNvbmZpZ3VyYWJsZTogITAgfSksIGRlZmluZVByb3BlcnR5KEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlLCBcImNvbnN0cnVjdG9yXCIsIHsgdmFsdWU6IEdlbmVyYXRvckZ1bmN0aW9uLCBjb25maWd1cmFibGU6ICEwIH0pLCBHZW5lcmF0b3JGdW5jdGlvbi5kaXNwbGF5TmFtZSA9IGRlZmluZShHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZSwgdG9TdHJpbmdUYWdTeW1ib2wsIFwiR2VuZXJhdG9yRnVuY3Rpb25cIiksIGV4cG9ydHMuaXNHZW5lcmF0b3JGdW5jdGlvbiA9IGZ1bmN0aW9uIChnZW5GdW4pIHsgdmFyIGN0b3IgPSBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIGdlbkZ1biAmJiBnZW5GdW4uY29uc3RydWN0b3I7IHJldHVybiAhIWN0b3IgJiYgKGN0b3IgPT09IEdlbmVyYXRvckZ1bmN0aW9uIHx8IFwiR2VuZXJhdG9yRnVuY3Rpb25cIiA9PT0gKGN0b3IuZGlzcGxheU5hbWUgfHwgY3Rvci5uYW1lKSk7IH0sIGV4cG9ydHMubWFyayA9IGZ1bmN0aW9uIChnZW5GdW4pIHsgcmV0dXJuIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihnZW5GdW4sIEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlKSA6IChnZW5GdW4uX19wcm90b19fID0gR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUsIGRlZmluZShnZW5GdW4sIHRvU3RyaW5nVGFnU3ltYm9sLCBcIkdlbmVyYXRvckZ1bmN0aW9uXCIpKSwgZ2VuRnVuLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoR3ApLCBnZW5GdW47IH0sIGV4cG9ydHMuYXdyYXAgPSBmdW5jdGlvbiAoYXJnKSB7IHJldHVybiB7IF9fYXdhaXQ6IGFyZyB9OyB9LCBkZWZpbmVJdGVyYXRvck1ldGhvZHMoQXN5bmNJdGVyYXRvci5wcm90b3R5cGUpLCBkZWZpbmUoQXN5bmNJdGVyYXRvci5wcm90b3R5cGUsIGFzeW5jSXRlcmF0b3JTeW1ib2wsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0pLCBleHBvcnRzLkFzeW5jSXRlcmF0b3IgPSBBc3luY0l0ZXJhdG9yLCBleHBvcnRzLmFzeW5jID0gZnVuY3Rpb24gKGlubmVyRm4sIG91dGVyRm4sIHNlbGYsIHRyeUxvY3NMaXN0LCBQcm9taXNlSW1wbCkgeyB2b2lkIDAgPT09IFByb21pc2VJbXBsICYmIChQcm9taXNlSW1wbCA9IFByb21pc2UpOyB2YXIgaXRlciA9IG5ldyBBc3luY0l0ZXJhdG9yKHdyYXAoaW5uZXJGbiwgb3V0ZXJGbiwgc2VsZiwgdHJ5TG9jc0xpc3QpLCBQcm9taXNlSW1wbCk7IHJldHVybiBleHBvcnRzLmlzR2VuZXJhdG9yRnVuY3Rpb24ob3V0ZXJGbikgPyBpdGVyIDogaXRlci5uZXh0KCkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7IHJldHVybiByZXN1bHQuZG9uZSA/IHJlc3VsdC52YWx1ZSA6IGl0ZXIubmV4dCgpOyB9KTsgfSwgZGVmaW5lSXRlcmF0b3JNZXRob2RzKEdwKSwgZGVmaW5lKEdwLCB0b1N0cmluZ1RhZ1N5bWJvbCwgXCJHZW5lcmF0b3JcIiksIGRlZmluZShHcCwgaXRlcmF0b3JTeW1ib2wsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0pLCBkZWZpbmUoR3AsIFwidG9TdHJpbmdcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gXCJbb2JqZWN0IEdlbmVyYXRvcl1cIjsgfSksIGV4cG9ydHMua2V5cyA9IGZ1bmN0aW9uICh2YWwpIHsgdmFyIG9iamVjdCA9IE9iamVjdCh2YWwpLCBrZXlzID0gW107IGZvciAodmFyIGtleSBpbiBvYmplY3QpIGtleXMucHVzaChrZXkpOyByZXR1cm4ga2V5cy5yZXZlcnNlKCksIGZ1bmN0aW9uIG5leHQoKSB7IGZvciAoOyBrZXlzLmxlbmd0aDspIHsgdmFyIGtleSA9IGtleXMucG9wKCk7IGlmIChrZXkgaW4gb2JqZWN0KSByZXR1cm4gbmV4dC52YWx1ZSA9IGtleSwgbmV4dC5kb25lID0gITEsIG5leHQ7IH0gcmV0dXJuIG5leHQuZG9uZSA9ICEwLCBuZXh0OyB9OyB9LCBleHBvcnRzLnZhbHVlcyA9IHZhbHVlcywgQ29udGV4dC5wcm90b3R5cGUgPSB7IGNvbnN0cnVjdG9yOiBDb250ZXh0LCByZXNldDogZnVuY3Rpb24gcmVzZXQoc2tpcFRlbXBSZXNldCkgeyBpZiAodGhpcy5wcmV2ID0gMCwgdGhpcy5uZXh0ID0gMCwgdGhpcy5zZW50ID0gdGhpcy5fc2VudCA9IHVuZGVmaW5lZCwgdGhpcy5kb25lID0gITEsIHRoaXMuZGVsZWdhdGUgPSBudWxsLCB0aGlzLm1ldGhvZCA9IFwibmV4dFwiLCB0aGlzLmFyZyA9IHVuZGVmaW5lZCwgdGhpcy50cnlFbnRyaWVzLmZvckVhY2gocmVzZXRUcnlFbnRyeSksICFza2lwVGVtcFJlc2V0KSBmb3IgKHZhciBuYW1lIGluIHRoaXMpIFwidFwiID09PSBuYW1lLmNoYXJBdCgwKSAmJiBoYXNPd24uY2FsbCh0aGlzLCBuYW1lKSAmJiAhaXNOYU4oK25hbWUuc2xpY2UoMSkpICYmICh0aGlzW25hbWVdID0gdW5kZWZpbmVkKTsgfSwgc3RvcDogZnVuY3Rpb24gc3RvcCgpIHsgdGhpcy5kb25lID0gITA7IHZhciByb290UmVjb3JkID0gdGhpcy50cnlFbnRyaWVzWzBdLmNvbXBsZXRpb247IGlmIChcInRocm93XCIgPT09IHJvb3RSZWNvcmQudHlwZSkgdGhyb3cgcm9vdFJlY29yZC5hcmc7IHJldHVybiB0aGlzLnJ2YWw7IH0sIGRpc3BhdGNoRXhjZXB0aW9uOiBmdW5jdGlvbiBkaXNwYXRjaEV4Y2VwdGlvbihleGNlcHRpb24pIHsgaWYgKHRoaXMuZG9uZSkgdGhyb3cgZXhjZXB0aW9uOyB2YXIgY29udGV4dCA9IHRoaXM7IGZ1bmN0aW9uIGhhbmRsZShsb2MsIGNhdWdodCkgeyByZXR1cm4gcmVjb3JkLnR5cGUgPSBcInRocm93XCIsIHJlY29yZC5hcmcgPSBleGNlcHRpb24sIGNvbnRleHQubmV4dCA9IGxvYywgY2F1Z2h0ICYmIChjb250ZXh0Lm1ldGhvZCA9IFwibmV4dFwiLCBjb250ZXh0LmFyZyA9IHVuZGVmaW5lZCksICEhY2F1Z2h0OyB9IGZvciAodmFyIGkgPSB0aGlzLnRyeUVudHJpZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHsgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldLCByZWNvcmQgPSBlbnRyeS5jb21wbGV0aW9uOyBpZiAoXCJyb290XCIgPT09IGVudHJ5LnRyeUxvYykgcmV0dXJuIGhhbmRsZShcImVuZFwiKTsgaWYgKGVudHJ5LnRyeUxvYyA8PSB0aGlzLnByZXYpIHsgdmFyIGhhc0NhdGNoID0gaGFzT3duLmNhbGwoZW50cnksIFwiY2F0Y2hMb2NcIiksIGhhc0ZpbmFsbHkgPSBoYXNPd24uY2FsbChlbnRyeSwgXCJmaW5hbGx5TG9jXCIpOyBpZiAoaGFzQ2F0Y2ggJiYgaGFzRmluYWxseSkgeyBpZiAodGhpcy5wcmV2IDwgZW50cnkuY2F0Y2hMb2MpIHJldHVybiBoYW5kbGUoZW50cnkuY2F0Y2hMb2MsICEwKTsgaWYgKHRoaXMucHJldiA8IGVudHJ5LmZpbmFsbHlMb2MpIHJldHVybiBoYW5kbGUoZW50cnkuZmluYWxseUxvYyk7IH0gZWxzZSBpZiAoaGFzQ2F0Y2gpIHsgaWYgKHRoaXMucHJldiA8IGVudHJ5LmNhdGNoTG9jKSByZXR1cm4gaGFuZGxlKGVudHJ5LmNhdGNoTG9jLCAhMCk7IH0gZWxzZSB7IGlmICghaGFzRmluYWxseSkgdGhyb3cgbmV3IEVycm9yKFwidHJ5IHN0YXRlbWVudCB3aXRob3V0IGNhdGNoIG9yIGZpbmFsbHlcIik7IGlmICh0aGlzLnByZXYgPCBlbnRyeS5maW5hbGx5TG9jKSByZXR1cm4gaGFuZGxlKGVudHJ5LmZpbmFsbHlMb2MpOyB9IH0gfSB9LCBhYnJ1cHQ6IGZ1bmN0aW9uIGFicnVwdCh0eXBlLCBhcmcpIHsgZm9yICh2YXIgaSA9IHRoaXMudHJ5RW50cmllcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgeyB2YXIgZW50cnkgPSB0aGlzLnRyeUVudHJpZXNbaV07IGlmIChlbnRyeS50cnlMb2MgPD0gdGhpcy5wcmV2ICYmIGhhc093bi5jYWxsKGVudHJ5LCBcImZpbmFsbHlMb2NcIikgJiYgdGhpcy5wcmV2IDwgZW50cnkuZmluYWxseUxvYykgeyB2YXIgZmluYWxseUVudHJ5ID0gZW50cnk7IGJyZWFrOyB9IH0gZmluYWxseUVudHJ5ICYmIChcImJyZWFrXCIgPT09IHR5cGUgfHwgXCJjb250aW51ZVwiID09PSB0eXBlKSAmJiBmaW5hbGx5RW50cnkudHJ5TG9jIDw9IGFyZyAmJiBhcmcgPD0gZmluYWxseUVudHJ5LmZpbmFsbHlMb2MgJiYgKGZpbmFsbHlFbnRyeSA9IG51bGwpOyB2YXIgcmVjb3JkID0gZmluYWxseUVudHJ5ID8gZmluYWxseUVudHJ5LmNvbXBsZXRpb24gOiB7fTsgcmV0dXJuIHJlY29yZC50eXBlID0gdHlwZSwgcmVjb3JkLmFyZyA9IGFyZywgZmluYWxseUVudHJ5ID8gKHRoaXMubWV0aG9kID0gXCJuZXh0XCIsIHRoaXMubmV4dCA9IGZpbmFsbHlFbnRyeS5maW5hbGx5TG9jLCBDb250aW51ZVNlbnRpbmVsKSA6IHRoaXMuY29tcGxldGUocmVjb3JkKTsgfSwgY29tcGxldGU6IGZ1bmN0aW9uIGNvbXBsZXRlKHJlY29yZCwgYWZ0ZXJMb2MpIHsgaWYgKFwidGhyb3dcIiA9PT0gcmVjb3JkLnR5cGUpIHRocm93IHJlY29yZC5hcmc7IHJldHVybiBcImJyZWFrXCIgPT09IHJlY29yZC50eXBlIHx8IFwiY29udGludWVcIiA9PT0gcmVjb3JkLnR5cGUgPyB0aGlzLm5leHQgPSByZWNvcmQuYXJnIDogXCJyZXR1cm5cIiA9PT0gcmVjb3JkLnR5cGUgPyAodGhpcy5ydmFsID0gdGhpcy5hcmcgPSByZWNvcmQuYXJnLCB0aGlzLm1ldGhvZCA9IFwicmV0dXJuXCIsIHRoaXMubmV4dCA9IFwiZW5kXCIpIDogXCJub3JtYWxcIiA9PT0gcmVjb3JkLnR5cGUgJiYgYWZ0ZXJMb2MgJiYgKHRoaXMubmV4dCA9IGFmdGVyTG9jKSwgQ29udGludWVTZW50aW5lbDsgfSwgZmluaXNoOiBmdW5jdGlvbiBmaW5pc2goZmluYWxseUxvYykgeyBmb3IgKHZhciBpID0gdGhpcy50cnlFbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7IHZhciBlbnRyeSA9IHRoaXMudHJ5RW50cmllc1tpXTsgaWYgKGVudHJ5LmZpbmFsbHlMb2MgPT09IGZpbmFsbHlMb2MpIHJldHVybiB0aGlzLmNvbXBsZXRlKGVudHJ5LmNvbXBsZXRpb24sIGVudHJ5LmFmdGVyTG9jKSwgcmVzZXRUcnlFbnRyeShlbnRyeSksIENvbnRpbnVlU2VudGluZWw7IH0gfSwgXCJjYXRjaFwiOiBmdW5jdGlvbiBfY2F0Y2godHJ5TG9jKSB7IGZvciAodmFyIGkgPSB0aGlzLnRyeUVudHJpZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHsgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldOyBpZiAoZW50cnkudHJ5TG9jID09PSB0cnlMb2MpIHsgdmFyIHJlY29yZCA9IGVudHJ5LmNvbXBsZXRpb247IGlmIChcInRocm93XCIgPT09IHJlY29yZC50eXBlKSB7IHZhciB0aHJvd24gPSByZWNvcmQuYXJnOyByZXNldFRyeUVudHJ5KGVudHJ5KTsgfSByZXR1cm4gdGhyb3duOyB9IH0gdGhyb3cgbmV3IEVycm9yKFwiaWxsZWdhbCBjYXRjaCBhdHRlbXB0XCIpOyB9LCBkZWxlZ2F0ZVlpZWxkOiBmdW5jdGlvbiBkZWxlZ2F0ZVlpZWxkKGl0ZXJhYmxlLCByZXN1bHROYW1lLCBuZXh0TG9jKSB7IHJldHVybiB0aGlzLmRlbGVnYXRlID0geyBpdGVyYXRvcjogdmFsdWVzKGl0ZXJhYmxlKSwgcmVzdWx0TmFtZTogcmVzdWx0TmFtZSwgbmV4dExvYzogbmV4dExvYyB9LCBcIm5leHRcIiA9PT0gdGhpcy5tZXRob2QgJiYgKHRoaXMuYXJnID0gdW5kZWZpbmVkKSwgQ29udGludWVTZW50aW5lbDsgfSB9LCBleHBvcnRzOyB9XG5mdW5jdGlvbiBhc3luY0dlbmVyYXRvclN0ZXAoZ2VuLCByZXNvbHZlLCByZWplY3QsIF9uZXh0LCBfdGhyb3csIGtleSwgYXJnKSB7IHRyeSB7IHZhciBpbmZvID0gZ2VuW2tleV0oYXJnKTsgdmFyIHZhbHVlID0gaW5mby52YWx1ZTsgfSBjYXRjaCAoZXJyb3IpIHsgcmVqZWN0KGVycm9yKTsgcmV0dXJuOyB9IGlmIChpbmZvLmRvbmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0gZWxzZSB7IFByb21pc2UucmVzb2x2ZSh2YWx1ZSkudGhlbihfbmV4dCwgX3Rocm93KTsgfSB9XG5mdW5jdGlvbiBfYXN5bmNUb0dlbmVyYXRvcihmbikgeyByZXR1cm4gZnVuY3Rpb24gKCkgeyB2YXIgc2VsZiA9IHRoaXMsIGFyZ3MgPSBhcmd1bWVudHM7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7IHZhciBnZW4gPSBmbi5hcHBseShzZWxmLCBhcmdzKTsgZnVuY3Rpb24gX25leHQodmFsdWUpIHsgYXN5bmNHZW5lcmF0b3JTdGVwKGdlbiwgcmVzb2x2ZSwgcmVqZWN0LCBfbmV4dCwgX3Rocm93LCBcIm5leHRcIiwgdmFsdWUpOyB9IGZ1bmN0aW9uIF90aHJvdyhlcnIpIHsgYXN5bmNHZW5lcmF0b3JTdGVwKGdlbiwgcmVzb2x2ZSwgcmVqZWN0LCBfbmV4dCwgX3Rocm93LCBcInRocm93XCIsIGVycik7IH0gX25leHQodW5kZWZpbmVkKTsgfSk7IH07IH1cbmltcG9ydCB7IEh0bWw1UXJjb2RlU2Nhbm5lciwgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUsIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyB9IGZyb20gXCJodG1sNS1xcmNvZGVcIjtcbmltcG9ydCB7IGVkNDQ4IH0gZnJvbSBcIkBub2JsZS9jdXJ2ZXMvZWQ0NDhcIjtcbmltcG9ydCB7IEJ1ZmZlciB9IGZyb20gXCJidWZmZXJcIjtcbnZhciBjdXJyZW50bHlBZGRpbmdJdGVtQnlUYWcgPSBuZXcgTWFwKCk7XG52YXIgcmVjZWl2ZWRfaXRlbXMgPSB7fTtcbnZhciBjb25maWc7XG52YXIgc2Nhbm5lciA9IG5ldyBIdG1sNVFyY29kZVNjYW5uZXIoXCJyZWFkZXJcIiwge1xuICBmcHM6IDEwLFxuICBxcmJveDoge1xuICAgIHdpZHRoOiAyNTAsXG4gICAgaGVpZ2h0OiAyNTBcbiAgfSxcbiAgc2hvd1RvcmNoQnV0dG9uSWZTdXBwb3J0ZWQ6IHRydWUsXG4gIGZvcm1hdHNUb1N1cHBvcnQ6IFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUVJfQ09ERV0sXG4gIC8vdGhlcmUgYXJlIG1hbnkgb3RoZXIgdHlwZXMgb2YgY29kZXMgb24gdGhlIGxhYmVscyB3ZSBkbyBub3Qgd2FudFxuICByZW1lbWJlckxhc3RVc2VkQ2FtZXJhOiB0cnVlXG59KTtcbnZhciBzY2FubmVyX2F1ZGlvID0gbmV3IEF1ZGlvKFwiL2JlZXAud2F2XCIpO1xuc2Nhbm5lcl9hdWRpby5sb2FkKCk7XG52YXIgdG9hc3REaXYgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcImJvdHRvbVRvYXN0XCIpO1xuXG4vKlxuICogSGVscGVyIGZ1bmN0aW9uc1xuICovXG5mdW5jdGlvbiBodG9hKGgpIHtcbiAgcmV0dXJuIFVpbnQ4QXJyYXkuZnJvbShCdWZmZXIuZnJvbShoLCBcImhleFwiKSk7XG59XG5mdW5jdGlvbiB0b2FzdCh0aXRsZSwgbWVzc2FnZSkge1xuICB0b2FzdERpdi5jaGlsZHJlblswXS5jaGlsZHJlblswXS5pbm5lckhUTUwgPSB0aXRsZTtcbiAgdG9hc3REaXYuY2hpbGRyZW5bMV0uaW5uZXJIVE1MID0gbWVzc2FnZTtcbiAgdG9hc3REaXYuY2xhc3NMaXN0LnJlbW92ZShcImhpZGVcIik7XG4gIHRvYXN0RGl2LmNsYXNzTGlzdC5hZGQoXCJzaG93XCIpO1xuICB0b2FzdERpdi5jbGFzc0xpc3QuYWRkKFwic2hvd2luZ1wiKTtcbiAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgdG9hc3REaXYuY2xhc3NMaXN0LnJlbW92ZShcInNob3dcIik7XG4gICAgdG9hc3REaXYuY2xhc3NMaXN0LnJlbW92ZShcInNob3dpbmdcIik7XG4gICAgdG9hc3REaXYuY2xhc3NMaXN0LmFkZChcImhpZGVcIik7XG4gIH0sIDMwMDApO1xufVxuZnVuY3Rpb24gZmV0Y2hXaXRoQXV0aChfeCwgX3gyKSB7XG4gIHJldHVybiBfZmV0Y2hXaXRoQXV0aC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2ZldGNoV2l0aEF1dGgoKSB7XG4gIF9mZXRjaFdpdGhBdXRoID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlKGlucHV0LCBpbml0KSB7XG4gICAgdmFyIHJlc3BvbnNlO1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlJChfY29udGV4dCkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQucHJldiA9IF9jb250ZXh0Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGlmIChpbml0ID09IHVuZGVmaW5lZCB8fCBpbml0ID09IG51bGwpIHtcbiAgICAgICAgICAgIGluaXQgPSB7fTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGluaXRbXCJoZWFkZXJzXCJdID09IG51bGwpIHtcbiAgICAgICAgICAgIGluaXRbXCJoZWFkZXJzXCJdID0ge307XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh3aW5kb3cuc2Vzc2lvblN0b3JhZ2UuZ2V0SXRlbShcImFjY2Vzc190b2tlblwiKSkge1xuICAgICAgICAgICAgX2NvbnRleHQubmV4dCA9IDU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgX2NvbnRleHQubmV4dCA9IDU7XG4gICAgICAgICAgcmV0dXJuIGxvZ2luKCk7XG4gICAgICAgIGNhc2UgNTpcbiAgICAgICAgICBpbml0W1wiaGVhZGVyc1wiXVtcIkF1dGhvcml6YXRpb25cIl0gPSBcIkJlYXJlciBcIiArIHdpbmRvdy5zZXNzaW9uU3RvcmFnZS5nZXRJdGVtKFwiYWNjZXNzX3Rva2VuXCIpO1xuICAgICAgICAgIF9jb250ZXh0Lm5leHQgPSA4O1xuICAgICAgICAgIHJldHVybiBmZXRjaChpbnB1dCwgaW5pdCk7XG4gICAgICAgIGNhc2UgODpcbiAgICAgICAgICByZXNwb25zZSA9IF9jb250ZXh0LnNlbnQ7XG4gICAgICAgIGNhc2UgOTpcbiAgICAgICAgICBpZiAoIShyZXNwb25zZS5zdGF0dXMgPT0gNDAxKSkge1xuICAgICAgICAgICAgX2NvbnRleHQubmV4dCA9IDE5O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiRmV0Y2ggd2l0aCBhdXRoIGZhaWxlZCBmb3JcIiwgaW5wdXQpO1xuICAgICAgICAgIF9jb250ZXh0Lm5leHQgPSAxMztcbiAgICAgICAgICByZXR1cm4gbG9naW4oKTtcbiAgICAgICAgY2FzZSAxMzpcbiAgICAgICAgICBpbml0W1wiaGVhZGVyc1wiXVtcIkF1dGhvcml6YXRpb25cIl0gPSBcIkJlYXJlciBcIiArIHdpbmRvdy5zZXNzaW9uU3RvcmFnZS5nZXRJdGVtKFwiYWNjZXNzX3Rva2VuXCIpO1xuICAgICAgICAgIF9jb250ZXh0Lm5leHQgPSAxNjtcbiAgICAgICAgICByZXR1cm4gZmV0Y2goaW5wdXQsIGluaXQpO1xuICAgICAgICBjYXNlIDE2OlxuICAgICAgICAgIHJlc3BvbnNlID0gX2NvbnRleHQuc2VudDtcbiAgICAgICAgICBfY29udGV4dC5uZXh0ID0gOTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAxOTpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQuYWJydXB0KFwicmV0dXJuXCIsIHJlc3BvbnNlKTtcbiAgICAgICAgY2FzZSAyMDpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dC5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZSk7XG4gIH0pKTtcbiAgcmV0dXJuIF9mZXRjaFdpdGhBdXRoLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBjaGVja1Jlc3BvbnNlRm9yRXJyb3IoX3gzLCBfeDQpIHtcbiAgcmV0dXJuIF9jaGVja1Jlc3BvbnNlRm9yRXJyb3IuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9jaGVja1Jlc3BvbnNlRm9yRXJyb3IoKSB7XG4gIF9jaGVja1Jlc3BvbnNlRm9yRXJyb3IgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUyKHJlc3BvbnNlLCBtZXNzYWdlKSB7XG4gICAgdmFyIGNvbnRlbnQ7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUyJChfY29udGV4dDIpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0Mi5wcmV2ID0gX2NvbnRleHQyLm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGlmICghKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSkge1xuICAgICAgICAgICAgX2NvbnRleHQyLm5leHQgPSA3O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0Mi5uZXh0ID0gMztcbiAgICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgY29udGVudCA9IF9jb250ZXh0Mi5zZW50O1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiR290IFJlc3BvbnNlIEVycm9yOlwiLCBtZXNzYWdlLCByZXNwb25zZSk7XG4gICAgICAgICAgYWxlcnQobWVzc2FnZSArIFwiOyBTdGF0dXM6IFwiICsgcmVzcG9uc2Uuc3RhdHVzICsgXCI7IENvbnRlbnQ6IFwiICsgY29udGVudCk7XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0Mi5hYnJ1cHQoXCJyZXR1cm5cIiwgZmFsc2UpO1xuICAgICAgICBjYXNlIDc6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0Mi5hYnJ1cHQoXCJyZXR1cm5cIiwgdHJ1ZSk7XG4gICAgICAgIGNhc2UgODpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDIuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUyKTtcbiAgfSkpO1xuICByZXR1cm4gX2NoZWNrUmVzcG9uc2VGb3JFcnJvci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gZ2V0Q29uZmlnKCkge1xuICByZXR1cm4gX2dldENvbmZpZy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2dldENvbmZpZygpIHtcbiAgX2dldENvbmZpZyA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTMoKSB7XG4gICAgdmFyIGNvbmZpZ19yZXF1ZXN0O1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMyQoX2NvbnRleHQzKSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDMucHJldiA9IF9jb250ZXh0My5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBpZiAoIShjb25maWcgPT0gdW5kZWZpbmVkKSkge1xuICAgICAgICAgICAgX2NvbnRleHQzLm5leHQgPSAxMjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dDMubmV4dCA9IDM7XG4gICAgICAgICAgcmV0dXJuIGZldGNoKFwiY29uZmlnLmpzb25cIik7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICBjb25maWdfcmVxdWVzdCA9IF9jb250ZXh0My5zZW50O1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiTG9hZGluZyBjb25maWdcIik7XG4gICAgICAgICAgX2NvbnRleHQzLm5leHQgPSA3O1xuICAgICAgICAgIHJldHVybiBjaGVja1Jlc3BvbnNlRm9yRXJyb3IoY29uZmlnX3JlcXVlc3QsIFwiQ291bGQgbm90IGxvYWQgY29uZmlnXCIpO1xuICAgICAgICBjYXNlIDc6XG4gICAgICAgICAgaWYgKCFfY29udGV4dDMuc2VudCkge1xuICAgICAgICAgICAgX2NvbnRleHQzLm5leHQgPSAxMjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dDMubmV4dCA9IDEwO1xuICAgICAgICAgIHJldHVybiBjb25maWdfcmVxdWVzdC5qc29uKCk7XG4gICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgY29uZmlnID0gX2NvbnRleHQzLnNlbnQ7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJMb2FkZWQgY29uZmlnXCIpO1xuICAgICAgICBjYXNlIDEyOlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0My5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTMpO1xuICB9KSk7XG4gIHJldHVybiBfZ2V0Q29uZmlnLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBsb2dpbihfeDUpIHtcbiAgcmV0dXJuIF9sb2dpbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2xvZ2luKCkge1xuICBfbG9naW4gPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWU0KHBhc3N3b3JkVG9UcnkpIHtcbiAgICB2YXIgbG9naW5TdWNjZXNzLCBwYXNzd29yZCwgZm9ybSwgcmVzcG9uc2UsIHJlc3VsdDtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTQkKF9jb250ZXh0NCkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQ0LnByZXYgPSBfY29udGV4dDQubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgY29uc29sZS5sb2coXCJQZXJmb3JtaW5nIGxvZ2luXCIpO1xuICAgICAgICAgIGxvZ2luU3VjY2VzcyA9IGZhbHNlO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgaWYgKHBhc3N3b3JkVG9UcnkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCJVc2luZyBwYXNzd29yZCB0byB0cnkgZnJvbSBwYXJhbWV0ZXJcIik7XG4gICAgICAgICAgICBwYXNzd29yZCA9IHBhc3N3b3JkVG9Ucnk7XG4gICAgICAgICAgICBwYXNzd29yZFRvVHJ5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIlByb21wdGluZyB1c2VyIGZvciBzaGFyZWQgc2VjcmV0LlwiKTtcbiAgICAgICAgICAgIHBhc3N3b3JkID0gcHJvbXB0KFwicHJvdmlkZSB0aGUgc2hhcmVkIHNlY3JldFwiKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZm9ybSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgIGZvcm0uYXBwZW5kKFwiZ3JhbnRfdHlwZVwiLCBcInBhc3N3b3JkXCIpO1xuICAgICAgICAgIGZvcm0uYXBwZW5kKFwidXNlcm5hbWVcIiwgXCJ3b3JrZXJcIik7XG4gICAgICAgICAgZm9ybS5hcHBlbmQoXCJwYXNzd29yZFwiLCBwYXNzd29yZCk7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJSZXF1ZXN0aW5nIHRva2VuLlwiKTtcbiAgICAgICAgICBfY29udGV4dDQubmV4dCA9IDEwO1xuICAgICAgICAgIHJldHVybiBmZXRjaChjb25maWcuYmFja2VuZF91cmwgKyBcIi90b2tlblwiLCB7XG4gICAgICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICAgICAgYm9keTogZm9ybVxuICAgICAgICAgIH0pO1xuICAgICAgICBjYXNlIDEwOlxuICAgICAgICAgIHJlc3BvbnNlID0gX2NvbnRleHQ0LnNlbnQ7XG4gICAgICAgICAgX2NvbnRleHQ0Lm5leHQgPSAxMztcbiAgICAgICAgICByZXR1cm4gY2hlY2tSZXNwb25zZUZvckVycm9yKHJlc3BvbnNlLCBcIkxvZ2luIGZhaWxlZFwiKTtcbiAgICAgICAgY2FzZSAxMzpcbiAgICAgICAgICBpZiAoIV9jb250ZXh0NC5zZW50KSB7XG4gICAgICAgICAgICBfY29udGV4dDQubmV4dCA9IDIwO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0NC5uZXh0ID0gMTY7XG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgY2FzZSAxNjpcbiAgICAgICAgICByZXN1bHQgPSBfY29udGV4dDQuc2VudDtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkdvdCB0b2tlblwiKTtcbiAgICAgICAgICB3aW5kb3cuc2Vzc2lvblN0b3JhZ2Uuc2V0SXRlbShcImFjY2Vzc190b2tlblwiLCByZXN1bHQuYWNjZXNzX3Rva2VuKTtcbiAgICAgICAgICBsb2dpblN1Y2Nlc3MgPSB0cnVlO1xuICAgICAgICBjYXNlIDIwOlxuICAgICAgICAgIGlmICghbG9naW5TdWNjZXNzKSB7XG4gICAgICAgICAgICBfY29udGV4dDQubmV4dCA9IDI7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIGNhc2UgMjE6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ0LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlNCk7XG4gIH0pKTtcbiAgcmV0dXJuIF9sb2dpbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gdXBkYXRlSXRlbXNWaWV3KCkge1xuICBjb25zb2xlLmxvZyhcIlVwZGF0aW5nIGl0ZW1zIHZpZXdcIik7XG4gIHZhciBpdGVtcyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjaXRlbXNcIik7XG4gIGl0ZW1zLmlubmVySFRNTCA9IFwiXCI7XG4gIGZvciAodmFyIGl0ZW0gaW4gcmVjZWl2ZWRfaXRlbXMpIHtcbiAgICB2YXIgbGkgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwibGlcIik7XG4gICAgY29uc29sZS5sb2coaXRlbSk7XG4gICAgY29uc29sZS5sb2cocmVjZWl2ZWRfaXRlbXNbaXRlbV0pO1xuICAgIGxpLmlubmVySFRNTCA9IFwiPGRpdiBpZD1cXFwiaXRlbV9cIiArIHJlY2VpdmVkX2l0ZW1zW2l0ZW1dLml0ZW0udXVpZCArIFwiXFxcIiBjbGFzcz1cXFwiYWxlcnQgYWxlcnQtc3VjY2Vzc1xcXCIgcm9sZT1cXFwiYWxlcnRcXFwiPlwiICsgcmVjZWl2ZWRfaXRlbXNbaXRlbV0uaXRlbS50YWcgKyBcIiAoXCIgKyByZWNlaXZlZF9pdGVtc1tpdGVtXS5pdGVtLmFkZHJlc3NlZSArIFwiLCBcIiArIHJlY2VpdmVkX2l0ZW1zW2l0ZW1dLml0ZW0udGVhbSArIFwiKVwiICsgXCImZW1zcDs8c3BhbiBjbGFzcz1cXFwiYmFkZ2UgYmFkZ2UtbGlnaHRcXFwiPlwiICsgcmVjZWl2ZWRfaXRlbXNbaXRlbV0ubnVtICsgXCI8L3NwYW4+XCIgKyBcIiZlbXNwOzxidXR0b24gY2xhc3M9XFxcImJ0biBidG4tcHJpbWFyeVxcXCIgb25jbGljaz1cXFwibGliLmluY3JlYXNlSXRlbUNvdW50KCdcIiArIHJlY2VpdmVkX2l0ZW1zW2l0ZW1dLml0ZW0udXVpZCArIFwiJylcXFwiPis8L2J1dHRvbj5cIiArIFwiJmVtc3A7PGJ1dHRvbiBjbGFzcz1cXFwiYnRuIGJ0bi1wcmltYXJ5XFxcIiBvbmNsaWNrPVxcXCJsaWIuZGVjcmVhc2VJdGVtQ291bnQoJ1wiICsgcmVjZWl2ZWRfaXRlbXNbaXRlbV0uaXRlbS51dWlkICsgXCInKVxcXCI+LTwvYnV0dG9uPjwvZGl2PlwiO1xuICAgIGl0ZW1zLmFwcGVuZENoaWxkKGxpKTtcbiAgfVxufVxuXG4vKlxuICogdmFyaW91cyBhZGQgSXRlbXMgZnVuY3Rpb25zXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG9uVGFnVGV4dFVwZGF0ZShfeDYpIHtcbiAgcmV0dXJuIF9vblRhZ1RleHRVcGRhdGUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9vblRhZ1RleHRVcGRhdGUoKSB7XG4gIF9vblRhZ1RleHRVcGRhdGUgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWU1KGVsZW1lbnQpIHtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTUkKF9jb250ZXh0NSkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQ1LnByZXYgPSBfY29udGV4dDUubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgaWYgKCEoZWxlbWVudC52YWx1ZS5sZW5ndGggPT0gMCkpIHtcbiAgICAgICAgICAgIF9jb250ZXh0NS5uZXh0ID0gNTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbGVtZW50LnNldEN1c3RvbVZhbGlkaXR5KFwiXCIpO1xuICAgICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShcImlzLWludmFsaWRcIik7XG4gICAgICAgICAgX2NvbnRleHQ1Lm5leHQgPSAxMjtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSA1OlxuICAgICAgICAgIGlmICghKGVsZW1lbnQudmFsdWUubGVuZ3RoICE9IDYpKSB7XG4gICAgICAgICAgICBfY29udGV4dDUubmV4dCA9IDExO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsZW1lbnQuc2V0Q3VzdG9tVmFsaWRpdHkoXCJDb2RlIG11c3QgYmUgNiBjaGFycyBsb25nLlwiKTtcbiAgICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5hZGQoXCJpcy1pbnZhbGlkXCIpO1xuICAgICAgICAgIHJldHVybiBfY29udGV4dDUuYWJydXB0KFwicmV0dXJuXCIpO1xuICAgICAgICBjYXNlIDExOlxuICAgICAgICAgIHRhZ0VudGVyZWQoZWxlbWVudCk7XG4gICAgICAgIGNhc2UgMTI6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ1LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlNSk7XG4gIH0pKTtcbiAgcmV0dXJuIF9vblRhZ1RleHRVcGRhdGUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBvblRhZ0lucHV0Q2hhbmdlZChfeDcpIHtcbiAgcmV0dXJuIF9vblRhZ0lucHV0Q2hhbmdlZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX29uVGFnSW5wdXRDaGFuZ2VkKCkge1xuICBfb25UYWdJbnB1dENoYW5nZWQgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWU2KGVsZW1lbnQpIHtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTYkKF9jb250ZXh0Nikge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQ2LnByZXYgPSBfY29udGV4dDYubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgLy8gRWxlbWVudCBsb3N0IGZvY3VzIG9yIHVzZXIgcHJlc3NlZCBlbnRlclxuICAgICAgICAgIGlmIChlbGVtZW50LnZhbHVlLmxlbmd0aCA9PSA2KSB7XG4gICAgICAgICAgICB0YWdFbnRlcmVkKGVsZW1lbnQpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbGVtZW50LnJlcG9ydFZhbGlkaXR5KCk7XG4gICAgICAgICAgfVxuICAgICAgICBjYXNlIDE6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ2LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlNik7XG4gIH0pKTtcbiAgcmV0dXJuIF9vblRhZ0lucHV0Q2hhbmdlZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gdGFnRW50ZXJlZChfeDgpIHtcbiAgcmV0dXJuIF90YWdFbnRlcmVkLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfdGFnRW50ZXJlZCgpIHtcbiAgX3RhZ0VudGVyZWQgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWU3KGVsZW1lbnQpIHtcbiAgICB2YXIgdGFnLCBzdWNjO1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlNyQoX2NvbnRleHQ3KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDcucHJldiA9IF9jb250ZXh0Ny5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICB0YWcgPSBlbGVtZW50LnZhbHVlO1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiVGFnIEVudGVyZWRcIiwgdGFnKTtcbiAgICAgICAgICBpZiAoIWN1cnJlbnRseUFkZGluZ0l0ZW1CeVRhZy5oYXModGFnKSkge1xuICAgICAgICAgICAgX2NvbnRleHQ3Lm5leHQgPSA0O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBfY29udGV4dDcuYWJydXB0KFwicmV0dXJuXCIpO1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgY3VycmVudGx5QWRkaW5nSXRlbUJ5VGFnLnNldCh0YWcsIFwiXCIpO1xuICAgICAgICAgIF9jb250ZXh0Ny5uZXh0ID0gNztcbiAgICAgICAgICByZXR1cm4gYWRkSXRlbUJ5VGFnKGVsZW1lbnQudmFsdWUpO1xuICAgICAgICBjYXNlIDc6XG4gICAgICAgICAgc3VjYyA9IF9jb250ZXh0Ny5zZW50O1xuICAgICAgICAgIGlmIChzdWNjKSB7XG4gICAgICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoXCJpcy1pbnZhbGlkXCIpO1xuICAgICAgICAgICAgZWxlbWVudC52YWx1ZSA9IFwiXCI7XG4gICAgICAgICAgICBlbGVtZW50LnNldEN1c3RvbVZhbGlkaXR5KFwiXCIpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbGVtZW50LnNldEN1c3RvbVZhbGlkaXR5KFwiVW5rbm93biBpdGVtXCIpO1xuICAgICAgICAgICAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKFwiaXMtaW52YWxpZFwiKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxlbWVudC5yZXBvcnRWYWxpZGl0eSgpO1xuICAgICAgICAgIGN1cnJlbnRseUFkZGluZ0l0ZW1CeVRhZ1tcImRlbGV0ZVwiXSh0YWcpO1xuICAgICAgICBjYXNlIDExOlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0Ny5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTcpO1xuICB9KSk7XG4gIHJldHVybiBfdGFnRW50ZXJlZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGFkZEl0ZW1CeVRhZyhfeDkpIHtcbiAgcmV0dXJuIF9hZGRJdGVtQnlUYWcuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9hZGRJdGVtQnlUYWcoKSB7XG4gIF9hZGRJdGVtQnlUYWcgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWU4KHRhZykge1xuICAgIHZhciByZXNwb25zZSwgdHJhY2tpbmdfaXRlbTtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTgkKF9jb250ZXh0OCkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQ4LnByZXYgPSBfY29udGV4dDgubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgaWYgKCEodGFnLmxlbmd0aCAhPSA2KSkge1xuICAgICAgICAgICAgX2NvbnRleHQ4Lm5leHQgPSAyO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRocm93IFwiSW50ZXJuYWwgRXJyb3I6IFRhZyBub3QgbGVuZ3RoIDYuXCI7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICB0YWcgPSB0YWcudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIlRyeWluZyB0byBhZGQgaXRlbSBieSB0YWc6XCIsIHRhZyk7XG4gICAgICAgICAgX2NvbnRleHQ4Lm5leHQgPSA2O1xuICAgICAgICAgIHJldHVybiBmZXRjaFdpdGhBdXRoKGNvbmZpZy5iYWNrZW5kX3VybCArIFwiL3RhZy9cIiArIHRhZyk7XG4gICAgICAgIGNhc2UgNjpcbiAgICAgICAgICByZXNwb25zZSA9IF9jb250ZXh0OC5zZW50O1xuICAgICAgICAgIGlmICghKHJlc3BvbnNlLnN0YXR1cyA9PSAyMDApKSB7XG4gICAgICAgICAgICBfY29udGV4dDgubmV4dCA9IDE4O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0OC5uZXh0ID0gMTA7XG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgY2FzZSAxMDpcbiAgICAgICAgICB0cmFja2luZ19pdGVtID0gX2NvbnRleHQ4LnNlbnQ7XG4gICAgICAgICAgaWYgKHRyYWNraW5nX2l0ZW0udXVpZCBpbiByZWNlaXZlZF9pdGVtcykge1xuICAgICAgICAgICAgcmVjZWl2ZWRfaXRlbXNbdHJhY2tpbmdfaXRlbS51dWlkXS5udW0gKz0gMTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVjZWl2ZWRfaXRlbXNbdHJhY2tpbmdfaXRlbS51dWlkXSA9IHtcbiAgICAgICAgICAgICAgXCJudW1cIjogMSxcbiAgICAgICAgICAgICAgXCJpdGVtXCI6IHRyYWNraW5nX2l0ZW1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICAgIHVwZGF0ZUl0ZW1zVmlldygpO1xuICAgICAgICAgIHNjYW5uZXJfYXVkaW8ucGxheSgpO1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiQWRkZWQgaXRlbSBieSB0YWdcIik7XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0OC5hYnJ1cHQoXCJyZXR1cm5cIiwgdHJ1ZSk7XG4gICAgICAgIGNhc2UgMTg6XG4gICAgICAgICAgaWYgKCEocmVzcG9uc2Uuc3RhdHVzID09IDQwNCkpIHtcbiAgICAgICAgICAgIF9jb250ZXh0OC5uZXh0ID0gMjM7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc29sZS5sb2coXCJJdGVtIG5vdCBmb3VuZFwiKTtcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ4LmFicnVwdChcInJldHVyblwiLCBmYWxzZSk7XG4gICAgICAgIGNhc2UgMjM6XG4gICAgICAgICAgY2hlY2tSZXNwb25zZUZvckVycm9yKHJlc3BvbnNlLCBcIkZhaWxlZCB0byBnZXQgaXRlbSBmcm9tIGJhY2tlbmRcIik7XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0OC5hYnJ1cHQoXCJyZXR1cm5cIiwgZmFsc2UpO1xuICAgICAgICBjYXNlIDI1OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0OC5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTgpO1xuICB9KSk7XG4gIHJldHVybiBfYWRkSXRlbUJ5VGFnLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBoYW5kbGVRckVycm9yKF94MTAsIF94MTEpIHtcbiAgcmV0dXJuIF9oYW5kbGVRckVycm9yLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfaGFuZGxlUXJFcnJvcigpIHtcbiAgX2hhbmRsZVFyRXJyb3IgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWU5KG1zZywgZXJyKSB7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWU5JChfY29udGV4dDkpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0OS5wcmV2ID0gX2NvbnRleHQ5Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDkuYWJydXB0KFwicmV0dXJuXCIpO1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ5LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlOSk7XG4gIH0pKTtcbiAgcmV0dXJuIF9oYW5kbGVRckVycm9yLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBkZWJvdW5jZVNjYW5uZXIoKSB7XG4gIGlmIChzY2FubmVyLmdldFN0YXRlKCkgIT0gSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuU0NBTk5JTkcpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgc2Nhbm5lci5wYXVzZShmYWxzZSk7XG4gIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgIGlmIChzY2FubmVyLmdldFN0YXRlKCkgPT0gSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICBzY2FubmVyLnJlc3VtZSgpO1xuICAgIH1cbiAgfSwgMTAwMCk7XG59XG5mdW5jdGlvbiBoYW5kbGVJdGVtU2NhblJlc3VsdChfeDEyKSB7XG4gIHJldHVybiBfaGFuZGxlSXRlbVNjYW5SZXN1bHQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9oYW5kbGVJdGVtU2NhblJlc3VsdCgpIHtcbiAgX2hhbmRsZUl0ZW1TY2FuUmVzdWx0ID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMTAoaXRlbV91dWlkKSB7XG4gICAgdmFyIHJlc3BvbnNlLCB0cmFja2luZ19pdGVtO1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMTAkKF9jb250ZXh0MTApIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MTAucHJldiA9IF9jb250ZXh0MTAubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgZGVib3VuY2VTY2FubmVyKCk7XG4gICAgICAgICAgaWYgKCEoaXRlbV91dWlkLmxlbmd0aCA9PSAzNikpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTAubmV4dCA9IDI3O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiVHJ5aW5nIHRvIGFkZCBpdGVtIGJ5IHV1aWQgKHNjYW5uZWQpXCIpO1xuICAgICAgICAgIGlmICghKGl0ZW1fdXVpZCBpbiByZWNlaXZlZF9pdGVtcykpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTAubmV4dCA9IDEwO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlY2VpdmVkX2l0ZW1zW2l0ZW1fdXVpZF0ubnVtICs9IDE7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJJbmNyZWFzZWQgY291bnQgb2YgZXhpc3RpbmcgaXRlbSB1dWlkXCIpO1xuICAgICAgICAgIHVwZGF0ZUl0ZW1zVmlldygpO1xuICAgICAgICAgIHNjYW5uZXJfYXVkaW8ucGxheSgpO1xuICAgICAgICAgIF9jb250ZXh0MTAubmV4dCA9IDI1O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDEwOlxuICAgICAgICAgIHJlY2VpdmVkX2l0ZW1zW2l0ZW1fdXVpZF0gPSB7XG4gICAgICAgICAgICBcIm51bVwiOiAxLFxuICAgICAgICAgICAgXCJpdGVtXCI6IG51bGxcbiAgICAgICAgICB9O1xuICAgICAgICAgIF9jb250ZXh0MTAubmV4dCA9IDEzO1xuICAgICAgICAgIHJldHVybiBmZXRjaFdpdGhBdXRoKGNvbmZpZy5iYWNrZW5kX3VybCArIFwiL2l0ZW0vXCIgKyBpdGVtX3V1aWQpO1xuICAgICAgICBjYXNlIDEzOlxuICAgICAgICAgIHJlc3BvbnNlID0gX2NvbnRleHQxMC5zZW50O1xuICAgICAgICAgIGlmICghKHJlc3BvbnNlLnN0YXR1cyA9PSAyMDApKSB7XG4gICAgICAgICAgICBfY29udGV4dDEwLm5leHQgPSAyNDtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dDEwLm5leHQgPSAxNztcbiAgICAgICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuICAgICAgICBjYXNlIDE3OlxuICAgICAgICAgIHRyYWNraW5nX2l0ZW0gPSBfY29udGV4dDEwLnNlbnQ7XG4gICAgICAgICAgcmVjZWl2ZWRfaXRlbXNbaXRlbV91dWlkXSA9IHtcbiAgICAgICAgICAgIFwibnVtXCI6IDEsXG4gICAgICAgICAgICBcIml0ZW1cIjogdHJhY2tpbmdfaXRlbVxuICAgICAgICAgIH07XG4gICAgICAgICAgdXBkYXRlSXRlbXNWaWV3KCk7XG4gICAgICAgICAgc2Nhbm5lcl9hdWRpby5wbGF5KCk7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJBZGRlZCBpdGVtIGJ5IHV1aWQuXCIpO1xuICAgICAgICAgIF9jb250ZXh0MTAubmV4dCA9IDI1O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDI0OlxuICAgICAgICAgIGlmIChyZXNwb25zZS5zdGF0dXMgPT0gNDA0KSB7XG4gICAgICAgICAgICBhbGVydChcIkl0ZW0gbm90IGZvdW5kXCIpO1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCJJdGVtIG5vdCBmb3VuZFwiKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2hlY2tSZXNwb25zZUZvckVycm9yKHJlc3BvbnNlLCBcIkZhaWxlZCB0byBnZXQgaXRlbSBmcm9tIGJhY2tlbmRcIik7XG4gICAgICAgICAgfVxuICAgICAgICBjYXNlIDI1OlxuICAgICAgICAgIF9jb250ZXh0MTAubmV4dCA9IDI4O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDI3OlxuICAgICAgICAgIGFsZXJ0KFwiUVIgQ29kZSBpcyBub3QgYSBiZ3AgY2hlY2tpbiBjb2RlLlwiKTtcbiAgICAgICAgY2FzZSAyODpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDEwLnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMTApO1xuICB9KSk7XG4gIHJldHVybiBfaGFuZGxlSXRlbVNjYW5SZXN1bHQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBhZGRJdGVtU2NhbigpIHtcbiAgcmV0dXJuIF9hZGRJdGVtU2Nhbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2FkZEl0ZW1TY2FuKCkge1xuICBfYWRkSXRlbVNjYW4gPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUxMSgpIHtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTExJChfY29udGV4dDExKSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDExLnByZXYgPSBfY29udGV4dDExLm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiU3RhcnRpbmcgc2Nhbm5lclwiKTtcbiAgICAgICAgICBzY2FubmVyLnJlbmRlcihoYW5kbGVJdGVtU2NhblJlc3VsdCwgaGFuZGxlUXJFcnJvcik7XG4gICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJzdGFydFNjYW5cIikuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwic3RvcFNjYW5cIikuc3R5bGUuZGlzcGxheSA9IFwiaW5saW5lLWJsb2NrXCI7XG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDExLnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMTEpO1xuICB9KSk7XG4gIHJldHVybiBfYWRkSXRlbVNjYW4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBzdG9wU2Nhbm5pbmdJdGVtKCkge1xuICByZXR1cm4gX3N0b3BTY2FubmluZ0l0ZW0uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9zdG9wU2Nhbm5pbmdJdGVtKCkge1xuICBfc3RvcFNjYW5uaW5nSXRlbSA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTEyKCkge1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMTIkKF9jb250ZXh0MTIpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MTIucHJldiA9IF9jb250ZXh0MTIubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgY29uc29sZS5sb2coXCJTdG9wcGluZyBzY2FubmVyXCIpO1xuICAgICAgICAgIHNjYW5uZXIuY2xlYXIoKTtcbiAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInN0YXJ0U2NhblwiKS5zdHlsZS5kaXNwbGF5ID0gXCJpbmxpbmUtYmxvY2tcIjtcbiAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInN0b3BTY2FuXCIpLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTIuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUxMik7XG4gIH0pKTtcbiAgcmV0dXJuIF9zdG9wU2Nhbm5pbmdJdGVtLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5leHBvcnQgZnVuY3Rpb24gYWRkSXRlbUltYWdlKF94MTMpIHtcbiAgcmV0dXJuIF9hZGRJdGVtSW1hZ2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9hZGRJdGVtSW1hZ2UoKSB7XG4gIF9hZGRJdGVtSW1hZ2UgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUxMyhlKSB7XG4gICAgdmFyIGZvcm0sIHJlc3BvbnNlLCB0cmFja2luZ19pdGVtO1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMTMkKF9jb250ZXh0MTMpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MTMucHJldiA9IF9jb250ZXh0MTMubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgY29uc29sZS5sb2coXCJBZGRpbmcgaXRlbSAgYnkgaW1hZ2VcIik7XG4gICAgICAgICAgZm9ybSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgIGZvcm0uYXBwZW5kKFwiaW1hZ2VcIiwgZS5maWxlc1swXSk7XG4gICAgICAgICAgX2NvbnRleHQxMy5uZXh0ID0gNTtcbiAgICAgICAgICByZXR1cm4gZmV0Y2hXaXRoQXV0aChjb25maWcuYmFja2VuZF91cmwgKyBcIi9pdGVtL3JlZ2lzdGVyXCIsIHtcbiAgICAgICAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICAgICAgICBib2R5OiBmb3JtXG4gICAgICAgICAgfSk7XG4gICAgICAgIGNhc2UgNTpcbiAgICAgICAgICByZXNwb25zZSA9IF9jb250ZXh0MTMuc2VudDtcbiAgICAgICAgICBfY29udGV4dDEzLm5leHQgPSA4O1xuICAgICAgICAgIHJldHVybiBjaGVja1Jlc3BvbnNlRm9yRXJyb3IocmVzcG9uc2UsIFwiRmFpbGVkIHRvIHNhdmUgaXRlbVwiKTtcbiAgICAgICAgY2FzZSA4OlxuICAgICAgICAgIGlmICghX2NvbnRleHQxMy5zZW50KSB7XG4gICAgICAgICAgICBfY29udGV4dDEzLm5leHQgPSAxNjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dDEzLm5leHQgPSAxMTtcbiAgICAgICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuICAgICAgICBjYXNlIDExOlxuICAgICAgICAgIHRyYWNraW5nX2l0ZW0gPSBfY29udGV4dDEzLnNlbnQ7XG4gICAgICAgICAgcmVjZWl2ZWRfaXRlbXNbdHJhY2tpbmdfaXRlbS51dWlkXSA9IHtcbiAgICAgICAgICAgIFwibnVtXCI6IDEsXG4gICAgICAgICAgICBcIml0ZW1cIjogdHJhY2tpbmdfaXRlbVxuICAgICAgICAgIH07XG4gICAgICAgICAgdXBkYXRlSXRlbXNWaWV3KCk7XG4gICAgICAgICAgc2Nhbm5lcl9hdWRpby5wbGF5KCk7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJBZGRlZCBpdGVtIGJ5IGltYWdlLlwiKTtcbiAgICAgICAgY2FzZSAxNjpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDEzLnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMTMpO1xuICB9KSk7XG4gIHJldHVybiBfYWRkSXRlbUltYWdlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5leHBvcnQgZnVuY3Rpb24gZGVjcmVhc2VJdGVtQ291bnQoX3gxNCkge1xuICByZXR1cm4gX2RlY3JlYXNlSXRlbUNvdW50LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfZGVjcmVhc2VJdGVtQ291bnQoKSB7XG4gIF9kZWNyZWFzZUl0ZW1Db3VudCA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTE0KHV1aWQpIHtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTE0JChfY29udGV4dDE0KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDE0LnByZXYgPSBfY29udGV4dDE0Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGlmICghKHJlY2VpdmVkX2l0ZW1zW3V1aWRdID09IG51bGwpKSB7XG4gICAgICAgICAgICBfY29udGV4dDE0Lm5leHQgPSAzO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiVHJ5aW5nIHRvIGRlY3JlYXNlIGl0ZW0gY291bnQgb2YgdW5rbm93biBpdGVtXCIsIHV1aWQpO1xuICAgICAgICAgIHJldHVybiBfY29udGV4dDE0LmFicnVwdChcInJldHVyblwiKTtcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiRGVjcmVhc2luZyBpdGVtIGNvdW50IG9mXCIsIHV1aWQpO1xuICAgICAgICAgIHJlY2VpdmVkX2l0ZW1zW3V1aWRdW1wibnVtXCJdLS07XG4gICAgICAgICAgaWYgKHJlY2VpdmVkX2l0ZW1zW3V1aWRdW1wibnVtXCJdIDw9IDApIHtcbiAgICAgICAgICAgIGRlbGV0ZSByZWNlaXZlZF9pdGVtc1t1dWlkXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdXBkYXRlSXRlbXNWaWV3KCk7XG4gICAgICAgIGNhc2UgNzpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDE0LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMTQpO1xuICB9KSk7XG4gIHJldHVybiBfZGVjcmVhc2VJdGVtQ291bnQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBpbmNyZWFzZUl0ZW1Db3VudChfeDE1KSB7XG4gIHJldHVybiBfaW5jcmVhc2VJdGVtQ291bnQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cblxuLypcbiAqIENoZWNraW4gdGhlIHNlbGVjdGVkIGl0ZW1zXG4gKi9cbmZ1bmN0aW9uIF9pbmNyZWFzZUl0ZW1Db3VudCgpIHtcbiAgX2luY3JlYXNlSXRlbUNvdW50ID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMTUodXVpZCkge1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMTUkKF9jb250ZXh0MTUpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MTUucHJldiA9IF9jb250ZXh0MTUubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgaWYgKCEocmVjZWl2ZWRfaXRlbXNbdXVpZF0gPT0gbnVsbCkpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTUubmV4dCA9IDM7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc29sZS5sb2coXCJUcnlpbmcgdG8gaW5jcmVhc2UgaXRlbSBjb3VudCBvZiB1bmtub3duIGl0ZW1cIiwgdXVpZCk7XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTUuYWJydXB0KFwicmV0dXJuXCIpO1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgY29uc29sZS5sb2coXCJJbmNyZWFzaW5nIGl0ZW0gY291bnQgb2ZcIiwgdXVpZCk7XG4gICAgICAgICAgcmVjZWl2ZWRfaXRlbXNbdXVpZF1bXCJudW1cIl0rKztcbiAgICAgICAgICB1cGRhdGVJdGVtc1ZpZXcoKTtcbiAgICAgICAgY2FzZSA2OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTUuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUxNSk7XG4gIH0pKTtcbiAgcmV0dXJuIF9pbmNyZWFzZUl0ZW1Db3VudC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGNoZWNraW5JdGVtcygpIHtcbiAgcmV0dXJuIF9jaGVja2luSXRlbXMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9jaGVja2luSXRlbXMoKSB7XG4gIF9jaGVja2luSXRlbXMgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUxNigpIHtcbiAgICB2YXIgc3VjY2Vzc2Z1bGxDb3VudCwgaXRlbSwgcmVzcG9uc2UsIHRyYWNraW5nX2l0ZW07XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUxNiQoX2NvbnRleHQxNikge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQxNi5wcmV2ID0gX2NvbnRleHQxNi5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkNoZWNraW5nIGluIGl0ZW1zXCIpO1xuICAgICAgICAgIHN1Y2Nlc3NmdWxsQ291bnQgPSAwO1xuICAgICAgICAgIF9jb250ZXh0MTYudDAgPSBfcmVnZW5lcmF0b3JSdW50aW1lKCkua2V5cyhyZWNlaXZlZF9pdGVtcyk7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICBpZiAoKF9jb250ZXh0MTYudDEgPSBfY29udGV4dDE2LnQwKCkpLmRvbmUpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTYubmV4dCA9IDE4O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGl0ZW0gPSBfY29udGV4dDE2LnQxLnZhbHVlO1xuICAgICAgICAgIF9jb250ZXh0MTYubmV4dCA9IDc7XG4gICAgICAgICAgcmV0dXJuIGZldGNoV2l0aEF1dGgoY29uZmlnLmJhY2tlbmRfdXJsICsgXCIvY2hlY2tpblwiLCB7XG4gICAgICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgXCJpdGVtX3V1aWRcIjogcmVjZWl2ZWRfaXRlbXNbaXRlbV0uaXRlbS51dWlkLFxuICAgICAgICAgICAgICBcInN0b3JhZ2VfbmFtZVwiOiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3N0b3JhZ2Vfc2VsZWN0XCIpLnZhbHVlLFxuICAgICAgICAgICAgICBcImFtb3VudFwiOiByZWNlaXZlZF9pdGVtc1tpdGVtXS5udW1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgfSk7XG4gICAgICAgIGNhc2UgNzpcbiAgICAgICAgICByZXNwb25zZSA9IF9jb250ZXh0MTYuc2VudDtcbiAgICAgICAgICBfY29udGV4dDE2Lm5leHQgPSAxMDtcbiAgICAgICAgICByZXR1cm4gY2hlY2tSZXNwb25zZUZvckVycm9yKHJlc3BvbnNlLCBcIkZhaWxlZCB0byBjaGVja2luIGl0ZW0gXCIgKyByZWNlaXZlZF9pdGVtc1tpdGVtXS5pdGVtLnRhZyk7XG4gICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgaWYgKCFfY29udGV4dDE2LnNlbnQpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTYubmV4dCA9IDE2O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0MTYubmV4dCA9IDEzO1xuICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgIGNhc2UgMTM6XG4gICAgICAgICAgdHJhY2tpbmdfaXRlbSA9IF9jb250ZXh0MTYuc2VudDtcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gICAgICAgICAgZGVsZXRlIHJlY2VpdmVkX2l0ZW1zW3RyYWNraW5nX2l0ZW0udXVpZF07XG4gICAgICAgICAgc3VjY2Vzc2Z1bGxDb3VudCsrO1xuICAgICAgICBjYXNlIDE2OlxuICAgICAgICAgIF9jb250ZXh0MTYubmV4dCA9IDM7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMTg6XG4gICAgICAgICAgdG9hc3QoXCJDaGVjay1JbiBzdWNjZXNzZnVsbC5cIiwgXCJUaGUgY2hlY2staW4gb2YgXCIgKyBzdWNjZXNzZnVsbENvdW50ICsgXCIgaXRlbXMgY29tcGxldGVkIHN1Y2Nlc2Z1bGx5LlwiKTtcbiAgICAgICAgICB1cGRhdGVJdGVtc1ZpZXcoKTtcbiAgICAgICAgY2FzZSAyMDpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDE2LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMTYpO1xuICB9KSk7XG4gIHJldHVybiBfY2hlY2tpbkl0ZW1zLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiB1cGRhdGVDaGVja291dEl0ZW0odHJhY2tpbmdfaXRlbSkge1xuICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3V1aWRcIikuaW5uZXJIVE1MID0gdHJhY2tpbmdfaXRlbS51dWlkO1xuICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3RhZ1wiKS5pbm5lckhUTUwgPSB0cmFja2luZ19pdGVtLnRhZztcbiAgZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNzdG9yYWdlXCIpLmlubmVySFRNTCA9IHRyYWNraW5nX2l0ZW0uc3RvcmFnZTtcbiAgZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNhZGRyZXNzZWVcIikuaW5uZXJIVE1MID0gdHJhY2tpbmdfaXRlbS5hZGRyZXNzZWU7XG4gIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjdGVhbVwiKS5pbm5lckhUTUwgPSB0cmFja2luZ19pdGVtLnRlYW07XG59XG5mdW5jdGlvbiBvblJlY2V2aWVyU2NhblN1Y2Nlc3MoX3gxNikge1xuICByZXR1cm4gX29uUmVjZXZpZXJTY2FuU3VjY2Vzcy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX29uUmVjZXZpZXJTY2FuU3VjY2VzcygpIHtcbiAgX29uUmVjZXZpZXJTY2FuU3VjY2VzcyA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTE3KHNjYW5uZWRDb2RlKSB7XG4gICAgdmFyIF9zY2FubmVkQ29kZSRzcGxpdCwgX3NjYW5uZWRDb2RlJHNwbGl0MiwgdXVpZCwgc2lnbmF0dXJlLCByZXNwb25zZSwgdHJhY2tpbmdfaXRlbTtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTE3JChfY29udGV4dDE3KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDE3LnByZXYgPSBfY29udGV4dDE3Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGRlYm91bmNlU2Nhbm5lcigpO1xuICAgICAgICAgIF9zY2FubmVkQ29kZSRzcGxpdCA9IHNjYW5uZWRDb2RlLnNwbGl0KFwiL1wiKSwgX3NjYW5uZWRDb2RlJHNwbGl0MiA9IF9zbGljZWRUb0FycmF5KF9zY2FubmVkQ29kZSRzcGxpdCwgMiksIHV1aWQgPSBfc2Nhbm5lZENvZGUkc3BsaXQyWzBdLCBzaWduYXR1cmUgPSBfc2Nhbm5lZENvZGUkc3BsaXQyWzFdO1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiUmVjZWl2ZXIgc2NhbiBzdWNjZXNzXCIpO1xuICAgICAgICAgIHNjYW5uZXJfYXVkaW8ucGxheSgpO1xuICAgICAgICAgIF9jb250ZXh0MTcubmV4dCA9IDY7XG4gICAgICAgICAgcmV0dXJuIGdldENvbmZpZygpO1xuICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgX2NvbnRleHQxNy5uZXh0ID0gODtcbiAgICAgICAgICByZXR1cm4gZmV0Y2goY29uZmlnLmJhY2tlbmRfdXJsICsgXCIvaXRlbS9cIiArIHV1aWQsIHtcbiAgICAgICAgICAgIGhlYWRlcnM6IHt9XG4gICAgICAgICAgfSk7XG4gICAgICAgIGNhc2UgODpcbiAgICAgICAgICByZXNwb25zZSA9IF9jb250ZXh0MTcuc2VudDtcbiAgICAgICAgICBpZiAoIShyZXNwb25zZS5zdGF0dXMgPT0gMjAwKSkge1xuICAgICAgICAgICAgX2NvbnRleHQxNy5uZXh0ID0gMjY7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgX2NvbnRleHQxNy5uZXh0ID0gMTI7XG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgY2FzZSAxMjpcbiAgICAgICAgICB0cmFja2luZ19pdGVtID0gX2NvbnRleHQxNy5zZW50O1xuICAgICAgICAgIGlmICghZWQ0NDgudmVyaWZ5KGh0b2Eoc2lnbmF0dXJlKSwgbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHRyYWNraW5nX2l0ZW0udXVpZCksIGh0b2EodHJhY2tpbmdfaXRlbS52ZXJpZmljYXRpb24pKSkge1xuICAgICAgICAgICAgX2NvbnRleHQxNy5uZXh0ID0gMjI7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCEodHJhY2tpbmdfaXRlbS5zdG9yYWdlID09IHVuZGVmaW5lZCB8fCB0cmFja2luZ19pdGVtLnN0b3JhZ2UgPT0gbnVsbCB8fCB0cmFja2luZ19pdGVtLnN0b3JhZ2UubGVuZ3RoID09IDApKSB7XG4gICAgICAgICAgICBfY29udGV4dDE3Lm5leHQgPSAxODtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBhbGVydChcIkl0ZW0gbm90IHlldCByZWNlaXZlZC5cIik7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJJdGVtIG5vdCB5ZXQgcmVjZWl2ZWQuXCIpO1xuICAgICAgICAgIHJldHVybiBfY29udGV4dDE3LmFicnVwdChcInJldHVyblwiKTtcbiAgICAgICAgY2FzZSAxODpcbiAgICAgICAgICB1cGRhdGVDaGVja291dEl0ZW0odHJhY2tpbmdfaXRlbSk7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJSZWNlaXZlciB2ZXJpZnkgc3VjY2Vzc1wiKTtcbiAgICAgICAgICBfY29udGV4dDE3Lm5leHQgPSAyNDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAyMjpcbiAgICAgICAgICBhbGVydChcIkNvdWxkIG5vdCB2ZXJpZnkgc2lnbmF0dXJlLlwiKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkNvdWxkIG5vdCB2ZXJpZnkgc2lnbmF0dXJlLlwiKTtcbiAgICAgICAgY2FzZSAyNDpcbiAgICAgICAgICBfY29udGV4dDE3Lm5leHQgPSAyNztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAyNjpcbiAgICAgICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09IDQwNCkge1xuICAgICAgICAgICAgYWxlcnQoXCJJdGVtIG5vdCBmb3VuZC5cIik7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNoZWNrUmVzcG9uc2VGb3JFcnJvcihyZXNwb25zZSwgXCJGYWlsZWQgdG8gZ2V0IGl0ZW0gZnJvbSBiYWNrZW5kLlwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIGNhc2UgMjc6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQxNy5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTE3KTtcbiAgfSkpO1xuICByZXR1cm4gX29uUmVjZXZpZXJTY2FuU3VjY2Vzcy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHNjYW5SZWNlaXZlcigpIHtcbiAgcmV0dXJuIF9zY2FuUmVjZWl2ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9zY2FuUmVjZWl2ZXIoKSB7XG4gIF9zY2FuUmVjZWl2ZXIgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUxOCgpIHtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTE4JChfY29udGV4dDE4KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDE4LnByZXYgPSBfY29udGV4dDE4Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiU2Nhbm5pbmcgcmVjZWl2ZXIuXCIpO1xuICAgICAgICAgIHNjYW5uZXIucmVuZGVyKG9uUmVjZXZpZXJTY2FuU3VjY2VzcywgaGFuZGxlUXJFcnJvcik7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDE4LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMTgpO1xuICB9KSk7XG4gIHJldHVybiBfc2NhblJlY2VpdmVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5leHBvcnQgZnVuY3Rpb24gbG9hZFN0b3JhZ2VzKF94MTcpIHtcbiAgcmV0dXJuIF9sb2FkU3RvcmFnZXMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9sb2FkU3RvcmFnZXMoKSB7XG4gIF9sb2FkU3RvcmFnZXMgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUxOShzZWxlY3RlZFN0b3JhZ2UpIHtcbiAgICB2YXIgcmVzcG9uc2UsIHN0b3JhZ2VzLCBzZWxlY3QsIGksIG9wdGlvbjtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTE5JChfY29udGV4dDE5KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDE5LnByZXYgPSBfY29udGV4dDE5Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiUmV0cmlldmluZyBzdG9yYWdlc1wiKTtcbiAgICAgICAgICBfY29udGV4dDE5Lm5leHQgPSAzO1xuICAgICAgICAgIHJldHVybiBmZXRjaFdpdGhBdXRoKGNvbmZpZy5iYWNrZW5kX3VybCArIFwiL3N0b3JhZ2VzXCIpO1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgcmVzcG9uc2UgPSBfY29udGV4dDE5LnNlbnQ7XG4gICAgICAgICAgX2NvbnRleHQxOS5uZXh0ID0gNjtcbiAgICAgICAgICByZXR1cm4gY2hlY2tSZXNwb25zZUZvckVycm9yKHJlc3BvbnNlLCBcIkZhaWxlZCB0byBsb2FkIHN0b3JhZ2VzLlwiKTtcbiAgICAgICAgY2FzZSA2OlxuICAgICAgICAgIGlmICghX2NvbnRleHQxOS5zZW50KSB7XG4gICAgICAgICAgICBfY29udGV4dDE5Lm5leHQgPSAxMztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dDE5Lm5leHQgPSA5O1xuICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgIGNhc2UgOTpcbiAgICAgICAgICBzdG9yYWdlcyA9IF9jb250ZXh0MTkuc2VudDtcbiAgICAgICAgICBzZWxlY3QgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3N0b3JhZ2Vfc2VsZWN0XCIpO1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiR290IHN0b3JhZ2VzXCIpO1xuICAgICAgICAgIGZvciAoaSBpbiBzdG9yYWdlcykge1xuICAgICAgICAgICAgb3B0aW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcIm9wdGlvblwiKTtcbiAgICAgICAgICAgIG9wdGlvbi50ZXh0Q29udGVudCA9IHN0b3JhZ2VzW2ldLm5hbWU7XG4gICAgICAgICAgICBvcHRpb24udmFsdWUgPSBzdG9yYWdlc1tpXS5uYW1lO1xuICAgICAgICAgICAgc2VsZWN0LmFwcGVuZENoaWxkKG9wdGlvbik7XG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWRTdG9yYWdlID09IHN0b3JhZ2VzW2ldLm5hbWUpIHtcbiAgICAgICAgICAgICAgc2VsZWN0LnZhbHVlID0gc2VsZWN0ZWRTdG9yYWdlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgY2FzZSAxMzpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDE5LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMTkpO1xuICB9KSk7XG4gIHJldHVybiBfbG9hZFN0b3JhZ2VzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5leHBvcnQgZnVuY3Rpb24gb25QYWdlTG9hZChfeDE4KSB7XG4gIHJldHVybiBfb25QYWdlTG9hZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX29uUGFnZUxvYWQoKSB7XG4gIF9vblBhZ2VMb2FkID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMjAoZG9sb2FkU3RvcmFnZXMpIHtcbiAgICB2YXIgcHc7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUyMCQoX2NvbnRleHQyMCkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQyMC5wcmV2ID0gX2NvbnRleHQyMC5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBfY29udGV4dDIwLm5leHQgPSAyO1xuICAgICAgICAgIHJldHVybiBnZXRDb25maWcoKTtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHB3ID0gd2luZG93LmxvY2F0aW9uLmhhc2guc3Vic3RyaW5nKDEpO1xuICAgICAgICAgIGlmICghKHB3Lmxlbmd0aCA+IDEpKSB7XG4gICAgICAgICAgICBfY29udGV4dDIwLm5leHQgPSA4O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0MjAubmV4dCA9IDY7XG4gICAgICAgICAgcmV0dXJuIGxvZ2luKHB3KTtcbiAgICAgICAgY2FzZSA2OlxuICAgICAgICAgIF9jb250ZXh0MjAubmV4dCA9IDEwO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDg6XG4gICAgICAgICAgX2NvbnRleHQyMC5uZXh0ID0gMTA7XG4gICAgICAgICAgcmV0dXJuIGxvZ2luKCk7XG4gICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgaWYgKGRvbG9hZFN0b3JhZ2VzKSB7XG4gICAgICAgICAgICBsb2FkU3RvcmFnZXMoZG9jdW1lbnQubG9jYXRpb24uc2VhcmNoLnN1YnN0cmluZygxKSk7XG4gICAgICAgICAgfVxuICAgICAgICBjYXNlIDExOlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MjAuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUyMCk7XG4gIH0pKTtcbiAgcmV0dXJuIF9vblBhZ2VMb2FkLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5leHBvcnQgZnVuY3Rpb24gY2hlY2tvdXRCeVRhZygpIHtcbiAgcmV0dXJuIF9jaGVja291dEJ5VGFnLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfY2hlY2tvdXRCeVRhZygpIHtcbiAgX2NoZWNrb3V0QnlUYWcgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUyMSgpIHtcbiAgICB2YXIgZWwsIHJlc3BvbnNlLCB0cmFja2luZ19pdGVtLCBjb25maXJtZWQ7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUyMSQoX2NvbnRleHQyMSkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQyMS5wcmV2ID0gX2NvbnRleHQyMS5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkNoZWNrb3V0IGJ5IHRhZ1wiKTtcbiAgICAgICAgICBlbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiY2hlY2tvdXRCeVRhZ1wiKTtcbiAgICAgICAgICBpZiAoIShlbC52YWx1ZS5sZW5ndGggIT0gNikpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MjEubmV4dCA9IDY7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgYWxlcnQoXCJOb3QgYSBCR1AgdGFnIVwiKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIk5vdCBhIEJHUCB0YWdcIik7XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MjEuYWJydXB0KFwicmV0dXJuXCIpO1xuICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgX2NvbnRleHQyMS5uZXh0ID0gODtcbiAgICAgICAgICByZXR1cm4gZmV0Y2hXaXRoQXV0aChjb25maWcuYmFja2VuZF91cmwgKyBcIi90YWcvXCIgKyBlbC52YWx1ZSk7XG4gICAgICAgIGNhc2UgODpcbiAgICAgICAgICByZXNwb25zZSA9IF9jb250ZXh0MjEuc2VudDtcbiAgICAgICAgICBpZiAoIShyZXNwb25zZS5zdGF0dXMgPT0gMjAwKSkge1xuICAgICAgICAgICAgX2NvbnRleHQyMS5uZXh0ID0gMjU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgX2NvbnRleHQyMS5uZXh0ID0gMTI7XG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgY2FzZSAxMjpcbiAgICAgICAgICB0cmFja2luZ19pdGVtID0gX2NvbnRleHQyMS5zZW50O1xuICAgICAgICAgIGNvbmZpcm1lZCA9IGNvbmZpcm0oXCJEaWQgeW91IG1ha2Ugc3VyZSB0aGUgcmVjaXBpZW50IGlzIHJlYWxseSB0aGUgcmlnaHQgcGVyc29uP1wiKTtcbiAgICAgICAgICBpZiAoY29uZmlybWVkKSB7XG4gICAgICAgICAgICBfY29udGV4dDIxLm5leHQgPSAxNztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zb2xlLmxvZyhcIlJlY2lwaWVudCBjb25maXJtYXRpb24gZGVuaWVkLlwiKTtcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQyMS5hYnJ1cHQoXCJyZXR1cm5cIik7XG4gICAgICAgIGNhc2UgMTc6XG4gICAgICAgICAgaWYgKCEodHJhY2tpbmdfaXRlbS5zdG9yYWdlID09IHVuZGVmaW5lZCB8fCB0cmFja2luZ19pdGVtLnN0b3JhZ2UgPT0gbnVsbCB8fCB0cmFja2luZ19pdGVtLnN0b3JhZ2UubGVuZ3RoID09IDApKSB7XG4gICAgICAgICAgICBfY29udGV4dDIxLm5leHQgPSAyMTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBhbGVydChcIkl0ZW0gbm90IHlldCByZWNlaXZlZC5cIik7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJJdGVtIG5vdCB5ZXQgcmVjZWl2ZWQuXCIpO1xuICAgICAgICAgIHJldHVybiBfY29udGV4dDIxLmFicnVwdChcInJldHVyblwiKTtcbiAgICAgICAgY2FzZSAyMTpcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkNoZWNrb3V0IGl0ZW0gYnkgdGFnIHN1Y2Nlc3MuXCIpO1xuICAgICAgICAgIHVwZGF0ZUNoZWNrb3V0SXRlbSh0cmFja2luZ19pdGVtKTtcbiAgICAgICAgICBfY29udGV4dDIxLm5leHQgPSAyNjtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAyNTpcbiAgICAgICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09IDQwNCkge1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCJJdGVtIG5vdCBmb3VuZFwiKTtcbiAgICAgICAgICAgIGFsZXJ0KFwiSXRlbSBub3QgZm91bmQhXCIpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjaGVja1Jlc3BvbnNlRm9yRXJyb3IocmVzcG9uc2UsIFwiRmFpbGVkIHRvIGdldCBpdGVtIGZyb20gYmFja2VuZFwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIGNhc2UgMjY6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQyMS5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTIxKTtcbiAgfSkpO1xuICByZXR1cm4gX2NoZWNrb3V0QnlUYWcuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn0iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///244\n')},742:(__unused_webpack_module,exports)=>{"use strict";eval("\n\nexports.byteLength = byteLength\nexports.toByteArray = toByteArray\nexports.fromByteArray = fromByteArray\n\nvar lookup = []\nvar revLookup = []\nvar Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array\n\nvar code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nfor (var i = 0, len = code.length; i < len; ++i) {\n  lookup[i] = code[i]\n  revLookup[code.charCodeAt(i)] = i\n}\n\n// Support decoding URL-safe base64 strings, as Node.js does.\n// See: https://en.wikipedia.org/wiki/Base64#URL_applications\nrevLookup['-'.charCodeAt(0)] = 62\nrevLookup['_'.charCodeAt(0)] = 63\n\nfunction getLens (b64) {\n  var len = b64.length\n\n  if (len % 4 > 0) {\n    throw new Error('Invalid string. Length must be a multiple of 4')\n  }\n\n  // Trim off extra bytes after placeholder bytes are found\n  // See: https://github.com/beatgammit/base64-js/issues/42\n  var validLen = b64.indexOf('=')\n  if (validLen === -1) validLen = len\n\n  var placeHoldersLen = validLen === len\n    ? 0\n    : 4 - (validLen % 4)\n\n  return [validLen, placeHoldersLen]\n}\n\n// base64 is 4/3 + up to two characters of the original data\nfunction byteLength (b64) {\n  var lens = getLens(b64)\n  var validLen = lens[0]\n  var placeHoldersLen = lens[1]\n  return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction _byteLength (b64, validLen, placeHoldersLen) {\n  return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction toByteArray (b64) {\n  var tmp\n  var lens = getLens(b64)\n  var validLen = lens[0]\n  var placeHoldersLen = lens[1]\n\n  var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))\n\n  var curByte = 0\n\n  // if there are placeholders, only get up to the last complete 4 chars\n  var len = placeHoldersLen > 0\n    ? validLen - 4\n    : validLen\n\n  var i\n  for (i = 0; i < len; i += 4) {\n    tmp =\n      (revLookup[b64.charCodeAt(i)] << 18) |\n      (revLookup[b64.charCodeAt(i + 1)] << 12) |\n      (revLookup[b64.charCodeAt(i + 2)] << 6) |\n      revLookup[b64.charCodeAt(i + 3)]\n    arr[curByte++] = (tmp >> 16) & 0xFF\n    arr[curByte++] = (tmp >> 8) & 0xFF\n    arr[curByte++] = tmp & 0xFF\n  }\n\n  if (placeHoldersLen === 2) {\n    tmp =\n      (revLookup[b64.charCodeAt(i)] << 2) |\n      (revLookup[b64.charCodeAt(i + 1)] >> 4)\n    arr[curByte++] = tmp & 0xFF\n  }\n\n  if (placeHoldersLen === 1) {\n    tmp =\n      (revLookup[b64.charCodeAt(i)] << 10) |\n      (revLookup[b64.charCodeAt(i + 1)] << 4) |\n      (revLookup[b64.charCodeAt(i + 2)] >> 2)\n    arr[curByte++] = (tmp >> 8) & 0xFF\n    arr[curByte++] = tmp & 0xFF\n  }\n\n  return arr\n}\n\nfunction tripletToBase64 (num) {\n  return lookup[num >> 18 & 0x3F] +\n    lookup[num >> 12 & 0x3F] +\n    lookup[num >> 6 & 0x3F] +\n    lookup[num & 0x3F]\n}\n\nfunction encodeChunk (uint8, start, end) {\n  var tmp\n  var output = []\n  for (var i = start; i < end; i += 3) {\n    tmp =\n      ((uint8[i] << 16) & 0xFF0000) +\n      ((uint8[i + 1] << 8) & 0xFF00) +\n      (uint8[i + 2] & 0xFF)\n    output.push(tripletToBase64(tmp))\n  }\n  return output.join('')\n}\n\nfunction fromByteArray (uint8) {\n  var tmp\n  var len = uint8.length\n  var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes\n  var parts = []\n  var maxChunkLength = 16383 // must be multiple of 3\n\n  // go through the array every three bytes, we'll deal with trailing stuff later\n  for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {\n    parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))\n  }\n\n  // pad the end with zeros, but make sure to not forget the extra bytes\n  if (extraBytes === 1) {\n    tmp = uint8[len - 1]\n    parts.push(\n      lookup[tmp >> 2] +\n      lookup[(tmp << 4) & 0x3F] +\n      '=='\n    )\n  } else if (extraBytes === 2) {\n    tmp = (uint8[len - 2] << 8) + uint8[len - 1]\n    parts.push(\n      lookup[tmp >> 10] +\n      lookup[(tmp >> 4) & 0x3F] +\n      lookup[(tmp << 2) & 0x3F] +\n      '='\n    )\n  }\n\n  return parts.join('')\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNzQyLmpzIiwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9iYXNlNjQtanMvaW5kZXguanM/MWZiNSJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCdcblxuZXhwb3J0cy5ieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aFxuZXhwb3J0cy50b0J5dGVBcnJheSA9IHRvQnl0ZUFycmF5XG5leHBvcnRzLmZyb21CeXRlQXJyYXkgPSBmcm9tQnl0ZUFycmF5XG5cbnZhciBsb29rdXAgPSBbXVxudmFyIHJldkxvb2t1cCA9IFtdXG52YXIgQXJyID0gdHlwZW9mIFVpbnQ4QXJyYXkgIT09ICd1bmRlZmluZWQnID8gVWludDhBcnJheSA6IEFycmF5XG5cbnZhciBjb2RlID0gJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8nXG5mb3IgKHZhciBpID0gMCwgbGVuID0gY29kZS5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xuICBsb29rdXBbaV0gPSBjb2RlW2ldXG4gIHJldkxvb2t1cFtjb2RlLmNoYXJDb2RlQXQoaSldID0gaVxufVxuXG4vLyBTdXBwb3J0IGRlY29kaW5nIFVSTC1zYWZlIGJhc2U2NCBzdHJpbmdzLCBhcyBOb2RlLmpzIGRvZXMuXG4vLyBTZWU6IGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Jhc2U2NCNVUkxfYXBwbGljYXRpb25zXG5yZXZMb29rdXBbJy0nLmNoYXJDb2RlQXQoMCldID0gNjJcbnJldkxvb2t1cFsnXycuY2hhckNvZGVBdCgwKV0gPSA2M1xuXG5mdW5jdGlvbiBnZXRMZW5zIChiNjQpIHtcbiAgdmFyIGxlbiA9IGI2NC5sZW5ndGhcblxuICBpZiAobGVuICUgNCA+IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc3RyaW5nLiBMZW5ndGggbXVzdCBiZSBhIG11bHRpcGxlIG9mIDQnKVxuICB9XG5cbiAgLy8gVHJpbSBvZmYgZXh0cmEgYnl0ZXMgYWZ0ZXIgcGxhY2Vob2xkZXIgYnl0ZXMgYXJlIGZvdW5kXG4gIC8vIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL2JlYXRnYW1taXQvYmFzZTY0LWpzL2lzc3Vlcy80MlxuICB2YXIgdmFsaWRMZW4gPSBiNjQuaW5kZXhPZignPScpXG4gIGlmICh2YWxpZExlbiA9PT0gLTEpIHZhbGlkTGVuID0gbGVuXG5cbiAgdmFyIHBsYWNlSG9sZGVyc0xlbiA9IHZhbGlkTGVuID09PSBsZW5cbiAgICA/IDBcbiAgICA6IDQgLSAodmFsaWRMZW4gJSA0KVxuXG4gIHJldHVybiBbdmFsaWRMZW4sIHBsYWNlSG9sZGVyc0xlbl1cbn1cblxuLy8gYmFzZTY0IGlzIDQvMyArIHVwIHRvIHR3byBjaGFyYWN0ZXJzIG9mIHRoZSBvcmlnaW5hbCBkYXRhXG5mdW5jdGlvbiBieXRlTGVuZ3RoIChiNjQpIHtcbiAgdmFyIGxlbnMgPSBnZXRMZW5zKGI2NClcbiAgdmFyIHZhbGlkTGVuID0gbGVuc1swXVxuICB2YXIgcGxhY2VIb2xkZXJzTGVuID0gbGVuc1sxXVxuICByZXR1cm4gKCh2YWxpZExlbiArIHBsYWNlSG9sZGVyc0xlbikgKiAzIC8gNCkgLSBwbGFjZUhvbGRlcnNMZW5cbn1cblxuZnVuY3Rpb24gX2J5dGVMZW5ndGggKGI2NCwgdmFsaWRMZW4sIHBsYWNlSG9sZGVyc0xlbikge1xuICByZXR1cm4gKCh2YWxpZExlbiArIHBsYWNlSG9sZGVyc0xlbikgKiAzIC8gNCkgLSBwbGFjZUhvbGRlcnNMZW5cbn1cblxuZnVuY3Rpb24gdG9CeXRlQXJyYXkgKGI2NCkge1xuICB2YXIgdG1wXG4gIHZhciBsZW5zID0gZ2V0TGVucyhiNjQpXG4gIHZhciB2YWxpZExlbiA9IGxlbnNbMF1cbiAgdmFyIHBsYWNlSG9sZGVyc0xlbiA9IGxlbnNbMV1cblxuICB2YXIgYXJyID0gbmV3IEFycihfYnl0ZUxlbmd0aChiNjQsIHZhbGlkTGVuLCBwbGFjZUhvbGRlcnNMZW4pKVxuXG4gIHZhciBjdXJCeXRlID0gMFxuXG4gIC8vIGlmIHRoZXJlIGFyZSBwbGFjZWhvbGRlcnMsIG9ubHkgZ2V0IHVwIHRvIHRoZSBsYXN0IGNvbXBsZXRlIDQgY2hhcnNcbiAgdmFyIGxlbiA9IHBsYWNlSG9sZGVyc0xlbiA+IDBcbiAgICA/IHZhbGlkTGVuIC0gNFxuICAgIDogdmFsaWRMZW5cblxuICB2YXIgaVxuICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpICs9IDQpIHtcbiAgICB0bXAgPVxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpKV0gPDwgMTgpIHxcbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDEpXSA8PCAxMikgfFxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMildIDw8IDYpIHxcbiAgICAgIHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMyldXG4gICAgYXJyW2N1ckJ5dGUrK10gPSAodG1wID4+IDE2KSAmIDB4RkZcbiAgICBhcnJbY3VyQnl0ZSsrXSA9ICh0bXAgPj4gOCkgJiAweEZGXG4gICAgYXJyW2N1ckJ5dGUrK10gPSB0bXAgJiAweEZGXG4gIH1cblxuICBpZiAocGxhY2VIb2xkZXJzTGVuID09PSAyKSB7XG4gICAgdG1wID1cbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSldIDw8IDIpIHxcbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDEpXSA+PiA0KVxuICAgIGFycltjdXJCeXRlKytdID0gdG1wICYgMHhGRlxuICB9XG5cbiAgaWYgKHBsYWNlSG9sZGVyc0xlbiA9PT0gMSkge1xuICAgIHRtcCA9XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkpXSA8PCAxMCkgfFxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMSldIDw8IDQpIHxcbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDIpXSA+PiAyKVxuICAgIGFycltjdXJCeXRlKytdID0gKHRtcCA+PiA4KSAmIDB4RkZcbiAgICBhcnJbY3VyQnl0ZSsrXSA9IHRtcCAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBhcnJcbn1cblxuZnVuY3Rpb24gdHJpcGxldFRvQmFzZTY0IChudW0pIHtcbiAgcmV0dXJuIGxvb2t1cFtudW0gPj4gMTggJiAweDNGXSArXG4gICAgbG9va3VwW251bSA+PiAxMiAmIDB4M0ZdICtcbiAgICBsb29rdXBbbnVtID4+IDYgJiAweDNGXSArXG4gICAgbG9va3VwW251bSAmIDB4M0ZdXG59XG5cbmZ1bmN0aW9uIGVuY29kZUNodW5rICh1aW50OCwgc3RhcnQsIGVuZCkge1xuICB2YXIgdG1wXG4gIHZhciBvdXRwdXQgPSBbXVxuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkgKz0gMykge1xuICAgIHRtcCA9XG4gICAgICAoKHVpbnQ4W2ldIDw8IDE2KSAmIDB4RkYwMDAwKSArXG4gICAgICAoKHVpbnQ4W2kgKyAxXSA8PCA4KSAmIDB4RkYwMCkgK1xuICAgICAgKHVpbnQ4W2kgKyAyXSAmIDB4RkYpXG4gICAgb3V0cHV0LnB1c2godHJpcGxldFRvQmFzZTY0KHRtcCkpXG4gIH1cbiAgcmV0dXJuIG91dHB1dC5qb2luKCcnKVxufVxuXG5mdW5jdGlvbiBmcm9tQnl0ZUFycmF5ICh1aW50OCkge1xuICB2YXIgdG1wXG4gIHZhciBsZW4gPSB1aW50OC5sZW5ndGhcbiAgdmFyIGV4dHJhQnl0ZXMgPSBsZW4gJSAzIC8vIGlmIHdlIGhhdmUgMSBieXRlIGxlZnQsIHBhZCAyIGJ5dGVzXG4gIHZhciBwYXJ0cyA9IFtdXG4gIHZhciBtYXhDaHVua0xlbmd0aCA9IDE2MzgzIC8vIG11c3QgYmUgbXVsdGlwbGUgb2YgM1xuXG4gIC8vIGdvIHRocm91Z2ggdGhlIGFycmF5IGV2ZXJ5IHRocmVlIGJ5dGVzLCB3ZSdsbCBkZWFsIHdpdGggdHJhaWxpbmcgc3R1ZmYgbGF0ZXJcbiAgZm9yICh2YXIgaSA9IDAsIGxlbjIgPSBsZW4gLSBleHRyYUJ5dGVzOyBpIDwgbGVuMjsgaSArPSBtYXhDaHVua0xlbmd0aCkge1xuICAgIHBhcnRzLnB1c2goZW5jb2RlQ2h1bmsodWludDgsIGksIChpICsgbWF4Q2h1bmtMZW5ndGgpID4gbGVuMiA/IGxlbjIgOiAoaSArIG1heENodW5rTGVuZ3RoKSkpXG4gIH1cblxuICAvLyBwYWQgdGhlIGVuZCB3aXRoIHplcm9zLCBidXQgbWFrZSBzdXJlIHRvIG5vdCBmb3JnZXQgdGhlIGV4dHJhIGJ5dGVzXG4gIGlmIChleHRyYUJ5dGVzID09PSAxKSB7XG4gICAgdG1wID0gdWludDhbbGVuIC0gMV1cbiAgICBwYXJ0cy5wdXNoKFxuICAgICAgbG9va3VwW3RtcCA+PiAyXSArXG4gICAgICBsb29rdXBbKHRtcCA8PCA0KSAmIDB4M0ZdICtcbiAgICAgICc9PSdcbiAgICApXG4gIH0gZWxzZSBpZiAoZXh0cmFCeXRlcyA9PT0gMikge1xuICAgIHRtcCA9ICh1aW50OFtsZW4gLSAyXSA8PCA4KSArIHVpbnQ4W2xlbiAtIDFdXG4gICAgcGFydHMucHVzaChcbiAgICAgIGxvb2t1cFt0bXAgPj4gMTBdICtcbiAgICAgIGxvb2t1cFsodG1wID4+IDQpICYgMHgzRl0gK1xuICAgICAgbG9va3VwWyh0bXAgPDwgMikgJiAweDNGXSArXG4gICAgICAnPSdcbiAgICApXG4gIH1cblxuICByZXR1cm4gcGFydHMuam9pbignJylcbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///742\n")},764:(__unused_webpack_module,exports,__webpack_require__)=>{"use strict";eval("var __webpack_unused_export__;\n/*!\n * The buffer module from node.js, for the browser.\n *\n * @author   Feross Aboukhadijeh <https://feross.org>\n * @license  MIT\n */\n/* eslint-disable no-proto */\n\n\n\nconst base64 = __webpack_require__(742)\nconst ieee754 = __webpack_require__(645)\nconst customInspectSymbol =\n  (typeof Symbol === 'function' && typeof Symbol['for'] === 'function') // eslint-disable-line dot-notation\n    ? Symbol['for']('nodejs.util.inspect.custom') // eslint-disable-line dot-notation\n    : null\n\nexports.lW = Buffer\n__webpack_unused_export__ = SlowBuffer\nexports.h2 = 50\n\nconst K_MAX_LENGTH = 0x7fffffff\n__webpack_unused_export__ = K_MAX_LENGTH\n\n/**\n * If `Buffer.TYPED_ARRAY_SUPPORT`:\n *   === true    Use Uint8Array implementation (fastest)\n *   === false   Print warning and recommend using `buffer` v4.x which has an Object\n *               implementation (most compatible, even IE6)\n *\n * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,\n * Opera 11.6+, iOS 4.2+.\n *\n * We report that the browser does not support typed arrays if the are not subclassable\n * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array`\n * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support\n * for __proto__ and has a buggy typed array implementation.\n */\nBuffer.TYPED_ARRAY_SUPPORT = typedArraySupport()\n\nif (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' &&\n    typeof console.error === 'function') {\n  console.error(\n    'This browser lacks typed array (Uint8Array) support which is required by ' +\n    '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.'\n  )\n}\n\nfunction typedArraySupport () {\n  // Can typed array instances can be augmented?\n  try {\n    const arr = new Uint8Array(1)\n    const proto = { foo: function () { return 42 } }\n    Object.setPrototypeOf(proto, Uint8Array.prototype)\n    Object.setPrototypeOf(arr, proto)\n    return arr.foo() === 42\n  } catch (e) {\n    return false\n  }\n}\n\nObject.defineProperty(Buffer.prototype, 'parent', {\n  enumerable: true,\n  get: function () {\n    if (!Buffer.isBuffer(this)) return undefined\n    return this.buffer\n  }\n})\n\nObject.defineProperty(Buffer.prototype, 'offset', {\n  enumerable: true,\n  get: function () {\n    if (!Buffer.isBuffer(this)) return undefined\n    return this.byteOffset\n  }\n})\n\nfunction createBuffer (length) {\n  if (length > K_MAX_LENGTH) {\n    throw new RangeError('The value \"' + length + '\" is invalid for option \"size\"')\n  }\n  // Return an augmented `Uint8Array` instance\n  const buf = new Uint8Array(length)\n  Object.setPrototypeOf(buf, Buffer.prototype)\n  return buf\n}\n\n/**\n * The Buffer constructor returns instances of `Uint8Array` that have their\n * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of\n * `Uint8Array`, so the returned instances will have all the node `Buffer` methods\n * and the `Uint8Array` methods. Square bracket notation works as expected -- it\n * returns a single octet.\n *\n * The `Uint8Array` prototype remains unmodified.\n */\n\nfunction Buffer (arg, encodingOrOffset, length) {\n  // Common case.\n  if (typeof arg === 'number') {\n    if (typeof encodingOrOffset === 'string') {\n      throw new TypeError(\n        'The \"string\" argument must be of type string. Received type number'\n      )\n    }\n    return allocUnsafe(arg)\n  }\n  return from(arg, encodingOrOffset, length)\n}\n\nBuffer.poolSize = 8192 // not used by this implementation\n\nfunction from (value, encodingOrOffset, length) {\n  if (typeof value === 'string') {\n    return fromString(value, encodingOrOffset)\n  }\n\n  if (ArrayBuffer.isView(value)) {\n    return fromArrayView(value)\n  }\n\n  if (value == null) {\n    throw new TypeError(\n      'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' +\n      'or Array-like Object. Received type ' + (typeof value)\n    )\n  }\n\n  if (isInstance(value, ArrayBuffer) ||\n      (value && isInstance(value.buffer, ArrayBuffer))) {\n    return fromArrayBuffer(value, encodingOrOffset, length)\n  }\n\n  if (typeof SharedArrayBuffer !== 'undefined' &&\n      (isInstance(value, SharedArrayBuffer) ||\n      (value && isInstance(value.buffer, SharedArrayBuffer)))) {\n    return fromArrayBuffer(value, encodingOrOffset, length)\n  }\n\n  if (typeof value === 'number') {\n    throw new TypeError(\n      'The \"value\" argument must not be of type number. Received type number'\n    )\n  }\n\n  const valueOf = value.valueOf && value.valueOf()\n  if (valueOf != null && valueOf !== value) {\n    return Buffer.from(valueOf, encodingOrOffset, length)\n  }\n\n  const b = fromObject(value)\n  if (b) return b\n\n  if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null &&\n      typeof value[Symbol.toPrimitive] === 'function') {\n    return Buffer.from(value[Symbol.toPrimitive]('string'), encodingOrOffset, length)\n  }\n\n  throw new TypeError(\n    'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' +\n    'or Array-like Object. Received type ' + (typeof value)\n  )\n}\n\n/**\n * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError\n * if value is a number.\n * Buffer.from(str[, encoding])\n * Buffer.from(array)\n * Buffer.from(buffer)\n * Buffer.from(arrayBuffer[, byteOffset[, length]])\n **/\nBuffer.from = function (value, encodingOrOffset, length) {\n  return from(value, encodingOrOffset, length)\n}\n\n// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug:\n// https://github.com/feross/buffer/pull/148\nObject.setPrototypeOf(Buffer.prototype, Uint8Array.prototype)\nObject.setPrototypeOf(Buffer, Uint8Array)\n\nfunction assertSize (size) {\n  if (typeof size !== 'number') {\n    throw new TypeError('\"size\" argument must be of type number')\n  } else if (size < 0) {\n    throw new RangeError('The value \"' + size + '\" is invalid for option \"size\"')\n  }\n}\n\nfunction alloc (size, fill, encoding) {\n  assertSize(size)\n  if (size <= 0) {\n    return createBuffer(size)\n  }\n  if (fill !== undefined) {\n    // Only pay attention to encoding if it's a string. This\n    // prevents accidentally sending in a number that would\n    // be interpreted as a start offset.\n    return typeof encoding === 'string'\n      ? createBuffer(size).fill(fill, encoding)\n      : createBuffer(size).fill(fill)\n  }\n  return createBuffer(size)\n}\n\n/**\n * Creates a new filled Buffer instance.\n * alloc(size[, fill[, encoding]])\n **/\nBuffer.alloc = function (size, fill, encoding) {\n  return alloc(size, fill, encoding)\n}\n\nfunction allocUnsafe (size) {\n  assertSize(size)\n  return createBuffer(size < 0 ? 0 : checked(size) | 0)\n}\n\n/**\n * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.\n * */\nBuffer.allocUnsafe = function (size) {\n  return allocUnsafe(size)\n}\n/**\n * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.\n */\nBuffer.allocUnsafeSlow = function (size) {\n  return allocUnsafe(size)\n}\n\nfunction fromString (string, encoding) {\n  if (typeof encoding !== 'string' || encoding === '') {\n    encoding = 'utf8'\n  }\n\n  if (!Buffer.isEncoding(encoding)) {\n    throw new TypeError('Unknown encoding: ' + encoding)\n  }\n\n  const length = byteLength(string, encoding) | 0\n  let buf = createBuffer(length)\n\n  const actual = buf.write(string, encoding)\n\n  if (actual !== length) {\n    // Writing a hex string, for example, that contains invalid characters will\n    // cause everything after the first invalid character to be ignored. (e.g.\n    // 'abxxcd' will be treated as 'ab')\n    buf = buf.slice(0, actual)\n  }\n\n  return buf\n}\n\nfunction fromArrayLike (array) {\n  const length = array.length < 0 ? 0 : checked(array.length) | 0\n  const buf = createBuffer(length)\n  for (let i = 0; i < length; i += 1) {\n    buf[i] = array[i] & 255\n  }\n  return buf\n}\n\nfunction fromArrayView (arrayView) {\n  if (isInstance(arrayView, Uint8Array)) {\n    const copy = new Uint8Array(arrayView)\n    return fromArrayBuffer(copy.buffer, copy.byteOffset, copy.byteLength)\n  }\n  return fromArrayLike(arrayView)\n}\n\nfunction fromArrayBuffer (array, byteOffset, length) {\n  if (byteOffset < 0 || array.byteLength < byteOffset) {\n    throw new RangeError('\"offset\" is outside of buffer bounds')\n  }\n\n  if (array.byteLength < byteOffset + (length || 0)) {\n    throw new RangeError('\"length\" is outside of buffer bounds')\n  }\n\n  let buf\n  if (byteOffset === undefined && length === undefined) {\n    buf = new Uint8Array(array)\n  } else if (length === undefined) {\n    buf = new Uint8Array(array, byteOffset)\n  } else {\n    buf = new Uint8Array(array, byteOffset, length)\n  }\n\n  // Return an augmented `Uint8Array` instance\n  Object.setPrototypeOf(buf, Buffer.prototype)\n\n  return buf\n}\n\nfunction fromObject (obj) {\n  if (Buffer.isBuffer(obj)) {\n    const len = checked(obj.length) | 0\n    const buf = createBuffer(len)\n\n    if (buf.length === 0) {\n      return buf\n    }\n\n    obj.copy(buf, 0, 0, len)\n    return buf\n  }\n\n  if (obj.length !== undefined) {\n    if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) {\n      return createBuffer(0)\n    }\n    return fromArrayLike(obj)\n  }\n\n  if (obj.type === 'Buffer' && Array.isArray(obj.data)) {\n    return fromArrayLike(obj.data)\n  }\n}\n\nfunction checked (length) {\n  // Note: cannot use `length < K_MAX_LENGTH` here because that fails when\n  // length is NaN (which is otherwise coerced to zero.)\n  if (length >= K_MAX_LENGTH) {\n    throw new RangeError('Attempt to allocate Buffer larger than maximum ' +\n                         'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes')\n  }\n  return length | 0\n}\n\nfunction SlowBuffer (length) {\n  if (+length != length) { // eslint-disable-line eqeqeq\n    length = 0\n  }\n  return Buffer.alloc(+length)\n}\n\nBuffer.isBuffer = function isBuffer (b) {\n  return b != null && b._isBuffer === true &&\n    b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false\n}\n\nBuffer.compare = function compare (a, b) {\n  if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength)\n  if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength)\n  if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {\n    throw new TypeError(\n      'The \"buf1\", \"buf2\" arguments must be one of type Buffer or Uint8Array'\n    )\n  }\n\n  if (a === b) return 0\n\n  let x = a.length\n  let y = b.length\n\n  for (let i = 0, len = Math.min(x, y); i < len; ++i) {\n    if (a[i] !== b[i]) {\n      x = a[i]\n      y = b[i]\n      break\n    }\n  }\n\n  if (x < y) return -1\n  if (y < x) return 1\n  return 0\n}\n\nBuffer.isEncoding = function isEncoding (encoding) {\n  switch (String(encoding).toLowerCase()) {\n    case 'hex':\n    case 'utf8':\n    case 'utf-8':\n    case 'ascii':\n    case 'latin1':\n    case 'binary':\n    case 'base64':\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n      return true\n    default:\n      return false\n  }\n}\n\nBuffer.concat = function concat (list, length) {\n  if (!Array.isArray(list)) {\n    throw new TypeError('\"list\" argument must be an Array of Buffers')\n  }\n\n  if (list.length === 0) {\n    return Buffer.alloc(0)\n  }\n\n  let i\n  if (length === undefined) {\n    length = 0\n    for (i = 0; i < list.length; ++i) {\n      length += list[i].length\n    }\n  }\n\n  const buffer = Buffer.allocUnsafe(length)\n  let pos = 0\n  for (i = 0; i < list.length; ++i) {\n    let buf = list[i]\n    if (isInstance(buf, Uint8Array)) {\n      if (pos + buf.length > buffer.length) {\n        if (!Buffer.isBuffer(buf)) buf = Buffer.from(buf)\n        buf.copy(buffer, pos)\n      } else {\n        Uint8Array.prototype.set.call(\n          buffer,\n          buf,\n          pos\n        )\n      }\n    } else if (!Buffer.isBuffer(buf)) {\n      throw new TypeError('\"list\" argument must be an Array of Buffers')\n    } else {\n      buf.copy(buffer, pos)\n    }\n    pos += buf.length\n  }\n  return buffer\n}\n\nfunction byteLength (string, encoding) {\n  if (Buffer.isBuffer(string)) {\n    return string.length\n  }\n  if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) {\n    return string.byteLength\n  }\n  if (typeof string !== 'string') {\n    throw new TypeError(\n      'The \"string\" argument must be one of type string, Buffer, or ArrayBuffer. ' +\n      'Received type ' + typeof string\n    )\n  }\n\n  const len = string.length\n  const mustMatch = (arguments.length > 2 && arguments[2] === true)\n  if (!mustMatch && len === 0) return 0\n\n  // Use a for loop to avoid recursion\n  let loweredCase = false\n  for (;;) {\n    switch (encoding) {\n      case 'ascii':\n      case 'latin1':\n      case 'binary':\n        return len\n      case 'utf8':\n      case 'utf-8':\n        return utf8ToBytes(string).length\n      case 'ucs2':\n      case 'ucs-2':\n      case 'utf16le':\n      case 'utf-16le':\n        return len * 2\n      case 'hex':\n        return len >>> 1\n      case 'base64':\n        return base64ToBytes(string).length\n      default:\n        if (loweredCase) {\n          return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8\n        }\n        encoding = ('' + encoding).toLowerCase()\n        loweredCase = true\n    }\n  }\n}\nBuffer.byteLength = byteLength\n\nfunction slowToString (encoding, start, end) {\n  let loweredCase = false\n\n  // No need to verify that \"this.length <= MAX_UINT32\" since it's a read-only\n  // property of a typed array.\n\n  // This behaves neither like String nor Uint8Array in that we set start/end\n  // to their upper/lower bounds if the value passed is out of range.\n  // undefined is handled specially as per ECMA-262 6th Edition,\n  // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.\n  if (start === undefined || start < 0) {\n    start = 0\n  }\n  // Return early if start > this.length. Done here to prevent potential uint32\n  // coercion fail below.\n  if (start > this.length) {\n    return ''\n  }\n\n  if (end === undefined || end > this.length) {\n    end = this.length\n  }\n\n  if (end <= 0) {\n    return ''\n  }\n\n  // Force coercion to uint32. This will also coerce falsey/NaN values to 0.\n  end >>>= 0\n  start >>>= 0\n\n  if (end <= start) {\n    return ''\n  }\n\n  if (!encoding) encoding = 'utf8'\n\n  while (true) {\n    switch (encoding) {\n      case 'hex':\n        return hexSlice(this, start, end)\n\n      case 'utf8':\n      case 'utf-8':\n        return utf8Slice(this, start, end)\n\n      case 'ascii':\n        return asciiSlice(this, start, end)\n\n      case 'latin1':\n      case 'binary':\n        return latin1Slice(this, start, end)\n\n      case 'base64':\n        return base64Slice(this, start, end)\n\n      case 'ucs2':\n      case 'ucs-2':\n      case 'utf16le':\n      case 'utf-16le':\n        return utf16leSlice(this, start, end)\n\n      default:\n        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)\n        encoding = (encoding + '').toLowerCase()\n        loweredCase = true\n    }\n  }\n}\n\n// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package)\n// to detect a Buffer instance. It's not possible to use `instanceof Buffer`\n// reliably in a browserify context because there could be multiple different\n// copies of the 'buffer' package in use. This method works even for Buffer\n// instances that were created from another copy of the `buffer` package.\n// See: https://github.com/feross/buffer/issues/154\nBuffer.prototype._isBuffer = true\n\nfunction swap (b, n, m) {\n  const i = b[n]\n  b[n] = b[m]\n  b[m] = i\n}\n\nBuffer.prototype.swap16 = function swap16 () {\n  const len = this.length\n  if (len % 2 !== 0) {\n    throw new RangeError('Buffer size must be a multiple of 16-bits')\n  }\n  for (let i = 0; i < len; i += 2) {\n    swap(this, i, i + 1)\n  }\n  return this\n}\n\nBuffer.prototype.swap32 = function swap32 () {\n  const len = this.length\n  if (len % 4 !== 0) {\n    throw new RangeError('Buffer size must be a multiple of 32-bits')\n  }\n  for (let i = 0; i < len; i += 4) {\n    swap(this, i, i + 3)\n    swap(this, i + 1, i + 2)\n  }\n  return this\n}\n\nBuffer.prototype.swap64 = function swap64 () {\n  const len = this.length\n  if (len % 8 !== 0) {\n    throw new RangeError('Buffer size must be a multiple of 64-bits')\n  }\n  for (let i = 0; i < len; i += 8) {\n    swap(this, i, i + 7)\n    swap(this, i + 1, i + 6)\n    swap(this, i + 2, i + 5)\n    swap(this, i + 3, i + 4)\n  }\n  return this\n}\n\nBuffer.prototype.toString = function toString () {\n  const length = this.length\n  if (length === 0) return ''\n  if (arguments.length === 0) return utf8Slice(this, 0, length)\n  return slowToString.apply(this, arguments)\n}\n\nBuffer.prototype.toLocaleString = Buffer.prototype.toString\n\nBuffer.prototype.equals = function equals (b) {\n  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')\n  if (this === b) return true\n  return Buffer.compare(this, b) === 0\n}\n\nBuffer.prototype.inspect = function inspect () {\n  let str = ''\n  const max = exports.h2\n  str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim()\n  if (this.length > max) str += ' ... '\n  return '<Buffer ' + str + '>'\n}\nif (customInspectSymbol) {\n  Buffer.prototype[customInspectSymbol] = Buffer.prototype.inspect\n}\n\nBuffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {\n  if (isInstance(target, Uint8Array)) {\n    target = Buffer.from(target, target.offset, target.byteLength)\n  }\n  if (!Buffer.isBuffer(target)) {\n    throw new TypeError(\n      'The \"target\" argument must be one of type Buffer or Uint8Array. ' +\n      'Received type ' + (typeof target)\n    )\n  }\n\n  if (start === undefined) {\n    start = 0\n  }\n  if (end === undefined) {\n    end = target ? target.length : 0\n  }\n  if (thisStart === undefined) {\n    thisStart = 0\n  }\n  if (thisEnd === undefined) {\n    thisEnd = this.length\n  }\n\n  if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {\n    throw new RangeError('out of range index')\n  }\n\n  if (thisStart >= thisEnd && start >= end) {\n    return 0\n  }\n  if (thisStart >= thisEnd) {\n    return -1\n  }\n  if (start >= end) {\n    return 1\n  }\n\n  start >>>= 0\n  end >>>= 0\n  thisStart >>>= 0\n  thisEnd >>>= 0\n\n  if (this === target) return 0\n\n  let x = thisEnd - thisStart\n  let y = end - start\n  const len = Math.min(x, y)\n\n  const thisCopy = this.slice(thisStart, thisEnd)\n  const targetCopy = target.slice(start, end)\n\n  for (let i = 0; i < len; ++i) {\n    if (thisCopy[i] !== targetCopy[i]) {\n      x = thisCopy[i]\n      y = targetCopy[i]\n      break\n    }\n  }\n\n  if (x < y) return -1\n  if (y < x) return 1\n  return 0\n}\n\n// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,\n// OR the last index of `val` in `buffer` at offset <= `byteOffset`.\n//\n// Arguments:\n// - buffer - a Buffer to search\n// - val - a string, Buffer, or number\n// - byteOffset - an index into `buffer`; will be clamped to an int32\n// - encoding - an optional encoding, relevant is val is a string\n// - dir - true for indexOf, false for lastIndexOf\nfunction bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {\n  // Empty buffer means no match\n  if (buffer.length === 0) return -1\n\n  // Normalize byteOffset\n  if (typeof byteOffset === 'string') {\n    encoding = byteOffset\n    byteOffset = 0\n  } else if (byteOffset > 0x7fffffff) {\n    byteOffset = 0x7fffffff\n  } else if (byteOffset < -0x80000000) {\n    byteOffset = -0x80000000\n  }\n  byteOffset = +byteOffset // Coerce to Number.\n  if (numberIsNaN(byteOffset)) {\n    // byteOffset: it it's undefined, null, NaN, \"foo\", etc, search whole buffer\n    byteOffset = dir ? 0 : (buffer.length - 1)\n  }\n\n  // Normalize byteOffset: negative offsets start from the end of the buffer\n  if (byteOffset < 0) byteOffset = buffer.length + byteOffset\n  if (byteOffset >= buffer.length) {\n    if (dir) return -1\n    else byteOffset = buffer.length - 1\n  } else if (byteOffset < 0) {\n    if (dir) byteOffset = 0\n    else return -1\n  }\n\n  // Normalize val\n  if (typeof val === 'string') {\n    val = Buffer.from(val, encoding)\n  }\n\n  // Finally, search either indexOf (if dir is true) or lastIndexOf\n  if (Buffer.isBuffer(val)) {\n    // Special case: looking for empty string/buffer always fails\n    if (val.length === 0) {\n      return -1\n    }\n    return arrayIndexOf(buffer, val, byteOffset, encoding, dir)\n  } else if (typeof val === 'number') {\n    val = val & 0xFF // Search for a byte value [0-255]\n    if (typeof Uint8Array.prototype.indexOf === 'function') {\n      if (dir) {\n        return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)\n      } else {\n        return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)\n      }\n    }\n    return arrayIndexOf(buffer, [val], byteOffset, encoding, dir)\n  }\n\n  throw new TypeError('val must be string, number or Buffer')\n}\n\nfunction arrayIndexOf (arr, val, byteOffset, encoding, dir) {\n  let indexSize = 1\n  let arrLength = arr.length\n  let valLength = val.length\n\n  if (encoding !== undefined) {\n    encoding = String(encoding).toLowerCase()\n    if (encoding === 'ucs2' || encoding === 'ucs-2' ||\n        encoding === 'utf16le' || encoding === 'utf-16le') {\n      if (arr.length < 2 || val.length < 2) {\n        return -1\n      }\n      indexSize = 2\n      arrLength /= 2\n      valLength /= 2\n      byteOffset /= 2\n    }\n  }\n\n  function read (buf, i) {\n    if (indexSize === 1) {\n      return buf[i]\n    } else {\n      return buf.readUInt16BE(i * indexSize)\n    }\n  }\n\n  let i\n  if (dir) {\n    let foundIndex = -1\n    for (i = byteOffset; i < arrLength; i++) {\n      if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {\n        if (foundIndex === -1) foundIndex = i\n        if (i - foundIndex + 1 === valLength) return foundIndex * indexSize\n      } else {\n        if (foundIndex !== -1) i -= i - foundIndex\n        foundIndex = -1\n      }\n    }\n  } else {\n    if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength\n    for (i = byteOffset; i >= 0; i--) {\n      let found = true\n      for (let j = 0; j < valLength; j++) {\n        if (read(arr, i + j) !== read(val, j)) {\n          found = false\n          break\n        }\n      }\n      if (found) return i\n    }\n  }\n\n  return -1\n}\n\nBuffer.prototype.includes = function includes (val, byteOffset, encoding) {\n  return this.indexOf(val, byteOffset, encoding) !== -1\n}\n\nBuffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {\n  return bidirectionalIndexOf(this, val, byteOffset, encoding, true)\n}\n\nBuffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {\n  return bidirectionalIndexOf(this, val, byteOffset, encoding, false)\n}\n\nfunction hexWrite (buf, string, offset, length) {\n  offset = Number(offset) || 0\n  const remaining = buf.length - offset\n  if (!length) {\n    length = remaining\n  } else {\n    length = Number(length)\n    if (length > remaining) {\n      length = remaining\n    }\n  }\n\n  const strLen = string.length\n\n  if (length > strLen / 2) {\n    length = strLen / 2\n  }\n  let i\n  for (i = 0; i < length; ++i) {\n    const parsed = parseInt(string.substr(i * 2, 2), 16)\n    if (numberIsNaN(parsed)) return i\n    buf[offset + i] = parsed\n  }\n  return i\n}\n\nfunction utf8Write (buf, string, offset, length) {\n  return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)\n}\n\nfunction asciiWrite (buf, string, offset, length) {\n  return blitBuffer(asciiToBytes(string), buf, offset, length)\n}\n\nfunction base64Write (buf, string, offset, length) {\n  return blitBuffer(base64ToBytes(string), buf, offset, length)\n}\n\nfunction ucs2Write (buf, string, offset, length) {\n  return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)\n}\n\nBuffer.prototype.write = function write (string, offset, length, encoding) {\n  // Buffer#write(string)\n  if (offset === undefined) {\n    encoding = 'utf8'\n    length = this.length\n    offset = 0\n  // Buffer#write(string, encoding)\n  } else if (length === undefined && typeof offset === 'string') {\n    encoding = offset\n    length = this.length\n    offset = 0\n  // Buffer#write(string, offset[, length][, encoding])\n  } else if (isFinite(offset)) {\n    offset = offset >>> 0\n    if (isFinite(length)) {\n      length = length >>> 0\n      if (encoding === undefined) encoding = 'utf8'\n    } else {\n      encoding = length\n      length = undefined\n    }\n  } else {\n    throw new Error(\n      'Buffer.write(string, encoding, offset[, length]) is no longer supported'\n    )\n  }\n\n  const remaining = this.length - offset\n  if (length === undefined || length > remaining) length = remaining\n\n  if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {\n    throw new RangeError('Attempt to write outside buffer bounds')\n  }\n\n  if (!encoding) encoding = 'utf8'\n\n  let loweredCase = false\n  for (;;) {\n    switch (encoding) {\n      case 'hex':\n        return hexWrite(this, string, offset, length)\n\n      case 'utf8':\n      case 'utf-8':\n        return utf8Write(this, string, offset, length)\n\n      case 'ascii':\n      case 'latin1':\n      case 'binary':\n        return asciiWrite(this, string, offset, length)\n\n      case 'base64':\n        // Warning: maxLength not taken into account in base64Write\n        return base64Write(this, string, offset, length)\n\n      case 'ucs2':\n      case 'ucs-2':\n      case 'utf16le':\n      case 'utf-16le':\n        return ucs2Write(this, string, offset, length)\n\n      default:\n        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)\n        encoding = ('' + encoding).toLowerCase()\n        loweredCase = true\n    }\n  }\n}\n\nBuffer.prototype.toJSON = function toJSON () {\n  return {\n    type: 'Buffer',\n    data: Array.prototype.slice.call(this._arr || this, 0)\n  }\n}\n\nfunction base64Slice (buf, start, end) {\n  if (start === 0 && end === buf.length) {\n    return base64.fromByteArray(buf)\n  } else {\n    return base64.fromByteArray(buf.slice(start, end))\n  }\n}\n\nfunction utf8Slice (buf, start, end) {\n  end = Math.min(buf.length, end)\n  const res = []\n\n  let i = start\n  while (i < end) {\n    const firstByte = buf[i]\n    let codePoint = null\n    let bytesPerSequence = (firstByte > 0xEF)\n      ? 4\n      : (firstByte > 0xDF)\n          ? 3\n          : (firstByte > 0xBF)\n              ? 2\n              : 1\n\n    if (i + bytesPerSequence <= end) {\n      let secondByte, thirdByte, fourthByte, tempCodePoint\n\n      switch (bytesPerSequence) {\n        case 1:\n          if (firstByte < 0x80) {\n            codePoint = firstByte\n          }\n          break\n        case 2:\n          secondByte = buf[i + 1]\n          if ((secondByte & 0xC0) === 0x80) {\n            tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)\n            if (tempCodePoint > 0x7F) {\n              codePoint = tempCodePoint\n            }\n          }\n          break\n        case 3:\n          secondByte = buf[i + 1]\n          thirdByte = buf[i + 2]\n          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {\n            tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)\n            if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {\n              codePoint = tempCodePoint\n            }\n          }\n          break\n        case 4:\n          secondByte = buf[i + 1]\n          thirdByte = buf[i + 2]\n          fourthByte = buf[i + 3]\n          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {\n            tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)\n            if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {\n              codePoint = tempCodePoint\n            }\n          }\n      }\n    }\n\n    if (codePoint === null) {\n      // we did not generate a valid codePoint so insert a\n      // replacement char (U+FFFD) and advance only 1 byte\n      codePoint = 0xFFFD\n      bytesPerSequence = 1\n    } else if (codePoint > 0xFFFF) {\n      // encode to utf16 (surrogate pair dance)\n      codePoint -= 0x10000\n      res.push(codePoint >>> 10 & 0x3FF | 0xD800)\n      codePoint = 0xDC00 | codePoint & 0x3FF\n    }\n\n    res.push(codePoint)\n    i += bytesPerSequence\n  }\n\n  return decodeCodePointsArray(res)\n}\n\n// Based on http://stackoverflow.com/a/22747272/680742, the browser with\n// the lowest limit is Chrome, with 0x10000 args.\n// We go 1 magnitude less, for safety\nconst MAX_ARGUMENTS_LENGTH = 0x1000\n\nfunction decodeCodePointsArray (codePoints) {\n  const len = codePoints.length\n  if (len <= MAX_ARGUMENTS_LENGTH) {\n    return String.fromCharCode.apply(String, codePoints) // avoid extra slice()\n  }\n\n  // Decode in chunks to avoid \"call stack size exceeded\".\n  let res = ''\n  let i = 0\n  while (i < len) {\n    res += String.fromCharCode.apply(\n      String,\n      codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)\n    )\n  }\n  return res\n}\n\nfunction asciiSlice (buf, start, end) {\n  let ret = ''\n  end = Math.min(buf.length, end)\n\n  for (let i = start; i < end; ++i) {\n    ret += String.fromCharCode(buf[i] & 0x7F)\n  }\n  return ret\n}\n\nfunction latin1Slice (buf, start, end) {\n  let ret = ''\n  end = Math.min(buf.length, end)\n\n  for (let i = start; i < end; ++i) {\n    ret += String.fromCharCode(buf[i])\n  }\n  return ret\n}\n\nfunction hexSlice (buf, start, end) {\n  const len = buf.length\n\n  if (!start || start < 0) start = 0\n  if (!end || end < 0 || end > len) end = len\n\n  let out = ''\n  for (let i = start; i < end; ++i) {\n    out += hexSliceLookupTable[buf[i]]\n  }\n  return out\n}\n\nfunction utf16leSlice (buf, start, end) {\n  const bytes = buf.slice(start, end)\n  let res = ''\n  // If bytes.length is odd, the last 8 bits must be ignored (same as node.js)\n  for (let i = 0; i < bytes.length - 1; i += 2) {\n    res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256))\n  }\n  return res\n}\n\nBuffer.prototype.slice = function slice (start, end) {\n  const len = this.length\n  start = ~~start\n  end = end === undefined ? len : ~~end\n\n  if (start < 0) {\n    start += len\n    if (start < 0) start = 0\n  } else if (start > len) {\n    start = len\n  }\n\n  if (end < 0) {\n    end += len\n    if (end < 0) end = 0\n  } else if (end > len) {\n    end = len\n  }\n\n  if (end < start) end = start\n\n  const newBuf = this.subarray(start, end)\n  // Return an augmented `Uint8Array` instance\n  Object.setPrototypeOf(newBuf, Buffer.prototype)\n\n  return newBuf\n}\n\n/*\n * Need to make sure that buffer isn't trying to write out of bounds.\n */\nfunction checkOffset (offset, ext, length) {\n  if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')\n  if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')\n}\n\nBuffer.prototype.readUintLE =\nBuffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {\n  offset = offset >>> 0\n  byteLength = byteLength >>> 0\n  if (!noAssert) checkOffset(offset, byteLength, this.length)\n\n  let val = this[offset]\n  let mul = 1\n  let i = 0\n  while (++i < byteLength && (mul *= 0x100)) {\n    val += this[offset + i] * mul\n  }\n\n  return val\n}\n\nBuffer.prototype.readUintBE =\nBuffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {\n  offset = offset >>> 0\n  byteLength = byteLength >>> 0\n  if (!noAssert) {\n    checkOffset(offset, byteLength, this.length)\n  }\n\n  let val = this[offset + --byteLength]\n  let mul = 1\n  while (byteLength > 0 && (mul *= 0x100)) {\n    val += this[offset + --byteLength] * mul\n  }\n\n  return val\n}\n\nBuffer.prototype.readUint8 =\nBuffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 1, this.length)\n  return this[offset]\n}\n\nBuffer.prototype.readUint16LE =\nBuffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 2, this.length)\n  return this[offset] | (this[offset + 1] << 8)\n}\n\nBuffer.prototype.readUint16BE =\nBuffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 2, this.length)\n  return (this[offset] << 8) | this[offset + 1]\n}\n\nBuffer.prototype.readUint32LE =\nBuffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 4, this.length)\n\n  return ((this[offset]) |\n      (this[offset + 1] << 8) |\n      (this[offset + 2] << 16)) +\n      (this[offset + 3] * 0x1000000)\n}\n\nBuffer.prototype.readUint32BE =\nBuffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 4, this.length)\n\n  return (this[offset] * 0x1000000) +\n    ((this[offset + 1] << 16) |\n    (this[offset + 2] << 8) |\n    this[offset + 3])\n}\n\nBuffer.prototype.readBigUInt64LE = defineBigIntMethod(function readBigUInt64LE (offset) {\n  offset = offset >>> 0\n  validateNumber(offset, 'offset')\n  const first = this[offset]\n  const last = this[offset + 7]\n  if (first === undefined || last === undefined) {\n    boundsError(offset, this.length - 8)\n  }\n\n  const lo = first +\n    this[++offset] * 2 ** 8 +\n    this[++offset] * 2 ** 16 +\n    this[++offset] * 2 ** 24\n\n  const hi = this[++offset] +\n    this[++offset] * 2 ** 8 +\n    this[++offset] * 2 ** 16 +\n    last * 2 ** 24\n\n  return BigInt(lo) + (BigInt(hi) << BigInt(32))\n})\n\nBuffer.prototype.readBigUInt64BE = defineBigIntMethod(function readBigUInt64BE (offset) {\n  offset = offset >>> 0\n  validateNumber(offset, 'offset')\n  const first = this[offset]\n  const last = this[offset + 7]\n  if (first === undefined || last === undefined) {\n    boundsError(offset, this.length - 8)\n  }\n\n  const hi = first * 2 ** 24 +\n    this[++offset] * 2 ** 16 +\n    this[++offset] * 2 ** 8 +\n    this[++offset]\n\n  const lo = this[++offset] * 2 ** 24 +\n    this[++offset] * 2 ** 16 +\n    this[++offset] * 2 ** 8 +\n    last\n\n  return (BigInt(hi) << BigInt(32)) + BigInt(lo)\n})\n\nBuffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {\n  offset = offset >>> 0\n  byteLength = byteLength >>> 0\n  if (!noAssert) checkOffset(offset, byteLength, this.length)\n\n  let val = this[offset]\n  let mul = 1\n  let i = 0\n  while (++i < byteLength && (mul *= 0x100)) {\n    val += this[offset + i] * mul\n  }\n  mul *= 0x80\n\n  if (val >= mul) val -= Math.pow(2, 8 * byteLength)\n\n  return val\n}\n\nBuffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {\n  offset = offset >>> 0\n  byteLength = byteLength >>> 0\n  if (!noAssert) checkOffset(offset, byteLength, this.length)\n\n  let i = byteLength\n  let mul = 1\n  let val = this[offset + --i]\n  while (i > 0 && (mul *= 0x100)) {\n    val += this[offset + --i] * mul\n  }\n  mul *= 0x80\n\n  if (val >= mul) val -= Math.pow(2, 8 * byteLength)\n\n  return val\n}\n\nBuffer.prototype.readInt8 = function readInt8 (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 1, this.length)\n  if (!(this[offset] & 0x80)) return (this[offset])\n  return ((0xff - this[offset] + 1) * -1)\n}\n\nBuffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 2, this.length)\n  const val = this[offset] | (this[offset + 1] << 8)\n  return (val & 0x8000) ? val | 0xFFFF0000 : val\n}\n\nBuffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 2, this.length)\n  const val = this[offset + 1] | (this[offset] << 8)\n  return (val & 0x8000) ? val | 0xFFFF0000 : val\n}\n\nBuffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 4, this.length)\n\n  return (this[offset]) |\n    (this[offset + 1] << 8) |\n    (this[offset + 2] << 16) |\n    (this[offset + 3] << 24)\n}\n\nBuffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 4, this.length)\n\n  return (this[offset] << 24) |\n    (this[offset + 1] << 16) |\n    (this[offset + 2] << 8) |\n    (this[offset + 3])\n}\n\nBuffer.prototype.readBigInt64LE = defineBigIntMethod(function readBigInt64LE (offset) {\n  offset = offset >>> 0\n  validateNumber(offset, 'offset')\n  const first = this[offset]\n  const last = this[offset + 7]\n  if (first === undefined || last === undefined) {\n    boundsError(offset, this.length - 8)\n  }\n\n  const val = this[offset + 4] +\n    this[offset + 5] * 2 ** 8 +\n    this[offset + 6] * 2 ** 16 +\n    (last << 24) // Overflow\n\n  return (BigInt(val) << BigInt(32)) +\n    BigInt(first +\n    this[++offset] * 2 ** 8 +\n    this[++offset] * 2 ** 16 +\n    this[++offset] * 2 ** 24)\n})\n\nBuffer.prototype.readBigInt64BE = defineBigIntMethod(function readBigInt64BE (offset) {\n  offset = offset >>> 0\n  validateNumber(offset, 'offset')\n  const first = this[offset]\n  const last = this[offset + 7]\n  if (first === undefined || last === undefined) {\n    boundsError(offset, this.length - 8)\n  }\n\n  const val = (first << 24) + // Overflow\n    this[++offset] * 2 ** 16 +\n    this[++offset] * 2 ** 8 +\n    this[++offset]\n\n  return (BigInt(val) << BigInt(32)) +\n    BigInt(this[++offset] * 2 ** 24 +\n    this[++offset] * 2 ** 16 +\n    this[++offset] * 2 ** 8 +\n    last)\n})\n\nBuffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 4, this.length)\n  return ieee754.read(this, offset, true, 23, 4)\n}\n\nBuffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 4, this.length)\n  return ieee754.read(this, offset, false, 23, 4)\n}\n\nBuffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 8, this.length)\n  return ieee754.read(this, offset, true, 52, 8)\n}\n\nBuffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 8, this.length)\n  return ieee754.read(this, offset, false, 52, 8)\n}\n\nfunction checkInt (buf, value, offset, ext, max, min) {\n  if (!Buffer.isBuffer(buf)) throw new TypeError('\"buffer\" argument must be a Buffer instance')\n  if (value > max || value < min) throw new RangeError('\"value\" argument is out of bounds')\n  if (offset + ext > buf.length) throw new RangeError('Index out of range')\n}\n\nBuffer.prototype.writeUintLE =\nBuffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  byteLength = byteLength >>> 0\n  if (!noAssert) {\n    const maxBytes = Math.pow(2, 8 * byteLength) - 1\n    checkInt(this, value, offset, byteLength, maxBytes, 0)\n  }\n\n  let mul = 1\n  let i = 0\n  this[offset] = value & 0xFF\n  while (++i < byteLength && (mul *= 0x100)) {\n    this[offset + i] = (value / mul) & 0xFF\n  }\n\n  return offset + byteLength\n}\n\nBuffer.prototype.writeUintBE =\nBuffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  byteLength = byteLength >>> 0\n  if (!noAssert) {\n    const maxBytes = Math.pow(2, 8 * byteLength) - 1\n    checkInt(this, value, offset, byteLength, maxBytes, 0)\n  }\n\n  let i = byteLength - 1\n  let mul = 1\n  this[offset + i] = value & 0xFF\n  while (--i >= 0 && (mul *= 0x100)) {\n    this[offset + i] = (value / mul) & 0xFF\n  }\n\n  return offset + byteLength\n}\n\nBuffer.prototype.writeUint8 =\nBuffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)\n  this[offset] = (value & 0xff)\n  return offset + 1\n}\n\nBuffer.prototype.writeUint16LE =\nBuffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)\n  this[offset] = (value & 0xff)\n  this[offset + 1] = (value >>> 8)\n  return offset + 2\n}\n\nBuffer.prototype.writeUint16BE =\nBuffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)\n  this[offset] = (value >>> 8)\n  this[offset + 1] = (value & 0xff)\n  return offset + 2\n}\n\nBuffer.prototype.writeUint32LE =\nBuffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)\n  this[offset + 3] = (value >>> 24)\n  this[offset + 2] = (value >>> 16)\n  this[offset + 1] = (value >>> 8)\n  this[offset] = (value & 0xff)\n  return offset + 4\n}\n\nBuffer.prototype.writeUint32BE =\nBuffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)\n  this[offset] = (value >>> 24)\n  this[offset + 1] = (value >>> 16)\n  this[offset + 2] = (value >>> 8)\n  this[offset + 3] = (value & 0xff)\n  return offset + 4\n}\n\nfunction wrtBigUInt64LE (buf, value, offset, min, max) {\n  checkIntBI(value, min, max, buf, offset, 7)\n\n  let lo = Number(value & BigInt(0xffffffff))\n  buf[offset++] = lo\n  lo = lo >> 8\n  buf[offset++] = lo\n  lo = lo >> 8\n  buf[offset++] = lo\n  lo = lo >> 8\n  buf[offset++] = lo\n  let hi = Number(value >> BigInt(32) & BigInt(0xffffffff))\n  buf[offset++] = hi\n  hi = hi >> 8\n  buf[offset++] = hi\n  hi = hi >> 8\n  buf[offset++] = hi\n  hi = hi >> 8\n  buf[offset++] = hi\n  return offset\n}\n\nfunction wrtBigUInt64BE (buf, value, offset, min, max) {\n  checkIntBI(value, min, max, buf, offset, 7)\n\n  let lo = Number(value & BigInt(0xffffffff))\n  buf[offset + 7] = lo\n  lo = lo >> 8\n  buf[offset + 6] = lo\n  lo = lo >> 8\n  buf[offset + 5] = lo\n  lo = lo >> 8\n  buf[offset + 4] = lo\n  let hi = Number(value >> BigInt(32) & BigInt(0xffffffff))\n  buf[offset + 3] = hi\n  hi = hi >> 8\n  buf[offset + 2] = hi\n  hi = hi >> 8\n  buf[offset + 1] = hi\n  hi = hi >> 8\n  buf[offset] = hi\n  return offset + 8\n}\n\nBuffer.prototype.writeBigUInt64LE = defineBigIntMethod(function writeBigUInt64LE (value, offset = 0) {\n  return wrtBigUInt64LE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff'))\n})\n\nBuffer.prototype.writeBigUInt64BE = defineBigIntMethod(function writeBigUInt64BE (value, offset = 0) {\n  return wrtBigUInt64BE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff'))\n})\n\nBuffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) {\n    const limit = Math.pow(2, (8 * byteLength) - 1)\n\n    checkInt(this, value, offset, byteLength, limit - 1, -limit)\n  }\n\n  let i = 0\n  let mul = 1\n  let sub = 0\n  this[offset] = value & 0xFF\n  while (++i < byteLength && (mul *= 0x100)) {\n    if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {\n      sub = 1\n    }\n    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF\n  }\n\n  return offset + byteLength\n}\n\nBuffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) {\n    const limit = Math.pow(2, (8 * byteLength) - 1)\n\n    checkInt(this, value, offset, byteLength, limit - 1, -limit)\n  }\n\n  let i = byteLength - 1\n  let mul = 1\n  let sub = 0\n  this[offset + i] = value & 0xFF\n  while (--i >= 0 && (mul *= 0x100)) {\n    if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {\n      sub = 1\n    }\n    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF\n  }\n\n  return offset + byteLength\n}\n\nBuffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)\n  if (value < 0) value = 0xff + value + 1\n  this[offset] = (value & 0xff)\n  return offset + 1\n}\n\nBuffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)\n  this[offset] = (value & 0xff)\n  this[offset + 1] = (value >>> 8)\n  return offset + 2\n}\n\nBuffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)\n  this[offset] = (value >>> 8)\n  this[offset + 1] = (value & 0xff)\n  return offset + 2\n}\n\nBuffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)\n  this[offset] = (value & 0xff)\n  this[offset + 1] = (value >>> 8)\n  this[offset + 2] = (value >>> 16)\n  this[offset + 3] = (value >>> 24)\n  return offset + 4\n}\n\nBuffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)\n  if (value < 0) value = 0xffffffff + value + 1\n  this[offset] = (value >>> 24)\n  this[offset + 1] = (value >>> 16)\n  this[offset + 2] = (value >>> 8)\n  this[offset + 3] = (value & 0xff)\n  return offset + 4\n}\n\nBuffer.prototype.writeBigInt64LE = defineBigIntMethod(function writeBigInt64LE (value, offset = 0) {\n  return wrtBigUInt64LE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff'))\n})\n\nBuffer.prototype.writeBigInt64BE = defineBigIntMethod(function writeBigInt64BE (value, offset = 0) {\n  return wrtBigUInt64BE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff'))\n})\n\nfunction checkIEEE754 (buf, value, offset, ext, max, min) {\n  if (offset + ext > buf.length) throw new RangeError('Index out of range')\n  if (offset < 0) throw new RangeError('Index out of range')\n}\n\nfunction writeFloat (buf, value, offset, littleEndian, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) {\n    checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)\n  }\n  ieee754.write(buf, value, offset, littleEndian, 23, 4)\n  return offset + 4\n}\n\nBuffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {\n  return writeFloat(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {\n  return writeFloat(this, value, offset, false, noAssert)\n}\n\nfunction writeDouble (buf, value, offset, littleEndian, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) {\n    checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)\n  }\n  ieee754.write(buf, value, offset, littleEndian, 52, 8)\n  return offset + 8\n}\n\nBuffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {\n  return writeDouble(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {\n  return writeDouble(this, value, offset, false, noAssert)\n}\n\n// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)\nBuffer.prototype.copy = function copy (target, targetStart, start, end) {\n  if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer')\n  if (!start) start = 0\n  if (!end && end !== 0) end = this.length\n  if (targetStart >= target.length) targetStart = target.length\n  if (!targetStart) targetStart = 0\n  if (end > 0 && end < start) end = start\n\n  // Copy 0 bytes; we're done\n  if (end === start) return 0\n  if (target.length === 0 || this.length === 0) return 0\n\n  // Fatal error conditions\n  if (targetStart < 0) {\n    throw new RangeError('targetStart out of bounds')\n  }\n  if (start < 0 || start >= this.length) throw new RangeError('Index out of range')\n  if (end < 0) throw new RangeError('sourceEnd out of bounds')\n\n  // Are we oob?\n  if (end > this.length) end = this.length\n  if (target.length - targetStart < end - start) {\n    end = target.length - targetStart + start\n  }\n\n  const len = end - start\n\n  if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') {\n    // Use built-in when available, missing from IE11\n    this.copyWithin(targetStart, start, end)\n  } else {\n    Uint8Array.prototype.set.call(\n      target,\n      this.subarray(start, end),\n      targetStart\n    )\n  }\n\n  return len\n}\n\n// Usage:\n//    buffer.fill(number[, offset[, end]])\n//    buffer.fill(buffer[, offset[, end]])\n//    buffer.fill(string[, offset[, end]][, encoding])\nBuffer.prototype.fill = function fill (val, start, end, encoding) {\n  // Handle string cases:\n  if (typeof val === 'string') {\n    if (typeof start === 'string') {\n      encoding = start\n      start = 0\n      end = this.length\n    } else if (typeof end === 'string') {\n      encoding = end\n      end = this.length\n    }\n    if (encoding !== undefined && typeof encoding !== 'string') {\n      throw new TypeError('encoding must be a string')\n    }\n    if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {\n      throw new TypeError('Unknown encoding: ' + encoding)\n    }\n    if (val.length === 1) {\n      const code = val.charCodeAt(0)\n      if ((encoding === 'utf8' && code < 128) ||\n          encoding === 'latin1') {\n        // Fast path: If `val` fits into a single byte, use that numeric value.\n        val = code\n      }\n    }\n  } else if (typeof val === 'number') {\n    val = val & 255\n  } else if (typeof val === 'boolean') {\n    val = Number(val)\n  }\n\n  // Invalid ranges are not set to a default, so can range check early.\n  if (start < 0 || this.length < start || this.length < end) {\n    throw new RangeError('Out of range index')\n  }\n\n  if (end <= start) {\n    return this\n  }\n\n  start = start >>> 0\n  end = end === undefined ? this.length : end >>> 0\n\n  if (!val) val = 0\n\n  let i\n  if (typeof val === 'number') {\n    for (i = start; i < end; ++i) {\n      this[i] = val\n    }\n  } else {\n    const bytes = Buffer.isBuffer(val)\n      ? val\n      : Buffer.from(val, encoding)\n    const len = bytes.length\n    if (len === 0) {\n      throw new TypeError('The value \"' + val +\n        '\" is invalid for argument \"value\"')\n    }\n    for (i = 0; i < end - start; ++i) {\n      this[i + start] = bytes[i % len]\n    }\n  }\n\n  return this\n}\n\n// CUSTOM ERRORS\n// =============\n\n// Simplified versions from Node, changed for Buffer-only usage\nconst errors = {}\nfunction E (sym, getMessage, Base) {\n  errors[sym] = class NodeError extends Base {\n    constructor () {\n      super()\n\n      Object.defineProperty(this, 'message', {\n        value: getMessage.apply(this, arguments),\n        writable: true,\n        configurable: true\n      })\n\n      // Add the error code to the name to include it in the stack trace.\n      this.name = `${this.name} [${sym}]`\n      // Access the stack to generate the error message including the error code\n      // from the name.\n      this.stack // eslint-disable-line no-unused-expressions\n      // Reset the name to the actual name.\n      delete this.name\n    }\n\n    get code () {\n      return sym\n    }\n\n    set code (value) {\n      Object.defineProperty(this, 'code', {\n        configurable: true,\n        enumerable: true,\n        value,\n        writable: true\n      })\n    }\n\n    toString () {\n      return `${this.name} [${sym}]: ${this.message}`\n    }\n  }\n}\n\nE('ERR_BUFFER_OUT_OF_BOUNDS',\n  function (name) {\n    if (name) {\n      return `${name} is outside of buffer bounds`\n    }\n\n    return 'Attempt to access memory outside buffer bounds'\n  }, RangeError)\nE('ERR_INVALID_ARG_TYPE',\n  function (name, actual) {\n    return `The \"${name}\" argument must be of type number. Received type ${typeof actual}`\n  }, TypeError)\nE('ERR_OUT_OF_RANGE',\n  function (str, range, input) {\n    let msg = `The value of \"${str}\" is out of range.`\n    let received = input\n    if (Number.isInteger(input) && Math.abs(input) > 2 ** 32) {\n      received = addNumericalSeparator(String(input))\n    } else if (typeof input === 'bigint') {\n      received = String(input)\n      if (input > BigInt(2) ** BigInt(32) || input < -(BigInt(2) ** BigInt(32))) {\n        received = addNumericalSeparator(received)\n      }\n      received += 'n'\n    }\n    msg += ` It must be ${range}. Received ${received}`\n    return msg\n  }, RangeError)\n\nfunction addNumericalSeparator (val) {\n  let res = ''\n  let i = val.length\n  const start = val[0] === '-' ? 1 : 0\n  for (; i >= start + 4; i -= 3) {\n    res = `_${val.slice(i - 3, i)}${res}`\n  }\n  return `${val.slice(0, i)}${res}`\n}\n\n// CHECK FUNCTIONS\n// ===============\n\nfunction checkBounds (buf, offset, byteLength) {\n  validateNumber(offset, 'offset')\n  if (buf[offset] === undefined || buf[offset + byteLength] === undefined) {\n    boundsError(offset, buf.length - (byteLength + 1))\n  }\n}\n\nfunction checkIntBI (value, min, max, buf, offset, byteLength) {\n  if (value > max || value < min) {\n    const n = typeof min === 'bigint' ? 'n' : ''\n    let range\n    if (byteLength > 3) {\n      if (min === 0 || min === BigInt(0)) {\n        range = `>= 0${n} and < 2${n} ** ${(byteLength + 1) * 8}${n}`\n      } else {\n        range = `>= -(2${n} ** ${(byteLength + 1) * 8 - 1}${n}) and < 2 ** ` +\n                `${(byteLength + 1) * 8 - 1}${n}`\n      }\n    } else {\n      range = `>= ${min}${n} and <= ${max}${n}`\n    }\n    throw new errors.ERR_OUT_OF_RANGE('value', range, value)\n  }\n  checkBounds(buf, offset, byteLength)\n}\n\nfunction validateNumber (value, name) {\n  if (typeof value !== 'number') {\n    throw new errors.ERR_INVALID_ARG_TYPE(name, 'number', value)\n  }\n}\n\nfunction boundsError (value, length, type) {\n  if (Math.floor(value) !== value) {\n    validateNumber(value, type)\n    throw new errors.ERR_OUT_OF_RANGE(type || 'offset', 'an integer', value)\n  }\n\n  if (length < 0) {\n    throw new errors.ERR_BUFFER_OUT_OF_BOUNDS()\n  }\n\n  throw new errors.ERR_OUT_OF_RANGE(type || 'offset',\n                                    `>= ${type ? 1 : 0} and <= ${length}`,\n                                    value)\n}\n\n// HELPER FUNCTIONS\n// ================\n\nconst INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g\n\nfunction base64clean (str) {\n  // Node takes equal signs as end of the Base64 encoding\n  str = str.split('=')[0]\n  // Node strips out invalid characters like \\n and \\t from the string, base64-js does not\n  str = str.trim().replace(INVALID_BASE64_RE, '')\n  // Node converts strings with length < 2 to ''\n  if (str.length < 2) return ''\n  // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not\n  while (str.length % 4 !== 0) {\n    str = str + '='\n  }\n  return str\n}\n\nfunction utf8ToBytes (string, units) {\n  units = units || Infinity\n  let codePoint\n  const length = string.length\n  let leadSurrogate = null\n  const bytes = []\n\n  for (let i = 0; i < length; ++i) {\n    codePoint = string.charCodeAt(i)\n\n    // is surrogate component\n    if (codePoint > 0xD7FF && codePoint < 0xE000) {\n      // last char was a lead\n      if (!leadSurrogate) {\n        // no lead yet\n        if (codePoint > 0xDBFF) {\n          // unexpected trail\n          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n          continue\n        } else if (i + 1 === length) {\n          // unpaired lead\n          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n          continue\n        }\n\n        // valid lead\n        leadSurrogate = codePoint\n\n        continue\n      }\n\n      // 2 leads in a row\n      if (codePoint < 0xDC00) {\n        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n        leadSurrogate = codePoint\n        continue\n      }\n\n      // valid surrogate pair\n      codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000\n    } else if (leadSurrogate) {\n      // valid bmp char, but last char was a lead\n      if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n    }\n\n    leadSurrogate = null\n\n    // encode utf8\n    if (codePoint < 0x80) {\n      if ((units -= 1) < 0) break\n      bytes.push(codePoint)\n    } else if (codePoint < 0x800) {\n      if ((units -= 2) < 0) break\n      bytes.push(\n        codePoint >> 0x6 | 0xC0,\n        codePoint & 0x3F | 0x80\n      )\n    } else if (codePoint < 0x10000) {\n      if ((units -= 3) < 0) break\n      bytes.push(\n        codePoint >> 0xC | 0xE0,\n        codePoint >> 0x6 & 0x3F | 0x80,\n        codePoint & 0x3F | 0x80\n      )\n    } else if (codePoint < 0x110000) {\n      if ((units -= 4) < 0) break\n      bytes.push(\n        codePoint >> 0x12 | 0xF0,\n        codePoint >> 0xC & 0x3F | 0x80,\n        codePoint >> 0x6 & 0x3F | 0x80,\n        codePoint & 0x3F | 0x80\n      )\n    } else {\n      throw new Error('Invalid code point')\n    }\n  }\n\n  return bytes\n}\n\nfunction asciiToBytes (str) {\n  const byteArray = []\n  for (let i = 0; i < str.length; ++i) {\n    // Node's code seems to be doing this and not & 0x7F..\n    byteArray.push(str.charCodeAt(i) & 0xFF)\n  }\n  return byteArray\n}\n\nfunction utf16leToBytes (str, units) {\n  let c, hi, lo\n  const byteArray = []\n  for (let i = 0; i < str.length; ++i) {\n    if ((units -= 2) < 0) break\n\n    c = str.charCodeAt(i)\n    hi = c >> 8\n    lo = c % 256\n    byteArray.push(lo)\n    byteArray.push(hi)\n  }\n\n  return byteArray\n}\n\nfunction base64ToBytes (str) {\n  return base64.toByteArray(base64clean(str))\n}\n\nfunction blitBuffer (src, dst, offset, length) {\n  let i\n  for (i = 0; i < length; ++i) {\n    if ((i + offset >= dst.length) || (i >= src.length)) break\n    dst[i + offset] = src[i]\n  }\n  return i\n}\n\n// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass\n// the `instanceof` check but they should be treated as of that type.\n// See: https://github.com/feross/buffer/issues/166\nfunction isInstance (obj, type) {\n  return obj instanceof type ||\n    (obj != null && obj.constructor != null && obj.constructor.name != null &&\n      obj.constructor.name === type.name)\n}\nfunction numberIsNaN (obj) {\n  // For IE11 support\n  return obj !== obj // eslint-disable-line no-self-compare\n}\n\n// Create lookup table for `toString('hex')`\n// See: https://github.com/feross/buffer/issues/219\nconst hexSliceLookupTable = (function () {\n  const alphabet = '0123456789abcdef'\n  const table = new Array(256)\n  for (let i = 0; i < 16; ++i) {\n    const i16 = i * 16\n    for (let j = 0; j < 16; ++j) {\n      table[i16 + j] = alphabet[i] + alphabet[j]\n    }\n  }\n  return table\n})()\n\n// Return not function with Error if BigInt not supported\nfunction defineBigIntMethod (fn) {\n  return typeof BigInt === 'undefined' ? BufferBigIntNotDefined : fn\n}\n\nfunction BufferBigIntNotDefined () {\n  throw new Error('BigInt not supported')\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNzY0LmpzIiwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvYnVmZmVyL2luZGV4LmpzP2I2MzkiXSwic291cmNlc0NvbnRlbnQiOlsiLyohXG4gKiBUaGUgYnVmZmVyIG1vZHVsZSBmcm9tIG5vZGUuanMsIGZvciB0aGUgYnJvd3Nlci5cbiAqXG4gKiBAYXV0aG9yICAgRmVyb3NzIEFib3VraGFkaWplaCA8aHR0cHM6Ly9mZXJvc3Mub3JnPlxuICogQGxpY2Vuc2UgIE1JVFxuICovXG4vKiBlc2xpbnQtZGlzYWJsZSBuby1wcm90byAqL1xuXG4ndXNlIHN0cmljdCdcblxuY29uc3QgYmFzZTY0ID0gcmVxdWlyZSgnYmFzZTY0LWpzJylcbmNvbnN0IGllZWU3NTQgPSByZXF1aXJlKCdpZWVlNzU0JylcbmNvbnN0IGN1c3RvbUluc3BlY3RTeW1ib2wgPVxuICAodHlwZW9mIFN5bWJvbCA9PT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgU3ltYm9sWydmb3InXSA9PT0gJ2Z1bmN0aW9uJykgLy8gZXNsaW50LWRpc2FibGUtbGluZSBkb3Qtbm90YXRpb25cbiAgICA/IFN5bWJvbFsnZm9yJ10oJ25vZGVqcy51dGlsLmluc3BlY3QuY3VzdG9tJykgLy8gZXNsaW50LWRpc2FibGUtbGluZSBkb3Qtbm90YXRpb25cbiAgICA6IG51bGxcblxuZXhwb3J0cy5CdWZmZXIgPSBCdWZmZXJcbmV4cG9ydHMuU2xvd0J1ZmZlciA9IFNsb3dCdWZmZXJcbmV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVMgPSA1MFxuXG5jb25zdCBLX01BWF9MRU5HVEggPSAweDdmZmZmZmZmXG5leHBvcnRzLmtNYXhMZW5ndGggPSBLX01BWF9MRU5HVEhcblxuLyoqXG4gKiBJZiBgQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlRgOlxuICogICA9PT0gdHJ1ZSAgICBVc2UgVWludDhBcnJheSBpbXBsZW1lbnRhdGlvbiAoZmFzdGVzdClcbiAqICAgPT09IGZhbHNlICAgUHJpbnQgd2FybmluZyBhbmQgcmVjb21tZW5kIHVzaW5nIGBidWZmZXJgIHY0Lnggd2hpY2ggaGFzIGFuIE9iamVjdFxuICogICAgICAgICAgICAgICBpbXBsZW1lbnRhdGlvbiAobW9zdCBjb21wYXRpYmxlLCBldmVuIElFNilcbiAqXG4gKiBCcm93c2VycyB0aGF0IHN1cHBvcnQgdHlwZWQgYXJyYXlzIGFyZSBJRSAxMCssIEZpcmVmb3ggNCssIENocm9tZSA3KywgU2FmYXJpIDUuMSssXG4gKiBPcGVyYSAxMS42KywgaU9TIDQuMisuXG4gKlxuICogV2UgcmVwb3J0IHRoYXQgdGhlIGJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCB0eXBlZCBhcnJheXMgaWYgdGhlIGFyZSBub3Qgc3ViY2xhc3NhYmxlXG4gKiB1c2luZyBfX3Byb3RvX18uIEZpcmVmb3ggNC0yOSBsYWNrcyBzdXBwb3J0IGZvciBhZGRpbmcgbmV3IHByb3BlcnRpZXMgdG8gYFVpbnQ4QXJyYXlgXG4gKiAoU2VlOiBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD02OTU0MzgpLiBJRSAxMCBsYWNrcyBzdXBwb3J0XG4gKiBmb3IgX19wcm90b19fIGFuZCBoYXMgYSBidWdneSB0eXBlZCBhcnJheSBpbXBsZW1lbnRhdGlvbi5cbiAqL1xuQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQgPSB0eXBlZEFycmF5U3VwcG9ydCgpXG5cbmlmICghQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQgJiYgdHlwZW9mIGNvbnNvbGUgIT09ICd1bmRlZmluZWQnICYmXG4gICAgdHlwZW9mIGNvbnNvbGUuZXJyb3IgPT09ICdmdW5jdGlvbicpIHtcbiAgY29uc29sZS5lcnJvcihcbiAgICAnVGhpcyBicm93c2VyIGxhY2tzIHR5cGVkIGFycmF5IChVaW50OEFycmF5KSBzdXBwb3J0IHdoaWNoIGlzIHJlcXVpcmVkIGJ5ICcgK1xuICAgICdgYnVmZmVyYCB2NS54LiBVc2UgYGJ1ZmZlcmAgdjQueCBpZiB5b3UgcmVxdWlyZSBvbGQgYnJvd3NlciBzdXBwb3J0LidcbiAgKVxufVxuXG5mdW5jdGlvbiB0eXBlZEFycmF5U3VwcG9ydCAoKSB7XG4gIC8vIENhbiB0eXBlZCBhcnJheSBpbnN0YW5jZXMgY2FuIGJlIGF1Z21lbnRlZD9cbiAgdHJ5IHtcbiAgICBjb25zdCBhcnIgPSBuZXcgVWludDhBcnJheSgxKVxuICAgIGNvbnN0IHByb3RvID0geyBmb286IGZ1bmN0aW9uICgpIHsgcmV0dXJuIDQyIH0gfVxuICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZihwcm90bywgVWludDhBcnJheS5wcm90b3R5cGUpXG4gICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKGFyciwgcHJvdG8pXG4gICAgcmV0dXJuIGFyci5mb28oKSA9PT0gNDJcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShCdWZmZXIucHJvdG90eXBlLCAncGFyZW50Jywge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcih0aGlzKSkgcmV0dXJuIHVuZGVmaW5lZFxuICAgIHJldHVybiB0aGlzLmJ1ZmZlclxuICB9XG59KVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoQnVmZmVyLnByb3RvdHlwZSwgJ29mZnNldCcsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCFCdWZmZXIuaXNCdWZmZXIodGhpcykpIHJldHVybiB1bmRlZmluZWRcbiAgICByZXR1cm4gdGhpcy5ieXRlT2Zmc2V0XG4gIH1cbn0pXG5cbmZ1bmN0aW9uIGNyZWF0ZUJ1ZmZlciAobGVuZ3RoKSB7XG4gIGlmIChsZW5ndGggPiBLX01BWF9MRU5HVEgpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignVGhlIHZhbHVlIFwiJyArIGxlbmd0aCArICdcIiBpcyBpbnZhbGlkIGZvciBvcHRpb24gXCJzaXplXCInKVxuICB9XG4gIC8vIFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlXG4gIGNvbnN0IGJ1ZiA9IG5ldyBVaW50OEFycmF5KGxlbmd0aClcbiAgT2JqZWN0LnNldFByb3RvdHlwZU9mKGJ1ZiwgQnVmZmVyLnByb3RvdHlwZSlcbiAgcmV0dXJuIGJ1ZlxufVxuXG4vKipcbiAqIFRoZSBCdWZmZXIgY29uc3RydWN0b3IgcmV0dXJucyBpbnN0YW5jZXMgb2YgYFVpbnQ4QXJyYXlgIHRoYXQgaGF2ZSB0aGVpclxuICogcHJvdG90eXBlIGNoYW5nZWQgdG8gYEJ1ZmZlci5wcm90b3R5cGVgLiBGdXJ0aGVybW9yZSwgYEJ1ZmZlcmAgaXMgYSBzdWJjbGFzcyBvZlxuICogYFVpbnQ4QXJyYXlgLCBzbyB0aGUgcmV0dXJuZWQgaW5zdGFuY2VzIHdpbGwgaGF2ZSBhbGwgdGhlIG5vZGUgYEJ1ZmZlcmAgbWV0aG9kc1xuICogYW5kIHRoZSBgVWludDhBcnJheWAgbWV0aG9kcy4gU3F1YXJlIGJyYWNrZXQgbm90YXRpb24gd29ya3MgYXMgZXhwZWN0ZWQgLS0gaXRcbiAqIHJldHVybnMgYSBzaW5nbGUgb2N0ZXQuXG4gKlxuICogVGhlIGBVaW50OEFycmF5YCBwcm90b3R5cGUgcmVtYWlucyB1bm1vZGlmaWVkLlxuICovXG5cbmZ1bmN0aW9uIEJ1ZmZlciAoYXJnLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpIHtcbiAgLy8gQ29tbW9uIGNhc2UuXG4gIGlmICh0eXBlb2YgYXJnID09PSAnbnVtYmVyJykge1xuICAgIGlmICh0eXBlb2YgZW5jb2RpbmdPck9mZnNldCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICdUaGUgXCJzdHJpbmdcIiBhcmd1bWVudCBtdXN0IGJlIG9mIHR5cGUgc3RyaW5nLiBSZWNlaXZlZCB0eXBlIG51bWJlcidcbiAgICAgIClcbiAgICB9XG4gICAgcmV0dXJuIGFsbG9jVW5zYWZlKGFyZylcbiAgfVxuICByZXR1cm4gZnJvbShhcmcsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aClcbn1cblxuQnVmZmVyLnBvb2xTaXplID0gODE5MiAvLyBub3QgdXNlZCBieSB0aGlzIGltcGxlbWVudGF0aW9uXG5cbmZ1bmN0aW9uIGZyb20gKHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gZnJvbVN0cmluZyh2YWx1ZSwgZW5jb2RpbmdPck9mZnNldClcbiAgfVxuXG4gIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcodmFsdWUpKSB7XG4gICAgcmV0dXJuIGZyb21BcnJheVZpZXcodmFsdWUpXG4gIH1cblxuICBpZiAodmFsdWUgPT0gbnVsbCkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnVGhlIGZpcnN0IGFyZ3VtZW50IG11c3QgYmUgb25lIG9mIHR5cGUgc3RyaW5nLCBCdWZmZXIsIEFycmF5QnVmZmVyLCBBcnJheSwgJyArXG4gICAgICAnb3IgQXJyYXktbGlrZSBPYmplY3QuIFJlY2VpdmVkIHR5cGUgJyArICh0eXBlb2YgdmFsdWUpXG4gICAgKVxuICB9XG5cbiAgaWYgKGlzSW5zdGFuY2UodmFsdWUsIEFycmF5QnVmZmVyKSB8fFxuICAgICAgKHZhbHVlICYmIGlzSW5zdGFuY2UodmFsdWUuYnVmZmVyLCBBcnJheUJ1ZmZlcikpKSB7XG4gICAgcmV0dXJuIGZyb21BcnJheUJ1ZmZlcih2YWx1ZSwgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKVxuICB9XG5cbiAgaWYgKHR5cGVvZiBTaGFyZWRBcnJheUJ1ZmZlciAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIChpc0luc3RhbmNlKHZhbHVlLCBTaGFyZWRBcnJheUJ1ZmZlcikgfHxcbiAgICAgICh2YWx1ZSAmJiBpc0luc3RhbmNlKHZhbHVlLmJ1ZmZlciwgU2hhcmVkQXJyYXlCdWZmZXIpKSkpIHtcbiAgICByZXR1cm4gZnJvbUFycmF5QnVmZmVyKHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpXG4gIH1cblxuICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnVGhlIFwidmFsdWVcIiBhcmd1bWVudCBtdXN0IG5vdCBiZSBvZiB0eXBlIG51bWJlci4gUmVjZWl2ZWQgdHlwZSBudW1iZXInXG4gICAgKVxuICB9XG5cbiAgY29uc3QgdmFsdWVPZiA9IHZhbHVlLnZhbHVlT2YgJiYgdmFsdWUudmFsdWVPZigpXG4gIGlmICh2YWx1ZU9mICE9IG51bGwgJiYgdmFsdWVPZiAhPT0gdmFsdWUpIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20odmFsdWVPZiwgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKVxuICB9XG5cbiAgY29uc3QgYiA9IGZyb21PYmplY3QodmFsdWUpXG4gIGlmIChiKSByZXR1cm4gYlxuXG4gIGlmICh0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9QcmltaXRpdmUgIT0gbnVsbCAmJlxuICAgICAgdHlwZW9mIHZhbHVlW1N5bWJvbC50b1ByaW1pdGl2ZV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20odmFsdWVbU3ltYm9sLnRvUHJpbWl0aXZlXSgnc3RyaW5nJyksIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aClcbiAgfVxuXG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgJ1RoZSBmaXJzdCBhcmd1bWVudCBtdXN0IGJlIG9uZSBvZiB0eXBlIHN0cmluZywgQnVmZmVyLCBBcnJheUJ1ZmZlciwgQXJyYXksICcgK1xuICAgICdvciBBcnJheS1saWtlIE9iamVjdC4gUmVjZWl2ZWQgdHlwZSAnICsgKHR5cGVvZiB2YWx1ZSlcbiAgKVxufVxuXG4vKipcbiAqIEZ1bmN0aW9uYWxseSBlcXVpdmFsZW50IHRvIEJ1ZmZlcihhcmcsIGVuY29kaW5nKSBidXQgdGhyb3dzIGEgVHlwZUVycm9yXG4gKiBpZiB2YWx1ZSBpcyBhIG51bWJlci5cbiAqIEJ1ZmZlci5mcm9tKHN0clssIGVuY29kaW5nXSlcbiAqIEJ1ZmZlci5mcm9tKGFycmF5KVxuICogQnVmZmVyLmZyb20oYnVmZmVyKVxuICogQnVmZmVyLmZyb20oYXJyYXlCdWZmZXJbLCBieXRlT2Zmc2V0WywgbGVuZ3RoXV0pXG4gKiovXG5CdWZmZXIuZnJvbSA9IGZ1bmN0aW9uICh2YWx1ZSwgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBmcm9tKHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpXG59XG5cbi8vIE5vdGU6IENoYW5nZSBwcm90b3R5cGUgKmFmdGVyKiBCdWZmZXIuZnJvbSBpcyBkZWZpbmVkIHRvIHdvcmthcm91bmQgQ2hyb21lIGJ1Zzpcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyL3B1bGwvMTQ4XG5PYmplY3Quc2V0UHJvdG90eXBlT2YoQnVmZmVyLnByb3RvdHlwZSwgVWludDhBcnJheS5wcm90b3R5cGUpXG5PYmplY3Quc2V0UHJvdG90eXBlT2YoQnVmZmVyLCBVaW50OEFycmF5KVxuXG5mdW5jdGlvbiBhc3NlcnRTaXplIChzaXplKSB7XG4gIGlmICh0eXBlb2Ygc2l6ZSAhPT0gJ251bWJlcicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcInNpemVcIiBhcmd1bWVudCBtdXN0IGJlIG9mIHR5cGUgbnVtYmVyJylcbiAgfSBlbHNlIGlmIChzaXplIDwgMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdUaGUgdmFsdWUgXCInICsgc2l6ZSArICdcIiBpcyBpbnZhbGlkIGZvciBvcHRpb24gXCJzaXplXCInKVxuICB9XG59XG5cbmZ1bmN0aW9uIGFsbG9jIChzaXplLCBmaWxsLCBlbmNvZGluZykge1xuICBhc3NlcnRTaXplKHNpemUpXG4gIGlmIChzaXplIDw9IDApIHtcbiAgICByZXR1cm4gY3JlYXRlQnVmZmVyKHNpemUpXG4gIH1cbiAgaWYgKGZpbGwgIT09IHVuZGVmaW5lZCkge1xuICAgIC8vIE9ubHkgcGF5IGF0dGVudGlvbiB0byBlbmNvZGluZyBpZiBpdCdzIGEgc3RyaW5nLiBUaGlzXG4gICAgLy8gcHJldmVudHMgYWNjaWRlbnRhbGx5IHNlbmRpbmcgaW4gYSBudW1iZXIgdGhhdCB3b3VsZFxuICAgIC8vIGJlIGludGVycHJldGVkIGFzIGEgc3RhcnQgb2Zmc2V0LlxuICAgIHJldHVybiB0eXBlb2YgZW5jb2RpbmcgPT09ICdzdHJpbmcnXG4gICAgICA/IGNyZWF0ZUJ1ZmZlcihzaXplKS5maWxsKGZpbGwsIGVuY29kaW5nKVxuICAgICAgOiBjcmVhdGVCdWZmZXIoc2l6ZSkuZmlsbChmaWxsKVxuICB9XG4gIHJldHVybiBjcmVhdGVCdWZmZXIoc2l6ZSlcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGZpbGxlZCBCdWZmZXIgaW5zdGFuY2UuXG4gKiBhbGxvYyhzaXplWywgZmlsbFssIGVuY29kaW5nXV0pXG4gKiovXG5CdWZmZXIuYWxsb2MgPSBmdW5jdGlvbiAoc2l6ZSwgZmlsbCwgZW5jb2RpbmcpIHtcbiAgcmV0dXJuIGFsbG9jKHNpemUsIGZpbGwsIGVuY29kaW5nKVxufVxuXG5mdW5jdGlvbiBhbGxvY1Vuc2FmZSAoc2l6ZSkge1xuICBhc3NlcnRTaXplKHNpemUpXG4gIHJldHVybiBjcmVhdGVCdWZmZXIoc2l6ZSA8IDAgPyAwIDogY2hlY2tlZChzaXplKSB8IDApXG59XG5cbi8qKlxuICogRXF1aXZhbGVudCB0byBCdWZmZXIobnVtKSwgYnkgZGVmYXVsdCBjcmVhdGVzIGEgbm9uLXplcm8tZmlsbGVkIEJ1ZmZlciBpbnN0YW5jZS5cbiAqICovXG5CdWZmZXIuYWxsb2NVbnNhZmUgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICByZXR1cm4gYWxsb2NVbnNhZmUoc2l6ZSlcbn1cbi8qKlxuICogRXF1aXZhbGVudCB0byBTbG93QnVmZmVyKG51bSksIGJ5IGRlZmF1bHQgY3JlYXRlcyBhIG5vbi16ZXJvLWZpbGxlZCBCdWZmZXIgaW5zdGFuY2UuXG4gKi9cbkJ1ZmZlci5hbGxvY1Vuc2FmZVNsb3cgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICByZXR1cm4gYWxsb2NVbnNhZmUoc2l6ZSlcbn1cblxuZnVuY3Rpb24gZnJvbVN0cmluZyAoc3RyaW5nLCBlbmNvZGluZykge1xuICBpZiAodHlwZW9mIGVuY29kaW5nICE9PSAnc3RyaW5nJyB8fCBlbmNvZGluZyA9PT0gJycpIHtcbiAgICBlbmNvZGluZyA9ICd1dGY4J1xuICB9XG5cbiAgaWYgKCFCdWZmZXIuaXNFbmNvZGluZyhlbmNvZGluZykpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gIH1cblxuICBjb25zdCBsZW5ndGggPSBieXRlTGVuZ3RoKHN0cmluZywgZW5jb2RpbmcpIHwgMFxuICBsZXQgYnVmID0gY3JlYXRlQnVmZmVyKGxlbmd0aClcblxuICBjb25zdCBhY3R1YWwgPSBidWYud3JpdGUoc3RyaW5nLCBlbmNvZGluZylcblxuICBpZiAoYWN0dWFsICE9PSBsZW5ndGgpIHtcbiAgICAvLyBXcml0aW5nIGEgaGV4IHN0cmluZywgZm9yIGV4YW1wbGUsIHRoYXQgY29udGFpbnMgaW52YWxpZCBjaGFyYWN0ZXJzIHdpbGxcbiAgICAvLyBjYXVzZSBldmVyeXRoaW5nIGFmdGVyIHRoZSBmaXJzdCBpbnZhbGlkIGNoYXJhY3RlciB0byBiZSBpZ25vcmVkLiAoZS5nLlxuICAgIC8vICdhYnh4Y2QnIHdpbGwgYmUgdHJlYXRlZCBhcyAnYWInKVxuICAgIGJ1ZiA9IGJ1Zi5zbGljZSgwLCBhY3R1YWwpXG4gIH1cblxuICByZXR1cm4gYnVmXG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheUxpa2UgKGFycmF5KSB7XG4gIGNvbnN0IGxlbmd0aCA9IGFycmF5Lmxlbmd0aCA8IDAgPyAwIDogY2hlY2tlZChhcnJheS5sZW5ndGgpIHwgMFxuICBjb25zdCBidWYgPSBjcmVhdGVCdWZmZXIobGVuZ3RoKVxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgYnVmW2ldID0gYXJyYXlbaV0gJiAyNTVcbiAgfVxuICByZXR1cm4gYnVmXG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheVZpZXcgKGFycmF5Vmlldykge1xuICBpZiAoaXNJbnN0YW5jZShhcnJheVZpZXcsIFVpbnQ4QXJyYXkpKSB7XG4gICAgY29uc3QgY29weSA9IG5ldyBVaW50OEFycmF5KGFycmF5VmlldylcbiAgICByZXR1cm4gZnJvbUFycmF5QnVmZmVyKGNvcHkuYnVmZmVyLCBjb3B5LmJ5dGVPZmZzZXQsIGNvcHkuYnl0ZUxlbmd0aClcbiAgfVxuICByZXR1cm4gZnJvbUFycmF5TGlrZShhcnJheVZpZXcpXG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheUJ1ZmZlciAoYXJyYXksIGJ5dGVPZmZzZXQsIGxlbmd0aCkge1xuICBpZiAoYnl0ZU9mZnNldCA8IDAgfHwgYXJyYXkuYnl0ZUxlbmd0aCA8IGJ5dGVPZmZzZXQpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignXCJvZmZzZXRcIiBpcyBvdXRzaWRlIG9mIGJ1ZmZlciBib3VuZHMnKVxuICB9XG5cbiAgaWYgKGFycmF5LmJ5dGVMZW5ndGggPCBieXRlT2Zmc2V0ICsgKGxlbmd0aCB8fCAwKSkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdcImxlbmd0aFwiIGlzIG91dHNpZGUgb2YgYnVmZmVyIGJvdW5kcycpXG4gIH1cblxuICBsZXQgYnVmXG4gIGlmIChieXRlT2Zmc2V0ID09PSB1bmRlZmluZWQgJiYgbGVuZ3RoID09PSB1bmRlZmluZWQpIHtcbiAgICBidWYgPSBuZXcgVWludDhBcnJheShhcnJheSlcbiAgfSBlbHNlIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCkge1xuICAgIGJ1ZiA9IG5ldyBVaW50OEFycmF5KGFycmF5LCBieXRlT2Zmc2V0KVxuICB9IGVsc2Uge1xuICAgIGJ1ZiA9IG5ldyBVaW50OEFycmF5KGFycmF5LCBieXRlT2Zmc2V0LCBsZW5ndGgpXG4gIH1cblxuICAvLyBSZXR1cm4gYW4gYXVnbWVudGVkIGBVaW50OEFycmF5YCBpbnN0YW5jZVxuICBPYmplY3Quc2V0UHJvdG90eXBlT2YoYnVmLCBCdWZmZXIucHJvdG90eXBlKVxuXG4gIHJldHVybiBidWZcbn1cblxuZnVuY3Rpb24gZnJvbU9iamVjdCAob2JqKSB7XG4gIGlmIChCdWZmZXIuaXNCdWZmZXIob2JqKSkge1xuICAgIGNvbnN0IGxlbiA9IGNoZWNrZWQob2JqLmxlbmd0aCkgfCAwXG4gICAgY29uc3QgYnVmID0gY3JlYXRlQnVmZmVyKGxlbilcblxuICAgIGlmIChidWYubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gYnVmXG4gICAgfVxuXG4gICAgb2JqLmNvcHkoYnVmLCAwLCAwLCBsZW4pXG4gICAgcmV0dXJuIGJ1ZlxuICB9XG5cbiAgaWYgKG9iai5sZW5ndGggIT09IHVuZGVmaW5lZCkge1xuICAgIGlmICh0eXBlb2Ygb2JqLmxlbmd0aCAhPT0gJ251bWJlcicgfHwgbnVtYmVySXNOYU4ob2JqLmxlbmd0aCkpIHtcbiAgICAgIHJldHVybiBjcmVhdGVCdWZmZXIoMClcbiAgICB9XG4gICAgcmV0dXJuIGZyb21BcnJheUxpa2Uob2JqKVxuICB9XG5cbiAgaWYgKG9iai50eXBlID09PSAnQnVmZmVyJyAmJiBBcnJheS5pc0FycmF5KG9iai5kYXRhKSkge1xuICAgIHJldHVybiBmcm9tQXJyYXlMaWtlKG9iai5kYXRhKVxuICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrZWQgKGxlbmd0aCkge1xuICAvLyBOb3RlOiBjYW5ub3QgdXNlIGBsZW5ndGggPCBLX01BWF9MRU5HVEhgIGhlcmUgYmVjYXVzZSB0aGF0IGZhaWxzIHdoZW5cbiAgLy8gbGVuZ3RoIGlzIE5hTiAod2hpY2ggaXMgb3RoZXJ3aXNlIGNvZXJjZWQgdG8gemVyby4pXG4gIGlmIChsZW5ndGggPj0gS19NQVhfTEVOR1RIKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0F0dGVtcHQgdG8gYWxsb2NhdGUgQnVmZmVyIGxhcmdlciB0aGFuIG1heGltdW0gJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgJ3NpemU6IDB4JyArIEtfTUFYX0xFTkdUSC50b1N0cmluZygxNikgKyAnIGJ5dGVzJylcbiAgfVxuICByZXR1cm4gbGVuZ3RoIHwgMFxufVxuXG5mdW5jdGlvbiBTbG93QnVmZmVyIChsZW5ndGgpIHtcbiAgaWYgKCtsZW5ndGggIT0gbGVuZ3RoKSB7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgZXFlcWVxXG4gICAgbGVuZ3RoID0gMFxuICB9XG4gIHJldHVybiBCdWZmZXIuYWxsb2MoK2xlbmd0aClcbn1cblxuQnVmZmVyLmlzQnVmZmVyID0gZnVuY3Rpb24gaXNCdWZmZXIgKGIpIHtcbiAgcmV0dXJuIGIgIT0gbnVsbCAmJiBiLl9pc0J1ZmZlciA9PT0gdHJ1ZSAmJlxuICAgIGIgIT09IEJ1ZmZlci5wcm90b3R5cGUgLy8gc28gQnVmZmVyLmlzQnVmZmVyKEJ1ZmZlci5wcm90b3R5cGUpIHdpbGwgYmUgZmFsc2Vcbn1cblxuQnVmZmVyLmNvbXBhcmUgPSBmdW5jdGlvbiBjb21wYXJlIChhLCBiKSB7XG4gIGlmIChpc0luc3RhbmNlKGEsIFVpbnQ4QXJyYXkpKSBhID0gQnVmZmVyLmZyb20oYSwgYS5vZmZzZXQsIGEuYnl0ZUxlbmd0aClcbiAgaWYgKGlzSW5zdGFuY2UoYiwgVWludDhBcnJheSkpIGIgPSBCdWZmZXIuZnJvbShiLCBiLm9mZnNldCwgYi5ieXRlTGVuZ3RoKVxuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihhKSB8fCAhQnVmZmVyLmlzQnVmZmVyKGIpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdUaGUgXCJidWYxXCIsIFwiYnVmMlwiIGFyZ3VtZW50cyBtdXN0IGJlIG9uZSBvZiB0eXBlIEJ1ZmZlciBvciBVaW50OEFycmF5J1xuICAgIClcbiAgfVxuXG4gIGlmIChhID09PSBiKSByZXR1cm4gMFxuXG4gIGxldCB4ID0gYS5sZW5ndGhcbiAgbGV0IHkgPSBiLmxlbmd0aFxuXG4gIGZvciAobGV0IGkgPSAwLCBsZW4gPSBNYXRoLm1pbih4LCB5KTsgaSA8IGxlbjsgKytpKSB7XG4gICAgaWYgKGFbaV0gIT09IGJbaV0pIHtcbiAgICAgIHggPSBhW2ldXG4gICAgICB5ID0gYltpXVxuICAgICAgYnJlYWtcbiAgICB9XG4gIH1cblxuICBpZiAoeCA8IHkpIHJldHVybiAtMVxuICBpZiAoeSA8IHgpIHJldHVybiAxXG4gIHJldHVybiAwXG59XG5cbkJ1ZmZlci5pc0VuY29kaW5nID0gZnVuY3Rpb24gaXNFbmNvZGluZyAoZW5jb2RpbmcpIHtcbiAgc3dpdGNoIChTdHJpbmcoZW5jb2RpbmcpLnRvTG93ZXJDYXNlKCkpIHtcbiAgICBjYXNlICdoZXgnOlxuICAgIGNhc2UgJ3V0ZjgnOlxuICAgIGNhc2UgJ3V0Zi04JzpcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgY2FzZSAnbGF0aW4xJzpcbiAgICBjYXNlICdiaW5hcnknOlxuICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndWNzLTInOlxuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgIHJldHVybiB0cnVlXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbkJ1ZmZlci5jb25jYXQgPSBmdW5jdGlvbiBjb25jYXQgKGxpc3QsIGxlbmd0aCkge1xuICBpZiAoIUFycmF5LmlzQXJyYXkobGlzdCkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RcIiBhcmd1bWVudCBtdXN0IGJlIGFuIEFycmF5IG9mIEJ1ZmZlcnMnKVxuICB9XG5cbiAgaWYgKGxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIEJ1ZmZlci5hbGxvYygwKVxuICB9XG5cbiAgbGV0IGlcbiAgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgbGVuZ3RoID0gMFxuICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgKytpKSB7XG4gICAgICBsZW5ndGggKz0gbGlzdFtpXS5sZW5ndGhcbiAgICB9XG4gIH1cblxuICBjb25zdCBidWZmZXIgPSBCdWZmZXIuYWxsb2NVbnNhZmUobGVuZ3RoKVxuICBsZXQgcG9zID0gMFxuICBmb3IgKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7ICsraSkge1xuICAgIGxldCBidWYgPSBsaXN0W2ldXG4gICAgaWYgKGlzSW5zdGFuY2UoYnVmLCBVaW50OEFycmF5KSkge1xuICAgICAgaWYgKHBvcyArIGJ1Zi5sZW5ndGggPiBidWZmZXIubGVuZ3RoKSB7XG4gICAgICAgIGlmICghQnVmZmVyLmlzQnVmZmVyKGJ1ZikpIGJ1ZiA9IEJ1ZmZlci5mcm9tKGJ1ZilcbiAgICAgICAgYnVmLmNvcHkoYnVmZmVyLCBwb3MpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBVaW50OEFycmF5LnByb3RvdHlwZS5zZXQuY2FsbChcbiAgICAgICAgICBidWZmZXIsXG4gICAgICAgICAgYnVmLFxuICAgICAgICAgIHBvc1xuICAgICAgICApXG4gICAgICB9XG4gICAgfSBlbHNlIGlmICghQnVmZmVyLmlzQnVmZmVyKGJ1ZikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdFwiIGFyZ3VtZW50IG11c3QgYmUgYW4gQXJyYXkgb2YgQnVmZmVycycpXG4gICAgfSBlbHNlIHtcbiAgICAgIGJ1Zi5jb3B5KGJ1ZmZlciwgcG9zKVxuICAgIH1cbiAgICBwb3MgKz0gYnVmLmxlbmd0aFxuICB9XG4gIHJldHVybiBidWZmZXJcbn1cblxuZnVuY3Rpb24gYnl0ZUxlbmd0aCAoc3RyaW5nLCBlbmNvZGluZykge1xuICBpZiAoQnVmZmVyLmlzQnVmZmVyKHN0cmluZykpIHtcbiAgICByZXR1cm4gc3RyaW5nLmxlbmd0aFxuICB9XG4gIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcoc3RyaW5nKSB8fCBpc0luc3RhbmNlKHN0cmluZywgQXJyYXlCdWZmZXIpKSB7XG4gICAgcmV0dXJuIHN0cmluZy5ieXRlTGVuZ3RoXG4gIH1cbiAgaWYgKHR5cGVvZiBzdHJpbmcgIT09ICdzdHJpbmcnKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdUaGUgXCJzdHJpbmdcIiBhcmd1bWVudCBtdXN0IGJlIG9uZSBvZiB0eXBlIHN0cmluZywgQnVmZmVyLCBvciBBcnJheUJ1ZmZlci4gJyArXG4gICAgICAnUmVjZWl2ZWQgdHlwZSAnICsgdHlwZW9mIHN0cmluZ1xuICAgIClcbiAgfVxuXG4gIGNvbnN0IGxlbiA9IHN0cmluZy5sZW5ndGhcbiAgY29uc3QgbXVzdE1hdGNoID0gKGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSA9PT0gdHJ1ZSlcbiAgaWYgKCFtdXN0TWF0Y2ggJiYgbGVuID09PSAwKSByZXR1cm4gMFxuXG4gIC8vIFVzZSBhIGZvciBsb29wIHRvIGF2b2lkIHJlY3Vyc2lvblxuICBsZXQgbG93ZXJlZENhc2UgPSBmYWxzZVxuICBmb3IgKDs7KSB7XG4gICAgc3dpdGNoIChlbmNvZGluZykge1xuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgY2FzZSAnbGF0aW4xJzpcbiAgICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICAgIHJldHVybiBsZW5cbiAgICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgY2FzZSAndXRmLTgnOlxuICAgICAgICByZXR1cm4gdXRmOFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGhcbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiBsZW4gKiAyXG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gbGVuID4+PiAxXG4gICAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgICByZXR1cm4gYmFzZTY0VG9CeXRlcyhzdHJpbmcpLmxlbmd0aFxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSB7XG4gICAgICAgICAgcmV0dXJuIG11c3RNYXRjaCA/IC0xIDogdXRmOFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGggLy8gYXNzdW1lIHV0ZjhcbiAgICAgICAgfVxuICAgICAgICBlbmNvZGluZyA9ICgnJyArIGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpXG4gICAgICAgIGxvd2VyZWRDYXNlID0gdHJ1ZVxuICAgIH1cbiAgfVxufVxuQnVmZmVyLmJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoXG5cbmZ1bmN0aW9uIHNsb3dUb1N0cmluZyAoZW5jb2RpbmcsIHN0YXJ0LCBlbmQpIHtcbiAgbGV0IGxvd2VyZWRDYXNlID0gZmFsc2VcblxuICAvLyBObyBuZWVkIHRvIHZlcmlmeSB0aGF0IFwidGhpcy5sZW5ndGggPD0gTUFYX1VJTlQzMlwiIHNpbmNlIGl0J3MgYSByZWFkLW9ubHlcbiAgLy8gcHJvcGVydHkgb2YgYSB0eXBlZCBhcnJheS5cblxuICAvLyBUaGlzIGJlaGF2ZXMgbmVpdGhlciBsaWtlIFN0cmluZyBub3IgVWludDhBcnJheSBpbiB0aGF0IHdlIHNldCBzdGFydC9lbmRcbiAgLy8gdG8gdGhlaXIgdXBwZXIvbG93ZXIgYm91bmRzIGlmIHRoZSB2YWx1ZSBwYXNzZWQgaXMgb3V0IG9mIHJhbmdlLlxuICAvLyB1bmRlZmluZWQgaXMgaGFuZGxlZCBzcGVjaWFsbHkgYXMgcGVyIEVDTUEtMjYyIDZ0aCBFZGl0aW9uLFxuICAvLyBTZWN0aW9uIDEzLjMuMy43IFJ1bnRpbWUgU2VtYW50aWNzOiBLZXllZEJpbmRpbmdJbml0aWFsaXphdGlvbi5cbiAgaWYgKHN0YXJ0ID09PSB1bmRlZmluZWQgfHwgc3RhcnQgPCAwKSB7XG4gICAgc3RhcnQgPSAwXG4gIH1cbiAgLy8gUmV0dXJuIGVhcmx5IGlmIHN0YXJ0ID4gdGhpcy5sZW5ndGguIERvbmUgaGVyZSB0byBwcmV2ZW50IHBvdGVudGlhbCB1aW50MzJcbiAgLy8gY29lcmNpb24gZmFpbCBiZWxvdy5cbiAgaWYgKHN0YXJ0ID4gdGhpcy5sZW5ndGgpIHtcbiAgICByZXR1cm4gJydcbiAgfVxuXG4gIGlmIChlbmQgPT09IHVuZGVmaW5lZCB8fCBlbmQgPiB0aGlzLmxlbmd0aCkge1xuICAgIGVuZCA9IHRoaXMubGVuZ3RoXG4gIH1cblxuICBpZiAoZW5kIDw9IDApIHtcbiAgICByZXR1cm4gJydcbiAgfVxuXG4gIC8vIEZvcmNlIGNvZXJjaW9uIHRvIHVpbnQzMi4gVGhpcyB3aWxsIGFsc28gY29lcmNlIGZhbHNleS9OYU4gdmFsdWVzIHRvIDAuXG4gIGVuZCA+Pj49IDBcbiAgc3RhcnQgPj4+PSAwXG5cbiAgaWYgKGVuZCA8PSBzdGFydCkge1xuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgaWYgKCFlbmNvZGluZykgZW5jb2RpbmcgPSAndXRmOCdcblxuICB3aGlsZSAodHJ1ZSkge1xuICAgIHN3aXRjaCAoZW5jb2RpbmcpIHtcbiAgICAgIGNhc2UgJ2hleCc6XG4gICAgICAgIHJldHVybiBoZXhTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICd1dGY4JzpcbiAgICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgICAgcmV0dXJuIHV0ZjhTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICdhc2NpaSc6XG4gICAgICAgIHJldHVybiBhc2NpaVNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ2xhdGluMSc6XG4gICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICByZXR1cm4gbGF0aW4xU2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgcmV0dXJuIGJhc2U2NFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiB1dGYxNmxlU2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gICAgICAgIGVuY29kaW5nID0gKGVuY29kaW5nICsgJycpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5cbi8vIFRoaXMgcHJvcGVydHkgaXMgdXNlZCBieSBgQnVmZmVyLmlzQnVmZmVyYCAoYW5kIHRoZSBgaXMtYnVmZmVyYCBucG0gcGFja2FnZSlcbi8vIHRvIGRldGVjdCBhIEJ1ZmZlciBpbnN0YW5jZS4gSXQncyBub3QgcG9zc2libGUgdG8gdXNlIGBpbnN0YW5jZW9mIEJ1ZmZlcmBcbi8vIHJlbGlhYmx5IGluIGEgYnJvd3NlcmlmeSBjb250ZXh0IGJlY2F1c2UgdGhlcmUgY291bGQgYmUgbXVsdGlwbGUgZGlmZmVyZW50XG4vLyBjb3BpZXMgb2YgdGhlICdidWZmZXInIHBhY2thZ2UgaW4gdXNlLiBUaGlzIG1ldGhvZCB3b3JrcyBldmVuIGZvciBCdWZmZXJcbi8vIGluc3RhbmNlcyB0aGF0IHdlcmUgY3JlYXRlZCBmcm9tIGFub3RoZXIgY29weSBvZiB0aGUgYGJ1ZmZlcmAgcGFja2FnZS5cbi8vIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXIvaXNzdWVzLzE1NFxuQnVmZmVyLnByb3RvdHlwZS5faXNCdWZmZXIgPSB0cnVlXG5cbmZ1bmN0aW9uIHN3YXAgKGIsIG4sIG0pIHtcbiAgY29uc3QgaSA9IGJbbl1cbiAgYltuXSA9IGJbbV1cbiAgYlttXSA9IGlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zd2FwMTYgPSBmdW5jdGlvbiBzd2FwMTYgKCkge1xuICBjb25zdCBsZW4gPSB0aGlzLmxlbmd0aFxuICBpZiAobGVuICUgMiAhPT0gMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdCdWZmZXIgc2l6ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgMTYtYml0cycpXG4gIH1cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkgKz0gMikge1xuICAgIHN3YXAodGhpcywgaSwgaSArIDEpXG4gIH1cbiAgcmV0dXJuIHRoaXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zd2FwMzIgPSBmdW5jdGlvbiBzd2FwMzIgKCkge1xuICBjb25zdCBsZW4gPSB0aGlzLmxlbmd0aFxuICBpZiAobGVuICUgNCAhPT0gMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdCdWZmZXIgc2l6ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgMzItYml0cycpXG4gIH1cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkgKz0gNCkge1xuICAgIHN3YXAodGhpcywgaSwgaSArIDMpXG4gICAgc3dhcCh0aGlzLCBpICsgMSwgaSArIDIpXG4gIH1cbiAgcmV0dXJuIHRoaXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zd2FwNjQgPSBmdW5jdGlvbiBzd2FwNjQgKCkge1xuICBjb25zdCBsZW4gPSB0aGlzLmxlbmd0aFxuICBpZiAobGVuICUgOCAhPT0gMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdCdWZmZXIgc2l6ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgNjQtYml0cycpXG4gIH1cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkgKz0gOCkge1xuICAgIHN3YXAodGhpcywgaSwgaSArIDcpXG4gICAgc3dhcCh0aGlzLCBpICsgMSwgaSArIDYpXG4gICAgc3dhcCh0aGlzLCBpICsgMiwgaSArIDUpXG4gICAgc3dhcCh0aGlzLCBpICsgMywgaSArIDQpXG4gIH1cbiAgcmV0dXJuIHRoaXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nICgpIHtcbiAgY29uc3QgbGVuZ3RoID0gdGhpcy5sZW5ndGhcbiAgaWYgKGxlbmd0aCA9PT0gMCkgcmV0dXJuICcnXG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSByZXR1cm4gdXRmOFNsaWNlKHRoaXMsIDAsIGxlbmd0aClcbiAgcmV0dXJuIHNsb3dUb1N0cmluZy5hcHBseSh0aGlzLCBhcmd1bWVudHMpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUudG9Mb2NhbGVTdHJpbmcgPSBCdWZmZXIucHJvdG90eXBlLnRvU3RyaW5nXG5cbkJ1ZmZlci5wcm90b3R5cGUuZXF1YWxzID0gZnVuY3Rpb24gZXF1YWxzIChiKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudCBtdXN0IGJlIGEgQnVmZmVyJylcbiAgaWYgKHRoaXMgPT09IGIpIHJldHVybiB0cnVlXG4gIHJldHVybiBCdWZmZXIuY29tcGFyZSh0aGlzLCBiKSA9PT0gMFxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluc3BlY3QgPSBmdW5jdGlvbiBpbnNwZWN0ICgpIHtcbiAgbGV0IHN0ciA9ICcnXG4gIGNvbnN0IG1heCA9IGV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVNcbiAgc3RyID0gdGhpcy50b1N0cmluZygnaGV4JywgMCwgbWF4KS5yZXBsYWNlKC8oLnsyfSkvZywgJyQxICcpLnRyaW0oKVxuICBpZiAodGhpcy5sZW5ndGggPiBtYXgpIHN0ciArPSAnIC4uLiAnXG4gIHJldHVybiAnPEJ1ZmZlciAnICsgc3RyICsgJz4nXG59XG5pZiAoY3VzdG9tSW5zcGVjdFN5bWJvbCkge1xuICBCdWZmZXIucHJvdG90eXBlW2N1c3RvbUluc3BlY3RTeW1ib2xdID0gQnVmZmVyLnByb3RvdHlwZS5pbnNwZWN0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuY29tcGFyZSA9IGZ1bmN0aW9uIGNvbXBhcmUgKHRhcmdldCwgc3RhcnQsIGVuZCwgdGhpc1N0YXJ0LCB0aGlzRW5kKSB7XG4gIGlmIChpc0luc3RhbmNlKHRhcmdldCwgVWludDhBcnJheSkpIHtcbiAgICB0YXJnZXQgPSBCdWZmZXIuZnJvbSh0YXJnZXQsIHRhcmdldC5vZmZzZXQsIHRhcmdldC5ieXRlTGVuZ3RoKVxuICB9XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKHRhcmdldCkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ1RoZSBcInRhcmdldFwiIGFyZ3VtZW50IG11c3QgYmUgb25lIG9mIHR5cGUgQnVmZmVyIG9yIFVpbnQ4QXJyYXkuICcgK1xuICAgICAgJ1JlY2VpdmVkIHR5cGUgJyArICh0eXBlb2YgdGFyZ2V0KVxuICAgIClcbiAgfVxuXG4gIGlmIChzdGFydCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgc3RhcnQgPSAwXG4gIH1cbiAgaWYgKGVuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgZW5kID0gdGFyZ2V0ID8gdGFyZ2V0Lmxlbmd0aCA6IDBcbiAgfVxuICBpZiAodGhpc1N0YXJ0ID09PSB1bmRlZmluZWQpIHtcbiAgICB0aGlzU3RhcnQgPSAwXG4gIH1cbiAgaWYgKHRoaXNFbmQgPT09IHVuZGVmaW5lZCkge1xuICAgIHRoaXNFbmQgPSB0aGlzLmxlbmd0aFxuICB9XG5cbiAgaWYgKHN0YXJ0IDwgMCB8fCBlbmQgPiB0YXJnZXQubGVuZ3RoIHx8IHRoaXNTdGFydCA8IDAgfHwgdGhpc0VuZCA+IHRoaXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ291dCBvZiByYW5nZSBpbmRleCcpXG4gIH1cblxuICBpZiAodGhpc1N0YXJ0ID49IHRoaXNFbmQgJiYgc3RhcnQgPj0gZW5kKSB7XG4gICAgcmV0dXJuIDBcbiAgfVxuICBpZiAodGhpc1N0YXJ0ID49IHRoaXNFbmQpIHtcbiAgICByZXR1cm4gLTFcbiAgfVxuICBpZiAoc3RhcnQgPj0gZW5kKSB7XG4gICAgcmV0dXJuIDFcbiAgfVxuXG4gIHN0YXJ0ID4+Pj0gMFxuICBlbmQgPj4+PSAwXG4gIHRoaXNTdGFydCA+Pj49IDBcbiAgdGhpc0VuZCA+Pj49IDBcblxuICBpZiAodGhpcyA9PT0gdGFyZ2V0KSByZXR1cm4gMFxuXG4gIGxldCB4ID0gdGhpc0VuZCAtIHRoaXNTdGFydFxuICBsZXQgeSA9IGVuZCAtIHN0YXJ0XG4gIGNvbnN0IGxlbiA9IE1hdGgubWluKHgsIHkpXG5cbiAgY29uc3QgdGhpc0NvcHkgPSB0aGlzLnNsaWNlKHRoaXNTdGFydCwgdGhpc0VuZClcbiAgY29uc3QgdGFyZ2V0Q29weSA9IHRhcmdldC5zbGljZShzdGFydCwgZW5kKVxuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyArK2kpIHtcbiAgICBpZiAodGhpc0NvcHlbaV0gIT09IHRhcmdldENvcHlbaV0pIHtcbiAgICAgIHggPSB0aGlzQ29weVtpXVxuICAgICAgeSA9IHRhcmdldENvcHlbaV1cbiAgICAgIGJyZWFrXG4gICAgfVxuICB9XG5cbiAgaWYgKHggPCB5KSByZXR1cm4gLTFcbiAgaWYgKHkgPCB4KSByZXR1cm4gMVxuICByZXR1cm4gMFxufVxuXG4vLyBGaW5kcyBlaXRoZXIgdGhlIGZpcnN0IGluZGV4IG9mIGB2YWxgIGluIGBidWZmZXJgIGF0IG9mZnNldCA+PSBgYnl0ZU9mZnNldGAsXG4vLyBPUiB0aGUgbGFzdCBpbmRleCBvZiBgdmFsYCBpbiBgYnVmZmVyYCBhdCBvZmZzZXQgPD0gYGJ5dGVPZmZzZXRgLlxuLy9cbi8vIEFyZ3VtZW50czpcbi8vIC0gYnVmZmVyIC0gYSBCdWZmZXIgdG8gc2VhcmNoXG4vLyAtIHZhbCAtIGEgc3RyaW5nLCBCdWZmZXIsIG9yIG51bWJlclxuLy8gLSBieXRlT2Zmc2V0IC0gYW4gaW5kZXggaW50byBgYnVmZmVyYDsgd2lsbCBiZSBjbGFtcGVkIHRvIGFuIGludDMyXG4vLyAtIGVuY29kaW5nIC0gYW4gb3B0aW9uYWwgZW5jb2RpbmcsIHJlbGV2YW50IGlzIHZhbCBpcyBhIHN0cmluZ1xuLy8gLSBkaXIgLSB0cnVlIGZvciBpbmRleE9mLCBmYWxzZSBmb3IgbGFzdEluZGV4T2ZcbmZ1bmN0aW9uIGJpZGlyZWN0aW9uYWxJbmRleE9mIChidWZmZXIsIHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcsIGRpcikge1xuICAvLyBFbXB0eSBidWZmZXIgbWVhbnMgbm8gbWF0Y2hcbiAgaWYgKGJ1ZmZlci5sZW5ndGggPT09IDApIHJldHVybiAtMVxuXG4gIC8vIE5vcm1hbGl6ZSBieXRlT2Zmc2V0XG4gIGlmICh0eXBlb2YgYnl0ZU9mZnNldCA9PT0gJ3N0cmluZycpIHtcbiAgICBlbmNvZGluZyA9IGJ5dGVPZmZzZXRcbiAgICBieXRlT2Zmc2V0ID0gMFxuICB9IGVsc2UgaWYgKGJ5dGVPZmZzZXQgPiAweDdmZmZmZmZmKSB7XG4gICAgYnl0ZU9mZnNldCA9IDB4N2ZmZmZmZmZcbiAgfSBlbHNlIGlmIChieXRlT2Zmc2V0IDwgLTB4ODAwMDAwMDApIHtcbiAgICBieXRlT2Zmc2V0ID0gLTB4ODAwMDAwMDBcbiAgfVxuICBieXRlT2Zmc2V0ID0gK2J5dGVPZmZzZXQgLy8gQ29lcmNlIHRvIE51bWJlci5cbiAgaWYgKG51bWJlcklzTmFOKGJ5dGVPZmZzZXQpKSB7XG4gICAgLy8gYnl0ZU9mZnNldDogaXQgaXQncyB1bmRlZmluZWQsIG51bGwsIE5hTiwgXCJmb29cIiwgZXRjLCBzZWFyY2ggd2hvbGUgYnVmZmVyXG4gICAgYnl0ZU9mZnNldCA9IGRpciA/IDAgOiAoYnVmZmVyLmxlbmd0aCAtIDEpXG4gIH1cblxuICAvLyBOb3JtYWxpemUgYnl0ZU9mZnNldDogbmVnYXRpdmUgb2Zmc2V0cyBzdGFydCBmcm9tIHRoZSBlbmQgb2YgdGhlIGJ1ZmZlclxuICBpZiAoYnl0ZU9mZnNldCA8IDApIGJ5dGVPZmZzZXQgPSBidWZmZXIubGVuZ3RoICsgYnl0ZU9mZnNldFxuICBpZiAoYnl0ZU9mZnNldCA+PSBidWZmZXIubGVuZ3RoKSB7XG4gICAgaWYgKGRpcikgcmV0dXJuIC0xXG4gICAgZWxzZSBieXRlT2Zmc2V0ID0gYnVmZmVyLmxlbmd0aCAtIDFcbiAgfSBlbHNlIGlmIChieXRlT2Zmc2V0IDwgMCkge1xuICAgIGlmIChkaXIpIGJ5dGVPZmZzZXQgPSAwXG4gICAgZWxzZSByZXR1cm4gLTFcbiAgfVxuXG4gIC8vIE5vcm1hbGl6ZSB2YWxcbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnKSB7XG4gICAgdmFsID0gQnVmZmVyLmZyb20odmFsLCBlbmNvZGluZylcbiAgfVxuXG4gIC8vIEZpbmFsbHksIHNlYXJjaCBlaXRoZXIgaW5kZXhPZiAoaWYgZGlyIGlzIHRydWUpIG9yIGxhc3RJbmRleE9mXG4gIGlmIChCdWZmZXIuaXNCdWZmZXIodmFsKSkge1xuICAgIC8vIFNwZWNpYWwgY2FzZTogbG9va2luZyBmb3IgZW1wdHkgc3RyaW5nL2J1ZmZlciBhbHdheXMgZmFpbHNcbiAgICBpZiAodmFsLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIC0xXG4gICAgfVxuICAgIHJldHVybiBhcnJheUluZGV4T2YoYnVmZmVyLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBkaXIpXG4gIH0gZWxzZSBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHtcbiAgICB2YWwgPSB2YWwgJiAweEZGIC8vIFNlYXJjaCBmb3IgYSBieXRlIHZhbHVlIFswLTI1NV1cbiAgICBpZiAodHlwZW9mIFVpbnQ4QXJyYXkucHJvdG90eXBlLmluZGV4T2YgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGlmIChkaXIpIHtcbiAgICAgICAgcmV0dXJuIFVpbnQ4QXJyYXkucHJvdG90eXBlLmluZGV4T2YuY2FsbChidWZmZXIsIHZhbCwgYnl0ZU9mZnNldClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBVaW50OEFycmF5LnByb3RvdHlwZS5sYXN0SW5kZXhPZi5jYWxsKGJ1ZmZlciwgdmFsLCBieXRlT2Zmc2V0KVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYXJyYXlJbmRleE9mKGJ1ZmZlciwgW3ZhbF0sIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBkaXIpXG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2YWwgbXVzdCBiZSBzdHJpbmcsIG51bWJlciBvciBCdWZmZXInKVxufVxuXG5mdW5jdGlvbiBhcnJheUluZGV4T2YgKGFyciwgdmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZywgZGlyKSB7XG4gIGxldCBpbmRleFNpemUgPSAxXG4gIGxldCBhcnJMZW5ndGggPSBhcnIubGVuZ3RoXG4gIGxldCB2YWxMZW5ndGggPSB2YWwubGVuZ3RoXG5cbiAgaWYgKGVuY29kaW5nICE9PSB1bmRlZmluZWQpIHtcbiAgICBlbmNvZGluZyA9IFN0cmluZyhlbmNvZGluZykudG9Mb3dlckNhc2UoKVxuICAgIGlmIChlbmNvZGluZyA9PT0gJ3VjczInIHx8IGVuY29kaW5nID09PSAndWNzLTInIHx8XG4gICAgICAgIGVuY29kaW5nID09PSAndXRmMTZsZScgfHwgZW5jb2RpbmcgPT09ICd1dGYtMTZsZScpIHtcbiAgICAgIGlmIChhcnIubGVuZ3RoIDwgMiB8fCB2YWwubGVuZ3RoIDwgMikge1xuICAgICAgICByZXR1cm4gLTFcbiAgICAgIH1cbiAgICAgIGluZGV4U2l6ZSA9IDJcbiAgICAgIGFyckxlbmd0aCAvPSAyXG4gICAgICB2YWxMZW5ndGggLz0gMlxuICAgICAgYnl0ZU9mZnNldCAvPSAyXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcmVhZCAoYnVmLCBpKSB7XG4gICAgaWYgKGluZGV4U2l6ZSA9PT0gMSkge1xuICAgICAgcmV0dXJuIGJ1ZltpXVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gYnVmLnJlYWRVSW50MTZCRShpICogaW5kZXhTaXplKVxuICAgIH1cbiAgfVxuXG4gIGxldCBpXG4gIGlmIChkaXIpIHtcbiAgICBsZXQgZm91bmRJbmRleCA9IC0xXG4gICAgZm9yIChpID0gYnl0ZU9mZnNldDsgaSA8IGFyckxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocmVhZChhcnIsIGkpID09PSByZWFkKHZhbCwgZm91bmRJbmRleCA9PT0gLTEgPyAwIDogaSAtIGZvdW5kSW5kZXgpKSB7XG4gICAgICAgIGlmIChmb3VuZEluZGV4ID09PSAtMSkgZm91bmRJbmRleCA9IGlcbiAgICAgICAgaWYgKGkgLSBmb3VuZEluZGV4ICsgMSA9PT0gdmFsTGVuZ3RoKSByZXR1cm4gZm91bmRJbmRleCAqIGluZGV4U2l6ZVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGZvdW5kSW5kZXggIT09IC0xKSBpIC09IGkgLSBmb3VuZEluZGV4XG4gICAgICAgIGZvdW5kSW5kZXggPSAtMVxuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZiAoYnl0ZU9mZnNldCArIHZhbExlbmd0aCA+IGFyckxlbmd0aCkgYnl0ZU9mZnNldCA9IGFyckxlbmd0aCAtIHZhbExlbmd0aFxuICAgIGZvciAoaSA9IGJ5dGVPZmZzZXQ7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBsZXQgZm91bmQgPSB0cnVlXG4gICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHZhbExlbmd0aDsgaisrKSB7XG4gICAgICAgIGlmIChyZWFkKGFyciwgaSArIGopICE9PSByZWFkKHZhbCwgaikpIHtcbiAgICAgICAgICBmb3VuZCA9IGZhbHNlXG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGZvdW5kKSByZXR1cm4gaVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiAtMVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluY2x1ZGVzID0gZnVuY3Rpb24gaW5jbHVkZXMgKHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcpIHtcbiAgcmV0dXJuIHRoaXMuaW5kZXhPZih2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nKSAhPT0gLTFcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5pbmRleE9mID0gZnVuY3Rpb24gaW5kZXhPZiAodmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZykge1xuICByZXR1cm4gYmlkaXJlY3Rpb25hbEluZGV4T2YodGhpcywgdmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZywgdHJ1ZSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5sYXN0SW5kZXhPZiA9IGZ1bmN0aW9uIGxhc3RJbmRleE9mICh2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nKSB7XG4gIHJldHVybiBiaWRpcmVjdGlvbmFsSW5kZXhPZih0aGlzLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBmYWxzZSlcbn1cblxuZnVuY3Rpb24gaGV4V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICBvZmZzZXQgPSBOdW1iZXIob2Zmc2V0KSB8fCAwXG4gIGNvbnN0IHJlbWFpbmluZyA9IGJ1Zi5sZW5ndGggLSBvZmZzZXRcbiAgaWYgKCFsZW5ndGgpIHtcbiAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgfSBlbHNlIHtcbiAgICBsZW5ndGggPSBOdW1iZXIobGVuZ3RoKVxuICAgIGlmIChsZW5ndGggPiByZW1haW5pbmcpIHtcbiAgICAgIGxlbmd0aCA9IHJlbWFpbmluZ1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHN0ckxlbiA9IHN0cmluZy5sZW5ndGhcblxuICBpZiAobGVuZ3RoID4gc3RyTGVuIC8gMikge1xuICAgIGxlbmd0aCA9IHN0ckxlbiAvIDJcbiAgfVxuICBsZXQgaVxuICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHtcbiAgICBjb25zdCBwYXJzZWQgPSBwYXJzZUludChzdHJpbmcuc3Vic3RyKGkgKiAyLCAyKSwgMTYpXG4gICAgaWYgKG51bWJlcklzTmFOKHBhcnNlZCkpIHJldHVybiBpXG4gICAgYnVmW29mZnNldCArIGldID0gcGFyc2VkXG4gIH1cbiAgcmV0dXJuIGlcbn1cblxuZnVuY3Rpb24gdXRmOFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIodXRmOFRvQnl0ZXMoc3RyaW5nLCBidWYubGVuZ3RoIC0gb2Zmc2V0KSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gYXNjaWlXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKGFzY2lpVG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiBiYXNlNjRXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKGJhc2U2NFRvQnl0ZXMoc3RyaW5nKSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gdWNzMldyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIodXRmMTZsZVRvQnl0ZXMoc3RyaW5nLCBidWYubGVuZ3RoIC0gb2Zmc2V0KSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZSA9IGZ1bmN0aW9uIHdyaXRlIChzdHJpbmcsIG9mZnNldCwgbGVuZ3RoLCBlbmNvZGluZykge1xuICAvLyBCdWZmZXIjd3JpdGUoc3RyaW5nKVxuICBpZiAob2Zmc2V0ID09PSB1bmRlZmluZWQpIHtcbiAgICBlbmNvZGluZyA9ICd1dGY4J1xuICAgIGxlbmd0aCA9IHRoaXMubGVuZ3RoXG4gICAgb2Zmc2V0ID0gMFxuICAvLyBCdWZmZXIjd3JpdGUoc3RyaW5nLCBlbmNvZGluZylcbiAgfSBlbHNlIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCAmJiB0eXBlb2Ygb2Zmc2V0ID09PSAnc3RyaW5nJykge1xuICAgIGVuY29kaW5nID0gb2Zmc2V0XG4gICAgbGVuZ3RoID0gdGhpcy5sZW5ndGhcbiAgICBvZmZzZXQgPSAwXG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcsIG9mZnNldFssIGxlbmd0aF1bLCBlbmNvZGluZ10pXG4gIH0gZWxzZSBpZiAoaXNGaW5pdGUob2Zmc2V0KSkge1xuICAgIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICAgIGlmIChpc0Zpbml0ZShsZW5ndGgpKSB7XG4gICAgICBsZW5ndGggPSBsZW5ndGggPj4+IDBcbiAgICAgIGlmIChlbmNvZGluZyA9PT0gdW5kZWZpbmVkKSBlbmNvZGluZyA9ICd1dGY4J1xuICAgIH0gZWxzZSB7XG4gICAgICBlbmNvZGluZyA9IGxlbmd0aFxuICAgICAgbGVuZ3RoID0gdW5kZWZpbmVkXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICdCdWZmZXIud3JpdGUoc3RyaW5nLCBlbmNvZGluZywgb2Zmc2V0WywgbGVuZ3RoXSkgaXMgbm8gbG9uZ2VyIHN1cHBvcnRlZCdcbiAgICApXG4gIH1cblxuICBjb25zdCByZW1haW5pbmcgPSB0aGlzLmxlbmd0aCAtIG9mZnNldFxuICBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQgfHwgbGVuZ3RoID4gcmVtYWluaW5nKSBsZW5ndGggPSByZW1haW5pbmdcblxuICBpZiAoKHN0cmluZy5sZW5ndGggPiAwICYmIChsZW5ndGggPCAwIHx8IG9mZnNldCA8IDApKSB8fCBvZmZzZXQgPiB0aGlzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdBdHRlbXB0IHRvIHdyaXRlIG91dHNpZGUgYnVmZmVyIGJvdW5kcycpXG4gIH1cblxuICBpZiAoIWVuY29kaW5nKSBlbmNvZGluZyA9ICd1dGY4J1xuXG4gIGxldCBsb3dlcmVkQ2FzZSA9IGZhbHNlXG4gIGZvciAoOzspIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gaGV4V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICAgIHJldHVybiB1dGY4V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgY2FzZSAnbGF0aW4xJzpcbiAgICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICAgIHJldHVybiBhc2NpaVdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICAgIC8vIFdhcm5pbmc6IG1heExlbmd0aCBub3QgdGFrZW4gaW50byBhY2NvdW50IGluIGJhc2U2NFdyaXRlXG4gICAgICAgIHJldHVybiBiYXNlNjRXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gdWNzMldyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChsb3dlcmVkQ2FzZSkgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBlbmNvZGluZzogJyArIGVuY29kaW5nKVxuICAgICAgICBlbmNvZGluZyA9ICgnJyArIGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpXG4gICAgICAgIGxvd2VyZWRDYXNlID0gdHJ1ZVxuICAgIH1cbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTiAoKSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogJ0J1ZmZlcicsXG4gICAgZGF0YTogQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwodGhpcy5fYXJyIHx8IHRoaXMsIDApXG4gIH1cbn1cblxuZnVuY3Rpb24gYmFzZTY0U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICBpZiAoc3RhcnQgPT09IDAgJiYgZW5kID09PSBidWYubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGJhc2U2NC5mcm9tQnl0ZUFycmF5KGJ1ZilcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmLnNsaWNlKHN0YXJ0LCBlbmQpKVxuICB9XG59XG5cbmZ1bmN0aW9uIHV0ZjhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcbiAgY29uc3QgcmVzID0gW11cblxuICBsZXQgaSA9IHN0YXJ0XG4gIHdoaWxlIChpIDwgZW5kKSB7XG4gICAgY29uc3QgZmlyc3RCeXRlID0gYnVmW2ldXG4gICAgbGV0IGNvZGVQb2ludCA9IG51bGxcbiAgICBsZXQgYnl0ZXNQZXJTZXF1ZW5jZSA9IChmaXJzdEJ5dGUgPiAweEVGKVxuICAgICAgPyA0XG4gICAgICA6IChmaXJzdEJ5dGUgPiAweERGKVxuICAgICAgICAgID8gM1xuICAgICAgICAgIDogKGZpcnN0Qnl0ZSA+IDB4QkYpXG4gICAgICAgICAgICAgID8gMlxuICAgICAgICAgICAgICA6IDFcblxuICAgIGlmIChpICsgYnl0ZXNQZXJTZXF1ZW5jZSA8PSBlbmQpIHtcbiAgICAgIGxldCBzZWNvbmRCeXRlLCB0aGlyZEJ5dGUsIGZvdXJ0aEJ5dGUsIHRlbXBDb2RlUG9pbnRcblxuICAgICAgc3dpdGNoIChieXRlc1BlclNlcXVlbmNlKSB7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICBpZiAoZmlyc3RCeXRlIDwgMHg4MCkge1xuICAgICAgICAgICAgY29kZVBvaW50ID0gZmlyc3RCeXRlXG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICBzZWNvbmRCeXRlID0gYnVmW2kgKyAxXVxuICAgICAgICAgIGlmICgoc2Vjb25kQnl0ZSAmIDB4QzApID09PSAweDgwKSB7XG4gICAgICAgICAgICB0ZW1wQ29kZVBvaW50ID0gKGZpcnN0Qnl0ZSAmIDB4MUYpIDw8IDB4NiB8IChzZWNvbmRCeXRlICYgMHgzRilcbiAgICAgICAgICAgIGlmICh0ZW1wQ29kZVBvaW50ID4gMHg3Rikge1xuICAgICAgICAgICAgICBjb2RlUG9pbnQgPSB0ZW1wQ29kZVBvaW50XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICBzZWNvbmRCeXRlID0gYnVmW2kgKyAxXVxuICAgICAgICAgIHRoaXJkQnl0ZSA9IGJ1ZltpICsgMl1cbiAgICAgICAgICBpZiAoKHNlY29uZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCAmJiAodGhpcmRCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgIHRlbXBDb2RlUG9pbnQgPSAoZmlyc3RCeXRlICYgMHhGKSA8PCAweEMgfCAoc2Vjb25kQnl0ZSAmIDB4M0YpIDw8IDB4NiB8ICh0aGlyZEJ5dGUgJiAweDNGKVxuICAgICAgICAgICAgaWYgKHRlbXBDb2RlUG9pbnQgPiAweDdGRiAmJiAodGVtcENvZGVQb2ludCA8IDB4RDgwMCB8fCB0ZW1wQ29kZVBvaW50ID4gMHhERkZGKSkge1xuICAgICAgICAgICAgICBjb2RlUG9pbnQgPSB0ZW1wQ29kZVBvaW50XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgICBzZWNvbmRCeXRlID0gYnVmW2kgKyAxXVxuICAgICAgICAgIHRoaXJkQnl0ZSA9IGJ1ZltpICsgMl1cbiAgICAgICAgICBmb3VydGhCeXRlID0gYnVmW2kgKyAzXVxuICAgICAgICAgIGlmICgoc2Vjb25kQnl0ZSAmIDB4QzApID09PSAweDgwICYmICh0aGlyZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCAmJiAoZm91cnRoQnl0ZSAmIDB4QzApID09PSAweDgwKSB7XG4gICAgICAgICAgICB0ZW1wQ29kZVBvaW50ID0gKGZpcnN0Qnl0ZSAmIDB4RikgPDwgMHgxMiB8IChzZWNvbmRCeXRlICYgMHgzRikgPDwgMHhDIHwgKHRoaXJkQnl0ZSAmIDB4M0YpIDw8IDB4NiB8IChmb3VydGhCeXRlICYgMHgzRilcbiAgICAgICAgICAgIGlmICh0ZW1wQ29kZVBvaW50ID4gMHhGRkZGICYmIHRlbXBDb2RlUG9pbnQgPCAweDExMDAwMCkge1xuICAgICAgICAgICAgICBjb2RlUG9pbnQgPSB0ZW1wQ29kZVBvaW50XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjb2RlUG9pbnQgPT09IG51bGwpIHtcbiAgICAgIC8vIHdlIGRpZCBub3QgZ2VuZXJhdGUgYSB2YWxpZCBjb2RlUG9pbnQgc28gaW5zZXJ0IGFcbiAgICAgIC8vIHJlcGxhY2VtZW50IGNoYXIgKFUrRkZGRCkgYW5kIGFkdmFuY2Ugb25seSAxIGJ5dGVcbiAgICAgIGNvZGVQb2ludCA9IDB4RkZGRFxuICAgICAgYnl0ZXNQZXJTZXF1ZW5jZSA9IDFcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA+IDB4RkZGRikge1xuICAgICAgLy8gZW5jb2RlIHRvIHV0ZjE2IChzdXJyb2dhdGUgcGFpciBkYW5jZSlcbiAgICAgIGNvZGVQb2ludCAtPSAweDEwMDAwXG4gICAgICByZXMucHVzaChjb2RlUG9pbnQgPj4+IDEwICYgMHgzRkYgfCAweEQ4MDApXG4gICAgICBjb2RlUG9pbnQgPSAweERDMDAgfCBjb2RlUG9pbnQgJiAweDNGRlxuICAgIH1cblxuICAgIHJlcy5wdXNoKGNvZGVQb2ludClcbiAgICBpICs9IGJ5dGVzUGVyU2VxdWVuY2VcbiAgfVxuXG4gIHJldHVybiBkZWNvZGVDb2RlUG9pbnRzQXJyYXkocmVzKVxufVxuXG4vLyBCYXNlZCBvbiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8yMjc0NzI3Mi82ODA3NDIsIHRoZSBicm93c2VyIHdpdGhcbi8vIHRoZSBsb3dlc3QgbGltaXQgaXMgQ2hyb21lLCB3aXRoIDB4MTAwMDAgYXJncy5cbi8vIFdlIGdvIDEgbWFnbml0dWRlIGxlc3MsIGZvciBzYWZldHlcbmNvbnN0IE1BWF9BUkdVTUVOVFNfTEVOR1RIID0gMHgxMDAwXG5cbmZ1bmN0aW9uIGRlY29kZUNvZGVQb2ludHNBcnJheSAoY29kZVBvaW50cykge1xuICBjb25zdCBsZW4gPSBjb2RlUG9pbnRzLmxlbmd0aFxuICBpZiAobGVuIDw9IE1BWF9BUkdVTUVOVFNfTEVOR1RIKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLCBjb2RlUG9pbnRzKSAvLyBhdm9pZCBleHRyYSBzbGljZSgpXG4gIH1cblxuICAvLyBEZWNvZGUgaW4gY2h1bmtzIHRvIGF2b2lkIFwiY2FsbCBzdGFjayBzaXplIGV4Y2VlZGVkXCIuXG4gIGxldCByZXMgPSAnJ1xuICBsZXQgaSA9IDBcbiAgd2hpbGUgKGkgPCBsZW4pIHtcbiAgICByZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShcbiAgICAgIFN0cmluZyxcbiAgICAgIGNvZGVQb2ludHMuc2xpY2UoaSwgaSArPSBNQVhfQVJHVU1FTlRTX0xFTkdUSClcbiAgICApXG4gIH1cbiAgcmV0dXJuIHJlc1xufVxuXG5mdW5jdGlvbiBhc2NpaVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgbGV0IHJldCA9ICcnXG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcblxuICBmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSkge1xuICAgIHJldCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ1ZltpXSAmIDB4N0YpXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBsYXRpbjFTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGxldCByZXQgPSAnJ1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG5cbiAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDwgZW5kOyArK2kpIHtcbiAgICByZXQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0pXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBoZXhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGNvbnN0IGxlbiA9IGJ1Zi5sZW5ndGhcblxuICBpZiAoIXN0YXJ0IHx8IHN0YXJ0IDwgMCkgc3RhcnQgPSAwXG4gIGlmICghZW5kIHx8IGVuZCA8IDAgfHwgZW5kID4gbGVuKSBlbmQgPSBsZW5cblxuICBsZXQgb3V0ID0gJydcbiAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDwgZW5kOyArK2kpIHtcbiAgICBvdXQgKz0gaGV4U2xpY2VMb29rdXBUYWJsZVtidWZbaV1dXG4gIH1cbiAgcmV0dXJuIG91dFxufVxuXG5mdW5jdGlvbiB1dGYxNmxlU2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICBjb25zdCBieXRlcyA9IGJ1Zi5zbGljZShzdGFydCwgZW5kKVxuICBsZXQgcmVzID0gJydcbiAgLy8gSWYgYnl0ZXMubGVuZ3RoIGlzIG9kZCwgdGhlIGxhc3QgOCBiaXRzIG11c3QgYmUgaWdub3JlZCAoc2FtZSBhcyBub2RlLmpzKVxuICBmb3IgKGxldCBpID0gMDsgaSA8IGJ5dGVzLmxlbmd0aCAtIDE7IGkgKz0gMikge1xuICAgIHJlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ5dGVzW2ldICsgKGJ5dGVzW2kgKyAxXSAqIDI1NikpXG4gIH1cbiAgcmV0dXJuIHJlc1xufVxuXG5CdWZmZXIucHJvdG90eXBlLnNsaWNlID0gZnVuY3Rpb24gc2xpY2UgKHN0YXJ0LCBlbmQpIHtcbiAgY29uc3QgbGVuID0gdGhpcy5sZW5ndGhcbiAgc3RhcnQgPSB+fnN0YXJ0XG4gIGVuZCA9IGVuZCA9PT0gdW5kZWZpbmVkID8gbGVuIDogfn5lbmRcblxuICBpZiAoc3RhcnQgPCAwKSB7XG4gICAgc3RhcnQgKz0gbGVuXG4gICAgaWYgKHN0YXJ0IDwgMCkgc3RhcnQgPSAwXG4gIH0gZWxzZSBpZiAoc3RhcnQgPiBsZW4pIHtcbiAgICBzdGFydCA9IGxlblxuICB9XG5cbiAgaWYgKGVuZCA8IDApIHtcbiAgICBlbmQgKz0gbGVuXG4gICAgaWYgKGVuZCA8IDApIGVuZCA9IDBcbiAgfSBlbHNlIGlmIChlbmQgPiBsZW4pIHtcbiAgICBlbmQgPSBsZW5cbiAgfVxuXG4gIGlmIChlbmQgPCBzdGFydCkgZW5kID0gc3RhcnRcblxuICBjb25zdCBuZXdCdWYgPSB0aGlzLnN1YmFycmF5KHN0YXJ0LCBlbmQpXG4gIC8vIFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlXG4gIE9iamVjdC5zZXRQcm90b3R5cGVPZihuZXdCdWYsIEJ1ZmZlci5wcm90b3R5cGUpXG5cbiAgcmV0dXJuIG5ld0J1ZlxufVxuXG4vKlxuICogTmVlZCB0byBtYWtlIHN1cmUgdGhhdCBidWZmZXIgaXNuJ3QgdHJ5aW5nIHRvIHdyaXRlIG91dCBvZiBib3VuZHMuXG4gKi9cbmZ1bmN0aW9uIGNoZWNrT2Zmc2V0IChvZmZzZXQsIGV4dCwgbGVuZ3RoKSB7XG4gIGlmICgob2Zmc2V0ICUgMSkgIT09IDAgfHwgb2Zmc2V0IDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ29mZnNldCBpcyBub3QgdWludCcpXG4gIGlmIChvZmZzZXQgKyBleHQgPiBsZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdUcnlpbmcgdG8gYWNjZXNzIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVWludExFID1cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnRMRSA9IGZ1bmN0aW9uIHJlYWRVSW50TEUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgbGV0IHZhbCA9IHRoaXNbb2Zmc2V0XVxuICBsZXQgbXVsID0gMVxuICBsZXQgaSA9IDBcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyBpXSAqIG11bFxuICB9XG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVaW50QkUgPVxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludEJFID0gZnVuY3Rpb24gcmVhZFVJbnRCRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG4gIH1cblxuICBsZXQgdmFsID0gdGhpc1tvZmZzZXQgKyAtLWJ5dGVMZW5ndGhdXG4gIGxldCBtdWwgPSAxXG4gIHdoaWxlIChieXRlTGVuZ3RoID4gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIC0tYnl0ZUxlbmd0aF0gKiBtdWxcbiAgfVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVWludDggPVxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDggPSBmdW5jdGlvbiByZWFkVUludDggKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMSwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiB0aGlzW29mZnNldF1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVWludDE2TEUgPVxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDE2TEUgPSBmdW5jdGlvbiByZWFkVUludDE2TEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiB0aGlzW29mZnNldF0gfCAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVaW50MTZCRSA9XG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MTZCRSA9IGZ1bmN0aW9uIHJlYWRVSW50MTZCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuICh0aGlzW29mZnNldF0gPDwgOCkgfCB0aGlzW29mZnNldCArIDFdXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVpbnQzMkxFID1cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQzMkxFID0gZnVuY3Rpb24gcmVhZFVJbnQzMkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuXG4gIHJldHVybiAoKHRoaXNbb2Zmc2V0XSkgfFxuICAgICAgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOCkgfFxuICAgICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgMTYpKSArXG4gICAgICAodGhpc1tvZmZzZXQgKyAzXSAqIDB4MTAwMDAwMClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVWludDMyQkUgPVxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDMyQkUgPSBmdW5jdGlvbiByZWFkVUludDMyQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICh0aGlzW29mZnNldF0gKiAweDEwMDAwMDApICtcbiAgICAoKHRoaXNbb2Zmc2V0ICsgMV0gPDwgMTYpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCA4KSB8XG4gICAgdGhpc1tvZmZzZXQgKyAzXSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkQmlnVUludDY0TEUgPSBkZWZpbmVCaWdJbnRNZXRob2QoZnVuY3Rpb24gcmVhZEJpZ1VJbnQ2NExFIChvZmZzZXQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIHZhbGlkYXRlTnVtYmVyKG9mZnNldCwgJ29mZnNldCcpXG4gIGNvbnN0IGZpcnN0ID0gdGhpc1tvZmZzZXRdXG4gIGNvbnN0IGxhc3QgPSB0aGlzW29mZnNldCArIDddXG4gIGlmIChmaXJzdCA9PT0gdW5kZWZpbmVkIHx8IGxhc3QgPT09IHVuZGVmaW5lZCkge1xuICAgIGJvdW5kc0Vycm9yKG9mZnNldCwgdGhpcy5sZW5ndGggLSA4KVxuICB9XG5cbiAgY29uc3QgbG8gPSBmaXJzdCArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDggK1xuICAgIHRoaXNbKytvZmZzZXRdICogMiAqKiAxNiArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDI0XG5cbiAgY29uc3QgaGkgPSB0aGlzWysrb2Zmc2V0XSArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDggK1xuICAgIHRoaXNbKytvZmZzZXRdICogMiAqKiAxNiArXG4gICAgbGFzdCAqIDIgKiogMjRcblxuICByZXR1cm4gQmlnSW50KGxvKSArIChCaWdJbnQoaGkpIDw8IEJpZ0ludCgzMikpXG59KVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRCaWdVSW50NjRCRSA9IGRlZmluZUJpZ0ludE1ldGhvZChmdW5jdGlvbiByZWFkQmlnVUludDY0QkUgKG9mZnNldCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgdmFsaWRhdGVOdW1iZXIob2Zmc2V0LCAnb2Zmc2V0JylcbiAgY29uc3QgZmlyc3QgPSB0aGlzW29mZnNldF1cbiAgY29uc3QgbGFzdCA9IHRoaXNbb2Zmc2V0ICsgN11cbiAgaWYgKGZpcnN0ID09PSB1bmRlZmluZWQgfHwgbGFzdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgYm91bmRzRXJyb3Iob2Zmc2V0LCB0aGlzLmxlbmd0aCAtIDgpXG4gIH1cblxuICBjb25zdCBoaSA9IGZpcnN0ICogMiAqKiAyNCArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDE2ICtcbiAgICB0aGlzWysrb2Zmc2V0XSAqIDIgKiogOCArXG4gICAgdGhpc1srK29mZnNldF1cblxuICBjb25zdCBsbyA9IHRoaXNbKytvZmZzZXRdICogMiAqKiAyNCArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDE2ICtcbiAgICB0aGlzWysrb2Zmc2V0XSAqIDIgKiogOCArXG4gICAgbGFzdFxuXG4gIHJldHVybiAoQmlnSW50KGhpKSA8PCBCaWdJbnQoMzIpKSArIEJpZ0ludChsbylcbn0pXG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludExFID0gZnVuY3Rpb24gcmVhZEludExFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuXG4gIGxldCB2YWwgPSB0aGlzW29mZnNldF1cbiAgbGV0IG11bCA9IDFcbiAgbGV0IGkgPSAwXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgaV0gKiBtdWxcbiAgfVxuICBtdWwgKj0gMHg4MFxuXG4gIGlmICh2YWwgPj0gbXVsKSB2YWwgLT0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpXG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnRCRSA9IGZ1bmN0aW9uIHJlYWRJbnRCRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICBsZXQgaSA9IGJ5dGVMZW5ndGhcbiAgbGV0IG11bCA9IDFcbiAgbGV0IHZhbCA9IHRoaXNbb2Zmc2V0ICsgLS1pXVxuICB3aGlsZSAoaSA+IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyAtLWldICogbXVsXG4gIH1cbiAgbXVsICo9IDB4ODBcblxuICBpZiAodmFsID49IG11bCkgdmFsIC09IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50OCA9IGZ1bmN0aW9uIHJlYWRJbnQ4IChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDEsIHRoaXMubGVuZ3RoKVxuICBpZiAoISh0aGlzW29mZnNldF0gJiAweDgwKSkgcmV0dXJuICh0aGlzW29mZnNldF0pXG4gIHJldHVybiAoKDB4ZmYgLSB0aGlzW29mZnNldF0gKyAxKSAqIC0xKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQxNkxFID0gZnVuY3Rpb24gcmVhZEludDE2TEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIGNvbnN0IHZhbCA9IHRoaXNbb2Zmc2V0XSB8ICh0aGlzW29mZnNldCArIDFdIDw8IDgpXG4gIHJldHVybiAodmFsICYgMHg4MDAwKSA/IHZhbCB8IDB4RkZGRjAwMDAgOiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MTZCRSA9IGZ1bmN0aW9uIHJlYWRJbnQxNkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICBjb25zdCB2YWwgPSB0aGlzW29mZnNldCArIDFdIHwgKHRoaXNbb2Zmc2V0XSA8PCA4KVxuICByZXR1cm4gKHZhbCAmIDB4ODAwMCkgPyB2YWwgfCAweEZGRkYwMDAwIDogdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDMyTEUgPSBmdW5jdGlvbiByZWFkSW50MzJMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSkgfFxuICAgICh0aGlzW29mZnNldCArIDFdIDw8IDgpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDNdIDw8IDI0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQzMkJFID0gZnVuY3Rpb24gcmVhZEludDMyQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICh0aGlzW29mZnNldF0gPDwgMjQpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDgpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAzXSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkQmlnSW50NjRMRSA9IGRlZmluZUJpZ0ludE1ldGhvZChmdW5jdGlvbiByZWFkQmlnSW50NjRMRSAob2Zmc2V0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICB2YWxpZGF0ZU51bWJlcihvZmZzZXQsICdvZmZzZXQnKVxuICBjb25zdCBmaXJzdCA9IHRoaXNbb2Zmc2V0XVxuICBjb25zdCBsYXN0ID0gdGhpc1tvZmZzZXQgKyA3XVxuICBpZiAoZmlyc3QgPT09IHVuZGVmaW5lZCB8fCBsYXN0ID09PSB1bmRlZmluZWQpIHtcbiAgICBib3VuZHNFcnJvcihvZmZzZXQsIHRoaXMubGVuZ3RoIC0gOClcbiAgfVxuXG4gIGNvbnN0IHZhbCA9IHRoaXNbb2Zmc2V0ICsgNF0gK1xuICAgIHRoaXNbb2Zmc2V0ICsgNV0gKiAyICoqIDggK1xuICAgIHRoaXNbb2Zmc2V0ICsgNl0gKiAyICoqIDE2ICtcbiAgICAobGFzdCA8PCAyNCkgLy8gT3ZlcmZsb3dcblxuICByZXR1cm4gKEJpZ0ludCh2YWwpIDw8IEJpZ0ludCgzMikpICtcbiAgICBCaWdJbnQoZmlyc3QgK1xuICAgIHRoaXNbKytvZmZzZXRdICogMiAqKiA4ICtcbiAgICB0aGlzWysrb2Zmc2V0XSAqIDIgKiogMTYgK1xuICAgIHRoaXNbKytvZmZzZXRdICogMiAqKiAyNClcbn0pXG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEJpZ0ludDY0QkUgPSBkZWZpbmVCaWdJbnRNZXRob2QoZnVuY3Rpb24gcmVhZEJpZ0ludDY0QkUgKG9mZnNldCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgdmFsaWRhdGVOdW1iZXIob2Zmc2V0LCAnb2Zmc2V0JylcbiAgY29uc3QgZmlyc3QgPSB0aGlzW29mZnNldF1cbiAgY29uc3QgbGFzdCA9IHRoaXNbb2Zmc2V0ICsgN11cbiAgaWYgKGZpcnN0ID09PSB1bmRlZmluZWQgfHwgbGFzdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgYm91bmRzRXJyb3Iob2Zmc2V0LCB0aGlzLmxlbmd0aCAtIDgpXG4gIH1cblxuICBjb25zdCB2YWwgPSAoZmlyc3QgPDwgMjQpICsgLy8gT3ZlcmZsb3dcbiAgICB0aGlzWysrb2Zmc2V0XSAqIDIgKiogMTYgK1xuICAgIHRoaXNbKytvZmZzZXRdICogMiAqKiA4ICtcbiAgICB0aGlzWysrb2Zmc2V0XVxuXG4gIHJldHVybiAoQmlnSW50KHZhbCkgPDwgQmlnSW50KDMyKSkgK1xuICAgIEJpZ0ludCh0aGlzWysrb2Zmc2V0XSAqIDIgKiogMjQgK1xuICAgIHRoaXNbKytvZmZzZXRdICogMiAqKiAxNiArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDggK1xuICAgIGxhc3QpXG59KVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRGbG9hdExFID0gZnVuY3Rpb24gcmVhZEZsb2F0TEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCB0cnVlLCAyMywgNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRmxvYXRCRSA9IGZ1bmN0aW9uIHJlYWRGbG9hdEJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgZmFsc2UsIDIzLCA0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWREb3VibGVMRSA9IGZ1bmN0aW9uIHJlYWREb3VibGVMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA4LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIHRydWUsIDUyLCA4KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWREb3VibGVCRSA9IGZ1bmN0aW9uIHJlYWREb3VibGVCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA4LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIGZhbHNlLCA1MiwgOClcbn1cblxuZnVuY3Rpb24gY2hlY2tJbnQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgZXh0LCBtYXgsIG1pbikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihidWYpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImJ1ZmZlclwiIGFyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXIgaW5zdGFuY2UnKVxuICBpZiAodmFsdWUgPiBtYXggfHwgdmFsdWUgPCBtaW4pIHRocm93IG5ldyBSYW5nZUVycm9yKCdcInZhbHVlXCIgYXJndW1lbnQgaXMgb3V0IG9mIGJvdW5kcycpXG4gIGlmIChvZmZzZXQgKyBleHQgPiBidWYubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignSW5kZXggb3V0IG9mIHJhbmdlJylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVpbnRMRSA9XG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludExFID0gZnVuY3Rpb24gd3JpdGVVSW50TEUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY29uc3QgbWF4Qnl0ZXMgPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCkgLSAxXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbWF4Qnl0ZXMsIDApXG4gIH1cblxuICBsZXQgbXVsID0gMVxuICBsZXQgaSA9IDBcbiAgdGhpc1tvZmZzZXRdID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICh2YWx1ZSAvIG11bCkgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVWludEJFID1cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50QkUgPSBmdW5jdGlvbiB3cml0ZVVJbnRCRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjb25zdCBtYXhCeXRlcyA9IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKSAtIDFcbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBtYXhCeXRlcywgMClcbiAgfVxuXG4gIGxldCBpID0gYnl0ZUxlbmd0aCAtIDFcbiAgbGV0IG11bCA9IDFcbiAgdGhpc1tvZmZzZXQgKyBpXSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoLS1pID49IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB0aGlzW29mZnNldCArIGldID0gKHZhbHVlIC8gbXVsKSAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVaW50OCA9XG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDggPSBmdW5jdGlvbiB3cml0ZVVJbnQ4ICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMSwgMHhmZiwgMClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDFcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVpbnQxNkxFID1cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MTZMRSA9IGZ1bmN0aW9uIHdyaXRlVUludDE2TEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweGZmZmYsIDApXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVaW50MTZCRSA9XG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDE2QkUgPSBmdW5jdGlvbiB3cml0ZVVJbnQxNkJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMiwgMHhmZmZmLCAwKVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDgpXG4gIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgJiAweGZmKVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVWludDMyTEUgPVxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkxFID0gZnVuY3Rpb24gd3JpdGVVSW50MzJMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4ZmZmZmZmZmYsIDApXG4gIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgPj4+IDI0KVxuICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiAxNilcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVpbnQzMkJFID1cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MzJCRSA9IGZ1bmN0aW9uIHdyaXRlVUludDMyQkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweGZmZmZmZmZmLCAwKVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDI0KVxuICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiAxNilcbiAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gOClcbiAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbmZ1bmN0aW9uIHdydEJpZ1VJbnQ2NExFIChidWYsIHZhbHVlLCBvZmZzZXQsIG1pbiwgbWF4KSB7XG4gIGNoZWNrSW50QkkodmFsdWUsIG1pbiwgbWF4LCBidWYsIG9mZnNldCwgNylcblxuICBsZXQgbG8gPSBOdW1iZXIodmFsdWUgJiBCaWdJbnQoMHhmZmZmZmZmZikpXG4gIGJ1ZltvZmZzZXQrK10gPSBsb1xuICBsbyA9IGxvID4+IDhcbiAgYnVmW29mZnNldCsrXSA9IGxvXG4gIGxvID0gbG8gPj4gOFxuICBidWZbb2Zmc2V0KytdID0gbG9cbiAgbG8gPSBsbyA+PiA4XG4gIGJ1ZltvZmZzZXQrK10gPSBsb1xuICBsZXQgaGkgPSBOdW1iZXIodmFsdWUgPj4gQmlnSW50KDMyKSAmIEJpZ0ludCgweGZmZmZmZmZmKSlcbiAgYnVmW29mZnNldCsrXSA9IGhpXG4gIGhpID0gaGkgPj4gOFxuICBidWZbb2Zmc2V0KytdID0gaGlcbiAgaGkgPSBoaSA+PiA4XG4gIGJ1ZltvZmZzZXQrK10gPSBoaVxuICBoaSA9IGhpID4+IDhcbiAgYnVmW29mZnNldCsrXSA9IGhpXG4gIHJldHVybiBvZmZzZXRcbn1cblxuZnVuY3Rpb24gd3J0QmlnVUludDY0QkUgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbWluLCBtYXgpIHtcbiAgY2hlY2tJbnRCSSh2YWx1ZSwgbWluLCBtYXgsIGJ1Ziwgb2Zmc2V0LCA3KVxuXG4gIGxldCBsbyA9IE51bWJlcih2YWx1ZSAmIEJpZ0ludCgweGZmZmZmZmZmKSlcbiAgYnVmW29mZnNldCArIDddID0gbG9cbiAgbG8gPSBsbyA+PiA4XG4gIGJ1ZltvZmZzZXQgKyA2XSA9IGxvXG4gIGxvID0gbG8gPj4gOFxuICBidWZbb2Zmc2V0ICsgNV0gPSBsb1xuICBsbyA9IGxvID4+IDhcbiAgYnVmW29mZnNldCArIDRdID0gbG9cbiAgbGV0IGhpID0gTnVtYmVyKHZhbHVlID4+IEJpZ0ludCgzMikgJiBCaWdJbnQoMHhmZmZmZmZmZikpXG4gIGJ1ZltvZmZzZXQgKyAzXSA9IGhpXG4gIGhpID0gaGkgPj4gOFxuICBidWZbb2Zmc2V0ICsgMl0gPSBoaVxuICBoaSA9IGhpID4+IDhcbiAgYnVmW29mZnNldCArIDFdID0gaGlcbiAgaGkgPSBoaSA+PiA4XG4gIGJ1ZltvZmZzZXRdID0gaGlcbiAgcmV0dXJuIG9mZnNldCArIDhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUJpZ1VJbnQ2NExFID0gZGVmaW5lQmlnSW50TWV0aG9kKGZ1bmN0aW9uIHdyaXRlQmlnVUludDY0TEUgKHZhbHVlLCBvZmZzZXQgPSAwKSB7XG4gIHJldHVybiB3cnRCaWdVSW50NjRMRSh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBCaWdJbnQoMCksIEJpZ0ludCgnMHhmZmZmZmZmZmZmZmZmZmZmJykpXG59KVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlQmlnVUludDY0QkUgPSBkZWZpbmVCaWdJbnRNZXRob2QoZnVuY3Rpb24gd3JpdGVCaWdVSW50NjRCRSAodmFsdWUsIG9mZnNldCA9IDApIHtcbiAgcmV0dXJuIHdydEJpZ1VJbnQ2NEJFKHRoaXMsIHZhbHVlLCBvZmZzZXQsIEJpZ0ludCgwKSwgQmlnSW50KCcweGZmZmZmZmZmZmZmZmZmZmYnKSlcbn0pXG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnRMRSA9IGZ1bmN0aW9uIHdyaXRlSW50TEUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY29uc3QgbGltaXQgPSBNYXRoLnBvdygyLCAoOCAqIGJ5dGVMZW5ndGgpIC0gMSlcblxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIGxpbWl0IC0gMSwgLWxpbWl0KVxuICB9XG5cbiAgbGV0IGkgPSAwXG4gIGxldCBtdWwgPSAxXG4gIGxldCBzdWIgPSAwXG4gIHRoaXNbb2Zmc2V0XSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIGlmICh2YWx1ZSA8IDAgJiYgc3ViID09PSAwICYmIHRoaXNbb2Zmc2V0ICsgaSAtIDFdICE9PSAwKSB7XG4gICAgICBzdWIgPSAxXG4gICAgfVxuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAoKHZhbHVlIC8gbXVsKSA+PiAwKSAtIHN1YiAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnRCRSA9IGZ1bmN0aW9uIHdyaXRlSW50QkUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY29uc3QgbGltaXQgPSBNYXRoLnBvdygyLCAoOCAqIGJ5dGVMZW5ndGgpIC0gMSlcblxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIGxpbWl0IC0gMSwgLWxpbWl0KVxuICB9XG5cbiAgbGV0IGkgPSBieXRlTGVuZ3RoIC0gMVxuICBsZXQgbXVsID0gMVxuICBsZXQgc3ViID0gMFxuICB0aGlzW29mZnNldCArIGldID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgtLWkgPj0gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIGlmICh2YWx1ZSA8IDAgJiYgc3ViID09PSAwICYmIHRoaXNbb2Zmc2V0ICsgaSArIDFdICE9PSAwKSB7XG4gICAgICBzdWIgPSAxXG4gICAgfVxuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAoKHZhbHVlIC8gbXVsKSA+PiAwKSAtIHN1YiAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQ4ID0gZnVuY3Rpb24gd3JpdGVJbnQ4ICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMSwgMHg3ZiwgLTB4ODApXG4gIGlmICh2YWx1ZSA8IDApIHZhbHVlID0gMHhmZiArIHZhbHVlICsgMVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICByZXR1cm4gb2Zmc2V0ICsgMVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MTZMRSA9IGZ1bmN0aW9uIHdyaXRlSW50MTZMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4N2ZmZiwgLTB4ODAwMClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDE2QkUgPSBmdW5jdGlvbiB3cml0ZUludDE2QkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweDdmZmYsIC0weDgwMDApXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gOClcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQzMkxFID0gZnVuY3Rpb24gd3JpdGVJbnQzMkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgNCwgMHg3ZmZmZmZmZiwgLTB4ODAwMDAwMDApXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gIHRoaXNbb2Zmc2V0ICsgMl0gPSAodmFsdWUgPj4+IDE2KVxuICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlID4+PiAyNClcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDMyQkUgPSBmdW5jdGlvbiB3cml0ZUludDMyQkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweDdmZmZmZmZmLCAtMHg4MDAwMDAwMClcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmZmZmZmZmICsgdmFsdWUgKyAxXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gMjQpXG4gIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDE2KVxuICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiA4KVxuICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUJpZ0ludDY0TEUgPSBkZWZpbmVCaWdJbnRNZXRob2QoZnVuY3Rpb24gd3JpdGVCaWdJbnQ2NExFICh2YWx1ZSwgb2Zmc2V0ID0gMCkge1xuICByZXR1cm4gd3J0QmlnVUludDY0TEUodGhpcywgdmFsdWUsIG9mZnNldCwgLUJpZ0ludCgnMHg4MDAwMDAwMDAwMDAwMDAwJyksIEJpZ0ludCgnMHg3ZmZmZmZmZmZmZmZmZmZmJykpXG59KVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlQmlnSW50NjRCRSA9IGRlZmluZUJpZ0ludE1ldGhvZChmdW5jdGlvbiB3cml0ZUJpZ0ludDY0QkUgKHZhbHVlLCBvZmZzZXQgPSAwKSB7XG4gIHJldHVybiB3cnRCaWdVSW50NjRCRSh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAtQmlnSW50KCcweDgwMDAwMDAwMDAwMDAwMDAnKSwgQmlnSW50KCcweDdmZmZmZmZmZmZmZmZmZmYnKSlcbn0pXG5cbmZ1bmN0aW9uIGNoZWNrSUVFRTc1NCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBleHQsIG1heCwgbWluKSB7XG4gIGlmIChvZmZzZXQgKyBleHQgPiBidWYubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignSW5kZXggb3V0IG9mIHJhbmdlJylcbiAgaWYgKG9mZnNldCA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbmRleCBvdXQgb2YgcmFuZ2UnKVxufVxuXG5mdW5jdGlvbiB3cml0ZUZsb2F0IChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjaGVja0lFRUU3NTQoYnVmLCB2YWx1ZSwgb2Zmc2V0LCA0LCAzLjQwMjgyMzQ2NjM4NTI4ODZlKzM4LCAtMy40MDI4MjM0NjYzODUyODg2ZSszOClcbiAgfVxuICBpZWVlNzU0LndyaXRlKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCAyMywgNClcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0TEUgPSBmdW5jdGlvbiB3cml0ZUZsb2F0TEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZUZsb2F0KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRmxvYXRCRSA9IGZ1bmN0aW9uIHdyaXRlRmxvYXRCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRmxvYXQodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiB3cml0ZURvdWJsZSAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tJRUVFNzU0KGJ1ZiwgdmFsdWUsIG9mZnNldCwgOCwgMS43OTc2OTMxMzQ4NjIzMTU3RSszMDgsIC0xLjc5NzY5MzEzNDg2MjMxNTdFKzMwOClcbiAgfVxuICBpZWVlNzU0LndyaXRlKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCA1MiwgOClcbiAgcmV0dXJuIG9mZnNldCArIDhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZURvdWJsZUxFID0gZnVuY3Rpb24gd3JpdGVEb3VibGVMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlQkUgPSBmdW5jdGlvbiB3cml0ZURvdWJsZUJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVEb3VibGUodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG4vLyBjb3B5KHRhcmdldEJ1ZmZlciwgdGFyZ2V0U3RhcnQ9MCwgc291cmNlU3RhcnQ9MCwgc291cmNlRW5kPWJ1ZmZlci5sZW5ndGgpXG5CdWZmZXIucHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbiBjb3B5ICh0YXJnZXQsIHRhcmdldFN0YXJ0LCBzdGFydCwgZW5kKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKHRhcmdldCkpIHRocm93IG5ldyBUeXBlRXJyb3IoJ2FyZ3VtZW50IHNob3VsZCBiZSBhIEJ1ZmZlcicpXG4gIGlmICghc3RhcnQpIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCAmJiBlbmQgIT09IDApIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmICh0YXJnZXRTdGFydCA+PSB0YXJnZXQubGVuZ3RoKSB0YXJnZXRTdGFydCA9IHRhcmdldC5sZW5ndGhcbiAgaWYgKCF0YXJnZXRTdGFydCkgdGFyZ2V0U3RhcnQgPSAwXG4gIGlmIChlbmQgPiAwICYmIGVuZCA8IHN0YXJ0KSBlbmQgPSBzdGFydFxuXG4gIC8vIENvcHkgMCBieXRlczsgd2UncmUgZG9uZVxuICBpZiAoZW5kID09PSBzdGFydCkgcmV0dXJuIDBcbiAgaWYgKHRhcmdldC5sZW5ndGggPT09IDAgfHwgdGhpcy5sZW5ndGggPT09IDApIHJldHVybiAwXG5cbiAgLy8gRmF0YWwgZXJyb3IgY29uZGl0aW9uc1xuICBpZiAodGFyZ2V0U3RhcnQgPCAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3RhcmdldFN0YXJ0IG91dCBvZiBib3VuZHMnKVxuICB9XG4gIGlmIChzdGFydCA8IDAgfHwgc3RhcnQgPj0gdGhpcy5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbmRleCBvdXQgb2YgcmFuZ2UnKVxuICBpZiAoZW5kIDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3NvdXJjZUVuZCBvdXQgb2YgYm91bmRzJylcblxuICAvLyBBcmUgd2Ugb29iP1xuICBpZiAoZW5kID4gdGhpcy5sZW5ndGgpIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmICh0YXJnZXQubGVuZ3RoIC0gdGFyZ2V0U3RhcnQgPCBlbmQgLSBzdGFydCkge1xuICAgIGVuZCA9IHRhcmdldC5sZW5ndGggLSB0YXJnZXRTdGFydCArIHN0YXJ0XG4gIH1cblxuICBjb25zdCBsZW4gPSBlbmQgLSBzdGFydFxuXG4gIGlmICh0aGlzID09PSB0YXJnZXQgJiYgdHlwZW9mIFVpbnQ4QXJyYXkucHJvdG90eXBlLmNvcHlXaXRoaW4gPT09ICdmdW5jdGlvbicpIHtcbiAgICAvLyBVc2UgYnVpbHQtaW4gd2hlbiBhdmFpbGFibGUsIG1pc3NpbmcgZnJvbSBJRTExXG4gICAgdGhpcy5jb3B5V2l0aGluKHRhcmdldFN0YXJ0LCBzdGFydCwgZW5kKVxuICB9IGVsc2Uge1xuICAgIFVpbnQ4QXJyYXkucHJvdG90eXBlLnNldC5jYWxsKFxuICAgICAgdGFyZ2V0LFxuICAgICAgdGhpcy5zdWJhcnJheShzdGFydCwgZW5kKSxcbiAgICAgIHRhcmdldFN0YXJ0XG4gICAgKVxuICB9XG5cbiAgcmV0dXJuIGxlblxufVxuXG4vLyBVc2FnZTpcbi8vICAgIGJ1ZmZlci5maWxsKG51bWJlclssIG9mZnNldFssIGVuZF1dKVxuLy8gICAgYnVmZmVyLmZpbGwoYnVmZmVyWywgb2Zmc2V0WywgZW5kXV0pXG4vLyAgICBidWZmZXIuZmlsbChzdHJpbmdbLCBvZmZzZXRbLCBlbmRdXVssIGVuY29kaW5nXSlcbkJ1ZmZlci5wcm90b3R5cGUuZmlsbCA9IGZ1bmN0aW9uIGZpbGwgKHZhbCwgc3RhcnQsIGVuZCwgZW5jb2RpbmcpIHtcbiAgLy8gSGFuZGxlIHN0cmluZyBjYXNlczpcbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnKSB7XG4gICAgaWYgKHR5cGVvZiBzdGFydCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGVuY29kaW5nID0gc3RhcnRcbiAgICAgIHN0YXJ0ID0gMFxuICAgICAgZW5kID0gdGhpcy5sZW5ndGhcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBlbmQgPT09ICdzdHJpbmcnKSB7XG4gICAgICBlbmNvZGluZyA9IGVuZFxuICAgICAgZW5kID0gdGhpcy5sZW5ndGhcbiAgICB9XG4gICAgaWYgKGVuY29kaW5nICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIGVuY29kaW5nICE9PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZW5jb2RpbmcgbXVzdCBiZSBhIHN0cmluZycpXG4gICAgfVxuICAgIGlmICh0eXBlb2YgZW5jb2RpbmcgPT09ICdzdHJpbmcnICYmICFCdWZmZXIuaXNFbmNvZGluZyhlbmNvZGluZykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBlbmNvZGluZylcbiAgICB9XG4gICAgaWYgKHZhbC5sZW5ndGggPT09IDEpIHtcbiAgICAgIGNvbnN0IGNvZGUgPSB2YWwuY2hhckNvZGVBdCgwKVxuICAgICAgaWYgKChlbmNvZGluZyA9PT0gJ3V0ZjgnICYmIGNvZGUgPCAxMjgpIHx8XG4gICAgICAgICAgZW5jb2RpbmcgPT09ICdsYXRpbjEnKSB7XG4gICAgICAgIC8vIEZhc3QgcGF0aDogSWYgYHZhbGAgZml0cyBpbnRvIGEgc2luZ2xlIGJ5dGUsIHVzZSB0aGF0IG51bWVyaWMgdmFsdWUuXG4gICAgICAgIHZhbCA9IGNvZGVcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHtcbiAgICB2YWwgPSB2YWwgJiAyNTVcbiAgfSBlbHNlIGlmICh0eXBlb2YgdmFsID09PSAnYm9vbGVhbicpIHtcbiAgICB2YWwgPSBOdW1iZXIodmFsKVxuICB9XG5cbiAgLy8gSW52YWxpZCByYW5nZXMgYXJlIG5vdCBzZXQgdG8gYSBkZWZhdWx0LCBzbyBjYW4gcmFuZ2UgY2hlY2sgZWFybHkuXG4gIGlmIChzdGFydCA8IDAgfHwgdGhpcy5sZW5ndGggPCBzdGFydCB8fCB0aGlzLmxlbmd0aCA8IGVuZCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdPdXQgb2YgcmFuZ2UgaW5kZXgnKVxuICB9XG5cbiAgaWYgKGVuZCA8PSBzdGFydCkge1xuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICBzdGFydCA9IHN0YXJ0ID4+PiAwXG4gIGVuZCA9IGVuZCA9PT0gdW5kZWZpbmVkID8gdGhpcy5sZW5ndGggOiBlbmQgPj4+IDBcblxuICBpZiAoIXZhbCkgdmFsID0gMFxuXG4gIGxldCBpXG4gIGlmICh0eXBlb2YgdmFsID09PSAnbnVtYmVyJykge1xuICAgIGZvciAoaSA9IHN0YXJ0OyBpIDwgZW5kOyArK2kpIHtcbiAgICAgIHRoaXNbaV0gPSB2YWxcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgYnl0ZXMgPSBCdWZmZXIuaXNCdWZmZXIodmFsKVxuICAgICAgPyB2YWxcbiAgICAgIDogQnVmZmVyLmZyb20odmFsLCBlbmNvZGluZylcbiAgICBjb25zdCBsZW4gPSBieXRlcy5sZW5ndGhcbiAgICBpZiAobGVuID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgdmFsdWUgXCInICsgdmFsICtcbiAgICAgICAgJ1wiIGlzIGludmFsaWQgZm9yIGFyZ3VtZW50IFwidmFsdWVcIicpXG4gICAgfVxuICAgIGZvciAoaSA9IDA7IGkgPCBlbmQgLSBzdGFydDsgKytpKSB7XG4gICAgICB0aGlzW2kgKyBzdGFydF0gPSBieXRlc1tpICUgbGVuXVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGlzXG59XG5cbi8vIENVU1RPTSBFUlJPUlNcbi8vID09PT09PT09PT09PT1cblxuLy8gU2ltcGxpZmllZCB2ZXJzaW9ucyBmcm9tIE5vZGUsIGNoYW5nZWQgZm9yIEJ1ZmZlci1vbmx5IHVzYWdlXG5jb25zdCBlcnJvcnMgPSB7fVxuZnVuY3Rpb24gRSAoc3ltLCBnZXRNZXNzYWdlLCBCYXNlKSB7XG4gIGVycm9yc1tzeW1dID0gY2xhc3MgTm9kZUVycm9yIGV4dGVuZHMgQmFzZSB7XG4gICAgY29uc3RydWN0b3IgKCkge1xuICAgICAgc3VwZXIoKVxuXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ21lc3NhZ2UnLCB7XG4gICAgICAgIHZhbHVlOiBnZXRNZXNzYWdlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyksXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH0pXG5cbiAgICAgIC8vIEFkZCB0aGUgZXJyb3IgY29kZSB0byB0aGUgbmFtZSB0byBpbmNsdWRlIGl0IGluIHRoZSBzdGFjayB0cmFjZS5cbiAgICAgIHRoaXMubmFtZSA9IGAke3RoaXMubmFtZX0gWyR7c3ltfV1gXG4gICAgICAvLyBBY2Nlc3MgdGhlIHN0YWNrIHRvIGdlbmVyYXRlIHRoZSBlcnJvciBtZXNzYWdlIGluY2x1ZGluZyB0aGUgZXJyb3IgY29kZVxuICAgICAgLy8gZnJvbSB0aGUgbmFtZS5cbiAgICAgIHRoaXMuc3RhY2sgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtZXhwcmVzc2lvbnNcbiAgICAgIC8vIFJlc2V0IHRoZSBuYW1lIHRvIHRoZSBhY3R1YWwgbmFtZS5cbiAgICAgIGRlbGV0ZSB0aGlzLm5hbWVcbiAgICB9XG5cbiAgICBnZXQgY29kZSAoKSB7XG4gICAgICByZXR1cm4gc3ltXG4gICAgfVxuXG4gICAgc2V0IGNvZGUgKHZhbHVlKSB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ2NvZGUnLCB7XG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgdmFsdWUsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlXG4gICAgICB9KVxuICAgIH1cblxuICAgIHRvU3RyaW5nICgpIHtcbiAgICAgIHJldHVybiBgJHt0aGlzLm5hbWV9IFske3N5bX1dOiAke3RoaXMubWVzc2FnZX1gXG4gICAgfVxuICB9XG59XG5cbkUoJ0VSUl9CVUZGRVJfT1VUX09GX0JPVU5EUycsXG4gIGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgaWYgKG5hbWUpIHtcbiAgICAgIHJldHVybiBgJHtuYW1lfSBpcyBvdXRzaWRlIG9mIGJ1ZmZlciBib3VuZHNgXG4gICAgfVxuXG4gICAgcmV0dXJuICdBdHRlbXB0IHRvIGFjY2VzcyBtZW1vcnkgb3V0c2lkZSBidWZmZXIgYm91bmRzJ1xuICB9LCBSYW5nZUVycm9yKVxuRSgnRVJSX0lOVkFMSURfQVJHX1RZUEUnLFxuICBmdW5jdGlvbiAobmFtZSwgYWN0dWFsKSB7XG4gICAgcmV0dXJuIGBUaGUgXCIke25hbWV9XCIgYXJndW1lbnQgbXVzdCBiZSBvZiB0eXBlIG51bWJlci4gUmVjZWl2ZWQgdHlwZSAke3R5cGVvZiBhY3R1YWx9YFxuICB9LCBUeXBlRXJyb3IpXG5FKCdFUlJfT1VUX09GX1JBTkdFJyxcbiAgZnVuY3Rpb24gKHN0ciwgcmFuZ2UsIGlucHV0KSB7XG4gICAgbGV0IG1zZyA9IGBUaGUgdmFsdWUgb2YgXCIke3N0cn1cIiBpcyBvdXQgb2YgcmFuZ2UuYFxuICAgIGxldCByZWNlaXZlZCA9IGlucHV0XG4gICAgaWYgKE51bWJlci5pc0ludGVnZXIoaW5wdXQpICYmIE1hdGguYWJzKGlucHV0KSA+IDIgKiogMzIpIHtcbiAgICAgIHJlY2VpdmVkID0gYWRkTnVtZXJpY2FsU2VwYXJhdG9yKFN0cmluZyhpbnB1dCkpXG4gICAgfSBlbHNlIGlmICh0eXBlb2YgaW5wdXQgPT09ICdiaWdpbnQnKSB7XG4gICAgICByZWNlaXZlZCA9IFN0cmluZyhpbnB1dClcbiAgICAgIGlmIChpbnB1dCA+IEJpZ0ludCgyKSAqKiBCaWdJbnQoMzIpIHx8IGlucHV0IDwgLShCaWdJbnQoMikgKiogQmlnSW50KDMyKSkpIHtcbiAgICAgICAgcmVjZWl2ZWQgPSBhZGROdW1lcmljYWxTZXBhcmF0b3IocmVjZWl2ZWQpXG4gICAgICB9XG4gICAgICByZWNlaXZlZCArPSAnbidcbiAgICB9XG4gICAgbXNnICs9IGAgSXQgbXVzdCBiZSAke3JhbmdlfS4gUmVjZWl2ZWQgJHtyZWNlaXZlZH1gXG4gICAgcmV0dXJuIG1zZ1xuICB9LCBSYW5nZUVycm9yKVxuXG5mdW5jdGlvbiBhZGROdW1lcmljYWxTZXBhcmF0b3IgKHZhbCkge1xuICBsZXQgcmVzID0gJydcbiAgbGV0IGkgPSB2YWwubGVuZ3RoXG4gIGNvbnN0IHN0YXJ0ID0gdmFsWzBdID09PSAnLScgPyAxIDogMFxuICBmb3IgKDsgaSA+PSBzdGFydCArIDQ7IGkgLT0gMykge1xuICAgIHJlcyA9IGBfJHt2YWwuc2xpY2UoaSAtIDMsIGkpfSR7cmVzfWBcbiAgfVxuICByZXR1cm4gYCR7dmFsLnNsaWNlKDAsIGkpfSR7cmVzfWBcbn1cblxuLy8gQ0hFQ0sgRlVOQ1RJT05TXG4vLyA9PT09PT09PT09PT09PT1cblxuZnVuY3Rpb24gY2hlY2tCb3VuZHMgKGJ1Ziwgb2Zmc2V0LCBieXRlTGVuZ3RoKSB7XG4gIHZhbGlkYXRlTnVtYmVyKG9mZnNldCwgJ29mZnNldCcpXG4gIGlmIChidWZbb2Zmc2V0XSA9PT0gdW5kZWZpbmVkIHx8IGJ1ZltvZmZzZXQgKyBieXRlTGVuZ3RoXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgYm91bmRzRXJyb3Iob2Zmc2V0LCBidWYubGVuZ3RoIC0gKGJ5dGVMZW5ndGggKyAxKSlcbiAgfVxufVxuXG5mdW5jdGlvbiBjaGVja0ludEJJICh2YWx1ZSwgbWluLCBtYXgsIGJ1Ziwgb2Zmc2V0LCBieXRlTGVuZ3RoKSB7XG4gIGlmICh2YWx1ZSA+IG1heCB8fCB2YWx1ZSA8IG1pbikge1xuICAgIGNvbnN0IG4gPSB0eXBlb2YgbWluID09PSAnYmlnaW50JyA/ICduJyA6ICcnXG4gICAgbGV0IHJhbmdlXG4gICAgaWYgKGJ5dGVMZW5ndGggPiAzKSB7XG4gICAgICBpZiAobWluID09PSAwIHx8IG1pbiA9PT0gQmlnSW50KDApKSB7XG4gICAgICAgIHJhbmdlID0gYD49IDAke259IGFuZCA8IDIke259ICoqICR7KGJ5dGVMZW5ndGggKyAxKSAqIDh9JHtufWBcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJhbmdlID0gYD49IC0oMiR7bn0gKiogJHsoYnl0ZUxlbmd0aCArIDEpICogOCAtIDF9JHtufSkgYW5kIDwgMiAqKiBgICtcbiAgICAgICAgICAgICAgICBgJHsoYnl0ZUxlbmd0aCArIDEpICogOCAtIDF9JHtufWBcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmFuZ2UgPSBgPj0gJHttaW59JHtufSBhbmQgPD0gJHttYXh9JHtufWBcbiAgICB9XG4gICAgdGhyb3cgbmV3IGVycm9ycy5FUlJfT1VUX09GX1JBTkdFKCd2YWx1ZScsIHJhbmdlLCB2YWx1ZSlcbiAgfVxuICBjaGVja0JvdW5kcyhidWYsIG9mZnNldCwgYnl0ZUxlbmd0aClcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVOdW1iZXIgKHZhbHVlLCBuYW1lKSB7XG4gIGlmICh0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInKSB7XG4gICAgdGhyb3cgbmV3IGVycm9ycy5FUlJfSU5WQUxJRF9BUkdfVFlQRShuYW1lLCAnbnVtYmVyJywgdmFsdWUpXG4gIH1cbn1cblxuZnVuY3Rpb24gYm91bmRzRXJyb3IgKHZhbHVlLCBsZW5ndGgsIHR5cGUpIHtcbiAgaWYgKE1hdGguZmxvb3IodmFsdWUpICE9PSB2YWx1ZSkge1xuICAgIHZhbGlkYXRlTnVtYmVyKHZhbHVlLCB0eXBlKVxuICAgIHRocm93IG5ldyBlcnJvcnMuRVJSX09VVF9PRl9SQU5HRSh0eXBlIHx8ICdvZmZzZXQnLCAnYW4gaW50ZWdlcicsIHZhbHVlKVxuICB9XG5cbiAgaWYgKGxlbmd0aCA8IDApIHtcbiAgICB0aHJvdyBuZXcgZXJyb3JzLkVSUl9CVUZGRVJfT1VUX09GX0JPVU5EUygpXG4gIH1cblxuICB0aHJvdyBuZXcgZXJyb3JzLkVSUl9PVVRfT0ZfUkFOR0UodHlwZSB8fCAnb2Zmc2V0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGA+PSAke3R5cGUgPyAxIDogMH0gYW5kIDw9ICR7bGVuZ3RofWAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSlcbn1cblxuLy8gSEVMUEVSIEZVTkNUSU9OU1xuLy8gPT09PT09PT09PT09PT09PVxuXG5jb25zdCBJTlZBTElEX0JBU0U2NF9SRSA9IC9bXisvMC05QS1aYS16LV9dL2dcblxuZnVuY3Rpb24gYmFzZTY0Y2xlYW4gKHN0cikge1xuICAvLyBOb2RlIHRha2VzIGVxdWFsIHNpZ25zIGFzIGVuZCBvZiB0aGUgQmFzZTY0IGVuY29kaW5nXG4gIHN0ciA9IHN0ci5zcGxpdCgnPScpWzBdXG4gIC8vIE5vZGUgc3RyaXBzIG91dCBpbnZhbGlkIGNoYXJhY3RlcnMgbGlrZSBcXG4gYW5kIFxcdCBmcm9tIHRoZSBzdHJpbmcsIGJhc2U2NC1qcyBkb2VzIG5vdFxuICBzdHIgPSBzdHIudHJpbSgpLnJlcGxhY2UoSU5WQUxJRF9CQVNFNjRfUkUsICcnKVxuICAvLyBOb2RlIGNvbnZlcnRzIHN0cmluZ3Mgd2l0aCBsZW5ndGggPCAyIHRvICcnXG4gIGlmIChzdHIubGVuZ3RoIDwgMikgcmV0dXJuICcnXG4gIC8vIE5vZGUgYWxsb3dzIGZvciBub24tcGFkZGVkIGJhc2U2NCBzdHJpbmdzIChtaXNzaW5nIHRyYWlsaW5nID09PSksIGJhc2U2NC1qcyBkb2VzIG5vdFxuICB3aGlsZSAoc3RyLmxlbmd0aCAlIDQgIT09IDApIHtcbiAgICBzdHIgPSBzdHIgKyAnPSdcbiAgfVxuICByZXR1cm4gc3RyXG59XG5cbmZ1bmN0aW9uIHV0ZjhUb0J5dGVzIChzdHJpbmcsIHVuaXRzKSB7XG4gIHVuaXRzID0gdW5pdHMgfHwgSW5maW5pdHlcbiAgbGV0IGNvZGVQb2ludFxuICBjb25zdCBsZW5ndGggPSBzdHJpbmcubGVuZ3RoXG4gIGxldCBsZWFkU3Vycm9nYXRlID0gbnVsbFxuICBjb25zdCBieXRlcyA9IFtdXG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkge1xuICAgIGNvZGVQb2ludCA9IHN0cmluZy5jaGFyQ29kZUF0KGkpXG5cbiAgICAvLyBpcyBzdXJyb2dhdGUgY29tcG9uZW50XG4gICAgaWYgKGNvZGVQb2ludCA+IDB4RDdGRiAmJiBjb2RlUG9pbnQgPCAweEUwMDApIHtcbiAgICAgIC8vIGxhc3QgY2hhciB3YXMgYSBsZWFkXG4gICAgICBpZiAoIWxlYWRTdXJyb2dhdGUpIHtcbiAgICAgICAgLy8gbm8gbGVhZCB5ZXRcbiAgICAgICAgaWYgKGNvZGVQb2ludCA+IDB4REJGRikge1xuICAgICAgICAgIC8vIHVuZXhwZWN0ZWQgdHJhaWxcbiAgICAgICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9IGVsc2UgaWYgKGkgKyAxID09PSBsZW5ndGgpIHtcbiAgICAgICAgICAvLyB1bnBhaXJlZCBsZWFkXG4gICAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHZhbGlkIGxlYWRcbiAgICAgICAgbGVhZFN1cnJvZ2F0ZSA9IGNvZGVQb2ludFxuXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIC8vIDIgbGVhZHMgaW4gYSByb3dcbiAgICAgIGlmIChjb2RlUG9pbnQgPCAweERDMDApIHtcbiAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgIGxlYWRTdXJyb2dhdGUgPSBjb2RlUG9pbnRcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgLy8gdmFsaWQgc3Vycm9nYXRlIHBhaXJcbiAgICAgIGNvZGVQb2ludCA9IChsZWFkU3Vycm9nYXRlIC0gMHhEODAwIDw8IDEwIHwgY29kZVBvaW50IC0gMHhEQzAwKSArIDB4MTAwMDBcbiAgICB9IGVsc2UgaWYgKGxlYWRTdXJyb2dhdGUpIHtcbiAgICAgIC8vIHZhbGlkIGJtcCBjaGFyLCBidXQgbGFzdCBjaGFyIHdhcyBhIGxlYWRcbiAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgIH1cblxuICAgIGxlYWRTdXJyb2dhdGUgPSBudWxsXG5cbiAgICAvLyBlbmNvZGUgdXRmOFxuICAgIGlmIChjb2RlUG9pbnQgPCAweDgwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDEpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goY29kZVBvaW50KVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHg4MDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gMikgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiB8IDB4QzAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDEwMDAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDMpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweEMgfCAweEUwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHg2ICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDExMDAwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSA0KSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHgxMiB8IDB4RjAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweEMgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgY29kZSBwb2ludCcpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ5dGVzXG59XG5cbmZ1bmN0aW9uIGFzY2lpVG9CeXRlcyAoc3RyKSB7XG4gIGNvbnN0IGJ5dGVBcnJheSA9IFtdXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgKytpKSB7XG4gICAgLy8gTm9kZSdzIGNvZGUgc2VlbXMgdG8gYmUgZG9pbmcgdGhpcyBhbmQgbm90ICYgMHg3Ri4uXG4gICAgYnl0ZUFycmF5LnB1c2goc3RyLmNoYXJDb2RlQXQoaSkgJiAweEZGKVxuICB9XG4gIHJldHVybiBieXRlQXJyYXlcbn1cblxuZnVuY3Rpb24gdXRmMTZsZVRvQnl0ZXMgKHN0ciwgdW5pdHMpIHtcbiAgbGV0IGMsIGhpLCBsb1xuICBjb25zdCBieXRlQXJyYXkgPSBbXVxuICBmb3IgKGxldCBpID0gMDsgaSA8IHN0ci5sZW5ndGg7ICsraSkge1xuICAgIGlmICgodW5pdHMgLT0gMikgPCAwKSBicmVha1xuXG4gICAgYyA9IHN0ci5jaGFyQ29kZUF0KGkpXG4gICAgaGkgPSBjID4+IDhcbiAgICBsbyA9IGMgJSAyNTZcbiAgICBieXRlQXJyYXkucHVzaChsbylcbiAgICBieXRlQXJyYXkucHVzaChoaSlcbiAgfVxuXG4gIHJldHVybiBieXRlQXJyYXlcbn1cblxuZnVuY3Rpb24gYmFzZTY0VG9CeXRlcyAoc3RyKSB7XG4gIHJldHVybiBiYXNlNjQudG9CeXRlQXJyYXkoYmFzZTY0Y2xlYW4oc3RyKSlcbn1cblxuZnVuY3Rpb24gYmxpdEJ1ZmZlciAoc3JjLCBkc3QsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIGxldCBpXG4gIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkge1xuICAgIGlmICgoaSArIG9mZnNldCA+PSBkc3QubGVuZ3RoKSB8fCAoaSA+PSBzcmMubGVuZ3RoKSkgYnJlYWtcbiAgICBkc3RbaSArIG9mZnNldF0gPSBzcmNbaV1cbiAgfVxuICByZXR1cm4gaVxufVxuXG4vLyBBcnJheUJ1ZmZlciBvciBVaW50OEFycmF5IG9iamVjdHMgZnJvbSBvdGhlciBjb250ZXh0cyAoaS5lLiBpZnJhbWVzKSBkbyBub3QgcGFzc1xuLy8gdGhlIGBpbnN0YW5jZW9mYCBjaGVjayBidXQgdGhleSBzaG91bGQgYmUgdHJlYXRlZCBhcyBvZiB0aGF0IHR5cGUuXG4vLyBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyL2lzc3Vlcy8xNjZcbmZ1bmN0aW9uIGlzSW5zdGFuY2UgKG9iaiwgdHlwZSkge1xuICByZXR1cm4gb2JqIGluc3RhbmNlb2YgdHlwZSB8fFxuICAgIChvYmogIT0gbnVsbCAmJiBvYmouY29uc3RydWN0b3IgIT0gbnVsbCAmJiBvYmouY29uc3RydWN0b3IubmFtZSAhPSBudWxsICYmXG4gICAgICBvYmouY29uc3RydWN0b3IubmFtZSA9PT0gdHlwZS5uYW1lKVxufVxuZnVuY3Rpb24gbnVtYmVySXNOYU4gKG9iaikge1xuICAvLyBGb3IgSUUxMSBzdXBwb3J0XG4gIHJldHVybiBvYmogIT09IG9iaiAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXNlbGYtY29tcGFyZVxufVxuXG4vLyBDcmVhdGUgbG9va3VwIHRhYmxlIGZvciBgdG9TdHJpbmcoJ2hleCcpYFxuLy8gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlci9pc3N1ZXMvMjE5XG5jb25zdCBoZXhTbGljZUxvb2t1cFRhYmxlID0gKGZ1bmN0aW9uICgpIHtcbiAgY29uc3QgYWxwaGFiZXQgPSAnMDEyMzQ1Njc4OWFiY2RlZidcbiAgY29uc3QgdGFibGUgPSBuZXcgQXJyYXkoMjU2KVxuICBmb3IgKGxldCBpID0gMDsgaSA8IDE2OyArK2kpIHtcbiAgICBjb25zdCBpMTYgPSBpICogMTZcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IDE2OyArK2opIHtcbiAgICAgIHRhYmxlW2kxNiArIGpdID0gYWxwaGFiZXRbaV0gKyBhbHBoYWJldFtqXVxuICAgIH1cbiAgfVxuICByZXR1cm4gdGFibGVcbn0pKClcblxuLy8gUmV0dXJuIG5vdCBmdW5jdGlvbiB3aXRoIEVycm9yIGlmIEJpZ0ludCBub3Qgc3VwcG9ydGVkXG5mdW5jdGlvbiBkZWZpbmVCaWdJbnRNZXRob2QgKGZuKSB7XG4gIHJldHVybiB0eXBlb2YgQmlnSW50ID09PSAndW5kZWZpbmVkJyA/IEJ1ZmZlckJpZ0ludE5vdERlZmluZWQgOiBmblxufVxuXG5mdW5jdGlvbiBCdWZmZXJCaWdJbnROb3REZWZpbmVkICgpIHtcbiAgdGhyb3cgbmV3IEVycm9yKCdCaWdJbnQgbm90IHN1cHBvcnRlZCcpXG59XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///764\n")},817:function(__unused_webpack_module,exports,__webpack_require__){eval("(function (global, factory) {\n     true ? factory(exports) :\n    0;\n}(this, (function (exports) { 'use strict';\n\n    function isNullOrUndefined(obj) {\n        return obj === null || obj === undefined;\n    }\n\n    /*\n     * Copyright 2008 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /* global Reflect, Promise */\n\n    var extendStatics = Object.setPrototypeOf ||\n        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n\n    function __extends(d, b) {\n        extendStatics(d, b);\n        function __() { this.constructor = d; }\n        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n    }\n\n    function fixProto(target, prototype) {\n        var setPrototypeOf = Object.setPrototypeOf;\n        setPrototypeOf ? setPrototypeOf(target, prototype) : (target.__proto__ = prototype);\n    }\n\n    function fixStack(target, fn) {\n        if (fn === void 0) {\n            fn = target.constructor;\n        }\n        var captureStackTrace = Error.captureStackTrace;\n        captureStackTrace && captureStackTrace(target, fn);\n    }\n\n    var CustomError = (function (_super) {\n        __extends(CustomError, _super);\n        function CustomError(message) {\n            var _newTarget = this.constructor;\n            var _this = _super.call(this, message) || this;\n            Object.defineProperty(_this, 'name', {\n                value: _newTarget.name,\n                enumerable: false\n            });\n            fixProto(_this, _newTarget.prototype);\n            fixStack(_this);\n            return _this;\n        }\n        \n        return CustomError;\n    })(Error);\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class Exception extends CustomError {\n        /**\n         * Allows Exception to be constructed directly\n         * with some message and prototype definition.\n         */\n        constructor(message = undefined) {\n            super(message);\n            this.message = message;\n        }\n        getKind() {\n            const ex = this.constructor;\n            return ex.kind;\n        }\n    }\n    /**\n     * It's typed as string so it can be extended and overriden.\n     */\n    Exception.kind = 'Exception';\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class ArgumentException extends Exception {\n    }\n    ArgumentException.kind = 'ArgumentException';\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class IllegalArgumentException extends Exception {\n    }\n    IllegalArgumentException.kind = 'IllegalArgumentException';\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    class BinaryBitmap {\n        constructor(binarizer) {\n            this.binarizer = binarizer;\n            if (binarizer === null) {\n                throw new IllegalArgumentException('Binarizer must be non-null.');\n            }\n        }\n        /**\n         * @return The width of the bitmap.\n         */\n        getWidth() {\n            return this.binarizer.getWidth();\n        }\n        /**\n         * @return The height of the bitmap.\n         */\n        getHeight() {\n            return this.binarizer.getHeight();\n        }\n        /**\n         * Converts one row of luminance data to 1 bit data. May actually do the conversion, or return\n         * cached data. Callers should assume this method is expensive and call it as seldom as possible.\n         * This method is intended for decoding 1D barcodes and may choose to apply sharpening.\n         *\n         * @param y The row to fetch, which must be in [0, bitmap height)\n         * @param row An optional preallocated array. If null or too small, it will be ignored.\n         *            If used, the Binarizer will call BitArray.clear(). Always use the returned object.\n         * @return The array of bits for this row (true means black).\n         * @throws NotFoundException if row can't be binarized\n         */\n        getBlackRow(y /*int*/, row) {\n            return this.binarizer.getBlackRow(y, row);\n        }\n        /**\n         * Converts a 2D array of luminance data to 1 bit. As above, assume this method is expensive\n         * and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or\n         * may not apply sharpening. Therefore, a row from this matrix may not be identical to one\n         * fetched using getBlackRow(), so don't mix and match between them.\n         *\n         * @return The 2D array of bits for the image (true means black).\n         * @throws NotFoundException if image can't be binarized to make a matrix\n         */\n        getBlackMatrix() {\n            // The matrix is created on demand the first time it is requested, then cached. There are two\n            // reasons for this:\n            // 1. This work will never be done if the caller only installs 1D Reader objects, or if a\n            //    1D Reader finds a barcode before the 2D Readers run.\n            // 2. This work will only be done once even if the caller installs multiple 2D Readers.\n            if (this.matrix === null || this.matrix === undefined) {\n                this.matrix = this.binarizer.getBlackMatrix();\n            }\n            return this.matrix;\n        }\n        /**\n         * @return Whether this bitmap can be cropped.\n         */\n        isCropSupported() {\n            return this.binarizer.getLuminanceSource().isCropSupported();\n        }\n        /**\n         * Returns a new object with cropped image data. Implementations may keep a reference to the\n         * original data rather than a copy. Only callable if isCropSupported() is true.\n         *\n         * @param left The left coordinate, which must be in [0,getWidth())\n         * @param top The top coordinate, which must be in [0,getHeight())\n         * @param width The width of the rectangle to crop.\n         * @param height The height of the rectangle to crop.\n         * @return A cropped version of this object.\n         */\n        crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n            const newSource = this.binarizer.getLuminanceSource().crop(left, top, width, height);\n            return new BinaryBitmap(this.binarizer.createBinarizer(newSource));\n        }\n        /**\n         * @return Whether this bitmap supports counter-clockwise rotation.\n         */\n        isRotateSupported() {\n            return this.binarizer.getLuminanceSource().isRotateSupported();\n        }\n        /**\n         * Returns a new object with rotated image data by 90 degrees counterclockwise.\n         * Only callable if {@link #isRotateSupported()} is true.\n         *\n         * @return A rotated version of this object.\n         */\n        rotateCounterClockwise() {\n            const newSource = this.binarizer.getLuminanceSource().rotateCounterClockwise();\n            return new BinaryBitmap(this.binarizer.createBinarizer(newSource));\n        }\n        /**\n         * Returns a new object with rotated image data by 45 degrees counterclockwise.\n         * Only callable if {@link #isRotateSupported()} is true.\n         *\n         * @return A rotated version of this object.\n         */\n        rotateCounterClockwise45() {\n            const newSource = this.binarizer.getLuminanceSource().rotateCounterClockwise45();\n            return new BinaryBitmap(this.binarizer.createBinarizer(newSource));\n        }\n        /*@Override*/\n        toString() {\n            try {\n                return this.getBlackMatrix().toString();\n            }\n            catch (e /*: NotFoundException*/) {\n                return '';\n            }\n        }\n    }\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class ChecksumException extends Exception {\n        static getChecksumInstance() {\n            return new ChecksumException();\n        }\n    }\n    ChecksumException.kind = 'ChecksumException';\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * This class hierarchy provides a set of methods to convert luminance data to 1 bit data.\n     * It allows the algorithm to vary polymorphically, for example allowing a very expensive\n     * thresholding technique for servers and a fast one for mobile. It also permits the implementation\n     * to vary, e.g. a JNI version for Android and a Java fallback version for other platforms.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class Binarizer {\n        constructor(source) {\n            this.source = source;\n        }\n        getLuminanceSource() {\n            return this.source;\n        }\n        getWidth() {\n            return this.source.getWidth();\n        }\n        getHeight() {\n            return this.source.getHeight();\n        }\n    }\n\n    class System {\n        // public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)\n        /**\n         * Makes a copy of a array.\n         */\n        static arraycopy(src, srcPos, dest, destPos, length) {\n            // TODO: better use split or set?\n            while (length--) {\n                dest[destPos++] = src[srcPos++];\n            }\n        }\n        /**\n         * Returns the current time in milliseconds.\n         */\n        static currentTimeMillis() {\n            return Date.now();\n        }\n    }\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class IndexOutOfBoundsException extends Exception {\n    }\n    IndexOutOfBoundsException.kind = 'IndexOutOfBoundsException';\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException {\n        constructor(index = undefined, message = undefined) {\n            super(message);\n            this.index = index;\n            this.message = message;\n        }\n    }\n    ArrayIndexOutOfBoundsException.kind = 'ArrayIndexOutOfBoundsException';\n\n    class Arrays {\n        /**\n         * Assigns the specified int value to each element of the specified array\n         * of ints.\n         *\n         * @param a the array to be filled\n         * @param val the value to be stored in all elements of the array\n         */\n        static fill(a, val) {\n            for (let i = 0, len = a.length; i < len; i++)\n                a[i] = val;\n        }\n        /**\n         * Assigns the specified int value to each element of the specified\n         * range of the specified array of ints.  The range to be filled\n         * extends from index {@code fromIndex}, inclusive, to index\n         * {@code toIndex}, exclusive.  (If {@code fromIndex==toIndex}, the\n         * range to be filled is empty.)\n         *\n         * @param a the array to be filled\n         * @param fromIndex the index of the first element (inclusive) to be\n         *        filled with the specified value\n         * @param toIndex the index of the last element (exclusive) to be\n         *        filled with the specified value\n         * @param val the value to be stored in all elements of the array\n         * @throws IllegalArgumentException if {@code fromIndex > toIndex}\n         * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or\n         *         {@code toIndex > a.length}\n         */\n        static fillWithin(a, fromIndex, toIndex, val) {\n            Arrays.rangeCheck(a.length, fromIndex, toIndex);\n            for (let i = fromIndex; i < toIndex; i++)\n                a[i] = val;\n        }\n        /**\n         * Checks that {@code fromIndex} and {@code toIndex} are in\n         * the range and throws an exception if they aren't.\n         */\n        static rangeCheck(arrayLength, fromIndex, toIndex) {\n            if (fromIndex > toIndex) {\n                throw new IllegalArgumentException('fromIndex(' + fromIndex + ') > toIndex(' + toIndex + ')');\n            }\n            if (fromIndex < 0) {\n                throw new ArrayIndexOutOfBoundsException(fromIndex);\n            }\n            if (toIndex > arrayLength) {\n                throw new ArrayIndexOutOfBoundsException(toIndex);\n            }\n        }\n        static asList(...args) {\n            return args;\n        }\n        static create(rows, cols, value) {\n            let arr = Array.from({ length: rows });\n            return arr.map(x => Array.from({ length: cols }).fill(value));\n        }\n        static createInt32Array(rows, cols, value) {\n            let arr = Array.from({ length: rows });\n            return arr.map(x => Int32Array.from({ length: cols }).fill(value));\n        }\n        static equals(first, second) {\n            if (!first) {\n                return false;\n            }\n            if (!second) {\n                return false;\n            }\n            if (!first.length) {\n                return false;\n            }\n            if (!second.length) {\n                return false;\n            }\n            if (first.length !== second.length) {\n                return false;\n            }\n            for (let i = 0, length = first.length; i < length; i++) {\n                if (first[i] !== second[i]) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        static hashCode(a) {\n            if (a === null) {\n                return 0;\n            }\n            let result = 1;\n            for (const element of a) {\n                result = 31 * result + element;\n            }\n            return result;\n        }\n        static fillUint8Array(a, value) {\n            for (let i = 0; i !== a.length; i++) {\n                a[i] = value;\n            }\n        }\n        static copyOf(original, newLength) {\n            return original.slice(0, newLength);\n        }\n        static copyOfUint8Array(original, newLength) {\n            if (original.length <= newLength) {\n                const newArray = new Uint8Array(newLength);\n                newArray.set(original);\n                return newArray;\n            }\n            return original.slice(0, newLength);\n        }\n        static copyOfRange(original, from, to) {\n            const newLength = to - from;\n            const copy = new Int32Array(newLength);\n            System.arraycopy(original, from, copy, 0, newLength);\n            return copy;\n        }\n        /*\n        * Returns the index of of the element in a sorted array or (-n-1) where n is the insertion point\n        * for the new element.\n        * Parameters:\n        *     ar - A sorted array\n        *     el - An element to search for\n        *     comparator - A comparator function. The function takes two arguments: (a, b) and returns:\n        *        a negative number  if a is less than b;\n        *        0 if a is equal to b;\n        *        a positive number of a is greater than b.\n        * The array may contain duplicate elements. If there are more than one equal elements in the array,\n        * the returned value can be the index of any one of the equal elements.\n        *\n        * http://jsfiddle.net/aryzhov/pkfst550/\n        */\n        static binarySearch(ar, el, comparator) {\n            if (undefined === comparator) {\n                comparator = Arrays.numberComparator;\n            }\n            let m = 0;\n            let n = ar.length - 1;\n            while (m <= n) {\n                const k = (n + m) >> 1;\n                const cmp = comparator(el, ar[k]);\n                if (cmp > 0) {\n                    m = k + 1;\n                }\n                else if (cmp < 0) {\n                    n = k - 1;\n                }\n                else {\n                    return k;\n                }\n            }\n            return -m - 1;\n        }\n        static numberComparator(a, b) {\n            return a - b;\n        }\n    }\n\n    /**\n     * Ponyfill for Java's Integer class.\n     */\n    class Integer {\n        static numberOfTrailingZeros(i) {\n            let y;\n            if (i === 0)\n                return 32;\n            let n = 31;\n            y = i << 16;\n            if (y !== 0) {\n                n -= 16;\n                i = y;\n            }\n            y = i << 8;\n            if (y !== 0) {\n                n -= 8;\n                i = y;\n            }\n            y = i << 4;\n            if (y !== 0) {\n                n -= 4;\n                i = y;\n            }\n            y = i << 2;\n            if (y !== 0) {\n                n -= 2;\n                i = y;\n            }\n            return n - ((i << 1) >>> 31);\n        }\n        static numberOfLeadingZeros(i) {\n            // HD, Figure 5-6\n            if (i === 0) {\n                return 32;\n            }\n            let n = 1;\n            if (i >>> 16 === 0) {\n                n += 16;\n                i <<= 16;\n            }\n            if (i >>> 24 === 0) {\n                n += 8;\n                i <<= 8;\n            }\n            if (i >>> 28 === 0) {\n                n += 4;\n                i <<= 4;\n            }\n            if (i >>> 30 === 0) {\n                n += 2;\n                i <<= 2;\n            }\n            n -= i >>> 31;\n            return n;\n        }\n        static toHexString(i) {\n            return i.toString(16);\n        }\n        static toBinaryString(intNumber) {\n            return String(parseInt(String(intNumber), 2));\n        }\n        // Returns the number of one-bits in the two's complement binary representation of the specified int value. This function is sometimes referred to as the population count.\n        // Returns:\n        // the number of one-bits in the two's complement binary representation of the specified int value.\n        static bitCount(i) {\n            // HD, Figure 5-2\n            i = i - ((i >>> 1) & 0x55555555);\n            i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);\n            i = (i + (i >>> 4)) & 0x0f0f0f0f;\n            i = i + (i >>> 8);\n            i = i + (i >>> 16);\n            return i & 0x3f;\n        }\n        static truncDivision(dividend, divisor) {\n            return Math.trunc(dividend / divisor);\n        }\n        /**\n         * Converts A string to an integer.\n         * @param s A string to convert into a number.\n         * @param radix A value between 2 and 36 that specifies the base of the number in numString. If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal. All other strings are considered decimal.\n         */\n        static parseInt(num, radix = undefined) {\n            return parseInt(num, radix);\n        }\n    }\n    Integer.MIN_VALUE_32_BITS = -2147483648;\n    Integer.MAX_VALUE = Number.MAX_SAFE_INTEGER;\n\n    /**\n     * <p>A simple, fast array of bits, represented compactly by an array of ints internally.</p>\n     *\n     * @author Sean Owen\n     */\n    class BitArray /*implements Cloneable*/ {\n        // For testing only\n        constructor(size /*int*/, bits) {\n            if (undefined === size) {\n                this.size = 0;\n                this.bits = new Int32Array(1);\n            }\n            else {\n                this.size = size;\n                if (undefined === bits || null === bits) {\n                    this.bits = BitArray.makeArray(size);\n                }\n                else {\n                    this.bits = bits;\n                }\n            }\n        }\n        getSize() {\n            return this.size;\n        }\n        getSizeInBytes() {\n            return Math.floor((this.size + 7) / 8);\n        }\n        ensureCapacity(size /*int*/) {\n            if (size > this.bits.length * 32) {\n                const newBits = BitArray.makeArray(size);\n                System.arraycopy(this.bits, 0, newBits, 0, this.bits.length);\n                this.bits = newBits;\n            }\n        }\n        /**\n         * @param i bit to get\n         * @return true iff bit i is set\n         */\n        get(i /*int*/) {\n            return (this.bits[Math.floor(i / 32)] & (1 << (i & 0x1F))) !== 0;\n        }\n        /**\n         * Sets bit i.\n         *\n         * @param i bit to set\n         */\n        set(i /*int*/) {\n            this.bits[Math.floor(i / 32)] |= 1 << (i & 0x1F);\n        }\n        /**\n         * Flips bit i.\n         *\n         * @param i bit to set\n         */\n        flip(i /*int*/) {\n            this.bits[Math.floor(i / 32)] ^= 1 << (i & 0x1F);\n        }\n        /**\n         * @param from first bit to check\n         * @return index of first bit that is set, starting from the given index, or size if none are set\n         *  at or beyond this given index\n         * @see #getNextUnset(int)\n         */\n        getNextSet(from /*int*/) {\n            const size = this.size;\n            if (from >= size) {\n                return size;\n            }\n            const bits = this.bits;\n            let bitsOffset = Math.floor(from / 32);\n            let currentBits = bits[bitsOffset];\n            // mask off lesser bits first\n            currentBits &= ~((1 << (from & 0x1F)) - 1);\n            const length = bits.length;\n            while (currentBits === 0) {\n                if (++bitsOffset === length) {\n                    return size;\n                }\n                currentBits = bits[bitsOffset];\n            }\n            const result = (bitsOffset * 32) + Integer.numberOfTrailingZeros(currentBits);\n            return result > size ? size : result;\n        }\n        /**\n         * @param from index to start looking for unset bit\n         * @return index of next unset bit, or {@code size} if none are unset until the end\n         * @see #getNextSet(int)\n         */\n        getNextUnset(from /*int*/) {\n            const size = this.size;\n            if (from >= size) {\n                return size;\n            }\n            const bits = this.bits;\n            let bitsOffset = Math.floor(from / 32);\n            let currentBits = ~bits[bitsOffset];\n            // mask off lesser bits first\n            currentBits &= ~((1 << (from & 0x1F)) - 1);\n            const length = bits.length;\n            while (currentBits === 0) {\n                if (++bitsOffset === length) {\n                    return size;\n                }\n                currentBits = ~bits[bitsOffset];\n            }\n            const result = (bitsOffset * 32) + Integer.numberOfTrailingZeros(currentBits);\n            return result > size ? size : result;\n        }\n        /**\n         * Sets a block of 32 bits, starting at bit i.\n         *\n         * @param i first bit to set\n         * @param newBits the new value of the next 32 bits. Note again that the least-significant bit\n         * corresponds to bit i, the next-least-significant to i+1, and so on.\n         */\n        setBulk(i /*int*/, newBits /*int*/) {\n            this.bits[Math.floor(i / 32)] = newBits;\n        }\n        /**\n         * Sets a range of bits.\n         *\n         * @param start start of range, inclusive.\n         * @param end end of range, exclusive\n         */\n        setRange(start /*int*/, end /*int*/) {\n            if (end < start || start < 0 || end > this.size) {\n                throw new IllegalArgumentException();\n            }\n            if (end === start) {\n                return;\n            }\n            end--; // will be easier to treat this as the last actually set bit -- inclusive\n            const firstInt = Math.floor(start / 32);\n            const lastInt = Math.floor(end / 32);\n            const bits = this.bits;\n            for (let i = firstInt; i <= lastInt; i++) {\n                const firstBit = i > firstInt ? 0 : start & 0x1F;\n                const lastBit = i < lastInt ? 31 : end & 0x1F;\n                // Ones from firstBit to lastBit, inclusive\n                const mask = (2 << lastBit) - (1 << firstBit);\n                bits[i] |= mask;\n            }\n        }\n        /**\n         * Clears all bits (sets to false).\n         */\n        clear() {\n            const max = this.bits.length;\n            const bits = this.bits;\n            for (let i = 0; i < max; i++) {\n                bits[i] = 0;\n            }\n        }\n        /**\n         * Efficient method to check if a range of bits is set, or not set.\n         *\n         * @param start start of range, inclusive.\n         * @param end end of range, exclusive\n         * @param value if true, checks that bits in range are set, otherwise checks that they are not set\n         * \n         * @return true iff all bits are set or not set in range, according to value argument\n         * @throws IllegalArgumentException if end is less than start or the range is not contained in the array\n         */\n        isRange(start /*int*/, end /*int*/, value) {\n            if (end < start || start < 0 || end > this.size) {\n                throw new IllegalArgumentException();\n            }\n            if (end === start) {\n                return true; // empty range matches\n            }\n            end--; // will be easier to treat this as the last actually set bit -- inclusive\n            const firstInt = Math.floor(start / 32);\n            const lastInt = Math.floor(end / 32);\n            const bits = this.bits;\n            for (let i = firstInt; i <= lastInt; i++) {\n                const firstBit = i > firstInt ? 0 : start & 0x1F;\n                const lastBit = i < lastInt ? 31 : end & 0x1F;\n                // Ones from firstBit to lastBit, inclusive\n                const mask = (2 << lastBit) - (1 << firstBit) & 0xFFFFFFFF;\n                // TYPESCRIPTPORT: & 0xFFFFFFFF added to discard anything after 32 bits, as ES has 53 bits\n                // Return false if we're looking for 1s and the masked bits[i] isn't all 1s (is: that,\n                // equals the mask, or we're looking for 0s and the masked portion is not all 0s\n                if ((bits[i] & mask) !== (value ? mask : 0)) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        appendBit(bit) {\n            this.ensureCapacity(this.size + 1);\n            if (bit) {\n                this.bits[Math.floor(this.size / 32)] |= 1 << (this.size & 0x1F);\n            }\n            this.size++;\n        }\n        /**\n         * Appends the least-significant bits, from value, in order from most-significant to\n         * least-significant. For example, appending 6 bits from 0x000001E will append the bits\n         * 0, 1, 1, 1, 1, 0 in that order.\n         *\n         * @param value {@code int} containing bits to append\n         * @param numBits bits from value to append\n         */\n        appendBits(value /*int*/, numBits /*int*/) {\n            if (numBits < 0 || numBits > 32) {\n                throw new IllegalArgumentException('Num bits must be between 0 and 32');\n            }\n            this.ensureCapacity(this.size + numBits);\n            // const appendBit = this.appendBit;\n            for (let numBitsLeft = numBits; numBitsLeft > 0; numBitsLeft--) {\n                this.appendBit(((value >> (numBitsLeft - 1)) & 0x01) === 1);\n            }\n        }\n        appendBitArray(other) {\n            const otherSize = other.size;\n            this.ensureCapacity(this.size + otherSize);\n            // const appendBit = this.appendBit;\n            for (let i = 0; i < otherSize; i++) {\n                this.appendBit(other.get(i));\n            }\n        }\n        xor(other) {\n            if (this.size !== other.size) {\n                throw new IllegalArgumentException('Sizes don\\'t match');\n            }\n            const bits = this.bits;\n            for (let i = 0, length = bits.length; i < length; i++) {\n                // The last int could be incomplete (i.e. not have 32 bits in\n                // it) but there is no problem since 0 XOR 0 == 0.\n                bits[i] ^= other.bits[i];\n            }\n        }\n        /**\n         *\n         * @param bitOffset first bit to start writing\n         * @param array array to write into. Bytes are written most-significant byte first. This is the opposite\n         *  of the internal representation, which is exposed by {@link #getBitArray()}\n         * @param offset position in array to start writing\n         * @param numBytes how many bytes to write\n         */\n        toBytes(bitOffset /*int*/, array, offset /*int*/, numBytes /*int*/) {\n            for (let i = 0; i < numBytes; i++) {\n                let theByte = 0;\n                for (let j = 0; j < 8; j++) {\n                    if (this.get(bitOffset)) {\n                        theByte |= 1 << (7 - j);\n                    }\n                    bitOffset++;\n                }\n                array[offset + i] = /*(byte)*/ theByte;\n            }\n        }\n        /**\n         * @return underlying array of ints. The first element holds the first 32 bits, and the least\n         *         significant bit is bit 0.\n         */\n        getBitArray() {\n            return this.bits;\n        }\n        /**\n         * Reverses all bits in the array.\n         */\n        reverse() {\n            const newBits = new Int32Array(this.bits.length);\n            // reverse all int's first\n            const len = Math.floor((this.size - 1) / 32);\n            const oldBitsLen = len + 1;\n            const bits = this.bits;\n            for (let i = 0; i < oldBitsLen; i++) {\n                let x = bits[i];\n                x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1);\n                x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2);\n                x = ((x >> 4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) << 4);\n                x = ((x >> 8) & 0x00ff00ff) | ((x & 0x00ff00ff) << 8);\n                x = ((x >> 16) & 0x0000ffff) | ((x & 0x0000ffff) << 16);\n                newBits[len - i] = /*(int)*/ x;\n            }\n            // now correct the int's if the bit size isn't a multiple of 32\n            if (this.size !== oldBitsLen * 32) {\n                const leftOffset = oldBitsLen * 32 - this.size;\n                let currentInt = newBits[0] >>> leftOffset;\n                for (let i = 1; i < oldBitsLen; i++) {\n                    const nextInt = newBits[i];\n                    currentInt |= nextInt << (32 - leftOffset);\n                    newBits[i - 1] = currentInt;\n                    currentInt = nextInt >>> leftOffset;\n                }\n                newBits[oldBitsLen - 1] = currentInt;\n            }\n            this.bits = newBits;\n        }\n        static makeArray(size /*int*/) {\n            return new Int32Array(Math.floor((size + 31) / 32));\n        }\n        /*@Override*/\n        equals(o) {\n            if (!(o instanceof BitArray)) {\n                return false;\n            }\n            const other = o;\n            return this.size === other.size && Arrays.equals(this.bits, other.bits);\n        }\n        /*@Override*/\n        hashCode() {\n            return 31 * this.size + Arrays.hashCode(this.bits);\n        }\n        /*@Override*/\n        toString() {\n            let result = '';\n            for (let i = 0, size = this.size; i < size; i++) {\n                if ((i & 0x07) === 0) {\n                    result += ' ';\n                }\n                result += this.get(i) ? 'X' : '.';\n            }\n            return result;\n        }\n        /*@Override*/\n        clone() {\n            return new BitArray(this.size, this.bits.slice());\n        }\n    }\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing {*/\n    /**\n     * Encapsulates a type of hint that a caller may pass to a barcode reader to help it\n     * more quickly or accurately decode it. It is up to implementations to decide what,\n     * if anything, to do with the information that is supplied.\n     *\n     * @author Sean Owen\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @see Reader#decode(BinaryBitmap,java.util.Map)\n     */\n    var DecodeHintType;\n    (function (DecodeHintType) {\n        /**\n         * Unspecified, application-specific hint. Maps to an unspecified {@link Object}.\n         */\n        DecodeHintType[DecodeHintType[\"OTHER\"] = 0] = \"OTHER\"; /*(Object.class)*/\n        /**\n         * Image is a pure monochrome image of a barcode. Doesn't matter what it maps to;\n         * use {@link Boolean#TRUE}.\n         */\n        DecodeHintType[DecodeHintType[\"PURE_BARCODE\"] = 1] = \"PURE_BARCODE\"; /*(Void.class)*/\n        /**\n         * Image is known to be of one of a few possible formats.\n         * Maps to a {@link List} of {@link BarcodeFormat}s.\n         */\n        DecodeHintType[DecodeHintType[\"POSSIBLE_FORMATS\"] = 2] = \"POSSIBLE_FORMATS\"; /*(List.class)*/\n        /**\n         * Spend more time to try to find a barcode; optimize for accuracy, not speed.\n         * Doesn't matter what it maps to; use {@link Boolean#TRUE}.\n         */\n        DecodeHintType[DecodeHintType[\"TRY_HARDER\"] = 3] = \"TRY_HARDER\"; /*(Void.class)*/\n        /**\n         * Specifies what character encoding to use when decoding, where applicable (type String)\n         */\n        DecodeHintType[DecodeHintType[\"CHARACTER_SET\"] = 4] = \"CHARACTER_SET\"; /*(String.class)*/\n        /**\n         * Allowed lengths of encoded data -- reject anything else. Maps to an {@code Int32Array}.\n         */\n        DecodeHintType[DecodeHintType[\"ALLOWED_LENGTHS\"] = 5] = \"ALLOWED_LENGTHS\"; /*(Int32Array.class)*/\n        /**\n         * Assume Code 39 codes employ a check digit. Doesn't matter what it maps to;\n         * use {@link Boolean#TRUE}.\n         */\n        DecodeHintType[DecodeHintType[\"ASSUME_CODE_39_CHECK_DIGIT\"] = 6] = \"ASSUME_CODE_39_CHECK_DIGIT\"; /*(Void.class)*/\n        /**\n         * Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed.\n         * For example this affects FNC1 handling for Code 128 (aka GS1-128). Doesn't matter what it maps to;\n         * use {@link Boolean#TRUE}.\n         */\n        DecodeHintType[DecodeHintType[\"ASSUME_GS1\"] = 7] = \"ASSUME_GS1\"; /*(Void.class)*/\n        /**\n         * If true, return the start and end digits in a Codabar barcode instead of stripping them. They\n         * are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them\n         * to not be. Doesn't matter what it maps to; use {@link Boolean#TRUE}.\n         */\n        DecodeHintType[DecodeHintType[\"RETURN_CODABAR_START_END\"] = 8] = \"RETURN_CODABAR_START_END\"; /*(Void.class)*/\n        /**\n         * The caller needs to be notified via callback when a possible {@link ResultPoint}\n         * is found. Maps to a {@link ResultPointCallback}.\n         */\n        DecodeHintType[DecodeHintType[\"NEED_RESULT_POINT_CALLBACK\"] = 9] = \"NEED_RESULT_POINT_CALLBACK\"; /*(ResultPointCallback.class)*/\n        /**\n         * Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this.\n         * Maps to an {@code Int32Array} of the allowed extension lengths, for example [2], [5], or [2, 5].\n         * If it is optional to have an extension, do not set this hint. If this is set,\n         * and a UPC or EAN barcode is found but an extension is not, then no result will be returned\n         * at all.\n         */\n        DecodeHintType[DecodeHintType[\"ALLOWED_EAN_EXTENSIONS\"] = 10] = \"ALLOWED_EAN_EXTENSIONS\"; /*(Int32Array.class)*/\n        // End of enumeration values.\n        /**\n         * Data type the hint is expecting.\n         * Among the possible values the {@link Void} stands out as being used for\n         * hints that do not expect a value to be supplied (flag hints). Such hints\n         * will possibly have their value ignored, or replaced by a\n         * {@link Boolean#TRUE}. Hint suppliers should probably use\n         * {@link Boolean#TRUE} as directed by the actual hint documentation.\n         */\n        // private valueType: Class<?>\n        // DecodeHintType(valueType: Class<?>) {\n        //   this.valueType = valueType\n        // }\n        // public getValueType(): Class<?> {\n        //   return valueType\n        // }\n    })(DecodeHintType || (DecodeHintType = {}));\n    var DecodeHintType$1 = DecodeHintType;\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class FormatException extends Exception {\n        static getFormatInstance() {\n            return new FormatException();\n        }\n    }\n    FormatException.kind = 'FormatException';\n\n    /*import java.util.HashMap;*/\n    /*import java.util.Map;*/\n    var CharacterSetValueIdentifiers;\n    (function (CharacterSetValueIdentifiers) {\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp437\"] = 0] = \"Cp437\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_1\"] = 1] = \"ISO8859_1\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_2\"] = 2] = \"ISO8859_2\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_3\"] = 3] = \"ISO8859_3\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_4\"] = 4] = \"ISO8859_4\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_5\"] = 5] = \"ISO8859_5\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_6\"] = 6] = \"ISO8859_6\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_7\"] = 7] = \"ISO8859_7\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_8\"] = 8] = \"ISO8859_8\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_9\"] = 9] = \"ISO8859_9\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_10\"] = 10] = \"ISO8859_10\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_11\"] = 11] = \"ISO8859_11\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_13\"] = 12] = \"ISO8859_13\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_14\"] = 13] = \"ISO8859_14\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_15\"] = 14] = \"ISO8859_15\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_16\"] = 15] = \"ISO8859_16\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"SJIS\"] = 16] = \"SJIS\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp1250\"] = 17] = \"Cp1250\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp1251\"] = 18] = \"Cp1251\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp1252\"] = 19] = \"Cp1252\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp1256\"] = 20] = \"Cp1256\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"UnicodeBigUnmarked\"] = 21] = \"UnicodeBigUnmarked\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"UTF8\"] = 22] = \"UTF8\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ASCII\"] = 23] = \"ASCII\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Big5\"] = 24] = \"Big5\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"GB18030\"] = 25] = \"GB18030\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"EUC_KR\"] = 26] = \"EUC_KR\";\n    })(CharacterSetValueIdentifiers || (CharacterSetValueIdentifiers = {}));\n    /**\n     * Encapsulates a Character Set ECI, according to \"Extended Channel Interpretations\" 5.3.1.1\n     * of ISO 18004.\n     *\n     * @author Sean Owen\n     */\n    class CharacterSetECI {\n        constructor(valueIdentifier, valuesParam, name, ...otherEncodingNames) {\n            this.valueIdentifier = valueIdentifier;\n            this.name = name;\n            if (typeof valuesParam === 'number') {\n                this.values = Int32Array.from([valuesParam]);\n            }\n            else {\n                this.values = valuesParam;\n            }\n            this.otherEncodingNames = otherEncodingNames;\n            CharacterSetECI.VALUE_IDENTIFIER_TO_ECI.set(valueIdentifier, this);\n            CharacterSetECI.NAME_TO_ECI.set(name, this);\n            const values = this.values;\n            for (let i = 0, length = values.length; i !== length; i++) {\n                const v = values[i];\n                CharacterSetECI.VALUES_TO_ECI.set(v, this);\n            }\n            for (const otherName of otherEncodingNames) {\n                CharacterSetECI.NAME_TO_ECI.set(otherName, this);\n            }\n        }\n        // CharacterSetECI(value: number /*int*/) {\n        //   this(new Int32Array {value})\n        // }\n        // CharacterSetECI(value: number /*int*/, String... otherEncodingNames) {\n        //   this.values = new Int32Array {value}\n        //   this.otherEncodingNames = otherEncodingNames\n        // }\n        // CharacterSetECI(values: Int32Array, String... otherEncodingNames) {\n        //   this.values = values\n        //   this.otherEncodingNames = otherEncodingNames\n        // }\n        getValueIdentifier() {\n            return this.valueIdentifier;\n        }\n        getName() {\n            return this.name;\n        }\n        getValue() {\n            return this.values[0];\n        }\n        /**\n         * @param value character set ECI value\n         * @return {@code CharacterSetECI} representing ECI of given value, or null if it is legal but\n         *   unsupported\n         * @throws FormatException if ECI value is invalid\n         */\n        static getCharacterSetECIByValue(value /*int*/) {\n            if (value < 0 || value >= 900) {\n                throw new FormatException('incorect value');\n            }\n            const characterSet = CharacterSetECI.VALUES_TO_ECI.get(value);\n            if (undefined === characterSet) {\n                throw new FormatException('incorect value');\n            }\n            return characterSet;\n        }\n        /**\n         * @param name character set ECI encoding name\n         * @return CharacterSetECI representing ECI for character encoding, or null if it is legal\n         *   but unsupported\n         */\n        static getCharacterSetECIByName(name) {\n            const characterSet = CharacterSetECI.NAME_TO_ECI.get(name);\n            if (undefined === characterSet) {\n                throw new FormatException('incorect value');\n            }\n            return characterSet;\n        }\n        equals(o) {\n            if (!(o instanceof CharacterSetECI)) {\n                return false;\n            }\n            const other = o;\n            return this.getName() === other.getName();\n        }\n    }\n    CharacterSetECI.VALUE_IDENTIFIER_TO_ECI = new Map();\n    CharacterSetECI.VALUES_TO_ECI = new Map();\n    CharacterSetECI.NAME_TO_ECI = new Map();\n    // Enum name is a Java encoding valid for java.lang and java.io\n    // TYPESCRIPTPORT: changed the main label for ISO as the TextEncoder did not recognized them in the form from java\n    // (eg ISO8859_1 must be ISO88591 or ISO8859-1 or ISO-8859-1)\n    // later on: well, except 16 wich does not work with ISO885916 so used ISO-8859-1 form for default\n    CharacterSetECI.Cp437 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp437, Int32Array.from([0, 2]), 'Cp437');\n    CharacterSetECI.ISO8859_1 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_1, Int32Array.from([1, 3]), 'ISO-8859-1', 'ISO88591', 'ISO8859_1');\n    CharacterSetECI.ISO8859_2 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_2, 4, 'ISO-8859-2', 'ISO88592', 'ISO8859_2');\n    CharacterSetECI.ISO8859_3 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_3, 5, 'ISO-8859-3', 'ISO88593', 'ISO8859_3');\n    CharacterSetECI.ISO8859_4 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_4, 6, 'ISO-8859-4', 'ISO88594', 'ISO8859_4');\n    CharacterSetECI.ISO8859_5 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_5, 7, 'ISO-8859-5', 'ISO88595', 'ISO8859_5');\n    CharacterSetECI.ISO8859_6 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_6, 8, 'ISO-8859-6', 'ISO88596', 'ISO8859_6');\n    CharacterSetECI.ISO8859_7 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_7, 9, 'ISO-8859-7', 'ISO88597', 'ISO8859_7');\n    CharacterSetECI.ISO8859_8 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_8, 10, 'ISO-8859-8', 'ISO88598', 'ISO8859_8');\n    CharacterSetECI.ISO8859_9 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_9, 11, 'ISO-8859-9', 'ISO88599', 'ISO8859_9');\n    CharacterSetECI.ISO8859_10 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_10, 12, 'ISO-8859-10', 'ISO885910', 'ISO8859_10');\n    CharacterSetECI.ISO8859_11 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_11, 13, 'ISO-8859-11', 'ISO885911', 'ISO8859_11');\n    CharacterSetECI.ISO8859_13 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_13, 15, 'ISO-8859-13', 'ISO885913', 'ISO8859_13');\n    CharacterSetECI.ISO8859_14 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_14, 16, 'ISO-8859-14', 'ISO885914', 'ISO8859_14');\n    CharacterSetECI.ISO8859_15 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_15, 17, 'ISO-8859-15', 'ISO885915', 'ISO8859_15');\n    CharacterSetECI.ISO8859_16 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_16, 18, 'ISO-8859-16', 'ISO885916', 'ISO8859_16');\n    CharacterSetECI.SJIS = new CharacterSetECI(CharacterSetValueIdentifiers.SJIS, 20, 'SJIS', 'Shift_JIS');\n    CharacterSetECI.Cp1250 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp1250, 21, 'Cp1250', 'windows-1250');\n    CharacterSetECI.Cp1251 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp1251, 22, 'Cp1251', 'windows-1251');\n    CharacterSetECI.Cp1252 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp1252, 23, 'Cp1252', 'windows-1252');\n    CharacterSetECI.Cp1256 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp1256, 24, 'Cp1256', 'windows-1256');\n    CharacterSetECI.UnicodeBigUnmarked = new CharacterSetECI(CharacterSetValueIdentifiers.UnicodeBigUnmarked, 25, 'UnicodeBigUnmarked', 'UTF-16BE', 'UnicodeBig');\n    CharacterSetECI.UTF8 = new CharacterSetECI(CharacterSetValueIdentifiers.UTF8, 26, 'UTF8', 'UTF-8');\n    CharacterSetECI.ASCII = new CharacterSetECI(CharacterSetValueIdentifiers.ASCII, Int32Array.from([27, 170]), 'ASCII', 'US-ASCII');\n    CharacterSetECI.Big5 = new CharacterSetECI(CharacterSetValueIdentifiers.Big5, 28, 'Big5');\n    CharacterSetECI.GB18030 = new CharacterSetECI(CharacterSetValueIdentifiers.GB18030, 29, 'GB18030', 'GB2312', 'EUC_CN', 'GBK');\n    CharacterSetECI.EUC_KR = new CharacterSetECI(CharacterSetValueIdentifiers.EUC_KR, 30, 'EUC_KR', 'EUC-KR');\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class UnsupportedOperationException extends Exception {\n    }\n    UnsupportedOperationException.kind = 'UnsupportedOperationException';\n\n    /**\n     * Responsible for en/decoding strings.\n     */\n    class StringEncoding {\n        /**\n         * Decodes some Uint8Array to a string format.\n         */\n        static decode(bytes, encoding) {\n            const encodingName = this.encodingName(encoding);\n            if (this.customDecoder) {\n                return this.customDecoder(bytes, encodingName);\n            }\n            // Increases browser support.\n            if (typeof TextDecoder === 'undefined' || this.shouldDecodeOnFallback(encodingName)) {\n                return this.decodeFallback(bytes, encodingName);\n            }\n            return new TextDecoder(encodingName).decode(bytes);\n        }\n        /**\n         * Checks if the decoding method should use the fallback for decoding\n         * once Node TextDecoder doesn't support all encoding formats.\n         *\n         * @param encodingName\n         */\n        static shouldDecodeOnFallback(encodingName) {\n            return !StringEncoding.isBrowser() && encodingName === 'ISO-8859-1';\n        }\n        /**\n         * Encodes some string into a Uint8Array.\n         */\n        static encode(s, encoding) {\n            const encodingName = this.encodingName(encoding);\n            if (this.customEncoder) {\n                return this.customEncoder(s, encodingName);\n            }\n            // Increases browser support.\n            if (typeof TextEncoder === 'undefined') {\n                return this.encodeFallback(s);\n            }\n            // TextEncoder only encodes to UTF8 by default as specified by encoding.spec.whatwg.org\n            return new TextEncoder().encode(s);\n        }\n        static isBrowser() {\n            return (typeof window !== 'undefined' && {}.toString.call(window) === '[object Window]');\n        }\n        /**\n         * Returns the string value from some encoding character set.\n         */\n        static encodingName(encoding) {\n            return typeof encoding === 'string'\n                ? encoding\n                : encoding.getName();\n        }\n        /**\n         * Returns character set from some encoding character set.\n         */\n        static encodingCharacterSet(encoding) {\n            if (encoding instanceof CharacterSetECI) {\n                return encoding;\n            }\n            return CharacterSetECI.getCharacterSetECIByName(encoding);\n        }\n        /**\n         * Runs a fallback for the native decoding funcion.\n         */\n        static decodeFallback(bytes, encoding) {\n            const characterSet = this.encodingCharacterSet(encoding);\n            if (StringEncoding.isDecodeFallbackSupported(characterSet)) {\n                let s = '';\n                for (let i = 0, length = bytes.length; i < length; i++) {\n                    let h = bytes[i].toString(16);\n                    if (h.length < 2) {\n                        h = '0' + h;\n                    }\n                    s += '%' + h;\n                }\n                return decodeURIComponent(s);\n            }\n            if (characterSet.equals(CharacterSetECI.UnicodeBigUnmarked)) {\n                return String.fromCharCode.apply(null, new Uint16Array(bytes.buffer));\n            }\n            throw new UnsupportedOperationException(`Encoding ${this.encodingName(encoding)} not supported by fallback.`);\n        }\n        static isDecodeFallbackSupported(characterSet) {\n            return characterSet.equals(CharacterSetECI.UTF8) ||\n                characterSet.equals(CharacterSetECI.ISO8859_1) ||\n                characterSet.equals(CharacterSetECI.ASCII);\n        }\n        /**\n         * Runs a fallback for the native encoding funcion.\n         *\n         * @see https://stackoverflow.com/a/17192845/4367683\n         */\n        static encodeFallback(s) {\n            const encodedURIstring = btoa(unescape(encodeURIComponent(s)));\n            const charList = encodedURIstring.split('');\n            const uintArray = [];\n            for (let i = 0; i < charList.length; i++) {\n                uintArray.push(charList[i].charCodeAt(0));\n            }\n            return new Uint8Array(uintArray);\n        }\n    }\n\n    /*\n     * Copyright (C) 2010 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * Common string-related functions.\n     *\n     * @author Sean Owen\n     * @author Alex Dupre\n     */\n    class StringUtils {\n        // SHIFT_JIS.equalsIgnoreCase(PLATFORM_DEFAULT_ENCODING) ||\n        // EUC_JP.equalsIgnoreCase(PLATFORM_DEFAULT_ENCODING);\n        static castAsNonUtf8Char(code, encoding = null) {\n            // ISO 8859-1 is the Java default as UTF-8 is JavaScripts\n            // you can see this method as a Java version of String.fromCharCode\n            const e = encoding ? encoding.getName() : this.ISO88591;\n            // use passed format (fromCharCode will return UTF8 encoding)\n            return StringEncoding.decode(new Uint8Array([code]), e);\n        }\n        /**\n         * @param bytes bytes encoding a string, whose encoding should be guessed\n         * @param hints decode hints if applicable\n         * @return name of guessed encoding; at the moment will only guess one of:\n         *  {@link #SHIFT_JIS}, {@link #UTF8}, {@link #ISO88591}, or the platform\n         *  default encoding if none of these can possibly be correct\n         */\n        static guessEncoding(bytes, hints) {\n            if (hints !== null && hints !== undefined && undefined !== hints.get(DecodeHintType$1.CHARACTER_SET)) {\n                return hints.get(DecodeHintType$1.CHARACTER_SET).toString();\n            }\n            // For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS,\n            // which should be by far the most common encodings.\n            const length = bytes.length;\n            let canBeISO88591 = true;\n            let canBeShiftJIS = true;\n            let canBeUTF8 = true;\n            let utf8BytesLeft = 0;\n            // int utf8LowChars = 0\n            let utf2BytesChars = 0;\n            let utf3BytesChars = 0;\n            let utf4BytesChars = 0;\n            let sjisBytesLeft = 0;\n            // int sjisLowChars = 0\n            let sjisKatakanaChars = 0;\n            // int sjisDoubleBytesChars = 0\n            let sjisCurKatakanaWordLength = 0;\n            let sjisCurDoubleBytesWordLength = 0;\n            let sjisMaxKatakanaWordLength = 0;\n            let sjisMaxDoubleBytesWordLength = 0;\n            // int isoLowChars = 0\n            // int isoHighChars = 0\n            let isoHighOther = 0;\n            const utf8bom = bytes.length > 3 &&\n                bytes[0] === /*(byte) */ 0xEF &&\n                bytes[1] === /*(byte) */ 0xBB &&\n                bytes[2] === /*(byte) */ 0xBF;\n            for (let i = 0; i < length && (canBeISO88591 || canBeShiftJIS || canBeUTF8); i++) {\n                const value = bytes[i] & 0xFF;\n                // UTF-8 stuff\n                if (canBeUTF8) {\n                    if (utf8BytesLeft > 0) {\n                        if ((value & 0x80) === 0) {\n                            canBeUTF8 = false;\n                        }\n                        else {\n                            utf8BytesLeft--;\n                        }\n                    }\n                    else if ((value & 0x80) !== 0) {\n                        if ((value & 0x40) === 0) {\n                            canBeUTF8 = false;\n                        }\n                        else {\n                            utf8BytesLeft++;\n                            if ((value & 0x20) === 0) {\n                                utf2BytesChars++;\n                            }\n                            else {\n                                utf8BytesLeft++;\n                                if ((value & 0x10) === 0) {\n                                    utf3BytesChars++;\n                                }\n                                else {\n                                    utf8BytesLeft++;\n                                    if ((value & 0x08) === 0) {\n                                        utf4BytesChars++;\n                                    }\n                                    else {\n                                        canBeUTF8 = false;\n                                    }\n                                }\n                            }\n                        }\n                    } // else {\n                    // utf8LowChars++\n                    // }\n                }\n                // ISO-8859-1 stuff\n                if (canBeISO88591) {\n                    if (value > 0x7F && value < 0xA0) {\n                        canBeISO88591 = false;\n                    }\n                    else if (value > 0x9F) {\n                        if (value < 0xC0 || value === 0xD7 || value === 0xF7) {\n                            isoHighOther++;\n                        } // else {\n                        // isoHighChars++\n                        // }\n                    } // else {\n                    // isoLowChars++\n                    // }\n                }\n                // Shift_JIS stuff\n                if (canBeShiftJIS) {\n                    if (sjisBytesLeft > 0) {\n                        if (value < 0x40 || value === 0x7F || value > 0xFC) {\n                            canBeShiftJIS = false;\n                        }\n                        else {\n                            sjisBytesLeft--;\n                        }\n                    }\n                    else if (value === 0x80 || value === 0xA0 || value > 0xEF) {\n                        canBeShiftJIS = false;\n                    }\n                    else if (value > 0xA0 && value < 0xE0) {\n                        sjisKatakanaChars++;\n                        sjisCurDoubleBytesWordLength = 0;\n                        sjisCurKatakanaWordLength++;\n                        if (sjisCurKatakanaWordLength > sjisMaxKatakanaWordLength) {\n                            sjisMaxKatakanaWordLength = sjisCurKatakanaWordLength;\n                        }\n                    }\n                    else if (value > 0x7F) {\n                        sjisBytesLeft++;\n                        // sjisDoubleBytesChars++\n                        sjisCurKatakanaWordLength = 0;\n                        sjisCurDoubleBytesWordLength++;\n                        if (sjisCurDoubleBytesWordLength > sjisMaxDoubleBytesWordLength) {\n                            sjisMaxDoubleBytesWordLength = sjisCurDoubleBytesWordLength;\n                        }\n                    }\n                    else {\n                        // sjisLowChars++\n                        sjisCurKatakanaWordLength = 0;\n                        sjisCurDoubleBytesWordLength = 0;\n                    }\n                }\n            }\n            if (canBeUTF8 && utf8BytesLeft > 0) {\n                canBeUTF8 = false;\n            }\n            if (canBeShiftJIS && sjisBytesLeft > 0) {\n                canBeShiftJIS = false;\n            }\n            // Easy -- if there is BOM or at least 1 valid not-single byte character (and no evidence it can't be UTF-8), done\n            if (canBeUTF8 && (utf8bom || utf2BytesChars + utf3BytesChars + utf4BytesChars > 0)) {\n                return StringUtils.UTF8;\n            }\n            // Easy -- if assuming Shift_JIS or at least 3 valid consecutive not-ascii characters (and no evidence it can't be), done\n            if (canBeShiftJIS && (StringUtils.ASSUME_SHIFT_JIS || sjisMaxKatakanaWordLength >= 3 || sjisMaxDoubleBytesWordLength >= 3)) {\n                return StringUtils.SHIFT_JIS;\n            }\n            // Distinguishing Shift_JIS and ISO-8859-1 can be a little tough for short words. The crude heuristic is:\n            // - If we saw\n            //   - only two consecutive katakana chars in the whole text, or\n            //   - at least 10% of bytes that could be \"upper\" not-alphanumeric Latin1,\n            // - then we conclude Shift_JIS, else ISO-8859-1\n            if (canBeISO88591 && canBeShiftJIS) {\n                return (sjisMaxKatakanaWordLength === 2 && sjisKatakanaChars === 2) || isoHighOther * 10 >= length\n                    ? StringUtils.SHIFT_JIS : StringUtils.ISO88591;\n            }\n            // Otherwise, try in order ISO-8859-1, Shift JIS, UTF-8 and fall back to default platform encoding\n            if (canBeISO88591) {\n                return StringUtils.ISO88591;\n            }\n            if (canBeShiftJIS) {\n                return StringUtils.SHIFT_JIS;\n            }\n            if (canBeUTF8) {\n                return StringUtils.UTF8;\n            }\n            // Otherwise, we take a wild guess with platform encoding\n            return StringUtils.PLATFORM_DEFAULT_ENCODING;\n        }\n        /**\n         *\n         * @see https://stackoverflow.com/a/13439711/4367683\n         *\n         * @param append The new string to append.\n         * @param args Argumets values to be formated.\n         */\n        static format(append, ...args) {\n            let i = -1;\n            function callback(exp, p0, p1, p2, p3, p4) {\n                if (exp === '%%')\n                    return '%';\n                if (args[++i] === undefined)\n                    return undefined;\n                exp = p2 ? parseInt(p2.substr(1)) : undefined;\n                let base = p3 ? parseInt(p3.substr(1)) : undefined;\n                let val;\n                switch (p4) {\n                    case 's':\n                        val = args[i];\n                        break;\n                    case 'c':\n                        val = args[i][0];\n                        break;\n                    case 'f':\n                        val = parseFloat(args[i]).toFixed(exp);\n                        break;\n                    case 'p':\n                        val = parseFloat(args[i]).toPrecision(exp);\n                        break;\n                    case 'e':\n                        val = parseFloat(args[i]).toExponential(exp);\n                        break;\n                    case 'x':\n                        val = parseInt(args[i]).toString(base ? base : 16);\n                        break;\n                    case 'd':\n                        val = parseFloat(parseInt(args[i], base ? base : 10).toPrecision(exp)).toFixed(0);\n                        break;\n                }\n                val = typeof val === 'object' ? JSON.stringify(val) : (+val).toString(base);\n                let size = parseInt(p1); /* padding size */\n                let ch = p1 && (p1[0] + '') === '0' ? '0' : ' '; /* isnull? */\n                while (val.length < size)\n                    val = p0 !== undefined ? val + ch : ch + val; /* isminus? */\n                return val;\n            }\n            let regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g;\n            return append.replace(regex, callback);\n        }\n        /**\n         *\n         */\n        static getBytes(str, encoding) {\n            return StringEncoding.encode(str, encoding);\n        }\n        /**\n         * Returns the charcode at the specified index or at index zero.\n         */\n        static getCharCode(str, index = 0) {\n            return str.charCodeAt(index);\n        }\n        /**\n         * Returns char for given charcode\n         */\n        static getCharAt(charCode) {\n            return String.fromCharCode(charCode);\n        }\n    }\n    StringUtils.SHIFT_JIS = CharacterSetECI.SJIS.getName(); // \"SJIS\"\n    StringUtils.GB2312 = 'GB2312';\n    StringUtils.ISO88591 = CharacterSetECI.ISO8859_1.getName(); // \"ISO8859_1\"\n    StringUtils.EUC_JP = 'EUC_JP';\n    StringUtils.UTF8 = CharacterSetECI.UTF8.getName(); // \"UTF8\"\n    StringUtils.PLATFORM_DEFAULT_ENCODING = StringUtils.UTF8; // \"UTF8\"//Charset.defaultCharset().name()\n    StringUtils.ASSUME_SHIFT_JIS = false;\n\n    class StringBuilder {\n        constructor(value = '') {\n            this.value = value;\n        }\n        enableDecoding(encoding) {\n            this.encoding = encoding;\n            return this;\n        }\n        append(s) {\n            if (typeof s === 'string') {\n                this.value += s.toString();\n            }\n            else if (this.encoding) {\n                // use passed format (fromCharCode will return UTF8 encoding)\n                this.value += StringUtils.castAsNonUtf8Char(s, this.encoding);\n            }\n            else {\n                // correctly converts from UTF-8, but not other encodings\n                this.value += String.fromCharCode(s);\n            }\n            return this;\n        }\n        appendChars(str, offset, len) {\n            for (let i = offset; offset < offset + len; i++) {\n                this.append(str[i]);\n            }\n            return this;\n        }\n        length() {\n            return this.value.length;\n        }\n        charAt(n) {\n            return this.value.charAt(n);\n        }\n        deleteCharAt(n) {\n            this.value = this.value.substr(0, n) + this.value.substring(n + 1);\n        }\n        setCharAt(n, c) {\n            this.value = this.value.substr(0, n) + c + this.value.substr(n + 1);\n        }\n        substring(start, end) {\n            return this.value.substring(start, end);\n        }\n        /**\n         * @note helper method for RSS Expanded\n         */\n        setLengthToZero() {\n            this.value = '';\n        }\n        toString() {\n            return this.value;\n        }\n        insert(n, c) {\n            this.value = this.value.substr(0, n) + c + this.value.substr(n + c.length);\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Represents a 2D matrix of bits. In function arguments below, and throughout the common\n     * module, x is the column position, and y is the row position. The ordering is always x, y.\n     * The origin is at the top-left.</p>\n     *\n     * <p>Internally the bits are represented in a 1-D array of 32-bit ints. However, each row begins\n     * with a new int. This is done intentionally so that we can copy out a row into a BitArray very\n     * efficiently.</p>\n     *\n     * <p>The ordering of bits is row-major. Within each int, the least significant bits are used first,\n     * meaning they represent lower x values. This is compatible with BitArray's implementation.</p>\n     *\n     * @author Sean Owen\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class BitMatrix /*implements Cloneable*/ {\n        /**\n         * Creates an empty square {@link BitMatrix}.\n         *\n         * @param dimension height and width\n         */\n        // public constructor(dimension: number /*int*/) {\n        //   this(dimension, dimension)\n        // }\n        /**\n         * Creates an empty {@link BitMatrix}.\n         *\n         * @param width bit matrix width\n         * @param height bit matrix height\n         */\n        // public constructor(width: number /*int*/, height: number /*int*/) {\n        //   if (width < 1 || height < 1) {\n        //     throw new IllegalArgumentException(\"Both dimensions must be greater than 0\")\n        //   }\n        //   this.width = width\n        //   this.height = height\n        //   this.rowSize = (width + 31) / 32\n        //   bits = new int[rowSize * height];\n        // }\n        constructor(width /*int*/, height /*int*/, rowSize /*int*/, bits) {\n            this.width = width;\n            this.height = height;\n            this.rowSize = rowSize;\n            this.bits = bits;\n            if (undefined === height || null === height) {\n                height = width;\n            }\n            this.height = height;\n            if (width < 1 || height < 1) {\n                throw new IllegalArgumentException('Both dimensions must be greater than 0');\n            }\n            if (undefined === rowSize || null === rowSize) {\n                rowSize = Math.floor((width + 31) / 32);\n            }\n            this.rowSize = rowSize;\n            if (undefined === bits || null === bits) {\n                this.bits = new Int32Array(this.rowSize * this.height);\n            }\n        }\n        /**\n         * Interprets a 2D array of booleans as a {@link BitMatrix}, where \"true\" means an \"on\" bit.\n         *\n         * @function parse\n         * @param image bits of the image, as a row-major 2D array. Elements are arrays representing rows\n         * @return {@link BitMatrix} representation of image\n         */\n        static parseFromBooleanArray(image) {\n            const height = image.length;\n            const width = image[0].length;\n            const bits = new BitMatrix(width, height);\n            for (let i = 0; i < height; i++) {\n                const imageI = image[i];\n                for (let j = 0; j < width; j++) {\n                    if (imageI[j]) {\n                        bits.set(j, i);\n                    }\n                }\n            }\n            return bits;\n        }\n        /**\n         *\n         * @function parse\n         * @param stringRepresentation\n         * @param setString\n         * @param unsetString\n         */\n        static parseFromString(stringRepresentation, setString, unsetString) {\n            if (stringRepresentation === null) {\n                throw new IllegalArgumentException('stringRepresentation cannot be null');\n            }\n            const bits = new Array(stringRepresentation.length);\n            let bitsPos = 0;\n            let rowStartPos = 0;\n            let rowLength = -1;\n            let nRows = 0;\n            let pos = 0;\n            while (pos < stringRepresentation.length) {\n                if (stringRepresentation.charAt(pos) === '\\n' ||\n                    stringRepresentation.charAt(pos) === '\\r') {\n                    if (bitsPos > rowStartPos) {\n                        if (rowLength === -1) {\n                            rowLength = bitsPos - rowStartPos;\n                        }\n                        else if (bitsPos - rowStartPos !== rowLength) {\n                            throw new IllegalArgumentException('row lengths do not match');\n                        }\n                        rowStartPos = bitsPos;\n                        nRows++;\n                    }\n                    pos++;\n                }\n                else if (stringRepresentation.substring(pos, pos + setString.length) === setString) {\n                    pos += setString.length;\n                    bits[bitsPos] = true;\n                    bitsPos++;\n                }\n                else if (stringRepresentation.substring(pos, pos + unsetString.length) === unsetString) {\n                    pos += unsetString.length;\n                    bits[bitsPos] = false;\n                    bitsPos++;\n                }\n                else {\n                    throw new IllegalArgumentException('illegal character encountered: ' + stringRepresentation.substring(pos));\n                }\n            }\n            // no EOL at end?\n            if (bitsPos > rowStartPos) {\n                if (rowLength === -1) {\n                    rowLength = bitsPos - rowStartPos;\n                }\n                else if (bitsPos - rowStartPos !== rowLength) {\n                    throw new IllegalArgumentException('row lengths do not match');\n                }\n                nRows++;\n            }\n            const matrix = new BitMatrix(rowLength, nRows);\n            for (let i = 0; i < bitsPos; i++) {\n                if (bits[i]) {\n                    matrix.set(Math.floor(i % rowLength), Math.floor(i / rowLength));\n                }\n            }\n            return matrix;\n        }\n        /**\n         * <p>Gets the requested bit, where true means black.</p>\n         *\n         * @param x The horizontal component (i.e. which column)\n         * @param y The vertical component (i.e. which row)\n         * @return value of given bit in matrix\n         */\n        get(x /*int*/, y /*int*/) {\n            const offset = y * this.rowSize + Math.floor(x / 32);\n            return ((this.bits[offset] >>> (x & 0x1f)) & 1) !== 0;\n        }\n        /**\n         * <p>Sets the given bit to true.</p>\n         *\n         * @param x The horizontal component (i.e. which column)\n         * @param y The vertical component (i.e. which row)\n         */\n        set(x /*int*/, y /*int*/) {\n            const offset = y * this.rowSize + Math.floor(x / 32);\n            this.bits[offset] |= (1 << (x & 0x1f)) & 0xFFFFFFFF;\n        }\n        unset(x /*int*/, y /*int*/) {\n            const offset = y * this.rowSize + Math.floor(x / 32);\n            this.bits[offset] &= ~((1 << (x & 0x1f)) & 0xFFFFFFFF);\n        }\n        /**\n         * <p>Flips the given bit.</p>\n         *\n         * @param x The horizontal component (i.e. which column)\n         * @param y The vertical component (i.e. which row)\n         */\n        flip(x /*int*/, y /*int*/) {\n            const offset = y * this.rowSize + Math.floor(x / 32);\n            this.bits[offset] ^= ((1 << (x & 0x1f)) & 0xFFFFFFFF);\n        }\n        /**\n         * Exclusive-or (XOR): Flip the bit in this {@code BitMatrix} if the corresponding\n         * mask bit is set.\n         *\n         * @param mask XOR mask\n         */\n        xor(mask) {\n            if (this.width !== mask.getWidth() || this.height !== mask.getHeight()\n                || this.rowSize !== mask.getRowSize()) {\n                throw new IllegalArgumentException('input matrix dimensions do not match');\n            }\n            const rowArray = new BitArray(Math.floor(this.width / 32) + 1);\n            const rowSize = this.rowSize;\n            const bits = this.bits;\n            for (let y = 0, height = this.height; y < height; y++) {\n                const offset = y * rowSize;\n                const row = mask.getRow(y, rowArray).getBitArray();\n                for (let x = 0; x < rowSize; x++) {\n                    bits[offset + x] ^= row[x];\n                }\n            }\n        }\n        /**\n         * Clears all bits (sets to false).\n         */\n        clear() {\n            const bits = this.bits;\n            const max = bits.length;\n            for (let i = 0; i < max; i++) {\n                bits[i] = 0;\n            }\n        }\n        /**\n         * <p>Sets a square region of the bit matrix to true.</p>\n         *\n         * @param left The horizontal position to begin at (inclusive)\n         * @param top The vertical position to begin at (inclusive)\n         * @param width The width of the region\n         * @param height The height of the region\n         */\n        setRegion(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n            if (top < 0 || left < 0) {\n                throw new IllegalArgumentException('Left and top must be nonnegative');\n            }\n            if (height < 1 || width < 1) {\n                throw new IllegalArgumentException('Height and width must be at least 1');\n            }\n            const right = left + width;\n            const bottom = top + height;\n            if (bottom > this.height || right > this.width) {\n                throw new IllegalArgumentException('The region must fit inside the matrix');\n            }\n            const rowSize = this.rowSize;\n            const bits = this.bits;\n            for (let y = top; y < bottom; y++) {\n                const offset = y * rowSize;\n                for (let x = left; x < right; x++) {\n                    bits[offset + Math.floor(x / 32)] |= ((1 << (x & 0x1f)) & 0xFFFFFFFF);\n                }\n            }\n        }\n        /**\n         * A fast method to retrieve one row of data from the matrix as a BitArray.\n         *\n         * @param y The row to retrieve\n         * @param row An optional caller-allocated BitArray, will be allocated if null or too small\n         * @return The resulting BitArray - this reference should always be used even when passing\n         *         your own row\n         */\n        getRow(y /*int*/, row) {\n            if (row === null || row === undefined || row.getSize() < this.width) {\n                row = new BitArray(this.width);\n            }\n            else {\n                row.clear();\n            }\n            const rowSize = this.rowSize;\n            const bits = this.bits;\n            const offset = y * rowSize;\n            for (let x = 0; x < rowSize; x++) {\n                row.setBulk(x * 32, bits[offset + x]);\n            }\n            return row;\n        }\n        /**\n         * @param y row to set\n         * @param row {@link BitArray} to copy from\n         */\n        setRow(y /*int*/, row) {\n            System.arraycopy(row.getBitArray(), 0, this.bits, y * this.rowSize, this.rowSize);\n        }\n        /**\n         * Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees\n         */\n        rotate180() {\n            const width = this.getWidth();\n            const height = this.getHeight();\n            let topRow = new BitArray(width);\n            let bottomRow = new BitArray(width);\n            for (let i = 0, length = Math.floor((height + 1) / 2); i < length; i++) {\n                topRow = this.getRow(i, topRow);\n                bottomRow = this.getRow(height - 1 - i, bottomRow);\n                topRow.reverse();\n                bottomRow.reverse();\n                this.setRow(i, bottomRow);\n                this.setRow(height - 1 - i, topRow);\n            }\n        }\n        /**\n         * This is useful in detecting the enclosing rectangle of a 'pure' barcode.\n         *\n         * @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white\n         */\n        getEnclosingRectangle() {\n            const width = this.width;\n            const height = this.height;\n            const rowSize = this.rowSize;\n            const bits = this.bits;\n            let left = width;\n            let top = height;\n            let right = -1;\n            let bottom = -1;\n            for (let y = 0; y < height; y++) {\n                for (let x32 = 0; x32 < rowSize; x32++) {\n                    const theBits = bits[y * rowSize + x32];\n                    if (theBits !== 0) {\n                        if (y < top) {\n                            top = y;\n                        }\n                        if (y > bottom) {\n                            bottom = y;\n                        }\n                        if (x32 * 32 < left) {\n                            let bit = 0;\n                            while (((theBits << (31 - bit)) & 0xFFFFFFFF) === 0) {\n                                bit++;\n                            }\n                            if ((x32 * 32 + bit) < left) {\n                                left = x32 * 32 + bit;\n                            }\n                        }\n                        if (x32 * 32 + 31 > right) {\n                            let bit = 31;\n                            while ((theBits >>> bit) === 0) {\n                                bit--;\n                            }\n                            if ((x32 * 32 + bit) > right) {\n                                right = x32 * 32 + bit;\n                            }\n                        }\n                    }\n                }\n            }\n            if (right < left || bottom < top) {\n                return null;\n            }\n            return Int32Array.from([left, top, right - left + 1, bottom - top + 1]);\n        }\n        /**\n         * This is useful in detecting a corner of a 'pure' barcode.\n         *\n         * @return {@code x,y} coordinate of top-left-most 1 bit, or null if it is all white\n         */\n        getTopLeftOnBit() {\n            const rowSize = this.rowSize;\n            const bits = this.bits;\n            let bitsOffset = 0;\n            while (bitsOffset < bits.length && bits[bitsOffset] === 0) {\n                bitsOffset++;\n            }\n            if (bitsOffset === bits.length) {\n                return null;\n            }\n            const y = bitsOffset / rowSize;\n            let x = (bitsOffset % rowSize) * 32;\n            const theBits = bits[bitsOffset];\n            let bit = 0;\n            while (((theBits << (31 - bit)) & 0xFFFFFFFF) === 0) {\n                bit++;\n            }\n            x += bit;\n            return Int32Array.from([x, y]);\n        }\n        getBottomRightOnBit() {\n            const rowSize = this.rowSize;\n            const bits = this.bits;\n            let bitsOffset = bits.length - 1;\n            while (bitsOffset >= 0 && bits[bitsOffset] === 0) {\n                bitsOffset--;\n            }\n            if (bitsOffset < 0) {\n                return null;\n            }\n            const y = Math.floor(bitsOffset / rowSize);\n            let x = Math.floor(bitsOffset % rowSize) * 32;\n            const theBits = bits[bitsOffset];\n            let bit = 31;\n            while ((theBits >>> bit) === 0) {\n                bit--;\n            }\n            x += bit;\n            return Int32Array.from([x, y]);\n        }\n        /**\n         * @return The width of the matrix\n         */\n        getWidth() {\n            return this.width;\n        }\n        /**\n         * @return The height of the matrix\n         */\n        getHeight() {\n            return this.height;\n        }\n        /**\n         * @return The row size of the matrix\n         */\n        getRowSize() {\n            return this.rowSize;\n        }\n        /*@Override*/\n        equals(o) {\n            if (!(o instanceof BitMatrix)) {\n                return false;\n            }\n            const other = o;\n            return this.width === other.width && this.height === other.height && this.rowSize === other.rowSize &&\n                Arrays.equals(this.bits, other.bits);\n        }\n        /*@Override*/\n        hashCode() {\n            let hash = this.width;\n            hash = 31 * hash + this.width;\n            hash = 31 * hash + this.height;\n            hash = 31 * hash + this.rowSize;\n            hash = 31 * hash + Arrays.hashCode(this.bits);\n            return hash;\n        }\n        /**\n         * @return string representation using \"X\" for set and \" \" for unset bits\n         */\n        /*@Override*/\n        // public toString(): string {\n        //   return toString(\": \"X, \"  \")\n        // }\n        /**\n         * @param setString representation of a set bit\n         * @param unsetString representation of an unset bit\n         * @return string representation of entire matrix utilizing given strings\n         */\n        // public toString(setString: string = \"X \", unsetString: string = \"  \"): string {\n        //   return this.buildToString(setString, unsetString, \"\\n\")\n        // }\n        /**\n         * @param setString representation of a set bit\n         * @param unsetString representation of an unset bit\n         * @param lineSeparator newline character in string representation\n         * @return string representation of entire matrix utilizing given strings and line separator\n         * @deprecated call {@link #toString(String,String)} only, which uses \\n line separator always\n         */\n        // @Deprecated\n        toString(setString = 'X ', unsetString = '  ', lineSeparator = '\\n') {\n            return this.buildToString(setString, unsetString, lineSeparator);\n        }\n        buildToString(setString, unsetString, lineSeparator) {\n            let result = new StringBuilder();\n            // result.append(lineSeparator);\n            for (let y = 0, height = this.height; y < height; y++) {\n                for (let x = 0, width = this.width; x < width; x++) {\n                    result.append(this.get(x, y) ? setString : unsetString);\n                }\n                result.append(lineSeparator);\n            }\n            return result.toString();\n        }\n        /*@Override*/\n        clone() {\n            return new BitMatrix(this.width, this.height, this.rowSize, this.bits.slice());\n        }\n    }\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class NotFoundException extends Exception {\n        static getNotFoundInstance() {\n            return new NotFoundException();\n        }\n    }\n    NotFoundException.kind = 'NotFoundException';\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * This Binarizer implementation uses the old ZXing global histogram approach. It is suitable\n     * for low-end mobile devices which don't have enough CPU or memory to use a local thresholding\n     * algorithm. However, because it picks a global black point, it cannot handle difficult shadows\n     * and gradients.\n     *\n     * Faster mobile devices and all desktop applications should probably use HybridBinarizer instead.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @author Sean Owen\n     */\n    class GlobalHistogramBinarizer extends Binarizer {\n        constructor(source) {\n            super(source);\n            this.luminances = GlobalHistogramBinarizer.EMPTY;\n            this.buckets = new Int32Array(GlobalHistogramBinarizer.LUMINANCE_BUCKETS);\n        }\n        // Applies simple sharpening to the row data to improve performance of the 1D Readers.\n        /*@Override*/\n        getBlackRow(y /*int*/, row) {\n            const source = this.getLuminanceSource();\n            const width = source.getWidth();\n            if (row === undefined || row === null || row.getSize() < width) {\n                row = new BitArray(width);\n            }\n            else {\n                row.clear();\n            }\n            this.initArrays(width);\n            const localLuminances = source.getRow(y, this.luminances);\n            const localBuckets = this.buckets;\n            for (let x = 0; x < width; x++) {\n                localBuckets[(localLuminances[x] & 0xff) >> GlobalHistogramBinarizer.LUMINANCE_SHIFT]++;\n            }\n            const blackPoint = GlobalHistogramBinarizer.estimateBlackPoint(localBuckets);\n            if (width < 3) {\n                // Special case for very small images\n                for (let x = 0; x < width; x++) {\n                    if ((localLuminances[x] & 0xff) < blackPoint) {\n                        row.set(x);\n                    }\n                }\n            }\n            else {\n                let left = localLuminances[0] & 0xff;\n                let center = localLuminances[1] & 0xff;\n                for (let x = 1; x < width - 1; x++) {\n                    const right = localLuminances[x + 1] & 0xff;\n                    // A simple -1 4 -1 box filter with a weight of 2.\n                    if (((center * 4) - left - right) / 2 < blackPoint) {\n                        row.set(x);\n                    }\n                    left = center;\n                    center = right;\n                }\n            }\n            return row;\n        }\n        // Does not sharpen the data, as this call is intended to only be used by 2D Readers.\n        /*@Override*/\n        getBlackMatrix() {\n            const source = this.getLuminanceSource();\n            const width = source.getWidth();\n            const height = source.getHeight();\n            const matrix = new BitMatrix(width, height);\n            // Quickly calculates the histogram by sampling four rows from the image. This proved to be\n            // more robust on the blackbox tests than sampling a diagonal as we used to do.\n            this.initArrays(width);\n            const localBuckets = this.buckets;\n            for (let y = 1; y < 5; y++) {\n                const row = Math.floor((height * y) / 5);\n                const localLuminances = source.getRow(row, this.luminances);\n                const right = Math.floor((width * 4) / 5);\n                for (let x = Math.floor(width / 5); x < right; x++) {\n                    const pixel = localLuminances[x] & 0xff;\n                    localBuckets[pixel >> GlobalHistogramBinarizer.LUMINANCE_SHIFT]++;\n                }\n            }\n            const blackPoint = GlobalHistogramBinarizer.estimateBlackPoint(localBuckets);\n            // We delay reading the entire image luminance until the black point estimation succeeds.\n            // Although we end up reading four rows twice, it is consistent with our motto of\n            // \"fail quickly\" which is necessary for continuous scanning.\n            const localLuminances = source.getMatrix();\n            for (let y = 0; y < height; y++) {\n                const offset = y * width;\n                for (let x = 0; x < width; x++) {\n                    const pixel = localLuminances[offset + x] & 0xff;\n                    if (pixel < blackPoint) {\n                        matrix.set(x, y);\n                    }\n                }\n            }\n            return matrix;\n        }\n        /*@Override*/\n        createBinarizer(source) {\n            return new GlobalHistogramBinarizer(source);\n        }\n        initArrays(luminanceSize /*int*/) {\n            if (this.luminances.length < luminanceSize) {\n                this.luminances = new Uint8ClampedArray(luminanceSize);\n            }\n            const buckets = this.buckets;\n            for (let x = 0; x < GlobalHistogramBinarizer.LUMINANCE_BUCKETS; x++) {\n                buckets[x] = 0;\n            }\n        }\n        static estimateBlackPoint(buckets) {\n            // Find the tallest peak in the histogram.\n            const numBuckets = buckets.length;\n            let maxBucketCount = 0;\n            let firstPeak = 0;\n            let firstPeakSize = 0;\n            for (let x = 0; x < numBuckets; x++) {\n                if (buckets[x] > firstPeakSize) {\n                    firstPeak = x;\n                    firstPeakSize = buckets[x];\n                }\n                if (buckets[x] > maxBucketCount) {\n                    maxBucketCount = buckets[x];\n                }\n            }\n            // Find the second-tallest peak which is somewhat far from the tallest peak.\n            let secondPeak = 0;\n            let secondPeakScore = 0;\n            for (let x = 0; x < numBuckets; x++) {\n                const distanceToBiggest = x - firstPeak;\n                // Encourage more distant second peaks by multiplying by square of distance.\n                const score = buckets[x] * distanceToBiggest * distanceToBiggest;\n                if (score > secondPeakScore) {\n                    secondPeak = x;\n                    secondPeakScore = score;\n                }\n            }\n            // Make sure firstPeak corresponds to the black peak.\n            if (firstPeak > secondPeak) {\n                const temp = firstPeak;\n                firstPeak = secondPeak;\n                secondPeak = temp;\n            }\n            // If there is too little contrast in the image to pick a meaningful black point, throw rather\n            // than waste time trying to decode the image, and risk false positives.\n            if (secondPeak - firstPeak <= numBuckets / 16) {\n                throw new NotFoundException();\n            }\n            // Find a valley between them that is low and closer to the white peak.\n            let bestValley = secondPeak - 1;\n            let bestValleyScore = -1;\n            for (let x = secondPeak - 1; x > firstPeak; x--) {\n                const fromFirst = x - firstPeak;\n                const score = fromFirst * fromFirst * (secondPeak - x) * (maxBucketCount - buckets[x]);\n                if (score > bestValleyScore) {\n                    bestValley = x;\n                    bestValleyScore = score;\n                }\n            }\n            return bestValley << GlobalHistogramBinarizer.LUMINANCE_SHIFT;\n        }\n    }\n    GlobalHistogramBinarizer.LUMINANCE_BITS = 5;\n    GlobalHistogramBinarizer.LUMINANCE_SHIFT = 8 - GlobalHistogramBinarizer.LUMINANCE_BITS;\n    GlobalHistogramBinarizer.LUMINANCE_BUCKETS = 1 << GlobalHistogramBinarizer.LUMINANCE_BITS;\n    GlobalHistogramBinarizer.EMPTY = Uint8ClampedArray.from([0]);\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * This class implements a local thresholding algorithm, which while slower than the\n     * GlobalHistogramBinarizer, is fairly efficient for what it does. It is designed for\n     * high frequency images of barcodes with black data on white backgrounds. For this application,\n     * it does a much better job than a global blackpoint with severe shadows and gradients.\n     * However it tends to produce artifacts on lower frequency images and is therefore not\n     * a good general purpose binarizer for uses outside ZXing.\n     *\n     * This class extends GlobalHistogramBinarizer, using the older histogram approach for 1D readers,\n     * and the newer local approach for 2D readers. 1D decoding using a per-row histogram is already\n     * inherently local, and only fails for horizontal gradients. We can revisit that problem later,\n     * but for now it was not a win to use local blocks for 1D.\n     *\n     * This Binarizer is the default for the unit tests and the recommended class for library users.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class HybridBinarizer extends GlobalHistogramBinarizer {\n        constructor(source) {\n            super(source);\n            this.matrix = null;\n        }\n        /**\n         * Calculates the final BitMatrix once for all requests. This could be called once from the\n         * constructor instead, but there are some advantages to doing it lazily, such as making\n         * profiling easier, and not doing heavy lifting when callers don't expect it.\n         */\n        /*@Override*/\n        getBlackMatrix() {\n            if (this.matrix !== null) {\n                return this.matrix;\n            }\n            const source = this.getLuminanceSource();\n            const width = source.getWidth();\n            const height = source.getHeight();\n            if (width >= HybridBinarizer.MINIMUM_DIMENSION && height >= HybridBinarizer.MINIMUM_DIMENSION) {\n                const luminances = source.getMatrix();\n                let subWidth = width >> HybridBinarizer.BLOCK_SIZE_POWER;\n                if ((width & HybridBinarizer.BLOCK_SIZE_MASK) !== 0) {\n                    subWidth++;\n                }\n                let subHeight = height >> HybridBinarizer.BLOCK_SIZE_POWER;\n                if ((height & HybridBinarizer.BLOCK_SIZE_MASK) !== 0) {\n                    subHeight++;\n                }\n                const blackPoints = HybridBinarizer.calculateBlackPoints(luminances, subWidth, subHeight, width, height);\n                const newMatrix = new BitMatrix(width, height);\n                HybridBinarizer.calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix);\n                this.matrix = newMatrix;\n            }\n            else {\n                // If the image is too small, fall back to the global histogram approach.\n                this.matrix = super.getBlackMatrix();\n            }\n            return this.matrix;\n        }\n        /*@Override*/\n        createBinarizer(source) {\n            return new HybridBinarizer(source);\n        }\n        /**\n         * For each block in the image, calculate the average black point using a 5x5 grid\n         * of the blocks around it. Also handles the corner cases (fractional blocks are computed based\n         * on the last pixels in the row/column which are also used in the previous block).\n         */\n        static calculateThresholdForBlock(luminances, subWidth /*int*/, subHeight /*int*/, width /*int*/, height /*int*/, blackPoints, matrix) {\n            const maxYOffset = height - HybridBinarizer.BLOCK_SIZE;\n            const maxXOffset = width - HybridBinarizer.BLOCK_SIZE;\n            for (let y = 0; y < subHeight; y++) {\n                let yoffset = y << HybridBinarizer.BLOCK_SIZE_POWER;\n                if (yoffset > maxYOffset) {\n                    yoffset = maxYOffset;\n                }\n                const top = HybridBinarizer.cap(y, 2, subHeight - 3);\n                for (let x = 0; x < subWidth; x++) {\n                    let xoffset = x << HybridBinarizer.BLOCK_SIZE_POWER;\n                    if (xoffset > maxXOffset) {\n                        xoffset = maxXOffset;\n                    }\n                    const left = HybridBinarizer.cap(x, 2, subWidth - 3);\n                    let sum = 0;\n                    for (let z = -2; z <= 2; z++) {\n                        const blackRow = blackPoints[top + z];\n                        sum += blackRow[left - 2] + blackRow[left - 1] + blackRow[left] + blackRow[left + 1] + blackRow[left + 2];\n                    }\n                    const average = sum / 25;\n                    HybridBinarizer.thresholdBlock(luminances, xoffset, yoffset, average, width, matrix);\n                }\n            }\n        }\n        static cap(value /*int*/, min /*int*/, max /*int*/) {\n            return value < min ? min : value > max ? max : value;\n        }\n        /**\n         * Applies a single threshold to a block of pixels.\n         */\n        static thresholdBlock(luminances, xoffset /*int*/, yoffset /*int*/, threshold /*int*/, stride /*int*/, matrix) {\n            for (let y = 0, offset = yoffset * stride + xoffset; y < HybridBinarizer.BLOCK_SIZE; y++, offset += stride) {\n                for (let x = 0; x < HybridBinarizer.BLOCK_SIZE; x++) {\n                    // Comparison needs to be <= so that black == 0 pixels are black even if the threshold is 0.\n                    if ((luminances[offset + x] & 0xFF) <= threshold) {\n                        matrix.set(xoffset + x, yoffset + y);\n                    }\n                }\n            }\n        }\n        /**\n         * Calculates a single black point for each block of pixels and saves it away.\n         * See the following thread for a discussion of this algorithm:\n         *  http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0\n         */\n        static calculateBlackPoints(luminances, subWidth /*int*/, subHeight /*int*/, width /*int*/, height /*int*/) {\n            const maxYOffset = height - HybridBinarizer.BLOCK_SIZE;\n            const maxXOffset = width - HybridBinarizer.BLOCK_SIZE;\n            // tslint:disable-next-line:whitespace\n            const blackPoints = new Array(subHeight); // subWidth\n            for (let y = 0; y < subHeight; y++) {\n                blackPoints[y] = new Int32Array(subWidth);\n                let yoffset = y << HybridBinarizer.BLOCK_SIZE_POWER;\n                if (yoffset > maxYOffset) {\n                    yoffset = maxYOffset;\n                }\n                for (let x = 0; x < subWidth; x++) {\n                    let xoffset = x << HybridBinarizer.BLOCK_SIZE_POWER;\n                    if (xoffset > maxXOffset) {\n                        xoffset = maxXOffset;\n                    }\n                    let sum = 0;\n                    let min = 0xFF;\n                    let max = 0;\n                    for (let yy = 0, offset = yoffset * width + xoffset; yy < HybridBinarizer.BLOCK_SIZE; yy++, offset += width) {\n                        for (let xx = 0; xx < HybridBinarizer.BLOCK_SIZE; xx++) {\n                            const pixel = luminances[offset + xx] & 0xFF;\n                            sum += pixel;\n                            // still looking for good contrast\n                            if (pixel < min) {\n                                min = pixel;\n                            }\n                            if (pixel > max) {\n                                max = pixel;\n                            }\n                        }\n                        // short-circuit min/max tests once dynamic range is met\n                        if (max - min > HybridBinarizer.MIN_DYNAMIC_RANGE) {\n                            // finish the rest of the rows quickly\n                            for (yy++, offset += width; yy < HybridBinarizer.BLOCK_SIZE; yy++, offset += width) {\n                                for (let xx = 0; xx < HybridBinarizer.BLOCK_SIZE; xx++) {\n                                    sum += luminances[offset + xx] & 0xFF;\n                                }\n                            }\n                        }\n                    }\n                    // The default estimate is the average of the values in the block.\n                    let average = sum >> (HybridBinarizer.BLOCK_SIZE_POWER * 2);\n                    if (max - min <= HybridBinarizer.MIN_DYNAMIC_RANGE) {\n                        // If variation within the block is low, assume this is a block with only light or only\n                        // dark pixels. In that case we do not want to use the average, as it would divide this\n                        // low contrast area into black and white pixels, essentially creating data out of noise.\n                        //\n                        // The default assumption is that the block is light/background. Since no estimate for\n                        // the level of dark pixels exists locally, use half the min for the block.\n                        average = min / 2;\n                        if (y > 0 && x > 0) {\n                            // Correct the \"white background\" assumption for blocks that have neighbors by comparing\n                            // the pixels in this block to the previously calculated black points. This is based on\n                            // the fact that dark barcode symbology is always surrounded by some amount of light\n                            // background for which reasonable black point estimates were made. The bp estimated at\n                            // the boundaries is used for the interior.\n                            // The (min < bp) is arbitrary but works better than other heuristics that were tried.\n                            const averageNeighborBlackPoint = (blackPoints[y - 1][x] + (2 * blackPoints[y][x - 1]) + blackPoints[y - 1][x - 1]) / 4;\n                            if (min < averageNeighborBlackPoint) {\n                                average = averageNeighborBlackPoint;\n                            }\n                        }\n                    }\n                    blackPoints[y][x] = average;\n                }\n            }\n            return blackPoints;\n        }\n    }\n    // This class uses 5x5 blocks to compute local luminance, where each block is 8x8 pixels.\n    // So this is the smallest dimension in each axis we can accept.\n    HybridBinarizer.BLOCK_SIZE_POWER = 3;\n    HybridBinarizer.BLOCK_SIZE = 1 << HybridBinarizer.BLOCK_SIZE_POWER; // ...0100...00\n    HybridBinarizer.BLOCK_SIZE_MASK = HybridBinarizer.BLOCK_SIZE - 1; // ...0011...11\n    HybridBinarizer.MINIMUM_DIMENSION = HybridBinarizer.BLOCK_SIZE * 5;\n    HybridBinarizer.MIN_DYNAMIC_RANGE = 24;\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing {*/\n    /**\n     * The purpose of this class hierarchy is to abstract different bitmap implementations across\n     * platforms into a standard interface for requesting greyscale luminance values. The interface\n     * only provides immutable methods; therefore crop and rotation create copies. This is to ensure\n     * that one Reader does not modify the original luminance source and leave it in an unknown state\n     * for other Readers in the chain.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class LuminanceSource {\n        constructor(width /*int*/, height /*int*/) {\n            this.width = width;\n            this.height = height;\n        }\n        /**\n         * @return The width of the bitmap.\n         */\n        getWidth() {\n            return this.width;\n        }\n        /**\n         * @return The height of the bitmap.\n         */\n        getHeight() {\n            return this.height;\n        }\n        /**\n         * @return Whether this subclass supports cropping.\n         */\n        isCropSupported() {\n            return false;\n        }\n        /**\n         * Returns a new object with cropped image data. Implementations may keep a reference to the\n         * original data rather than a copy. Only callable if isCropSupported() is true.\n         *\n         * @param left The left coordinate, which must be in [0,getWidth())\n         * @param top The top coordinate, which must be in [0,getHeight())\n         * @param width The width of the rectangle to crop.\n         * @param height The height of the rectangle to crop.\n         * @return A cropped version of this object.\n         */\n        crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n            throw new UnsupportedOperationException('This luminance source does not support cropping.');\n        }\n        /**\n         * @return Whether this subclass supports counter-clockwise rotation.\n         */\n        isRotateSupported() {\n            return false;\n        }\n        /**\n         * Returns a new object with rotated image data by 90 degrees counterclockwise.\n         * Only callable if {@link #isRotateSupported()} is true.\n         *\n         * @return A rotated version of this object.\n         */\n        rotateCounterClockwise() {\n            throw new UnsupportedOperationException('This luminance source does not support rotation by 90 degrees.');\n        }\n        /**\n         * Returns a new object with rotated image data by 45 degrees counterclockwise.\n         * Only callable if {@link #isRotateSupported()} is true.\n         *\n         * @return A rotated version of this object.\n         */\n        rotateCounterClockwise45() {\n            throw new UnsupportedOperationException('This luminance source does not support rotation by 45 degrees.');\n        }\n        /*@Override*/\n        toString() {\n            const row = new Uint8ClampedArray(this.width);\n            let result = new StringBuilder();\n            for (let y = 0; y < this.height; y++) {\n                const sourceRow = this.getRow(y, row);\n                for (let x = 0; x < this.width; x++) {\n                    const luminance = sourceRow[x] & 0xFF;\n                    let c;\n                    if (luminance < 0x40) {\n                        c = '#';\n                    }\n                    else if (luminance < 0x80) {\n                        c = '+';\n                    }\n                    else if (luminance < 0xC0) {\n                        c = '.';\n                    }\n                    else {\n                        c = ' ';\n                    }\n                    result.append(c);\n                }\n                result.append('\\n');\n            }\n            return result.toString();\n        }\n    }\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing {*/\n    /**\n     * A wrapper implementation of {@link LuminanceSource} which inverts the luminances it returns -- black becomes\n     * white and vice versa, and each value becomes (255-value).\n     *\n     * @author Sean Owen\n     */\n    class InvertedLuminanceSource extends LuminanceSource {\n        constructor(delegate) {\n            super(delegate.getWidth(), delegate.getHeight());\n            this.delegate = delegate;\n        }\n        /*@Override*/\n        getRow(y /*int*/, row) {\n            const sourceRow = this.delegate.getRow(y, row);\n            const width = this.getWidth();\n            for (let i = 0; i < width; i++) {\n                sourceRow[i] = /*(byte)*/ (255 - (sourceRow[i] & 0xFF));\n            }\n            return sourceRow;\n        }\n        /*@Override*/\n        getMatrix() {\n            const matrix = this.delegate.getMatrix();\n            const length = this.getWidth() * this.getHeight();\n            const invertedMatrix = new Uint8ClampedArray(length);\n            for (let i = 0; i < length; i++) {\n                invertedMatrix[i] = /*(byte)*/ (255 - (matrix[i] & 0xFF));\n            }\n            return invertedMatrix;\n        }\n        /*@Override*/\n        isCropSupported() {\n            return this.delegate.isCropSupported();\n        }\n        /*@Override*/\n        crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n            return new InvertedLuminanceSource(this.delegate.crop(left, top, width, height));\n        }\n        /*@Override*/\n        isRotateSupported() {\n            return this.delegate.isRotateSupported();\n        }\n        /**\n         * @return original delegate {@link LuminanceSource} since invert undoes itself\n         */\n        /*@Override*/\n        invert() {\n            return this.delegate;\n        }\n        /*@Override*/\n        rotateCounterClockwise() {\n            return new InvertedLuminanceSource(this.delegate.rotateCounterClockwise());\n        }\n        /*@Override*/\n        rotateCounterClockwise45() {\n            return new InvertedLuminanceSource(this.delegate.rotateCounterClockwise45());\n        }\n    }\n\n    /**\n     * @deprecated Moving to @zxing/browser\n     */\n    class HTMLCanvasElementLuminanceSource extends LuminanceSource {\n        constructor(canvas) {\n            super(canvas.width, canvas.height);\n            this.canvas = canvas;\n            this.tempCanvasElement = null;\n            this.buffer = HTMLCanvasElementLuminanceSource.makeBufferFromCanvasImageData(canvas);\n        }\n        static makeBufferFromCanvasImageData(canvas) {\n            const imageData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);\n            return HTMLCanvasElementLuminanceSource.toGrayscaleBuffer(imageData.data, canvas.width, canvas.height);\n        }\n        static toGrayscaleBuffer(imageBuffer, width, height) {\n            const grayscaleBuffer = new Uint8ClampedArray(width * height);\n            for (let i = 0, j = 0, length = imageBuffer.length; i < length; i += 4, j++) {\n                let gray;\n                const alpha = imageBuffer[i + 3];\n                // The color of fully-transparent pixels is irrelevant. They are often, technically, fully-transparent\n                // black (0 alpha, and then 0 RGB). They are often used, of course as the \"white\" area in a\n                // barcode image. Force any such pixel to be white:\n                if (alpha === 0) {\n                    gray = 0xFF;\n                }\n                else {\n                    const pixelR = imageBuffer[i];\n                    const pixelG = imageBuffer[i + 1];\n                    const pixelB = imageBuffer[i + 2];\n                    // .299R + 0.587G + 0.114B (YUV/YIQ for PAL and NTSC),\n                    // (306*R) >> 10 is approximately equal to R*0.299, and so on.\n                    // 0x200 >> 10 is 0.5, it implements rounding.\n                    gray = (306 * pixelR +\n                        601 * pixelG +\n                        117 * pixelB +\n                        0x200) >> 10;\n                }\n                grayscaleBuffer[j] = gray;\n            }\n            return grayscaleBuffer;\n        }\n        getRow(y /*int*/, row) {\n            if (y < 0 || y >= this.getHeight()) {\n                throw new IllegalArgumentException('Requested row is outside the image: ' + y);\n            }\n            const width = this.getWidth();\n            const start = y * width;\n            if (row === null) {\n                row = this.buffer.slice(start, start + width);\n            }\n            else {\n                if (row.length < width) {\n                    row = new Uint8ClampedArray(width);\n                }\n                // The underlying raster of image consists of bytes with the luminance values\n                // TODO: can avoid set/slice?\n                row.set(this.buffer.slice(start, start + width));\n            }\n            return row;\n        }\n        getMatrix() {\n            return this.buffer;\n        }\n        isCropSupported() {\n            return true;\n        }\n        crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n            super.crop(left, top, width, height);\n            return this;\n        }\n        /**\n         * This is always true, since the image is a gray-scale image.\n         *\n         * @return true\n         */\n        isRotateSupported() {\n            return true;\n        }\n        rotateCounterClockwise() {\n            this.rotate(-90);\n            return this;\n        }\n        rotateCounterClockwise45() {\n            this.rotate(-45);\n            return this;\n        }\n        getTempCanvasElement() {\n            if (null === this.tempCanvasElement) {\n                const tempCanvasElement = this.canvas.ownerDocument.createElement('canvas');\n                tempCanvasElement.width = this.canvas.width;\n                tempCanvasElement.height = this.canvas.height;\n                this.tempCanvasElement = tempCanvasElement;\n            }\n            return this.tempCanvasElement;\n        }\n        rotate(angle) {\n            const tempCanvasElement = this.getTempCanvasElement();\n            const tempContext = tempCanvasElement.getContext('2d');\n            const angleRadians = angle * HTMLCanvasElementLuminanceSource.DEGREE_TO_RADIANS;\n            // Calculate and set new dimensions for temp canvas\n            const width = this.canvas.width;\n            const height = this.canvas.height;\n            const newWidth = Math.ceil(Math.abs(Math.cos(angleRadians)) * width + Math.abs(Math.sin(angleRadians)) * height);\n            const newHeight = Math.ceil(Math.abs(Math.sin(angleRadians)) * width + Math.abs(Math.cos(angleRadians)) * height);\n            tempCanvasElement.width = newWidth;\n            tempCanvasElement.height = newHeight;\n            // Draw at center of temp canvas to prevent clipping of image data\n            tempContext.translate(newWidth / 2, newHeight / 2);\n            tempContext.rotate(angleRadians);\n            tempContext.drawImage(this.canvas, width / -2, height / -2);\n            this.buffer = HTMLCanvasElementLuminanceSource.makeBufferFromCanvasImageData(tempCanvasElement);\n            return this;\n        }\n        invert() {\n            return new InvertedLuminanceSource(this);\n        }\n    }\n    HTMLCanvasElementLuminanceSource.DEGREE_TO_RADIANS = Math.PI / 180;\n\n    /**\n     * @deprecated Moving to @zxing/browser\n     *\n     * Video input device metadata containing the id and label of the device if available.\n     */\n    class VideoInputDevice {\n        /**\n         * Creates an instance of VideoInputDevice.\n         *\n         * @param {string} deviceId the video input device id\n         * @param {string} label the label of the device if available\n         */\n        constructor(deviceId, label, groupId) {\n            this.deviceId = deviceId;\n            this.label = label;\n            /** @inheritdoc */\n            this.kind = 'videoinput';\n            this.groupId = groupId || undefined;\n        }\n        /** @inheritdoc */\n        toJSON() {\n            return {\n                kind: this.kind,\n                groupId: this.groupId,\n                deviceId: this.deviceId,\n                label: this.label,\n            };\n        }\n    }\n\n    var __awaiter = ((globalThis || __webpack_require__.g || self || window || undefined) && (globalThis || __webpack_require__.g || self || window || undefined).__awaiter) || function (thisArg, _arguments, P, generator) {\n        function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n        return new (P || (P = Promise))(function (resolve, reject) {\n            function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n            function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n            function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n            step((generator = generator.apply(thisArg, _arguments || [])).next());\n        });\n    };\n    /**\n     * @deprecated Moving to @zxing/browser\n     *\n     * Base class for browser code reader.\n     */\n    class BrowserCodeReader {\n        /**\n         * Creates an instance of BrowserCodeReader.\n         * @param {Reader} reader The reader instance to decode the barcode\n         * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent successful decode tries\n         *\n         * @memberOf BrowserCodeReader\n         */\n        constructor(reader, timeBetweenScansMillis = 500, _hints) {\n            this.reader = reader;\n            this.timeBetweenScansMillis = timeBetweenScansMillis;\n            this._hints = _hints;\n            /**\n             * This will break the loop.\n             */\n            this._stopContinuousDecode = false;\n            /**\n             * This will break the loop.\n             */\n            this._stopAsyncDecode = false;\n            /**\n             * Delay time between decode attempts made by the scanner.\n             */\n            this._timeBetweenDecodingAttempts = 0;\n        }\n        /**\n         * If navigator is present.\n         */\n        get hasNavigator() {\n            return typeof navigator !== 'undefined';\n        }\n        /**\n         * If mediaDevices under navigator is supported.\n         */\n        get isMediaDevicesSuported() {\n            return this.hasNavigator && !!navigator.mediaDevices;\n        }\n        /**\n         * If enumerateDevices under navigator is supported.\n         */\n        get canEnumerateDevices() {\n            return !!(this.isMediaDevicesSuported && navigator.mediaDevices.enumerateDevices);\n        }\n        /** Time between two decoding tries in milli seconds. */\n        get timeBetweenDecodingAttempts() {\n            return this._timeBetweenDecodingAttempts;\n        }\n        /**\n         * Change the time span the decoder waits between two decoding tries.\n         *\n         * @param {number} millis Time between two decoding tries in milli seconds.\n         */\n        set timeBetweenDecodingAttempts(millis) {\n            this._timeBetweenDecodingAttempts = millis < 0 ? 0 : millis;\n        }\n        /**\n         * Sets the hints.\n         */\n        set hints(hints) {\n            this._hints = hints || null;\n        }\n        /**\n         * Sets the hints.\n         */\n        get hints() {\n            return this._hints;\n        }\n        /**\n         * Lists all the available video input devices.\n         */\n        listVideoInputDevices() {\n            return __awaiter(this, void 0, void 0, function* () {\n                if (!this.hasNavigator) {\n                    throw new Error('Can\\'t enumerate devices, navigator is not present.');\n                }\n                if (!this.canEnumerateDevices) {\n                    throw new Error('Can\\'t enumerate devices, method not supported.');\n                }\n                const devices = yield navigator.mediaDevices.enumerateDevices();\n                const videoDevices = [];\n                for (const device of devices) {\n                    const kind = device.kind === 'video' ? 'videoinput' : device.kind;\n                    if (kind !== 'videoinput') {\n                        continue;\n                    }\n                    const deviceId = device.deviceId || device.id;\n                    const label = device.label || `Video device ${videoDevices.length + 1}`;\n                    const groupId = device.groupId;\n                    const videoDevice = { deviceId, label, kind, groupId };\n                    videoDevices.push(videoDevice);\n                }\n                return videoDevices;\n            });\n        }\n        /**\n         * Obtain the list of available devices with type 'videoinput'.\n         *\n         * @returns {Promise<VideoInputDevice[]>} an array of available video input devices\n         *\n         * @memberOf BrowserCodeReader\n         *\n         * @deprecated Use `listVideoInputDevices` instead.\n         */\n        getVideoInputDevices() {\n            return __awaiter(this, void 0, void 0, function* () {\n                const devices = yield this.listVideoInputDevices();\n                return devices.map(d => new VideoInputDevice(d.deviceId, d.label));\n            });\n        }\n        /**\n         * Let's you find a device using it's Id.\n         */\n        findDeviceById(deviceId) {\n            return __awaiter(this, void 0, void 0, function* () {\n                const devices = yield this.listVideoInputDevices();\n                if (!devices) {\n                    return null;\n                }\n                return devices.find(x => x.deviceId === deviceId);\n            });\n        }\n        /**\n         * Decodes the barcode from the device specified by deviceId while showing the video in the specified video element.\n         *\n         * @param deviceId the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available.\n         * @param video the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n         * @returns The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         *\n         * @deprecated Use `decodeOnceFromVideoDevice` instead.\n         */\n        decodeFromInputVideoDevice(deviceId, videoSource) {\n            return __awaiter(this, void 0, void 0, function* () {\n                return yield this.decodeOnceFromVideoDevice(deviceId, videoSource);\n            });\n        }\n        /**\n         * In one attempt, tries to decode the barcode from the device specified by deviceId while showing the video in the specified video element.\n         *\n         * @param deviceId the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available.\n         * @param video the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n         * @returns The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         */\n        decodeOnceFromVideoDevice(deviceId, videoSource) {\n            return __awaiter(this, void 0, void 0, function* () {\n                this.reset();\n                let videoConstraints;\n                if (!deviceId) {\n                    videoConstraints = { facingMode: 'environment' };\n                }\n                else {\n                    videoConstraints = { deviceId: { exact: deviceId } };\n                }\n                const constraints = { video: videoConstraints };\n                return yield this.decodeOnceFromConstraints(constraints, videoSource);\n            });\n        }\n        /**\n         * In one attempt, tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.\n         *\n         * @param constraints the media stream constraints to get s valid media stream to decode from\n         * @param video the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n         * @returns The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         */\n        decodeOnceFromConstraints(constraints, videoSource) {\n            return __awaiter(this, void 0, void 0, function* () {\n                const stream = yield navigator.mediaDevices.getUserMedia(constraints);\n                return yield this.decodeOnceFromStream(stream, videoSource);\n            });\n        }\n        /**\n         * In one attempt, tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.\n         *\n         * @param {MediaStream} [constraints] the media stream constraints to get s valid media stream to decode from\n         * @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n         * @returns {Promise<Result>} The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         */\n        decodeOnceFromStream(stream, videoSource) {\n            return __awaiter(this, void 0, void 0, function* () {\n                this.reset();\n                const video = yield this.attachStreamToVideo(stream, videoSource);\n                const result = yield this.decodeOnce(video);\n                return result;\n            });\n        }\n        /**\n         * Continuously decodes the barcode from the device specified by device while showing the video in the specified video element.\n         *\n         * @param {string|null} [deviceId] the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available.\n         * @param {string|HTMLVideoElement|null} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n         * @returns {Promise<void>}\n         *\n         * @memberOf BrowserCodeReader\n         *\n         * @deprecated Use `decodeFromVideoDevice` instead.\n         */\n        decodeFromInputVideoDeviceContinuously(deviceId, videoSource, callbackFn) {\n            return __awaiter(this, void 0, void 0, function* () {\n                return yield this.decodeFromVideoDevice(deviceId, videoSource, callbackFn);\n            });\n        }\n        /**\n         * Continuously tries to decode the barcode from the device specified by device while showing the video in the specified video element.\n         *\n         * @param {string|null} [deviceId] the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available.\n         * @param {string|HTMLVideoElement|null} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n         * @returns {Promise<void>}\n         *\n         * @memberOf BrowserCodeReader\n         */\n        decodeFromVideoDevice(deviceId, videoSource, callbackFn) {\n            return __awaiter(this, void 0, void 0, function* () {\n                let videoConstraints;\n                if (!deviceId) {\n                    videoConstraints = { facingMode: 'environment' };\n                }\n                else {\n                    videoConstraints = { deviceId: { exact: deviceId } };\n                }\n                const constraints = { video: videoConstraints };\n                return yield this.decodeFromConstraints(constraints, videoSource, callbackFn);\n            });\n        }\n        /**\n         * Continuously tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.\n         *\n         * @param {MediaStream} [constraints] the media stream constraints to get s valid media stream to decode from\n         * @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n         * @returns {Promise<Result>} The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         */\n        decodeFromConstraints(constraints, videoSource, callbackFn) {\n            return __awaiter(this, void 0, void 0, function* () {\n                const stream = yield navigator.mediaDevices.getUserMedia(constraints);\n                return yield this.decodeFromStream(stream, videoSource, callbackFn);\n            });\n        }\n        /**\n         * In one attempt, tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.\n         *\n         * @param {MediaStream} [constraints] the media stream constraints to get s valid media stream to decode from\n         * @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n         * @returns {Promise<Result>} The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         */\n        decodeFromStream(stream, videoSource, callbackFn) {\n            return __awaiter(this, void 0, void 0, function* () {\n                this.reset();\n                const video = yield this.attachStreamToVideo(stream, videoSource);\n                return yield this.decodeContinuously(video, callbackFn);\n            });\n        }\n        /**\n         * Breaks the decoding loop.\n         */\n        stopAsyncDecode() {\n            this._stopAsyncDecode = true;\n        }\n        /**\n         * Breaks the decoding loop.\n         */\n        stopContinuousDecode() {\n            this._stopContinuousDecode = true;\n        }\n        /**\n         * Sets the new stream and request a new decoding-with-delay.\n         *\n         * @param stream The stream to be shown in the video element.\n         * @param decodeFn A callback for the decode method.\n         */\n        attachStreamToVideo(stream, videoSource) {\n            return __awaiter(this, void 0, void 0, function* () {\n                const videoElement = this.prepareVideoElement(videoSource);\n                this.addVideoSource(videoElement, stream);\n                this.videoElement = videoElement;\n                this.stream = stream;\n                yield this.playVideoOnLoadAsync(videoElement);\n                return videoElement;\n            });\n        }\n        /**\n         *\n         * @param videoElement\n         */\n        playVideoOnLoadAsync(videoElement) {\n            return new Promise((resolve, reject) => this.playVideoOnLoad(videoElement, () => resolve()));\n        }\n        /**\n         * Binds listeners and callbacks to the videoElement.\n         *\n         * @param element\n         * @param callbackFn\n         */\n        playVideoOnLoad(element, callbackFn) {\n            this.videoEndedListener = () => this.stopStreams();\n            this.videoCanPlayListener = () => this.tryPlayVideo(element);\n            element.addEventListener('ended', this.videoEndedListener);\n            element.addEventListener('canplay', this.videoCanPlayListener);\n            element.addEventListener('playing', callbackFn);\n            // if canplay was already fired, we won't know when to play, so just give it a try\n            this.tryPlayVideo(element);\n        }\n        /**\n         * Checks if the given video element is currently playing.\n         */\n        isVideoPlaying(video) {\n            return video.currentTime > 0 && !video.paused && !video.ended && video.readyState > 2;\n        }\n        /**\n         * Just tries to play the video and logs any errors.\n         * The play call is only made is the video is not already playing.\n         */\n        tryPlayVideo(videoElement) {\n            return __awaiter(this, void 0, void 0, function* () {\n                if (this.isVideoPlaying(videoElement)) {\n                    console.warn('Trying to play video that is already playing.');\n                    return;\n                }\n                try {\n                    yield videoElement.play();\n                }\n                catch (_a) {\n                    console.warn('It was not possible to play the video.');\n                }\n            });\n        }\n        /**\n         * Searches and validates a media element.\n         */\n        getMediaElement(mediaElementId, type) {\n            const mediaElement = document.getElementById(mediaElementId);\n            if (!mediaElement) {\n                throw new ArgumentException(`element with id '${mediaElementId}' not found`);\n            }\n            if (mediaElement.nodeName.toLowerCase() !== type.toLowerCase()) {\n                throw new ArgumentException(`element with id '${mediaElementId}' must be an ${type} element`);\n            }\n            return mediaElement;\n        }\n        /**\n         * Decodes the barcode from an image.\n         *\n         * @param {(string|HTMLImageElement)} [source] The image element that can be either an element id or the element itself. Can be undefined in which case the decoding will be done from the imageUrl parameter.\n         * @param {string} [url]\n         * @returns {Promise<Result>} The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         */\n        decodeFromImage(source, url) {\n            if (!source && !url) {\n                throw new ArgumentException('either imageElement with a src set or an url must be provided');\n            }\n            if (url && !source) {\n                return this.decodeFromImageUrl(url);\n            }\n            return this.decodeFromImageElement(source);\n        }\n        /**\n         * Decodes the barcode from a video.\n         *\n         * @param {(string|HTMLImageElement)} [source] The image element that can be either an element id or the element itself. Can be undefined in which case the decoding will be done from the imageUrl parameter.\n         * @param {string} [url]\n         * @returns {Promise<Result>} The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         */\n        decodeFromVideo(source, url) {\n            if (!source && !url) {\n                throw new ArgumentException('Either an element with a src set or an URL must be provided');\n            }\n            if (url && !source) {\n                return this.decodeFromVideoUrl(url);\n            }\n            return this.decodeFromVideoElement(source);\n        }\n        /**\n         * Decodes continuously the barcode from a video.\n         *\n         * @param {(string|HTMLImageElement)} [source] The image element that can be either an element id or the element itself. Can be undefined in which case the decoding will be done from the imageUrl parameter.\n         * @param {string} [url]\n         * @returns {Promise<Result>} The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         *\n         * @experimental\n         */\n        decodeFromVideoContinuously(source, url, callbackFn) {\n            if (undefined === source && undefined === url) {\n                throw new ArgumentException('Either an element with a src set or an URL must be provided');\n            }\n            if (url && !source) {\n                return this.decodeFromVideoUrlContinuously(url, callbackFn);\n            }\n            return this.decodeFromVideoElementContinuously(source, callbackFn);\n        }\n        /**\n         * Decodes something from an image HTML element.\n         */\n        decodeFromImageElement(source) {\n            if (!source) {\n                throw new ArgumentException('An image element must be provided.');\n            }\n            this.reset();\n            const element = this.prepareImageElement(source);\n            this.imageElement = element;\n            let task;\n            if (this.isImageLoaded(element)) {\n                task = this.decodeOnce(element, false, true);\n            }\n            else {\n                task = this._decodeOnLoadImage(element);\n            }\n            return task;\n        }\n        /**\n         * Decodes something from an image HTML element.\n         */\n        decodeFromVideoElement(source) {\n            const element = this._decodeFromVideoElementSetup(source);\n            return this._decodeOnLoadVideo(element);\n        }\n        /**\n         * Decodes something from an image HTML element.\n         */\n        decodeFromVideoElementContinuously(source, callbackFn) {\n            const element = this._decodeFromVideoElementSetup(source);\n            return this._decodeOnLoadVideoContinuously(element, callbackFn);\n        }\n        /**\n         * Sets up the video source so it can be decoded when loaded.\n         *\n         * @param source The video source element.\n         */\n        _decodeFromVideoElementSetup(source) {\n            if (!source) {\n                throw new ArgumentException('A video element must be provided.');\n            }\n            this.reset();\n            const element = this.prepareVideoElement(source);\n            // defines the video element before starts decoding\n            this.videoElement = element;\n            return element;\n        }\n        /**\n         * Decodes an image from a URL.\n         */\n        decodeFromImageUrl(url) {\n            if (!url) {\n                throw new ArgumentException('An URL must be provided.');\n            }\n            this.reset();\n            const element = this.prepareImageElement();\n            this.imageElement = element;\n            const decodeTask = this._decodeOnLoadImage(element);\n            element.src = url;\n            return decodeTask;\n        }\n        /**\n         * Decodes an image from a URL.\n         */\n        decodeFromVideoUrl(url) {\n            if (!url) {\n                throw new ArgumentException('An URL must be provided.');\n            }\n            this.reset();\n            // creates a new element\n            const element = this.prepareVideoElement();\n            const decodeTask = this.decodeFromVideoElement(element);\n            element.src = url;\n            return decodeTask;\n        }\n        /**\n         * Decodes an image from a URL.\n         *\n         * @experimental\n         */\n        decodeFromVideoUrlContinuously(url, callbackFn) {\n            if (!url) {\n                throw new ArgumentException('An URL must be provided.');\n            }\n            this.reset();\n            // creates a new element\n            const element = this.prepareVideoElement();\n            const decodeTask = this.decodeFromVideoElementContinuously(element, callbackFn);\n            element.src = url;\n            return decodeTask;\n        }\n        _decodeOnLoadImage(element) {\n            return new Promise((resolve, reject) => {\n                this.imageLoadedListener = () => this.decodeOnce(element, false, true).then(resolve, reject);\n                element.addEventListener('load', this.imageLoadedListener);\n            });\n        }\n        _decodeOnLoadVideo(videoElement) {\n            return __awaiter(this, void 0, void 0, function* () {\n                // plays the video\n                yield this.playVideoOnLoadAsync(videoElement);\n                // starts decoding after played the video\n                return yield this.decodeOnce(videoElement);\n            });\n        }\n        _decodeOnLoadVideoContinuously(videoElement, callbackFn) {\n            return __awaiter(this, void 0, void 0, function* () {\n                // plays the video\n                yield this.playVideoOnLoadAsync(videoElement);\n                // starts decoding after played the video\n                this.decodeContinuously(videoElement, callbackFn);\n            });\n        }\n        isImageLoaded(img) {\n            // During the onload event, IE correctly identifies any images that\n            // weren’t downloaded as not complete. Others should too. Gecko-based\n            // browsers act like NS4 in that they report this incorrectly.\n            if (!img.complete) {\n                return false;\n            }\n            // However, they do have two very useful properties: naturalWidth and\n            // naturalHeight. These give the true size of the image. If it failed\n            // to load, either of these should be zero.\n            if (img.naturalWidth === 0) {\n                return false;\n            }\n            // No other way of checking: assume it’s ok.\n            return true;\n        }\n        prepareImageElement(imageSource) {\n            let imageElement;\n            if (typeof imageSource === 'undefined') {\n                imageElement = document.createElement('img');\n                imageElement.width = 200;\n                imageElement.height = 200;\n            }\n            if (typeof imageSource === 'string') {\n                imageElement = this.getMediaElement(imageSource, 'img');\n            }\n            if (imageSource instanceof HTMLImageElement) {\n                imageElement = imageSource;\n            }\n            return imageElement;\n        }\n        /**\n         * Sets a HTMLVideoElement for scanning or creates a new one.\n         *\n         * @param videoSource The HTMLVideoElement to be set.\n         */\n        prepareVideoElement(videoSource) {\n            let videoElement;\n            if (!videoSource && typeof document !== 'undefined') {\n                videoElement = document.createElement('video');\n                videoElement.width = 200;\n                videoElement.height = 200;\n            }\n            if (typeof videoSource === 'string') {\n                videoElement = this.getMediaElement(videoSource, 'video');\n            }\n            if (videoSource instanceof HTMLVideoElement) {\n                videoElement = videoSource;\n            }\n            // Needed for iOS 11\n            videoElement.setAttribute('autoplay', 'true');\n            videoElement.setAttribute('muted', 'true');\n            videoElement.setAttribute('playsinline', 'true');\n            return videoElement;\n        }\n        /**\n         * Tries to decode from the video input until it finds some value.\n         */\n        decodeOnce(element, retryIfNotFound = true, retryIfChecksumOrFormatError = true) {\n            this._stopAsyncDecode = false;\n            const loop = (resolve, reject) => {\n                if (this._stopAsyncDecode) {\n                    reject(new NotFoundException('Video stream has ended before any code could be detected.'));\n                    this._stopAsyncDecode = undefined;\n                    return;\n                }\n                try {\n                    const result = this.decode(element);\n                    resolve(result);\n                }\n                catch (e) {\n                    const ifNotFound = retryIfNotFound && e instanceof NotFoundException;\n                    const isChecksumOrFormatError = e instanceof ChecksumException || e instanceof FormatException;\n                    const ifChecksumOrFormat = isChecksumOrFormatError && retryIfChecksumOrFormatError;\n                    if (ifNotFound || ifChecksumOrFormat) {\n                        // trying again\n                        return setTimeout(loop, this._timeBetweenDecodingAttempts, resolve, reject);\n                    }\n                    reject(e);\n                }\n            };\n            return new Promise((resolve, reject) => loop(resolve, reject));\n        }\n        /**\n         * Continuously decodes from video input.\n         */\n        decodeContinuously(element, callbackFn) {\n            this._stopContinuousDecode = false;\n            const loop = () => {\n                if (this._stopContinuousDecode) {\n                    this._stopContinuousDecode = undefined;\n                    return;\n                }\n                try {\n                    const result = this.decode(element);\n                    callbackFn(result, null);\n                    setTimeout(loop, this.timeBetweenScansMillis);\n                }\n                catch (e) {\n                    callbackFn(null, e);\n                    const isChecksumOrFormatError = e instanceof ChecksumException || e instanceof FormatException;\n                    const isNotFound = e instanceof NotFoundException;\n                    if (isChecksumOrFormatError || isNotFound) {\n                        // trying again\n                        setTimeout(loop, this._timeBetweenDecodingAttempts);\n                    }\n                }\n            };\n            loop();\n        }\n        /**\n         * Gets the BinaryBitmap for ya! (and decodes it)\n         */\n        decode(element) {\n            // get binary bitmap for decode function\n            const binaryBitmap = this.createBinaryBitmap(element);\n            return this.decodeBitmap(binaryBitmap);\n        }\n        /**\n         * Returns true if media element is indeed a {@link HtmlVideoElement}.\n         */\n        _isHTMLVideoElement(mediaElement) {\n            const potentialVideo = mediaElement;\n            return potentialVideo.videoWidth !== 0;\n        }\n        /**\n         * Overwriting this allows you to manipulate the next frame in anyway\n         * you want before decode.\n         */\n        drawFrameOnCanvas(\n            srcElement, dimensions, canvasElementContext) {\n            if (!dimensions) {\n                dimensions = {\n                    sx: 0,\n                    sy: 0,\n                    sWidth: srcElement.videoWidth,\n                    sHeight: srcElement.videoHeight,\n                    dx: 0,\n                    dy: 0,\n                    dWidth: srcElement.videoWidth,\n                    dHeight: srcElement.videoHeight};\n            }\n            if (!canvasElementContext) {\n                canvasElementContext = this.captureCanvasContext;\n            }\n            canvasElementContext.drawImage(\n                srcElement,\n                dimensions.sx,\n                dimensions.sy,\n                dimensions.sWidth,\n                dimensions.sHeight,\n                dimensions.dx,\n                dimensions.dy,\n                dimensions.dWidth,\n                dimensions.dHeight);\n        }\n        /**\n         * Ovewriting this allows you to manipulate the snapshot image in anyway\n         *  you want before decode.\n         */\n        drawImageOnCanvas(\n            srcElement,\n            dimensions,\n            canvasElementContext = this.captureCanvasContext) {\n            if (!dimensions) {\n                dimensions = {\n                    sx: 0,\n                    sy: 0,\n                    sWidth: srcElement.naturalWidth,\n                    sHeight: srcElement.naturalHeight,\n                    dx: 0,\n                    dy: 0,\n                    dWidth: srcElement.naturalWidth,\n                    dHeight: srcElement.naturalHeight\n                };\n            }\n            if (!canvasElementContext) {\n                canvasElementContext = this.captureCanvasContext;\n            }\n            canvasElementContext.drawImage(\n                srcElement,\n                dimensions.sx,\n                dimensions.sy,\n                dimensions.sWidth,\n                dimensions.sHeight,\n                dimensions.dx,\n                dimensions.dy,\n                dimensions.dWidth,\n                dimensions.dHeight);\n        }\n        /**\n         * Creates a binaryBitmap based in some image source.\n         *\n         * @param mediaElement HTML element containing drawable image source.\n         */\n        createBinaryBitmap(mediaElement) {\n            const ctx = this.getCaptureCanvasContext(mediaElement);\n            if (this._isHTMLVideoElement(mediaElement)) {\n                this.drawFrameOnCanvas(mediaElement);\n            } else {\n                this.drawImageOnCanvas(mediaElement);\n            }\n            const canvas = this.getCaptureCanvas(mediaElement);\n            const luminanceSource = new HTMLCanvasElementLuminanceSource(canvas);\n            const hybridBinarizer = new HybridBinarizer(luminanceSource);\n\n            return new BinaryBitmap(hybridBinarizer);\n        }\n\n        getCaptureCanvasContext(mediaElement) {\n            if (!this.captureCanvasContext) {\n                const elem = this.getCaptureCanvas(mediaElement);\n                const ctx = elem.getContext('2d');\n                this.captureCanvasContext = ctx;\n            }\n            return this.captureCanvasContext;\n        }\n        getCaptureCanvas(mediaElement) {\n            if (!this.captureCanvas) {\n                const elem = this.createCaptureCanvas(mediaElement);\n                this.captureCanvas = elem;\n            }\n            return this.captureCanvas;\n        }\n        /**\n         * Call the encapsulated readers decode\n         */\n        decodeBitmap(binaryBitmap) {\n            return this.reader.decode(binaryBitmap, this._hints);\n        }\n        /**\n         * 🖌 Prepares the canvas for capture and scan frames.\n         */\n        createCaptureCanvas(mediaElement) {\n            if (typeof document === 'undefined') {\n                this._destroyCaptureCanvas();\n                return null;\n            }\n            const canvasElement = document.createElement('canvas');\n            let width;\n            let height;\n            if (typeof mediaElement !== 'undefined') {\n                if (mediaElement instanceof HTMLVideoElement) {\n                    width = mediaElement.videoWidth;\n                    height = mediaElement.videoHeight;\n                }\n                else if (mediaElement instanceof HTMLImageElement) {\n                    width = mediaElement.naturalWidth || mediaElement.width;\n                    height = mediaElement.naturalHeight || mediaElement.height;\n                }\n            }\n            canvasElement.style.width = width + 'px';\n            canvasElement.style.height = height + 'px';\n            canvasElement.width = width;\n            canvasElement.height = height;\n            return canvasElement;\n        }\n        /**\n         * Stops the continuous scan and cleans the stream.\n         */\n        stopStreams() {\n            if (this.stream) {\n                this.stream.getVideoTracks().forEach(t => t.stop());\n                this.stream = undefined;\n            }\n            if (this._stopAsyncDecode === false) {\n                this.stopAsyncDecode();\n            }\n            if (this._stopContinuousDecode === false) {\n                this.stopContinuousDecode();\n            }\n        }\n        /**\n         * Resets the code reader to the initial state. Cancels any ongoing barcode scanning from video or camera.\n         *\n         * @memberOf BrowserCodeReader\n         */\n        reset() {\n            // stops the camera, preview and scan 🔴\n            this.stopStreams();\n            // clean and forget about HTML elements\n            this._destroyVideoElement();\n            this._destroyImageElement();\n            this._destroyCaptureCanvas();\n        }\n        _destroyVideoElement() {\n            if (!this.videoElement) {\n                return;\n            }\n            // first gives freedon to the element 🕊\n            if (typeof this.videoEndedListener !== 'undefined') {\n                this.videoElement.removeEventListener('ended', this.videoEndedListener);\n            }\n            if (typeof this.videoPlayingEventListener !== 'undefined') {\n                this.videoElement.removeEventListener('playing', this.videoPlayingEventListener);\n            }\n            if (typeof this.videoCanPlayListener !== 'undefined') {\n                this.videoElement.removeEventListener('loadedmetadata', this.videoCanPlayListener);\n            }\n            // then forgets about that element 😢\n            this.cleanVideoSource(this.videoElement);\n            this.videoElement = undefined;\n        }\n        _destroyImageElement() {\n            if (!this.imageElement) {\n                return;\n            }\n            // first gives freedon to the element 🕊\n            if (undefined !== this.imageLoadedListener) {\n                this.imageElement.removeEventListener('load', this.imageLoadedListener);\n            }\n            // then forget about that element 😢\n            this.imageElement.src = undefined;\n            this.imageElement.removeAttribute('src');\n            this.imageElement = undefined;\n        }\n        /**\n         * Cleans canvas references 🖌\n         */\n        _destroyCaptureCanvas() {\n            // then forget about that element 😢\n            this.captureCanvasContext = undefined;\n            this.captureCanvas = undefined;\n        }\n        /**\n         * Defines what the videoElement src will be.\n         *\n         * @param videoElement\n         * @param stream\n         */\n        addVideoSource(videoElement, stream) {\n            // Older browsers may not have `srcObject`\n            try {\n                // @note Throws Exception if interrupted by a new loaded request\n                videoElement.srcObject = stream;\n            }\n            catch (err) {\n                // @note Avoid using this in new browsers, as it is going away.\n                videoElement.src = URL.createObjectURL(stream);\n            }\n        }\n        /**\n         * Unbinds a HTML video src property.\n         *\n         * @param videoElement\n         */\n        cleanVideoSource(videoElement) {\n            try {\n                videoElement.srcObject = null;\n            }\n            catch (err) {\n                videoElement.src = '';\n            }\n            this.videoElement.removeAttribute('src');\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates the result of decoding a barcode within an image.</p>\n     *\n     * @author Sean Owen\n     */\n    class Result {\n        // public constructor(private text: string,\n        //               Uint8Array rawBytes,\n        //               ResultPoconst resultPoints: Int32Array,\n        //               BarcodeFormat format) {\n        //   this(text, rawBytes, resultPoints, format, System.currentTimeMillis())\n        // }\n        // public constructor(text: string,\n        //               Uint8Array rawBytes,\n        //               ResultPoconst resultPoints: Int32Array,\n        //               BarcodeFormat format,\n        //               long timestamp) {\n        //   this(text, rawBytes, rawBytes == null ? 0 : 8 * rawBytes.length,\n        //        resultPoints, format, timestamp)\n        // }\n        constructor(text, rawBytes, numBits = rawBytes == null ? 0 : 8 * rawBytes.length, resultPoints, format, timestamp = System.currentTimeMillis()) {\n            this.text = text;\n            this.rawBytes = rawBytes;\n            this.numBits = numBits;\n            this.resultPoints = resultPoints;\n            this.format = format;\n            this.timestamp = timestamp;\n            this.text = text;\n            this.rawBytes = rawBytes;\n            if (undefined === numBits || null === numBits) {\n                this.numBits = (rawBytes === null || rawBytes === undefined) ? 0 : 8 * rawBytes.length;\n            }\n            else {\n                this.numBits = numBits;\n            }\n            this.resultPoints = resultPoints;\n            this.format = format;\n            this.resultMetadata = null;\n            if (undefined === timestamp || null === timestamp) {\n                this.timestamp = System.currentTimeMillis();\n            }\n            else {\n                this.timestamp = timestamp;\n            }\n        }\n        /**\n         * @return raw text encoded by the barcode\n         */\n        getText() {\n            return this.text;\n        }\n        /**\n         * @return raw bytes encoded by the barcode, if applicable, otherwise {@code null}\n         */\n        getRawBytes() {\n            return this.rawBytes;\n        }\n        /**\n         * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length\n         * @since 3.3.0\n         */\n        getNumBits() {\n            return this.numBits;\n        }\n        /**\n         * @return points related to the barcode in the image. These are typically points\n         *         identifying finder patterns or the corners of the barcode. The exact meaning is\n         *         specific to the type of barcode that was decoded.\n         */\n        getResultPoints() {\n            return this.resultPoints;\n        }\n        /**\n         * @return {@link BarcodeFormat} representing the format of the barcode that was decoded\n         */\n        getBarcodeFormat() {\n            return this.format;\n        }\n        /**\n         * @return {@link Map} mapping {@link ResultMetadataType} keys to values. May be\n         *   {@code null}. This contains optional metadata about what was detected about the barcode,\n         *   like orientation.\n         */\n        getResultMetadata() {\n            return this.resultMetadata;\n        }\n        putMetadata(type, value) {\n            if (this.resultMetadata === null) {\n                this.resultMetadata = new Map();\n            }\n            this.resultMetadata.set(type, value);\n        }\n        putAllMetadata(metadata) {\n            if (metadata !== null) {\n                if (this.resultMetadata === null) {\n                    this.resultMetadata = metadata;\n                }\n                else {\n                    this.resultMetadata = new Map(metadata);\n                }\n            }\n        }\n        addResultPoints(newPoints) {\n            const oldPoints = this.resultPoints;\n            if (oldPoints === null) {\n                this.resultPoints = newPoints;\n            }\n            else if (newPoints !== null && newPoints.length > 0) {\n                const allPoints = new Array(oldPoints.length + newPoints.length);\n                System.arraycopy(oldPoints, 0, allPoints, 0, oldPoints.length);\n                System.arraycopy(newPoints, 0, allPoints, oldPoints.length, newPoints.length);\n                this.resultPoints = allPoints;\n            }\n        }\n        getTimestamp() {\n            return this.timestamp;\n        }\n        /*@Override*/\n        toString() {\n            return this.text;\n        }\n    }\n\n    /*\n     * Direct port to TypeScript of ZXing by Adrian Toșcă\n     */\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing {*/\n    /**\n     * Enumerates barcode formats known to this package. Please keep alphabetized.\n     *\n     * @author Sean Owen\n     */\n    var BarcodeFormat;\n    (function (BarcodeFormat) {\n        /** Aztec 2D barcode format. */\n        BarcodeFormat[BarcodeFormat[\"AZTEC\"] = 0] = \"AZTEC\";\n        /** CODABAR 1D format. */\n        BarcodeFormat[BarcodeFormat[\"CODABAR\"] = 1] = \"CODABAR\";\n        /** Code 39 1D format. */\n        BarcodeFormat[BarcodeFormat[\"CODE_39\"] = 2] = \"CODE_39\";\n        /** Code 93 1D format. */\n        BarcodeFormat[BarcodeFormat[\"CODE_93\"] = 3] = \"CODE_93\";\n        /** Code 128 1D format. */\n        BarcodeFormat[BarcodeFormat[\"CODE_128\"] = 4] = \"CODE_128\";\n        /** Data Matrix 2D barcode format. */\n        BarcodeFormat[BarcodeFormat[\"DATA_MATRIX\"] = 5] = \"DATA_MATRIX\";\n        /** EAN-8 1D format. */\n        BarcodeFormat[BarcodeFormat[\"EAN_8\"] = 6] = \"EAN_8\";\n        /** EAN-13 1D format. */\n        BarcodeFormat[BarcodeFormat[\"EAN_13\"] = 7] = \"EAN_13\";\n        /** ITF (Interleaved Two of Five) 1D format. */\n        BarcodeFormat[BarcodeFormat[\"ITF\"] = 8] = \"ITF\";\n        /** MaxiCode 2D barcode format. */\n        BarcodeFormat[BarcodeFormat[\"MAXICODE\"] = 9] = \"MAXICODE\";\n        /** PDF417 format. */\n        BarcodeFormat[BarcodeFormat[\"PDF_417\"] = 10] = \"PDF_417\";\n        /** QR Code 2D barcode format. */\n        BarcodeFormat[BarcodeFormat[\"QR_CODE\"] = 11] = \"QR_CODE\";\n        /** RSS 14 */\n        BarcodeFormat[BarcodeFormat[\"RSS_14\"] = 12] = \"RSS_14\";\n        /** RSS EXPANDED */\n        BarcodeFormat[BarcodeFormat[\"RSS_EXPANDED\"] = 13] = \"RSS_EXPANDED\";\n        /** UPC-A 1D format. */\n        BarcodeFormat[BarcodeFormat[\"UPC_A\"] = 14] = \"UPC_A\";\n        /** UPC-E 1D format. */\n        BarcodeFormat[BarcodeFormat[\"UPC_E\"] = 15] = \"UPC_E\";\n        /** UPC/EAN extension format. Not a stand-alone format. */\n        BarcodeFormat[BarcodeFormat[\"UPC_EAN_EXTENSION\"] = 16] = \"UPC_EAN_EXTENSION\";\n    })(BarcodeFormat || (BarcodeFormat = {}));\n    var BarcodeFormat$1 = BarcodeFormat;\n\n    /*namespace com.google.zxing {*/\n    /**\n     * Represents some type of metadata about the result of the decoding that the decoder\n     * wishes to communicate back to the caller.\n     *\n     * @author Sean Owen\n     */\n    var ResultMetadataType;\n    (function (ResultMetadataType) {\n        /**\n         * Unspecified, application-specific metadata. Maps to an unspecified {@link Object}.\n         */\n        ResultMetadataType[ResultMetadataType[\"OTHER\"] = 0] = \"OTHER\";\n        /**\n         * Denotes the likely approximate orientation of the barcode in the image. This value\n         * is given as degrees rotated clockwise from the normal, upright orientation.\n         * For example a 1D barcode which was found by reading top-to-bottom would be\n         * said to have orientation \"90\". This key maps to an {@link Integer} whose\n         * value is in the range [0,360).\n         */\n        ResultMetadataType[ResultMetadataType[\"ORIENTATION\"] = 1] = \"ORIENTATION\";\n        /**\n         * <p>2D barcode formats typically encode text, but allow for a sort of 'byte mode'\n         * which is sometimes used to encode binary data. While {@link Result} makes available\n         * the complete raw bytes in the barcode for these formats, it does not offer the bytes\n         * from the byte segments alone.</p>\n         *\n         * <p>This maps to a {@link java.util.List} of byte arrays corresponding to the\n         * raw bytes in the byte segments in the barcode, in order.</p>\n         */\n        ResultMetadataType[ResultMetadataType[\"BYTE_SEGMENTS\"] = 2] = \"BYTE_SEGMENTS\";\n        /**\n         * Error correction level used, if applicable. The value type depends on the\n         * format, but is typically a String.\n         */\n        ResultMetadataType[ResultMetadataType[\"ERROR_CORRECTION_LEVEL\"] = 3] = \"ERROR_CORRECTION_LEVEL\";\n        /**\n         * For some periodicals, indicates the issue number as an {@link Integer}.\n         */\n        ResultMetadataType[ResultMetadataType[\"ISSUE_NUMBER\"] = 4] = \"ISSUE_NUMBER\";\n        /**\n         * For some products, indicates the suggested retail price in the barcode as a\n         * formatted {@link String}.\n         */\n        ResultMetadataType[ResultMetadataType[\"SUGGESTED_PRICE\"] = 5] = \"SUGGESTED_PRICE\";\n        /**\n         * For some products, the possible country of manufacture as a {@link String} denoting the\n         * ISO country code. Some map to multiple possible countries, like \"US/CA\".\n         */\n        ResultMetadataType[ResultMetadataType[\"POSSIBLE_COUNTRY\"] = 6] = \"POSSIBLE_COUNTRY\";\n        /**\n         * For some products, the extension text\n         */\n        ResultMetadataType[ResultMetadataType[\"UPC_EAN_EXTENSION\"] = 7] = \"UPC_EAN_EXTENSION\";\n        /**\n         * PDF417-specific metadata\n         */\n        ResultMetadataType[ResultMetadataType[\"PDF417_EXTRA_METADATA\"] = 8] = \"PDF417_EXTRA_METADATA\";\n        /**\n         * If the code format supports structured append and the current scanned code is part of one then the\n         * sequence number is given with it.\n         */\n        ResultMetadataType[ResultMetadataType[\"STRUCTURED_APPEND_SEQUENCE\"] = 9] = \"STRUCTURED_APPEND_SEQUENCE\";\n        /**\n         * If the code format supports structured append and the current scanned code is part of one then the\n         * parity is given with it.\n         */\n        ResultMetadataType[ResultMetadataType[\"STRUCTURED_APPEND_PARITY\"] = 10] = \"STRUCTURED_APPEND_PARITY\";\n    })(ResultMetadataType || (ResultMetadataType = {}));\n    var ResultMetadataType$1 = ResultMetadataType;\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing.common {*/\n    /*import java.util.List;*/\n    /**\n     * <p>Encapsulates the result of decoding a matrix of bits. This typically\n     * applies to 2D barcode formats. For now it contains the raw bytes obtained,\n     * as well as a String interpretation of those bytes, if applicable.</p>\n     *\n     * @author Sean Owen\n     */\n    class DecoderResult {\n        // public constructor(rawBytes: Uint8Array,\n        //                      text: string,\n        //                      List<Uint8Array> byteSegments,\n        //                      String ecLevel) {\n        //   this(rawBytes, text, byteSegments, ecLevel, -1, -1)\n        // }\n        constructor(rawBytes, text, byteSegments, ecLevel, structuredAppendSequenceNumber = -1, structuredAppendParity = -1) {\n            this.rawBytes = rawBytes;\n            this.text = text;\n            this.byteSegments = byteSegments;\n            this.ecLevel = ecLevel;\n            this.structuredAppendSequenceNumber = structuredAppendSequenceNumber;\n            this.structuredAppendParity = structuredAppendParity;\n            this.numBits = (rawBytes === undefined || rawBytes === null) ? 0 : 8 * rawBytes.length;\n        }\n        /**\n         * @return raw bytes representing the result, or {@code null} if not applicable\n         */\n        getRawBytes() {\n            return this.rawBytes;\n        }\n        /**\n         * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length\n         * @since 3.3.0\n         */\n        getNumBits() {\n            return this.numBits;\n        }\n        /**\n         * @param numBits overrides the number of bits that are valid in {@link #getRawBytes()}\n         * @since 3.3.0\n         */\n        setNumBits(numBits /*int*/) {\n            this.numBits = numBits;\n        }\n        /**\n         * @return text representation of the result\n         */\n        getText() {\n            return this.text;\n        }\n        /**\n         * @return list of byte segments in the result, or {@code null} if not applicable\n         */\n        getByteSegments() {\n            return this.byteSegments;\n        }\n        /**\n         * @return name of error correction level used, or {@code null} if not applicable\n         */\n        getECLevel() {\n            return this.ecLevel;\n        }\n        /**\n         * @return number of errors corrected, or {@code null} if not applicable\n         */\n        getErrorsCorrected() {\n            return this.errorsCorrected;\n        }\n        setErrorsCorrected(errorsCorrected /*Integer*/) {\n            this.errorsCorrected = errorsCorrected;\n        }\n        /**\n         * @return number of erasures corrected, or {@code null} if not applicable\n         */\n        getErasures() {\n            return this.erasures;\n        }\n        setErasures(erasures /*Integer*/) {\n            this.erasures = erasures;\n        }\n        /**\n         * @return arbitrary additional metadata\n         */\n        getOther() {\n            return this.other;\n        }\n        setOther(other) {\n            this.other = other;\n        }\n        hasStructuredAppend() {\n            return this.structuredAppendParity >= 0 && this.structuredAppendSequenceNumber >= 0;\n        }\n        getStructuredAppendParity() {\n            return this.structuredAppendParity;\n        }\n        getStructuredAppendSequenceNumber() {\n            return this.structuredAppendSequenceNumber;\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>This class contains utility methods for performing mathematical operations over\n     * the Galois Fields. Operations use a given primitive polynomial in calculations.</p>\n     *\n     * <p>Throughout this package, elements of the GF are represented as an {@code int}\n     * for convenience and speed (but at the cost of memory).\n     * </p>\n     *\n     * @author Sean Owen\n     * @author David Olivier\n     */\n    class AbstractGenericGF {\n        /**\n         * @return 2 to the power of a in GF(size)\n         */\n        exp(a) {\n            return this.expTable[a];\n        }\n        /**\n         * @return base 2 log of a in GF(size)\n         */\n        log(a /*int*/) {\n            if (a === 0) {\n                throw new IllegalArgumentException();\n            }\n            return this.logTable[a];\n        }\n        /**\n         * Implements both addition and subtraction -- they are the same in GF(size).\n         *\n         * @return sum/difference of a and b\n         */\n        static addOrSubtract(a /*int*/, b /*int*/) {\n            return a ^ b;\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Represents a polynomial whose coefficients are elements of a GF.\n     * Instances of this class are immutable.</p>\n     *\n     * <p>Much credit is due to William Rucklidge since portions of this code are an indirect\n     * port of his C++ Reed-Solomon implementation.</p>\n     *\n     * @author Sean Owen\n     */\n    class GenericGFPoly {\n        /**\n         * @param field the {@link GenericGF} instance representing the field to use\n         * to perform computations\n         * @param coefficients coefficients as ints representing elements of GF(size), arranged\n         * from most significant (highest-power term) coefficient to least significant\n         * @throws IllegalArgumentException if argument is null or empty,\n         * or if leading coefficient is 0 and this is not a\n         * constant polynomial (that is, it is not the monomial \"0\")\n         */\n        constructor(field, coefficients) {\n            if (coefficients.length === 0) {\n                throw new IllegalArgumentException();\n            }\n            this.field = field;\n            const coefficientsLength = coefficients.length;\n            if (coefficientsLength > 1 && coefficients[0] === 0) {\n                // Leading term must be non-zero for anything except the constant polynomial \"0\"\n                let firstNonZero = 1;\n                while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) {\n                    firstNonZero++;\n                }\n                if (firstNonZero === coefficientsLength) {\n                    this.coefficients = Int32Array.from([0]);\n                }\n                else {\n                    this.coefficients = new Int32Array(coefficientsLength - firstNonZero);\n                    System.arraycopy(coefficients, firstNonZero, this.coefficients, 0, this.coefficients.length);\n                }\n            }\n            else {\n                this.coefficients = coefficients;\n            }\n        }\n        getCoefficients() {\n            return this.coefficients;\n        }\n        /**\n         * @return degree of this polynomial\n         */\n        getDegree() {\n            return this.coefficients.length - 1;\n        }\n        /**\n         * @return true iff this polynomial is the monomial \"0\"\n         */\n        isZero() {\n            return this.coefficients[0] === 0;\n        }\n        /**\n         * @return coefficient of x^degree term in this polynomial\n         */\n        getCoefficient(degree /*int*/) {\n            return this.coefficients[this.coefficients.length - 1 - degree];\n        }\n        /**\n         * @return evaluation of this polynomial at a given point\n         */\n        evaluateAt(a /*int*/) {\n            if (a === 0) {\n                // Just return the x^0 coefficient\n                return this.getCoefficient(0);\n            }\n            const coefficients = this.coefficients;\n            let result;\n            if (a === 1) {\n                // Just the sum of the coefficients\n                result = 0;\n                for (let i = 0, length = coefficients.length; i !== length; i++) {\n                    const coefficient = coefficients[i];\n                    result = AbstractGenericGF.addOrSubtract(result, coefficient);\n                }\n                return result;\n            }\n            result = coefficients[0];\n            const size = coefficients.length;\n            const field = this.field;\n            for (let i = 1; i < size; i++) {\n                result = AbstractGenericGF.addOrSubtract(field.multiply(a, result), coefficients[i]);\n            }\n            return result;\n        }\n        addOrSubtract(other) {\n            if (!this.field.equals(other.field)) {\n                throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field');\n            }\n            if (this.isZero()) {\n                return other;\n            }\n            if (other.isZero()) {\n                return this;\n            }\n            let smallerCoefficients = this.coefficients;\n            let largerCoefficients = other.coefficients;\n            if (smallerCoefficients.length > largerCoefficients.length) {\n                const temp = smallerCoefficients;\n                smallerCoefficients = largerCoefficients;\n                largerCoefficients = temp;\n            }\n            let sumDiff = new Int32Array(largerCoefficients.length);\n            const lengthDiff = largerCoefficients.length - smallerCoefficients.length;\n            // Copy high-order terms only found in higher-degree polynomial's coefficients\n            System.arraycopy(largerCoefficients, 0, sumDiff, 0, lengthDiff);\n            for (let i = lengthDiff; i < largerCoefficients.length; i++) {\n                sumDiff[i] = AbstractGenericGF.addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);\n            }\n            return new GenericGFPoly(this.field, sumDiff);\n        }\n        multiply(other) {\n            if (!this.field.equals(other.field)) {\n                throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field');\n            }\n            if (this.isZero() || other.isZero()) {\n                return this.field.getZero();\n            }\n            const aCoefficients = this.coefficients;\n            const aLength = aCoefficients.length;\n            const bCoefficients = other.coefficients;\n            const bLength = bCoefficients.length;\n            const product = new Int32Array(aLength + bLength - 1);\n            const field = this.field;\n            for (let i = 0; i < aLength; i++) {\n                const aCoeff = aCoefficients[i];\n                for (let j = 0; j < bLength; j++) {\n                    product[i + j] = AbstractGenericGF.addOrSubtract(product[i + j], field.multiply(aCoeff, bCoefficients[j]));\n                }\n            }\n            return new GenericGFPoly(field, product);\n        }\n        multiplyScalar(scalar /*int*/) {\n            if (scalar === 0) {\n                return this.field.getZero();\n            }\n            if (scalar === 1) {\n                return this;\n            }\n            const size = this.coefficients.length;\n            const field = this.field;\n            const product = new Int32Array(size);\n            const coefficients = this.coefficients;\n            for (let i = 0; i < size; i++) {\n                product[i] = field.multiply(coefficients[i], scalar);\n            }\n            return new GenericGFPoly(field, product);\n        }\n        multiplyByMonomial(degree /*int*/, coefficient /*int*/) {\n            if (degree < 0) {\n                throw new IllegalArgumentException();\n            }\n            if (coefficient === 0) {\n                return this.field.getZero();\n            }\n            const coefficients = this.coefficients;\n            const size = coefficients.length;\n            const product = new Int32Array(size + degree);\n            const field = this.field;\n            for (let i = 0; i < size; i++) {\n                product[i] = field.multiply(coefficients[i], coefficient);\n            }\n            return new GenericGFPoly(field, product);\n        }\n        divide(other) {\n            if (!this.field.equals(other.field)) {\n                throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field');\n            }\n            if (other.isZero()) {\n                throw new IllegalArgumentException('Divide by 0');\n            }\n            const field = this.field;\n            let quotient = field.getZero();\n            let remainder = this;\n            const denominatorLeadingTerm = other.getCoefficient(other.getDegree());\n            const inverseDenominatorLeadingTerm = field.inverse(denominatorLeadingTerm);\n            while (remainder.getDegree() >= other.getDegree() && !remainder.isZero()) {\n                const degreeDifference = remainder.getDegree() - other.getDegree();\n                const scale = field.multiply(remainder.getCoefficient(remainder.getDegree()), inverseDenominatorLeadingTerm);\n                const term = other.multiplyByMonomial(degreeDifference, scale);\n                const iterationQuotient = field.buildMonomial(degreeDifference, scale);\n                quotient = quotient.addOrSubtract(iterationQuotient);\n                remainder = remainder.addOrSubtract(term);\n            }\n            return [quotient, remainder];\n        }\n        /*@Override*/\n        toString() {\n            let result = '';\n            for (let degree = this.getDegree(); degree >= 0; degree--) {\n                let coefficient = this.getCoefficient(degree);\n                if (coefficient !== 0) {\n                    if (coefficient < 0) {\n                        result += ' - ';\n                        coefficient = -coefficient;\n                    }\n                    else {\n                        if (result.length > 0) {\n                            result += ' + ';\n                        }\n                    }\n                    if (degree === 0 || coefficient !== 1) {\n                        const alphaPower = this.field.log(coefficient);\n                        if (alphaPower === 0) {\n                            result += '1';\n                        }\n                        else if (alphaPower === 1) {\n                            result += 'a';\n                        }\n                        else {\n                            result += 'a^';\n                            result += alphaPower;\n                        }\n                    }\n                    if (degree !== 0) {\n                        if (degree === 1) {\n                            result += 'x';\n                        }\n                        else {\n                            result += 'x^';\n                            result += degree;\n                        }\n                    }\n                }\n            }\n            return result;\n        }\n    }\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class ArithmeticException extends Exception {\n    }\n    ArithmeticException.kind = 'ArithmeticException';\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>This class contains utility methods for performing mathematical operations over\n     * the Galois Fields. Operations use a given primitive polynomial in calculations.</p>\n     *\n     * <p>Throughout this package, elements of the GF are represented as an {@code int}\n     * for convenience and speed (but at the cost of memory).\n     * </p>\n     *\n     * @author Sean Owen\n     * @author David Olivier\n     */\n    class GenericGF extends AbstractGenericGF {\n        /**\n         * Create a representation of GF(size) using the given primitive polynomial.\n         *\n         * @param primitive irreducible polynomial whose coefficients are represented by\n         *  the bits of an int, where the least-significant bit represents the constant\n         *  coefficient\n         * @param size the size of the field\n         * @param b the factor b in the generator polynomial can be 0- or 1-based\n         *  (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))).\n         *  In most cases it should be 1, but for QR code it is 0.\n         */\n        constructor(primitive /*int*/, size /*int*/, generatorBase /*int*/) {\n            super();\n            this.primitive = primitive;\n            this.size = size;\n            this.generatorBase = generatorBase;\n            const expTable = new Int32Array(size);\n            let x = 1;\n            for (let i = 0; i < size; i++) {\n                expTable[i] = x;\n                x *= 2; // we're assuming the generator alpha is 2\n                if (x >= size) {\n                    x ^= primitive;\n                    x &= size - 1;\n                }\n            }\n            this.expTable = expTable;\n            const logTable = new Int32Array(size);\n            for (let i = 0; i < size - 1; i++) {\n                logTable[expTable[i]] = i;\n            }\n            this.logTable = logTable;\n            // logTable[0] == 0 but this should never be used\n            this.zero = new GenericGFPoly(this, Int32Array.from([0]));\n            this.one = new GenericGFPoly(this, Int32Array.from([1]));\n        }\n        getZero() {\n            return this.zero;\n        }\n        getOne() {\n            return this.one;\n        }\n        /**\n         * @return the monomial representing coefficient * x^degree\n         */\n        buildMonomial(degree /*int*/, coefficient /*int*/) {\n            if (degree < 0) {\n                throw new IllegalArgumentException();\n            }\n            if (coefficient === 0) {\n                return this.zero;\n            }\n            const coefficients = new Int32Array(degree + 1);\n            coefficients[0] = coefficient;\n            return new GenericGFPoly(this, coefficients);\n        }\n        /**\n         * @return multiplicative inverse of a\n         */\n        inverse(a /*int*/) {\n            if (a === 0) {\n                throw new ArithmeticException();\n            }\n            return this.expTable[this.size - this.logTable[a] - 1];\n        }\n        /**\n         * @return product of a and b in GF(size)\n         */\n        multiply(a /*int*/, b /*int*/) {\n            if (a === 0 || b === 0) {\n                return 0;\n            }\n            return this.expTable[(this.logTable[a] + this.logTable[b]) % (this.size - 1)];\n        }\n        getSize() {\n            return this.size;\n        }\n        getGeneratorBase() {\n            return this.generatorBase;\n        }\n        /*@Override*/\n        toString() {\n            return ('GF(0x' + Integer.toHexString(this.primitive) + ',' + this.size + ')');\n        }\n        equals(o) {\n            return o === this;\n        }\n    }\n    GenericGF.AZTEC_DATA_12 = new GenericGF(0x1069, 4096, 1); // x^12 + x^6 + x^5 + x^3 + 1\n    GenericGF.AZTEC_DATA_10 = new GenericGF(0x409, 1024, 1); // x^10 + x^3 + 1\n    GenericGF.AZTEC_DATA_6 = new GenericGF(0x43, 64, 1); // x^6 + x + 1\n    GenericGF.AZTEC_PARAM = new GenericGF(0x13, 16, 1); // x^4 + x + 1\n    GenericGF.QR_CODE_FIELD_256 = new GenericGF(0x011d, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1\n    GenericGF.DATA_MATRIX_FIELD_256 = new GenericGF(0x012d, 256, 1); // x^8 + x^5 + x^3 + x^2 + 1\n    GenericGF.AZTEC_DATA_8 = GenericGF.DATA_MATRIX_FIELD_256;\n    GenericGF.MAXICODE_FIELD_64 = GenericGF.AZTEC_DATA_6;\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class ReedSolomonException extends Exception {\n    }\n    ReedSolomonException.kind = 'ReedSolomonException';\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class IllegalStateException extends Exception {\n    }\n    IllegalStateException.kind = 'IllegalStateException';\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Implements Reed-Solomon decoding, as the name implies.</p>\n     *\n     * <p>The algorithm will not be explained here, but the following references were helpful\n     * in creating this implementation:</p>\n     *\n     * <ul>\n     * <li>Bruce Maggs.\n     * <a href=\"http://www.cs.cmu.edu/afs/cs.cmu.edu/project/pscico-guyb/realworld/www/rs_decode.ps\">\n     * \"Decoding Reed-Solomon Codes\"</a> (see discussion of Forney's Formula)</li>\n     * <li>J.I. Hall. <a href=\"www.mth.msu.edu/~jhall/classes/codenotes/GRS.pdf\">\n     * \"Chapter 5. Generalized Reed-Solomon Codes\"</a>\n     * (see discussion of Euclidean algorithm)</li>\n     * </ul>\n     *\n     * <p>Much credit is due to William Rucklidge since portions of this code are an indirect\n     * port of his C++ Reed-Solomon implementation.</p>\n     *\n     * @author Sean Owen\n     * @author William Rucklidge\n     * @author sanfordsquires\n     */\n    class ReedSolomonDecoder {\n        constructor(field) {\n            this.field = field;\n        }\n        /**\n         * <p>Decodes given set of received codewords, which include both data and error-correction\n         * codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place,\n         * in the input.</p>\n         *\n         * @param received data and error-correction codewords\n         * @param twoS number of error-correction codewords available\n         * @throws ReedSolomonException if decoding fails for any reason\n         */\n        decode(received, twoS /*int*/) {\n            const field = this.field;\n            const poly = new GenericGFPoly(field, received);\n            const syndromeCoefficients = new Int32Array(twoS);\n            let noError = true;\n            for (let i = 0; i < twoS; i++) {\n                const evalResult = poly.evaluateAt(field.exp(i + field.getGeneratorBase()));\n                syndromeCoefficients[syndromeCoefficients.length - 1 - i] = evalResult;\n                if (evalResult !== 0) {\n                    noError = false;\n                }\n            }\n            if (noError) {\n                return;\n            }\n            const syndrome = new GenericGFPoly(field, syndromeCoefficients);\n            const sigmaOmega = this.runEuclideanAlgorithm(field.buildMonomial(twoS, 1), syndrome, twoS);\n            const sigma = sigmaOmega[0];\n            const omega = sigmaOmega[1];\n            const errorLocations = this.findErrorLocations(sigma);\n            const errorMagnitudes = this.findErrorMagnitudes(omega, errorLocations);\n            for (let i = 0; i < errorLocations.length; i++) {\n                const position = received.length - 1 - field.log(errorLocations[i]);\n                if (position < 0) {\n                    throw new ReedSolomonException('Bad error location');\n                }\n                received[position] = GenericGF.addOrSubtract(received[position], errorMagnitudes[i]);\n            }\n        }\n        runEuclideanAlgorithm(a, b, R /*int*/) {\n            // Assume a's degree is >= b's\n            if (a.getDegree() < b.getDegree()) {\n                const temp = a;\n                a = b;\n                b = temp;\n            }\n            const field = this.field;\n            let rLast = a;\n            let r = b;\n            let tLast = field.getZero();\n            let t = field.getOne();\n            // Run Euclidean algorithm until r's degree is less than R/2\n            while (r.getDegree() >= (R / 2 | 0)) {\n                let rLastLast = rLast;\n                let tLastLast = tLast;\n                rLast = r;\n                tLast = t;\n                // Divide rLastLast by rLast, with quotient in q and remainder in r\n                if (rLast.isZero()) {\n                    // Oops, Euclidean algorithm already terminated?\n                    throw new ReedSolomonException('r_{i-1} was zero');\n                }\n                r = rLastLast;\n                let q = field.getZero();\n                const denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree());\n                const dltInverse = field.inverse(denominatorLeadingTerm);\n                while (r.getDegree() >= rLast.getDegree() && !r.isZero()) {\n                    const degreeDiff = r.getDegree() - rLast.getDegree();\n                    const scale = field.multiply(r.getCoefficient(r.getDegree()), dltInverse);\n                    q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale));\n                    r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale));\n                }\n                t = q.multiply(tLast).addOrSubtract(tLastLast);\n                if (r.getDegree() >= rLast.getDegree()) {\n                    throw new IllegalStateException('Division algorithm failed to reduce polynomial?');\n                }\n            }\n            const sigmaTildeAtZero = t.getCoefficient(0);\n            if (sigmaTildeAtZero === 0) {\n                throw new ReedSolomonException('sigmaTilde(0) was zero');\n            }\n            const inverse = field.inverse(sigmaTildeAtZero);\n            const sigma = t.multiplyScalar(inverse);\n            const omega = r.multiplyScalar(inverse);\n            return [sigma, omega];\n        }\n        findErrorLocations(errorLocator) {\n            // This is a direct application of Chien's search\n            const numErrors = errorLocator.getDegree();\n            if (numErrors === 1) { // shortcut\n                return Int32Array.from([errorLocator.getCoefficient(1)]);\n            }\n            const result = new Int32Array(numErrors);\n            let e = 0;\n            const field = this.field;\n            for (let i = 1; i < field.getSize() && e < numErrors; i++) {\n                if (errorLocator.evaluateAt(i) === 0) {\n                    result[e] = field.inverse(i);\n                    e++;\n                }\n            }\n            if (e !== numErrors) {\n                throw new ReedSolomonException('Error locator degree does not match number of roots');\n            }\n            return result;\n        }\n        findErrorMagnitudes(errorEvaluator, errorLocations) {\n            // This is directly applying Forney's Formula\n            const s = errorLocations.length;\n            const result = new Int32Array(s);\n            const field = this.field;\n            for (let i = 0; i < s; i++) {\n                const xiInverse = field.inverse(errorLocations[i]);\n                let denominator = 1;\n                for (let j = 0; j < s; j++) {\n                    if (i !== j) {\n                        // denominator = field.multiply(denominator,\n                        //    GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse)))\n                        // Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug.\n                        // Below is a funny-looking workaround from Steven Parkes\n                        const term = field.multiply(errorLocations[j], xiInverse);\n                        const termPlus1 = (term & 0x1) === 0 ? term | 1 : term & ~1;\n                        denominator = field.multiply(denominator, termPlus1);\n                    }\n                }\n                result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denominator));\n                if (field.getGeneratorBase() !== 0) {\n                    result[i] = field.multiply(result[i], xiInverse);\n                }\n            }\n            return result;\n        }\n    }\n\n    /*\n     * Copyright 2010 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    // import java.util.Arrays;\n    var Table;\n    (function (Table) {\n        Table[Table[\"UPPER\"] = 0] = \"UPPER\";\n        Table[Table[\"LOWER\"] = 1] = \"LOWER\";\n        Table[Table[\"MIXED\"] = 2] = \"MIXED\";\n        Table[Table[\"DIGIT\"] = 3] = \"DIGIT\";\n        Table[Table[\"PUNCT\"] = 4] = \"PUNCT\";\n        Table[Table[\"BINARY\"] = 5] = \"BINARY\";\n    })(Table || (Table = {}));\n    /**\n     * <p>The main class which implements Aztec Code decoding -- as opposed to locating and extracting\n     * the Aztec Code from an image.</p>\n     *\n     * @author David Olivier\n     */\n    class Decoder {\n        decode(detectorResult) {\n            this.ddata = detectorResult;\n            let matrix = detectorResult.getBits();\n            let rawbits = this.extractBits(matrix);\n            let correctedBits = this.correctBits(rawbits);\n            let rawBytes = Decoder.convertBoolArrayToByteArray(correctedBits);\n            let result = Decoder.getEncodedData(correctedBits);\n            let decoderResult = new DecoderResult(rawBytes, result, null, null);\n            decoderResult.setNumBits(correctedBits.length);\n            return decoderResult;\n        }\n        // This method is used for testing the high-level encoder\n        static highLevelDecode(correctedBits) {\n            return this.getEncodedData(correctedBits);\n        }\n        /**\n         * Gets the string encoded in the aztec code bits\n         *\n         * @return the decoded string\n         */\n        static getEncodedData(correctedBits) {\n            let endIndex = correctedBits.length;\n            let latchTable = Table.UPPER; // table most recently latched to\n            let shiftTable = Table.UPPER; // table to use for the next read\n            let result = '';\n            let index = 0;\n            while (index < endIndex) {\n                if (shiftTable === Table.BINARY) {\n                    if (endIndex - index < 5) {\n                        break;\n                    }\n                    let length = Decoder.readCode(correctedBits, index, 5);\n                    index += 5;\n                    if (length === 0) {\n                        if (endIndex - index < 11) {\n                            break;\n                        }\n                        length = Decoder.readCode(correctedBits, index, 11) + 31;\n                        index += 11;\n                    }\n                    for (let charCount = 0; charCount < length; charCount++) {\n                        if (endIndex - index < 8) {\n                            index = endIndex; // Force outer loop to exit\n                            break;\n                        }\n                        const code = Decoder.readCode(correctedBits, index, 8);\n                        result += /*(char)*/ StringUtils.castAsNonUtf8Char(code);\n                        index += 8;\n                    }\n                    // Go back to whatever mode we had been in\n                    shiftTable = latchTable;\n                }\n                else {\n                    let size = shiftTable === Table.DIGIT ? 4 : 5;\n                    if (endIndex - index < size) {\n                        break;\n                    }\n                    let code = Decoder.readCode(correctedBits, index, size);\n                    index += size;\n                    let str = Decoder.getCharacter(shiftTable, code);\n                    if (str.startsWith('CTRL_')) {\n                        // Table changes\n                        // ISO/IEC 24778:2008 prescribes ending a shift sequence in the mode from which it was invoked.\n                        // That's including when that mode is a shift.\n                        // Our test case dlusbs.png for issue #642 exercises that.\n                        latchTable = shiftTable; // Latch the current mode, so as to return to Upper after U/S B/S\n                        shiftTable = Decoder.getTable(str.charAt(5));\n                        if (str.charAt(6) === 'L') {\n                            latchTable = shiftTable;\n                        }\n                    }\n                    else {\n                        result += str;\n                        // Go back to whatever mode we had been in\n                        shiftTable = latchTable;\n                    }\n                }\n            }\n            return result;\n        }\n        /**\n         * gets the table corresponding to the char passed\n         */\n        static getTable(t) {\n            switch (t) {\n                case 'L':\n                    return Table.LOWER;\n                case 'P':\n                    return Table.PUNCT;\n                case 'M':\n                    return Table.MIXED;\n                case 'D':\n                    return Table.DIGIT;\n                case 'B':\n                    return Table.BINARY;\n                case 'U':\n                default:\n                    return Table.UPPER;\n            }\n        }\n        /**\n         * Gets the character (or string) corresponding to the passed code in the given table\n         *\n         * @param table the table used\n         * @param code the code of the character\n         */\n        static getCharacter(table, code) {\n            switch (table) {\n                case Table.UPPER:\n                    return Decoder.UPPER_TABLE[code];\n                case Table.LOWER:\n                    return Decoder.LOWER_TABLE[code];\n                case Table.MIXED:\n                    return Decoder.MIXED_TABLE[code];\n                case Table.PUNCT:\n                    return Decoder.PUNCT_TABLE[code];\n                case Table.DIGIT:\n                    return Decoder.DIGIT_TABLE[code];\n                default:\n                    // Should not reach here.\n                    throw new IllegalStateException('Bad table');\n            }\n        }\n        /**\n         * <p>Performs RS error correction on an array of bits.</p>\n         *\n         * @return the corrected array\n         * @throws FormatException if the input contains too many errors\n         */\n        correctBits(rawbits) {\n            let gf;\n            let codewordSize;\n            if (this.ddata.getNbLayers() <= 2) {\n                codewordSize = 6;\n                gf = GenericGF.AZTEC_DATA_6;\n            }\n            else if (this.ddata.getNbLayers() <= 8) {\n                codewordSize = 8;\n                gf = GenericGF.AZTEC_DATA_8;\n            }\n            else if (this.ddata.getNbLayers() <= 22) {\n                codewordSize = 10;\n                gf = GenericGF.AZTEC_DATA_10;\n            }\n            else {\n                codewordSize = 12;\n                gf = GenericGF.AZTEC_DATA_12;\n            }\n            let numDataCodewords = this.ddata.getNbDatablocks();\n            let numCodewords = rawbits.length / codewordSize;\n            if (numCodewords < numDataCodewords) {\n                throw new FormatException();\n            }\n            let offset = rawbits.length % codewordSize;\n            let dataWords = new Int32Array(numCodewords);\n            for (let i = 0; i < numCodewords; i++, offset += codewordSize) {\n                dataWords[i] = Decoder.readCode(rawbits, offset, codewordSize);\n            }\n            try {\n                let rsDecoder = new ReedSolomonDecoder(gf);\n                rsDecoder.decode(dataWords, numCodewords - numDataCodewords);\n            }\n            catch (ex) {\n                throw new FormatException(ex);\n            }\n            // Now perform the unstuffing operation.\n            // First, count how many bits are going to be thrown out as stuffing\n            let mask = (1 << codewordSize) - 1;\n            let stuffedBits = 0;\n            for (let i = 0; i < numDataCodewords; i++) {\n                let dataWord = dataWords[i];\n                if (dataWord === 0 || dataWord === mask) {\n                    throw new FormatException();\n                }\n                else if (dataWord === 1 || dataWord === mask - 1) {\n                    stuffedBits++;\n                }\n            }\n            // Now, actually unpack the bits and remove the stuffing\n            let correctedBits = new Array(numDataCodewords * codewordSize - stuffedBits);\n            let index = 0;\n            for (let i = 0; i < numDataCodewords; i++) {\n                let dataWord = dataWords[i];\n                if (dataWord === 1 || dataWord === mask - 1) {\n                    // next codewordSize-1 bits are all zeros or all ones\n                    correctedBits.fill(dataWord > 1, index, index + codewordSize - 1);\n                    // Arrays.fill(correctedBits, index, index + codewordSize - 1, dataWord > 1);\n                    index += codewordSize - 1;\n                }\n                else {\n                    for (let bit = codewordSize - 1; bit >= 0; --bit) {\n                        correctedBits[index++] = (dataWord & (1 << bit)) !== 0;\n                    }\n                }\n            }\n            return correctedBits;\n        }\n        /**\n         * Gets the array of bits from an Aztec Code matrix\n         *\n         * @return the array of bits\n         */\n        extractBits(matrix) {\n            let compact = this.ddata.isCompact();\n            let layers = this.ddata.getNbLayers();\n            let baseMatrixSize = (compact ? 11 : 14) + layers * 4; // not including alignment lines\n            let alignmentMap = new Int32Array(baseMatrixSize);\n            let rawbits = new Array(this.totalBitsInLayer(layers, compact));\n            if (compact) {\n                for (let i = 0; i < alignmentMap.length; i++) {\n                    alignmentMap[i] = i;\n                }\n            }\n            else {\n                let matrixSize = baseMatrixSize + 1 + 2 * Integer.truncDivision((Integer.truncDivision(baseMatrixSize, 2) - 1), 15);\n                let origCenter = baseMatrixSize / 2;\n                let center = Integer.truncDivision(matrixSize, 2);\n                for (let i = 0; i < origCenter; i++) {\n                    let newOffset = i + Integer.truncDivision(i, 15);\n                    alignmentMap[origCenter - i - 1] = center - newOffset - 1;\n                    alignmentMap[origCenter + i] = center + newOffset + 1;\n                }\n            }\n            for (let i = 0, rowOffset = 0; i < layers; i++) {\n                let rowSize = (layers - i) * 4 + (compact ? 9 : 12);\n                // The top-left most point of this layer is <low, low> (not including alignment lines)\n                let low = i * 2;\n                // The bottom-right most point of this layer is <high, high> (not including alignment lines)\n                let high = baseMatrixSize - 1 - low;\n                // We pull bits from the two 2 x rowSize columns and two rowSize x 2 rows\n                for (let j = 0; j < rowSize; j++) {\n                    let columnOffset = j * 2;\n                    for (let k = 0; k < 2; k++) {\n                        // left column\n                        rawbits[rowOffset + columnOffset + k] =\n                            matrix.get(alignmentMap[low + k], alignmentMap[low + j]);\n                        // bottom row\n                        rawbits[rowOffset + 2 * rowSize + columnOffset + k] =\n                            matrix.get(alignmentMap[low + j], alignmentMap[high - k]);\n                        // right column\n                        rawbits[rowOffset + 4 * rowSize + columnOffset + k] =\n                            matrix.get(alignmentMap[high - k], alignmentMap[high - j]);\n                        // top row\n                        rawbits[rowOffset + 6 * rowSize + columnOffset + k] =\n                            matrix.get(alignmentMap[high - j], alignmentMap[low + k]);\n                    }\n                }\n                rowOffset += rowSize * 8;\n            }\n            return rawbits;\n        }\n        /**\n         * Reads a code of given length and at given index in an array of bits\n         */\n        static readCode(rawbits, startIndex, length) {\n            let res = 0;\n            for (let i = startIndex; i < startIndex + length; i++) {\n                res <<= 1;\n                if (rawbits[i]) {\n                    res |= 0x01;\n                }\n            }\n            return res;\n        }\n        /**\n         * Reads a code of length 8 in an array of bits, padding with zeros\n         */\n        static readByte(rawbits, startIndex) {\n            let n = rawbits.length - startIndex;\n            if (n >= 8) {\n                return Decoder.readCode(rawbits, startIndex, 8);\n            }\n            return Decoder.readCode(rawbits, startIndex, n) << (8 - n);\n        }\n        /**\n         * Packs a bit array into bytes, most significant bit first\n         */\n        static convertBoolArrayToByteArray(boolArr) {\n            let byteArr = new Uint8Array((boolArr.length + 7) / 8);\n            for (let i = 0; i < byteArr.length; i++) {\n                byteArr[i] = Decoder.readByte(boolArr, 8 * i);\n            }\n            return byteArr;\n        }\n        totalBitsInLayer(layers, compact) {\n            return ((compact ? 88 : 112) + 16 * layers) * layers;\n        }\n    }\n    Decoder.UPPER_TABLE = [\n        'CTRL_PS', ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',\n        'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'CTRL_LL', 'CTRL_ML', 'CTRL_DL', 'CTRL_BS'\n    ];\n    Decoder.LOWER_TABLE = [\n        'CTRL_PS', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',\n        'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'CTRL_US', 'CTRL_ML', 'CTRL_DL', 'CTRL_BS'\n    ];\n    Decoder.MIXED_TABLE = [\n        // Module parse failed: Octal literal in strict mode (50:29)\n        // so number string were scaped\n        'CTRL_PS', ' ', '\\\\1', '\\\\2', '\\\\3', '\\\\4', '\\\\5', '\\\\6', '\\\\7', '\\b', '\\t', '\\n',\n        '\\\\13', '\\f', '\\r', '\\\\33', '\\\\34', '\\\\35', '\\\\36', '\\\\37', '@', '\\\\', '^', '_',\n        '`', '|', '~', '\\\\177', 'CTRL_LL', 'CTRL_UL', 'CTRL_PL', 'CTRL_BS'\n    ];\n    Decoder.PUNCT_TABLE = [\n        '', '\\r', '\\r\\n', '. ', ', ', ': ', '!', '\"', '#', '$', '%', '&', '\\'', '(', ')',\n        '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', ']', '{', '}', 'CTRL_UL'\n    ];\n    Decoder.DIGIT_TABLE = [\n        'CTRL_PS', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ',', '.', 'CTRL_UL', 'CTRL_US'\n    ];\n\n    /*\n     * Copyright 2012 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing.common.detector {*/\n    /**\n     * General math-related and numeric utility functions.\n     */\n    class MathUtils {\n        constructor() { }\n        /**\n         * Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its\n         * argument to the nearest int, where x.5 rounds up to x+1. Semantics of this shortcut\n         * differ slightly from {@link Math#round(float)} in that half rounds down for negative\n         * values. -2.5 rounds to -3, not -2. For purposes here it makes no difference.\n         *\n         * @param d real value to round\n         * @return nearest {@code int}\n         */\n        static round(d /*float*/) {\n            if (NaN === d)\n                return 0;\n            if (d <= Number.MIN_SAFE_INTEGER)\n                return Number.MIN_SAFE_INTEGER;\n            if (d >= Number.MAX_SAFE_INTEGER)\n                return Number.MAX_SAFE_INTEGER;\n            return /*(int) */ (d + (d < 0.0 ? -0.5 : 0.5)) | 0;\n        }\n        // TYPESCRIPTPORT: maybe remove round method and call directly Math.round, it looks like it doesn't make sense for js\n        /**\n         * @param aX point A x coordinate\n         * @param aY point A y coordinate\n         * @param bX point B x coordinate\n         * @param bY point B y coordinate\n         * @return Euclidean distance between points A and B\n         */\n        static distance(aX /*float|int*/, aY /*float|int*/, bX /*float|int*/, bY /*float|int*/) {\n            const xDiff = aX - bX;\n            const yDiff = aY - bY;\n            return /*(float) */ Math.sqrt(xDiff * xDiff + yDiff * yDiff);\n        }\n        /**\n         * @param aX point A x coordinate\n         * @param aY point A y coordinate\n         * @param bX point B x coordinate\n         * @param bY point B y coordinate\n         * @return Euclidean distance between points A and B\n         */\n        // public static distance(aX: number /*int*/, aY: number /*int*/, bX: number /*int*/, bY: number /*int*/): float {\n        //   const xDiff = aX - bX\n        //   const yDiff = aY - bY\n        //   return (float) Math.sqrt(xDiff * xDiff + yDiff * yDiff);\n        // }\n        /**\n         * @param array values to sum\n         * @return sum of values in array\n         */\n        static sum(array) {\n            let count = 0;\n            for (let i = 0, length = array.length; i !== length; i++) {\n                const a = array[i];\n                count += a;\n            }\n            return count;\n        }\n    }\n\n    /**\n     * Ponyfill for Java's Float class.\n     */\n    class Float {\n        /**\n         * SincTS has no difference between int and float, there's all numbers,\n         * this is used only to polyfill Java code.\n         */\n        static floatToIntBits(f) {\n            return f;\n        }\n    }\n    /**\n     * The float max value in JS is the number max value.\n     */\n    Float.MAX_VALUE = Number.MAX_SAFE_INTEGER;\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates a point of interest in an image containing a barcode. Typically, this\n     * would be the location of a finder pattern or the corner of the barcode, for example.</p>\n     *\n     * @author Sean Owen\n     */\n    class ResultPoint {\n        constructor(x, y) {\n            this.x = x;\n            this.y = y;\n        }\n        getX() {\n            return this.x;\n        }\n        getY() {\n            return this.y;\n        }\n        /*@Override*/\n        equals(other) {\n            if (other instanceof ResultPoint) {\n                const otherPoint = other;\n                return this.x === otherPoint.x && this.y === otherPoint.y;\n            }\n            return false;\n        }\n        /*@Override*/\n        hashCode() {\n            return 31 * Float.floatToIntBits(this.x) + Float.floatToIntBits(this.y);\n        }\n        /*@Override*/\n        toString() {\n            return '(' + this.x + ',' + this.y + ')';\n        }\n        /**\n         * Orders an array of three ResultPoints in an order [A,B,C] such that AB is less than AC\n         * and BC is less than AC, and the angle between BC and BA is less than 180 degrees.\n         *\n         * @param patterns array of three {@code ResultPoint} to order\n         */\n        static orderBestPatterns(patterns) {\n            // Find distances between pattern centers\n            const zeroOneDistance = this.distance(patterns[0], patterns[1]);\n            const oneTwoDistance = this.distance(patterns[1], patterns[2]);\n            const zeroTwoDistance = this.distance(patterns[0], patterns[2]);\n            let pointA;\n            let pointB;\n            let pointC;\n            // Assume one closest to other two is B; A and C will just be guesses at first\n            if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) {\n                pointB = patterns[0];\n                pointA = patterns[1];\n                pointC = patterns[2];\n            }\n            else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) {\n                pointB = patterns[1];\n                pointA = patterns[0];\n                pointC = patterns[2];\n            }\n            else {\n                pointB = patterns[2];\n                pointA = patterns[0];\n                pointC = patterns[1];\n            }\n            // Use cross product to figure out whether A and C are correct or flipped.\n            // This asks whether BC x BA has a positive z component, which is the arrangement\n            // we want for A, B, C. If it's negative, then we've got it flipped around and\n            // should swap A and C.\n            if (this.crossProductZ(pointA, pointB, pointC) < 0.0) {\n                const temp = pointA;\n                pointA = pointC;\n                pointC = temp;\n            }\n            patterns[0] = pointA;\n            patterns[1] = pointB;\n            patterns[2] = pointC;\n        }\n        /**\n         * @param pattern1 first pattern\n         * @param pattern2 second pattern\n         * @return distance between two points\n         */\n        static distance(pattern1, pattern2) {\n            return MathUtils.distance(pattern1.x, pattern1.y, pattern2.x, pattern2.y);\n        }\n        /**\n         * Returns the z component of the cross product between vectors BC and BA.\n         */\n        static crossProductZ(pointA, pointB, pointC) {\n            const bX = pointB.x;\n            const bY = pointB.y;\n            return ((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX));\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates the result of detecting a barcode in an image. This includes the raw\n     * matrix of black/white pixels corresponding to the barcode, and possibly points of interest\n     * in the image, like the location of finder patterns or corners of the barcode in the image.</p>\n     *\n     * @author Sean Owen\n     */\n    class DetectorResult {\n        constructor(bits, points) {\n            this.bits = bits;\n            this.points = points;\n        }\n        getBits() {\n            return this.bits;\n        }\n        getPoints() {\n            return this.points;\n        }\n    }\n\n    /*\n     * Copyright 2010 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Extends {@link DetectorResult} with more information specific to the Aztec format,\n     * like the number of layers and whether it's compact.</p>\n     *\n     * @author Sean Owen\n     */\n    class AztecDetectorResult extends DetectorResult {\n        constructor(bits, points, compact, nbDatablocks, nbLayers) {\n            super(bits, points);\n            this.compact = compact;\n            this.nbDatablocks = nbDatablocks;\n            this.nbLayers = nbLayers;\n        }\n        getNbLayers() {\n            return this.nbLayers;\n        }\n        getNbDatablocks() {\n            return this.nbDatablocks;\n        }\n        isCompact() {\n            return this.compact;\n        }\n    }\n\n    /*\n     * Copyright 2010 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>\n     * Detects a candidate barcode-like rectangular region within an image. It\n     * starts around the center of the image, increases the size of the candidate\n     * region until it finds a white rectangular region. By keeping track of the\n     * last black points it encountered, it determines the corners of the barcode.\n     * </p>\n     *\n     * @author David Olivier\n     */\n    class WhiteRectangleDetector {\n        // public constructor(private image: BitMatrix) /*throws NotFoundException*/ {\n        //   this(image, INIT_SIZE, image.getWidth() / 2, image.getHeight() / 2)\n        // }\n        /**\n         * @param image barcode image to find a rectangle in\n         * @param initSize initial size of search area around center\n         * @param x x position of search center\n         * @param y y position of search center\n         * @throws NotFoundException if image is too small to accommodate {@code initSize}\n         */\n        constructor(image, initSize /*int*/, x /*int*/, y /*int*/) {\n            this.image = image;\n            this.height = image.getHeight();\n            this.width = image.getWidth();\n            if (undefined === initSize || null === initSize) {\n                initSize = WhiteRectangleDetector.INIT_SIZE;\n            }\n            if (undefined === x || null === x) {\n                x = image.getWidth() / 2 | 0;\n            }\n            if (undefined === y || null === y) {\n                y = image.getHeight() / 2 | 0;\n            }\n            const halfsize = initSize / 2 | 0;\n            this.leftInit = x - halfsize;\n            this.rightInit = x + halfsize;\n            this.upInit = y - halfsize;\n            this.downInit = y + halfsize;\n            if (this.upInit < 0 || this.leftInit < 0 || this.downInit >= this.height || this.rightInit >= this.width) {\n                throw new NotFoundException();\n            }\n        }\n        /**\n         * <p>\n         * Detects a candidate barcode-like rectangular region within an image. It\n         * starts around the center of the image, increases the size of the candidate\n         * region until it finds a white rectangular region.\n         * </p>\n         *\n         * @return {@link ResultPoint}[] describing the corners of the rectangular\n         *         region. The first and last points are opposed on the diagonal, as\n         *         are the second and third. The first point will be the topmost\n         *         point and the last, the bottommost. The second point will be\n         *         leftmost and the third, the rightmost\n         * @throws NotFoundException if no Data Matrix Code can be found\n         */\n        detect() {\n            let left = this.leftInit;\n            let right = this.rightInit;\n            let up = this.upInit;\n            let down = this.downInit;\n            let sizeExceeded = false;\n            let aBlackPointFoundOnBorder = true;\n            let atLeastOneBlackPointFoundOnBorder = false;\n            let atLeastOneBlackPointFoundOnRight = false;\n            let atLeastOneBlackPointFoundOnBottom = false;\n            let atLeastOneBlackPointFoundOnLeft = false;\n            let atLeastOneBlackPointFoundOnTop = false;\n            const width = this.width;\n            const height = this.height;\n            while (aBlackPointFoundOnBorder) {\n                aBlackPointFoundOnBorder = false;\n                // .....\n                // .   |\n                // .....\n                let rightBorderNotWhite = true;\n                while ((rightBorderNotWhite || !atLeastOneBlackPointFoundOnRight) && right < width) {\n                    rightBorderNotWhite = this.containsBlackPoint(up, down, right, false);\n                    if (rightBorderNotWhite) {\n                        right++;\n                        aBlackPointFoundOnBorder = true;\n                        atLeastOneBlackPointFoundOnRight = true;\n                    }\n                    else if (!atLeastOneBlackPointFoundOnRight) {\n                        right++;\n                    }\n                }\n                if (right >= width) {\n                    sizeExceeded = true;\n                    break;\n                }\n                // .....\n                // .   .\n                // .___.\n                let bottomBorderNotWhite = true;\n                while ((bottomBorderNotWhite || !atLeastOneBlackPointFoundOnBottom) && down < height) {\n                    bottomBorderNotWhite = this.containsBlackPoint(left, right, down, true);\n                    if (bottomBorderNotWhite) {\n                        down++;\n                        aBlackPointFoundOnBorder = true;\n                        atLeastOneBlackPointFoundOnBottom = true;\n                    }\n                    else if (!atLeastOneBlackPointFoundOnBottom) {\n                        down++;\n                    }\n                }\n                if (down >= height) {\n                    sizeExceeded = true;\n                    break;\n                }\n                // .....\n                // |   .\n                // .....\n                let leftBorderNotWhite = true;\n                while ((leftBorderNotWhite || !atLeastOneBlackPointFoundOnLeft) && left >= 0) {\n                    leftBorderNotWhite = this.containsBlackPoint(up, down, left, false);\n                    if (leftBorderNotWhite) {\n                        left--;\n                        aBlackPointFoundOnBorder = true;\n                        atLeastOneBlackPointFoundOnLeft = true;\n                    }\n                    else if (!atLeastOneBlackPointFoundOnLeft) {\n                        left--;\n                    }\n                }\n                if (left < 0) {\n                    sizeExceeded = true;\n                    break;\n                }\n                // .___.\n                // .   .\n                // .....\n                let topBorderNotWhite = true;\n                while ((topBorderNotWhite || !atLeastOneBlackPointFoundOnTop) && up >= 0) {\n                    topBorderNotWhite = this.containsBlackPoint(left, right, up, true);\n                    if (topBorderNotWhite) {\n                        up--;\n                        aBlackPointFoundOnBorder = true;\n                        atLeastOneBlackPointFoundOnTop = true;\n                    }\n                    else if (!atLeastOneBlackPointFoundOnTop) {\n                        up--;\n                    }\n                }\n                if (up < 0) {\n                    sizeExceeded = true;\n                    break;\n                }\n                if (aBlackPointFoundOnBorder) {\n                    atLeastOneBlackPointFoundOnBorder = true;\n                }\n            }\n            if (!sizeExceeded && atLeastOneBlackPointFoundOnBorder) {\n                const maxSize = right - left;\n                let z = null;\n                for (let i = 1; z === null && i < maxSize; i++) {\n                    z = this.getBlackPointOnSegment(left, down - i, left + i, down);\n                }\n                if (z == null) {\n                    throw new NotFoundException();\n                }\n                let t = null;\n                // go down right\n                for (let i = 1; t === null && i < maxSize; i++) {\n                    t = this.getBlackPointOnSegment(left, up + i, left + i, up);\n                }\n                if (t == null) {\n                    throw new NotFoundException();\n                }\n                let x = null;\n                // go down left\n                for (let i = 1; x === null && i < maxSize; i++) {\n                    x = this.getBlackPointOnSegment(right, up + i, right - i, up);\n                }\n                if (x == null) {\n                    throw new NotFoundException();\n                }\n                let y = null;\n                // go up left\n                for (let i = 1; y === null && i < maxSize; i++) {\n                    y = this.getBlackPointOnSegment(right, down - i, right - i, down);\n                }\n                if (y == null) {\n                    throw new NotFoundException();\n                }\n                return this.centerEdges(y, z, x, t);\n            }\n            else {\n                throw new NotFoundException();\n            }\n        }\n        getBlackPointOnSegment(aX /*float*/, aY /*float*/, bX /*float*/, bY /*float*/) {\n            const dist = MathUtils.round(MathUtils.distance(aX, aY, bX, bY));\n            const xStep = (bX - aX) / dist;\n            const yStep = (bY - aY) / dist;\n            const image = this.image;\n            for (let i = 0; i < dist; i++) {\n                const x = MathUtils.round(aX + i * xStep);\n                const y = MathUtils.round(aY + i * yStep);\n                if (image.get(x, y)) {\n                    return new ResultPoint(x, y);\n                }\n            }\n            return null;\n        }\n        /**\n         * recenters the points of a constant distance towards the center\n         *\n         * @param y bottom most point\n         * @param z left most point\n         * @param x right most point\n         * @param t top most point\n         * @return {@link ResultPoint}[] describing the corners of the rectangular\n         *         region. The first and last points are opposed on the diagonal, as\n         *         are the second and third. The first point will be the topmost\n         *         point and the last, the bottommost. The second point will be\n         *         leftmost and the third, the rightmost\n         */\n        centerEdges(y, z, x, t) {\n            //\n            //       t            t\n            //  z                      x\n            //        x    OR    z\n            //   y                    y\n            //\n            const yi = y.getX();\n            const yj = y.getY();\n            const zi = z.getX();\n            const zj = z.getY();\n            const xi = x.getX();\n            const xj = x.getY();\n            const ti = t.getX();\n            const tj = t.getY();\n            const CORR = WhiteRectangleDetector.CORR;\n            if (yi < this.width / 2.0) {\n                return [\n                    new ResultPoint(ti - CORR, tj + CORR),\n                    new ResultPoint(zi + CORR, zj + CORR),\n                    new ResultPoint(xi - CORR, xj - CORR),\n                    new ResultPoint(yi + CORR, yj - CORR)\n                ];\n            }\n            else {\n                return [\n                    new ResultPoint(ti + CORR, tj + CORR),\n                    new ResultPoint(zi + CORR, zj - CORR),\n                    new ResultPoint(xi - CORR, xj + CORR),\n                    new ResultPoint(yi - CORR, yj - CORR)\n                ];\n            }\n        }\n        /**\n         * Determines whether a segment contains a black point\n         *\n         * @param a          min value of the scanned coordinate\n         * @param b          max value of the scanned coordinate\n         * @param fixed      value of fixed coordinate\n         * @param horizontal set to true if scan must be horizontal, false if vertical\n         * @return true if a black point has been found, else false.\n         */\n        containsBlackPoint(a /*int*/, b /*int*/, fixed /*int*/, horizontal) {\n            const image = this.image;\n            if (horizontal) {\n                for (let x = a; x <= b; x++) {\n                    if (image.get(x, fixed)) {\n                        return true;\n                    }\n                }\n            }\n            else {\n                for (let y = a; y <= b; y++) {\n                    if (image.get(fixed, y)) {\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n    }\n    WhiteRectangleDetector.INIT_SIZE = 10;\n    WhiteRectangleDetector.CORR = 1;\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * Implementations of this class can, given locations of finder patterns for a QR code in an\n     * image, sample the right points in the image to reconstruct the QR code, accounting for\n     * perspective distortion. It is abstracted since it is relatively expensive and should be allowed\n     * to take advantage of platform-specific optimized implementations, like Sun's Java Advanced\n     * Imaging library, but which may not be available in other environments such as J2ME, and vice\n     * versa.\n     *\n     * The implementation used can be controlled by calling {@link #setGridSampler(GridSampler)}\n     * with an instance of a class which implements this interface.\n     *\n     * @author Sean Owen\n     */\n    class GridSampler {\n        /**\n         * <p>Checks a set of points that have been transformed to sample points on an image against\n         * the image's dimensions to see if the point are even within the image.</p>\n         *\n         * <p>This method will actually \"nudge\" the endpoints back onto the image if they are found to be\n         * barely (less than 1 pixel) off the image. This accounts for imperfect detection of finder\n         * patterns in an image where the QR Code runs all the way to the image border.</p>\n         *\n         * <p>For efficiency, the method will check points from either end of the line until one is found\n         * to be within the image. Because the set of points are assumed to be linear, this is valid.</p>\n         *\n         * @param image image into which the points should map\n         * @param points actual points in x1,y1,...,xn,yn form\n         * @throws NotFoundException if an endpoint is lies outside the image boundaries\n         */\n        static checkAndNudgePoints(image, points) {\n            const width = image.getWidth();\n            const height = image.getHeight();\n            // Check and nudge points from start until we see some that are OK:\n            let nudged = true;\n            for (let offset = 0; offset < points.length && nudged; offset += 2) {\n                const x = Math.floor(points[offset]);\n                const y = Math.floor(points[offset + 1]);\n                if (x < -1 || x > width || y < -1 || y > height) {\n                    throw new NotFoundException();\n                }\n                nudged = false;\n                if (x === -1) {\n                    points[offset] = 0.0;\n                    nudged = true;\n                }\n                else if (x === width) {\n                    points[offset] = width - 1;\n                    nudged = true;\n                }\n                if (y === -1) {\n                    points[offset + 1] = 0.0;\n                    nudged = true;\n                }\n                else if (y === height) {\n                    points[offset + 1] = height - 1;\n                    nudged = true;\n                }\n            }\n            // Check and nudge points from end:\n            nudged = true;\n            for (let offset = points.length - 2; offset >= 0 && nudged; offset -= 2) {\n                const x = Math.floor(points[offset]);\n                const y = Math.floor(points[offset + 1]);\n                if (x < -1 || x > width || y < -1 || y > height) {\n                    throw new NotFoundException();\n                }\n                nudged = false;\n                if (x === -1) {\n                    points[offset] = 0.0;\n                    nudged = true;\n                }\n                else if (x === width) {\n                    points[offset] = width - 1;\n                    nudged = true;\n                }\n                if (y === -1) {\n                    points[offset + 1] = 0.0;\n                    nudged = true;\n                }\n                else if (y === height) {\n                    points[offset + 1] = height - 1;\n                    nudged = true;\n                }\n            }\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing.common {*/\n    /**\n     * <p>This class implements a perspective transform in two dimensions. Given four source and four\n     * destination points, it will compute the transformation implied between them. The code is based\n     * directly upon section 3.4.2 of George Wolberg's \"Digital Image Warping\"; see pages 54-56.</p>\n     *\n     * @author Sean Owen\n     */\n    class PerspectiveTransform {\n        constructor(a11 /*float*/, a21 /*float*/, a31 /*float*/, a12 /*float*/, a22 /*float*/, a32 /*float*/, a13 /*float*/, a23 /*float*/, a33 /*float*/) {\n            this.a11 = a11;\n            this.a21 = a21;\n            this.a31 = a31;\n            this.a12 = a12;\n            this.a22 = a22;\n            this.a32 = a32;\n            this.a13 = a13;\n            this.a23 = a23;\n            this.a33 = a33;\n        }\n        static quadrilateralToQuadrilateral(x0 /*float*/, y0 /*float*/, x1 /*float*/, y1 /*float*/, x2 /*float*/, y2 /*float*/, x3 /*float*/, y3 /*float*/, x0p /*float*/, y0p /*float*/, x1p /*float*/, y1p /*float*/, x2p /*float*/, y2p /*float*/, x3p /*float*/, y3p /*float*/) {\n            const qToS = PerspectiveTransform.quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);\n            const sToQ = PerspectiveTransform.squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);\n            return sToQ.times(qToS);\n        }\n        transformPoints(points) {\n            const max = points.length;\n            const a11 = this.a11;\n            const a12 = this.a12;\n            const a13 = this.a13;\n            const a21 = this.a21;\n            const a22 = this.a22;\n            const a23 = this.a23;\n            const a31 = this.a31;\n            const a32 = this.a32;\n            const a33 = this.a33;\n            for (let i = 0; i < max; i += 2) {\n                const x = points[i];\n                const y = points[i + 1];\n                const denominator = a13 * x + a23 * y + a33;\n                points[i] = (a11 * x + a21 * y + a31) / denominator;\n                points[i + 1] = (a12 * x + a22 * y + a32) / denominator;\n            }\n        }\n        transformPointsWithValues(xValues, yValues) {\n            const a11 = this.a11;\n            const a12 = this.a12;\n            const a13 = this.a13;\n            const a21 = this.a21;\n            const a22 = this.a22;\n            const a23 = this.a23;\n            const a31 = this.a31;\n            const a32 = this.a32;\n            const a33 = this.a33;\n            const n = xValues.length;\n            for (let i = 0; i < n; i++) {\n                const x = xValues[i];\n                const y = yValues[i];\n                const denominator = a13 * x + a23 * y + a33;\n                xValues[i] = (a11 * x + a21 * y + a31) / denominator;\n                yValues[i] = (a12 * x + a22 * y + a32) / denominator;\n            }\n        }\n        static squareToQuadrilateral(x0 /*float*/, y0 /*float*/, x1 /*float*/, y1 /*float*/, x2 /*float*/, y2 /*float*/, x3 /*float*/, y3 /*float*/) {\n            const dx3 = x0 - x1 + x2 - x3;\n            const dy3 = y0 - y1 + y2 - y3;\n            if (dx3 === 0.0 && dy3 === 0.0) {\n                // Affine\n                return new PerspectiveTransform(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0.0, 0.0, 1.0);\n            }\n            else {\n                const dx1 = x1 - x2;\n                const dx2 = x3 - x2;\n                const dy1 = y1 - y2;\n                const dy2 = y3 - y2;\n                const denominator = dx1 * dy2 - dx2 * dy1;\n                const a13 = (dx3 * dy2 - dx2 * dy3) / denominator;\n                const a23 = (dx1 * dy3 - dx3 * dy1) / denominator;\n                return new PerspectiveTransform(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, y1 - y0 + a13 * y1, y3 - y0 + a23 * y3, y0, a13, a23, 1.0);\n            }\n        }\n        static quadrilateralToSquare(x0 /*float*/, y0 /*float*/, x1 /*float*/, y1 /*float*/, x2 /*float*/, y2 /*float*/, x3 /*float*/, y3 /*float*/) {\n            // Here, the adjoint serves as the inverse:\n            return PerspectiveTransform.squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint();\n        }\n        buildAdjoint() {\n            // Adjoint is the transpose of the cofactor matrix:\n            return new PerspectiveTransform(this.a22 * this.a33 - this.a23 * this.a32, this.a23 * this.a31 - this.a21 * this.a33, this.a21 * this.a32 - this.a22 * this.a31, this.a13 * this.a32 - this.a12 * this.a33, this.a11 * this.a33 - this.a13 * this.a31, this.a12 * this.a31 - this.a11 * this.a32, this.a12 * this.a23 - this.a13 * this.a22, this.a13 * this.a21 - this.a11 * this.a23, this.a11 * this.a22 - this.a12 * this.a21);\n        }\n        times(other) {\n            return new PerspectiveTransform(this.a11 * other.a11 + this.a21 * other.a12 + this.a31 * other.a13, this.a11 * other.a21 + this.a21 * other.a22 + this.a31 * other.a23, this.a11 * other.a31 + this.a21 * other.a32 + this.a31 * other.a33, this.a12 * other.a11 + this.a22 * other.a12 + this.a32 * other.a13, this.a12 * other.a21 + this.a22 * other.a22 + this.a32 * other.a23, this.a12 * other.a31 + this.a22 * other.a32 + this.a32 * other.a33, this.a13 * other.a11 + this.a23 * other.a12 + this.a33 * other.a13, this.a13 * other.a21 + this.a23 * other.a22 + this.a33 * other.a23, this.a13 * other.a31 + this.a23 * other.a32 + this.a33 * other.a33);\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * @author Sean Owen\n     */\n    class DefaultGridSampler extends GridSampler {\n        /*@Override*/\n        sampleGrid(image, dimensionX /*int*/, dimensionY /*int*/, p1ToX /*float*/, p1ToY /*float*/, p2ToX /*float*/, p2ToY /*float*/, p3ToX /*float*/, p3ToY /*float*/, p4ToX /*float*/, p4ToY /*float*/, p1FromX /*float*/, p1FromY /*float*/, p2FromX /*float*/, p2FromY /*float*/, p3FromX /*float*/, p3FromY /*float*/, p4FromX /*float*/, p4FromY /*float*/) {\n            const transform = PerspectiveTransform.quadrilateralToQuadrilateral(p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY, p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY);\n            return this.sampleGridWithTransform(image, dimensionX, dimensionY, transform);\n        }\n        /*@Override*/\n        sampleGridWithTransform(image, dimensionX /*int*/, dimensionY /*int*/, transform) {\n            if (dimensionX <= 0 || dimensionY <= 0) {\n                throw new NotFoundException();\n            }\n            const bits = new BitMatrix(dimensionX, dimensionY);\n            const points = new Float32Array(2 * dimensionX);\n            for (let y = 0; y < dimensionY; y++) {\n                const max = points.length;\n                const iValue = y + 0.5;\n                for (let x = 0; x < max; x += 2) {\n                    points[x] = (x / 2) + 0.5;\n                    points[x + 1] = iValue;\n                }\n                transform.transformPoints(points);\n                // Quick check to see if points transformed to something inside the image\n                // sufficient to check the endpoints\n                GridSampler.checkAndNudgePoints(image, points);\n                try {\n                    for (let x = 0; x < max; x += 2) {\n                        if (image.get(Math.floor(points[x]), Math.floor(points[x + 1]))) {\n                            // Black(-ish) pixel\n                            bits.set(x / 2, y);\n                        }\n                    }\n                }\n                catch (aioobe /*: ArrayIndexOutOfBoundsException*/) {\n                    // This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting\n                    // transform gets \"twisted\" such that it maps a straight line of points to a set of points\n                    // whose endpoints are in bounds, but others are not. There is probably some mathematical\n                    // way to detect this about the transformation that I don't know yet.\n                    // This results in an ugly runtime exception despite our clever checks above -- can't have\n                    // that. We could check each point's coordinates but that feels duplicative. We settle for\n                    // catching and wrapping ArrayIndexOutOfBoundsException.\n                    throw new NotFoundException();\n                }\n            }\n            return bits;\n        }\n    }\n\n    class GridSamplerInstance {\n        /**\n         * Sets the implementation of GridSampler used by the library. One global\n         * instance is stored, which may sound problematic. But, the implementation provided\n         * ought to be appropriate for the entire platform, and all uses of this library\n         * in the whole lifetime of the JVM. For instance, an Android activity can swap in\n         * an implementation that takes advantage of native platform libraries.\n         *\n         * @param newGridSampler The platform-specific object to install.\n         */\n        static setGridSampler(newGridSampler) {\n            GridSamplerInstance.gridSampler = newGridSampler;\n        }\n        /**\n         * @return the current implementation of GridSampler\n         */\n        static getInstance() {\n            return GridSamplerInstance.gridSampler;\n        }\n    }\n    GridSamplerInstance.gridSampler = new DefaultGridSampler();\n\n    /*\n     * Copyright 2010 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    class Point {\n        constructor(x, y) {\n            this.x = x;\n            this.y = y;\n        }\n        toResultPoint() {\n            return new ResultPoint(this.getX(), this.getY());\n        }\n        getX() {\n            return this.x;\n        }\n        getY() {\n            return this.y;\n        }\n    }\n    /**\n     * Encapsulates logic that can detect an Aztec Code in an image, even if the Aztec Code\n     * is rotated or skewed, or partially obscured.\n     *\n     * @author David Olivier\n     * @author Frank Yellin\n     */\n    class Detector {\n        constructor(image) {\n            this.EXPECTED_CORNER_BITS = new Int32Array([\n                0xee0,\n                0x1dc,\n                0x83b,\n                0x707,\n            ]);\n            this.image = image;\n        }\n        detect() {\n            return this.detectMirror(false);\n        }\n        /**\n         * Detects an Aztec Code in an image.\n         *\n         * @param isMirror if true, image is a mirror-image of original\n         * @return {@link AztecDetectorResult} encapsulating results of detecting an Aztec Code\n         * @throws NotFoundException if no Aztec Code can be found\n         */\n        detectMirror(isMirror) {\n            // 1. Get the center of the aztec matrix\n            let pCenter = this.getMatrixCenter();\n            // 2. Get the center points of the four diagonal points just outside the bull's eye\n            //  [topRight, bottomRight, bottomLeft, topLeft]\n            let bullsEyeCorners = this.getBullsEyeCorners(pCenter);\n            if (isMirror) {\n                let temp = bullsEyeCorners[0];\n                bullsEyeCorners[0] = bullsEyeCorners[2];\n                bullsEyeCorners[2] = temp;\n            }\n            // 3. Get the size of the matrix and other parameters from the bull's eye\n            this.extractParameters(bullsEyeCorners);\n            // 4. Sample the grid\n            let bits = this.sampleGrid(this.image, bullsEyeCorners[this.shift % 4], bullsEyeCorners[(this.shift + 1) % 4], bullsEyeCorners[(this.shift + 2) % 4], bullsEyeCorners[(this.shift + 3) % 4]);\n            // 5. Get the corners of the matrix.\n            let corners = this.getMatrixCornerPoints(bullsEyeCorners);\n            return new AztecDetectorResult(bits, corners, this.compact, this.nbDataBlocks, this.nbLayers);\n        }\n        /**\n         * Extracts the number of data layers and data blocks from the layer around the bull's eye.\n         *\n         * @param bullsEyeCorners the array of bull's eye corners\n         * @throws NotFoundException in case of too many errors or invalid parameters\n         */\n        extractParameters(bullsEyeCorners) {\n            if (!this.isValidPoint(bullsEyeCorners[0]) || !this.isValidPoint(bullsEyeCorners[1]) ||\n                !this.isValidPoint(bullsEyeCorners[2]) || !this.isValidPoint(bullsEyeCorners[3])) {\n                throw new NotFoundException();\n            }\n            let length = 2 * this.nbCenterLayers;\n            // Get the bits around the bull's eye\n            let sides = new Int32Array([\n                this.sampleLine(bullsEyeCorners[0], bullsEyeCorners[1], length),\n                this.sampleLine(bullsEyeCorners[1], bullsEyeCorners[2], length),\n                this.sampleLine(bullsEyeCorners[2], bullsEyeCorners[3], length),\n                this.sampleLine(bullsEyeCorners[3], bullsEyeCorners[0], length) // Top\n            ]);\n            // bullsEyeCorners[shift] is the corner of the bulls'eye that has three\n            // orientation marks.\n            // sides[shift] is the row/column that goes from the corner with three\n            // orientation marks to the corner with two.\n            this.shift = this.getRotation(sides, length);\n            // Flatten the parameter bits into a single 28- or 40-bit long\n            let parameterData = 0;\n            for (let i = 0; i < 4; i++) {\n                let side = sides[(this.shift + i) % 4];\n                if (this.compact) {\n                    // Each side of the form ..XXXXXXX. where Xs are parameter data\n                    parameterData <<= 7;\n                    parameterData += (side >> 1) & 0x7F;\n                }\n                else {\n                    // Each side of the form ..XXXXX.XXXXX. where Xs are parameter data\n                    parameterData <<= 10;\n                    parameterData += ((side >> 2) & (0x1f << 5)) + ((side >> 1) & 0x1F);\n                }\n            }\n            // Corrects parameter data using RS.  Returns just the data portion\n            // without the error correction.\n            let correctedData = this.getCorrectedParameterData(parameterData, this.compact);\n            if (this.compact) {\n                // 8 bits:  2 bits layers and 6 bits data blocks\n                this.nbLayers = (correctedData >> 6) + 1;\n                this.nbDataBlocks = (correctedData & 0x3F) + 1;\n            }\n            else {\n                // 16 bits:  5 bits layers and 11 bits data blocks\n                this.nbLayers = (correctedData >> 11) + 1;\n                this.nbDataBlocks = (correctedData & 0x7FF) + 1;\n            }\n        }\n        getRotation(sides, length) {\n            // In a normal pattern, we expect to See\n            //   **    .*             D       A\n            //   *      *\n            //\n            //   .      *\n            //   ..    ..             C       B\n            //\n            // Grab the 3 bits from each of the sides the form the locator pattern and concatenate\n            // into a 12-bit integer.  Start with the bit at A\n            let cornerBits = 0;\n            sides.forEach((side, idx, arr) => {\n                // XX......X where X's are orientation marks\n                let t = ((side >> (length - 2)) << 1) + (side & 1);\n                cornerBits = (cornerBits << 3) + t;\n            });\n            // for (var side in sides) {\n            //     // XX......X where X's are orientation marks\n            //     var t = ((side >> (length - 2)) << 1) + (side & 1);\n            //     cornerBits = (cornerBits << 3) + t;\n            // }\n            // Mov the bottom bit to the top, so that the three bits of the locator pattern at A are\n            // together.  cornerBits is now:\n            //  3 orientation bits at A || 3 orientation bits at B || ... || 3 orientation bits at D\n            cornerBits = ((cornerBits & 1) << 11) + (cornerBits >> 1);\n            // The result shift indicates which element of BullsEyeCorners[] goes into the top-left\n            // corner. Since the four rotation values have a Hamming distance of 8, we\n            // can easily tolerate two errors.\n            for (let shift = 0; shift < 4; shift++) {\n                if (Integer.bitCount(cornerBits ^ this.EXPECTED_CORNER_BITS[shift]) <= 2) {\n                    return shift;\n                }\n            }\n            throw new NotFoundException();\n        }\n        /**\n         * Corrects the parameter bits using Reed-Solomon algorithm.\n         *\n         * @param parameterData parameter bits\n         * @param compact true if this is a compact Aztec code\n         * @throws NotFoundException if the array contains too many errors\n         */\n        getCorrectedParameterData(parameterData, compact) {\n            let numCodewords;\n            let numDataCodewords;\n            if (compact) {\n                numCodewords = 7;\n                numDataCodewords = 2;\n            }\n            else {\n                numCodewords = 10;\n                numDataCodewords = 4;\n            }\n            let numECCodewords = numCodewords - numDataCodewords;\n            let parameterWords = new Int32Array(numCodewords);\n            for (let i = numCodewords - 1; i >= 0; --i) {\n                parameterWords[i] = parameterData & 0xF;\n                parameterData >>= 4;\n            }\n            try {\n                let rsDecoder = new ReedSolomonDecoder(GenericGF.AZTEC_PARAM);\n                rsDecoder.decode(parameterWords, numECCodewords);\n            }\n            catch (ignored) {\n                throw new NotFoundException();\n            }\n            // Toss the error correction.  Just return the data as an integer\n            let result = 0;\n            for (let i = 0; i < numDataCodewords; i++) {\n                result = (result << 4) + parameterWords[i];\n            }\n            return result;\n        }\n        /**\n         * Finds the corners of a bull-eye centered on the passed point.\n         * This returns the centers of the diagonal points just outside the bull's eye\n         * Returns [topRight, bottomRight, bottomLeft, topLeft]\n         *\n         * @param pCenter Center point\n         * @return The corners of the bull-eye\n         * @throws NotFoundException If no valid bull-eye can be found\n         */\n        getBullsEyeCorners(pCenter) {\n            let pina = pCenter;\n            let pinb = pCenter;\n            let pinc = pCenter;\n            let pind = pCenter;\n            let color = true;\n            for (this.nbCenterLayers = 1; this.nbCenterLayers < 9; this.nbCenterLayers++) {\n                let pouta = this.getFirstDifferent(pina, color, 1, -1);\n                let poutb = this.getFirstDifferent(pinb, color, 1, 1);\n                let poutc = this.getFirstDifferent(pinc, color, -1, 1);\n                let poutd = this.getFirstDifferent(pind, color, -1, -1);\n                // d      a\n                //\n                // c      b\n                if (this.nbCenterLayers > 2) {\n                    let q = (this.distancePoint(poutd, pouta) * this.nbCenterLayers) / (this.distancePoint(pind, pina) * (this.nbCenterLayers + 2));\n                    if (q < 0.75 || q > 1.25 || !this.isWhiteOrBlackRectangle(pouta, poutb, poutc, poutd)) {\n                        break;\n                    }\n                }\n                pina = pouta;\n                pinb = poutb;\n                pinc = poutc;\n                pind = poutd;\n                color = !color;\n            }\n            if (this.nbCenterLayers !== 5 && this.nbCenterLayers !== 7) {\n                throw new NotFoundException();\n            }\n            this.compact = this.nbCenterLayers === 5;\n            // Expand the square by .5 pixel in each direction so that we're on the border\n            // between the white square and the black square\n            let pinax = new ResultPoint(pina.getX() + 0.5, pina.getY() - 0.5);\n            let pinbx = new ResultPoint(pinb.getX() + 0.5, pinb.getY() + 0.5);\n            let pincx = new ResultPoint(pinc.getX() - 0.5, pinc.getY() + 0.5);\n            let pindx = new ResultPoint(pind.getX() - 0.5, pind.getY() - 0.5);\n            // Expand the square so that its corners are the centers of the points\n            // just outside the bull's eye.\n            return this.expandSquare([pinax, pinbx, pincx, pindx], 2 * this.nbCenterLayers - 3, 2 * this.nbCenterLayers);\n        }\n        /**\n         * Finds a candidate center point of an Aztec code from an image\n         *\n         * @return the center point\n         */\n        getMatrixCenter() {\n            let pointA;\n            let pointB;\n            let pointC;\n            let pointD;\n            // Get a white rectangle that can be the border of the matrix in center bull's eye or\n            try {\n                let cornerPoints = new WhiteRectangleDetector(this.image).detect();\n                pointA = cornerPoints[0];\n                pointB = cornerPoints[1];\n                pointC = cornerPoints[2];\n                pointD = cornerPoints[3];\n            }\n            catch (e) {\n                // This exception can be in case the initial rectangle is white\n                // In that case, surely in the bull's eye, we try to expand the rectangle.\n                let cx = this.image.getWidth() / 2;\n                let cy = this.image.getHeight() / 2;\n                pointA = this.getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toResultPoint();\n                pointB = this.getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toResultPoint();\n                pointC = this.getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint();\n                pointD = this.getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint();\n            }\n            // Compute the center of the rectangle\n            let cx = MathUtils.round((pointA.getX() + pointD.getX() + pointB.getX() + pointC.getX()) / 4.0);\n            let cy = MathUtils.round((pointA.getY() + pointD.getY() + pointB.getY() + pointC.getY()) / 4.0);\n            // Redetermine the white rectangle starting from previously computed center.\n            // This will ensure that we end up with a white rectangle in center bull's eye\n            // in order to compute a more accurate center.\n            try {\n                let cornerPoints = new WhiteRectangleDetector(this.image, 15, cx, cy).detect();\n                pointA = cornerPoints[0];\n                pointB = cornerPoints[1];\n                pointC = cornerPoints[2];\n                pointD = cornerPoints[3];\n            }\n            catch (e) {\n                // This exception can be in case the initial rectangle is white\n                // In that case we try to expand the rectangle.\n                pointA = this.getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toResultPoint();\n                pointB = this.getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toResultPoint();\n                pointC = this.getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint();\n                pointD = this.getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint();\n            }\n            // Recompute the center of the rectangle\n            cx = MathUtils.round((pointA.getX() + pointD.getX() + pointB.getX() + pointC.getX()) / 4.0);\n            cy = MathUtils.round((pointA.getY() + pointD.getY() + pointB.getY() + pointC.getY()) / 4.0);\n            return new Point(cx, cy);\n        }\n        /**\n         * Gets the Aztec code corners from the bull's eye corners and the parameters.\n         *\n         * @param bullsEyeCorners the array of bull's eye corners\n         * @return the array of aztec code corners\n         */\n        getMatrixCornerPoints(bullsEyeCorners) {\n            return this.expandSquare(bullsEyeCorners, 2 * this.nbCenterLayers, this.getDimension());\n        }\n        /**\n         * Creates a BitMatrix by sampling the provided image.\n         * topLeft, topRight, bottomRight, and bottomLeft are the centers of the squares on the\n         * diagonal just outside the bull's eye.\n         */\n        sampleGrid(image, topLeft, topRight, bottomRight, bottomLeft) {\n            let sampler = GridSamplerInstance.getInstance();\n            let dimension = this.getDimension();\n            let low = dimension / 2 - this.nbCenterLayers;\n            let high = dimension / 2 + this.nbCenterLayers;\n            return sampler.sampleGrid(image, dimension, dimension, low, low, // topleft\n            high, low, // topright\n            high, high, // bottomright\n            low, high, // bottomleft\n            topLeft.getX(), topLeft.getY(), topRight.getX(), topRight.getY(), bottomRight.getX(), bottomRight.getY(), bottomLeft.getX(), bottomLeft.getY());\n        }\n        /**\n         * Samples a line.\n         *\n         * @param p1   start point (inclusive)\n         * @param p2   end point (exclusive)\n         * @param size number of bits\n         * @return the array of bits as an int (first bit is high-order bit of result)\n         */\n        sampleLine(p1, p2, size) {\n            let result = 0;\n            let d = this.distanceResultPoint(p1, p2);\n            let moduleSize = d / size;\n            let px = p1.getX();\n            let py = p1.getY();\n            let dx = moduleSize * (p2.getX() - p1.getX()) / d;\n            let dy = moduleSize * (p2.getY() - p1.getY()) / d;\n            for (let i = 0; i < size; i++) {\n                if (this.image.get(MathUtils.round(px + i * dx), MathUtils.round(py + i * dy))) {\n                    result |= 1 << (size - i - 1);\n                }\n            }\n            return result;\n        }\n        /**\n         * @return true if the border of the rectangle passed in parameter is compound of white points only\n         *         or black points only\n         */\n        isWhiteOrBlackRectangle(p1, p2, p3, p4) {\n            let corr = 3;\n            p1 = new Point(p1.getX() - corr, p1.getY() + corr);\n            p2 = new Point(p2.getX() - corr, p2.getY() - corr);\n            p3 = new Point(p3.getX() + corr, p3.getY() - corr);\n            p4 = new Point(p4.getX() + corr, p4.getY() + corr);\n            let cInit = this.getColor(p4, p1);\n            if (cInit === 0) {\n                return false;\n            }\n            let c = this.getColor(p1, p2);\n            if (c !== cInit) {\n                return false;\n            }\n            c = this.getColor(p2, p3);\n            if (c !== cInit) {\n                return false;\n            }\n            c = this.getColor(p3, p4);\n            return c === cInit;\n        }\n        /**\n         * Gets the color of a segment\n         *\n         * @return 1 if segment more than 90% black, -1 if segment is more than 90% white, 0 else\n         */\n        getColor(p1, p2) {\n            let d = this.distancePoint(p1, p2);\n            let dx = (p2.getX() - p1.getX()) / d;\n            let dy = (p2.getY() - p1.getY()) / d;\n            let error = 0;\n            let px = p1.getX();\n            let py = p1.getY();\n            let colorModel = this.image.get(p1.getX(), p1.getY());\n            let iMax = Math.ceil(d);\n            for (let i = 0; i < iMax; i++) {\n                px += dx;\n                py += dy;\n                if (this.image.get(MathUtils.round(px), MathUtils.round(py)) !== colorModel) {\n                    error++;\n                }\n            }\n            let errRatio = error / d;\n            if (errRatio > 0.1 && errRatio < 0.9) {\n                return 0;\n            }\n            return (errRatio <= 0.1) === colorModel ? 1 : -1;\n        }\n        /**\n         * Gets the coordinate of the first point with a different color in the given direction\n         */\n        getFirstDifferent(init, color, dx, dy) {\n            let x = init.getX() + dx;\n            let y = init.getY() + dy;\n            while (this.isValid(x, y) && this.image.get(x, y) === color) {\n                x += dx;\n                y += dy;\n            }\n            x -= dx;\n            y -= dy;\n            while (this.isValid(x, y) && this.image.get(x, y) === color) {\n                x += dx;\n            }\n            x -= dx;\n            while (this.isValid(x, y) && this.image.get(x, y) === color) {\n                y += dy;\n            }\n            y -= dy;\n            return new Point(x, y);\n        }\n        /**\n         * Expand the square represented by the corner points by pushing out equally in all directions\n         *\n         * @param cornerPoints the corners of the square, which has the bull's eye at its center\n         * @param oldSide the original length of the side of the square in the target bit matrix\n         * @param newSide the new length of the size of the square in the target bit matrix\n         * @return the corners of the expanded square\n         */\n        expandSquare(cornerPoints, oldSide, newSide) {\n            let ratio = newSide / (2.0 * oldSide);\n            let dx = cornerPoints[0].getX() - cornerPoints[2].getX();\n            let dy = cornerPoints[0].getY() - cornerPoints[2].getY();\n            let centerx = (cornerPoints[0].getX() + cornerPoints[2].getX()) / 2.0;\n            let centery = (cornerPoints[0].getY() + cornerPoints[2].getY()) / 2.0;\n            let result0 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy);\n            let result2 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy);\n            dx = cornerPoints[1].getX() - cornerPoints[3].getX();\n            dy = cornerPoints[1].getY() - cornerPoints[3].getY();\n            centerx = (cornerPoints[1].getX() + cornerPoints[3].getX()) / 2.0;\n            centery = (cornerPoints[1].getY() + cornerPoints[3].getY()) / 2.0;\n            let result1 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy);\n            let result3 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy);\n            let results = [result0, result1, result2, result3];\n            return results;\n        }\n        isValid(x, y) {\n            return x >= 0 && x < this.image.getWidth() && y > 0 && y < this.image.getHeight();\n        }\n        isValidPoint(point) {\n            let x = MathUtils.round(point.getX());\n            let y = MathUtils.round(point.getY());\n            return this.isValid(x, y);\n        }\n        distancePoint(a, b) {\n            return MathUtils.distance(a.getX(), a.getY(), b.getX(), b.getY());\n        }\n        distanceResultPoint(a, b) {\n            return MathUtils.distance(a.getX(), a.getY(), b.getX(), b.getY());\n        }\n        getDimension() {\n            if (this.compact) {\n                return 4 * this.nbLayers + 11;\n            }\n            if (this.nbLayers <= 4) {\n                return 4 * this.nbLayers + 15;\n            }\n            return 4 * this.nbLayers + 2 * (Integer.truncDivision((this.nbLayers - 4), 8) + 1) + 15;\n        }\n    }\n\n    /*\n     * Copyright 2010 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    // import java.util.List;\n    // import java.util.Map;\n    /**\n     * This implementation can detect and decode Aztec codes in an image.\n     *\n     * @author David Olivier\n     */\n    class AztecReader {\n        /**\n         * Locates and decodes a Data Matrix code in an image.\n         *\n         * @return a String representing the content encoded by the Data Matrix code\n         * @throws NotFoundException if a Data Matrix code cannot be found\n         * @throws FormatException if a Data Matrix code cannot be decoded\n         */\n        decode(image, hints = null) {\n            let exception = null;\n            let detector = new Detector(image.getBlackMatrix());\n            let points = null;\n            let decoderResult = null;\n            try {\n                let detectorResult = detector.detectMirror(false);\n                points = detectorResult.getPoints();\n                this.reportFoundResultPoints(hints, points);\n                decoderResult = new Decoder().decode(detectorResult);\n            }\n            catch (e) {\n                exception = e;\n            }\n            if (decoderResult == null) {\n                try {\n                    let detectorResult = detector.detectMirror(true);\n                    points = detectorResult.getPoints();\n                    this.reportFoundResultPoints(hints, points);\n                    decoderResult = new Decoder().decode(detectorResult);\n                }\n                catch (e) {\n                    if (exception != null) {\n                        throw exception;\n                    }\n                    throw e;\n                }\n            }\n            let result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), decoderResult.getNumBits(), points, BarcodeFormat$1.AZTEC, System.currentTimeMillis());\n            let byteSegments = decoderResult.getByteSegments();\n            if (byteSegments != null) {\n                result.putMetadata(ResultMetadataType$1.BYTE_SEGMENTS, byteSegments);\n            }\n            let ecLevel = decoderResult.getECLevel();\n            if (ecLevel != null) {\n                result.putMetadata(ResultMetadataType$1.ERROR_CORRECTION_LEVEL, ecLevel);\n            }\n            return result;\n        }\n        reportFoundResultPoints(hints, points) {\n            if (hints != null) {\n                let rpcb = hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n                if (rpcb != null) {\n                    points.forEach((point, idx, arr) => {\n                        rpcb.foundPossibleResultPoint(point);\n                    });\n                }\n            }\n        }\n        // @Override\n        reset() {\n            // do nothing\n        }\n    }\n\n    /**\n     * Aztec Code reader to use from browser.\n     *\n     * @class BrowserAztecCodeReader\n     * @extends {BrowserCodeReader}\n     */\n    class BrowserAztecCodeReader extends BrowserCodeReader {\n        /**\n         * Creates an instance of BrowserAztecCodeReader.\n         * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n         *\n         * @memberOf BrowserAztecCodeReader\n         */\n        constructor(timeBetweenScansMillis = 500) {\n            super(new AztecReader(), timeBetweenScansMillis);\n        }\n    }\n\n    /**\n     * Encapsulates functionality and implementation that is common to all families\n     * of one-dimensional barcodes.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @author Sean Owen\n     */\n    class OneDReader {\n        /*\n        @Override\n        public Result decode(BinaryBitmap image) throws NotFoundException, FormatException {\n          return decode(image, null);\n        }\n        */\n        // Note that we don't try rotation without the try harder flag, even if rotation was supported.\n        // @Override\n        decode(image, hints) {\n            try {\n                return this.doDecode(image, hints);\n            }\n            catch (nfe) {\n                const tryHarder = hints && (hints.get(DecodeHintType$1.TRY_HARDER) === true);\n                if (tryHarder && image.isRotateSupported()) {\n                    const rotatedImage = image.rotateCounterClockwise();\n                    const result = this.doDecode(rotatedImage, hints);\n                    // Record that we found it rotated 90 degrees CCW / 270 degrees CW\n                    const metadata = result.getResultMetadata();\n                    let orientation = 270;\n                    if (metadata !== null && (metadata.get(ResultMetadataType$1.ORIENTATION) === true)) {\n                        // But if we found it reversed in doDecode(), add in that result here:\n                        orientation = (orientation + metadata.get(ResultMetadataType$1.ORIENTATION) % 360);\n                    }\n                    result.putMetadata(ResultMetadataType$1.ORIENTATION, orientation);\n                    // Update result points\n                    const points = result.getResultPoints();\n                    if (points !== null) {\n                        const height = rotatedImage.getHeight();\n                        for (let i = 0; i < points.length; i++) {\n                            points[i] = new ResultPoint(height - points[i].getY() - 1, points[i].getX());\n                        }\n                    }\n                    return result;\n                }\n                else {\n                    throw new NotFoundException();\n                }\n            }\n        }\n        // @Override\n        reset() {\n            // do nothing\n        }\n        /**\n         * We're going to examine rows from the middle outward, searching alternately above and below the\n         * middle, and farther out each time. rowStep is the number of rows between each successive\n         * attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then\n         * middle + rowStep, then middle - (2 * rowStep), etc.\n         * rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily\n         * decided that moving up and down by about 1/16 of the image is pretty good; we try more of the\n         * image if \"trying harder\".\n         *\n         * @param image The image to decode\n         * @param hints Any hints that were requested\n         * @return The contents of the decoded barcode\n         * @throws NotFoundException Any spontaneous errors which occur\n         */\n        doDecode(image, hints) {\n            const width = image.getWidth();\n            const height = image.getHeight();\n            let row = new BitArray(width);\n            const tryHarder = hints && (hints.get(DecodeHintType$1.TRY_HARDER) === true);\n            const rowStep = Math.max(1, height >> (tryHarder ? 8 : 5));\n            let maxLines;\n            if (tryHarder) {\n                maxLines = height; // Look at the whole image, not just the center\n            }\n            else {\n                maxLines = 15; // 15 rows spaced 1/32 apart is roughly the middle half of the image\n            }\n            const middle = Math.trunc(height / 2);\n            for (let x = 0; x < maxLines; x++) {\n                // Scanning from the middle out. Determine which row we're looking at next:\n                const rowStepsAboveOrBelow = Math.trunc((x + 1) / 2);\n                const isAbove = (x & 0x01) === 0; // i.e. is x even?\n                const rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow);\n                if (rowNumber < 0 || rowNumber >= height) {\n                    // Oops, if we run off the top or bottom, stop\n                    break;\n                }\n                // Estimate black point for this row and load it:\n                try {\n                    row = image.getBlackRow(rowNumber, row);\n                }\n                catch (ignored) {\n                    continue;\n                }\n                // While we have the image data in a BitArray, it's fairly cheap to reverse it in place to\n                // handle decoding upside down barcodes.\n                for (let attempt = 0; attempt < 2; attempt++) {\n                    if (attempt === 1) { // trying again?\n                        row.reverse(); // reverse the row and continue\n                        // This means we will only ever draw result points *once* in the life of this method\n                        // since we want to avoid drawing the wrong points after flipping the row, and,\n                        // don't want to clutter with noise from every single row scan -- just the scans\n                        // that start on the center line.\n                        if (hints && (hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK) === true)) {\n                            const newHints = new Map();\n                            hints.forEach((hint, key) => newHints.set(key, hint));\n                            newHints.delete(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n                            hints = newHints;\n                        }\n                    }\n                    try {\n                        // Look for a barcode\n                        const result = this.decodeRow(rowNumber, row, hints);\n                        // We found our barcode\n                        if (attempt === 1) {\n                            // But it was upside down, so note that\n                            result.putMetadata(ResultMetadataType$1.ORIENTATION, 180);\n                            // And remember to flip the result points horizontally.\n                            const points = result.getResultPoints();\n                            if (points !== null) {\n                                points[0] = new ResultPoint(width - points[0].getX() - 1, points[0].getY());\n                                points[1] = new ResultPoint(width - points[1].getX() - 1, points[1].getY());\n                            }\n                        }\n                        return result;\n                    }\n                    catch (re) {\n                        // continue -- just couldn't decode this row\n                    }\n                }\n            }\n            throw new NotFoundException();\n        }\n        /**\n         * Records the size of successive runs of white and black pixels in a row, starting at a given point.\n         * The values are recorded in the given array, and the number of runs recorded is equal to the size\n         * of the array. If the row starts on a white pixel at the given start point, then the first count\n         * recorded is the run of white pixels starting from that point; likewise it is the count of a run\n         * of black pixels if the row begin on a black pixels at that point.\n         *\n         * @param row row to count from\n         * @param start offset into row to start at\n         * @param counters array into which to record counts\n         * @throws NotFoundException if counters cannot be filled entirely from row before running out\n         *  of pixels\n         */\n        static recordPattern(row, start, counters) {\n            const numCounters = counters.length;\n            for (let index = 0; index < numCounters; index++)\n                counters[index] = 0;\n            const end = row.getSize();\n            if (start >= end) {\n                throw new NotFoundException();\n            }\n            let isWhite = !row.get(start);\n            let counterPosition = 0;\n            let i = start;\n            while (i < end) {\n                if (row.get(i) !== isWhite) {\n                    counters[counterPosition]++;\n                }\n                else {\n                    if (++counterPosition === numCounters) {\n                        break;\n                    }\n                    else {\n                        counters[counterPosition] = 1;\n                        isWhite = !isWhite;\n                    }\n                }\n                i++;\n            }\n            // If we read fully the last section of pixels and filled up our counters -- or filled\n            // the last counter but ran off the side of the image, OK. Otherwise, a problem.\n            if (!(counterPosition === numCounters || (counterPosition === numCounters - 1 && i === end))) {\n                throw new NotFoundException();\n            }\n        }\n        static recordPatternInReverse(row, start, counters) {\n            // This could be more efficient I guess\n            let numTransitionsLeft = counters.length;\n            let last = row.get(start);\n            while (start > 0 && numTransitionsLeft >= 0) {\n                if (row.get(--start) !== last) {\n                    numTransitionsLeft--;\n                    last = !last;\n                }\n            }\n            if (numTransitionsLeft >= 0) {\n                throw new NotFoundException();\n            }\n            OneDReader.recordPattern(row, start + 1, counters);\n        }\n        /**\n         * Determines how closely a set of observed counts of runs of black/white values matches a given\n         * target pattern. This is reported as the ratio of the total variance from the expected pattern\n         * proportions across all pattern elements, to the length of the pattern.\n         *\n         * @param counters observed counters\n         * @param pattern expected pattern\n         * @param maxIndividualVariance The most any counter can differ before we give up\n         * @return ratio of total variance between counters and pattern compared to total pattern size\n         */\n        static patternMatchVariance(counters, pattern, maxIndividualVariance) {\n            const numCounters = counters.length;\n            let total = 0;\n            let patternLength = 0;\n            for (let i = 0; i < numCounters; i++) {\n                total += counters[i];\n                patternLength += pattern[i];\n            }\n            if (total < patternLength) {\n                // If we don't even have one pixel per unit of bar width, assume this is too small\n                // to reliably match, so fail:\n                return Number.POSITIVE_INFINITY;\n            }\n            const unitBarWidth = total / patternLength;\n            maxIndividualVariance *= unitBarWidth;\n            let totalVariance = 0.0;\n            for (let x = 0; x < numCounters; x++) {\n                const counter = counters[x];\n                const scaledPattern = pattern[x] * unitBarWidth;\n                const variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter;\n                if (variance > maxIndividualVariance) {\n                    return Number.POSITIVE_INFINITY;\n                }\n                totalVariance += variance;\n            }\n            return totalVariance / total;\n        }\n    }\n\n    /**\n     * <p>Decodes Code 128 barcodes.</p>\n     *\n     * @author Sean Owen\n     */\n    class Code128Reader extends OneDReader {\n        static findStartPattern(row) {\n            const width = row.getSize();\n            const rowOffset = row.getNextSet(0);\n            let counterPosition = 0;\n            let counters = Int32Array.from([0, 0, 0, 0, 0, 0]);\n            let patternStart = rowOffset;\n            let isWhite = false;\n            const patternLength = 6;\n            for (let i = rowOffset; i < width; i++) {\n                if (row.get(i) !== isWhite) {\n                    counters[counterPosition]++;\n                }\n                else {\n                    if (counterPosition === (patternLength - 1)) {\n                        let bestVariance = Code128Reader.MAX_AVG_VARIANCE;\n                        let bestMatch = -1;\n                        for (let startCode = Code128Reader.CODE_START_A; startCode <= Code128Reader.CODE_START_C; startCode++) {\n                            const variance = OneDReader.patternMatchVariance(counters, Code128Reader.CODE_PATTERNS[startCode], Code128Reader.MAX_INDIVIDUAL_VARIANCE);\n                            if (variance < bestVariance) {\n                                bestVariance = variance;\n                                bestMatch = startCode;\n                            }\n                        }\n                        // Look for whitespace before start pattern, >= 50% of width of start pattern\n                        if (bestMatch >= 0 &&\n                            row.isRange(Math.max(0, patternStart - (i - patternStart) / 2), patternStart, false)) {\n                            return Int32Array.from([patternStart, i, bestMatch]);\n                        }\n                        patternStart += counters[0] + counters[1];\n                        counters = counters.slice(2, counters.length - 1);\n                        counters[counterPosition - 1] = 0;\n                        counters[counterPosition] = 0;\n                        counterPosition--;\n                    }\n                    else {\n                        counterPosition++;\n                    }\n                    counters[counterPosition] = 1;\n                    isWhite = !isWhite;\n                }\n            }\n            throw new NotFoundException();\n        }\n        static decodeCode(row, counters, rowOffset) {\n            OneDReader.recordPattern(row, rowOffset, counters);\n            let bestVariance = Code128Reader.MAX_AVG_VARIANCE; // worst variance we'll accept\n            let bestMatch = -1;\n            for (let d = 0; d < Code128Reader.CODE_PATTERNS.length; d++) {\n                const pattern = Code128Reader.CODE_PATTERNS[d];\n                const variance = this.patternMatchVariance(counters, pattern, Code128Reader.MAX_INDIVIDUAL_VARIANCE);\n                if (variance < bestVariance) {\n                    bestVariance = variance;\n                    bestMatch = d;\n                }\n            }\n            // TODO We're overlooking the fact that the STOP pattern has 7 values, not 6.\n            if (bestMatch >= 0) {\n                return bestMatch;\n            }\n            else {\n                throw new NotFoundException();\n            }\n        }\n        decodeRow(rowNumber, row, hints) {\n            const convertFNC1 = hints && (hints.get(DecodeHintType$1.ASSUME_GS1) === true);\n            const startPatternInfo = Code128Reader.findStartPattern(row);\n            const startCode = startPatternInfo[2];\n            let currentRawCodesIndex = 0;\n            const rawCodes = new Uint8Array(20);\n            rawCodes[currentRawCodesIndex++] = startCode;\n            let codeSet;\n            switch (startCode) {\n                case Code128Reader.CODE_START_A:\n                    codeSet = Code128Reader.CODE_CODE_A;\n                    break;\n                case Code128Reader.CODE_START_B:\n                    codeSet = Code128Reader.CODE_CODE_B;\n                    break;\n                case Code128Reader.CODE_START_C:\n                    codeSet = Code128Reader.CODE_CODE_C;\n                    break;\n                default:\n                    throw new FormatException();\n            }\n            let done = false;\n            let isNextShifted = false;\n            let result = '';\n            let lastStart = startPatternInfo[0];\n            let nextStart = startPatternInfo[1];\n            const counters = Int32Array.from([0, 0, 0, 0, 0, 0]);\n            let lastCode = 0;\n            let code = 0;\n            let checksumTotal = startCode;\n            let multiplier = 0;\n            let lastCharacterWasPrintable = true;\n            let upperMode = false;\n            let shiftUpperMode = false;\n            while (!done) {\n                const unshift = isNextShifted;\n                isNextShifted = false;\n                // Save off last code\n                lastCode = code;\n                // Decode another code from image\n                code = Code128Reader.decodeCode(row, counters, nextStart);\n                rawCodes[currentRawCodesIndex++] = code;\n                // Remember whether the last code was printable or not (excluding CODE_STOP)\n                if (code !== Code128Reader.CODE_STOP) {\n                    lastCharacterWasPrintable = true;\n                }\n                // Add to checksum computation (if not CODE_STOP of course)\n                if (code !== Code128Reader.CODE_STOP) {\n                    multiplier++;\n                    checksumTotal += multiplier * code;\n                }\n                // Advance to where the next code will to start\n                lastStart = nextStart;\n                nextStart += counters.reduce((previous, current) => previous + current, 0);\n                // Take care of illegal start codes\n                switch (code) {\n                    case Code128Reader.CODE_START_A:\n                    case Code128Reader.CODE_START_B:\n                    case Code128Reader.CODE_START_C:\n                        throw new FormatException();\n                }\n                switch (codeSet) {\n                    case Code128Reader.CODE_CODE_A:\n                        if (code < 64) {\n                            if (shiftUpperMode === upperMode) {\n                                result += String.fromCharCode((' '.charCodeAt(0) + code));\n                            }\n                            else {\n                                result += String.fromCharCode((' '.charCodeAt(0) + code + 128));\n                            }\n                            shiftUpperMode = false;\n                        }\n                        else if (code < 96) {\n                            if (shiftUpperMode === upperMode) {\n                                result += String.fromCharCode((code - 64));\n                            }\n                            else {\n                                result += String.fromCharCode((code + 64));\n                            }\n                            shiftUpperMode = false;\n                        }\n                        else {\n                            // Don't let CODE_STOP, which always appears, affect whether whether we think the last\n                            // code was printable or not.\n                            if (code !== Code128Reader.CODE_STOP) {\n                                lastCharacterWasPrintable = false;\n                            }\n                            switch (code) {\n                                case Code128Reader.CODE_FNC_1:\n                                    if (convertFNC1) {\n                                        if (result.length === 0) {\n                                            // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code\n                                            // is FNC1 then this is GS1-128. We add the symbology identifier.\n                                            result += ']C1';\n                                        }\n                                        else {\n                                            // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS)\n                                            result += String.fromCharCode(29);\n                                        }\n                                    }\n                                    break;\n                                case Code128Reader.CODE_FNC_2:\n                                case Code128Reader.CODE_FNC_3:\n                                    // do nothing?\n                                    break;\n                                case Code128Reader.CODE_FNC_4_A:\n                                    if (!upperMode && shiftUpperMode) {\n                                        upperMode = true;\n                                        shiftUpperMode = false;\n                                    }\n                                    else if (upperMode && shiftUpperMode) {\n                                        upperMode = false;\n                                        shiftUpperMode = false;\n                                    }\n                                    else {\n                                        shiftUpperMode = true;\n                                    }\n                                    break;\n                                case Code128Reader.CODE_SHIFT:\n                                    isNextShifted = true;\n                                    codeSet = Code128Reader.CODE_CODE_B;\n                                    break;\n                                case Code128Reader.CODE_CODE_B:\n                                    codeSet = Code128Reader.CODE_CODE_B;\n                                    break;\n                                case Code128Reader.CODE_CODE_C:\n                                    codeSet = Code128Reader.CODE_CODE_C;\n                                    break;\n                                case Code128Reader.CODE_STOP:\n                                    done = true;\n                                    break;\n                            }\n                        }\n                        break;\n                    case Code128Reader.CODE_CODE_B:\n                        if (code < 96) {\n                            if (shiftUpperMode === upperMode) {\n                                result += String.fromCharCode((' '.charCodeAt(0) + code));\n                            }\n                            else {\n                                result += String.fromCharCode((' '.charCodeAt(0) + code + 128));\n                            }\n                            shiftUpperMode = false;\n                        }\n                        else {\n                            if (code !== Code128Reader.CODE_STOP) {\n                                lastCharacterWasPrintable = false;\n                            }\n                            switch (code) {\n                                case Code128Reader.CODE_FNC_1:\n                                    if (convertFNC1) {\n                                        if (result.length === 0) {\n                                            // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code\n                                            // is FNC1 then this is GS1-128. We add the symbology identifier.\n                                            result += ']C1';\n                                        }\n                                        else {\n                                            // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS)\n                                            result += String.fromCharCode(29);\n                                        }\n                                    }\n                                    break;\n                                case Code128Reader.CODE_FNC_2:\n                                case Code128Reader.CODE_FNC_3:\n                                    // do nothing?\n                                    break;\n                                case Code128Reader.CODE_FNC_4_B:\n                                    if (!upperMode && shiftUpperMode) {\n                                        upperMode = true;\n                                        shiftUpperMode = false;\n                                    }\n                                    else if (upperMode && shiftUpperMode) {\n                                        upperMode = false;\n                                        shiftUpperMode = false;\n                                    }\n                                    else {\n                                        shiftUpperMode = true;\n                                    }\n                                    break;\n                                case Code128Reader.CODE_SHIFT:\n                                    isNextShifted = true;\n                                    codeSet = Code128Reader.CODE_CODE_A;\n                                    break;\n                                case Code128Reader.CODE_CODE_A:\n                                    codeSet = Code128Reader.CODE_CODE_A;\n                                    break;\n                                case Code128Reader.CODE_CODE_C:\n                                    codeSet = Code128Reader.CODE_CODE_C;\n                                    break;\n                                case Code128Reader.CODE_STOP:\n                                    done = true;\n                                    break;\n                            }\n                        }\n                        break;\n                    case Code128Reader.CODE_CODE_C:\n                        if (code < 100) {\n                            if (code < 10) {\n                                result += '0';\n                            }\n                            result += code;\n                        }\n                        else {\n                            if (code !== Code128Reader.CODE_STOP) {\n                                lastCharacterWasPrintable = false;\n                            }\n                            switch (code) {\n                                case Code128Reader.CODE_FNC_1:\n                                    if (convertFNC1) {\n                                        if (result.length === 0) {\n                                            // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code\n                                            // is FNC1 then this is GS1-128. We add the symbology identifier.\n                                            result += ']C1';\n                                        }\n                                        else {\n                                            // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS)\n                                            result += String.fromCharCode(29);\n                                        }\n                                    }\n                                    break;\n                                case Code128Reader.CODE_CODE_A:\n                                    codeSet = Code128Reader.CODE_CODE_A;\n                                    break;\n                                case Code128Reader.CODE_CODE_B:\n                                    codeSet = Code128Reader.CODE_CODE_B;\n                                    break;\n                                case Code128Reader.CODE_STOP:\n                                    done = true;\n                                    break;\n                            }\n                        }\n                        break;\n                }\n                // Unshift back to another code set if we were shifted\n                if (unshift) {\n                    codeSet = codeSet === Code128Reader.CODE_CODE_A ? Code128Reader.CODE_CODE_B : Code128Reader.CODE_CODE_A;\n                }\n            }\n            const lastPatternSize = nextStart - lastStart;\n            // Check for ample whitespace following pattern, but, to do this we first need to remember that\n            // we fudged decoding CODE_STOP since it actually has 7 bars, not 6. There is a black bar left\n            // to read off. Would be slightly better to properly read. Here we just skip it:\n            nextStart = row.getNextUnset(nextStart);\n            if (!row.isRange(nextStart, Math.min(row.getSize(), nextStart + (nextStart - lastStart) / 2), false)) {\n                throw new NotFoundException();\n            }\n            // Pull out from sum the value of the penultimate check code\n            checksumTotal -= multiplier * lastCode;\n            // lastCode is the checksum then:\n            if (checksumTotal % 103 !== lastCode) {\n                throw new ChecksumException();\n            }\n            // Need to pull out the check digits from string\n            const resultLength = result.length;\n            if (resultLength === 0) {\n                // false positive\n                throw new NotFoundException();\n            }\n            // Only bother if the result had at least one character, and if the checksum digit happened to\n            // be a printable character. If it was just interpreted as a control code, nothing to remove.\n            if (resultLength > 0 && lastCharacterWasPrintable) {\n                if (codeSet === Code128Reader.CODE_CODE_C) {\n                    result = result.substring(0, resultLength - 2);\n                }\n                else {\n                    result = result.substring(0, resultLength - 1);\n                }\n            }\n            const left = (startPatternInfo[1] + startPatternInfo[0]) / 2.0;\n            const right = lastStart + lastPatternSize / 2.0;\n            const rawCodesSize = rawCodes.length;\n            const rawBytes = new Uint8Array(rawCodesSize);\n            for (let i = 0; i < rawCodesSize; i++) {\n                rawBytes[i] = rawCodes[i];\n            }\n            const points = [new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber)];\n            return new Result(result, rawBytes, 0, points, BarcodeFormat$1.CODE_128, new Date().getTime());\n        }\n    }\n    Code128Reader.CODE_PATTERNS = [\n        Int32Array.from([2, 1, 2, 2, 2, 2]),\n        Int32Array.from([2, 2, 2, 1, 2, 2]),\n        Int32Array.from([2, 2, 2, 2, 2, 1]),\n        Int32Array.from([1, 2, 1, 2, 2, 3]),\n        Int32Array.from([1, 2, 1, 3, 2, 2]),\n        Int32Array.from([1, 3, 1, 2, 2, 2]),\n        Int32Array.from([1, 2, 2, 2, 1, 3]),\n        Int32Array.from([1, 2, 2, 3, 1, 2]),\n        Int32Array.from([1, 3, 2, 2, 1, 2]),\n        Int32Array.from([2, 2, 1, 2, 1, 3]),\n        Int32Array.from([2, 2, 1, 3, 1, 2]),\n        Int32Array.from([2, 3, 1, 2, 1, 2]),\n        Int32Array.from([1, 1, 2, 2, 3, 2]),\n        Int32Array.from([1, 2, 2, 1, 3, 2]),\n        Int32Array.from([1, 2, 2, 2, 3, 1]),\n        Int32Array.from([1, 1, 3, 2, 2, 2]),\n        Int32Array.from([1, 2, 3, 1, 2, 2]),\n        Int32Array.from([1, 2, 3, 2, 2, 1]),\n        Int32Array.from([2, 2, 3, 2, 1, 1]),\n        Int32Array.from([2, 2, 1, 1, 3, 2]),\n        Int32Array.from([2, 2, 1, 2, 3, 1]),\n        Int32Array.from([2, 1, 3, 2, 1, 2]),\n        Int32Array.from([2, 2, 3, 1, 1, 2]),\n        Int32Array.from([3, 1, 2, 1, 3, 1]),\n        Int32Array.from([3, 1, 1, 2, 2, 2]),\n        Int32Array.from([3, 2, 1, 1, 2, 2]),\n        Int32Array.from([3, 2, 1, 2, 2, 1]),\n        Int32Array.from([3, 1, 2, 2, 1, 2]),\n        Int32Array.from([3, 2, 2, 1, 1, 2]),\n        Int32Array.from([3, 2, 2, 2, 1, 1]),\n        Int32Array.from([2, 1, 2, 1, 2, 3]),\n        Int32Array.from([2, 1, 2, 3, 2, 1]),\n        Int32Array.from([2, 3, 2, 1, 2, 1]),\n        Int32Array.from([1, 1, 1, 3, 2, 3]),\n        Int32Array.from([1, 3, 1, 1, 2, 3]),\n        Int32Array.from([1, 3, 1, 3, 2, 1]),\n        Int32Array.from([1, 1, 2, 3, 1, 3]),\n        Int32Array.from([1, 3, 2, 1, 1, 3]),\n        Int32Array.from([1, 3, 2, 3, 1, 1]),\n        Int32Array.from([2, 1, 1, 3, 1, 3]),\n        Int32Array.from([2, 3, 1, 1, 1, 3]),\n        Int32Array.from([2, 3, 1, 3, 1, 1]),\n        Int32Array.from([1, 1, 2, 1, 3, 3]),\n        Int32Array.from([1, 1, 2, 3, 3, 1]),\n        Int32Array.from([1, 3, 2, 1, 3, 1]),\n        Int32Array.from([1, 1, 3, 1, 2, 3]),\n        Int32Array.from([1, 1, 3, 3, 2, 1]),\n        Int32Array.from([1, 3, 3, 1, 2, 1]),\n        Int32Array.from([3, 1, 3, 1, 2, 1]),\n        Int32Array.from([2, 1, 1, 3, 3, 1]),\n        Int32Array.from([2, 3, 1, 1, 3, 1]),\n        Int32Array.from([2, 1, 3, 1, 1, 3]),\n        Int32Array.from([2, 1, 3, 3, 1, 1]),\n        Int32Array.from([2, 1, 3, 1, 3, 1]),\n        Int32Array.from([3, 1, 1, 1, 2, 3]),\n        Int32Array.from([3, 1, 1, 3, 2, 1]),\n        Int32Array.from([3, 3, 1, 1, 2, 1]),\n        Int32Array.from([3, 1, 2, 1, 1, 3]),\n        Int32Array.from([3, 1, 2, 3, 1, 1]),\n        Int32Array.from([3, 3, 2, 1, 1, 1]),\n        Int32Array.from([3, 1, 4, 1, 1, 1]),\n        Int32Array.from([2, 2, 1, 4, 1, 1]),\n        Int32Array.from([4, 3, 1, 1, 1, 1]),\n        Int32Array.from([1, 1, 1, 2, 2, 4]),\n        Int32Array.from([1, 1, 1, 4, 2, 2]),\n        Int32Array.from([1, 2, 1, 1, 2, 4]),\n        Int32Array.from([1, 2, 1, 4, 2, 1]),\n        Int32Array.from([1, 4, 1, 1, 2, 2]),\n        Int32Array.from([1, 4, 1, 2, 2, 1]),\n        Int32Array.from([1, 1, 2, 2, 1, 4]),\n        Int32Array.from([1, 1, 2, 4, 1, 2]),\n        Int32Array.from([1, 2, 2, 1, 1, 4]),\n        Int32Array.from([1, 2, 2, 4, 1, 1]),\n        Int32Array.from([1, 4, 2, 1, 1, 2]),\n        Int32Array.from([1, 4, 2, 2, 1, 1]),\n        Int32Array.from([2, 4, 1, 2, 1, 1]),\n        Int32Array.from([2, 2, 1, 1, 1, 4]),\n        Int32Array.from([4, 1, 3, 1, 1, 1]),\n        Int32Array.from([2, 4, 1, 1, 1, 2]),\n        Int32Array.from([1, 3, 4, 1, 1, 1]),\n        Int32Array.from([1, 1, 1, 2, 4, 2]),\n        Int32Array.from([1, 2, 1, 1, 4, 2]),\n        Int32Array.from([1, 2, 1, 2, 4, 1]),\n        Int32Array.from([1, 1, 4, 2, 1, 2]),\n        Int32Array.from([1, 2, 4, 1, 1, 2]),\n        Int32Array.from([1, 2, 4, 2, 1, 1]),\n        Int32Array.from([4, 1, 1, 2, 1, 2]),\n        Int32Array.from([4, 2, 1, 1, 1, 2]),\n        Int32Array.from([4, 2, 1, 2, 1, 1]),\n        Int32Array.from([2, 1, 2, 1, 4, 1]),\n        Int32Array.from([2, 1, 4, 1, 2, 1]),\n        Int32Array.from([4, 1, 2, 1, 2, 1]),\n        Int32Array.from([1, 1, 1, 1, 4, 3]),\n        Int32Array.from([1, 1, 1, 3, 4, 1]),\n        Int32Array.from([1, 3, 1, 1, 4, 1]),\n        Int32Array.from([1, 1, 4, 1, 1, 3]),\n        Int32Array.from([1, 1, 4, 3, 1, 1]),\n        Int32Array.from([4, 1, 1, 1, 1, 3]),\n        Int32Array.from([4, 1, 1, 3, 1, 1]),\n        Int32Array.from([1, 1, 3, 1, 4, 1]),\n        Int32Array.from([1, 1, 4, 1, 3, 1]),\n        Int32Array.from([3, 1, 1, 1, 4, 1]),\n        Int32Array.from([4, 1, 1, 1, 3, 1]),\n        Int32Array.from([2, 1, 1, 4, 1, 2]),\n        Int32Array.from([2, 1, 1, 2, 1, 4]),\n        Int32Array.from([2, 1, 1, 2, 3, 2]),\n        Int32Array.from([2, 3, 3, 1, 1, 1, 2]),\n    ];\n    Code128Reader.MAX_AVG_VARIANCE = 0.25;\n    Code128Reader.MAX_INDIVIDUAL_VARIANCE = 0.7;\n    Code128Reader.CODE_SHIFT = 98;\n    Code128Reader.CODE_CODE_C = 99;\n    Code128Reader.CODE_CODE_B = 100;\n    Code128Reader.CODE_CODE_A = 101;\n    Code128Reader.CODE_FNC_1 = 102;\n    Code128Reader.CODE_FNC_2 = 97;\n    Code128Reader.CODE_FNC_3 = 96;\n    Code128Reader.CODE_FNC_4_A = 101;\n    Code128Reader.CODE_FNC_4_B = 100;\n    Code128Reader.CODE_START_A = 103;\n    Code128Reader.CODE_START_B = 104;\n    Code128Reader.CODE_START_C = 105;\n    Code128Reader.CODE_STOP = 106;\n\n    /**\n     * <p>Decodes Code 39 barcodes. Supports \"Full ASCII Code 39\" if USE_CODE_39_EXTENDED_MODE is set.</p>\n     *\n     * @author Sean Owen\n     * @see Code93Reader\n     */\n    class Code39Reader extends OneDReader {\n        /**\n         * Creates a reader that assumes all encoded data is data, and does not treat the final\n         * character as a check digit. It will not decoded \"extended Code 39\" sequences.\n         */\n        // public Code39Reader() {\n        //   this(false);\n        // }\n        /**\n         * Creates a reader that can be configured to check the last character as a check digit.\n         * It will not decoded \"extended Code 39\" sequences.\n         *\n         * @param usingCheckDigit if true, treat the last data character as a check digit, not\n         * data, and verify that the checksum passes.\n         */\n        // public Code39Reader(boolean usingCheckDigit) {\n        //   this(usingCheckDigit, false);\n        // }\n        /**\n         * Creates a reader that can be configured to check the last character as a check digit,\n         * or optionally attempt to decode \"extended Code 39\" sequences that are used to encode\n         * the full ASCII character set.\n         *\n         * @param usingCheckDigit if true, treat the last data character as a check digit, not\n         * data, and verify that the checksum passes.\n         * @param extendedMode if true, will attempt to decode extended Code 39 sequences in the\n         * text.\n         */\n        constructor(usingCheckDigit = false, extendedMode = false) {\n            super();\n            this.usingCheckDigit = usingCheckDigit;\n            this.extendedMode = extendedMode;\n            this.decodeRowResult = '';\n            this.counters = new Int32Array(9);\n        }\n        decodeRow(rowNumber, row, hints) {\n            let theCounters = this.counters;\n            theCounters.fill(0);\n            this.decodeRowResult = '';\n            let start = Code39Reader.findAsteriskPattern(row, theCounters);\n            // Read off white space\n            let nextStart = row.getNextSet(start[1]);\n            let end = row.getSize();\n            let decodedChar;\n            let lastStart;\n            do {\n                Code39Reader.recordPattern(row, nextStart, theCounters);\n                let pattern = Code39Reader.toNarrowWidePattern(theCounters);\n                if (pattern < 0) {\n                    throw new NotFoundException();\n                }\n                decodedChar = Code39Reader.patternToChar(pattern);\n                this.decodeRowResult += decodedChar;\n                lastStart = nextStart;\n                for (let counter of theCounters) {\n                    nextStart += counter;\n                }\n                // Read off white space\n                nextStart = row.getNextSet(nextStart);\n            } while (decodedChar !== '*');\n            this.decodeRowResult = this.decodeRowResult.substring(0, this.decodeRowResult.length - 1); // remove asterisk\n            // Look for whitespace after pattern:\n            let lastPatternSize = 0;\n            for (let counter of theCounters) {\n                lastPatternSize += counter;\n            }\n            let whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize;\n            // If 50% of last pattern size, following last pattern, is not whitespace, fail\n            // (but if it's whitespace to the very end of the image, that's OK)\n            if (nextStart !== end && (whiteSpaceAfterEnd * 2) < lastPatternSize) {\n                throw new NotFoundException();\n            }\n            if (this.usingCheckDigit) {\n                let max = this.decodeRowResult.length - 1;\n                let total = 0;\n                for (let i = 0; i < max; i++) {\n                    total += Code39Reader.ALPHABET_STRING.indexOf(this.decodeRowResult.charAt(i));\n                }\n                if (this.decodeRowResult.charAt(max) !== Code39Reader.ALPHABET_STRING.charAt(total % 43)) {\n                    throw new ChecksumException();\n                }\n                this.decodeRowResult = this.decodeRowResult.substring(0, max);\n            }\n            if (this.decodeRowResult.length === 0) {\n                // false positive\n                throw new NotFoundException();\n            }\n            let resultString;\n            if (this.extendedMode) {\n                resultString = Code39Reader.decodeExtended(this.decodeRowResult);\n            }\n            else {\n                resultString = this.decodeRowResult;\n            }\n            let left = (start[1] + start[0]) / 2.0;\n            let right = lastStart + lastPatternSize / 2.0;\n            return new Result(resultString, null, 0, [new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber)], BarcodeFormat$1.CODE_39, new Date().getTime());\n        }\n        static findAsteriskPattern(row, counters) {\n            let width = row.getSize();\n            let rowOffset = row.getNextSet(0);\n            let counterPosition = 0;\n            let patternStart = rowOffset;\n            let isWhite = false;\n            let patternLength = counters.length;\n            for (let i = rowOffset; i < width; i++) {\n                if (row.get(i) !== isWhite) {\n                    counters[counterPosition]++;\n                }\n                else {\n                    if (counterPosition === patternLength - 1) {\n                        // Look for whitespace before start pattern, >= 50% of width of start pattern\n                        if (this.toNarrowWidePattern(counters) === Code39Reader.ASTERISK_ENCODING &&\n                            row.isRange(Math.max(0, patternStart - Math.floor((i - patternStart) / 2)), patternStart, false)) {\n                            return [patternStart, i];\n                        }\n                        patternStart += counters[0] + counters[1];\n                        counters.copyWithin(0, 2, 2 + counterPosition - 1);\n                        counters[counterPosition - 1] = 0;\n                        counters[counterPosition] = 0;\n                        counterPosition--;\n                    }\n                    else {\n                        counterPosition++;\n                    }\n                    counters[counterPosition] = 1;\n                    isWhite = !isWhite;\n                }\n            }\n            throw new NotFoundException();\n        }\n        // For efficiency, returns -1 on failure. Not throwing here saved as many as 700 exceptions\n        // per image when using some of our blackbox images.\n        static toNarrowWidePattern(counters) {\n            let numCounters = counters.length;\n            let maxNarrowCounter = 0;\n            let wideCounters;\n            do {\n                let minCounter = 0x7fffffff;\n                for (let counter of counters) {\n                    if (counter < minCounter && counter > maxNarrowCounter) {\n                        minCounter = counter;\n                    }\n                }\n                maxNarrowCounter = minCounter;\n                wideCounters = 0;\n                let totalWideCountersWidth = 0;\n                let pattern = 0;\n                for (let i = 0; i < numCounters; i++) {\n                    let counter = counters[i];\n                    if (counter > maxNarrowCounter) {\n                        pattern |= 1 << (numCounters - 1 - i);\n                        wideCounters++;\n                        totalWideCountersWidth += counter;\n                    }\n                }\n                if (wideCounters === 3) {\n                    // Found 3 wide counters, but are they close enough in width?\n                    // We can perform a cheap, conservative check to see if any individual\n                    // counter is more than 1.5 times the average:\n                    for (let i = 0; i < numCounters && wideCounters > 0; i++) {\n                        let counter = counters[i];\n                        if (counter > maxNarrowCounter) {\n                            wideCounters--;\n                            // totalWideCountersWidth = 3 * average, so this checks if counter >= 3/2 * average\n                            if ((counter * 2) >= totalWideCountersWidth) {\n                                return -1;\n                            }\n                        }\n                    }\n                    return pattern;\n                }\n            } while (wideCounters > 3);\n            return -1;\n        }\n        static patternToChar(pattern) {\n            for (let i = 0; i < Code39Reader.CHARACTER_ENCODINGS.length; i++) {\n                if (Code39Reader.CHARACTER_ENCODINGS[i] === pattern) {\n                    return Code39Reader.ALPHABET_STRING.charAt(i);\n                }\n            }\n            if (pattern === Code39Reader.ASTERISK_ENCODING) {\n                return '*';\n            }\n            throw new NotFoundException();\n        }\n        static decodeExtended(encoded) {\n            let length = encoded.length;\n            let decoded = '';\n            for (let i = 0; i < length; i++) {\n                let c = encoded.charAt(i);\n                if (c === '+' || c === '$' || c === '%' || c === '/') {\n                    let next = encoded.charAt(i + 1);\n                    let decodedChar = '\\0';\n                    switch (c) {\n                        case '+':\n                            // +A to +Z map to a to z\n                            if (next >= 'A' && next <= 'Z') {\n                                decodedChar = String.fromCharCode(next.charCodeAt(0) + 32);\n                            }\n                            else {\n                                throw new FormatException();\n                            }\n                            break;\n                        case '$':\n                            // $A to $Z map to control codes SH to SB\n                            if (next >= 'A' && next <= 'Z') {\n                                decodedChar = String.fromCharCode(next.charCodeAt(0) - 64);\n                            }\n                            else {\n                                throw new FormatException();\n                            }\n                            break;\n                        case '%':\n                            // %A to %E map to control codes ESC to US\n                            if (next >= 'A' && next <= 'E') {\n                                decodedChar = String.fromCharCode(next.charCodeAt(0) - 38);\n                            }\n                            else if (next >= 'F' && next <= 'J') {\n                                decodedChar = String.fromCharCode(next.charCodeAt(0) - 11);\n                            }\n                            else if (next >= 'K' && next <= 'O') {\n                                decodedChar = String.fromCharCode(next.charCodeAt(0) + 16);\n                            }\n                            else if (next >= 'P' && next <= 'T') {\n                                decodedChar = String.fromCharCode(next.charCodeAt(0) + 43);\n                            }\n                            else if (next === 'U') {\n                                decodedChar = '\\0';\n                            }\n                            else if (next === 'V') {\n                                decodedChar = '@';\n                            }\n                            else if (next === 'W') {\n                                decodedChar = '`';\n                            }\n                            else if (next === 'X' || next === 'Y' || next === 'Z') {\n                                decodedChar = '\\x7f';\n                            }\n                            else {\n                                throw new FormatException();\n                            }\n                            break;\n                        case '/':\n                            // /A to /O map to ! to , and /Z maps to :\n                            if (next >= 'A' && next <= 'O') {\n                                decodedChar = String.fromCharCode(next.charCodeAt(0) - 32);\n                            }\n                            else if (next === 'Z') {\n                                decodedChar = ':';\n                            }\n                            else {\n                                throw new FormatException();\n                            }\n                            break;\n                    }\n                    decoded += decodedChar;\n                    // bump up i again since we read two characters\n                    i++;\n                }\n                else {\n                    decoded += c;\n                }\n            }\n            return decoded;\n        }\n    }\n    Code39Reader.ALPHABET_STRING = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%';\n    /**\n     * These represent the encodings of characters, as patterns of wide and narrow bars.\n     * The 9 least-significant bits of each int correspond to the pattern of wide and narrow,\n     * with 1s representing \"wide\" and 0s representing narrow.\n     */\n    Code39Reader.CHARACTER_ENCODINGS = [\n        0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064,\n        0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C,\n        0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016,\n        0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x0A8,\n        0x0A2, 0x08A, 0x02A // /-%\n    ];\n    Code39Reader.ASTERISK_ENCODING = 0x094;\n\n    /**\n     * <p>Decodes ITF barcodes.</p>\n     *\n     * @author Tjieco\n     */\n    class ITFReader extends OneDReader {\n        constructor() {\n            // private static W = 3; // Pixel width of a 3x wide line\n            // private static w = 2; // Pixel width of a 2x wide line\n            // private static N = 1; // Pixed width of a narrow line\n            super(...arguments);\n            // Stores the actual narrow line width of the image being decoded.\n            this.narrowLineWidth = -1;\n        }\n        // See ITFWriter.PATTERNS\n        /*\n      \n        /!**\n         * Patterns of Wide / Narrow lines to indicate each digit\n         *!/\n        */\n        decodeRow(rowNumber, row, hints) {\n            // Find out where the Middle section (payload) starts & ends\n            let startRange = this.decodeStart(row);\n            let endRange = this.decodeEnd(row);\n            let result = new StringBuilder();\n            ITFReader.decodeMiddle(row, startRange[1], endRange[0], result);\n            let resultString = result.toString();\n            let allowedLengths = null;\n            if (hints != null) {\n                allowedLengths = hints.get(DecodeHintType$1.ALLOWED_LENGTHS);\n            }\n            if (allowedLengths == null) {\n                allowedLengths = ITFReader.DEFAULT_ALLOWED_LENGTHS;\n            }\n            // To avoid false positives with 2D barcodes (and other patterns), make\n            // an assumption that the decoded string must be a 'standard' length if it's short\n            let length = resultString.length;\n            let lengthOK = false;\n            let maxAllowedLength = 0;\n            for (let value of allowedLengths) {\n                if (length === value) {\n                    lengthOK = true;\n                    break;\n                }\n                if (value > maxAllowedLength) {\n                    maxAllowedLength = value;\n                }\n            }\n            if (!lengthOK && length > maxAllowedLength) {\n                lengthOK = true;\n            }\n            if (!lengthOK) {\n                throw new FormatException();\n            }\n            const points = [new ResultPoint(startRange[1], rowNumber), new ResultPoint(endRange[0], rowNumber)];\n            let resultReturn = new Result(resultString, null, // no natural byte representation for these barcodes\n            0, points, BarcodeFormat$1.ITF, new Date().getTime());\n            return resultReturn;\n        }\n        /*\n        /!**\n         * @param row          row of black/white values to search\n         * @param payloadStart offset of start pattern\n         * @param resultString {@link StringBuilder} to append decoded chars to\n         * @throws NotFoundException if decoding could not complete successfully\n         *!/*/\n        static decodeMiddle(row, payloadStart, payloadEnd, resultString) {\n            // Digits are interleaved in pairs - 5 black lines for one digit, and the\n            // 5\n            // interleaved white lines for the second digit.\n            // Therefore, need to scan 10 lines and then\n            // split these into two arrays\n            let counterDigitPair = new Int32Array(10); // 10\n            let counterBlack = new Int32Array(5); // 5\n            let counterWhite = new Int32Array(5); // 5\n            counterDigitPair.fill(0);\n            counterBlack.fill(0);\n            counterWhite.fill(0);\n            while (payloadStart < payloadEnd) {\n                // Get 10 runs of black/white.\n                OneDReader.recordPattern(row, payloadStart, counterDigitPair);\n                // Split them into each array\n                for (let k = 0; k < 5; k++) {\n                    let twoK = 2 * k;\n                    counterBlack[k] = counterDigitPair[twoK];\n                    counterWhite[k] = counterDigitPair[twoK + 1];\n                }\n                let bestMatch = ITFReader.decodeDigit(counterBlack);\n                resultString.append(bestMatch.toString());\n                bestMatch = this.decodeDigit(counterWhite);\n                resultString.append(bestMatch.toString());\n                counterDigitPair.forEach(function (counterDigit) {\n                    payloadStart += counterDigit;\n                });\n            }\n        }\n        /*/!**\n         * Identify where the start of the middle / payload section starts.\n         *\n         * @param row row of black/white values to search\n         * @return Array, containing index of start of 'start block' and end of\n         *         'start block'\n         *!/*/\n        decodeStart(row) {\n            let endStart = ITFReader.skipWhiteSpace(row);\n            let startPattern = ITFReader.findGuardPattern(row, endStart, ITFReader.START_PATTERN);\n            // Determine the width of a narrow line in pixels. We can do this by\n            // getting the width of the start pattern and dividing by 4 because its\n            // made up of 4 narrow lines.\n            this.narrowLineWidth = (startPattern[1] - startPattern[0]) / 4;\n            this.validateQuietZone(row, startPattern[0]);\n            return startPattern;\n        }\n        /*/!**\n         * The start & end patterns must be pre/post fixed by a quiet zone. This\n         * zone must be at least 10 times the width of a narrow line.  Scan back until\n         * we either get to the start of the barcode or match the necessary number of\n         * quiet zone pixels.\n         *\n         * Note: Its assumed the row is reversed when using this method to find\n         * quiet zone after the end pattern.\n         *\n         * ref: http://www.barcode-1.net/i25code.html\n         *\n         * @param row bit array representing the scanned barcode.\n         * @param startPattern index into row of the start or end pattern.\n         * @throws NotFoundException if the quiet zone cannot be found\n         *!/*/\n        validateQuietZone(row, startPattern) {\n            let quietCount = this.narrowLineWidth * 10; // expect to find this many pixels of quiet zone\n            // if there are not so many pixel at all let's try as many as possible\n            quietCount = quietCount < startPattern ? quietCount : startPattern;\n            for (let i = startPattern - 1; quietCount > 0 && i >= 0; i--) {\n                if (row.get(i)) {\n                    break;\n                }\n                quietCount--;\n            }\n            if (quietCount !== 0) {\n                // Unable to find the necessary number of quiet zone pixels.\n                throw new NotFoundException();\n            }\n        }\n        /*\n        /!**\n         * Skip all whitespace until we get to the first black line.\n         *\n         * @param row row of black/white values to search\n         * @return index of the first black line.\n         * @throws NotFoundException Throws exception if no black lines are found in the row\n         *!/*/\n        static skipWhiteSpace(row) {\n            const width = row.getSize();\n            const endStart = row.getNextSet(0);\n            if (endStart === width) {\n                throw new NotFoundException();\n            }\n            return endStart;\n        }\n        /*/!**\n         * Identify where the end of the middle / payload section ends.\n         *\n         * @param row row of black/white values to search\n         * @return Array, containing index of start of 'end block' and end of 'end\n         *         block'\n         *!/*/\n        decodeEnd(row) {\n            // For convenience, reverse the row and then\n            // search from 'the start' for the end block\n            row.reverse();\n            try {\n                let endStart = ITFReader.skipWhiteSpace(row);\n                let endPattern;\n                try {\n                    endPattern = ITFReader.findGuardPattern(row, endStart, ITFReader.END_PATTERN_REVERSED[0]);\n                }\n                catch (error) {\n                    if (error instanceof NotFoundException) {\n                        endPattern = ITFReader.findGuardPattern(row, endStart, ITFReader.END_PATTERN_REVERSED[1]);\n                    }\n                }\n                // The start & end patterns must be pre/post fixed by a quiet zone. This\n                // zone must be at least 10 times the width of a narrow line.\n                // ref: http://www.barcode-1.net/i25code.html\n                this.validateQuietZone(row, endPattern[0]);\n                // Now recalculate the indices of where the 'endblock' starts & stops to\n                // accommodate\n                // the reversed nature of the search\n                let temp = endPattern[0];\n                endPattern[0] = row.getSize() - endPattern[1];\n                endPattern[1] = row.getSize() - temp;\n                return endPattern;\n            }\n            finally {\n                // Put the row back the right way.\n                row.reverse();\n            }\n        }\n        /*\n        /!**\n         * @param row       row of black/white values to search\n         * @param rowOffset position to start search\n         * @param pattern   pattern of counts of number of black and white pixels that are\n         *                  being searched for as a pattern\n         * @return start/end horizontal offset of guard pattern, as an array of two\n         *         ints\n         * @throws NotFoundException if pattern is not found\n         *!/*/\n        static findGuardPattern(row, rowOffset, pattern) {\n            let patternLength = pattern.length;\n            let counters = new Int32Array(patternLength);\n            let width = row.getSize();\n            let isWhite = false;\n            let counterPosition = 0;\n            let patternStart = rowOffset;\n            counters.fill(0);\n            for (let x = rowOffset; x < width; x++) {\n                if (row.get(x) !== isWhite) {\n                    counters[counterPosition]++;\n                }\n                else {\n                    if (counterPosition === patternLength - 1) {\n                        if (OneDReader.patternMatchVariance(counters, pattern, ITFReader.MAX_INDIVIDUAL_VARIANCE) < ITFReader.MAX_AVG_VARIANCE) {\n                            return [patternStart, x];\n                        }\n                        patternStart += counters[0] + counters[1];\n                        System.arraycopy(counters, 2, counters, 0, counterPosition - 1);\n                        counters[counterPosition - 1] = 0;\n                        counters[counterPosition] = 0;\n                        counterPosition--;\n                    }\n                    else {\n                        counterPosition++;\n                    }\n                    counters[counterPosition] = 1;\n                    isWhite = !isWhite;\n                }\n            }\n            throw new NotFoundException();\n        }\n        /*/!**\n         * Attempts to decode a sequence of ITF black/white lines into single\n         * digit.\n         *\n         * @param counters the counts of runs of observed black/white/black/... values\n         * @return The decoded digit\n         * @throws NotFoundException if digit cannot be decoded\n         *!/*/\n        static decodeDigit(counters) {\n            let bestVariance = ITFReader.MAX_AVG_VARIANCE; // worst variance we'll accept\n            let bestMatch = -1;\n            let max = ITFReader.PATTERNS.length;\n            for (let i = 0; i < max; i++) {\n                let pattern = ITFReader.PATTERNS[i];\n                let variance = OneDReader.patternMatchVariance(counters, pattern, ITFReader.MAX_INDIVIDUAL_VARIANCE);\n                if (variance < bestVariance) {\n                    bestVariance = variance;\n                    bestMatch = i;\n                }\n                else if (variance === bestVariance) {\n                    // if we find a second 'best match' with the same variance, we can not reliably report to have a suitable match\n                    bestMatch = -1;\n                }\n            }\n            if (bestMatch >= 0) {\n                return bestMatch % 10;\n            }\n            else {\n                throw new NotFoundException();\n            }\n        }\n    }\n    ITFReader.PATTERNS = [\n        Int32Array.from([1, 1, 2, 2, 1]),\n        Int32Array.from([2, 1, 1, 1, 2]),\n        Int32Array.from([1, 2, 1, 1, 2]),\n        Int32Array.from([2, 2, 1, 1, 1]),\n        Int32Array.from([1, 1, 2, 1, 2]),\n        Int32Array.from([2, 1, 2, 1, 1]),\n        Int32Array.from([1, 2, 2, 1, 1]),\n        Int32Array.from([1, 1, 1, 2, 2]),\n        Int32Array.from([2, 1, 1, 2, 1]),\n        Int32Array.from([1, 2, 1, 2, 1]),\n        Int32Array.from([1, 1, 3, 3, 1]),\n        Int32Array.from([3, 1, 1, 1, 3]),\n        Int32Array.from([1, 3, 1, 1, 3]),\n        Int32Array.from([3, 3, 1, 1, 1]),\n        Int32Array.from([1, 1, 3, 1, 3]),\n        Int32Array.from([3, 1, 3, 1, 1]),\n        Int32Array.from([1, 3, 3, 1, 1]),\n        Int32Array.from([1, 1, 1, 3, 3]),\n        Int32Array.from([3, 1, 1, 3, 1]),\n        Int32Array.from([1, 3, 1, 3, 1]) // 9\n    ];\n    ITFReader.MAX_AVG_VARIANCE = 0.38;\n    ITFReader.MAX_INDIVIDUAL_VARIANCE = 0.5;\n    /* /!** Valid ITF lengths. Anything longer than the largest value is also allowed. *!/*/\n    ITFReader.DEFAULT_ALLOWED_LENGTHS = [6, 8, 10, 12, 14];\n    /*/!**\n     * Start/end guard pattern.\n     *\n     * Note: The end pattern is reversed because the row is reversed before\n     * searching for the END_PATTERN\n     *!/*/\n    ITFReader.START_PATTERN = Int32Array.from([1, 1, 1, 1]);\n    ITFReader.END_PATTERN_REVERSED = [\n        Int32Array.from([1, 1, 2]),\n        Int32Array.from([1, 1, 3]) // 3x\n    ];\n\n    /**\n     * <p>Encapsulates functionality and implementation that is common to UPC and EAN families\n     * of one-dimensional barcodes.</p>\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @author Sean Owen\n     * @author alasdair@google.com (Alasdair Mackintosh)\n     */\n    class AbstractUPCEANReader extends OneDReader {\n        constructor() {\n            super(...arguments);\n            this.decodeRowStringBuffer = '';\n        }\n\n        static findStartGuardPattern(row) {\n            let foundStart = false;\n            let startRange;\n            let nextStart = 0;\n            let counters = Int32Array.from([0, 0, 0]);\n            while (!foundStart) {\n                counters = Int32Array.from([0, 0, 0]);\n                startRange = AbstractUPCEANReader.findGuardPattern(row, nextStart, false, this.START_END_PATTERN, counters);\n                let start = startRange[0];\n                nextStart = startRange[1];\n                let quietStart = start - (nextStart - start);\n                if (quietStart >= 0) {\n                    foundStart = row.isRange(quietStart, start, false);\n                }\n            }\n            return startRange;\n        }\n        static checkChecksum(s) {\n            return AbstractUPCEANReader.checkStandardUPCEANChecksum(s);\n        }\n        static checkStandardUPCEANChecksum(s) {\n            let length = s.length;\n            if (length === 0)\n                return false;\n            let check = parseInt(s.charAt(length - 1), 10);\n            return AbstractUPCEANReader.getStandardUPCEANChecksum(s.substring(0, length - 1)) === check;\n        }\n        static getStandardUPCEANChecksum(s) {\n            let length = s.length;\n            let sum = 0;\n            for (let i = length - 1; i >= 0; i -= 2) {\n                let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n                if (digit < 0 || digit > 9) {\n                    throw new FormatException();\n                }\n                sum += digit;\n            }\n            sum *= 3;\n            for (let i = length - 2; i >= 0; i -= 2) {\n                let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n                if (digit < 0 || digit > 9) {\n                    throw new FormatException();\n                }\n                sum += digit;\n            }\n            return (1000 - sum) % 10;\n        }\n        static decodeEnd(row, endStart) {\n            return AbstractUPCEANReader.findGuardPattern(row, endStart, false, AbstractUPCEANReader.START_END_PATTERN, new Int32Array(AbstractUPCEANReader.START_END_PATTERN.length).fill(0));\n        }\n        /**\n         * @throws NotFoundException\n         */\n        static findGuardPatternWithoutCounters(row, rowOffset, whiteFirst, pattern) {\n            return this.findGuardPattern(row, rowOffset, whiteFirst, pattern, new Int32Array(pattern.length));\n        }\n        /**\n         * @param row row of black/white values to search\n         * @param rowOffset position to start search\n         * @param whiteFirst if true, indicates that the pattern specifies white/black/white/...\n         * pixel counts, otherwise, it is interpreted as black/white/black/...\n         * @param pattern pattern of counts of number of black and white pixels that are being\n         * searched for as a pattern\n         * @param counters array of counters, as long as pattern, to re-use\n         * @return start/end horizontal offset of guard pattern, as an array of two ints\n         * @throws NotFoundException if pattern is not found\n         */\n        static findGuardPattern(row, rowOffset, whiteFirst, pattern, counters) {\n            let width = row.getSize();\n            rowOffset = whiteFirst ? row.getNextUnset(rowOffset) : row.getNextSet(rowOffset);\n            let counterPosition = 0;\n            let patternStart = rowOffset;\n            let patternLength = pattern.length;\n            let isWhite = whiteFirst;\n            for (let x = rowOffset; x < width; x++) {\n                if (row.get(x) !== isWhite) {\n                    counters[counterPosition]++;\n                }\n                else {\n                    if (counterPosition === patternLength - 1) {\n                        if (OneDReader.patternMatchVariance(counters, pattern, AbstractUPCEANReader.MAX_INDIVIDUAL_VARIANCE) < AbstractUPCEANReader.MAX_AVG_VARIANCE) {\n                            return Int32Array.from([patternStart, x]);\n                        }\n                        patternStart += counters[0] + counters[1];\n                        let slice = counters.slice(2, counters.length - 1);\n                        for (let i = 0; i < counterPosition - 1; i++) {\n                            counters[i] = slice[i];\n                        }\n                        counters[counterPosition - 1] = 0;\n                        counters[counterPosition] = 0;\n                        counterPosition--;\n                    }\n                    else {\n                        counterPosition++;\n                    }\n                    counters[counterPosition] = 1;\n                    isWhite = !isWhite;\n                }\n            }\n            throw new NotFoundException();\n        }\n        static decodeDigit(row, counters, rowOffset, patterns) {\n            this.recordPattern(row, rowOffset, counters);\n            let bestVariance = this.MAX_AVG_VARIANCE;\n            let bestMatch = -1;\n            let max = patterns.length;\n            for (let i = 0; i < max; i++) {\n                let pattern = patterns[i];\n                let variance = OneDReader.patternMatchVariance(counters, pattern, AbstractUPCEANReader.MAX_INDIVIDUAL_VARIANCE);\n                if (variance < bestVariance) {\n                    bestVariance = variance;\n                    bestMatch = i;\n                }\n            }\n            if (bestMatch >= 0) {\n                return bestMatch;\n            }\n            else {\n                throw new NotFoundException();\n            }\n        }\n    }\n    // These two values are critical for determining how permissive the decoding will be.\n    // We've arrived at these values through a lot of trial and error. Setting them any higher\n    // lets false positives creep in quickly.\n    AbstractUPCEANReader.MAX_AVG_VARIANCE = 0.48;\n    AbstractUPCEANReader.MAX_INDIVIDUAL_VARIANCE = 0.7;\n    /**\n     * Start/end guard pattern.\n     */\n    AbstractUPCEANReader.START_END_PATTERN = Int32Array.from([1, 1, 1]);\n    /**\n     * Pattern marking the middle of a UPC/EAN pattern, separating the two halves.\n     */\n    AbstractUPCEANReader.MIDDLE_PATTERN = Int32Array.from([1, 1, 1, 1, 1]);\n    /**\n     * end guard pattern.\n     */\n    AbstractUPCEANReader.END_PATTERN = Int32Array.from([1, 1, 1, 1, 1, 1]);\n    /**\n     * \"Odd\", or \"L\" patterns used to encode UPC/EAN digits.\n     */\n    AbstractUPCEANReader.L_PATTERNS = [\n        Int32Array.from([3, 2, 1, 1]),\n        Int32Array.from([2, 2, 2, 1]),\n        Int32Array.from([2, 1, 2, 2]),\n        Int32Array.from([1, 4, 1, 1]),\n        Int32Array.from([1, 1, 3, 2]),\n        Int32Array.from([1, 2, 3, 1]),\n        Int32Array.from([1, 1, 1, 4]),\n        Int32Array.from([1, 3, 1, 2]),\n        Int32Array.from([1, 2, 1, 3]),\n        Int32Array.from([3, 1, 1, 2]),\n    ];\n\n    /**\n     * @see UPCEANExtension2Support\n     */\n    class UPCEANExtension5Support {\n        constructor() {\n            this.CHECK_DIGIT_ENCODINGS = [0x18, 0x14, 0x12, 0x11, 0x0C, 0x06, 0x03, 0x0A, 0x09, 0x05];\n            this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]);\n            this.decodeRowStringBuffer = '';\n        }\n        decodeRow(rowNumber, row, extensionStartRange) {\n            let result = this.decodeRowStringBuffer;\n            let end = this.decodeMiddle(row, extensionStartRange, result);\n            let resultString = result.toString();\n            let extensionData = UPCEANExtension5Support.parseExtensionString(resultString);\n            let resultPoints = [\n                new ResultPoint((extensionStartRange[0] + extensionStartRange[1]) / 2.0, rowNumber),\n                new ResultPoint(end, rowNumber)\n            ];\n            let extensionResult = new Result(resultString, null, 0, resultPoints, BarcodeFormat$1.UPC_EAN_EXTENSION, new Date().getTime());\n            if (extensionData != null) {\n                extensionResult.putAllMetadata(extensionData);\n            }\n            return extensionResult;\n        }\n        decodeMiddle(row, startRange, resultString) {\n            let counters = this.decodeMiddleCounters;\n            counters[0] = 0;\n            counters[1] = 0;\n            counters[2] = 0;\n            counters[3] = 0;\n            let end = row.getSize();\n            let rowOffset = startRange[1];\n            let lgPatternFound = 0;\n            for (let x = 0; x < 5 && rowOffset < end; x++) {\n                let bestMatch = AbstractUPCEANReader.decodeDigit(\n                    row,\n                    counters,\n                    rowOffset,\n                    AbstractUPCEANReader.L_AND_G_PATTERNS);\n                resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch % 10));\n                for (let counter of counters) {\n                    rowOffset += counter;\n                }\n                if (bestMatch >= 10) {\n                    lgPatternFound |= 1 << (4 - x);\n                }\n                if (x !== 4) {\n                    // Read off separator if not last\n                    rowOffset = row.getNextSet(rowOffset);\n                    rowOffset = row.getNextUnset(rowOffset);\n                }\n            }\n            if (resultString.length !== 5) {\n                throw new NotFoundException();\n            }\n            let checkDigit = this.determineCheckDigit(lgPatternFound);\n            if (UPCEANExtension5Support.extensionChecksum(resultString.toString()) !== checkDigit) {\n                throw new NotFoundException();\n            }\n            return rowOffset;\n        }\n        static extensionChecksum(s) {\n            let length = s.length;\n            let sum = 0;\n            for (let i = length - 2; i >= 0; i -= 2) {\n                sum += s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n            }\n            sum *= 3;\n            for (let i = length - 1; i >= 0; i -= 2) {\n                sum += s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n            }\n            sum *= 3;\n            return sum % 10;\n        }\n        determineCheckDigit(lgPatternFound) {\n            for (let d = 0; d < 10; d++) {\n                if (lgPatternFound === this.CHECK_DIGIT_ENCODINGS[d]) {\n                    return d;\n                }\n            }\n            throw new NotFoundException();\n        }\n        static parseExtensionString(raw) {\n            if (raw.length !== 5) {\n                return null;\n            }\n            let value = UPCEANExtension5Support.parseExtension5String(raw);\n            if (value == null) {\n                return null;\n            }\n            return new Map([[ResultMetadataType$1.SUGGESTED_PRICE, value]]);\n        }\n        static parseExtension5String(raw) {\n            let currency;\n            switch (raw.charAt(0)) {\n                case '0':\n                    currency = '£';\n                    break;\n                case '5':\n                    currency = '$';\n                    break;\n                case '9':\n                    // Reference: http://www.jollytech.com\n                    switch (raw) {\n                        case '90000':\n                            // No suggested retail price\n                            return null;\n                        case '99991':\n                            // Complementary\n                            return '0.00';\n                        case '99990':\n                            return 'Used';\n                    }\n                    // Otherwise... unknown currency?\n                    currency = '';\n                    break;\n                default:\n                    currency = '';\n                    break;\n            }\n            let rawAmount = parseInt(raw.substring(1));\n            let unitsString = (rawAmount / 100).toString();\n            let hundredths = rawAmount % 100;\n            let hundredthsString = hundredths < 10 ? '0' + hundredths : hundredths.toString(); // fixme\n            return currency + unitsString + '.' + hundredthsString;\n        }\n    }\n\n    /**\n     * @see UPCEANExtension5Support\n     */\n    class UPCEANExtension2Support {\n        constructor() {\n            this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]);\n            this.decodeRowStringBuffer = '';\n        }\n        decodeRow(rowNumber, row, extensionStartRange) {\n            let result = this.decodeRowStringBuffer;\n            let end = this.decodeMiddle(row, extensionStartRange, result);\n            let resultString = result.toString();\n            let extensionData = UPCEANExtension2Support.parseExtensionString(resultString);\n            let resultPoints = [\n                new ResultPoint((extensionStartRange[0] + extensionStartRange[1]) / 2.0, rowNumber),\n                new ResultPoint(end, rowNumber)\n            ];\n            let extensionResult = new Result(resultString, null, 0, resultPoints, BarcodeFormat$1.UPC_EAN_EXTENSION, new Date().getTime());\n            if (extensionData != null) {\n                extensionResult.putAllMetadata(extensionData);\n            }\n            return extensionResult;\n        }\n        decodeMiddle(row, startRange, resultString) {\n            let counters = this.decodeMiddleCounters;\n            counters[0] = 0;\n            counters[1] = 0;\n            counters[2] = 0;\n            counters[3] = 0;\n            let end = row.getSize();\n            let rowOffset = startRange[1];\n            let checkParity = 0;\n            for (let x = 0; x < 2 && rowOffset < end; x++) {\n                let bestMatch = AbstractUPCEANReader.decodeDigit(row, counters, rowOffset, AbstractUPCEANReader.L_AND_G_PATTERNS);\n                resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch % 10));\n                for (let counter of counters) {\n                    rowOffset += counter;\n                }\n                if (bestMatch >= 10) {\n                    checkParity |= 1 << (1 - x);\n                }\n                if (x !== 1) {\n                    // Read off separator if not last\n                    rowOffset = row.getNextSet(rowOffset);\n                    rowOffset = row.getNextUnset(rowOffset);\n                }\n            }\n            if (resultString.length !== 2) {\n                throw new NotFoundException();\n            }\n            if (parseInt(resultString.toString()) % 4 !== checkParity) {\n                throw new NotFoundException();\n            }\n            return rowOffset;\n        }\n        static parseExtensionString(raw) {\n            if (raw.length !== 2) {\n                return null;\n            }\n            return new Map([[ResultMetadataType$1.ISSUE_NUMBER, parseInt(raw)]]);\n        }\n    }\n\n    class UPCEANExtensionSupport {\n        static decodeRow(rowNumber, row, rowOffset) {\n            let extensionStartRange = AbstractUPCEANReader.findGuardPattern(\n                row,\n                rowOffset,\n                false,\n                this.EXTENSION_START_PATTERN,\n                new Int32Array(this.EXTENSION_START_PATTERN.length).fill(0));\n            try {\n                // return null;\n                let fiveSupport = new UPCEANExtension5Support();\n                return fiveSupport.decodeRow(rowNumber, row, extensionStartRange);\n            }\n            catch (err) {\n                // return null;\n                let twoSupport = new UPCEANExtension2Support();\n                return twoSupport.decodeRow(rowNumber, row, extensionStartRange);\n            }\n        }\n    }\n    UPCEANExtensionSupport.EXTENSION_START_PATTERN = Int32Array.from([1, 1, 2]);\n\n    /**\n     * <p>Encapsulates functionality and implementation that is common to UPC and EAN families\n     * of one-dimensional barcodes.</p>\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @author Sean Owen\n     * @author alasdair@google.com (Alasdair Mackintosh)\n     */\n    class UPCEANReader extends AbstractUPCEANReader {\n        constructor() {\n            super();\n            this.decodeRowStringBuffer = '';\n            UPCEANReader.L_AND_G_PATTERNS = UPCEANReader.L_PATTERNS.map(arr => Int32Array.from(arr));\n            for (let i = 10; i < 20; i++) {\n                let widths = UPCEANReader.L_PATTERNS[i - 10];\n                let reversedWidths = new Int32Array(widths.length);\n                for (let j = 0; j < widths.length; j++) {\n                    reversedWidths[j] = widths[widths.length - j - 1];\n                }\n                UPCEANReader.L_AND_G_PATTERNS[i] = reversedWidths;\n            }\n        }\n        decodeRow(rowNumber, row, hints) {\n            let startGuardRange = UPCEANReader.findStartGuardPattern(row);\n            let resultPointCallback = hints == null ? null : hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n            if (resultPointCallback != null) {\n                const resultPoint = new ResultPoint((startGuardRange[0] + startGuardRange[1]) / 2.0, rowNumber);\n                resultPointCallback.foundPossibleResultPoint(resultPoint);\n            }\n            let budello = this.decodeMiddle(row, startGuardRange, this.decodeRowStringBuffer);\n            let endStart = budello.rowOffset;\n            let result = budello.resultString;\n            if (resultPointCallback != null) {\n                const resultPoint = new ResultPoint(endStart, rowNumber);\n                resultPointCallback.foundPossibleResultPoint(resultPoint);\n            }\n            let endRange = this.decodeEnd(row, endStart);\n            if (resultPointCallback != null) {\n                const resultPoint = new ResultPoint((endRange[0] + endRange[1]) / 2.0, rowNumber);\n                resultPointCallback.foundPossibleResultPoint(resultPoint);\n            }\n            // Make sure there is a quiet zone at least as big as the end pattern after the barcode. The\n            // spec might want more whitespace, but in practice this is the maximum we can count on.\n            let end = endRange[1];\n            let quietEnd = end + (end - endRange[0]);\n            if (quietEnd >= row.getSize() || !row.isRange(end, quietEnd, false)) {\n                throw new NotFoundException();\n            }\n            let resultString = result.toString();\n            // UPC/EAN should never be less than 8 chars anyway\n            if (resultString.length < 8) {\n                throw new FormatException();\n            }\n            if (!UPCEANReader.checkChecksum(resultString)) {\n                throw new ChecksumException();\n            }\n            let left = (startGuardRange[1] + startGuardRange[0]) / 2.0;\n            let right = (endRange[1] + endRange[0]) / 2.0;\n            let format = this.getBarcodeFormat();\n            let resultPoint = [new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber)];\n            let decodeResult = new Result(resultString, null, 0, resultPoint, format, new Date().getTime());\n            let extensionLength = 0;\n            try {\n                let extensionResult = UPCEANExtensionSupport.decodeRow(rowNumber, row, endRange[1]);\n                decodeResult.putMetadata(ResultMetadataType$1.UPC_EAN_EXTENSION, extensionResult.getText());\n                decodeResult.putAllMetadata(extensionResult.getResultMetadata());\n                decodeResult.addResultPoints(extensionResult.getResultPoints());\n                extensionLength = extensionResult.getText().length;\n            }\n            catch (ignoreError) {}\n            let allowedExtensions = hints == null ? null : hints.get(DecodeHintType$1.ALLOWED_EAN_EXTENSIONS);\n            if (allowedExtensions != null) {\n                let valid = false;\n                for (let length in allowedExtensions) {\n                    if (extensionLength.toString() === length) { // check me\n                        valid = true;\n                        break;\n                    }\n                }\n                if (!valid) {\n                    throw new NotFoundException();\n                }\n            }\n            return decodeResult;\n        }\n        decodeEnd(row, endStart) {\n            return UPCEANReader.findGuardPattern(\n                row, endStart, false, UPCEANReader.START_END_PATTERN,\n                new Int32Array(UPCEANReader.START_END_PATTERN.length).fill(0));\n        }\n        static checkChecksum(s) {\n            return UPCEANReader.checkStandardUPCEANChecksum(s);\n        }\n        static checkStandardUPCEANChecksum(s) {\n            let length = s.length;\n            if (length === 0)\n                return false;\n            let check = parseInt(s.charAt(length - 1), 10);\n            return UPCEANReader.getStandardUPCEANChecksum(s.substring(0, length - 1)) === check;\n        }\n        static getStandardUPCEANChecksum(s) {\n            let length = s.length;\n            let sum = 0;\n            for (let i = length - 1; i >= 0; i -= 2) {\n                let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n                if (digit < 0 || digit > 9) {\n                    throw new FormatException();\n                }\n                sum += digit;\n            }\n            sum *= 3;\n            for (let i = length - 2; i >= 0; i -= 2) {\n                let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n                if (digit < 0 || digit > 9) {\n                    throw new FormatException();\n                }\n                sum += digit;\n            }\n            return (1000 - sum) % 10;\n        }\n    }\n\n    /**\n     * <p>Implements decoding of the EAN-13 format.</p>\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @author Sean Owen\n     * @author alasdair@google.com (Alasdair Mackintosh)\n     */\n    class EAN13Reader extends UPCEANReader {\n        constructor() {\n            super();\n            this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]);\n        }\n        decodeMiddle(row, startRange, resultString) {\n            let counters = this.decodeMiddleCounters;\n            counters[0] = 0;\n            counters[1] = 0;\n            counters[2] = 0;\n            counters[3] = 0;\n            let end = row.getSize();\n            let rowOffset = startRange[1];\n            let lgPatternFound = 0;\n            for (let x = 0; x < 6 && rowOffset < end; x++) {\n                let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_AND_G_PATTERNS);\n                resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch % 10));\n                for (let counter of counters) {\n                    rowOffset += counter;\n                }\n                if (bestMatch >= 10) {\n                    lgPatternFound |= 1 << (5 - x);\n                }\n            }\n            resultString = EAN13Reader.determineFirstDigit(resultString, lgPatternFound);\n            let middleRange = UPCEANReader.findGuardPattern(\n                row,\n                rowOffset,\n                true,\n                UPCEANReader.MIDDLE_PATTERN,\n                new Int32Array(UPCEANReader.MIDDLE_PATTERN.length).fill(0));\n            rowOffset = middleRange[1];\n            for (let x = 0; x < 6 && rowOffset < end; x++) {\n                let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS);\n                resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch));\n                for (let counter of counters) {\n                    rowOffset += counter;\n                }\n            }\n            return { rowOffset, resultString };\n        }\n        getBarcodeFormat() {\n            return BarcodeFormat$1.EAN_13;\n        }\n        static determineFirstDigit(resultString, lgPatternFound) {\n            for (let d = 0; d < 10; d++) {\n                if (lgPatternFound === this.FIRST_DIGIT_ENCODINGS[d]) {\n                    resultString = String.fromCharCode(('0'.charCodeAt(0) + d)) + resultString;\n                    return resultString;\n                }\n            }\n            throw new NotFoundException();\n        }\n    }\n    EAN13Reader.FIRST_DIGIT_ENCODINGS = [0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A];\n\n    /**\n     * <p>Implements decoding of the EAN-8 format.</p>\n     *\n     * @author Sean Owen\n     */\n    class EAN8Reader extends UPCEANReader {\n        constructor() {\n            super();\n            this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]);\n        }\n        decodeMiddle(row, startRange, resultString) {\n            const counters = this.decodeMiddleCounters;\n            counters[0] = 0;\n            counters[1] = 0;\n            counters[2] = 0;\n            counters[3] = 0;\n            let end = row.getSize();\n            let rowOffset = startRange[1];\n            for (let x = 0; x < 4 && rowOffset < end; x++) {\n                let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS);\n                resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch));\n                for (let counter of counters) {\n                    rowOffset += counter;\n                }\n            }\n            let middleRange = UPCEANReader.findGuardPattern(row, rowOffset, true, UPCEANReader.MIDDLE_PATTERN, new Int32Array(UPCEANReader.MIDDLE_PATTERN.length).fill(0));\n            rowOffset = middleRange[1];\n            for (let x = 0; x < 4 && rowOffset < end; x++) {\n                let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS);\n                resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch));\n                for (let counter of counters) {\n                    rowOffset += counter;\n                }\n            }\n            return { rowOffset, resultString };\n        }\n        getBarcodeFormat() {\n            return BarcodeFormat$1.EAN_8;\n        }\n    }\n\n    /**\n     * Encapsulates functionality and implementation that is common to all families\n     * of one-dimensional barcodes.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @author Sean Owen\n     * @author sam2332 (Sam Rudloff)\n     *\n     * @source https://github.com/zxing/zxing/blob/3c96923276dd5785d58eb970b6ba3f80d36a9505/core/src/main/java/com/google/zxing/oned/UPCAReader.java\n     *\n     * @experimental\n     */\n    class UPCAReader extends UPCEANReader {\n        constructor() {\n            super(...arguments);\n            this.ean13Reader = new EAN13Reader();\n        }\n        // @Override\n        getBarcodeFormat() {\n            return BarcodeFormat$1.UPC_A;\n        }\n        // Note that we don't try rotation without the try harder flag, even if rotation was supported.\n        // @Override\n        decode(image, hints) {\n            return this.maybeReturnResult(this.ean13Reader.decode(image));\n        }\n        // @Override\n        decodeRow(rowNumber, row, hints) {\n            return this.maybeReturnResult(this.ean13Reader.decodeRow(rowNumber, row, hints));\n        }\n        // @Override\n        decodeMiddle(row, startRange, resultString) {\n            return this.ean13Reader.decodeMiddle(row, startRange, resultString);\n        }\n        maybeReturnResult(result) {\n            let text = result.getText();\n            if (text.charAt(0) === '0') {\n                let upcaResult = new Result(text.substring(1), null, null, result.getResultPoints(), BarcodeFormat$1.UPC_A);\n                if (result.getResultMetadata() != null) {\n                    upcaResult.putAllMetadata(result.getResultMetadata());\n                }\n                return upcaResult;\n            }\n            else {\n                throw new NotFoundException();\n            }\n        }\n        reset() {\n            this.ean13Reader.reset();\n        }\n    }\n\n    /**\n     * <p>Implements decoding of the UPC-E format.</p>\n     * <p><a href=\"http://www.barcodeisland.com/upce.phtml\">This</a> is a great reference for\n     * UPC-E information.</p>\n     *\n     * @author Sean Owen\n     *\n     * @source https://github.com/zxing/zxing/blob/3c96923276dd5785d58eb970b6ba3f80d36a9505/core/src/main/java/com/google/zxing/oned/UPCEReader.java\n     *\n     * @experimental\n     */\n    /* final */ class UPCEReader extends UPCEANReader {\n        constructor() {\n            super();\n            this.decodeMiddleCounters = new Int32Array(4);\n        }\n        /**\n         * @throws NotFoundException\n         */\n        // @Override\n        decodeMiddle(row, startRange, result) {\n            const counters = this.decodeMiddleCounters.map(x => x);\n            counters[0] = 0;\n            counters[1] = 0;\n            counters[2] = 0;\n            counters[3] = 0;\n            const end = row.getSize();\n            let rowOffset = startRange[1];\n            let lgPatternFound = 0;\n            for (let x = 0; x < 6 && rowOffset < end; x++) {\n                const bestMatch = UPCEReader.decodeDigit(\n                    row, counters, rowOffset, UPCEReader.L_AND_G_PATTERNS);\n                result += String.fromCharCode(('0'.charCodeAt(0) + (bestMatch % 10)));\n                for (let counter of counters) {\n                    rowOffset += counter;\n                }\n                if (bestMatch >= 10) {\n                    lgPatternFound |= (1 << (5 - x));\n                }\n            }\n            let resultString = UPCEReader.determineNumSysAndCheckDigit(\n                result, lgPatternFound);\n            return {rowOffset, resultString};\n        }\n        /**\n         * @throws NotFoundException\n         */\n        // @Override\n        decodeEnd(row, endStart) {\n            return UPCEReader.findGuardPatternWithoutCounters(\n                row, endStart, true, UPCEReader.MIDDLE_END_PATTERN);\n        }\n        /**\n         * @throws FormatException\n         */\n        // @Override\n        checkChecksum(s) {\n            return UPCEANReader.checkChecksum(UPCEReader.convertUPCEtoUPCA(s));\n        }\n        /**\n         * @throws NotFoundException\n         */\n        static determineNumSysAndCheckDigit(resultString, lgPatternFound) {\n            for (let numSys = 0; numSys <= 1; numSys++) {\n                for (let d = 0; d < 10; d++) {\n                    if (lgPatternFound === this.NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d]) {\n                        let prefix = String.fromCharCode('0'.charCodeAt(0) + numSys);\n                        let suffix = String.fromCharCode('0'.charCodeAt(0) + d);\n                        return prefix + resultString + suffix;\n                    }\n                }\n            }\n            throw NotFoundException.getNotFoundInstance();\n        }\n        // @Override\n        getBarcodeFormat() {\n            return BarcodeFormat$1.UPC_E;\n        }\n        /**\n         * Expands a UPC-E value back into its full, equivalent UPC-A code value.\n         *\n         * @param upce UPC-E code as string of digits\n         * @return equivalent UPC-A code as string of digits\n         */\n        static convertUPCEtoUPCA(upce) {\n            // the following line is equivalent to upce.getChars(1, 7, upceChars, 0);\n            const upceChars = upce.slice(1, 7).split('').map(x => x.charCodeAt(0));\n            const result = new StringBuilder( /*12*/);\n            result.append(upce.charAt(0));\n            let lastChar = upceChars[5];\n            switch (lastChar) {\n                case 0:\n                case 1:\n                case 2:\n                    result.appendChars(upceChars, 0, 2);\n                    result.append(lastChar);\n                    result.append('0000');\n                    result.appendChars(upceChars, 2, 3);\n                    break;\n                case 3:\n                    result.appendChars(upceChars, 0, 3);\n                    result.append('00000');\n                    result.appendChars(upceChars, 3, 2);\n                    break;\n                case 4:\n                    result.appendChars(upceChars, 0, 4);\n                    result.append('00000');\n                    result.append(upceChars[4]);\n                    break;\n                default:\n                    result.appendChars(upceChars, 0, 5);\n                    result.append('0000');\n                    result.append(lastChar);\n                    break;\n            }\n            // Only append check digit in conversion if supplied\n            if (upce.length >= 8) {\n                result.append(upce.charAt(7));\n            }\n            return result.toString();\n        }\n    }\n    /**\n     * The pattern that marks the middle, and end, of a UPC-E pattern.\n     * There is no \"second half\" to a UPC-E barcode.\n     */\n    UPCEReader.MIDDLE_END_PATTERN = Int32Array.from([1, 1, 1, 1, 1, 1]);\n    // For an UPC-E barcode, the final digit is represented by the parities used\n    // to encode the middle six digits, according to the table below.\n    //\n    //                Parity of next 6 digits\n    //    Digit   0     1     2     3     4     5\n    //       0    Even   Even  Even Odd  Odd   Odd\n    //       1    Even   Even  Odd  Even Odd   Odd\n    //       2    Even   Even  Odd  Odd  Even  Odd\n    //       3    Even   Even  Odd  Odd  Odd   Even\n    //       4    Even   Odd   Even Even Odd   Odd\n    //       5    Even   Odd   Odd  Even Even  Odd\n    //       6    Even   Odd   Odd  Odd  Even  Even\n    //       7    Even   Odd   Even Odd  Even  Odd\n    //       8    Even   Odd   Even Odd  Odd   Even\n    //       9    Even   Odd   Odd  Even Odd   Even\n    //\n    // The encoding is represented by the following array, which is a bit pattern\n    // using Odd = 0 and Even = 1. For example, 5 is represented by:\n    //\n    //              Odd Even Even Odd Odd Even\n    // in binary:\n    //                0    1    1   0   0    1   == 0x19\n    //\n    /**\n     * See {@link #L_AND_G_PATTERNS}; these values similarly represent patterns of\n     * even-odd parity encodings of digits that imply both the number system (0 or 1)\n     * used, and the check digit.\n     */\n    UPCEReader.NUMSYS_AND_CHECK_DIGIT_PATTERNS = [\n        Int32Array.from([0x38, 0x34, 0x32, 0x31, 0x2C, 0x26, 0x23, 0x2A, 0x29, 0x25]),\n        Int32Array.from([0x07, 0x0B, 0x0D, 0x0E, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A]),\n    ];\n\n    /**\n     * <p>A reader that can read all available UPC/EAN formats. If a caller wants to try to\n     * read all such formats, it is most efficient to use this implementation rather than invoke\n     * individual readers.</p>\n     *\n     * @author Sean Owen\n     */\n    class MultiFormatUPCEANReader extends OneDReader {\n        constructor(hints) {\n            super();\n            let possibleFormats = hints == null ? null : hints.get(DecodeHintType$1.POSSIBLE_FORMATS);\n            let readers = [];\n            if (!isNullOrUndefined(possibleFormats)) {\n                if (possibleFormats.indexOf(BarcodeFormat$1.EAN_13) > -1) {\n                    readers.push(new EAN13Reader());\n                }\n                if (possibleFormats.indexOf(BarcodeFormat$1.UPC_A) > -1) {\n                    readers.push(new UPCAReader());\n                }\n                if (possibleFormats.indexOf(BarcodeFormat$1.EAN_8) > -1) {\n                    readers.push(new EAN8Reader());\n                }\n                if (possibleFormats.indexOf(BarcodeFormat$1.UPC_E) > -1) {\n                    readers.push(new UPCEReader());\n                }\n            } else {\n                // No hints provided.\n                readers.push(new EAN13Reader());\n                readers.push(new UPCAReader());\n                readers.push(new EAN8Reader());\n                readers.push(new UPCEReader());\n            }\n            this.readers = readers;\n        }\n        decodeRow(rowNumber, row, hints) {\n            for (let reader of this.readers) {\n                try {\n                    // const result: Result = reader.decodeRow(rowNumber, row, startGuardPattern, hints);\n                    const result = reader.decodeRow(rowNumber, row, hints);\n                    // Special case: a 12-digit code encoded in UPC-A is identical to a \"0\"\n                    // followed by those 12 digits encoded as EAN-13. Each will recognize such a code,\n                    // UPC-A as a 12-digit string and EAN-13 as a 13-digit string starting with \"0\".\n                    // Individually these are correct and their readers will both read such a code\n                    // and correctly call it EAN-13, or UPC-A, respectively.\n                    //\n                    // In this case, if we've been looking for both types, we'd like to call it\n                    // a UPC-A code. But for efficiency we only run the EAN-13 decoder to also read\n                    // UPC-A. So we special case it here, and convert an EAN-13 result to a UPC-A\n                    // result if appropriate.\n                    //\n                    // But, don't return UPC-A if UPC-A was not a requested format!\n                    const ean13MayBeUPCA = result.getBarcodeFormat() === BarcodeFormat$1.EAN_13 &&\n                        result.getText().charAt(0) === '0';\n                    // @SuppressWarnings(\"unchecked\")\n                    const possibleFormats = hints == null ? null : hints.get(DecodeHintType$1.POSSIBLE_FORMATS);\n                    const canReturnUPCA = possibleFormats == null || possibleFormats.includes(BarcodeFormat$1.UPC_A);\n                    if (ean13MayBeUPCA && canReturnUPCA) {\n                        const rawBytes = result.getRawBytes();\n                        // Transfer the metadata across\n                        const resultUPCA = new Result(\n                            result.getText().substring(1),\n                            rawBytes,\n                            (rawBytes ? rawBytes.length : null),\n                            result.getResultPoints(),\n                            BarcodeFormat$1.UPC_A);\n                        resultUPCA.putAllMetadata(result.getResultMetadata());\n                        return resultUPCA;\n                    }\n                    return result;\n                }\n                catch (err) {\n                    // continue;\n                }\n            }\n            throw new NotFoundException();\n        }\n        reset() {\n            for (let reader of this.readers) {\n                reader.reset();\n            }\n        }\n    }\n\n    // import Integer from '../../util/Integer';\n    // import Float from '../../util/Float';\n    class AbstractRSSReader extends OneDReader {\n        constructor() {\n            super();\n            this.decodeFinderCounters = new Int32Array(4);\n            this.dataCharacterCounters = new Int32Array(8);\n            this.oddRoundingErrors = new Array(4);\n            this.evenRoundingErrors = new Array(4);\n            this.oddCounts = new Array(this.dataCharacterCounters.length / 2);\n            this.evenCounts = new Array(this.dataCharacterCounters.length / 2);\n        }\n        getDecodeFinderCounters() {\n            return this.decodeFinderCounters;\n        }\n        getDataCharacterCounters() {\n            return this.dataCharacterCounters;\n        }\n        getOddRoundingErrors() {\n            return this.oddRoundingErrors;\n        }\n        getEvenRoundingErrors() {\n            return this.evenRoundingErrors;\n        }\n        getOddCounts() {\n            return this.oddCounts;\n        }\n        getEvenCounts() {\n            return this.evenCounts;\n        }\n        parseFinderValue(counters, finderPatterns) {\n            for (let value = 0; value < finderPatterns.length; value++) {\n                if (OneDReader.patternMatchVariance(counters, finderPatterns[value], AbstractRSSReader.MAX_INDIVIDUAL_VARIANCE) < AbstractRSSReader.MAX_AVG_VARIANCE) {\n                    return value;\n                }\n            }\n            throw new NotFoundException();\n        }\n        /**\n         * @param array values to sum\n         * @return sum of values\n         * @deprecated call {@link MathUtils#sum(int[])}\n         */\n        static count(array) {\n            return MathUtils.sum(new Int32Array(array));\n        }\n        static increment(array, errors) {\n            let index = 0;\n            let biggestError = errors[0];\n            for (let i = 1; i < array.length; i++) {\n                if (errors[i] > biggestError) {\n                    biggestError = errors[i];\n                    index = i;\n                }\n            }\n            array[index]++;\n        }\n        static decrement(array, errors) {\n            let index = 0;\n            let biggestError = errors[0];\n            for (let i = 1; i < array.length; i++) {\n                if (errors[i] < biggestError) {\n                    biggestError = errors[i];\n                    index = i;\n                }\n            }\n            array[index]--;\n        }\n        static isFinderPattern(counters) {\n            let firstTwoSum = counters[0] + counters[1];\n            let sum = firstTwoSum + counters[2] + counters[3];\n            let ratio = firstTwoSum / sum;\n            if (ratio >= AbstractRSSReader.MIN_FINDER_PATTERN_RATIO && ratio <= AbstractRSSReader.MAX_FINDER_PATTERN_RATIO) {\n                // passes ratio test in spec, but see if the counts are unreasonable\n                let minCounter = Number.MAX_SAFE_INTEGER;\n                let maxCounter = Number.MIN_SAFE_INTEGER;\n                for (let counter of counters) {\n                    if (counter > maxCounter) {\n                        maxCounter = counter;\n                    }\n                    if (counter < minCounter) {\n                        minCounter = counter;\n                    }\n                }\n                return maxCounter < 10 * minCounter;\n            }\n            return false;\n        }\n    }\n    AbstractRSSReader.MAX_AVG_VARIANCE = 0.2;\n    AbstractRSSReader.MAX_INDIVIDUAL_VARIANCE = 0.45;\n    AbstractRSSReader.MIN_FINDER_PATTERN_RATIO = 9.5 / 12.0;\n    AbstractRSSReader.MAX_FINDER_PATTERN_RATIO = 12.5 / 14.0;\n\n    class DataCharacter {\n        constructor(value, checksumPortion) {\n            this.value = value;\n            this.checksumPortion = checksumPortion;\n        }\n        getValue() {\n            return this.value;\n        }\n        getChecksumPortion() {\n            return this.checksumPortion;\n        }\n        toString() {\n            return this.value + '(' + this.checksumPortion + ')';\n        }\n        equals(o) {\n            if (!(o instanceof DataCharacter)) {\n                return false;\n            }\n            const that = o;\n            return this.value === that.value && this.checksumPortion === that.checksumPortion;\n        }\n        hashCode() {\n            return this.value ^ this.checksumPortion;\n        }\n    }\n\n    class FinderPattern {\n        constructor(value, startEnd, start, end, rowNumber) {\n            this.value = value;\n            this.startEnd = startEnd;\n            this.value = value;\n            this.startEnd = startEnd;\n            this.resultPoints = new Array();\n            this.resultPoints.push(new ResultPoint(start, rowNumber));\n            this.resultPoints.push(new ResultPoint(end, rowNumber));\n        }\n        getValue() {\n            return this.value;\n        }\n        getStartEnd() {\n            return this.startEnd;\n        }\n        getResultPoints() {\n            return this.resultPoints;\n        }\n        equals(o) {\n            if (!(o instanceof FinderPattern)) {\n                return false;\n            }\n            const that = o;\n            return this.value === that.value;\n        }\n        hashCode() {\n            return this.value;\n        }\n    }\n\n    /**\n     * RSS util functions.\n     */\n    class RSSUtils {\n        constructor() { }\n        static getRSSvalue(widths, maxWidth, noNarrow) {\n            let n = 0;\n            for (let width of widths) {\n                n += width;\n            }\n            let val = 0;\n            let narrowMask = 0;\n            let elements = widths.length;\n            for (let bar = 0; bar < elements - 1; bar++) {\n                let elmWidth;\n                for (elmWidth = 1, narrowMask |= 1 << bar; elmWidth < widths[bar]; elmWidth++, narrowMask &= ~(1 << bar)) {\n                    let subVal = RSSUtils.combins(n - elmWidth - 1, elements - bar - 2);\n                    if (noNarrow && (narrowMask === 0) && (n - elmWidth - (elements - bar - 1) >= elements - bar - 1)) {\n                        subVal -= RSSUtils.combins(n - elmWidth - (elements - bar), elements - bar - 2);\n                    }\n                    if (elements - bar - 1 > 1) {\n                        let lessVal = 0;\n                        for (let mxwElement = n - elmWidth - (elements - bar - 2); mxwElement > maxWidth; mxwElement--) {\n                            lessVal += RSSUtils.combins(n - elmWidth - mxwElement - 1, elements - bar - 3);\n                        }\n                        subVal -= lessVal * (elements - 1 - bar);\n                    }\n                    else if (n - elmWidth > maxWidth) {\n                        subVal--;\n                    }\n                    val += subVal;\n                }\n                n -= elmWidth;\n            }\n            return val;\n        }\n        static combins(n, r) {\n            let maxDenom;\n            let minDenom;\n            if (n - r > r) {\n                minDenom = r;\n                maxDenom = n - r;\n            }\n            else {\n                minDenom = n - r;\n                maxDenom = r;\n            }\n            let val = 1;\n            let j = 1;\n            for (let i = n; i > maxDenom; i--) {\n                val *= i;\n                if (j <= minDenom) {\n                    val /= j;\n                    j++;\n                }\n            }\n            while ((j <= minDenom)) {\n                val /= j;\n                j++;\n            }\n            return val;\n        }\n    }\n\n    class BitArrayBuilder {\n        static buildBitArray(pairs) {\n            let charNumber = (pairs.length * 2) - 1;\n            if (pairs[pairs.length - 1].getRightChar() == null) {\n                charNumber -= 1;\n            }\n            let size = 12 * charNumber;\n            let binary = new BitArray(size);\n            let accPos = 0;\n            let firstPair = pairs[0];\n            let firstValue = firstPair.getRightChar().getValue();\n            for (let i = 11; i >= 0; --i) {\n                if ((firstValue & (1 << i)) != 0) {\n                    binary.set(accPos);\n                }\n                accPos++;\n            }\n            for (let i = 1; i < pairs.length; ++i) {\n                let currentPair = pairs[i];\n                let leftValue = currentPair.getLeftChar().getValue();\n                for (let j = 11; j >= 0; --j) {\n                    if ((leftValue & (1 << j)) != 0) {\n                        binary.set(accPos);\n                    }\n                    accPos++;\n                }\n                if (currentPair.getRightChar() != null) {\n                    let rightValue = currentPair.getRightChar().getValue();\n                    for (let j = 11; j >= 0; --j) {\n                        if ((rightValue & (1 << j)) != 0) {\n                            binary.set(accPos);\n                        }\n                        accPos++;\n                    }\n                }\n            }\n            return binary;\n        }\n    }\n\n    class BlockParsedResult {\n        constructor(finished, decodedInformation) {\n            if (decodedInformation) {\n                this.decodedInformation = null;\n            }\n            else {\n                this.finished = finished;\n                this.decodedInformation = decodedInformation;\n            }\n        }\n        getDecodedInformation() {\n            return this.decodedInformation;\n        }\n        isFinished() {\n            return this.finished;\n        }\n    }\n\n    class DecodedObject {\n        constructor(newPosition) {\n            this.newPosition = newPosition;\n        }\n        getNewPosition() {\n            return this.newPosition;\n        }\n    }\n\n    class DecodedChar extends DecodedObject {\n        constructor(newPosition, value) {\n            super(newPosition);\n            this.value = value;\n        }\n        getValue() {\n            return this.value;\n        }\n        isFNC1() {\n            return this.value === DecodedChar.FNC1;\n        }\n    }\n    DecodedChar.FNC1 = '$';\n\n    class DecodedInformation extends DecodedObject {\n        constructor(newPosition, newString, remainingValue) {\n            super(newPosition);\n            if (remainingValue) {\n                this.remaining = true;\n                this.remainingValue = this.remainingValue;\n            }\n            else {\n                this.remaining = false;\n                this.remainingValue = 0;\n            }\n            this.newString = newString;\n        }\n        getNewString() {\n            return this.newString;\n        }\n        isRemaining() {\n            return this.remaining;\n        }\n        getRemainingValue() {\n            return this.remainingValue;\n        }\n    }\n\n    class DecodedNumeric extends DecodedObject {\n        constructor(newPosition, firstDigit, secondDigit) {\n            super(newPosition);\n            if (firstDigit < 0 || firstDigit > 10 || secondDigit < 0 || secondDigit > 10) {\n                throw new FormatException();\n            }\n            this.firstDigit = firstDigit;\n            this.secondDigit = secondDigit;\n        }\n        getFirstDigit() {\n            return this.firstDigit;\n        }\n        getSecondDigit() {\n            return this.secondDigit;\n        }\n        getValue() {\n            return this.firstDigit * 10 + this.secondDigit;\n        }\n        isFirstDigitFNC1() {\n            return this.firstDigit === DecodedNumeric.FNC1;\n        }\n        isSecondDigitFNC1() {\n            return this.secondDigit === DecodedNumeric.FNC1;\n        }\n        isAnyFNC1() {\n            return this.firstDigit === DecodedNumeric.FNC1 || this.secondDigit === DecodedNumeric.FNC1;\n        }\n    }\n    DecodedNumeric.FNC1 = 10;\n\n    class FieldParser {\n        constructor() {\n        }\n        static parseFieldsInGeneralPurpose(rawInformation) {\n            if (!rawInformation) {\n                return null;\n            }\n            // Processing 2-digit AIs\n            if (rawInformation.length < 2) {\n                throw new NotFoundException();\n            }\n            let firstTwoDigits = rawInformation.substring(0, 2);\n            for (let dataLength of FieldParser.TWO_DIGIT_DATA_LENGTH) {\n                if (dataLength[0] === firstTwoDigits) {\n                    if (dataLength[1] === FieldParser.VARIABLE_LENGTH) {\n                        return FieldParser.processVariableAI(2, dataLength[2], rawInformation);\n                    }\n                    return FieldParser.processFixedAI(2, dataLength[1], rawInformation);\n                }\n            }\n            if (rawInformation.length < 3) {\n                throw new NotFoundException();\n            }\n            let firstThreeDigits = rawInformation.substring(0, 3);\n            for (let dataLength of FieldParser.THREE_DIGIT_DATA_LENGTH) {\n                if (dataLength[0] === firstThreeDigits) {\n                    if (dataLength[1] === FieldParser.VARIABLE_LENGTH) {\n                        return FieldParser.processVariableAI(3, dataLength[2], rawInformation);\n                    }\n                    return FieldParser.processFixedAI(3, dataLength[1], rawInformation);\n                }\n            }\n            for (let dataLength of FieldParser.THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH) {\n                if (dataLength[0] === firstThreeDigits) {\n                    if (dataLength[1] === FieldParser.VARIABLE_LENGTH) {\n                        return FieldParser.processVariableAI(4, dataLength[2], rawInformation);\n                    }\n                    return FieldParser.processFixedAI(4, dataLength[1], rawInformation);\n                }\n            }\n            if (rawInformation.length < 4) {\n                throw new NotFoundException();\n            }\n            let firstFourDigits = rawInformation.substring(0, 4);\n            for (let dataLength of FieldParser.FOUR_DIGIT_DATA_LENGTH) {\n                if (dataLength[0] === firstFourDigits) {\n                    if (dataLength[1] === FieldParser.VARIABLE_LENGTH) {\n                        return FieldParser.processVariableAI(4, dataLength[2], rawInformation);\n                    }\n                    return FieldParser.processFixedAI(4, dataLength[1], rawInformation);\n                }\n            }\n            throw new NotFoundException();\n        }\n        static processFixedAI(aiSize, fieldSize, rawInformation) {\n            if (rawInformation.length < aiSize) {\n                throw new NotFoundException();\n            }\n            let ai = rawInformation.substring(0, aiSize);\n            if (rawInformation.length < aiSize + fieldSize) {\n                throw new NotFoundException();\n            }\n            let field = rawInformation.substring(aiSize, aiSize + fieldSize);\n            let remaining = rawInformation.substring(aiSize + fieldSize);\n            let result = '(' + ai + ')' + field;\n            let parsedAI = FieldParser.parseFieldsInGeneralPurpose(remaining);\n            return parsedAI == null ? result : result + parsedAI;\n        }\n        static processVariableAI(aiSize, variableFieldSize, rawInformation) {\n            let ai = rawInformation.substring(0, aiSize);\n            let maxSize;\n            if (rawInformation.length < aiSize + variableFieldSize) {\n                maxSize = rawInformation.length;\n            }\n            else {\n                maxSize = aiSize + variableFieldSize;\n            }\n            let field = rawInformation.substring(aiSize, maxSize);\n            let remaining = rawInformation.substring(maxSize);\n            let result = '(' + ai + ')' + field;\n            let parsedAI = FieldParser.parseFieldsInGeneralPurpose(remaining);\n            return parsedAI == null ? result : result + parsedAI;\n        }\n    }\n    FieldParser.VARIABLE_LENGTH = [];\n    FieldParser.TWO_DIGIT_DATA_LENGTH = [\n        ['00', 18],\n        ['01', 14],\n        ['02', 14],\n        ['10', FieldParser.VARIABLE_LENGTH, 20],\n        ['11', 6],\n        ['12', 6],\n        ['13', 6],\n        ['15', 6],\n        ['17', 6],\n        ['20', 2],\n        ['21', FieldParser.VARIABLE_LENGTH, 20],\n        ['22', FieldParser.VARIABLE_LENGTH, 29],\n        ['30', FieldParser.VARIABLE_LENGTH, 8],\n        ['37', FieldParser.VARIABLE_LENGTH, 8],\n        // internal company codes\n        ['90', FieldParser.VARIABLE_LENGTH, 30],\n        ['91', FieldParser.VARIABLE_LENGTH, 30],\n        ['92', FieldParser.VARIABLE_LENGTH, 30],\n        ['93', FieldParser.VARIABLE_LENGTH, 30],\n        ['94', FieldParser.VARIABLE_LENGTH, 30],\n        ['95', FieldParser.VARIABLE_LENGTH, 30],\n        ['96', FieldParser.VARIABLE_LENGTH, 30],\n        ['97', FieldParser.VARIABLE_LENGTH, 3],\n        ['98', FieldParser.VARIABLE_LENGTH, 30],\n        ['99', FieldParser.VARIABLE_LENGTH, 30],\n    ];\n    FieldParser.THREE_DIGIT_DATA_LENGTH = [\n        // Same format as above\n        ['240', FieldParser.VARIABLE_LENGTH, 30],\n        ['241', FieldParser.VARIABLE_LENGTH, 30],\n        ['242', FieldParser.VARIABLE_LENGTH, 6],\n        ['250', FieldParser.VARIABLE_LENGTH, 30],\n        ['251', FieldParser.VARIABLE_LENGTH, 30],\n        ['253', FieldParser.VARIABLE_LENGTH, 17],\n        ['254', FieldParser.VARIABLE_LENGTH, 20],\n        ['400', FieldParser.VARIABLE_LENGTH, 30],\n        ['401', FieldParser.VARIABLE_LENGTH, 30],\n        ['402', 17],\n        ['403', FieldParser.VARIABLE_LENGTH, 30],\n        ['410', 13],\n        ['411', 13],\n        ['412', 13],\n        ['413', 13],\n        ['414', 13],\n        ['420', FieldParser.VARIABLE_LENGTH, 20],\n        ['421', FieldParser.VARIABLE_LENGTH, 15],\n        ['422', 3],\n        ['423', FieldParser.VARIABLE_LENGTH, 15],\n        ['424', 3],\n        ['425', 3],\n        ['426', 3],\n    ];\n    FieldParser.THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH = [\n        // Same format as above\n        ['310', 6],\n        ['311', 6],\n        ['312', 6],\n        ['313', 6],\n        ['314', 6],\n        ['315', 6],\n        ['316', 6],\n        ['320', 6],\n        ['321', 6],\n        ['322', 6],\n        ['323', 6],\n        ['324', 6],\n        ['325', 6],\n        ['326', 6],\n        ['327', 6],\n        ['328', 6],\n        ['329', 6],\n        ['330', 6],\n        ['331', 6],\n        ['332', 6],\n        ['333', 6],\n        ['334', 6],\n        ['335', 6],\n        ['336', 6],\n        ['340', 6],\n        ['341', 6],\n        ['342', 6],\n        ['343', 6],\n        ['344', 6],\n        ['345', 6],\n        ['346', 6],\n        ['347', 6],\n        ['348', 6],\n        ['349', 6],\n        ['350', 6],\n        ['351', 6],\n        ['352', 6],\n        ['353', 6],\n        ['354', 6],\n        ['355', 6],\n        ['356', 6],\n        ['357', 6],\n        ['360', 6],\n        ['361', 6],\n        ['362', 6],\n        ['363', 6],\n        ['364', 6],\n        ['365', 6],\n        ['366', 6],\n        ['367', 6],\n        ['368', 6],\n        ['369', 6],\n        ['390', FieldParser.VARIABLE_LENGTH, 15],\n        ['391', FieldParser.VARIABLE_LENGTH, 18],\n        ['392', FieldParser.VARIABLE_LENGTH, 15],\n        ['393', FieldParser.VARIABLE_LENGTH, 18],\n        ['703', FieldParser.VARIABLE_LENGTH, 30],\n    ];\n    FieldParser.FOUR_DIGIT_DATA_LENGTH = [\n        // Same format as above\n        ['7001', 13],\n        ['7002', FieldParser.VARIABLE_LENGTH, 30],\n        ['7003', 10],\n        ['8001', 14],\n        ['8002', FieldParser.VARIABLE_LENGTH, 20],\n        ['8003', FieldParser.VARIABLE_LENGTH, 30],\n        ['8004', FieldParser.VARIABLE_LENGTH, 30],\n        ['8005', 6],\n        ['8006', 18],\n        ['8007', FieldParser.VARIABLE_LENGTH, 30],\n        ['8008', FieldParser.VARIABLE_LENGTH, 12],\n        ['8018', 18],\n        ['8020', FieldParser.VARIABLE_LENGTH, 25],\n        ['8100', 6],\n        ['8101', 10],\n        ['8102', 2],\n        ['8110', FieldParser.VARIABLE_LENGTH, 70],\n        ['8200', FieldParser.VARIABLE_LENGTH, 70],\n    ];\n\n    class GeneralAppIdDecoder {\n        constructor(information) {\n            this.buffer = new StringBuilder();\n            this.information = information;\n        }\n        decodeAllCodes(buff, initialPosition) {\n            let currentPosition = initialPosition;\n            let remaining = null;\n            do {\n                let info = this.decodeGeneralPurposeField(currentPosition, remaining);\n                let parsedFields = FieldParser.parseFieldsInGeneralPurpose(info.getNewString());\n                if (parsedFields != null) {\n                    buff.append(parsedFields);\n                }\n                if (info.isRemaining()) {\n                    remaining = '' + info.getRemainingValue();\n                }\n                else {\n                    remaining = null;\n                }\n                if (currentPosition === info.getNewPosition()) { // No step forward!\n                    break;\n                }\n                currentPosition = info.getNewPosition();\n            } while (true);\n            return buff.toString();\n        }\n        isStillNumeric(pos) {\n            // It's numeric if it still has 7 positions\n            // and one of the first 4 bits is \"1\".\n            if (pos + 7 > this.information.getSize()) {\n                return pos + 4 <= this.information.getSize();\n            }\n            for (let i = pos; i < pos + 3; ++i) {\n                if (this.information.get(i)) {\n                    return true;\n                }\n            }\n            return this.information.get(pos + 3);\n        }\n        decodeNumeric(pos) {\n            if (pos + 7 > this.information.getSize()) {\n                let numeric = this.extractNumericValueFromBitArray(pos, 4);\n                if (numeric === 0) {\n                    return new DecodedNumeric(this.information.getSize(), DecodedNumeric.FNC1, DecodedNumeric.FNC1);\n                }\n                return new DecodedNumeric(this.information.getSize(), numeric - 1, DecodedNumeric.FNC1);\n            }\n            let numeric = this.extractNumericValueFromBitArray(pos, 7);\n            let digit1 = (numeric - 8) / 11;\n            let digit2 = (numeric - 8) % 11;\n            return new DecodedNumeric(pos + 7, digit1, digit2);\n        }\n        extractNumericValueFromBitArray(pos, bits) {\n            return GeneralAppIdDecoder.extractNumericValueFromBitArray(this.information, pos, bits);\n        }\n        static extractNumericValueFromBitArray(information, pos, bits) {\n            let value = 0;\n            for (let i = 0; i < bits; ++i) {\n                if (information.get(pos + i)) {\n                    value |= 1 << (bits - i - 1);\n                }\n            }\n            return value;\n        }\n        decodeGeneralPurposeField(pos, remaining) {\n            // this.buffer.setLength(0);\n            this.buffer.setLengthToZero();\n            if (remaining != null) {\n                this.buffer.append(remaining);\n            }\n            this.current.setPosition(pos);\n            let lastDecoded = this.parseBlocks();\n            if (lastDecoded != null && lastDecoded.isRemaining()) {\n                return new DecodedInformation(this.current.getPosition(), this.buffer.toString(), lastDecoded.getRemainingValue());\n            }\n            return new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n        }\n        parseBlocks() {\n            let isFinished;\n            let result;\n            do {\n                let initialPosition = this.current.getPosition();\n                if (this.current.isAlpha()) {\n                    result = this.parseAlphaBlock();\n                    isFinished = result.isFinished();\n                }\n                else if (this.current.isIsoIec646()) {\n                    result = this.parseIsoIec646Block();\n                    isFinished = result.isFinished();\n                }\n                else { // it must be numeric\n                    result = this.parseNumericBlock();\n                    isFinished = result.isFinished();\n                }\n                let positionChanged = initialPosition !== this.current.getPosition();\n                if (!positionChanged && !isFinished) {\n                    break;\n                }\n            } while (!isFinished);\n            return result.getDecodedInformation();\n        }\n        parseNumericBlock() {\n            while (this.isStillNumeric(this.current.getPosition())) {\n                let numeric = this.decodeNumeric(this.current.getPosition());\n                this.current.setPosition(numeric.getNewPosition());\n                if (numeric.isFirstDigitFNC1()) {\n                    let information;\n                    if (numeric.isSecondDigitFNC1()) {\n                        information = new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n                    }\n                    else {\n                        information = new DecodedInformation(this.current.getPosition(), this.buffer.toString(), numeric.getSecondDigit());\n                    }\n                    return new BlockParsedResult(true, information);\n                }\n                this.buffer.append(numeric.getFirstDigit());\n                if (numeric.isSecondDigitFNC1()) {\n                    let information = new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n                    return new BlockParsedResult(true, information);\n                }\n                this.buffer.append(numeric.getSecondDigit());\n            }\n            if (this.isNumericToAlphaNumericLatch(this.current.getPosition())) {\n                this.current.setAlpha();\n                this.current.incrementPosition(4);\n            }\n            return new BlockParsedResult(false);\n        }\n        parseIsoIec646Block() {\n            while (this.isStillIsoIec646(this.current.getPosition())) {\n                let iso = this.decodeIsoIec646(this.current.getPosition());\n                this.current.setPosition(iso.getNewPosition());\n                if (iso.isFNC1()) {\n                    let information = new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n                    return new BlockParsedResult(true, information);\n                }\n                this.buffer.append(iso.getValue());\n            }\n            if (this.isAlphaOr646ToNumericLatch(this.current.getPosition())) {\n                this.current.incrementPosition(3);\n                this.current.setNumeric();\n            }\n            else if (this.isAlphaTo646ToAlphaLatch(this.current.getPosition())) {\n                if (this.current.getPosition() + 5 < this.information.getSize()) {\n                    this.current.incrementPosition(5);\n                }\n                else {\n                    this.current.setPosition(this.information.getSize());\n                }\n                this.current.setAlpha();\n            }\n            return new BlockParsedResult(false);\n        }\n        parseAlphaBlock() {\n            while (this.isStillAlpha(this.current.getPosition())) {\n                let alpha = this.decodeAlphanumeric(this.current.getPosition());\n                this.current.setPosition(alpha.getNewPosition());\n                if (alpha.isFNC1()) {\n                    let information = new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n                    return new BlockParsedResult(true, information); // end of the char block\n                }\n                this.buffer.append(alpha.getValue());\n            }\n            if (this.isAlphaOr646ToNumericLatch(this.current.getPosition())) {\n                this.current.incrementPosition(3);\n                this.current.setNumeric();\n            }\n            else if (this.isAlphaTo646ToAlphaLatch(this.current.getPosition())) {\n                if (this.current.getPosition() + 5 < this.information.getSize()) {\n                    this.current.incrementPosition(5);\n                }\n                else {\n                    this.current.setPosition(this.information.getSize());\n                }\n                this.current.setIsoIec646();\n            }\n            return new BlockParsedResult(false);\n        }\n        isStillIsoIec646(pos) {\n            if (pos + 5 > this.information.getSize()) {\n                return false;\n            }\n            let fiveBitValue = this.extractNumericValueFromBitArray(pos, 5);\n            if (fiveBitValue >= 5 && fiveBitValue < 16) {\n                return true;\n            }\n            if (pos + 7 > this.information.getSize()) {\n                return false;\n            }\n            let sevenBitValue = this.extractNumericValueFromBitArray(pos, 7);\n            if (sevenBitValue >= 64 && sevenBitValue < 116) {\n                return true;\n            }\n            if (pos + 8 > this.information.getSize()) {\n                return false;\n            }\n            let eightBitValue = this.extractNumericValueFromBitArray(pos, 8);\n            return eightBitValue >= 232 && eightBitValue < 253;\n        }\n        decodeIsoIec646(pos) {\n            let fiveBitValue = this.extractNumericValueFromBitArray(pos, 5);\n            if (fiveBitValue === 15) {\n                return new DecodedChar(pos + 5, DecodedChar.FNC1);\n            }\n            if (fiveBitValue >= 5 && fiveBitValue < 15) {\n                return new DecodedChar(pos + 5, ('0' + (fiveBitValue - 5)));\n            }\n            let sevenBitValue = this.extractNumericValueFromBitArray(pos, 7);\n            if (sevenBitValue >= 64 && sevenBitValue < 90) {\n                return new DecodedChar(pos + 7, ('' + (sevenBitValue + 1)));\n            }\n            if (sevenBitValue >= 90 && sevenBitValue < 116) {\n                return new DecodedChar(pos + 7, ('' + (sevenBitValue + 7)));\n            }\n            let eightBitValue = this.extractNumericValueFromBitArray(pos, 8);\n            let c;\n            switch (eightBitValue) {\n                case 232:\n                    c = '!';\n                    break;\n                case 233:\n                    c = '\"';\n                    break;\n                case 234:\n                    c = '%';\n                    break;\n                case 235:\n                    c = '&';\n                    break;\n                case 236:\n                    c = '\\'';\n                    break;\n                case 237:\n                    c = '(';\n                    break;\n                case 238:\n                    c = ')';\n                    break;\n                case 239:\n                    c = '*';\n                    break;\n                case 240:\n                    c = '+';\n                    break;\n                case 241:\n                    c = ',';\n                    break;\n                case 242:\n                    c = '-';\n                    break;\n                case 243:\n                    c = '.';\n                    break;\n                case 244:\n                    c = '/';\n                    break;\n                case 245:\n                    c = ':';\n                    break;\n                case 246:\n                    c = ';';\n                    break;\n                case 247:\n                    c = '<';\n                    break;\n                case 248:\n                    c = '=';\n                    break;\n                case 249:\n                    c = '>';\n                    break;\n                case 250:\n                    c = '?';\n                    break;\n                case 251:\n                    c = '_';\n                    break;\n                case 252:\n                    c = ' ';\n                    break;\n                default:\n                    throw new FormatException();\n            }\n            return new DecodedChar(pos + 8, c);\n        }\n        isStillAlpha(pos) {\n            if (pos + 5 > this.information.getSize()) {\n                return false;\n            }\n            // We now check if it's a valid 5-bit value (0..9 and FNC1)\n            let fiveBitValue = this.extractNumericValueFromBitArray(pos, 5);\n            if (fiveBitValue >= 5 && fiveBitValue < 16) {\n                return true;\n            }\n            if (pos + 6 > this.information.getSize()) {\n                return false;\n            }\n            let sixBitValue = this.extractNumericValueFromBitArray(pos, 6);\n            return sixBitValue >= 16 && sixBitValue < 63; // 63 not included\n        }\n        decodeAlphanumeric(pos) {\n            let fiveBitValue = this.extractNumericValueFromBitArray(pos, 5);\n            if (fiveBitValue === 15) {\n                return new DecodedChar(pos + 5, DecodedChar.FNC1);\n            }\n            if (fiveBitValue >= 5 && fiveBitValue < 15) {\n                return new DecodedChar(pos + 5, ('0' + (fiveBitValue - 5)));\n            }\n            let sixBitValue = this.extractNumericValueFromBitArray(pos, 6);\n            if (sixBitValue >= 32 && sixBitValue < 58) {\n                return new DecodedChar(pos + 6, ('' + (sixBitValue + 33)));\n            }\n            let c;\n            switch (sixBitValue) {\n                case 58:\n                    c = '*';\n                    break;\n                case 59:\n                    c = ',';\n                    break;\n                case 60:\n                    c = '-';\n                    break;\n                case 61:\n                    c = '.';\n                    break;\n                case 62:\n                    c = '/';\n                    break;\n                default:\n                    throw new IllegalStateException('Decoding invalid alphanumeric value: ' + sixBitValue);\n            }\n            return new DecodedChar(pos + 6, c);\n        }\n        isAlphaTo646ToAlphaLatch(pos) {\n            if (pos + 1 > this.information.getSize()) {\n                return false;\n            }\n            for (let i = 0; i < 5 && i + pos < this.information.getSize(); ++i) {\n                if (i === 2) {\n                    if (!this.information.get(pos + 2)) {\n                        return false;\n                    }\n                }\n                else if (this.information.get(pos + i)) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        isAlphaOr646ToNumericLatch(pos) {\n            // Next is alphanumeric if there are 3 positions and they are all zeros\n            if (pos + 3 > this.information.getSize()) {\n                return false;\n            }\n            for (let i = pos; i < pos + 3; ++i) {\n                if (this.information.get(i)) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        isNumericToAlphaNumericLatch(pos) {\n            // Next is alphanumeric if there are 4 positions and they are all zeros, or\n            // if there is a subset of this just before the end of the symbol\n            if (pos + 1 > this.information.getSize()) {\n                return false;\n            }\n            for (let i = 0; i < 4 && i + pos < this.information.getSize(); ++i) {\n                if (this.information.get(pos + i)) {\n                    return false;\n                }\n            }\n            return true;\n        }\n    }\n\n    class AbstractExpandedDecoder {\n        constructor(information) {\n            this.information = information;\n            this.generalDecoder = new GeneralAppIdDecoder(information);\n        }\n        getInformation() {\n            return this.information;\n        }\n        getGeneralDecoder() {\n            return this.generalDecoder;\n        }\n    }\n\n    class AI01decoder extends AbstractExpandedDecoder {\n        constructor(information) {\n            super(information);\n        }\n        encodeCompressedGtin(buf, currentPos) {\n            buf.append('(01)');\n            let initialPosition = buf.length();\n            buf.append('9');\n            this.encodeCompressedGtinWithoutAI(buf, currentPos, initialPosition);\n        }\n        encodeCompressedGtinWithoutAI(buf, currentPos, initialBufferPosition) {\n            for (let i = 0; i < 4; ++i) {\n                let currentBlock = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos + 10 * i, 10);\n                if (currentBlock / 100 === 0) {\n                    buf.append('0');\n                }\n                if (currentBlock / 10 === 0) {\n                    buf.append('0');\n                }\n                buf.append(currentBlock);\n            }\n            AI01decoder.appendCheckDigit(buf, initialBufferPosition);\n        }\n        static appendCheckDigit(buf, currentPos) {\n            let checkDigit = 0;\n            for (let i = 0; i < 13; i++) {\n                // let digit = buf.charAt(i + currentPos) - '0';\n                // To be checked\n                let digit = buf.charAt(i + currentPos).charCodeAt(0) - '0'.charCodeAt(0);\n                checkDigit += (i & 0x01) === 0 ? 3 * digit : digit;\n            }\n            checkDigit = 10 - (checkDigit % 10);\n            if (checkDigit === 10) {\n                checkDigit = 0;\n            }\n            buf.append(checkDigit);\n        }\n    }\n    AI01decoder.GTIN_SIZE = 40;\n\n    class AI01AndOtherAIs extends AI01decoder {\n        // the second one is the encodation method, and the other two are for the variable length\n        constructor(information) {\n            super(information);\n        }\n        parseInformation() {\n            let buff = new StringBuilder();\n            buff.append('(01)');\n            let initialGtinPosition = buff.length();\n            let firstGtinDigit = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01AndOtherAIs.HEADER_SIZE, 4);\n            buff.append(firstGtinDigit);\n            this.encodeCompressedGtinWithoutAI(buff, AI01AndOtherAIs.HEADER_SIZE + 4, initialGtinPosition);\n            return this.getGeneralDecoder().decodeAllCodes(buff, AI01AndOtherAIs.HEADER_SIZE + 44);\n        }\n    }\n    AI01AndOtherAIs.HEADER_SIZE = 1 + 1 + 2; // first bit encodes the linkage flag,\n\n    class AnyAIDecoder extends AbstractExpandedDecoder {\n        constructor(information) {\n            super(information);\n        }\n        parseInformation() {\n            let buf = new StringBuilder();\n            return this.getGeneralDecoder().decodeAllCodes(buf, AnyAIDecoder.HEADER_SIZE);\n        }\n    }\n    AnyAIDecoder.HEADER_SIZE = 2 + 1 + 2;\n\n    class AI01weightDecoder extends AI01decoder {\n        constructor(information) {\n            super(information);\n        }\n        encodeCompressedWeight(buf, currentPos, weightSize) {\n            let originalWeightNumeric = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos, weightSize);\n            this.addWeightCode(buf, originalWeightNumeric);\n            let weightNumeric = this.checkWeight(originalWeightNumeric);\n            let currentDivisor = 100000;\n            for (let i = 0; i < 5; ++i) {\n                if (weightNumeric / currentDivisor === 0) {\n                    buf.append('0');\n                }\n                currentDivisor /= 10;\n            }\n            buf.append(weightNumeric);\n        }\n    }\n\n    class AI013x0xDecoder extends AI01weightDecoder {\n        constructor(information) {\n            super(information);\n        }\n        parseInformation() {\n            if (this.getInformation().getSize() != AI013x0xDecoder.HEADER_SIZE + AI01weightDecoder.GTIN_SIZE + AI013x0xDecoder.WEIGHT_SIZE) {\n                throw new NotFoundException();\n            }\n            let buf = new StringBuilder();\n            this.encodeCompressedGtin(buf, AI013x0xDecoder.HEADER_SIZE);\n            this.encodeCompressedWeight(buf, AI013x0xDecoder.HEADER_SIZE + AI01weightDecoder.GTIN_SIZE, AI013x0xDecoder.WEIGHT_SIZE);\n            return buf.toString();\n        }\n    }\n    AI013x0xDecoder.HEADER_SIZE = 4 + 1;\n    AI013x0xDecoder.WEIGHT_SIZE = 15;\n\n    class AI013103decoder extends AI013x0xDecoder {\n        constructor(information) {\n            super(information);\n        }\n        addWeightCode(buf, weight) {\n            buf.append('(3103)');\n        }\n        checkWeight(weight) {\n            return weight;\n        }\n    }\n\n    class AI01320xDecoder extends AI013x0xDecoder {\n        constructor(information) {\n            super(information);\n        }\n        addWeightCode(buf, weight) {\n            if (weight < 10000) {\n                buf.append('(3202)');\n            }\n            else {\n                buf.append('(3203)');\n            }\n        }\n        checkWeight(weight) {\n            if (weight < 10000) {\n                return weight;\n            }\n            return weight - 10000;\n        }\n    }\n\n    class AI01392xDecoder extends AI01decoder {\n        constructor(information) {\n            super(information);\n        }\n        parseInformation() {\n            if (this.getInformation().getSize() < AI01392xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE) {\n                throw new NotFoundException();\n            }\n            let buf = new StringBuilder();\n            this.encodeCompressedGtin(buf, AI01392xDecoder.HEADER_SIZE);\n            let lastAIdigit = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01392xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE, AI01392xDecoder.LAST_DIGIT_SIZE);\n            buf.append('(392');\n            buf.append(lastAIdigit);\n            buf.append(')');\n            let decodedInformation = this.getGeneralDecoder().decodeGeneralPurposeField(AI01392xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE + AI01392xDecoder.LAST_DIGIT_SIZE, null);\n            buf.append(decodedInformation.getNewString());\n            return buf.toString();\n        }\n    }\n    AI01392xDecoder.HEADER_SIZE = 5 + 1 + 2;\n    AI01392xDecoder.LAST_DIGIT_SIZE = 2;\n\n    class AI01393xDecoder extends AI01decoder {\n        constructor(information) {\n            super(information);\n        }\n        parseInformation() {\n            if (this.getInformation().getSize() < AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE) {\n                throw new NotFoundException();\n            }\n            let buf = new StringBuilder();\n            this.encodeCompressedGtin(buf, AI01393xDecoder.HEADER_SIZE);\n            let lastAIdigit = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE, AI01393xDecoder.LAST_DIGIT_SIZE);\n            buf.append('(393');\n            buf.append(lastAIdigit);\n            buf.append(')');\n            let firstThreeDigits = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE + AI01393xDecoder.LAST_DIGIT_SIZE, AI01393xDecoder.FIRST_THREE_DIGITS_SIZE);\n            if (firstThreeDigits / 100 == 0) {\n                buf.append('0');\n            }\n            if (firstThreeDigits / 10 == 0) {\n                buf.append('0');\n            }\n            buf.append(firstThreeDigits);\n            let generalInformation = this.getGeneralDecoder().decodeGeneralPurposeField(AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE + AI01393xDecoder.LAST_DIGIT_SIZE + AI01393xDecoder.FIRST_THREE_DIGITS_SIZE, null);\n            buf.append(generalInformation.getNewString());\n            return buf.toString();\n        }\n    }\n    AI01393xDecoder.HEADER_SIZE = 5 + 1 + 2;\n    AI01393xDecoder.LAST_DIGIT_SIZE = 2;\n    AI01393xDecoder.FIRST_THREE_DIGITS_SIZE = 10;\n\n    class AI013x0x1xDecoder extends AI01weightDecoder {\n        constructor(information, firstAIdigits, dateCode) {\n            super(information);\n            this.dateCode = dateCode;\n            this.firstAIdigits = firstAIdigits;\n        }\n        parseInformation() {\n            if (this.getInformation().getSize() != AI013x0x1xDecoder.HEADER_SIZE + AI013x0x1xDecoder.GTIN_SIZE + AI013x0x1xDecoder.WEIGHT_SIZE + AI013x0x1xDecoder.DATE_SIZE) {\n                throw new NotFoundException();\n            }\n            let buf = new StringBuilder();\n            this.encodeCompressedGtin(buf, AI013x0x1xDecoder.HEADER_SIZE);\n            this.encodeCompressedWeight(buf, AI013x0x1xDecoder.HEADER_SIZE + AI013x0x1xDecoder.GTIN_SIZE, AI013x0x1xDecoder.WEIGHT_SIZE);\n            this.encodeCompressedDate(buf, AI013x0x1xDecoder.HEADER_SIZE + AI013x0x1xDecoder.GTIN_SIZE + AI013x0x1xDecoder.WEIGHT_SIZE);\n            return buf.toString();\n        }\n        encodeCompressedDate(buf, currentPos) {\n            let numericDate = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos, AI013x0x1xDecoder.DATE_SIZE);\n            if (numericDate == 38400) {\n                return;\n            }\n            buf.append('(');\n            buf.append(this.dateCode);\n            buf.append(')');\n            let day = numericDate % 32;\n            numericDate /= 32;\n            let month = numericDate % 12 + 1;\n            numericDate /= 12;\n            let year = numericDate;\n            if (year / 10 == 0) {\n                buf.append('0');\n            }\n            buf.append(year);\n            if (month / 10 == 0) {\n                buf.append('0');\n            }\n            buf.append(month);\n            if (day / 10 == 0) {\n                buf.append('0');\n            }\n            buf.append(day);\n        }\n        addWeightCode(buf, weight) {\n            buf.append('(');\n            buf.append(this.firstAIdigits);\n            buf.append(weight / 100000);\n            buf.append(')');\n        }\n        checkWeight(weight) {\n            return weight % 100000;\n        }\n    }\n    AI013x0x1xDecoder.HEADER_SIZE = 7 + 1;\n    AI013x0x1xDecoder.WEIGHT_SIZE = 20;\n    AI013x0x1xDecoder.DATE_SIZE = 16;\n\n    function createDecoder(information) {\n        try {\n            if (information.get(1)) {\n                return new AI01AndOtherAIs(information);\n            }\n            if (!information.get(2)) {\n                return new AnyAIDecoder(information);\n            }\n            let fourBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 4);\n            switch (fourBitEncodationMethod) {\n                case 4: return new AI013103decoder(information);\n                case 5: return new AI01320xDecoder(information);\n            }\n            let fiveBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 5);\n            switch (fiveBitEncodationMethod) {\n                case 12: return new AI01392xDecoder(information);\n                case 13: return new AI01393xDecoder(information);\n            }\n            let sevenBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 7);\n            switch (sevenBitEncodationMethod) {\n                case 56: return new AI013x0x1xDecoder(information, '310', '11');\n                case 57: return new AI013x0x1xDecoder(information, '320', '11');\n                case 58: return new AI013x0x1xDecoder(information, '310', '13');\n                case 59: return new AI013x0x1xDecoder(information, '320', '13');\n                case 60: return new AI013x0x1xDecoder(information, '310', '15');\n                case 61: return new AI013x0x1xDecoder(information, '320', '15');\n                case 62: return new AI013x0x1xDecoder(information, '310', '17');\n                case 63: return new AI013x0x1xDecoder(information, '320', '17');\n            }\n        }\n        catch (e) {\n            console.log(e);\n            throw new IllegalStateException('unknown decoder: ' + information);\n        }\n    }\n\n    class ExpandedPair {\n        constructor(leftChar, rightChar, finderPatter, mayBeLast) {\n            this.leftchar = leftChar;\n            this.rightchar = rightChar;\n            this.finderpattern = finderPatter;\n            this.maybeLast = mayBeLast;\n        }\n        mayBeLast() {\n            return this.maybeLast;\n        }\n        getLeftChar() {\n            return this.leftchar;\n        }\n        getRightChar() {\n            return this.rightchar;\n        }\n        getFinderPattern() {\n            return this.finderpattern;\n        }\n        mustBeLast() {\n            return this.rightchar == null;\n        }\n        toString() {\n            return '[ ' + this.leftchar + ', ' + this.rightchar + ' : ' + (this.finderpattern == null ? 'null' : this.finderpattern.getValue()) + ' ]';\n        }\n        static equals(o1, o2) {\n            if (!(o1 instanceof ExpandedPair)) {\n                return false;\n            }\n            return ExpandedPair.equalsOrNull(o1.leftchar, o2.leftchar) &&\n                ExpandedPair.equalsOrNull(o1.rightchar, o2.rightchar) &&\n                ExpandedPair.equalsOrNull(o1.finderpattern, o2.finderpattern);\n        }\n        static equalsOrNull(o1, o2) {\n            return o1 === null ? o2 === null : ExpandedPair.equals(o1, o2);\n        }\n        hashCode() {\n            // return ExpandedPair.hashNotNull(leftChar) ^ hashNotNull(rightChar) ^ hashNotNull(finderPattern);\n            let value = this.leftchar.getValue() ^ this.rightchar.getValue() ^ this.finderpattern.getValue();\n            return value;\n        }\n    }\n\n    class ExpandedRow {\n        constructor(pairs, rowNumber, wasReversed) {\n            this.pairs = pairs;\n            this.rowNumber = rowNumber;\n            this.wasReversed = wasReversed;\n        }\n        getPairs() {\n            return this.pairs;\n        }\n        getRowNumber() {\n            return this.rowNumber;\n        }\n        isReversed() {\n            return this.wasReversed;\n        }\n        // check implementation\n        isEquivalent(otherPairs) {\n            return this.checkEqualitity(this, otherPairs);\n        }\n        // @Override\n        toString() {\n            return '{ ' + this.pairs + ' }';\n        }\n        /**\n         * Two rows are equal if they contain the same pairs in the same order.\n         */\n        // @Override\n        // check implementation\n        equals(o1, o2) {\n            if (!(o1 instanceof ExpandedRow)) {\n                return false;\n            }\n            return this.checkEqualitity(o1, o2) && o1.wasReversed === o2.wasReversed;\n        }\n        checkEqualitity(pair1, pair2) {\n            if (!pair1 || !pair2)\n                return;\n            let result;\n            pair1.forEach((e1, i) => {\n                pair2.forEach(e2 => {\n                    if (e1.getLeftChar().getValue() === e2.getLeftChar().getValue() && e1.getRightChar().getValue() === e2.getRightChar().getValue() && e1.getFinderPatter().getValue() === e2.getFinderPatter().getValue()) {\n                        result = true;\n                    }\n                });\n            });\n            return result;\n        }\n    }\n\n    // import java.util.ArrayList;\n    // import java.util.Iterator;\n    // import java.util.List;\n    // import java.util.Map;\n    // import java.util.Collections;\n    class RSSExpandedReader extends AbstractRSSReader {\n        constructor(verbose) {\n            super(...arguments);\n            this.pairs = new Array(RSSExpandedReader.MAX_PAIRS);\n            this.rows = new Array();\n            this.startEnd = [2];\n            this.verbose = (verbose === true);\n        }\n        decodeRow(rowNumber, row, hints) {\n            // Rows can start with even pattern in case in prev rows there where odd number of patters.\n            // So lets try twice\n            // this.pairs.clear();\n            this.pairs.length = 0;\n            this.startFromEven = false;\n            try {\n                return RSSExpandedReader.constructResult(this.decodeRow2pairs(rowNumber, row));\n            }\n            catch (e) {\n                // OK\n                if (this.verbose) {\n                    console.log(e);\n                }\n            }\n            this.pairs.length = 0;\n            this.startFromEven = true;\n            return RSSExpandedReader.constructResult(this.decodeRow2pairs(rowNumber, row));\n        }\n        reset() {\n            this.pairs.length = 0;\n            this.rows.length = 0;\n        }\n        // Not private for testing\n        decodeRow2pairs(rowNumber, row) {\n            let done = false;\n            while (!done) {\n                try {\n                    this.pairs.push(this.retrieveNextPair(row, this.pairs, rowNumber));\n                }\n                catch (error) {\n                    if (error instanceof NotFoundException) {\n                        if (!this.pairs.length) {\n                            throw new NotFoundException();\n                        }\n                        // exit this loop when retrieveNextPair() fails and throws\n                        done = true;\n                    }\n                }\n            }\n            // TODO: verify sequence of finder patterns as in checkPairSequence()\n            if (this.checkChecksum()) {\n                return this.pairs;\n            }\n            let tryStackedDecode;\n            if (this.rows.length) {\n                tryStackedDecode = true;\n            }\n            else {\n                tryStackedDecode = false;\n            }\n            // let tryStackedDecode = !this.rows.isEmpty();\n            this.storeRow(rowNumber, false); // TODO: deal with reversed rows\n            if (tryStackedDecode) {\n                // When the image is 180-rotated, then rows are sorted in wrong direction.\n                // Try twice with both the directions.\n                let ps = this.checkRowsBoolean(false);\n                if (ps != null) {\n                    return ps;\n                }\n                ps = this.checkRowsBoolean(true);\n                if (ps != null) {\n                    return ps;\n                }\n            }\n            throw new NotFoundException();\n        }\n        // Need to Verify\n        checkRowsBoolean(reverse) {\n            // Limit number of rows we are checking\n            // We use recursive algorithm with pure complexity and don't want it to take forever\n            // Stacked barcode can have up to 11 rows, so 25 seems reasonable enough\n            if (this.rows.length > 25) {\n                this.rows.length = 0; // We will never have a chance to get result, so clear it\n                return null;\n            }\n            this.pairs.length = 0;\n            if (reverse) {\n                this.rows = this.rows.reverse();\n                // Collections.reverse(this.rows);\n            }\n            let ps = null;\n            try {\n                ps = this.checkRows(new Array(), 0);\n            }\n            catch (e) {\n                // OK\n                if (this.verbose) {\n                    console.log(e);\n                }\n            }\n            if (reverse) {\n                this.rows = this.rows.reverse();\n                // Collections.reverse(this.rows);\n            }\n            return ps;\n        }\n        // Try to construct a valid rows sequence\n        // Recursion is used to implement backtracking\n        checkRows(collectedRows, currentRow) {\n            for (let i = currentRow; i < this.rows.length; i++) {\n                let row = this.rows[i];\n                this.pairs.length = 0;\n                for (let collectedRow of collectedRows) {\n                    this.pairs.push(collectedRow.getPairs());\n                }\n                this.pairs.push(row.getPairs());\n                if (!RSSExpandedReader.isValidSequence(this.pairs)) {\n                    continue;\n                }\n                if (this.checkChecksum()) {\n                    return this.pairs;\n                }\n                let rs = new Array(collectedRows);\n                rs.push(row);\n                try {\n                    // Recursion: try to add more rows\n                    return this.checkRows(rs, i + 1);\n                }\n                catch (e) {\n                    // We failed, try the next candidate\n                    if (this.verbose) {\n                        console.log(e);\n                    }\n                }\n            }\n            throw new NotFoundException();\n        }\n        // Whether the pairs form a valid find pattern sequence,\n        // either complete or a prefix\n        static isValidSequence(pairs) {\n            for (let sequence of RSSExpandedReader.FINDER_PATTERN_SEQUENCES) {\n                if (pairs.length > sequence.length) {\n                    continue;\n                }\n                let stop = true;\n                for (let j = 0; j < pairs.length; j++) {\n                    if (pairs[j].getFinderPattern().getValue() != sequence[j]) {\n                        stop = false;\n                        break;\n                    }\n                }\n                if (stop) {\n                    return true;\n                }\n            }\n            return false;\n        }\n        storeRow(rowNumber, wasReversed) {\n            // Discard if duplicate above or below; otherwise insert in order by row number.\n            let insertPos = 0;\n            let prevIsSame = false;\n            let nextIsSame = false;\n            while (insertPos < this.rows.length) {\n                let erow = this.rows[insertPos];\n                if (erow.getRowNumber() > rowNumber) {\n                    nextIsSame = erow.isEquivalent(this.pairs);\n                    break;\n                }\n                prevIsSame = erow.isEquivalent(this.pairs);\n                insertPos++;\n            }\n            if (nextIsSame || prevIsSame) {\n                return;\n            }\n            // When the row was partially decoded (e.g. 2 pairs found instead of 3),\n            // it will prevent us from detecting the barcode.\n            // Try to merge partial rows\n            // Check whether the row is part of an allready detected row\n            if (RSSExpandedReader.isPartialRow(this.pairs, this.rows)) {\n                return;\n            }\n            this.rows.push(insertPos, new ExpandedRow(this.pairs, rowNumber, wasReversed));\n            this.removePartialRows(this.pairs, this.rows);\n        }\n        // Remove all the rows that contains only specified pairs\n        removePartialRows(pairs, rows) {\n            // for (Iterator<ExpandedRow> iterator = rows.iterator(); iterator.hasNext();) {\n            //   ExpandedRow r = iterator.next();\n            //   if (r.getPairs().size() == pairs.size()) {\n            //     continue;\n            //   }\n            //   boolean allFound = true;\n            //   for (ExpandedPair p : r.getPairs()) {\n            //     boolean found = false;\n            //     for (ExpandedPair pp : pairs) {\n            //       if (p.equals(pp)) {\n            //         found = true;\n            //         break;\n            //       }\n            //     }\n            //     if (!found) {\n            //       allFound = false;\n            //       break;\n            //     }\n            //   }\n            //   if (allFound) {\n            //     // 'pairs' contains all the pairs from the row 'r'\n            //     iterator.remove();\n            //   }\n            // }\n            for (let row of rows) {\n                if (row.getPairs().length === pairs.length) {\n                    continue;\n                }\n                for (let p of row.getPairs()) {\n                    for (let pp of pairs) {\n                        if (ExpandedPair.equals(p, pp)) {\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n        // Returns true when one of the rows already contains all the pairs\n        static isPartialRow(pairs, rows) {\n            for (let r of rows) {\n                let allFound = true;\n                for (let p of pairs) {\n                    let found = false;\n                    for (let pp of r.getPairs()) {\n                        if (p.equals(pp)) {\n                            found = true;\n                            break;\n                        }\n                    }\n                    if (!found) {\n                        allFound = false;\n                        break;\n                    }\n                }\n                if (allFound) {\n                    // the row 'r' contain all the pairs from 'pairs'\n                    return true;\n                }\n            }\n            return false;\n        }\n        // Only used for unit testing\n        getRows() {\n            return this.rows;\n        }\n        // Not private for unit testing\n        static constructResult(pairs) {\n            let binary = BitArrayBuilder.buildBitArray(pairs);\n            let decoder = createDecoder(binary);\n            let resultingString = decoder.parseInformation();\n            let firstPoints = pairs[0].getFinderPattern().getResultPoints();\n            let lastPoints = pairs[pairs.length - 1].getFinderPattern().getResultPoints();\n            let points = [firstPoints[0], firstPoints[1], lastPoints[0], lastPoints[1]];\n            return new Result(resultingString, null, null, points, BarcodeFormat$1.RSS_EXPANDED, null);\n        }\n        checkChecksum() {\n            let firstPair = this.pairs.get(0);\n            let checkCharacter = firstPair.getLeftChar();\n            let firstCharacter = firstPair.getRightChar();\n            if (firstCharacter == null) {\n                return false;\n            }\n            let checksum = firstCharacter.getChecksumPortion();\n            let s = 2;\n            for (let i = 1; i < this.pairs.size(); ++i) {\n                let currentPair = this.pairs.get(i);\n                checksum += currentPair.getLeftChar().getChecksumPortion();\n                s++;\n                let currentRightChar = currentPair.getRightChar();\n                if (currentRightChar != null) {\n                    checksum += currentRightChar.getChecksumPortion();\n                    s++;\n                }\n            }\n            checksum %= 211;\n            let checkCharacterValue = 211 * (s - 4) + checksum;\n            return checkCharacterValue == checkCharacter.getValue();\n        }\n        static getNextSecondBar(row, initialPos) {\n            let currentPos;\n            if (row.get(initialPos)) {\n                currentPos = row.getNextUnset(initialPos);\n                currentPos = row.getNextSet(currentPos);\n            }\n            else {\n                currentPos = row.getNextSet(initialPos);\n                currentPos = row.getNextUnset(currentPos);\n            }\n            return currentPos;\n        }\n        // not private for testing\n        retrieveNextPair(row, previousPairs, rowNumber) {\n            let isOddPattern = previousPairs.length % 2 == 0;\n            if (this.startFromEven) {\n                isOddPattern = !isOddPattern;\n            }\n            let pattern;\n            let keepFinding = true;\n            let forcedOffset = -1;\n            do {\n                this.findNextPair(row, previousPairs, forcedOffset);\n                pattern = this.parseFoundFinderPattern(row, rowNumber, isOddPattern);\n                if (pattern == null) {\n                    forcedOffset = RSSExpandedReader.getNextSecondBar(row, this.startEnd[0]);\n                }\n                else {\n                    keepFinding = false;\n                }\n            } while (keepFinding);\n            // When stacked symbol is split over multiple rows, there's no way to guess if this pair can be last or not.\n            // boolean mayBeLast = checkPairSequence(previousPairs, pattern);\n            let leftChar = this.decodeDataCharacter(row, pattern, isOddPattern, true);\n            if (!this.isEmptyPair(previousPairs) && previousPairs[previousPairs.length - 1].mustBeLast()) {\n                throw new NotFoundException();\n            }\n            let rightChar;\n            try {\n                rightChar = this.decodeDataCharacter(row, pattern, isOddPattern, false);\n            }\n            catch (e) {\n                rightChar = null;\n                if (this.verbose) {\n                    console.log(e);\n                }\n            }\n            return new ExpandedPair(leftChar, rightChar, pattern, true);\n        }\n        isEmptyPair(pairs) {\n            if (pairs.length === 0) {\n                return true;\n            }\n            return false;\n        }\n        findNextPair(row, previousPairs, forcedOffset) {\n            let counters = this.getDecodeFinderCounters();\n            counters[0] = 0;\n            counters[1] = 0;\n            counters[2] = 0;\n            counters[3] = 0;\n            let width = row.getSize();\n            let rowOffset;\n            if (forcedOffset >= 0) {\n                rowOffset = forcedOffset;\n            }\n            else if (this.isEmptyPair(previousPairs)) {\n                rowOffset = 0;\n            }\n            else {\n                let lastPair = previousPairs[previousPairs.length - 1];\n                rowOffset = lastPair.getFinderPattern().getStartEnd()[1];\n            }\n            let searchingEvenPair = previousPairs.length % 2 != 0;\n            if (this.startFromEven) {\n                searchingEvenPair = !searchingEvenPair;\n            }\n            let isWhite = false;\n            while (rowOffset < width) {\n                isWhite = !row.get(rowOffset);\n                if (!isWhite) {\n                    break;\n                }\n                rowOffset++;\n            }\n            let counterPosition = 0;\n            let patternStart = rowOffset;\n            for (let x = rowOffset; x < width; x++) {\n                if (row.get(x) != isWhite) {\n                    counters[counterPosition]++;\n                }\n                else {\n                    if (counterPosition == 3) {\n                        if (searchingEvenPair) {\n                            RSSExpandedReader.reverseCounters(counters);\n                        }\n                        if (RSSExpandedReader.isFinderPattern(counters)) {\n                            this.startEnd[0] = patternStart;\n                            this.startEnd[1] = x;\n                            return;\n                        }\n                        if (searchingEvenPair) {\n                            RSSExpandedReader.reverseCounters(counters);\n                        }\n                        patternStart += counters[0] + counters[1];\n                        counters[0] = counters[2];\n                        counters[1] = counters[3];\n                        counters[2] = 0;\n                        counters[3] = 0;\n                        counterPosition--;\n                    }\n                    else {\n                        counterPosition++;\n                    }\n                    counters[counterPosition] = 1;\n                    isWhite = !isWhite;\n                }\n            }\n            throw new NotFoundException();\n        }\n        static reverseCounters(counters) {\n            let length = counters.length;\n            for (let i = 0; i < length / 2; ++i) {\n                let tmp = counters[i];\n                counters[i] = counters[length - i - 1];\n                counters[length - i - 1] = tmp;\n            }\n        }\n        parseFoundFinderPattern(row, rowNumber, oddPattern) {\n            // Actually we found elements 2-5.\n            let firstCounter;\n            let start;\n            let end;\n            if (oddPattern) {\n                // If pattern number is odd, we need to locate element 1 *before* the current block.\n                let firstElementStart = this.startEnd[0] - 1;\n                // Locate element 1\n                while (firstElementStart >= 0 && !row.get(firstElementStart)) {\n                    firstElementStart--;\n                }\n                firstElementStart++;\n                firstCounter = this.startEnd[0] - firstElementStart;\n                start = firstElementStart;\n                end = this.startEnd[1];\n            }\n            else {\n                // If pattern number is even, the pattern is reversed, so we need to locate element 1 *after* the current block.\n                start = this.startEnd[0];\n                end = row.getNextUnset(this.startEnd[1] + 1);\n                firstCounter = end - this.startEnd[1];\n            }\n            // Make 'counters' hold 1-4\n            let counters = this.getDecodeFinderCounters();\n            System.arraycopy(counters, 0, counters, 1, counters.length - 1);\n            counters[0] = firstCounter;\n            let value;\n            try {\n                value = this.parseFinderValue(counters, RSSExpandedReader.FINDER_PATTERNS);\n            }\n            catch (e) {\n                return null;\n            }\n            // return new FinderPattern(value, new int[] { start, end }, start, end, rowNumber});\n            return new FinderPattern(value, [start, end], start, end, rowNumber);\n        }\n        decodeDataCharacter(row, pattern, isOddPattern, leftChar) {\n            let counters = this.getDataCharacterCounters();\n            for (let x = 0; x < counters.length; x++) {\n                counters[x] = 0;\n            }\n            if (leftChar) {\n                RSSExpandedReader.recordPatternInReverse(row, pattern.getStartEnd()[0], counters);\n            }\n            else {\n                RSSExpandedReader.recordPattern(row, pattern.getStartEnd()[1], counters);\n                // reverse it\n                for (let i = 0, j = counters.length - 1; i < j; i++, j--) {\n                    let temp = counters[i];\n                    counters[i] = counters[j];\n                    counters[j] = temp;\n                }\n            } // counters[] has the pixels of the module\n            let numModules = 17; // left and right data characters have all the same length\n            let elementWidth = MathUtils.sum(new Int32Array(counters)) / numModules;\n            // Sanity check: element width for pattern and the character should match\n            let expectedElementWidth = (pattern.getStartEnd()[1] - pattern.getStartEnd()[0]) / 15.0;\n            if (Math.abs(elementWidth - expectedElementWidth) / expectedElementWidth > 0.3) {\n                throw new NotFoundException();\n            }\n            let oddCounts = this.getOddCounts();\n            let evenCounts = this.getEvenCounts();\n            let oddRoundingErrors = this.getOddRoundingErrors();\n            let evenRoundingErrors = this.getEvenRoundingErrors();\n            for (let i = 0; i < counters.length; i++) {\n                let value = 1.0 * counters[i] / elementWidth;\n                let count = value + 0.5; // Round\n                if (count < 1) {\n                    if (value < 0.3) {\n                        throw new NotFoundException();\n                    }\n                    count = 1;\n                }\n                else if (count > 8) {\n                    if (value > 8.7) {\n                        throw new NotFoundException();\n                    }\n                    count = 8;\n                }\n                let offset = i / 2;\n                if ((i & 0x01) == 0) {\n                    oddCounts[offset] = count;\n                    oddRoundingErrors[offset] = value - count;\n                }\n                else {\n                    evenCounts[offset] = count;\n                    evenRoundingErrors[offset] = value - count;\n                }\n            }\n            this.adjustOddEvenCounts(numModules);\n            let weightRowNumber = 4 * pattern.getValue() + (isOddPattern ? 0 : 2) + (leftChar ? 0 : 1) - 1;\n            let oddSum = 0;\n            let oddChecksumPortion = 0;\n            for (let i = oddCounts.length - 1; i >= 0; i--) {\n                if (RSSExpandedReader.isNotA1left(pattern, isOddPattern, leftChar)) {\n                    let weight = RSSExpandedReader.WEIGHTS[weightRowNumber][2 * i];\n                    oddChecksumPortion += oddCounts[i] * weight;\n                }\n                oddSum += oddCounts[i];\n            }\n            let evenChecksumPortion = 0;\n            // int evenSum = 0;\n            for (let i = evenCounts.length - 1; i >= 0; i--) {\n                if (RSSExpandedReader.isNotA1left(pattern, isOddPattern, leftChar)) {\n                    let weight = RSSExpandedReader.WEIGHTS[weightRowNumber][2 * i + 1];\n                    evenChecksumPortion += evenCounts[i] * weight;\n                }\n                // evenSum += evenCounts[i];\n            }\n            let checksumPortion = oddChecksumPortion + evenChecksumPortion;\n            if ((oddSum & 0x01) != 0 || oddSum > 13 || oddSum < 4) {\n                throw new NotFoundException();\n            }\n            let group = (13 - oddSum) / 2;\n            let oddWidest = RSSExpandedReader.SYMBOL_WIDEST[group];\n            let evenWidest = 9 - oddWidest;\n            let vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, true);\n            let vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, false);\n            let tEven = RSSExpandedReader.EVEN_TOTAL_SUBSET[group];\n            let gSum = RSSExpandedReader.GSUM[group];\n            let value = vOdd * tEven + vEven + gSum;\n            return new DataCharacter(value, checksumPortion);\n        }\n        static isNotA1left(pattern, isOddPattern, leftChar) {\n            // A1: pattern.getValue is 0 (A), and it's an oddPattern, and it is a left char\n            return !(pattern.getValue() == 0 && isOddPattern && leftChar);\n        }\n        adjustOddEvenCounts(numModules) {\n            let oddSum = MathUtils.sum(new Int32Array(this.getOddCounts()));\n            let evenSum = MathUtils.sum(new Int32Array(this.getEvenCounts()));\n            let incrementOdd = false;\n            let decrementOdd = false;\n            if (oddSum > 13) {\n                decrementOdd = true;\n            }\n            else if (oddSum < 4) {\n                incrementOdd = true;\n            }\n            let incrementEven = false;\n            let decrementEven = false;\n            if (evenSum > 13) {\n                decrementEven = true;\n            }\n            else if (evenSum < 4) {\n                incrementEven = true;\n            }\n            let mismatch = oddSum + evenSum - numModules;\n            let oddParityBad = (oddSum & 0x01) == 1;\n            let evenParityBad = (evenSum & 0x01) == 0;\n            if (mismatch == 1) {\n                if (oddParityBad) {\n                    if (evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    decrementOdd = true;\n                }\n                else {\n                    if (!evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    decrementEven = true;\n                }\n            }\n            else if (mismatch == -1) {\n                if (oddParityBad) {\n                    if (evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    incrementOdd = true;\n                }\n                else {\n                    if (!evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    incrementEven = true;\n                }\n            }\n            else if (mismatch == 0) {\n                if (oddParityBad) {\n                    if (!evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    // Both bad\n                    if (oddSum < evenSum) {\n                        incrementOdd = true;\n                        decrementEven = true;\n                    }\n                    else {\n                        decrementOdd = true;\n                        incrementEven = true;\n                    }\n                }\n                else {\n                    if (evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    // Nothing to do!\n                }\n            }\n            else {\n                throw new NotFoundException();\n            }\n            if (incrementOdd) {\n                if (decrementOdd) {\n                    throw new NotFoundException();\n                }\n                RSSExpandedReader.increment(this.getOddCounts(), this.getOddRoundingErrors());\n            }\n            if (decrementOdd) {\n                RSSExpandedReader.decrement(this.getOddCounts(), this.getOddRoundingErrors());\n            }\n            if (incrementEven) {\n                if (decrementEven) {\n                    throw new NotFoundException();\n                }\n                RSSExpandedReader.increment(this.getEvenCounts(), this.getOddRoundingErrors());\n            }\n            if (decrementEven) {\n                RSSExpandedReader.decrement(this.getEvenCounts(), this.getEvenRoundingErrors());\n            }\n        }\n    }\n    RSSExpandedReader.SYMBOL_WIDEST = [7, 5, 4, 3, 1];\n    RSSExpandedReader.EVEN_TOTAL_SUBSET = [4, 20, 52, 104, 204];\n    RSSExpandedReader.GSUM = [0, 348, 1388, 2948, 3988];\n    RSSExpandedReader.FINDER_PATTERNS = [\n        Int32Array.from([1, 8, 4, 1]),\n        Int32Array.from([3, 6, 4, 1]),\n        Int32Array.from([3, 4, 6, 1]),\n        Int32Array.from([3, 2, 8, 1]),\n        Int32Array.from([2, 6, 5, 1]),\n        Int32Array.from([2, 2, 9, 1]) // F\n    ];\n    RSSExpandedReader.WEIGHTS = [\n        [1, 3, 9, 27, 81, 32, 96, 77],\n        [20, 60, 180, 118, 143, 7, 21, 63],\n        [189, 145, 13, 39, 117, 140, 209, 205],\n        [193, 157, 49, 147, 19, 57, 171, 91],\n        [62, 186, 136, 197, 169, 85, 44, 132],\n        [185, 133, 188, 142, 4, 12, 36, 108],\n        [113, 128, 173, 97, 80, 29, 87, 50],\n        [150, 28, 84, 41, 123, 158, 52, 156],\n        [46, 138, 203, 187, 139, 206, 196, 166],\n        [76, 17, 51, 153, 37, 111, 122, 155],\n        [43, 129, 176, 106, 107, 110, 119, 146],\n        [16, 48, 144, 10, 30, 90, 59, 177],\n        [109, 116, 137, 200, 178, 112, 125, 164],\n        [70, 210, 208, 202, 184, 130, 179, 115],\n        [134, 191, 151, 31, 93, 68, 204, 190],\n        [148, 22, 66, 198, 172, 94, 71, 2],\n        [6, 18, 54, 162, 64, 192, 154, 40],\n        [120, 149, 25, 75, 14, 42, 126, 167],\n        [79, 26, 78, 23, 69, 207, 199, 175],\n        [103, 98, 83, 38, 114, 131, 182, 124],\n        [161, 61, 183, 127, 170, 88, 53, 159],\n        [55, 165, 73, 8, 24, 72, 5, 15],\n        [45, 135, 194, 160, 58, 174, 100, 89]\n    ];\n    RSSExpandedReader.FINDER_PAT_A = 0;\n    RSSExpandedReader.FINDER_PAT_B = 1;\n    RSSExpandedReader.FINDER_PAT_C = 2;\n    RSSExpandedReader.FINDER_PAT_D = 3;\n    RSSExpandedReader.FINDER_PAT_E = 4;\n    RSSExpandedReader.FINDER_PAT_F = 5;\n    RSSExpandedReader.FINDER_PATTERN_SEQUENCES = [\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_D],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_C],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_F],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_F, RSSExpandedReader.FINDER_PAT_F],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_D],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_E],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_F, RSSExpandedReader.FINDER_PAT_F],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_F, RSSExpandedReader.FINDER_PAT_F],\n    ];\n    RSSExpandedReader.MAX_PAIRS = 11;\n\n    class Pair extends DataCharacter {\n        constructor(value, checksumPortion, finderPattern) {\n            super(value, checksumPortion);\n            this.count = 0;\n            this.finderPattern = finderPattern;\n        }\n        getFinderPattern() {\n            return this.finderPattern;\n        }\n        getCount() {\n            return this.count;\n        }\n        incrementCount() {\n            this.count++;\n        }\n    }\n\n    class RSS14Reader extends AbstractRSSReader {\n        constructor() {\n            super(...arguments);\n            this.possibleLeftPairs = [];\n            this.possibleRightPairs = [];\n        }\n        decodeRow(rowNumber, row, hints) {\n            const leftPair = this.decodePair(row, false, rowNumber, hints);\n            RSS14Reader.addOrTally(this.possibleLeftPairs, leftPair);\n            row.reverse();\n            let rightPair = this.decodePair(row, true, rowNumber, hints);\n            RSS14Reader.addOrTally(this.possibleRightPairs, rightPair);\n            row.reverse();\n            for (let left of this.possibleLeftPairs) {\n                if (left.getCount() > 1) {\n                    for (let right of this.possibleRightPairs) {\n                        if (right.getCount() > 1 && RSS14Reader.checkChecksum(left, right)) {\n                            return RSS14Reader.constructResult(left, right);\n                        }\n                    }\n                }\n            }\n            throw new NotFoundException();\n        }\n        static addOrTally(possiblePairs, pair) {\n            if (pair == null) {\n                return;\n            }\n            let found = false;\n            for (let other of possiblePairs) {\n                if (other.getValue() === pair.getValue()) {\n                    other.incrementCount();\n                    found = true;\n                    break;\n                }\n            }\n            if (!found) {\n                possiblePairs.push(pair);\n            }\n        }\n        reset() {\n            this.possibleLeftPairs.length = 0;\n            this.possibleRightPairs.length = 0;\n        }\n        static constructResult(leftPair, rightPair) {\n            let symbolValue = 4537077 * leftPair.getValue() + rightPair.getValue();\n            let text = new String(symbolValue).toString();\n            let buffer = new StringBuilder();\n            for (let i = 13 - text.length; i > 0; i--) {\n                buffer.append('0');\n            }\n            buffer.append(text);\n            let checkDigit = 0;\n            for (let i = 0; i < 13; i++) {\n                let digit = buffer.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n                checkDigit += ((i & 0x01) === 0) ? 3 * digit : digit;\n            }\n            checkDigit = 10 - (checkDigit % 10);\n            if (checkDigit === 10) {\n                checkDigit = 0;\n            }\n            buffer.append(checkDigit.toString());\n            let leftPoints = leftPair.getFinderPattern().getResultPoints();\n            let rightPoints = rightPair.getFinderPattern().getResultPoints();\n            return new Result(buffer.toString(), null, 0, [leftPoints[0], leftPoints[1], rightPoints[0], rightPoints[1]], BarcodeFormat$1.RSS_14, new Date().getTime());\n        }\n        static checkChecksum(leftPair, rightPair) {\n            let checkValue = (leftPair.getChecksumPortion() + 16 * rightPair.getChecksumPortion()) % 79;\n            let targetCheckValue = 9 * leftPair.getFinderPattern().getValue() + rightPair.getFinderPattern().getValue();\n            if (targetCheckValue > 72) {\n                targetCheckValue--;\n            }\n            if (targetCheckValue > 8) {\n                targetCheckValue--;\n            }\n            return checkValue === targetCheckValue;\n        }\n        decodePair(row, right, rowNumber, hints) {\n            try {\n                let startEnd = this.findFinderPattern(row, right);\n                let pattern = this.parseFoundFinderPattern(row, rowNumber, right, startEnd);\n                let resultPointCallback = hints == null ? null : hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n                if (resultPointCallback != null) {\n                    let center = (startEnd[0] + startEnd[1]) / 2.0;\n                    if (right) {\n                        // row is actually reversed\n                        center = row.getSize() - 1 - center;\n                    }\n                    resultPointCallback.foundPossibleResultPoint(new ResultPoint(center, rowNumber));\n                }\n                let outside = this.decodeDataCharacter(row, pattern, true);\n                let inside = this.decodeDataCharacter(row, pattern, false);\n                return new Pair(1597 * outside.getValue() + inside.getValue(), outside.getChecksumPortion() + 4 * inside.getChecksumPortion(), pattern);\n            }\n            catch (err) {\n                return null;\n            }\n        }\n        decodeDataCharacter(row, pattern, outsideChar) {\n            let counters = this.getDataCharacterCounters();\n            for (let x = 0; x < counters.length; x++) {\n                counters[x] = 0;\n            }\n            if (outsideChar) {\n                OneDReader.recordPatternInReverse(row, pattern.getStartEnd()[0], counters);\n            }\n            else {\n                OneDReader.recordPattern(row, pattern.getStartEnd()[1] + 1, counters);\n                // reverse it\n                for (let i = 0, j = counters.length - 1; i < j; i++, j--) {\n                    let temp = counters[i];\n                    counters[i] = counters[j];\n                    counters[j] = temp;\n                }\n            }\n            let numModules = outsideChar ? 16 : 15;\n            let elementWidth = MathUtils.sum(new Int32Array(counters)) / numModules;\n            let oddCounts = this.getOddCounts();\n            let evenCounts = this.getEvenCounts();\n            let oddRoundingErrors = this.getOddRoundingErrors();\n            let evenRoundingErrors = this.getEvenRoundingErrors();\n            for (let i = 0; i < counters.length; i++) {\n                let value = counters[i] / elementWidth;\n                let count = Math.floor(value + 0.5);\n                if (count < 1) {\n                    count = 1;\n                }\n                else if (count > 8) {\n                    count = 8;\n                }\n                let offset = Math.floor(i / 2);\n                if ((i & 0x01) === 0) {\n                    oddCounts[offset] = count;\n                    oddRoundingErrors[offset] = value - count;\n                }\n                else {\n                    evenCounts[offset] = count;\n                    evenRoundingErrors[offset] = value - count;\n                }\n            }\n            this.adjustOddEvenCounts(outsideChar, numModules);\n            let oddSum = 0;\n            let oddChecksumPortion = 0;\n            for (let i = oddCounts.length - 1; i >= 0; i--) {\n                oddChecksumPortion *= 9;\n                oddChecksumPortion += oddCounts[i];\n                oddSum += oddCounts[i];\n            }\n            let evenChecksumPortion = 0;\n            let evenSum = 0;\n            for (let i = evenCounts.length - 1; i >= 0; i--) {\n                evenChecksumPortion *= 9;\n                evenChecksumPortion += evenCounts[i];\n                evenSum += evenCounts[i];\n            }\n            let checksumPortion = oddChecksumPortion + 3 * evenChecksumPortion;\n            if (outsideChar) {\n                if ((oddSum & 0x01) !== 0 || oddSum > 12 || oddSum < 4) {\n                    throw new NotFoundException();\n                }\n                let group = (12 - oddSum) / 2;\n                let oddWidest = RSS14Reader.OUTSIDE_ODD_WIDEST[group];\n                let evenWidest = 9 - oddWidest;\n                let vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, false);\n                let vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, true);\n                let tEven = RSS14Reader.OUTSIDE_EVEN_TOTAL_SUBSET[group];\n                let gSum = RSS14Reader.OUTSIDE_GSUM[group];\n                return new DataCharacter(vOdd * tEven + vEven + gSum, checksumPortion);\n            }\n            else {\n                if ((evenSum & 0x01) !== 0 || evenSum > 10 || evenSum < 4) {\n                    throw new NotFoundException();\n                }\n                let group = (10 - evenSum) / 2;\n                let oddWidest = RSS14Reader.INSIDE_ODD_WIDEST[group];\n                let evenWidest = 9 - oddWidest;\n                let vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, true);\n                let vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, false);\n                let tOdd = RSS14Reader.INSIDE_ODD_TOTAL_SUBSET[group];\n                let gSum = RSS14Reader.INSIDE_GSUM[group];\n                return new DataCharacter(vEven * tOdd + vOdd + gSum, checksumPortion);\n            }\n        }\n        findFinderPattern(row, rightFinderPattern) {\n            let counters = this.getDecodeFinderCounters();\n            counters[0] = 0;\n            counters[1] = 0;\n            counters[2] = 0;\n            counters[3] = 0;\n            let width = row.getSize();\n            let isWhite = false;\n            let rowOffset = 0;\n            while (rowOffset < width) {\n                isWhite = !row.get(rowOffset);\n                if (rightFinderPattern === isWhite) {\n                    // Will encounter white first when searching for right finder pattern\n                    break;\n                }\n                rowOffset++;\n            }\n            let counterPosition = 0;\n            let patternStart = rowOffset;\n            for (let x = rowOffset; x < width; x++) {\n                if (row.get(x) !== isWhite) {\n                    counters[counterPosition]++;\n                }\n                else {\n                    if (counterPosition === 3) {\n                        if (AbstractRSSReader.isFinderPattern(counters)) {\n                            return [patternStart, x];\n                        }\n                        patternStart += counters[0] + counters[1];\n                        counters[0] = counters[2];\n                        counters[1] = counters[3];\n                        counters[2] = 0;\n                        counters[3] = 0;\n                        counterPosition--;\n                    }\n                    else {\n                        counterPosition++;\n                    }\n                    counters[counterPosition] = 1;\n                    isWhite = !isWhite;\n                }\n            }\n            throw new NotFoundException();\n        }\n        parseFoundFinderPattern(row, rowNumber, right, startEnd) {\n            // Actually we found elements 2-5\n            let firstIsBlack = row.get(startEnd[0]);\n            let firstElementStart = startEnd[0] - 1;\n            // Locate element 1\n            while (firstElementStart >= 0 && firstIsBlack !== row.get(firstElementStart)) {\n                firstElementStart--;\n            }\n            firstElementStart++;\n            const firstCounter = startEnd[0] - firstElementStart;\n            // Make 'counters' hold 1-4\n            const counters = this.getDecodeFinderCounters();\n            const copy = new Int32Array(counters.length);\n            System.arraycopy(counters, 0, copy, 1, counters.length - 1);\n            copy[0] = firstCounter;\n            const value = this.parseFinderValue(copy, RSS14Reader.FINDER_PATTERNS);\n            let start = firstElementStart;\n            let end = startEnd[1];\n            if (right) {\n                // row is actually reversed\n                start = row.getSize() - 1 - start;\n                end = row.getSize() - 1 - end;\n            }\n            return new FinderPattern(value, [firstElementStart, startEnd[1]], start, end, rowNumber);\n        }\n        adjustOddEvenCounts(outsideChar, numModules) {\n            let oddSum = MathUtils.sum(new Int32Array(this.getOddCounts()));\n            let evenSum = MathUtils.sum(new Int32Array(this.getEvenCounts()));\n            let incrementOdd = false;\n            let decrementOdd = false;\n            let incrementEven = false;\n            let decrementEven = false;\n            if (outsideChar) {\n                if (oddSum > 12) {\n                    decrementOdd = true;\n                }\n                else if (oddSum < 4) {\n                    incrementOdd = true;\n                }\n                if (evenSum > 12) {\n                    decrementEven = true;\n                }\n                else if (evenSum < 4) {\n                    incrementEven = true;\n                }\n            }\n            else {\n                if (oddSum > 11) {\n                    decrementOdd = true;\n                }\n                else if (oddSum < 5) {\n                    incrementOdd = true;\n                }\n                if (evenSum > 10) {\n                    decrementEven = true;\n                }\n                else if (evenSum < 4) {\n                    incrementEven = true;\n                }\n            }\n            let mismatch = oddSum + evenSum - numModules;\n            let oddParityBad = (oddSum & 0x01) === (outsideChar ? 1 : 0);\n            let evenParityBad = (evenSum & 0x01) === 1;\n            if (mismatch === 1) {\n                if (oddParityBad) {\n                    if (evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    decrementOdd = true;\n                }\n                else {\n                    if (!evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    decrementEven = true;\n                }\n            }\n            else if (mismatch === -1) {\n                if (oddParityBad) {\n                    if (evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    incrementOdd = true;\n                }\n                else {\n                    if (!evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    incrementEven = true;\n                }\n            }\n            else if (mismatch === 0) {\n                if (oddParityBad) {\n                    if (!evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    // Both bad\n                    if (oddSum < evenSum) {\n                        incrementOdd = true;\n                        decrementEven = true;\n                    }\n                    else {\n                        decrementOdd = true;\n                        incrementEven = true;\n                    }\n                }\n                else {\n                    if (evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    // Nothing to do!\n                }\n            }\n            else {\n                throw new NotFoundException();\n            }\n            if (incrementOdd) {\n                if (decrementOdd) {\n                    throw new NotFoundException();\n                }\n                AbstractRSSReader.increment(this.getOddCounts(), this.getOddRoundingErrors());\n            }\n            if (decrementOdd) {\n                AbstractRSSReader.decrement(this.getOddCounts(), this.getOddRoundingErrors());\n            }\n            if (incrementEven) {\n                if (decrementEven) {\n                    throw new NotFoundException();\n                }\n                AbstractRSSReader.increment(this.getEvenCounts(), this.getOddRoundingErrors());\n            }\n            if (decrementEven) {\n                AbstractRSSReader.decrement(this.getEvenCounts(), this.getEvenRoundingErrors());\n            }\n        }\n    }\n    RSS14Reader.OUTSIDE_EVEN_TOTAL_SUBSET = [1, 10, 34, 70, 126];\n    RSS14Reader.INSIDE_ODD_TOTAL_SUBSET = [4, 20, 48, 81];\n    RSS14Reader.OUTSIDE_GSUM = [0, 161, 961, 2015, 2715];\n    RSS14Reader.INSIDE_GSUM = [0, 336, 1036, 1516];\n    RSS14Reader.OUTSIDE_ODD_WIDEST = [8, 6, 4, 3, 1];\n    RSS14Reader.INSIDE_ODD_WIDEST = [2, 4, 6, 8];\n    RSS14Reader.FINDER_PATTERNS = [\n        Int32Array.from([3, 8, 2, 1]),\n        Int32Array.from([3, 5, 5, 1]),\n        Int32Array.from([3, 3, 7, 1]),\n        Int32Array.from([3, 1, 9, 1]),\n        Int32Array.from([2, 7, 4, 1]),\n        Int32Array.from([2, 5, 6, 1]),\n        Int32Array.from([2, 3, 8, 1]),\n        Int32Array.from([1, 5, 7, 1]),\n        Int32Array.from([1, 3, 9, 1]),\n    ];\n\n    /**\n     * @author Daniel Switkin <dswitkin@google.com>\n     * @author Sean Owen\n     */\n    class MultiFormatOneDReader extends OneDReader {\n        constructor(hints, verbose) {\n            super();\n            this.readers = [];\n            this.verbose = (verbose === true);\n            const possibleFormats = !hints ? null : hints.get(DecodeHintType$1.POSSIBLE_FORMATS);\n            const useCode39CheckDigit = hints && hints.get(DecodeHintType$1.ASSUME_CODE_39_CHECK_DIGIT) !== undefined;\n            if (possibleFormats) {\n                if (possibleFormats.includes(BarcodeFormat$1.EAN_13) ||\n                    possibleFormats.includes(BarcodeFormat$1.UPC_A) ||\n                    possibleFormats.includes(BarcodeFormat$1.EAN_8) ||\n                    possibleFormats.includes(BarcodeFormat$1.UPC_E)) {\n                    this.readers.push(new MultiFormatUPCEANReader(hints));\n                }\n                if (possibleFormats.includes(BarcodeFormat$1.CODE_39)) {\n                    this.readers.push(new Code39Reader(useCode39CheckDigit));\n                }\n                // if (possibleFormats.includes(BarcodeFormat.CODE_93)) {\n                //    this.readers.push(new Code93Reader());\n                // }\n                if (possibleFormats.includes(BarcodeFormat$1.CODE_128)) {\n                    this.readers.push(new Code128Reader());\n                }\n                if (possibleFormats.includes(BarcodeFormat$1.ITF)) {\n                    this.readers.push(new ITFReader());\n                }\n                // if (possibleFormats.includes(BarcodeFormat.CODABAR)) {\n                //    this.readers.push(new CodaBarReader());\n                // }\n                if (possibleFormats.includes(BarcodeFormat$1.RSS_14)) {\n                    this.readers.push(new RSS14Reader());\n                }\n                if (possibleFormats.includes(BarcodeFormat$1.RSS_EXPANDED)) {\n                    this.readers.push(new RSSExpandedReader(this.verbose));\n                }\n            } else {\n                // Case when no hints were provided -> add all.\n                this.readers.push(new MultiFormatUPCEANReader(hints));\n                this.readers.push(new Code39Reader());\n                // this.readers.push(new CodaBarReader());\n                // this.readers.push(new Code93Reader());\n                this.readers.push(new MultiFormatUPCEANReader(hints));\n                this.readers.push(new Code128Reader());\n                this.readers.push(new ITFReader());\n                this.readers.push(new RSS14Reader());\n                this.readers.push(new RSSExpandedReader(this.verbose));\n            }\n        }\n        // @Override\n        decodeRow(rowNumber, row, hints) {\n            for (let i = 0; i < this.readers.length; i++) {\n                try {\n                    return this.readers[i].decodeRow(rowNumber, row, hints);\n                }\n                catch (re) {\n                    // continue\n                }\n            }\n            throw new NotFoundException();\n        }\n        // @Override\n        reset() {\n            this.readers.forEach(reader => reader.reset());\n        }\n    }\n\n    /**\n     * @deprecated Moving to @zxing/browser\n     *\n     * Barcode reader reader to use from browser.\n     */\n    class BrowserBarcodeReader extends BrowserCodeReader {\n        /**\n         * Creates an instance of BrowserBarcodeReader.\n         * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n         * @param {Map<DecodeHintType, any>} hints\n         */\n        constructor(timeBetweenScansMillis = 500, hints) {\n            super(new MultiFormatOneDReader(hints), timeBetweenScansMillis, hints);\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will\n     * use blocks of differing sizes within one version, so, this encapsulates the parameters for\n     * each set of blocks. It also holds the number of error-correction codewords per block since it\n     * will be the same across all blocks within one version.</p>\n     */\n    class ECBlocks {\n        constructor(ecCodewords, ecBlocks1, ecBlocks2) {\n            this.ecCodewords = ecCodewords;\n            this.ecBlocks = [ecBlocks1];\n            ecBlocks2 && this.ecBlocks.push(ecBlocks2);\n        }\n        getECCodewords() {\n            return this.ecCodewords;\n        }\n        getECBlocks() {\n            return this.ecBlocks;\n        }\n    }\n    /**\n     * <p>Encapsulates the parameters for one error-correction block in one symbol version.\n     * This includes the number of data codewords, and the number of times a block with these\n     * parameters is used consecutively in the Data Matrix code version's format.</p>\n     */\n    class ECB {\n        constructor(count, dataCodewords) {\n            this.count = count;\n            this.dataCodewords = dataCodewords;\n        }\n        getCount() {\n            return this.count;\n        }\n        getDataCodewords() {\n            return this.dataCodewords;\n        }\n    }\n    /**\n     * The Version object encapsulates attributes about a particular\n     * size Data Matrix Code.\n     *\n     * @author bbrown@google.com (Brian Brown)\n     */\n    class Version {\n        constructor(versionNumber, symbolSizeRows, symbolSizeColumns, dataRegionSizeRows, dataRegionSizeColumns, ecBlocks) {\n            this.versionNumber = versionNumber;\n            this.symbolSizeRows = symbolSizeRows;\n            this.symbolSizeColumns = symbolSizeColumns;\n            this.dataRegionSizeRows = dataRegionSizeRows;\n            this.dataRegionSizeColumns = dataRegionSizeColumns;\n            this.ecBlocks = ecBlocks;\n            // Calculate the total number of codewords\n            let total = 0;\n            const ecCodewords = ecBlocks.getECCodewords();\n            const ecbArray = ecBlocks.getECBlocks();\n            for (let ecBlock of ecbArray) {\n                total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);\n            }\n            this.totalCodewords = total;\n        }\n        getVersionNumber() {\n            return this.versionNumber;\n        }\n        getSymbolSizeRows() {\n            return this.symbolSizeRows;\n        }\n        getSymbolSizeColumns() {\n            return this.symbolSizeColumns;\n        }\n        getDataRegionSizeRows() {\n            return this.dataRegionSizeRows;\n        }\n        getDataRegionSizeColumns() {\n            return this.dataRegionSizeColumns;\n        }\n        getTotalCodewords() {\n            return this.totalCodewords;\n        }\n        getECBlocks() {\n            return this.ecBlocks;\n        }\n        /**\n         * <p>Deduces version information from Data Matrix dimensions.</p>\n         *\n         * @param numRows Number of rows in modules\n         * @param numColumns Number of columns in modules\n         * @return Version for a Data Matrix Code of those dimensions\n         * @throws FormatException if dimensions do correspond to a valid Data Matrix size\n         */\n        static getVersionForDimensions(numRows, numColumns) {\n            if ((numRows & 0x01) !== 0 || (numColumns & 0x01) !== 0) {\n                throw new FormatException();\n            }\n            for (let version of Version.VERSIONS) {\n                if (version.symbolSizeRows === numRows && version.symbolSizeColumns === numColumns) {\n                    return version;\n                }\n            }\n            throw new FormatException();\n        }\n        //  @Override\n        toString() {\n            return '' + this.versionNumber;\n        }\n        /**\n         * See ISO 16022:2006 5.5.1 Table 7\n         */\n        static buildVersions() {\n            return [\n                new Version(1, 10, 10, 8, 8, new ECBlocks(5, new ECB(1, 3))),\n                new Version(2, 12, 12, 10, 10, new ECBlocks(7, new ECB(1, 5))),\n                new Version(3, 14, 14, 12, 12, new ECBlocks(10, new ECB(1, 8))),\n                new Version(4, 16, 16, 14, 14, new ECBlocks(12, new ECB(1, 12))),\n                new Version(5, 18, 18, 16, 16, new ECBlocks(14, new ECB(1, 18))),\n                new Version(6, 20, 20, 18, 18, new ECBlocks(18, new ECB(1, 22))),\n                new Version(7, 22, 22, 20, 20, new ECBlocks(20, new ECB(1, 30))),\n                new Version(8, 24, 24, 22, 22, new ECBlocks(24, new ECB(1, 36))),\n                new Version(9, 26, 26, 24, 24, new ECBlocks(28, new ECB(1, 44))),\n                new Version(10, 32, 32, 14, 14, new ECBlocks(36, new ECB(1, 62))),\n                new Version(11, 36, 36, 16, 16, new ECBlocks(42, new ECB(1, 86))),\n                new Version(12, 40, 40, 18, 18, new ECBlocks(48, new ECB(1, 114))),\n                new Version(13, 44, 44, 20, 20, new ECBlocks(56, new ECB(1, 144))),\n                new Version(14, 48, 48, 22, 22, new ECBlocks(68, new ECB(1, 174))),\n                new Version(15, 52, 52, 24, 24, new ECBlocks(42, new ECB(2, 102))),\n                new Version(16, 64, 64, 14, 14, new ECBlocks(56, new ECB(2, 140))),\n                new Version(17, 72, 72, 16, 16, new ECBlocks(36, new ECB(4, 92))),\n                new Version(18, 80, 80, 18, 18, new ECBlocks(48, new ECB(4, 114))),\n                new Version(19, 88, 88, 20, 20, new ECBlocks(56, new ECB(4, 144))),\n                new Version(20, 96, 96, 22, 22, new ECBlocks(68, new ECB(4, 174))),\n                new Version(21, 104, 104, 24, 24, new ECBlocks(56, new ECB(6, 136))),\n                new Version(22, 120, 120, 18, 18, new ECBlocks(68, new ECB(6, 175))),\n                new Version(23, 132, 132, 20, 20, new ECBlocks(62, new ECB(8, 163))),\n                new Version(24, 144, 144, 22, 22, new ECBlocks(62, new ECB(8, 156), new ECB(2, 155))),\n                new Version(25, 8, 18, 6, 16, new ECBlocks(7, new ECB(1, 5))),\n                new Version(26, 8, 32, 6, 14, new ECBlocks(11, new ECB(1, 10))),\n                new Version(27, 12, 26, 10, 24, new ECBlocks(14, new ECB(1, 16))),\n                new Version(28, 12, 36, 10, 16, new ECBlocks(18, new ECB(1, 22))),\n                new Version(29, 16, 36, 14, 16, new ECBlocks(24, new ECB(1, 32))),\n                new Version(30, 16, 48, 14, 22, new ECBlocks(28, new ECB(1, 49)))\n            ];\n        }\n    }\n    Version.VERSIONS = Version.buildVersions();\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * @author bbrown@google.com (Brian Brown)\n     */\n    class BitMatrixParser {\n        /**\n         * @param bitMatrix {@link BitMatrix} to parse\n         * @throws FormatException if dimension is < 8 or > 144 or not 0 mod 2\n         */\n        constructor(bitMatrix) {\n            const dimension = bitMatrix.getHeight();\n            if (dimension < 8 || dimension > 144 || (dimension & 0x01) !== 0) {\n                throw new FormatException();\n            }\n            this.version = BitMatrixParser.readVersion(bitMatrix);\n            this.mappingBitMatrix = this.extractDataRegion(bitMatrix);\n            this.readMappingMatrix = new BitMatrix(this.mappingBitMatrix.getWidth(), this.mappingBitMatrix.getHeight());\n        }\n        getVersion() {\n            return this.version;\n        }\n        /**\n         * <p>Creates the version object based on the dimension of the original bit matrix from\n         * the datamatrix code.</p>\n         *\n         * <p>See ISO 16022:2006 Table 7 - ECC 200 symbol attributes</p>\n         *\n         * @param bitMatrix Original {@link BitMatrix} including alignment patterns\n         * @return {@link Version} encapsulating the Data Matrix Code's \"version\"\n         * @throws FormatException if the dimensions of the mapping matrix are not valid\n         * Data Matrix dimensions.\n         */\n        static readVersion(bitMatrix) {\n            const numRows = bitMatrix.getHeight();\n            const numColumns = bitMatrix.getWidth();\n            return Version.getVersionForDimensions(numRows, numColumns);\n        }\n        /**\n         * <p>Reads the bits in the {@link BitMatrix} representing the mapping matrix (No alignment patterns)\n         * in the correct order in order to reconstitute the codewords bytes contained within the\n         * Data Matrix Code.</p>\n         *\n         * @return bytes encoded within the Data Matrix Code\n         * @throws FormatException if the exact number of bytes expected is not read\n         */\n        readCodewords() {\n            const result = new Int8Array(this.version.getTotalCodewords());\n            let resultOffset = 0;\n            let row = 4;\n            let column = 0;\n            const numRows = this.mappingBitMatrix.getHeight();\n            const numColumns = this.mappingBitMatrix.getWidth();\n            let corner1Read = false;\n            let corner2Read = false;\n            let corner3Read = false;\n            let corner4Read = false;\n            // Read all of the codewords\n            do {\n                // Check the four corner cases\n                if ((row === numRows) && (column === 0) && !corner1Read) {\n                    result[resultOffset++] = this.readCorner1(numRows, numColumns) & 0xff;\n                    row -= 2;\n                    column += 2;\n                    corner1Read = true;\n                }\n                else if ((row === numRows - 2) && (column === 0) && ((numColumns & 0x03) !== 0) && !corner2Read) {\n                    result[resultOffset++] = this.readCorner2(numRows, numColumns) & 0xff;\n                    row -= 2;\n                    column += 2;\n                    corner2Read = true;\n                }\n                else if ((row === numRows + 4) && (column === 2) && ((numColumns & 0x07) === 0) && !corner3Read) {\n                    result[resultOffset++] = this.readCorner3(numRows, numColumns) & 0xff;\n                    row -= 2;\n                    column += 2;\n                    corner3Read = true;\n                }\n                else if ((row === numRows - 2) && (column === 0) && ((numColumns & 0x07) === 4) && !corner4Read) {\n                    result[resultOffset++] = this.readCorner4(numRows, numColumns) & 0xff;\n                    row -= 2;\n                    column += 2;\n                    corner4Read = true;\n                }\n                else {\n                    // Sweep upward diagonally to the right\n                    do {\n                        if ((row < numRows) && (column >= 0) && !this.readMappingMatrix.get(column, row)) {\n                            result[resultOffset++] = this.readUtah(row, column, numRows, numColumns) & 0xff;\n                        }\n                        row -= 2;\n                        column += 2;\n                    } while ((row >= 0) && (column < numColumns));\n                    row += 1;\n                    column += 3;\n                    // Sweep downward diagonally to the left\n                    do {\n                        if ((row >= 0) && (column < numColumns) && !this.readMappingMatrix.get(column, row)) {\n                            result[resultOffset++] = this.readUtah(row, column, numRows, numColumns) & 0xff;\n                        }\n                        row += 2;\n                        column -= 2;\n                    } while ((row < numRows) && (column >= 0));\n                    row += 3;\n                    column += 1;\n                }\n            } while ((row < numRows) || (column < numColumns));\n            if (resultOffset !== this.version.getTotalCodewords()) {\n                throw new FormatException();\n            }\n            return result;\n        }\n        /**\n         * <p>Reads a bit of the mapping matrix accounting for boundary wrapping.</p>\n         *\n         * @param row Row to read in the mapping matrix\n         * @param column Column to read in the mapping matrix\n         * @param numRows Number of rows in the mapping matrix\n         * @param numColumns Number of columns in the mapping matrix\n         * @return value of the given bit in the mapping matrix\n         */\n        readModule(row, column, numRows, numColumns) {\n            // Adjust the row and column indices based on boundary wrapping\n            if (row < 0) {\n                row += numRows;\n                column += 4 - ((numRows + 4) & 0x07);\n            }\n            if (column < 0) {\n                column += numColumns;\n                row += 4 - ((numColumns + 4) & 0x07);\n            }\n            this.readMappingMatrix.set(column, row);\n            return this.mappingBitMatrix.get(column, row);\n        }\n        /**\n         * <p>Reads the 8 bits of the standard Utah-shaped pattern.</p>\n         *\n         * <p>See ISO 16022:2006, 5.8.1 Figure 6</p>\n         *\n         * @param row Current row in the mapping matrix, anchored at the 8th bit (LSB) of the pattern\n         * @param column Current column in the mapping matrix, anchored at the 8th bit (LSB) of the pattern\n         * @param numRows Number of rows in the mapping matrix\n         * @param numColumns Number of columns in the mapping matrix\n         * @return byte from the utah shape\n         */\n        readUtah(row, column, numRows, numColumns) {\n            let currentByte = 0;\n            if (this.readModule(row - 2, column - 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(row - 2, column - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(row - 1, column - 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(row - 1, column - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(row - 1, column, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(row, column - 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(row, column - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(row, column, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            return currentByte;\n        }\n        /**\n         * <p>Reads the 8 bits of the special corner condition 1.</p>\n         *\n         * <p>See ISO 16022:2006, Figure F.3</p>\n         *\n         * @param numRows Number of rows in the mapping matrix\n         * @param numColumns Number of columns in the mapping matrix\n         * @return byte from the Corner condition 1\n         */\n        readCorner1(numRows, numColumns) {\n            let currentByte = 0;\n            if (this.readModule(numRows - 1, 0, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(numRows - 1, 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(numRows - 1, 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(1, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(2, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(3, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            return currentByte;\n        }\n        /**\n         * <p>Reads the 8 bits of the special corner condition 2.</p>\n         *\n         * <p>See ISO 16022:2006, Figure F.4</p>\n         *\n         * @param numRows Number of rows in the mapping matrix\n         * @param numColumns Number of columns in the mapping matrix\n         * @return byte from the Corner condition 2\n         */\n        readCorner2(numRows, numColumns) {\n            let currentByte = 0;\n            if (this.readModule(numRows - 3, 0, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(numRows - 2, 0, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(numRows - 1, 0, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 4, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 3, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(1, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            return currentByte;\n        }\n        /**\n         * <p>Reads the 8 bits of the special corner condition 3.</p>\n         *\n         * <p>See ISO 16022:2006, Figure F.5</p>\n         *\n         * @param numRows Number of rows in the mapping matrix\n         * @param numColumns Number of columns in the mapping matrix\n         * @return byte from the Corner condition 3\n         */\n        readCorner3(numRows, numColumns) {\n            let currentByte = 0;\n            if (this.readModule(numRows - 1, 0, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(numRows - 1, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 3, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(1, numColumns - 3, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(1, numColumns - 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(1, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            return currentByte;\n        }\n        /**\n         * <p>Reads the 8 bits of the special corner condition 4.</p>\n         *\n         * <p>See ISO 16022:2006, Figure F.6</p>\n         *\n         * @param numRows Number of rows in the mapping matrix\n         * @param numColumns Number of columns in the mapping matrix\n         * @return byte from the Corner condition 4\n         */\n        readCorner4(numRows, numColumns) {\n            let currentByte = 0;\n            if (this.readModule(numRows - 3, 0, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(numRows - 2, 0, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(numRows - 1, 0, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(1, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(2, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(3, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            return currentByte;\n        }\n        /**\n         * <p>Extracts the data region from a {@link BitMatrix} that contains\n         * alignment patterns.</p>\n         *\n         * @param bitMatrix Original {@link BitMatrix} with alignment patterns\n         * @return BitMatrix that has the alignment patterns removed\n         */\n        extractDataRegion(bitMatrix) {\n            const symbolSizeRows = this.version.getSymbolSizeRows();\n            const symbolSizeColumns = this.version.getSymbolSizeColumns();\n            if (bitMatrix.getHeight() !== symbolSizeRows) {\n                throw new IllegalArgumentException('Dimension of bitMatrix must match the version size');\n            }\n            const dataRegionSizeRows = this.version.getDataRegionSizeRows();\n            const dataRegionSizeColumns = this.version.getDataRegionSizeColumns();\n            const numDataRegionsRow = symbolSizeRows / dataRegionSizeRows | 0;\n            const numDataRegionsColumn = symbolSizeColumns / dataRegionSizeColumns | 0;\n            const sizeDataRegionRow = numDataRegionsRow * dataRegionSizeRows;\n            const sizeDataRegionColumn = numDataRegionsColumn * dataRegionSizeColumns;\n            const bitMatrixWithoutAlignment = new BitMatrix(sizeDataRegionColumn, sizeDataRegionRow);\n            for (let dataRegionRow = 0; dataRegionRow < numDataRegionsRow; ++dataRegionRow) {\n                const dataRegionRowOffset = dataRegionRow * dataRegionSizeRows;\n                for (let dataRegionColumn = 0; dataRegionColumn < numDataRegionsColumn; ++dataRegionColumn) {\n                    const dataRegionColumnOffset = dataRegionColumn * dataRegionSizeColumns;\n                    for (let i = 0; i < dataRegionSizeRows; ++i) {\n                        const readRowOffset = dataRegionRow * (dataRegionSizeRows + 2) + 1 + i;\n                        const writeRowOffset = dataRegionRowOffset + i;\n                        for (let j = 0; j < dataRegionSizeColumns; ++j) {\n                            const readColumnOffset = dataRegionColumn * (dataRegionSizeColumns + 2) + 1 + j;\n                            if (bitMatrix.get(readColumnOffset, readRowOffset)) {\n                                const writeColumnOffset = dataRegionColumnOffset + j;\n                                bitMatrixWithoutAlignment.set(writeColumnOffset, writeRowOffset);\n                            }\n                        }\n                    }\n                }\n            }\n            return bitMatrixWithoutAlignment;\n        }\n    }\n\n    /**\n     * <p>Encapsulates a block of data within a Data Matrix Code. Data Matrix Codes may split their data into\n     * multiple blocks, each of which is a unit of data and error-correction codewords. Each\n     * is represented by an instance of this class.</p>\n     *\n     * @author bbrown@google.com (Brian Brown)\n     */\n    class DataBlock {\n        constructor(numDataCodewords, codewords) {\n            this.numDataCodewords = numDataCodewords;\n            this.codewords = codewords;\n        }\n        /**\n         * <p>When Data Matrix Codes use multiple data blocks, they actually interleave the bytes of each of them.\n         * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This\n         * method will separate the data into original blocks.</p>\n         *\n         * @param rawCodewords bytes as read directly from the Data Matrix Code\n         * @param version version of the Data Matrix Code\n         * @return DataBlocks containing original bytes, \"de-interleaved\" from representation in the\n         *         Data Matrix Code\n         */\n        static getDataBlocks(rawCodewords, version) {\n            // Figure out the number and size of data blocks used by this version\n            const ecBlocks = version.getECBlocks();\n            // First count the total number of data blocks\n            let totalBlocks = 0;\n            const ecBlockArray = ecBlocks.getECBlocks();\n            for (let ecBlock of ecBlockArray) {\n                totalBlocks += ecBlock.getCount();\n            }\n            // Now establish DataBlocks of the appropriate size and number of data codewords\n            const result = new Array(totalBlocks);\n            let numResultBlocks = 0;\n            for (let ecBlock of ecBlockArray) {\n                for (let i = 0; i < ecBlock.getCount(); i++) {\n                    const numDataCodewords = ecBlock.getDataCodewords();\n                    const numBlockCodewords = ecBlocks.getECCodewords() + numDataCodewords;\n                    result[numResultBlocks++] = new DataBlock(numDataCodewords, new Uint8Array(numBlockCodewords));\n                }\n            }\n            // All blocks have the same amount of data, except that the last n\n            // (where n may be 0) have 1 less byte. Figure out where these start.\n            // TODO(bbrown): There is only one case where there is a difference for Data Matrix for size 144\n            const longerBlocksTotalCodewords = result[0].codewords.length;\n            // int shorterBlocksTotalCodewords = longerBlocksTotalCodewords - 1;\n            const longerBlocksNumDataCodewords = longerBlocksTotalCodewords - ecBlocks.getECCodewords();\n            const shorterBlocksNumDataCodewords = longerBlocksNumDataCodewords - 1;\n            // The last elements of result may be 1 element shorter for 144 matrix\n            // first fill out as many elements as all of them have minus 1\n            let rawCodewordsOffset = 0;\n            for (let i = 0; i < shorterBlocksNumDataCodewords; i++) {\n                for (let j = 0; j < numResultBlocks; j++) {\n                    result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];\n                }\n            }\n            // Fill out the last data block in the longer ones\n            const specialVersion = version.getVersionNumber() === 24;\n            const numLongerBlocks = specialVersion ? 8 : numResultBlocks;\n            for (let j = 0; j < numLongerBlocks; j++) {\n                result[j].codewords[longerBlocksNumDataCodewords - 1] = rawCodewords[rawCodewordsOffset++];\n            }\n            // Now add in error correction blocks\n            const max = result[0].codewords.length;\n            for (let i = longerBlocksNumDataCodewords; i < max; i++) {\n                for (let j = 0; j < numResultBlocks; j++) {\n                    const jOffset = specialVersion ? (j + 8) % numResultBlocks : j;\n                    const iOffset = specialVersion && jOffset > 7 ? i - 1 : i;\n                    result[jOffset].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];\n                }\n            }\n            if (rawCodewordsOffset !== rawCodewords.length) {\n                throw new IllegalArgumentException();\n            }\n            return result;\n        }\n        getNumDataCodewords() {\n            return this.numDataCodewords;\n        }\n        getCodewords() {\n            return this.codewords;\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>This provides an easy abstraction to read bits at a time from a sequence of bytes, where the\n     * number of bits read is not often a multiple of 8.</p>\n     *\n     * <p>This class is thread-safe but not reentrant -- unless the caller modifies the bytes array\n     * it passed in, in which case all bets are off.</p>\n     *\n     * @author Sean Owen\n     */\n    class BitSource {\n        /**\n         * @param bytes bytes from which this will read bits. Bits will be read from the first byte first.\n         * Bits are read within a byte from most-significant to least-significant bit.\n         */\n        constructor(bytes) {\n            this.bytes = bytes;\n            this.byteOffset = 0;\n            this.bitOffset = 0;\n        }\n        /**\n         * @return index of next bit in current byte which would be read by the next call to {@link #readBits(int)}.\n         */\n        getBitOffset() {\n            return this.bitOffset;\n        }\n        /**\n         * @return index of next byte in input byte array which would be read by the next call to {@link #readBits(int)}.\n         */\n        getByteOffset() {\n            return this.byteOffset;\n        }\n        /**\n         * @param numBits number of bits to read\n         * @return int representing the bits read. The bits will appear as the least-significant\n         *         bits of the int\n         * @throws IllegalArgumentException if numBits isn't in [1,32] or more than is available\n         */\n        readBits(numBits /*int*/) {\n            if (numBits < 1 || numBits > 32 || numBits > this.available()) {\n                throw new IllegalArgumentException('' + numBits);\n            }\n            let result = 0;\n            let bitOffset = this.bitOffset;\n            let byteOffset = this.byteOffset;\n            const bytes = this.bytes;\n            // First, read remainder from current byte\n            if (bitOffset > 0) {\n                const bitsLeft = 8 - bitOffset;\n                const toRead = numBits < bitsLeft ? numBits : bitsLeft;\n                const bitsToNotRead = bitsLeft - toRead;\n                const mask = (0xFF >> (8 - toRead)) << bitsToNotRead;\n                result = (bytes[byteOffset] & mask) >> bitsToNotRead;\n                numBits -= toRead;\n                bitOffset += toRead;\n                if (bitOffset === 8) {\n                    bitOffset = 0;\n                    byteOffset++;\n                }\n            }\n            // Next read whole bytes\n            if (numBits > 0) {\n                while (numBits >= 8) {\n                    result = (result << 8) | (bytes[byteOffset] & 0xFF);\n                    byteOffset++;\n                    numBits -= 8;\n                }\n                // Finally read a partial byte\n                if (numBits > 0) {\n                    const bitsToNotRead = 8 - numBits;\n                    const mask = (0xFF >> bitsToNotRead) << bitsToNotRead;\n                    result = (result << numBits) | ((bytes[byteOffset] & mask) >> bitsToNotRead);\n                    bitOffset += numBits;\n                }\n            }\n            this.bitOffset = bitOffset;\n            this.byteOffset = byteOffset;\n            return result;\n        }\n        /**\n         * @return number of bits that can be read successfully\n         */\n        available() {\n            return 8 * (this.bytes.length - this.byteOffset) - this.bitOffset;\n        }\n    }\n\n    var Mode;\n    (function (Mode) {\n        Mode[Mode[\"PAD_ENCODE\"] = 0] = \"PAD_ENCODE\";\n        Mode[Mode[\"ASCII_ENCODE\"] = 1] = \"ASCII_ENCODE\";\n        Mode[Mode[\"C40_ENCODE\"] = 2] = \"C40_ENCODE\";\n        Mode[Mode[\"TEXT_ENCODE\"] = 3] = \"TEXT_ENCODE\";\n        Mode[Mode[\"ANSIX12_ENCODE\"] = 4] = \"ANSIX12_ENCODE\";\n        Mode[Mode[\"EDIFACT_ENCODE\"] = 5] = \"EDIFACT_ENCODE\";\n        Mode[Mode[\"BASE256_ENCODE\"] = 6] = \"BASE256_ENCODE\";\n    })(Mode || (Mode = {}));\n    /**\n     * <p>Data Matrix Codes can encode text as bits in one of several modes, and can use multiple modes\n     * in one Data Matrix Code. This class decodes the bits back into text.</p>\n     *\n     * <p>See ISO 16022:2006, 5.2.1 - 5.2.9.2</p>\n     *\n     * @author bbrown@google.com (Brian Brown)\n     * @author Sean Owen\n     */\n    class DecodedBitStreamParser {\n        static decode(bytes) {\n            const bits = new BitSource(bytes);\n            const result = new StringBuilder();\n            const resultTrailer = new StringBuilder();\n            const byteSegments = new Array();\n            let mode = Mode.ASCII_ENCODE;\n            do {\n                if (mode === Mode.ASCII_ENCODE) {\n                    mode = this.decodeAsciiSegment(bits, result, resultTrailer);\n                }\n                else {\n                    switch (mode) {\n                        case Mode.C40_ENCODE:\n                            this.decodeC40Segment(bits, result);\n                            break;\n                        case Mode.TEXT_ENCODE:\n                            this.decodeTextSegment(bits, result);\n                            break;\n                        case Mode.ANSIX12_ENCODE:\n                            this.decodeAnsiX12Segment(bits, result);\n                            break;\n                        case Mode.EDIFACT_ENCODE:\n                            this.decodeEdifactSegment(bits, result);\n                            break;\n                        case Mode.BASE256_ENCODE:\n                            this.decodeBase256Segment(bits, result, byteSegments);\n                            break;\n                        default:\n                            throw new FormatException();\n                    }\n                    mode = Mode.ASCII_ENCODE;\n                }\n            } while (mode !== Mode.PAD_ENCODE && bits.available() > 0);\n            if (resultTrailer.length() > 0) {\n                result.append(resultTrailer.toString());\n            }\n            return new DecoderResult(bytes, result.toString(), byteSegments.length === 0 ? null : byteSegments, null);\n        }\n        /**\n         * See ISO 16022:2006, 5.2.3 and Annex C, Table C.2\n         */\n        static decodeAsciiSegment(bits, result, resultTrailer) {\n            let upperShift = false;\n            do {\n                let oneByte = bits.readBits(8);\n                if (oneByte === 0) {\n                    throw new FormatException();\n                }\n                else if (oneByte <= 128) { // ASCII data (ASCII value + 1)\n                    if (upperShift) {\n                        oneByte += 128;\n                        // upperShift = false;\n                    }\n                    result.append(String.fromCharCode(oneByte - 1));\n                    return Mode.ASCII_ENCODE;\n                }\n                else if (oneByte === 129) { // Pad\n                    return Mode.PAD_ENCODE;\n                }\n                else if (oneByte <= 229) { // 2-digit data 00-99 (Numeric Value + 130)\n                    const value = oneByte - 130;\n                    if (value < 10) { // pad with '0' for single digit values\n                        result.append('0');\n                    }\n                    result.append('' + value);\n                }\n                else {\n                    switch (oneByte) {\n                        case 230: // Latch to C40 encodation\n                            return Mode.C40_ENCODE;\n                        case 231: // Latch to Base 256 encodation\n                            return Mode.BASE256_ENCODE;\n                        case 232: // FNC1\n                            result.append(String.fromCharCode(29)); // translate as ASCII 29\n                            break;\n                        case 233: // Structured Append\n                        case 234: // Reader Programming\n                            // Ignore these symbols for now\n                            // throw ReaderException.getInstance();\n                            break;\n                        case 235: // Upper Shift (shift to Extended ASCII)\n                            upperShift = true;\n                            break;\n                        case 236: // 05 Macro\n                            result.append('[)>\\u001E05\\u001D');\n                            resultTrailer.insert(0, '\\u001E\\u0004');\n                            break;\n                        case 237: // 06 Macro\n                            result.append('[)>\\u001E06\\u001D');\n                            resultTrailer.insert(0, '\\u001E\\u0004');\n                            break;\n                        case 238: // Latch to ANSI X12 encodation\n                            return Mode.ANSIX12_ENCODE;\n                        case 239: // Latch to Text encodation\n                            return Mode.TEXT_ENCODE;\n                        case 240: // Latch to EDIFACT encodation\n                            return Mode.EDIFACT_ENCODE;\n                        case 241: // ECI Character\n                            // TODO(bbrown): I think we need to support ECI\n                            // throw ReaderException.getInstance();\n                            // Ignore this symbol for now\n                            break;\n                        default:\n                            // Not to be used in ASCII encodation\n                            // but work around encoders that end with 254, latch back to ASCII\n                            if (oneByte !== 254 || bits.available() !== 0) {\n                                throw new FormatException();\n                            }\n                            break;\n                    }\n                }\n            } while (bits.available() > 0);\n            return Mode.ASCII_ENCODE;\n        }\n        /**\n         * See ISO 16022:2006, 5.2.5 and Annex C, Table C.1\n         */\n        static decodeC40Segment(bits, result) {\n            // Three C40 values are encoded in a 16-bit value as\n            // (1600 * C1) + (40 * C2) + C3 + 1\n            // TODO(bbrown): The Upper Shift with C40 doesn't work in the 4 value scenario all the time\n            let upperShift = false;\n            const cValues = [];\n            let shift = 0;\n            do {\n                // If there is only one byte left then it will be encoded as ASCII\n                if (bits.available() === 8) {\n                    return;\n                }\n                const firstByte = bits.readBits(8);\n                if (firstByte === 254) { // Unlatch codeword\n                    return;\n                }\n                this.parseTwoBytes(firstByte, bits.readBits(8), cValues);\n                for (let i = 0; i < 3; i++) {\n                    const cValue = cValues[i];\n                    switch (shift) {\n                        case 0:\n                            if (cValue < 3) {\n                                shift = cValue + 1;\n                            }\n                            else if (cValue < this.C40_BASIC_SET_CHARS.length) {\n                                const c40char = this.C40_BASIC_SET_CHARS[cValue];\n                                if (upperShift) {\n                                    result.append(String.fromCharCode(c40char.charCodeAt(0) + 128));\n                                    upperShift = false;\n                                }\n                                else {\n                                    result.append(c40char);\n                                }\n                            }\n                            else {\n                                throw new FormatException();\n                            }\n                            break;\n                        case 1:\n                            if (upperShift) {\n                                result.append(String.fromCharCode(cValue + 128));\n                                upperShift = false;\n                            }\n                            else {\n                                result.append(String.fromCharCode(cValue));\n                            }\n                            shift = 0;\n                            break;\n                        case 2:\n                            if (cValue < this.C40_SHIFT2_SET_CHARS.length) {\n                                const c40char = this.C40_SHIFT2_SET_CHARS[cValue];\n                                if (upperShift) {\n                                    result.append(String.fromCharCode(c40char.charCodeAt(0) + 128));\n                                    upperShift = false;\n                                }\n                                else {\n                                    result.append(c40char);\n                                }\n                            }\n                            else {\n                                switch (cValue) {\n                                    case 27: // FNC1\n                                        result.append(String.fromCharCode(29)); // translate as ASCII 29\n                                        break;\n                                    case 30: // Upper Shift\n                                        upperShift = true;\n                                        break;\n                                    default:\n                                        throw new FormatException();\n                                }\n                            }\n                            shift = 0;\n                            break;\n                        case 3:\n                            if (upperShift) {\n                                result.append(String.fromCharCode(cValue + 224));\n                                upperShift = false;\n                            }\n                            else {\n                                result.append(String.fromCharCode(cValue + 96));\n                            }\n                            shift = 0;\n                            break;\n                        default:\n                            throw new FormatException();\n                    }\n                }\n            } while (bits.available() > 0);\n        }\n        /**\n         * See ISO 16022:2006, 5.2.6 and Annex C, Table C.2\n         */\n        static decodeTextSegment(bits, result) {\n            // Three Text values are encoded in a 16-bit value as\n            // (1600 * C1) + (40 * C2) + C3 + 1\n            // TODO(bbrown): The Upper Shift with Text doesn't work in the 4 value scenario all the time\n            let upperShift = false;\n            let cValues = [];\n            let shift = 0;\n            do {\n                // If there is only one byte left then it will be encoded as ASCII\n                if (bits.available() === 8) {\n                    return;\n                }\n                const firstByte = bits.readBits(8);\n                if (firstByte === 254) { // Unlatch codeword\n                    return;\n                }\n                this.parseTwoBytes(firstByte, bits.readBits(8), cValues);\n                for (let i = 0; i < 3; i++) {\n                    const cValue = cValues[i];\n                    switch (shift) {\n                        case 0:\n                            if (cValue < 3) {\n                                shift = cValue + 1;\n                            }\n                            else if (cValue < this.TEXT_BASIC_SET_CHARS.length) {\n                                const textChar = this.TEXT_BASIC_SET_CHARS[cValue];\n                                if (upperShift) {\n                                    result.append(String.fromCharCode(textChar.charCodeAt(0) + 128));\n                                    upperShift = false;\n                                }\n                                else {\n                                    result.append(textChar);\n                                }\n                            }\n                            else {\n                                throw new FormatException();\n                            }\n                            break;\n                        case 1:\n                            if (upperShift) {\n                                result.append(String.fromCharCode(cValue + 128));\n                                upperShift = false;\n                            }\n                            else {\n                                result.append(String.fromCharCode(cValue));\n                            }\n                            shift = 0;\n                            break;\n                        case 2:\n                            // Shift 2 for Text is the same encoding as C40\n                            if (cValue < this.TEXT_SHIFT2_SET_CHARS.length) {\n                                const textChar = this.TEXT_SHIFT2_SET_CHARS[cValue];\n                                if (upperShift) {\n                                    result.append(String.fromCharCode(textChar.charCodeAt(0) + 128));\n                                    upperShift = false;\n                                }\n                                else {\n                                    result.append(textChar);\n                                }\n                            }\n                            else {\n                                switch (cValue) {\n                                    case 27: // FNC1\n                                        result.append(String.fromCharCode(29)); // translate as ASCII 29\n                                        break;\n                                    case 30: // Upper Shift\n                                        upperShift = true;\n                                        break;\n                                    default:\n                                        throw new FormatException();\n                                }\n                            }\n                            shift = 0;\n                            break;\n                        case 3:\n                            if (cValue < this.TEXT_SHIFT3_SET_CHARS.length) {\n                                const textChar = this.TEXT_SHIFT3_SET_CHARS[cValue];\n                                if (upperShift) {\n                                    result.append(String.fromCharCode(textChar.charCodeAt(0) + 128));\n                                    upperShift = false;\n                                }\n                                else {\n                                    result.append(textChar);\n                                }\n                                shift = 0;\n                            }\n                            else {\n                                throw new FormatException();\n                            }\n                            break;\n                        default:\n                            throw new FormatException();\n                    }\n                }\n            } while (bits.available() > 0);\n        }\n        /**\n         * See ISO 16022:2006, 5.2.7\n         */\n        static decodeAnsiX12Segment(bits, result) {\n            // Three ANSI X12 values are encoded in a 16-bit value as\n            // (1600 * C1) + (40 * C2) + C3 + 1\n            const cValues = [];\n            do {\n                // If there is only one byte left then it will be encoded as ASCII\n                if (bits.available() === 8) {\n                    return;\n                }\n                const firstByte = bits.readBits(8);\n                if (firstByte === 254) { // Unlatch codeword\n                    return;\n                }\n                this.parseTwoBytes(firstByte, bits.readBits(8), cValues);\n                for (let i = 0; i < 3; i++) {\n                    const cValue = cValues[i];\n                    switch (cValue) {\n                        case 0: // X12 segment terminator <CR>\n                            result.append('\\r');\n                            break;\n                        case 1: // X12 segment separator *\n                            result.append('*');\n                            break;\n                        case 2: // X12 sub-element separator >\n                            result.append('>');\n                            break;\n                        case 3: // space\n                            result.append(' ');\n                            break;\n                        default:\n                            if (cValue < 14) { // 0 - 9\n                                result.append(String.fromCharCode(cValue + 44));\n                            }\n                            else if (cValue < 40) { // A - Z\n                                result.append(String.fromCharCode(cValue + 51));\n                            }\n                            else {\n                                throw new FormatException();\n                            }\n                            break;\n                    }\n                }\n            } while (bits.available() > 0);\n        }\n        static parseTwoBytes(firstByte, secondByte, result) {\n            let fullBitValue = (firstByte << 8) + secondByte - 1;\n            let temp = Math.floor(fullBitValue / 1600);\n            result[0] = temp;\n            fullBitValue -= temp * 1600;\n            temp = Math.floor(fullBitValue / 40);\n            result[1] = temp;\n            result[2] = fullBitValue - temp * 40;\n        }\n        /**\n         * See ISO 16022:2006, 5.2.8 and Annex C Table C.3\n         */\n        static decodeEdifactSegment(bits, result) {\n            do {\n                // If there is only two or less bytes left then it will be encoded as ASCII\n                if (bits.available() <= 16) {\n                    return;\n                }\n                for (let i = 0; i < 4; i++) {\n                    let edifactValue = bits.readBits(6);\n                    // Check for the unlatch character\n                    if (edifactValue === 0x1F) { // 011111\n                        // Read rest of byte, which should be 0, and stop\n                        const bitsLeft = 8 - bits.getBitOffset();\n                        if (bitsLeft !== 8) {\n                            bits.readBits(bitsLeft);\n                        }\n                        return;\n                    }\n                    if ((edifactValue & 0x20) === 0) { // no 1 in the leading (6th) bit\n                        edifactValue |= 0x40; // Add a leading 01 to the 6 bit binary value\n                    }\n                    result.append(String.fromCharCode(edifactValue));\n                }\n            } while (bits.available() > 0);\n        }\n        /**\n         * See ISO 16022:2006, 5.2.9 and Annex B, B.2\n         */\n        static decodeBase256Segment(bits, result, byteSegments) {\n            // Figure out how long the Base 256 Segment is.\n            let codewordPosition = 1 + bits.getByteOffset(); // position is 1-indexed\n            const d1 = this.unrandomize255State(bits.readBits(8), codewordPosition++);\n            let count;\n            if (d1 === 0) { // Read the remainder of the symbol\n                count = bits.available() / 8 | 0;\n            }\n            else if (d1 < 250) {\n                count = d1;\n            }\n            else {\n                count = 250 * (d1 - 249) + this.unrandomize255State(bits.readBits(8), codewordPosition++);\n            }\n            // We're seeing NegativeArraySizeException errors from users.\n            if (count < 0) {\n                throw new FormatException();\n            }\n            const bytes = new Uint8Array(count);\n            for (let i = 0; i < count; i++) {\n                // Have seen this particular error in the wild, such as at\n                // http://www.bcgen.com/demo/IDAutomationStreamingDataMatrix.aspx?MODE=3&D=Fred&PFMT=3&PT=F&X=0.3&O=0&LM=0.2\n                if (bits.available() < 8) {\n                    throw new FormatException();\n                }\n                bytes[i] = this.unrandomize255State(bits.readBits(8), codewordPosition++);\n            }\n            byteSegments.push(bytes);\n            try {\n                result.append(StringEncoding.decode(bytes, StringUtils.ISO88591));\n            }\n            catch (uee) {\n                throw new IllegalStateException('Platform does not support required encoding: ' + uee.message);\n            }\n        }\n        /**\n         * See ISO 16022:2006, Annex B, B.2\n         */\n        static unrandomize255State(randomizedBase256Codeword, base256CodewordPosition) {\n            const pseudoRandomNumber = ((149 * base256CodewordPosition) % 255) + 1;\n            const tempVariable = randomizedBase256Codeword - pseudoRandomNumber;\n            return tempVariable >= 0 ? tempVariable : tempVariable + 256;\n        }\n    }\n    /**\n     * See ISO 16022:2006, Annex C Table C.1\n     * The C40 Basic Character Set (*'s used for placeholders for the shift values)\n     */\n    DecodedBitStreamParser.C40_BASIC_SET_CHARS = [\n        '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',\n        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',\n        'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'\n    ];\n    DecodedBitStreamParser.C40_SHIFT2_SET_CHARS = [\n        '!', '\"', '#', '$', '%', '&', '\\'', '(', ')', '*', '+', ',', '-', '.',\n        '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\\\', ']', '^', '_'\n    ];\n    /**\n     * See ISO 16022:2006, Annex C Table C.2\n     * The Text Basic Character Set (*'s used for placeholders for the shift values)\n     */\n    DecodedBitStreamParser.TEXT_BASIC_SET_CHARS = [\n        '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',\n        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',\n        'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'\n    ];\n    // Shift 2 for Text is the same encoding as C40\n    DecodedBitStreamParser.TEXT_SHIFT2_SET_CHARS = DecodedBitStreamParser.C40_SHIFT2_SET_CHARS;\n    DecodedBitStreamParser.TEXT_SHIFT3_SET_CHARS = [\n        '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',\n        'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', String.fromCharCode(127)\n    ];\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>The main class which implements Data Matrix Code decoding -- as opposed to locating and extracting\n     * the Data Matrix Code from an image.</p>\n     *\n     * @author bbrown@google.com (Brian Brown)\n     */\n    class Decoder$1 {\n        constructor() {\n            this.rsDecoder = new ReedSolomonDecoder(GenericGF.DATA_MATRIX_FIELD_256);\n        }\n        /**\n         * <p>Decodes a Data Matrix Code represented as a {@link BitMatrix}. A 1 or \"true\" is taken\n         * to mean a black module.</p>\n         *\n         * @param bits booleans representing white/black Data Matrix Code modules\n         * @return text and bytes encoded within the Data Matrix Code\n         * @throws FormatException if the Data Matrix Code cannot be decoded\n         * @throws ChecksumException if error correction fails\n         */\n        decode(bits) {\n            // Construct a parser and read version, error-correction level\n            const parser = new BitMatrixParser(bits);\n            const version = parser.getVersion();\n            // Read codewords\n            const codewords = parser.readCodewords();\n            // Separate into data blocks\n            const dataBlocks = DataBlock.getDataBlocks(codewords, version);\n            // Count total number of data bytes\n            let totalBytes = 0;\n            for (let db of dataBlocks) {\n                totalBytes += db.getNumDataCodewords();\n            }\n            const resultBytes = new Uint8Array(totalBytes);\n            const dataBlocksCount = dataBlocks.length;\n            // Error-correct and copy data blocks together into a stream of bytes\n            for (let j = 0; j < dataBlocksCount; j++) {\n                const dataBlock = dataBlocks[j];\n                const codewordBytes = dataBlock.getCodewords();\n                const numDataCodewords = dataBlock.getNumDataCodewords();\n                this.correctErrors(codewordBytes, numDataCodewords);\n                for (let i = 0; i < numDataCodewords; i++) {\n                    // De-interlace data blocks.\n                    resultBytes[i * dataBlocksCount + j] = codewordBytes[i];\n                }\n            }\n            // Decode the contents of that stream of bytes\n            return DecodedBitStreamParser.decode(resultBytes);\n        }\n        /**\n         * <p>Given data and error-correction codewords received, possibly corrupted by errors, attempts to\n         * correct the errors in-place using Reed-Solomon error correction.</p>\n         *\n         * @param codewordBytes data and error correction codewords\n         * @param numDataCodewords number of codewords that are data bytes\n         * @throws ChecksumException if error correction fails\n         */\n        correctErrors(codewordBytes, numDataCodewords) {\n            // const numCodewords = codewordBytes.length;\n            // First read into an array of ints\n            const codewordsInts = new Int32Array(codewordBytes);\n            // for (let i = 0; i < numCodewords; i++) {\n            //   codewordsInts[i] = codewordBytes[i] & 0xFF;\n            // }\n            try {\n                this.rsDecoder.decode(codewordsInts, codewordBytes.length - numDataCodewords);\n            }\n            catch (ignored /* ReedSolomonException */) {\n                throw new ChecksumException();\n            }\n            // Copy back into array of bytes -- only need to worry about the bytes that were data\n            // We don't care about errors in the error-correction codewords\n            for (let i = 0; i < numDataCodewords; i++) {\n                codewordBytes[i] = codewordsInts[i];\n            }\n        }\n    }\n\n    /**\n     * <p>Encapsulates logic that can detect a Data Matrix Code in an image, even if the Data Matrix Code\n     * is rotated or skewed, or partially obscured.</p>\n     *\n     * @author Sean Owen\n     */\n    class Detector$1 {\n        constructor(image) {\n            this.image = image;\n            this.rectangleDetector = new WhiteRectangleDetector(this.image);\n        }\n        /**\n         * <p>Detects a Data Matrix Code in an image.</p>\n         *\n         * @return {@link DetectorResult} encapsulating results of detecting a Data Matrix Code\n         * @throws NotFoundException if no Data Matrix Code can be found\n         */\n        detect() {\n            const cornerPoints = this.rectangleDetector.detect();\n            let points = this.detectSolid1(cornerPoints);\n            points = this.detectSolid2(points);\n            points[3] = this.correctTopRight(points);\n            if (!points[3]) {\n                throw new NotFoundException();\n            }\n            points = this.shiftToModuleCenter(points);\n            const topLeft = points[0];\n            const bottomLeft = points[1];\n            const bottomRight = points[2];\n            const topRight = points[3];\n            let dimensionTop = this.transitionsBetween(topLeft, topRight) + 1;\n            let dimensionRight = this.transitionsBetween(bottomRight, topRight) + 1;\n            if ((dimensionTop & 0x01) === 1) {\n                dimensionTop += 1;\n            }\n            if ((dimensionRight & 0x01) === 1) {\n                dimensionRight += 1;\n            }\n            if (4 * dimensionTop < 7 * dimensionRight && 4 * dimensionRight < 7 * dimensionTop) {\n                // The matrix is square\n                dimensionTop = dimensionRight = Math.max(dimensionTop, dimensionRight);\n            }\n            let bits = Detector$1.sampleGrid(this.image, topLeft, bottomLeft, bottomRight, topRight, dimensionTop, dimensionRight);\n            return new DetectorResult(bits, [topLeft, bottomLeft, bottomRight, topRight]);\n        }\n        static shiftPoint(point, to, div) {\n            let x = (to.getX() - point.getX()) / (div + 1);\n            let y = (to.getY() - point.getY()) / (div + 1);\n            return new ResultPoint(point.getX() + x, point.getY() + y);\n        }\n        static moveAway(point, fromX, fromY) {\n            let x = point.getX();\n            let y = point.getY();\n            if (x < fromX) {\n                x -= 1;\n            }\n            else {\n                x += 1;\n            }\n            if (y < fromY) {\n                y -= 1;\n            }\n            else {\n                y += 1;\n            }\n            return new ResultPoint(x, y);\n        }\n        /**\n         * Detect a solid side which has minimum transition.\n         */\n        detectSolid1(cornerPoints) {\n            // 0  2\n            // 1  3\n            let pointA = cornerPoints[0];\n            let pointB = cornerPoints[1];\n            let pointC = cornerPoints[3];\n            let pointD = cornerPoints[2];\n            let trAB = this.transitionsBetween(pointA, pointB);\n            let trBC = this.transitionsBetween(pointB, pointC);\n            let trCD = this.transitionsBetween(pointC, pointD);\n            let trDA = this.transitionsBetween(pointD, pointA);\n            // 0..3\n            // :  :\n            // 1--2\n            let min = trAB;\n            let points = [pointD, pointA, pointB, pointC];\n            if (min > trBC) {\n                min = trBC;\n                points[0] = pointA;\n                points[1] = pointB;\n                points[2] = pointC;\n                points[3] = pointD;\n            }\n            if (min > trCD) {\n                min = trCD;\n                points[0] = pointB;\n                points[1] = pointC;\n                points[2] = pointD;\n                points[3] = pointA;\n            }\n            if (min > trDA) {\n                points[0] = pointC;\n                points[1] = pointD;\n                points[2] = pointA;\n                points[3] = pointB;\n            }\n            return points;\n        }\n        /**\n         * Detect a second solid side next to first solid side.\n         */\n        detectSolid2(points) {\n            // A..D\n            // :  :\n            // B--C\n            let pointA = points[0];\n            let pointB = points[1];\n            let pointC = points[2];\n            let pointD = points[3];\n            // Transition detection on the edge is not stable.\n            // To safely detect, shift the points to the module center.\n            let tr = this.transitionsBetween(pointA, pointD);\n            let pointBs = Detector$1.shiftPoint(pointB, pointC, (tr + 1) * 4);\n            let pointCs = Detector$1.shiftPoint(pointC, pointB, (tr + 1) * 4);\n            let trBA = this.transitionsBetween(pointBs, pointA);\n            let trCD = this.transitionsBetween(pointCs, pointD);\n            // 0..3\n            // |  :\n            // 1--2\n            if (trBA < trCD) {\n                // solid sides: A-B-C\n                points[0] = pointA;\n                points[1] = pointB;\n                points[2] = pointC;\n                points[3] = pointD;\n            }\n            else {\n                // solid sides: B-C-D\n                points[0] = pointB;\n                points[1] = pointC;\n                points[2] = pointD;\n                points[3] = pointA;\n            }\n            return points;\n        }\n        /**\n         * Calculates the corner position of the white top right module.\n         */\n        correctTopRight(points) {\n            // A..D\n            // |  :\n            // B--C\n            let pointA = points[0];\n            let pointB = points[1];\n            let pointC = points[2];\n            let pointD = points[3];\n            // shift points for safe transition detection.\n            let trTop = this.transitionsBetween(pointA, pointD);\n            let trRight = this.transitionsBetween(pointB, pointD);\n            let pointAs = Detector$1.shiftPoint(pointA, pointB, (trRight + 1) * 4);\n            let pointCs = Detector$1.shiftPoint(pointC, pointB, (trTop + 1) * 4);\n            trTop = this.transitionsBetween(pointAs, pointD);\n            trRight = this.transitionsBetween(pointCs, pointD);\n            let candidate1 = new ResultPoint(pointD.getX() + (pointC.getX() - pointB.getX()) / (trTop + 1), pointD.getY() + (pointC.getY() - pointB.getY()) / (trTop + 1));\n            let candidate2 = new ResultPoint(pointD.getX() + (pointA.getX() - pointB.getX()) / (trRight + 1), pointD.getY() + (pointA.getY() - pointB.getY()) / (trRight + 1));\n            if (!this.isValid(candidate1)) {\n                if (this.isValid(candidate2)) {\n                    return candidate2;\n                }\n                return null;\n            }\n            if (!this.isValid(candidate2)) {\n                return candidate1;\n            }\n            let sumc1 = this.transitionsBetween(pointAs, candidate1) + this.transitionsBetween(pointCs, candidate1);\n            let sumc2 = this.transitionsBetween(pointAs, candidate2) + this.transitionsBetween(pointCs, candidate2);\n            if (sumc1 > sumc2) {\n                return candidate1;\n            }\n            else {\n                return candidate2;\n            }\n        }\n        /**\n         * Shift the edge points to the module center.\n         */\n        shiftToModuleCenter(points) {\n            // A..D\n            // |  :\n            // B--C\n            let pointA = points[0];\n            let pointB = points[1];\n            let pointC = points[2];\n            let pointD = points[3];\n            // calculate pseudo dimensions\n            let dimH = this.transitionsBetween(pointA, pointD) + 1;\n            let dimV = this.transitionsBetween(pointC, pointD) + 1;\n            // shift points for safe dimension detection\n            let pointAs = Detector$1.shiftPoint(pointA, pointB, dimV * 4);\n            let pointCs = Detector$1.shiftPoint(pointC, pointB, dimH * 4);\n            //  calculate more precise dimensions\n            dimH = this.transitionsBetween(pointAs, pointD) + 1;\n            dimV = this.transitionsBetween(pointCs, pointD) + 1;\n            if ((dimH & 0x01) === 1) {\n                dimH += 1;\n            }\n            if ((dimV & 0x01) === 1) {\n                dimV += 1;\n            }\n            // WhiteRectangleDetector returns points inside of the rectangle.\n            // I want points on the edges.\n            let centerX = (pointA.getX() + pointB.getX() + pointC.getX() + pointD.getX()) / 4;\n            let centerY = (pointA.getY() + pointB.getY() + pointC.getY() + pointD.getY()) / 4;\n            pointA = Detector$1.moveAway(pointA, centerX, centerY);\n            pointB = Detector$1.moveAway(pointB, centerX, centerY);\n            pointC = Detector$1.moveAway(pointC, centerX, centerY);\n            pointD = Detector$1.moveAway(pointD, centerX, centerY);\n            let pointBs;\n            let pointDs;\n            // shift points to the center of each modules\n            pointAs = Detector$1.shiftPoint(pointA, pointB, dimV * 4);\n            pointAs = Detector$1.shiftPoint(pointAs, pointD, dimH * 4);\n            pointBs = Detector$1.shiftPoint(pointB, pointA, dimV * 4);\n            pointBs = Detector$1.shiftPoint(pointBs, pointC, dimH * 4);\n            pointCs = Detector$1.shiftPoint(pointC, pointD, dimV * 4);\n            pointCs = Detector$1.shiftPoint(pointCs, pointB, dimH * 4);\n            pointDs = Detector$1.shiftPoint(pointD, pointC, dimV * 4);\n            pointDs = Detector$1.shiftPoint(pointDs, pointA, dimH * 4);\n            return [pointAs, pointBs, pointCs, pointDs];\n        }\n        isValid(p) {\n            return p.getX() >= 0 && p.getX() < this.image.getWidth() && p.getY() > 0 && p.getY() < this.image.getHeight();\n        }\n        static sampleGrid(image, topLeft, bottomLeft, bottomRight, topRight, dimensionX, dimensionY) {\n            const sampler = GridSamplerInstance.getInstance();\n            return sampler.sampleGrid(image, dimensionX, dimensionY, 0.5, 0.5, dimensionX - 0.5, 0.5, dimensionX - 0.5, dimensionY - 0.5, 0.5, dimensionY - 0.5, topLeft.getX(), topLeft.getY(), topRight.getX(), topRight.getY(), bottomRight.getX(), bottomRight.getY(), bottomLeft.getX(), bottomLeft.getY());\n        }\n        /**\n         * Counts the number of black/white transitions between two points, using something like Bresenham's algorithm.\n         */\n        transitionsBetween(from, to) {\n            // See QR Code Detector, sizeOfBlackWhiteBlackRun()\n            let fromX = Math.trunc(from.getX());\n            let fromY = Math.trunc(from.getY());\n            let toX = Math.trunc(to.getX());\n            let toY = Math.trunc(to.getY());\n            let steep = Math.abs(toY - fromY) > Math.abs(toX - fromX);\n            if (steep) {\n                let temp = fromX;\n                fromX = fromY;\n                fromY = temp;\n                temp = toX;\n                toX = toY;\n                toY = temp;\n            }\n            let dx = Math.abs(toX - fromX);\n            let dy = Math.abs(toY - fromY);\n            let error = -dx / 2;\n            let ystep = fromY < toY ? 1 : -1;\n            let xstep = fromX < toX ? 1 : -1;\n            let transitions = 0;\n            let inBlack = this.image.get(steep ? fromY : fromX, steep ? fromX : fromY);\n            for (let x = fromX, y = fromY; x !== toX; x += xstep) {\n                let isBlack = this.image.get(steep ? y : x, steep ? x : y);\n                if (isBlack !== inBlack) {\n                    transitions++;\n                    inBlack = isBlack;\n                }\n                error += dy;\n                if (error > 0) {\n                    if (y === toY) {\n                        break;\n                    }\n                    y += ystep;\n                    error -= dx;\n                }\n            }\n            return transitions;\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * This implementation can detect and decode Data Matrix codes in an image.\n     *\n     * @author bbrown@google.com (Brian Brown)\n     */\n    class DataMatrixReader {\n        constructor() {\n            this.decoder = new Decoder$1();\n        }\n        /**\n         * Locates and decodes a Data Matrix code in an image.\n         *\n         * @return a String representing the content encoded by the Data Matrix code\n         * @throws NotFoundException if a Data Matrix code cannot be found\n         * @throws FormatException if a Data Matrix code cannot be decoded\n         * @throws ChecksumException if error correction fails\n         */\n        // @Override\n        // public Result decode(BinaryBitmap image) throws NotFoundException, ChecksumException, FormatException {\n        //   return decode(image, null);\n        // }\n        // @Override\n        decode(image, hints = null) {\n            let decoderResult;\n            let points;\n            if (hints != null && hints.has(DecodeHintType$1.PURE_BARCODE)) {\n                const bits = DataMatrixReader.extractPureBits(image.getBlackMatrix());\n                decoderResult = this.decoder.decode(bits);\n                points = DataMatrixReader.NO_POINTS;\n            }\n            else {\n                const detectorResult = new Detector$1(image.getBlackMatrix()).detect();\n                decoderResult = this.decoder.decode(detectorResult.getBits());\n                points = detectorResult.getPoints();\n            }\n            const rawBytes = decoderResult.getRawBytes();\n            const result = new Result(decoderResult.getText(), rawBytes, 8 * rawBytes.length, points, BarcodeFormat$1.DATA_MATRIX, System.currentTimeMillis());\n            const byteSegments = decoderResult.getByteSegments();\n            if (byteSegments != null) {\n                result.putMetadata(ResultMetadataType$1.BYTE_SEGMENTS, byteSegments);\n            }\n            const ecLevel = decoderResult.getECLevel();\n            if (ecLevel != null) {\n                result.putMetadata(ResultMetadataType$1.ERROR_CORRECTION_LEVEL, ecLevel);\n            }\n            return result;\n        }\n        // @Override\n        reset() {\n            // do nothing\n        }\n        /**\n         * This method detects a code in a \"pure\" image -- that is, pure monochrome image\n         * which contains only an unrotated, unskewed, image of a code, with some white border\n         * around it. This is a specialized method that works exceptionally fast in this special\n         * case.\n         *\n         * @see com.google.zxing.qrcode.QRCodeReader#extractPureBits(BitMatrix)\n         */\n        static extractPureBits(image) {\n            const leftTopBlack = image.getTopLeftOnBit();\n            const rightBottomBlack = image.getBottomRightOnBit();\n            if (leftTopBlack == null || rightBottomBlack == null) {\n                throw new NotFoundException();\n            }\n            const moduleSize = this.moduleSize(leftTopBlack, image);\n            let top = leftTopBlack[1];\n            const bottom = rightBottomBlack[1];\n            let left = leftTopBlack[0];\n            const right = rightBottomBlack[0];\n            const matrixWidth = (right - left + 1) / moduleSize;\n            const matrixHeight = (bottom - top + 1) / moduleSize;\n            if (matrixWidth <= 0 || matrixHeight <= 0) {\n                throw new NotFoundException();\n            }\n            // Push in the \"border\" by half the module width so that we start\n            // sampling in the middle of the module. Just in case the image is a\n            // little off, this will help recover.\n            const nudge = moduleSize / 2;\n            top += nudge;\n            left += nudge;\n            // Now just read off the bits\n            const bits = new BitMatrix(matrixWidth, matrixHeight);\n            for (let y = 0; y < matrixHeight; y++) {\n                const iOffset = top + y * moduleSize;\n                for (let x = 0; x < matrixWidth; x++) {\n                    if (image.get(left + x * moduleSize, iOffset)) {\n                        bits.set(x, y);\n                    }\n                }\n            }\n            return bits;\n        }\n        static moduleSize(leftTopBlack, image) {\n            const width = image.getWidth();\n            let x = leftTopBlack[0];\n            const y = leftTopBlack[1];\n            while (x < width && image.get(x, y)) {\n                x++;\n            }\n            if (x === width) {\n                throw new NotFoundException();\n            }\n            const moduleSize = x - leftTopBlack[0];\n            if (moduleSize === 0) {\n                throw new NotFoundException();\n            }\n            return moduleSize;\n        }\n    }\n    DataMatrixReader.NO_POINTS = [];\n\n    /**\n     * @deprecated Moving to @zxing/browser\n     *\n     * QR Code reader to use from browser.\n     */\n    class BrowserDatamatrixCodeReader extends BrowserCodeReader {\n        /**\n         * Creates an instance of BrowserQRCodeReader.\n         * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n         */\n        constructor(timeBetweenScansMillis = 500) {\n            super(new DataMatrixReader(), timeBetweenScansMillis);\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    var ErrorCorrectionLevelValues;\n    (function (ErrorCorrectionLevelValues) {\n        ErrorCorrectionLevelValues[ErrorCorrectionLevelValues[\"L\"] = 0] = \"L\";\n        ErrorCorrectionLevelValues[ErrorCorrectionLevelValues[\"M\"] = 1] = \"M\";\n        ErrorCorrectionLevelValues[ErrorCorrectionLevelValues[\"Q\"] = 2] = \"Q\";\n        ErrorCorrectionLevelValues[ErrorCorrectionLevelValues[\"H\"] = 3] = \"H\";\n    })(ErrorCorrectionLevelValues || (ErrorCorrectionLevelValues = {}));\n    /**\n     * <p>See ISO 18004:2006, 6.5.1. This enum encapsulates the four error correction levels\n     * defined by the QR code standard.</p>\n     *\n     * @author Sean Owen\n     */\n    class ErrorCorrectionLevel {\n        constructor(value, stringValue, bits /*int*/) {\n            this.value = value;\n            this.stringValue = stringValue;\n            this.bits = bits;\n            ErrorCorrectionLevel.FOR_BITS.set(bits, this);\n            ErrorCorrectionLevel.FOR_VALUE.set(value, this);\n        }\n        getValue() {\n            return this.value;\n        }\n        getBits() {\n            return this.bits;\n        }\n        static fromString(s) {\n            switch (s) {\n                case 'L': return ErrorCorrectionLevel.L;\n                case 'M': return ErrorCorrectionLevel.M;\n                case 'Q': return ErrorCorrectionLevel.Q;\n                case 'H': return ErrorCorrectionLevel.H;\n                default: throw new ArgumentException(s + 'not available');\n            }\n        }\n        toString() {\n            return this.stringValue;\n        }\n        equals(o) {\n            if (!(o instanceof ErrorCorrectionLevel)) {\n                return false;\n            }\n            const other = o;\n            return this.value === other.value;\n        }\n        /**\n         * @param bits int containing the two bits encoding a QR Code's error correction level\n         * @return ErrorCorrectionLevel representing the encoded error correction level\n         */\n        static forBits(bits /*int*/) {\n            if (bits < 0 || bits >= ErrorCorrectionLevel.FOR_BITS.size) {\n                throw new IllegalArgumentException();\n            }\n            return ErrorCorrectionLevel.FOR_BITS.get(bits);\n        }\n    }\n    ErrorCorrectionLevel.FOR_BITS = new Map();\n    ErrorCorrectionLevel.FOR_VALUE = new Map();\n    /** L = ~7% correction */\n    ErrorCorrectionLevel.L = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.L, 'L', 0x01);\n    /** M = ~15% correction */\n    ErrorCorrectionLevel.M = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.M, 'M', 0x00);\n    /** Q = ~25% correction */\n    ErrorCorrectionLevel.Q = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.Q, 'Q', 0x03);\n    /** H = ~30% correction */\n    ErrorCorrectionLevel.H = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.H, 'H', 0x02);\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates a QR Code's format information, including the data mask used and\n     * error correction level.</p>\n     *\n     * @author Sean Owen\n     * @see DataMask\n     * @see ErrorCorrectionLevel\n     */\n    class FormatInformation {\n        constructor(formatInfo /*int*/) {\n            // Bits 3,4\n            this.errorCorrectionLevel = ErrorCorrectionLevel.forBits((formatInfo >> 3) & 0x03);\n            // Bottom 3 bits\n            this.dataMask = /*(byte) */ (formatInfo & 0x07);\n        }\n        static numBitsDiffering(a /*int*/, b /*int*/) {\n            return Integer.bitCount(a ^ b);\n        }\n        /**\n         * @param maskedFormatInfo1 format info indicator, with mask still applied\n         * @param maskedFormatInfo2 second copy of same info; both are checked at the same time\n         *  to establish best match\n         * @return information about the format it specifies, or {@code null}\n         *  if doesn't seem to match any known pattern\n         */\n        static decodeFormatInformation(maskedFormatInfo1 /*int*/, maskedFormatInfo2 /*int*/) {\n            const formatInfo = FormatInformation.doDecodeFormatInformation(maskedFormatInfo1, maskedFormatInfo2);\n            if (formatInfo !== null) {\n                return formatInfo;\n            }\n            // Should return null, but, some QR codes apparently\n            // do not mask this info. Try again by actually masking the pattern\n            // first\n            return FormatInformation.doDecodeFormatInformation(maskedFormatInfo1 ^ FormatInformation.FORMAT_INFO_MASK_QR, maskedFormatInfo2 ^ FormatInformation.FORMAT_INFO_MASK_QR);\n        }\n        static doDecodeFormatInformation(maskedFormatInfo1 /*int*/, maskedFormatInfo2 /*int*/) {\n            // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing\n            let bestDifference = Number.MAX_SAFE_INTEGER;\n            let bestFormatInfo = 0;\n            for (const decodeInfo of FormatInformation.FORMAT_INFO_DECODE_LOOKUP) {\n                const targetInfo = decodeInfo[0];\n                if (targetInfo === maskedFormatInfo1 || targetInfo === maskedFormatInfo2) {\n                    // Found an exact match\n                    return new FormatInformation(decodeInfo[1]);\n                }\n                let bitsDifference = FormatInformation.numBitsDiffering(maskedFormatInfo1, targetInfo);\n                if (bitsDifference < bestDifference) {\n                    bestFormatInfo = decodeInfo[1];\n                    bestDifference = bitsDifference;\n                }\n                if (maskedFormatInfo1 !== maskedFormatInfo2) {\n                    // also try the other option\n                    bitsDifference = FormatInformation.numBitsDiffering(maskedFormatInfo2, targetInfo);\n                    if (bitsDifference < bestDifference) {\n                        bestFormatInfo = decodeInfo[1];\n                        bestDifference = bitsDifference;\n                    }\n                }\n            }\n            // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits\n            // differing means we found a match\n            if (bestDifference <= 3) {\n                return new FormatInformation(bestFormatInfo);\n            }\n            return null;\n        }\n        getErrorCorrectionLevel() {\n            return this.errorCorrectionLevel;\n        }\n        getDataMask() {\n            return this.dataMask;\n        }\n        /*@Override*/\n        hashCode() {\n            return (this.errorCorrectionLevel.getBits() << 3) | this.dataMask;\n        }\n        /*@Override*/\n        equals(o) {\n            if (!(o instanceof FormatInformation)) {\n                return false;\n            }\n            const other = o;\n            return this.errorCorrectionLevel === other.errorCorrectionLevel &&\n                this.dataMask === other.dataMask;\n        }\n    }\n    FormatInformation.FORMAT_INFO_MASK_QR = 0x5412;\n    /**\n     * See ISO 18004:2006, Annex C, Table C.1\n     */\n    FormatInformation.FORMAT_INFO_DECODE_LOOKUP = [\n        Int32Array.from([0x5412, 0x00]),\n        Int32Array.from([0x5125, 0x01]),\n        Int32Array.from([0x5E7C, 0x02]),\n        Int32Array.from([0x5B4B, 0x03]),\n        Int32Array.from([0x45F9, 0x04]),\n        Int32Array.from([0x40CE, 0x05]),\n        Int32Array.from([0x4F97, 0x06]),\n        Int32Array.from([0x4AA0, 0x07]),\n        Int32Array.from([0x77C4, 0x08]),\n        Int32Array.from([0x72F3, 0x09]),\n        Int32Array.from([0x7DAA, 0x0A]),\n        Int32Array.from([0x789D, 0x0B]),\n        Int32Array.from([0x662F, 0x0C]),\n        Int32Array.from([0x6318, 0x0D]),\n        Int32Array.from([0x6C41, 0x0E]),\n        Int32Array.from([0x6976, 0x0F]),\n        Int32Array.from([0x1689, 0x10]),\n        Int32Array.from([0x13BE, 0x11]),\n        Int32Array.from([0x1CE7, 0x12]),\n        Int32Array.from([0x19D0, 0x13]),\n        Int32Array.from([0x0762, 0x14]),\n        Int32Array.from([0x0255, 0x15]),\n        Int32Array.from([0x0D0C, 0x16]),\n        Int32Array.from([0x083B, 0x17]),\n        Int32Array.from([0x355F, 0x18]),\n        Int32Array.from([0x3068, 0x19]),\n        Int32Array.from([0x3F31, 0x1A]),\n        Int32Array.from([0x3A06, 0x1B]),\n        Int32Array.from([0x24B4, 0x1C]),\n        Int32Array.from([0x2183, 0x1D]),\n        Int32Array.from([0x2EDA, 0x1E]),\n        Int32Array.from([0x2BED, 0x1F]),\n    ];\n\n    /**\n     * <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will\n     * use blocks of differing sizes within one version, so, this encapsulates the parameters for\n     * each set of blocks. It also holds the number of error-correction codewords per block since it\n     * will be the same across all blocks within one version.</p>\n     */\n    class ECBlocks$1 {\n        constructor(ecCodewordsPerBlock /*int*/, ...ecBlocks) {\n            this.ecCodewordsPerBlock = ecCodewordsPerBlock;\n            this.ecBlocks = ecBlocks;\n        }\n        getECCodewordsPerBlock() {\n            return this.ecCodewordsPerBlock;\n        }\n        getNumBlocks() {\n            let total = 0;\n            const ecBlocks = this.ecBlocks;\n            for (const ecBlock of ecBlocks) {\n                total += ecBlock.getCount();\n            }\n            return total;\n        }\n        getTotalECCodewords() {\n            return this.ecCodewordsPerBlock * this.getNumBlocks();\n        }\n        getECBlocks() {\n            return this.ecBlocks;\n        }\n    }\n\n    /**\n     * <p>Encapsulates the parameters for one error-correction block in one symbol version.\n     * This includes the number of data codewords, and the number of times a block with these\n     * parameters is used consecutively in the QR code version's format.</p>\n     */\n    class ECB$1 {\n        constructor(count /*int*/, dataCodewords /*int*/) {\n            this.count = count;\n            this.dataCodewords = dataCodewords;\n        }\n        getCount() {\n            return this.count;\n        }\n        getDataCodewords() {\n            return this.dataCodewords;\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * See ISO 18004:2006 Annex D\n     *\n     * @author Sean Owen\n     */\n    class Version$1 {\n        constructor(versionNumber /*int*/, alignmentPatternCenters, ...ecBlocks) {\n            this.versionNumber = versionNumber;\n            this.alignmentPatternCenters = alignmentPatternCenters;\n            this.ecBlocks = ecBlocks;\n            let total = 0;\n            const ecCodewords = ecBlocks[0].getECCodewordsPerBlock();\n            const ecbArray = ecBlocks[0].getECBlocks();\n            for (const ecBlock of ecbArray) {\n                total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);\n            }\n            this.totalCodewords = total;\n        }\n        getVersionNumber() {\n            return this.versionNumber;\n        }\n        getAlignmentPatternCenters() {\n            return this.alignmentPatternCenters;\n        }\n        getTotalCodewords() {\n            return this.totalCodewords;\n        }\n        getDimensionForVersion() {\n            return 17 + 4 * this.versionNumber;\n        }\n        getECBlocksForLevel(ecLevel) {\n            return this.ecBlocks[ecLevel.getValue()];\n            // TYPESCRIPTPORT: original was using ordinal, and using the order of levels as defined in ErrorCorrectionLevel enum (LMQH)\n            // I will use the direct value from ErrorCorrectionLevelValues enum which in typescript goes to a number\n        }\n        /**\n         * <p>Deduces version information purely from QR Code dimensions.</p>\n         *\n         * @param dimension dimension in modules\n         * @return Version for a QR Code of that dimension\n         * @throws FormatException if dimension is not 1 mod 4\n         */\n        static getProvisionalVersionForDimension(dimension /*int*/) {\n            if (dimension % 4 !== 1) {\n                throw new FormatException();\n            }\n            try {\n                return this.getVersionForNumber((dimension - 17) / 4);\n            }\n            catch (ignored /*: IllegalArgumentException*/) {\n                throw new FormatException();\n            }\n        }\n        static getVersionForNumber(versionNumber /*int*/) {\n            if (versionNumber < 1 || versionNumber > 40) {\n                throw new IllegalArgumentException();\n            }\n            return Version$1.VERSIONS[versionNumber - 1];\n        }\n        static decodeVersionInformation(versionBits /*int*/) {\n            let bestDifference = Number.MAX_SAFE_INTEGER;\n            let bestVersion = 0;\n            for (let i = 0; i < Version$1.VERSION_DECODE_INFO.length; i++) {\n                const targetVersion = Version$1.VERSION_DECODE_INFO[i];\n                // Do the version info bits match exactly? done.\n                if (targetVersion === versionBits) {\n                    return Version$1.getVersionForNumber(i + 7);\n                }\n                // Otherwise see if this is the closest to a real version info bit string\n                // we have seen so far\n                const bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion);\n                if (bitsDifference < bestDifference) {\n                    bestVersion = i + 7;\n                    bestDifference = bitsDifference;\n                }\n            }\n            // We can tolerate up to 3 bits of error since no two version info codewords will\n            // differ in less than 8 bits.\n            if (bestDifference <= 3) {\n                return Version$1.getVersionForNumber(bestVersion);\n            }\n            // If we didn't find a close enough match, fail\n            return null;\n        }\n        /**\n         * See ISO 18004:2006 Annex E\n         */\n        buildFunctionPattern() {\n            const dimension = this.getDimensionForVersion();\n            const bitMatrix = new BitMatrix(dimension);\n            // Top left finder pattern + separator + format\n            bitMatrix.setRegion(0, 0, 9, 9);\n            // Top right finder pattern + separator + format\n            bitMatrix.setRegion(dimension - 8, 0, 8, 9);\n            // Bottom left finder pattern + separator + format\n            bitMatrix.setRegion(0, dimension - 8, 9, 8);\n            // Alignment patterns\n            const max = this.alignmentPatternCenters.length;\n            for (let x = 0; x < max; x++) {\n                const i = this.alignmentPatternCenters[x] - 2;\n                for (let y = 0; y < max; y++) {\n                    if ((x === 0 && (y === 0 || y === max - 1)) || (x === max - 1 && y === 0)) {\n                        // No alignment patterns near the three finder patterns\n                        continue;\n                    }\n                    bitMatrix.setRegion(this.alignmentPatternCenters[y] - 2, i, 5, 5);\n                }\n            }\n            // Vertical timing pattern\n            bitMatrix.setRegion(6, 9, 1, dimension - 17);\n            // Horizontal timing pattern\n            bitMatrix.setRegion(9, 6, dimension - 17, 1);\n            if (this.versionNumber > 6) {\n                // Version info, top right\n                bitMatrix.setRegion(dimension - 11, 0, 3, 6);\n                // Version info, bottom left\n                bitMatrix.setRegion(0, dimension - 11, 6, 3);\n            }\n            return bitMatrix;\n        }\n        /*@Override*/\n        toString() {\n            return '' + this.versionNumber;\n        }\n    }\n    /**\n       * See ISO 18004:2006 Annex D.\n       * Element i represents the raw version bits that specify version i + 7\n       */\n    Version$1.VERSION_DECODE_INFO = Int32Array.from([\n        0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6,\n        0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78,\n        0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683,\n        0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB,\n        0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250,\n        0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B,\n        0x2542E, 0x26A64, 0x27541, 0x28C69\n    ]);\n    /**\n       * See ISO 18004:2006 6.5.1 Table 9\n       */\n    Version$1.VERSIONS = [\n        new Version$1(1, new Int32Array(0), new ECBlocks$1(7, new ECB$1(1, 19)), new ECBlocks$1(10, new ECB$1(1, 16)), new ECBlocks$1(13, new ECB$1(1, 13)), new ECBlocks$1(17, new ECB$1(1, 9))),\n        new Version$1(2, Int32Array.from([6, 18]), new ECBlocks$1(10, new ECB$1(1, 34)), new ECBlocks$1(16, new ECB$1(1, 28)), new ECBlocks$1(22, new ECB$1(1, 22)), new ECBlocks$1(28, new ECB$1(1, 16))),\n        new Version$1(3, Int32Array.from([6, 22]), new ECBlocks$1(15, new ECB$1(1, 55)), new ECBlocks$1(26, new ECB$1(1, 44)), new ECBlocks$1(18, new ECB$1(2, 17)), new ECBlocks$1(22, new ECB$1(2, 13))),\n        new Version$1(4, Int32Array.from([6, 26]), new ECBlocks$1(20, new ECB$1(1, 80)), new ECBlocks$1(18, new ECB$1(2, 32)), new ECBlocks$1(26, new ECB$1(2, 24)), new ECBlocks$1(16, new ECB$1(4, 9))),\n        new Version$1(5, Int32Array.from([6, 30]), new ECBlocks$1(26, new ECB$1(1, 108)), new ECBlocks$1(24, new ECB$1(2, 43)), new ECBlocks$1(18, new ECB$1(2, 15), new ECB$1(2, 16)), new ECBlocks$1(22, new ECB$1(2, 11), new ECB$1(2, 12))),\n        new Version$1(6, Int32Array.from([6, 34]), new ECBlocks$1(18, new ECB$1(2, 68)), new ECBlocks$1(16, new ECB$1(4, 27)), new ECBlocks$1(24, new ECB$1(4, 19)), new ECBlocks$1(28, new ECB$1(4, 15))),\n        new Version$1(7, Int32Array.from([6, 22, 38]), new ECBlocks$1(20, new ECB$1(2, 78)), new ECBlocks$1(18, new ECB$1(4, 31)), new ECBlocks$1(18, new ECB$1(2, 14), new ECB$1(4, 15)), new ECBlocks$1(26, new ECB$1(4, 13), new ECB$1(1, 14))),\n        new Version$1(8, Int32Array.from([6, 24, 42]), new ECBlocks$1(24, new ECB$1(2, 97)), new ECBlocks$1(22, new ECB$1(2, 38), new ECB$1(2, 39)), new ECBlocks$1(22, new ECB$1(4, 18), new ECB$1(2, 19)), new ECBlocks$1(26, new ECB$1(4, 14), new ECB$1(2, 15))),\n        new Version$1(9, Int32Array.from([6, 26, 46]), new ECBlocks$1(30, new ECB$1(2, 116)), new ECBlocks$1(22, new ECB$1(3, 36), new ECB$1(2, 37)), new ECBlocks$1(20, new ECB$1(4, 16), new ECB$1(4, 17)), new ECBlocks$1(24, new ECB$1(4, 12), new ECB$1(4, 13))),\n        new Version$1(10, Int32Array.from([6, 28, 50]), new ECBlocks$1(18, new ECB$1(2, 68), new ECB$1(2, 69)), new ECBlocks$1(26, new ECB$1(4, 43), new ECB$1(1, 44)), new ECBlocks$1(24, new ECB$1(6, 19), new ECB$1(2, 20)), new ECBlocks$1(28, new ECB$1(6, 15), new ECB$1(2, 16))),\n        new Version$1(11, Int32Array.from([6, 30, 54]), new ECBlocks$1(20, new ECB$1(4, 81)), new ECBlocks$1(30, new ECB$1(1, 50), new ECB$1(4, 51)), new ECBlocks$1(28, new ECB$1(4, 22), new ECB$1(4, 23)), new ECBlocks$1(24, new ECB$1(3, 12), new ECB$1(8, 13))),\n        new Version$1(12, Int32Array.from([6, 32, 58]), new ECBlocks$1(24, new ECB$1(2, 92), new ECB$1(2, 93)), new ECBlocks$1(22, new ECB$1(6, 36), new ECB$1(2, 37)), new ECBlocks$1(26, new ECB$1(4, 20), new ECB$1(6, 21)), new ECBlocks$1(28, new ECB$1(7, 14), new ECB$1(4, 15))),\n        new Version$1(13, Int32Array.from([6, 34, 62]), new ECBlocks$1(26, new ECB$1(4, 107)), new ECBlocks$1(22, new ECB$1(8, 37), new ECB$1(1, 38)), new ECBlocks$1(24, new ECB$1(8, 20), new ECB$1(4, 21)), new ECBlocks$1(22, new ECB$1(12, 11), new ECB$1(4, 12))),\n        new Version$1(14, Int32Array.from([6, 26, 46, 66]), new ECBlocks$1(30, new ECB$1(3, 115), new ECB$1(1, 116)), new ECBlocks$1(24, new ECB$1(4, 40), new ECB$1(5, 41)), new ECBlocks$1(20, new ECB$1(11, 16), new ECB$1(5, 17)), new ECBlocks$1(24, new ECB$1(11, 12), new ECB$1(5, 13))),\n        new Version$1(15, Int32Array.from([6, 26, 48, 70]), new ECBlocks$1(22, new ECB$1(5, 87), new ECB$1(1, 88)), new ECBlocks$1(24, new ECB$1(5, 41), new ECB$1(5, 42)), new ECBlocks$1(30, new ECB$1(5, 24), new ECB$1(7, 25)), new ECBlocks$1(24, new ECB$1(11, 12), new ECB$1(7, 13))),\n        new Version$1(16, Int32Array.from([6, 26, 50, 74]), new ECBlocks$1(24, new ECB$1(5, 98), new ECB$1(1, 99)), new ECBlocks$1(28, new ECB$1(7, 45), new ECB$1(3, 46)), new ECBlocks$1(24, new ECB$1(15, 19), new ECB$1(2, 20)), new ECBlocks$1(30, new ECB$1(3, 15), new ECB$1(13, 16))),\n        new Version$1(17, Int32Array.from([6, 30, 54, 78]), new ECBlocks$1(28, new ECB$1(1, 107), new ECB$1(5, 108)), new ECBlocks$1(28, new ECB$1(10, 46), new ECB$1(1, 47)), new ECBlocks$1(28, new ECB$1(1, 22), new ECB$1(15, 23)), new ECBlocks$1(28, new ECB$1(2, 14), new ECB$1(17, 15))),\n        new Version$1(18, Int32Array.from([6, 30, 56, 82]), new ECBlocks$1(30, new ECB$1(5, 120), new ECB$1(1, 121)), new ECBlocks$1(26, new ECB$1(9, 43), new ECB$1(4, 44)), new ECBlocks$1(28, new ECB$1(17, 22), new ECB$1(1, 23)), new ECBlocks$1(28, new ECB$1(2, 14), new ECB$1(19, 15))),\n        new Version$1(19, Int32Array.from([6, 30, 58, 86]), new ECBlocks$1(28, new ECB$1(3, 113), new ECB$1(4, 114)), new ECBlocks$1(26, new ECB$1(3, 44), new ECB$1(11, 45)), new ECBlocks$1(26, new ECB$1(17, 21), new ECB$1(4, 22)), new ECBlocks$1(26, new ECB$1(9, 13), new ECB$1(16, 14))),\n        new Version$1(20, Int32Array.from([6, 34, 62, 90]), new ECBlocks$1(28, new ECB$1(3, 107), new ECB$1(5, 108)), new ECBlocks$1(26, new ECB$1(3, 41), new ECB$1(13, 42)), new ECBlocks$1(30, new ECB$1(15, 24), new ECB$1(5, 25)), new ECBlocks$1(28, new ECB$1(15, 15), new ECB$1(10, 16))),\n        new Version$1(21, Int32Array.from([6, 28, 50, 72, 94]), new ECBlocks$1(28, new ECB$1(4, 116), new ECB$1(4, 117)), new ECBlocks$1(26, new ECB$1(17, 42)), new ECBlocks$1(28, new ECB$1(17, 22), new ECB$1(6, 23)), new ECBlocks$1(30, new ECB$1(19, 16), new ECB$1(6, 17))),\n        new Version$1(22, Int32Array.from([6, 26, 50, 74, 98]), new ECBlocks$1(28, new ECB$1(2, 111), new ECB$1(7, 112)), new ECBlocks$1(28, new ECB$1(17, 46)), new ECBlocks$1(30, new ECB$1(7, 24), new ECB$1(16, 25)), new ECBlocks$1(24, new ECB$1(34, 13))),\n        new Version$1(23, Int32Array.from([6, 30, 54, 78, 102]), new ECBlocks$1(30, new ECB$1(4, 121), new ECB$1(5, 122)), new ECBlocks$1(28, new ECB$1(4, 47), new ECB$1(14, 48)), new ECBlocks$1(30, new ECB$1(11, 24), new ECB$1(14, 25)), new ECBlocks$1(30, new ECB$1(16, 15), new ECB$1(14, 16))),\n        new Version$1(24, Int32Array.from([6, 28, 54, 80, 106]), new ECBlocks$1(30, new ECB$1(6, 117), new ECB$1(4, 118)), new ECBlocks$1(28, new ECB$1(6, 45), new ECB$1(14, 46)), new ECBlocks$1(30, new ECB$1(11, 24), new ECB$1(16, 25)), new ECBlocks$1(30, new ECB$1(30, 16), new ECB$1(2, 17))),\n        new Version$1(25, Int32Array.from([6, 32, 58, 84, 110]), new ECBlocks$1(26, new ECB$1(8, 106), new ECB$1(4, 107)), new ECBlocks$1(28, new ECB$1(8, 47), new ECB$1(13, 48)), new ECBlocks$1(30, new ECB$1(7, 24), new ECB$1(22, 25)), new ECBlocks$1(30, new ECB$1(22, 15), new ECB$1(13, 16))),\n        new Version$1(26, Int32Array.from([6, 30, 58, 86, 114]), new ECBlocks$1(28, new ECB$1(10, 114), new ECB$1(2, 115)), new ECBlocks$1(28, new ECB$1(19, 46), new ECB$1(4, 47)), new ECBlocks$1(28, new ECB$1(28, 22), new ECB$1(6, 23)), new ECBlocks$1(30, new ECB$1(33, 16), new ECB$1(4, 17))),\n        new Version$1(27, Int32Array.from([6, 34, 62, 90, 118]), new ECBlocks$1(30, new ECB$1(8, 122), new ECB$1(4, 123)), new ECBlocks$1(28, new ECB$1(22, 45), new ECB$1(3, 46)), new ECBlocks$1(30, new ECB$1(8, 23), new ECB$1(26, 24)), new ECBlocks$1(30, new ECB$1(12, 15), new ECB$1(28, 16))),\n        new Version$1(28, Int32Array.from([6, 26, 50, 74, 98, 122]), new ECBlocks$1(30, new ECB$1(3, 117), new ECB$1(10, 118)), new ECBlocks$1(28, new ECB$1(3, 45), new ECB$1(23, 46)), new ECBlocks$1(30, new ECB$1(4, 24), new ECB$1(31, 25)), new ECBlocks$1(30, new ECB$1(11, 15), new ECB$1(31, 16))),\n        new Version$1(29, Int32Array.from([6, 30, 54, 78, 102, 126]), new ECBlocks$1(30, new ECB$1(7, 116), new ECB$1(7, 117)), new ECBlocks$1(28, new ECB$1(21, 45), new ECB$1(7, 46)), new ECBlocks$1(30, new ECB$1(1, 23), new ECB$1(37, 24)), new ECBlocks$1(30, new ECB$1(19, 15), new ECB$1(26, 16))),\n        new Version$1(30, Int32Array.from([6, 26, 52, 78, 104, 130]), new ECBlocks$1(30, new ECB$1(5, 115), new ECB$1(10, 116)), new ECBlocks$1(28, new ECB$1(19, 47), new ECB$1(10, 48)), new ECBlocks$1(30, new ECB$1(15, 24), new ECB$1(25, 25)), new ECBlocks$1(30, new ECB$1(23, 15), new ECB$1(25, 16))),\n        new Version$1(31, Int32Array.from([6, 30, 56, 82, 108, 134]), new ECBlocks$1(30, new ECB$1(13, 115), new ECB$1(3, 116)), new ECBlocks$1(28, new ECB$1(2, 46), new ECB$1(29, 47)), new ECBlocks$1(30, new ECB$1(42, 24), new ECB$1(1, 25)), new ECBlocks$1(30, new ECB$1(23, 15), new ECB$1(28, 16))),\n        new Version$1(32, Int32Array.from([6, 34, 60, 86, 112, 138]), new ECBlocks$1(30, new ECB$1(17, 115)), new ECBlocks$1(28, new ECB$1(10, 46), new ECB$1(23, 47)), new ECBlocks$1(30, new ECB$1(10, 24), new ECB$1(35, 25)), new ECBlocks$1(30, new ECB$1(19, 15), new ECB$1(35, 16))),\n        new Version$1(33, Int32Array.from([6, 30, 58, 86, 114, 142]), new ECBlocks$1(30, new ECB$1(17, 115), new ECB$1(1, 116)), new ECBlocks$1(28, new ECB$1(14, 46), new ECB$1(21, 47)), new ECBlocks$1(30, new ECB$1(29, 24), new ECB$1(19, 25)), new ECBlocks$1(30, new ECB$1(11, 15), new ECB$1(46, 16))),\n        new Version$1(34, Int32Array.from([6, 34, 62, 90, 118, 146]), new ECBlocks$1(30, new ECB$1(13, 115), new ECB$1(6, 116)), new ECBlocks$1(28, new ECB$1(14, 46), new ECB$1(23, 47)), new ECBlocks$1(30, new ECB$1(44, 24), new ECB$1(7, 25)), new ECBlocks$1(30, new ECB$1(59, 16), new ECB$1(1, 17))),\n        new Version$1(35, Int32Array.from([6, 30, 54, 78, 102, 126, 150]), new ECBlocks$1(30, new ECB$1(12, 121), new ECB$1(7, 122)), new ECBlocks$1(28, new ECB$1(12, 47), new ECB$1(26, 48)), new ECBlocks$1(30, new ECB$1(39, 24), new ECB$1(14, 25)), new ECBlocks$1(30, new ECB$1(22, 15), new ECB$1(41, 16))),\n        new Version$1(36, Int32Array.from([6, 24, 50, 76, 102, 128, 154]), new ECBlocks$1(30, new ECB$1(6, 121), new ECB$1(14, 122)), new ECBlocks$1(28, new ECB$1(6, 47), new ECB$1(34, 48)), new ECBlocks$1(30, new ECB$1(46, 24), new ECB$1(10, 25)), new ECBlocks$1(30, new ECB$1(2, 15), new ECB$1(64, 16))),\n        new Version$1(37, Int32Array.from([6, 28, 54, 80, 106, 132, 158]), new ECBlocks$1(30, new ECB$1(17, 122), new ECB$1(4, 123)), new ECBlocks$1(28, new ECB$1(29, 46), new ECB$1(14, 47)), new ECBlocks$1(30, new ECB$1(49, 24), new ECB$1(10, 25)), new ECBlocks$1(30, new ECB$1(24, 15), new ECB$1(46, 16))),\n        new Version$1(38, Int32Array.from([6, 32, 58, 84, 110, 136, 162]), new ECBlocks$1(30, new ECB$1(4, 122), new ECB$1(18, 123)), new ECBlocks$1(28, new ECB$1(13, 46), new ECB$1(32, 47)), new ECBlocks$1(30, new ECB$1(48, 24), new ECB$1(14, 25)), new ECBlocks$1(30, new ECB$1(42, 15), new ECB$1(32, 16))),\n        new Version$1(39, Int32Array.from([6, 26, 54, 82, 110, 138, 166]), new ECBlocks$1(30, new ECB$1(20, 117), new ECB$1(4, 118)), new ECBlocks$1(28, new ECB$1(40, 47), new ECB$1(7, 48)), new ECBlocks$1(30, new ECB$1(43, 24), new ECB$1(22, 25)), new ECBlocks$1(30, new ECB$1(10, 15), new ECB$1(67, 16))),\n        new Version$1(40, Int32Array.from([6, 30, 58, 86, 114, 142, 170]), new ECBlocks$1(30, new ECB$1(19, 118), new ECB$1(6, 119)), new ECBlocks$1(28, new ECB$1(18, 47), new ECB$1(31, 48)), new ECBlocks$1(30, new ECB$1(34, 24), new ECB$1(34, 25)), new ECBlocks$1(30, new ECB$1(20, 15), new ECB$1(61, 16)))\n    ];\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    var DataMaskValues;\n    (function (DataMaskValues) {\n        DataMaskValues[DataMaskValues[\"DATA_MASK_000\"] = 0] = \"DATA_MASK_000\";\n        DataMaskValues[DataMaskValues[\"DATA_MASK_001\"] = 1] = \"DATA_MASK_001\";\n        DataMaskValues[DataMaskValues[\"DATA_MASK_010\"] = 2] = \"DATA_MASK_010\";\n        DataMaskValues[DataMaskValues[\"DATA_MASK_011\"] = 3] = \"DATA_MASK_011\";\n        DataMaskValues[DataMaskValues[\"DATA_MASK_100\"] = 4] = \"DATA_MASK_100\";\n        DataMaskValues[DataMaskValues[\"DATA_MASK_101\"] = 5] = \"DATA_MASK_101\";\n        DataMaskValues[DataMaskValues[\"DATA_MASK_110\"] = 6] = \"DATA_MASK_110\";\n        DataMaskValues[DataMaskValues[\"DATA_MASK_111\"] = 7] = \"DATA_MASK_111\";\n    })(DataMaskValues || (DataMaskValues = {}));\n    /**\n     * <p>Encapsulates data masks for the data bits in a QR code, per ISO 18004:2006 6.8. Implementations\n     * of this class can un-mask a raw BitMatrix. For simplicity, they will unmask the entire BitMatrix,\n     * including areas used for finder patterns, timing patterns, etc. These areas should be unused\n     * after the point they are unmasked anyway.</p>\n     *\n     * <p>Note that the diagram in section 6.8.1 is misleading since it indicates that i is column position\n     * and j is row position. In fact, as the text says, i is row position and j is column position.</p>\n     *\n     * @author Sean Owen\n     */\n    class DataMask {\n        // See ISO 18004:2006 6.8.1\n        constructor(value, isMasked) {\n            this.value = value;\n            this.isMasked = isMasked;\n        }\n        // End of enum constants.\n        /**\n         * <p>Implementations of this method reverse the data masking process applied to a QR Code and\n         * make its bits ready to read.</p>\n         *\n         * @param bits representation of QR Code bits\n         * @param dimension dimension of QR Code, represented by bits, being unmasked\n         */\n        unmaskBitMatrix(bits, dimension /*int*/) {\n            for (let i = 0; i < dimension; i++) {\n                for (let j = 0; j < dimension; j++) {\n                    if (this.isMasked(i, j)) {\n                        bits.flip(j, i);\n                    }\n                }\n            }\n        }\n    }\n    DataMask.values = new Map([\n        /**\n         * 000: mask bits for which (x + y) mod 2 == 0\n         */\n        [DataMaskValues.DATA_MASK_000, new DataMask(DataMaskValues.DATA_MASK_000, (i /*int*/, j /*int*/) => { return ((i + j) & 0x01) === 0; })],\n        /**\n         * 001: mask bits for which x mod 2 == 0\n         */\n        [DataMaskValues.DATA_MASK_001, new DataMask(DataMaskValues.DATA_MASK_001, (i /*int*/, j /*int*/) => { return (i & 0x01) === 0; })],\n        /**\n         * 010: mask bits for which y mod 3 == 0\n         */\n        [DataMaskValues.DATA_MASK_010, new DataMask(DataMaskValues.DATA_MASK_010, (i /*int*/, j /*int*/) => { return j % 3 === 0; })],\n        /**\n         * 011: mask bits for which (x + y) mod 3 == 0\n         */\n        [DataMaskValues.DATA_MASK_011, new DataMask(DataMaskValues.DATA_MASK_011, (i /*int*/, j /*int*/) => { return (i + j) % 3 === 0; })],\n        /**\n         * 100: mask bits for which (x/2 + y/3) mod 2 == 0\n         */\n        [DataMaskValues.DATA_MASK_100, new DataMask(DataMaskValues.DATA_MASK_100, (i /*int*/, j /*int*/) => { return ((Math.floor(i / 2) + Math.floor(j / 3)) & 0x01) === 0; })],\n        /**\n         * 101: mask bits for which xy mod 2 + xy mod 3 == 0\n         * equivalently, such that xy mod 6 == 0\n         */\n        [DataMaskValues.DATA_MASK_101, new DataMask(DataMaskValues.DATA_MASK_101, (i /*int*/, j /*int*/) => { return (i * j) % 6 === 0; })],\n        /**\n         * 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0\n         * equivalently, such that xy mod 6 < 3\n         */\n        [DataMaskValues.DATA_MASK_110, new DataMask(DataMaskValues.DATA_MASK_110, (i /*int*/, j /*int*/) => { return ((i * j) % 6) < 3; })],\n        /**\n         * 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0\n         * equivalently, such that (x + y + xy mod 3) mod 2 == 0\n         */\n        [DataMaskValues.DATA_MASK_111, new DataMask(DataMaskValues.DATA_MASK_111, (i /*int*/, j /*int*/) => { return ((i + j + ((i * j) % 3)) & 0x01) === 0; })],\n    ]);\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * @author Sean Owen\n     */\n    class BitMatrixParser$1 {\n        /**\n         * @param bitMatrix {@link BitMatrix} to parse\n         * @throws FormatException if dimension is not >= 21 and 1 mod 4\n         */\n        constructor(bitMatrix) {\n            const dimension = bitMatrix.getHeight();\n            if (dimension < 21 || (dimension & 0x03) !== 1) {\n                throw new FormatException();\n            }\n            this.bitMatrix = bitMatrix;\n        }\n        /**\n         * <p>Reads format information from one of its two locations within the QR Code.</p>\n         *\n         * @return {@link FormatInformation} encapsulating the QR Code's format info\n         * @throws FormatException if both format information locations cannot be parsed as\n         * the valid encoding of format information\n         */\n        readFormatInformation() {\n            if (this.parsedFormatInfo !== null && this.parsedFormatInfo !== undefined) {\n                return this.parsedFormatInfo;\n            }\n            // Read top-left format info bits\n            let formatInfoBits1 = 0;\n            for (let i = 0; i < 6; i++) {\n                formatInfoBits1 = this.copyBit(i, 8, formatInfoBits1);\n            }\n            // .. and skip a bit in the timing pattern ...\n            formatInfoBits1 = this.copyBit(7, 8, formatInfoBits1);\n            formatInfoBits1 = this.copyBit(8, 8, formatInfoBits1);\n            formatInfoBits1 = this.copyBit(8, 7, formatInfoBits1);\n            // .. and skip a bit in the timing pattern ...\n            for (let j = 5; j >= 0; j--) {\n                formatInfoBits1 = this.copyBit(8, j, formatInfoBits1);\n            }\n            // Read the top-right/bottom-left pattern too\n            const dimension = this.bitMatrix.getHeight();\n            let formatInfoBits2 = 0;\n            const jMin = dimension - 7;\n            for (let j = dimension - 1; j >= jMin; j--) {\n                formatInfoBits2 = this.copyBit(8, j, formatInfoBits2);\n            }\n            for (let i = dimension - 8; i < dimension; i++) {\n                formatInfoBits2 = this.copyBit(i, 8, formatInfoBits2);\n            }\n            this.parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits1, formatInfoBits2);\n            if (this.parsedFormatInfo !== null) {\n                return this.parsedFormatInfo;\n            }\n            throw new FormatException();\n        }\n        /**\n         * <p>Reads version information from one of its two locations within the QR Code.</p>\n         *\n         * @return {@link Version} encapsulating the QR Code's version\n         * @throws FormatException if both version information locations cannot be parsed as\n         * the valid encoding of version information\n         */\n        readVersion() {\n            if (this.parsedVersion !== null && this.parsedVersion !== undefined) {\n                return this.parsedVersion;\n            }\n            const dimension = this.bitMatrix.getHeight();\n            const provisionalVersion = Math.floor((dimension - 17) / 4);\n            if (provisionalVersion <= 6) {\n                return Version$1.getVersionForNumber(provisionalVersion);\n            }\n            // Read top-right version info: 3 wide by 6 tall\n            let versionBits = 0;\n            const ijMin = dimension - 11;\n            for (let j = 5; j >= 0; j--) {\n                for (let i = dimension - 9; i >= ijMin; i--) {\n                    versionBits = this.copyBit(i, j, versionBits);\n                }\n            }\n            let theParsedVersion = Version$1.decodeVersionInformation(versionBits);\n            if (theParsedVersion !== null && theParsedVersion.getDimensionForVersion() === dimension) {\n                this.parsedVersion = theParsedVersion;\n                return theParsedVersion;\n            }\n            // Hmm, failed. Try bottom left: 6 wide by 3 tall\n            versionBits = 0;\n            for (let i = 5; i >= 0; i--) {\n                for (let j = dimension - 9; j >= ijMin; j--) {\n                    versionBits = this.copyBit(i, j, versionBits);\n                }\n            }\n            theParsedVersion = Version$1.decodeVersionInformation(versionBits);\n            if (theParsedVersion !== null && theParsedVersion.getDimensionForVersion() === dimension) {\n                this.parsedVersion = theParsedVersion;\n                return theParsedVersion;\n            }\n            throw new FormatException();\n        }\n        copyBit(i /*int*/, j /*int*/, versionBits /*int*/) {\n            const bit = this.isMirror ? this.bitMatrix.get(j, i) : this.bitMatrix.get(i, j);\n            return bit ? (versionBits << 1) | 0x1 : versionBits << 1;\n        }\n        /**\n         * <p>Reads the bits in the {@link BitMatrix} representing the finder pattern in the\n         * correct order in order to reconstruct the codewords bytes contained within the\n         * QR Code.</p>\n         *\n         * @return bytes encoded within the QR Code\n         * @throws FormatException if the exact number of bytes expected is not read\n         */\n        readCodewords() {\n            const formatInfo = this.readFormatInformation();\n            const version = this.readVersion();\n            // Get the data mask for the format used in this QR Code. This will exclude\n            // some bits from reading as we wind through the bit matrix.\n            const dataMask = DataMask.values.get(formatInfo.getDataMask());\n            const dimension = this.bitMatrix.getHeight();\n            dataMask.unmaskBitMatrix(this.bitMatrix, dimension);\n            const functionPattern = version.buildFunctionPattern();\n            let readingUp = true;\n            const result = new Uint8Array(version.getTotalCodewords());\n            let resultOffset = 0;\n            let currentByte = 0;\n            let bitsRead = 0;\n            // Read columns in pairs, from right to left\n            for (let j = dimension - 1; j > 0; j -= 2) {\n                if (j === 6) {\n                    // Skip whole column with vertical alignment pattern\n                    // saves time and makes the other code proceed more cleanly\n                    j--;\n                }\n                // Read alternatingly from bottom to top then top to bottom\n                for (let count = 0; count < dimension; count++) {\n                    const i = readingUp ? dimension - 1 - count : count;\n                    for (let col = 0; col < 2; col++) {\n                        // Ignore bits covered by the function pattern\n                        if (!functionPattern.get(j - col, i)) {\n                            // Read a bit\n                            bitsRead++;\n                            currentByte <<= 1;\n                            if (this.bitMatrix.get(j - col, i)) {\n                                currentByte |= 1;\n                            }\n                            // If we've made a whole byte, save it off\n                            if (bitsRead === 8) {\n                                result[resultOffset++] = /*(byte) */ currentByte;\n                                bitsRead = 0;\n                                currentByte = 0;\n                            }\n                        }\n                    }\n                }\n                readingUp = !readingUp; // readingUp ^= true; // readingUp = !readingUp; // switch directions\n            }\n            if (resultOffset !== version.getTotalCodewords()) {\n                throw new FormatException();\n            }\n            return result;\n        }\n        /**\n         * Revert the mask removal done while reading the code words. The bit matrix should revert to its original state.\n         */\n        remask() {\n            if (this.parsedFormatInfo === null) {\n                return; // We have no format information, and have no data mask\n            }\n            const dataMask = DataMask.values[this.parsedFormatInfo.getDataMask()];\n            const dimension = this.bitMatrix.getHeight();\n            dataMask.unmaskBitMatrix(this.bitMatrix, dimension);\n        }\n        /**\n         * Prepare the parser for a mirrored operation.\n         * This flag has effect only on the {@link #readFormatInformation()} and the\n         * {@link #readVersion()}. Before proceeding with {@link #readCodewords()} the\n         * {@link #mirror()} method should be called.\n         *\n         * @param mirror Whether to read version and format information mirrored.\n         */\n        setMirror(isMirror) {\n            this.parsedVersion = null;\n            this.parsedFormatInfo = null;\n            this.isMirror = isMirror;\n        }\n        /** Mirror the bit matrix in order to attempt a second reading. */\n        mirror() {\n            const bitMatrix = this.bitMatrix;\n            for (let x = 0, width = bitMatrix.getWidth(); x < width; x++) {\n                for (let y = x + 1, height = bitMatrix.getHeight(); y < height; y++) {\n                    if (bitMatrix.get(x, y) !== bitMatrix.get(y, x)) {\n                        bitMatrix.flip(y, x);\n                        bitMatrix.flip(x, y);\n                    }\n                }\n            }\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates a block of data within a QR Code. QR Codes may split their data into\n     * multiple blocks, each of which is a unit of data and error-correction codewords. Each\n     * is represented by an instance of this class.</p>\n     *\n     * @author Sean Owen\n     */\n    class DataBlock$1 {\n        constructor(numDataCodewords /*int*/, codewords) {\n            this.numDataCodewords = numDataCodewords;\n            this.codewords = codewords;\n        }\n        /**\n         * <p>When QR Codes use multiple data blocks, they are actually interleaved.\n         * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This\n         * method will separate the data into original blocks.</p>\n         *\n         * @param rawCodewords bytes as read directly from the QR Code\n         * @param version version of the QR Code\n         * @param ecLevel error-correction level of the QR Code\n         * @return DataBlocks containing original bytes, \"de-interleaved\" from representation in the\n         *         QR Code\n         */\n        static getDataBlocks(rawCodewords, version, ecLevel) {\n            if (rawCodewords.length !== version.getTotalCodewords()) {\n                throw new IllegalArgumentException();\n            }\n            // Figure out the number and size of data blocks used by this version and\n            // error correction level\n            const ecBlocks = version.getECBlocksForLevel(ecLevel);\n            // First count the total number of data blocks\n            let totalBlocks = 0;\n            const ecBlockArray = ecBlocks.getECBlocks();\n            for (const ecBlock of ecBlockArray) {\n                totalBlocks += ecBlock.getCount();\n            }\n            // Now establish DataBlocks of the appropriate size and number of data codewords\n            const result = new Array(totalBlocks);\n            let numResultBlocks = 0;\n            for (const ecBlock of ecBlockArray) {\n                for (let i = 0; i < ecBlock.getCount(); i++) {\n                    const numDataCodewords = ecBlock.getDataCodewords();\n                    const numBlockCodewords = ecBlocks.getECCodewordsPerBlock() + numDataCodewords;\n                    result[numResultBlocks++] = new DataBlock$1(numDataCodewords, new Uint8Array(numBlockCodewords));\n                }\n            }\n            // All blocks have the same amount of data, except that the last n\n            // (where n may be 0) have 1 more byte. Figure out where these start.\n            const shorterBlocksTotalCodewords = result[0].codewords.length;\n            let longerBlocksStartAt = result.length - 1;\n            // TYPESCRIPTPORT: check length is correct here\n            while (longerBlocksStartAt >= 0) {\n                const numCodewords = result[longerBlocksStartAt].codewords.length;\n                if (numCodewords === shorterBlocksTotalCodewords) {\n                    break;\n                }\n                longerBlocksStartAt--;\n            }\n            longerBlocksStartAt++;\n            const shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.getECCodewordsPerBlock();\n            // The last elements of result may be 1 element longer\n            // first fill out as many elements as all of them have\n            let rawCodewordsOffset = 0;\n            for (let i = 0; i < shorterBlocksNumDataCodewords; i++) {\n                for (let j = 0; j < numResultBlocks; j++) {\n                    result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];\n                }\n            }\n            // Fill out the last data block in the longer ones\n            for (let j = longerBlocksStartAt; j < numResultBlocks; j++) {\n                result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++];\n            }\n            // Now add in error correction blocks\n            const max = result[0].codewords.length;\n            for (let i = shorterBlocksNumDataCodewords; i < max; i++) {\n                for (let j = 0; j < numResultBlocks; j++) {\n                    const iOffset = j < longerBlocksStartAt ? i : i + 1;\n                    result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];\n                }\n            }\n            return result;\n        }\n        getNumDataCodewords() {\n            return this.numDataCodewords;\n        }\n        getCodewords() {\n            return this.codewords;\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    var ModeValues;\n    (function (ModeValues) {\n        ModeValues[ModeValues[\"TERMINATOR\"] = 0] = \"TERMINATOR\";\n        ModeValues[ModeValues[\"NUMERIC\"] = 1] = \"NUMERIC\";\n        ModeValues[ModeValues[\"ALPHANUMERIC\"] = 2] = \"ALPHANUMERIC\";\n        ModeValues[ModeValues[\"STRUCTURED_APPEND\"] = 3] = \"STRUCTURED_APPEND\";\n        ModeValues[ModeValues[\"BYTE\"] = 4] = \"BYTE\";\n        ModeValues[ModeValues[\"ECI\"] = 5] = \"ECI\";\n        ModeValues[ModeValues[\"KANJI\"] = 6] = \"KANJI\";\n        ModeValues[ModeValues[\"FNC1_FIRST_POSITION\"] = 7] = \"FNC1_FIRST_POSITION\";\n        ModeValues[ModeValues[\"FNC1_SECOND_POSITION\"] = 8] = \"FNC1_SECOND_POSITION\";\n        /** See GBT 18284-2000; \"Hanzi\" is a transliteration of this mode name. */\n        ModeValues[ModeValues[\"HANZI\"] = 9] = \"HANZI\";\n    })(ModeValues || (ModeValues = {}));\n    /**\n     * <p>See ISO 18004:2006, 6.4.1, Tables 2 and 3. This enum encapsulates the various modes in which\n     * data can be encoded to bits in the QR code standard.</p>\n     *\n     * @author Sean Owen\n     */\n    class Mode$1 {\n        constructor(value, stringValue, characterCountBitsForVersions, bits /*int*/) {\n            this.value = value;\n            this.stringValue = stringValue;\n            this.characterCountBitsForVersions = characterCountBitsForVersions;\n            this.bits = bits;\n            Mode$1.FOR_BITS.set(bits, this);\n            Mode$1.FOR_VALUE.set(value, this);\n        }\n        /**\n         * @param bits four bits encoding a QR Code data mode\n         * @return Mode encoded by these bits\n         * @throws IllegalArgumentException if bits do not correspond to a known mode\n         */\n        static forBits(bits /*int*/) {\n            const mode = Mode$1.FOR_BITS.get(bits);\n            if (undefined === mode) {\n                throw new IllegalArgumentException();\n            }\n            return mode;\n        }\n        /**\n         * @param version version in question\n         * @return number of bits used, in this QR Code symbol {@link Version}, to encode the\n         *         count of characters that will follow encoded in this Mode\n         */\n        getCharacterCountBits(version) {\n            const versionNumber = version.getVersionNumber();\n            let offset;\n            if (versionNumber <= 9) {\n                offset = 0;\n            }\n            else if (versionNumber <= 26) {\n                offset = 1;\n            }\n            else {\n                offset = 2;\n            }\n            return this.characterCountBitsForVersions[offset];\n        }\n        getValue() {\n            return this.value;\n        }\n        getBits() {\n            return this.bits;\n        }\n        equals(o) {\n            if (!(o instanceof Mode$1)) {\n                return false;\n            }\n            const other = o;\n            return this.value === other.value;\n        }\n        toString() {\n            return this.stringValue;\n        }\n    }\n    Mode$1.FOR_BITS = new Map();\n    Mode$1.FOR_VALUE = new Map();\n    Mode$1.TERMINATOR = new Mode$1(ModeValues.TERMINATOR, 'TERMINATOR', Int32Array.from([0, 0, 0]), 0x00); // Not really a mode...\n    Mode$1.NUMERIC = new Mode$1(ModeValues.NUMERIC, 'NUMERIC', Int32Array.from([10, 12, 14]), 0x01);\n    Mode$1.ALPHANUMERIC = new Mode$1(ModeValues.ALPHANUMERIC, 'ALPHANUMERIC', Int32Array.from([9, 11, 13]), 0x02);\n    Mode$1.STRUCTURED_APPEND = new Mode$1(ModeValues.STRUCTURED_APPEND, 'STRUCTURED_APPEND', Int32Array.from([0, 0, 0]), 0x03); // Not supported\n    Mode$1.BYTE = new Mode$1(ModeValues.BYTE, 'BYTE', Int32Array.from([8, 16, 16]), 0x04);\n    Mode$1.ECI = new Mode$1(ModeValues.ECI, 'ECI', Int32Array.from([0, 0, 0]), 0x07); // character counts don't apply\n    Mode$1.KANJI = new Mode$1(ModeValues.KANJI, 'KANJI', Int32Array.from([8, 10, 12]), 0x08);\n    Mode$1.FNC1_FIRST_POSITION = new Mode$1(ModeValues.FNC1_FIRST_POSITION, 'FNC1_FIRST_POSITION', Int32Array.from([0, 0, 0]), 0x05);\n    Mode$1.FNC1_SECOND_POSITION = new Mode$1(ModeValues.FNC1_SECOND_POSITION, 'FNC1_SECOND_POSITION', Int32Array.from([0, 0, 0]), 0x09);\n    /** See GBT 18284-2000; \"Hanzi\" is a transliteration of this mode name. */\n    Mode$1.HANZI = new Mode$1(ModeValues.HANZI, 'HANZI', Int32Array.from([8, 10, 12]), 0x0D);\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*import java.io.UnsupportedEncodingException;*/\n    /*import java.util.ArrayList;*/\n    /*import java.util.Collection;*/\n    /*import java.util.List;*/\n    /*import java.util.Map;*/\n    /**\n     * <p>QR Codes can encode text as bits in one of several modes, and can use multiple modes\n     * in one QR Code. This class decodes the bits back into text.</p>\n     *\n     * <p>See ISO 18004:2006, 6.4.3 - 6.4.7</p>\n     *\n     * @author Sean Owen\n     */\n    class DecodedBitStreamParser$1 {\n        static decode(bytes, version, ecLevel, hints) {\n            const bits = new BitSource(bytes);\n            let result = new StringBuilder();\n            const byteSegments = new Array(); // 1\n            // TYPESCRIPTPORT: I do not use constructor with size 1 as in original Java means capacity and the array length is checked below\n            let symbolSequence = -1;\n            let parityData = -1;\n            try {\n                let currentCharacterSetECI = null;\n                let fc1InEffect = false;\n                let mode;\n                do {\n                    // While still another segment to read...\n                    if (bits.available() < 4) {\n                        // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here\n                        mode = Mode$1.TERMINATOR;\n                    }\n                    else {\n                        const modeBits = bits.readBits(4);\n                        mode = Mode$1.forBits(modeBits); // mode is encoded by 4 bits\n                    }\n                    switch (mode) {\n                        case Mode$1.TERMINATOR:\n                            break;\n                        case Mode$1.FNC1_FIRST_POSITION:\n                        case Mode$1.FNC1_SECOND_POSITION:\n                            // We do little with FNC1 except alter the parsed result a bit according to the spec\n                            fc1InEffect = true;\n                            break;\n                        case Mode$1.STRUCTURED_APPEND:\n                            if (bits.available() < 16) {\n                                throw new FormatException();\n                            }\n                            // sequence number and parity is added later to the result metadata\n                            // Read next 8 bits (symbol sequence #) and 8 bits (data: parity), then continue\n                            symbolSequence = bits.readBits(8);\n                            parityData = bits.readBits(8);\n                            break;\n                        case Mode$1.ECI:\n                            // Count doesn't apply to ECI\n                            const value = DecodedBitStreamParser$1.parseECIValue(bits);\n                            currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value);\n                            if (currentCharacterSetECI === null) {\n                                throw new FormatException();\n                            }\n                            break;\n                        case Mode$1.HANZI:\n                            // First handle Hanzi mode which does not start with character count\n                            // Chinese mode contains a sub set indicator right after mode indicator\n                            const subset = bits.readBits(4);\n                            const countHanzi = bits.readBits(mode.getCharacterCountBits(version));\n                            if (subset === DecodedBitStreamParser$1.GB2312_SUBSET) {\n                                DecodedBitStreamParser$1.decodeHanziSegment(bits, result, countHanzi);\n                            }\n                            break;\n                        default:\n                            // \"Normal\" QR code modes:\n                            // How many characters will follow, encoded in this mode?\n                            const count = bits.readBits(mode.getCharacterCountBits(version));\n                            switch (mode) {\n                                case Mode$1.NUMERIC:\n                                    DecodedBitStreamParser$1.decodeNumericSegment(bits, result, count);\n                                    break;\n                                case Mode$1.ALPHANUMERIC:\n                                    DecodedBitStreamParser$1.decodeAlphanumericSegment(bits, result, count, fc1InEffect);\n                                    break;\n                                case Mode$1.BYTE:\n                                    DecodedBitStreamParser$1.decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints);\n                                    break;\n                                case Mode$1.KANJI:\n                                    DecodedBitStreamParser$1.decodeKanjiSegment(bits, result, count);\n                                    break;\n                                default:\n                                    throw new FormatException();\n                            }\n                            break;\n                    }\n                } while (mode !== Mode$1.TERMINATOR);\n            }\n            catch (iae /*: IllegalArgumentException*/) {\n                // from readBits() calls\n                throw new FormatException();\n            }\n            return new DecoderResult(bytes, result.toString(), byteSegments.length === 0 ? null : byteSegments, ecLevel === null ? null : ecLevel.toString(), symbolSequence, parityData);\n        }\n        /**\n         * See specification GBT 18284-2000\n         */\n        static decodeHanziSegment(bits, result, count /*int*/) {\n            // Don't crash trying to read more bits than we have available.\n            if (count * 13 > bits.available()) {\n                throw new FormatException();\n            }\n            // Each character will require 2 bytes. Read the characters as 2-byte pairs\n            // and decode as GB2312 afterwards\n            const buffer = new Uint8Array(2 * count);\n            let offset = 0;\n            while (count > 0) {\n                // Each 13 bits encodes a 2-byte character\n                const twoBytes = bits.readBits(13);\n                let assembledTwoBytes = (((twoBytes / 0x060) << 8) & 0xFFFFFFFF) | (twoBytes % 0x060);\n                if (assembledTwoBytes < 0x003BF) {\n                    // In the 0xA1A1 to 0xAAFE range\n                    assembledTwoBytes += 0x0A1A1;\n                }\n                else {\n                    // In the 0xB0A1 to 0xFAFE range\n                    assembledTwoBytes += 0x0A6A1;\n                }\n                buffer[offset] = /*(byte) */ ((assembledTwoBytes >> 8) & 0xFF);\n                buffer[offset + 1] = /*(byte) */ (assembledTwoBytes & 0xFF);\n                offset += 2;\n                count--;\n            }\n            try {\n                result.append(StringEncoding.decode(buffer, StringUtils.GB2312));\n                // TYPESCRIPTPORT: TODO: implement GB2312 decode. StringView from MDN could be a starting point\n            }\n            catch (ignored /*: UnsupportedEncodingException*/) {\n                throw new FormatException(ignored);\n            }\n        }\n        static decodeKanjiSegment(bits, result, count /*int*/) {\n            // Don't crash trying to read more bits than we have available.\n            if (count * 13 > bits.available()) {\n                throw new FormatException();\n            }\n            // Each character will require 2 bytes. Read the characters as 2-byte pairs\n            // and decode as Shift_JIS afterwards\n            const buffer = new Uint8Array(2 * count);\n            let offset = 0;\n            while (count > 0) {\n                // Each 13 bits encodes a 2-byte character\n                const twoBytes = bits.readBits(13);\n                let assembledTwoBytes = (((twoBytes / 0x0C0) << 8) & 0xFFFFFFFF) | (twoBytes % 0x0C0);\n                if (assembledTwoBytes < 0x01F00) {\n                    // In the 0x8140 to 0x9FFC range\n                    assembledTwoBytes += 0x08140;\n                }\n                else {\n                    // In the 0xE040 to 0xEBBF range\n                    assembledTwoBytes += 0x0C140;\n                }\n                buffer[offset] = /*(byte) */ (assembledTwoBytes >> 8);\n                buffer[offset + 1] = /*(byte) */ assembledTwoBytes;\n                offset += 2;\n                count--;\n            }\n            // Shift_JIS may not be supported in some environments:\n            try {\n                result.append(StringEncoding.decode(buffer, StringUtils.SHIFT_JIS));\n                // TYPESCRIPTPORT: TODO: implement SHIFT_JIS decode. StringView from MDN could be a starting point\n            }\n            catch (ignored /*: UnsupportedEncodingException*/) {\n                throw new FormatException(ignored);\n            }\n        }\n        static decodeByteSegment(bits, result, count /*int*/, currentCharacterSetECI, byteSegments, hints) {\n            // Don't crash trying to read more bits than we have available.\n            if (8 * count > bits.available()) {\n                throw new FormatException();\n            }\n            const readBytes = new Uint8Array(count);\n            for (let i = 0; i < count; i++) {\n                readBytes[i] = /*(byte) */ bits.readBits(8);\n            }\n            let encoding;\n            if (currentCharacterSetECI === null) {\n                // The spec isn't clear on this mode; see\n                // section 6.4.5: t does not say which encoding to assuming\n                // upon decoding. I have seen ISO-8859-1 used as well as\n                // Shift_JIS -- without anything like an ECI designator to\n                // give a hint.\n                encoding = StringUtils.guessEncoding(readBytes, hints);\n            }\n            else {\n                encoding = currentCharacterSetECI.getName();\n            }\n            try {\n                result.append(StringEncoding.decode(readBytes, encoding));\n            }\n            catch (ignored /*: UnsupportedEncodingException*/) {\n                throw new FormatException(ignored);\n            }\n            byteSegments.push(readBytes);\n        }\n        static toAlphaNumericChar(value /*int*/) {\n            if (value >= DecodedBitStreamParser$1.ALPHANUMERIC_CHARS.length) {\n                throw new FormatException();\n            }\n            return DecodedBitStreamParser$1.ALPHANUMERIC_CHARS[value];\n        }\n        static decodeAlphanumericSegment(bits, result, count /*int*/, fc1InEffect) {\n            // Read two characters at a time\n            const start = result.length();\n            while (count > 1) {\n                if (bits.available() < 11) {\n                    throw new FormatException();\n                }\n                const nextTwoCharsBits = bits.readBits(11);\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(Math.floor(nextTwoCharsBits / 45)));\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(nextTwoCharsBits % 45));\n                count -= 2;\n            }\n            if (count === 1) {\n                // special case: one character left\n                if (bits.available() < 6) {\n                    throw new FormatException();\n                }\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(bits.readBits(6)));\n            }\n            // See section 6.4.8.1, 6.4.8.2\n            if (fc1InEffect) {\n                // We need to massage the result a bit if in an FNC1 mode:\n                for (let i = start; i < result.length(); i++) {\n                    if (result.charAt(i) === '%') {\n                        if (i < result.length() - 1 && result.charAt(i + 1) === '%') {\n                            // %% is rendered as %\n                            result.deleteCharAt(i + 1);\n                        }\n                        else {\n                            // In alpha mode, % should be converted to FNC1 separator 0x1D\n                            result.setCharAt(i, String.fromCharCode(0x1D));\n                        }\n                    }\n                }\n            }\n        }\n        static decodeNumericSegment(bits, result, count /*int*/) {\n            // Read three digits at a time\n            while (count >= 3) {\n                // Each 10 bits encodes three digits\n                if (bits.available() < 10) {\n                    throw new FormatException();\n                }\n                const threeDigitsBits = bits.readBits(10);\n                if (threeDigitsBits >= 1000) {\n                    throw new FormatException();\n                }\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(Math.floor(threeDigitsBits / 100)));\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(Math.floor(threeDigitsBits / 10) % 10));\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(threeDigitsBits % 10));\n                count -= 3;\n            }\n            if (count === 2) {\n                // Two digits left over to read, encoded in 7 bits\n                if (bits.available() < 7) {\n                    throw new FormatException();\n                }\n                const twoDigitsBits = bits.readBits(7);\n                if (twoDigitsBits >= 100) {\n                    throw new FormatException();\n                }\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(Math.floor(twoDigitsBits / 10)));\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(twoDigitsBits % 10));\n            }\n            else if (count === 1) {\n                // One digit left over to read\n                if (bits.available() < 4) {\n                    throw new FormatException();\n                }\n                const digitBits = bits.readBits(4);\n                if (digitBits >= 10) {\n                    throw new FormatException();\n                }\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(digitBits));\n            }\n        }\n        static parseECIValue(bits) {\n            const firstByte = bits.readBits(8);\n            if ((firstByte & 0x80) === 0) {\n                // just one byte\n                return firstByte & 0x7F;\n            }\n            if ((firstByte & 0xC0) === 0x80) {\n                // two bytes\n                const secondByte = bits.readBits(8);\n                return (((firstByte & 0x3F) << 8) & 0xFFFFFFFF) | secondByte;\n            }\n            if ((firstByte & 0xE0) === 0xC0) {\n                // three bytes\n                const secondThirdBytes = bits.readBits(16);\n                return (((firstByte & 0x1F) << 16) & 0xFFFFFFFF) | secondThirdBytes;\n            }\n            throw new FormatException();\n        }\n    }\n    /**\n     * See ISO 18004:2006, 6.4.4 Table 5\n     */\n    DecodedBitStreamParser$1.ALPHANUMERIC_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:';\n    DecodedBitStreamParser$1.GB2312_SUBSET = 1;\n    // function Uint8ArrayToString(a: Uint8Array): string {\n    //     const CHUNK_SZ = 0x8000;\n    //     const c = new StringBuilder();\n    //     for (let i = 0, length = a.length; i < length; i += CHUNK_SZ) {\n    //         c.append(String.fromCharCode.apply(null, a.subarray(i, i + CHUNK_SZ)));\n    //     }\n    //     return c.toString();\n    // }\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * Meta-data container for QR Code decoding. Instances of this class may be used to convey information back to the\n     * decoding caller. Callers are expected to process this.\n     *\n     * @see com.google.zxing.common.DecoderResult#getOther()\n     */\n    class QRCodeDecoderMetaData {\n        constructor(mirrored) {\n            this.mirrored = mirrored;\n        }\n        /**\n         * @return true if the QR Code was mirrored.\n         */\n        isMirrored() {\n            return this.mirrored;\n        }\n        /**\n         * Apply the result points' order correction due to mirroring.\n         *\n         * @param points Array of points to apply mirror correction to.\n         */\n        applyMirroredCorrection(points) {\n            if (!this.mirrored || points === null || points.length < 3) {\n                return;\n            }\n            const bottomLeft = points[0];\n            points[0] = points[2];\n            points[2] = bottomLeft;\n            // No need to 'fix' top-left and alignment pattern.\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*import java.util.Map;*/\n    /**\n     * <p>The main class which implements QR Code decoding -- as opposed to locating and extracting\n     * the QR Code from an image.</p>\n     *\n     * @author Sean Owen\n     */\n    class Decoder$2 {\n        constructor() {\n            this.rsDecoder = new ReedSolomonDecoder(GenericGF.QR_CODE_FIELD_256);\n        }\n        // public decode(image: boolean[][]): DecoderResult /*throws ChecksumException, FormatException*/ {\n        //   return decode(image, null)\n        // }\n        /**\n         * <p>Convenience method that can decode a QR Code represented as a 2D array of booleans.\n         * \"true\" is taken to mean a black module.</p>\n         *\n         * @param image booleans representing white/black QR Code modules\n         * @param hints decoding hints that should be used to influence decoding\n         * @return text and bytes encoded within the QR Code\n         * @throws FormatException if the QR Code cannot be decoded\n         * @throws ChecksumException if error correction fails\n         */\n        decodeBooleanArray(image, hints) {\n            return this.decodeBitMatrix(BitMatrix.parseFromBooleanArray(image), hints);\n        }\n        // public decodeBitMatrix(bits: BitMatrix): DecoderResult /*throws ChecksumException, FormatException*/ {\n        //   return decode(bits, null)\n        // }\n        /**\n         * <p>Decodes a QR Code represented as a {@link BitMatrix}. A 1 or \"true\" is taken to mean a black module.</p>\n         *\n         * @param bits booleans representing white/black QR Code modules\n         * @param hints decoding hints that should be used to influence decoding\n         * @return text and bytes encoded within the QR Code\n         * @throws FormatException if the QR Code cannot be decoded\n         * @throws ChecksumException if error correction fails\n         */\n        decodeBitMatrix(bits, hints) {\n            // Construct a parser and read version, error-correction level\n            const parser = new BitMatrixParser$1(bits);\n            let ex = null;\n            try {\n                return this.decodeBitMatrixParser(parser, hints);\n            }\n            catch (e /*: FormatException, ChecksumException*/) {\n                ex = e;\n            }\n            try {\n                // Revert the bit matrix\n                parser.remask();\n                // Will be attempting a mirrored reading of the version and format info.\n                parser.setMirror(true);\n                // Preemptively read the version.\n                parser.readVersion();\n                // Preemptively read the format information.\n                parser.readFormatInformation();\n                /*\n                 * Since we're here, this means we have successfully detected some kind\n                 * of version and format information when mirrored. This is a good sign,\n                 * that the QR code may be mirrored, and we should try once more with a\n                 * mirrored content.\n                 */\n                // Prepare for a mirrored reading.\n                parser.mirror();\n                const result = this.decodeBitMatrixParser(parser, hints);\n                // Success! Notify the caller that the code was mirrored.\n                result.setOther(new QRCodeDecoderMetaData(true));\n                return result;\n            }\n            catch (e /*FormatException | ChecksumException*/) {\n                // Throw the exception from the original reading\n                if (ex !== null) {\n                    throw ex;\n                }\n                throw e;\n            }\n        }\n        decodeBitMatrixParser(parser, hints) {\n            const version = parser.readVersion();\n            const ecLevel = parser.readFormatInformation().getErrorCorrectionLevel();\n            // Read codewords\n            const codewords = parser.readCodewords();\n            // Separate into data blocks\n            const dataBlocks = DataBlock$1.getDataBlocks(codewords, version, ecLevel);\n            // Count total number of data bytes\n            let totalBytes = 0;\n            for (const dataBlock of dataBlocks) {\n                totalBytes += dataBlock.getNumDataCodewords();\n            }\n            const resultBytes = new Uint8Array(totalBytes);\n            let resultOffset = 0;\n            // Error-correct and copy data blocks together into a stream of bytes\n            for (const dataBlock of dataBlocks) {\n                const codewordBytes = dataBlock.getCodewords();\n                const numDataCodewords = dataBlock.getNumDataCodewords();\n                this.correctErrors(codewordBytes, numDataCodewords);\n                for (let i = 0; i < numDataCodewords; i++) {\n                    resultBytes[resultOffset++] = codewordBytes[i];\n                }\n            }\n            // Decode the contents of that stream of bytes\n            return DecodedBitStreamParser$1.decode(resultBytes, version, ecLevel, hints);\n        }\n        /**\n         * <p>Given data and error-correction codewords received, possibly corrupted by errors, attempts to\n         * correct the errors in-place using Reed-Solomon error correction.</p>\n         *\n         * @param codewordBytes data and error correction codewords\n         * @param numDataCodewords number of codewords that are data bytes\n         * @throws ChecksumException if error correction fails\n         */\n        correctErrors(codewordBytes, numDataCodewords /*int*/) {\n            // const numCodewords = codewordBytes.length;\n            // First read into an array of ints\n            const codewordsInts = new Int32Array(codewordBytes);\n            // TYPESCRIPTPORT: not realy necessary to transform to ints? could redesign everything to work with unsigned bytes?\n            // const codewordsInts = new Int32Array(numCodewords)\n            // for (let i = 0; i < numCodewords; i++) {\n            //   codewordsInts[i] = codewordBytes[i] & 0xFF\n            // }\n            try {\n                this.rsDecoder.decode(codewordsInts, codewordBytes.length - numDataCodewords);\n            }\n            catch (ignored /*: ReedSolomonException*/) {\n                throw new ChecksumException();\n            }\n            // Copy back into array of bytes -- only need to worry about the bytes that were data\n            // We don't care about errors in the error-correction codewords\n            for (let i = 0; i < numDataCodewords; i++) {\n                codewordBytes[i] = /*(byte) */ codewordsInts[i];\n            }\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates an alignment pattern, which are the smaller square patterns found in\n     * all but the simplest QR Codes.</p>\n     *\n     * @author Sean Owen\n     */\n    class AlignmentPattern extends ResultPoint {\n        constructor(posX /*float*/, posY /*float*/, estimatedModuleSize /*float*/) {\n            super(posX, posY);\n            this.estimatedModuleSize = estimatedModuleSize;\n        }\n        /**\n         * <p>Determines if this alignment pattern \"about equals\" an alignment pattern at the stated\n         * position and size -- meaning, it is at nearly the same center with nearly the same size.</p>\n         */\n        aboutEquals(moduleSize /*float*/, i /*float*/, j /*float*/) {\n            if (Math.abs(i - this.getY()) <= moduleSize && Math.abs(j - this.getX()) <= moduleSize) {\n                const moduleSizeDiff = Math.abs(moduleSize - this.estimatedModuleSize);\n                return moduleSizeDiff <= 1.0 || moduleSizeDiff <= this.estimatedModuleSize;\n            }\n            return false;\n        }\n        /**\n         * Combines this object's current estimate of a finder pattern position and module size\n         * with a new estimate. It returns a new {@code FinderPattern} containing an average of the two.\n         */\n        combineEstimate(i /*float*/, j /*float*/, newModuleSize /*float*/) {\n            const combinedX = (this.getX() + j) / 2.0;\n            const combinedY = (this.getY() + i) / 2.0;\n            const combinedModuleSize = (this.estimatedModuleSize + newModuleSize) / 2.0;\n            return new AlignmentPattern(combinedX, combinedY, combinedModuleSize);\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*import java.util.ArrayList;*/\n    /*import java.util.List;*/\n    /**\n     * <p>This class attempts to find alignment patterns in a QR Code. Alignment patterns look like finder\n     * patterns but are smaller and appear at regular intervals throughout the image.</p>\n     *\n     * <p>At the moment this only looks for the bottom-right alignment pattern.</p>\n     *\n     * <p>This is mostly a simplified copy of {@link FinderPatternFinder}. It is copied,\n     * pasted and stripped down here for maximum performance but does unfortunately duplicate\n     * some code.</p>\n     *\n     * <p>This class is thread-safe but not reentrant. Each thread must allocate its own object.</p>\n     *\n     * @author Sean Owen\n     */\n    class AlignmentPatternFinder {\n        /**\n         * <p>Creates a finder that will look in a portion of the whole image.</p>\n         *\n         * @param image image to search\n         * @param startX left column from which to start searching\n         * @param startY top row from which to start searching\n         * @param width width of region to search\n         * @param height height of region to search\n         * @param moduleSize estimated module size so far\n         */\n        constructor(image, startX /*int*/, startY /*int*/, width /*int*/, height /*int*/, moduleSize /*float*/, resultPointCallback) {\n            this.image = image;\n            this.startX = startX;\n            this.startY = startY;\n            this.width = width;\n            this.height = height;\n            this.moduleSize = moduleSize;\n            this.resultPointCallback = resultPointCallback;\n            this.possibleCenters = []; // new Array<any>(5))\n            // TYPESCRIPTPORT: array initialization without size as the length is checked below\n            this.crossCheckStateCount = new Int32Array(3);\n        }\n        /**\n         * <p>This method attempts to find the bottom-right alignment pattern in the image. It is a bit messy since\n         * it's pretty performance-critical and so is written to be fast foremost.</p>\n         *\n         * @return {@link AlignmentPattern} if found\n         * @throws NotFoundException if not found\n         */\n        find() {\n            const startX = this.startX;\n            const height = this.height;\n            const width = this.width;\n            const maxJ = startX + width;\n            const middleI = this.startY + (height / 2);\n            // We are looking for black/white/black modules in 1:1:1 ratio\n            // this tracks the number of black/white/black modules seen so far\n            const stateCount = new Int32Array(3);\n            const image = this.image;\n            for (let iGen = 0; iGen < height; iGen++) {\n                // Search from middle outwards\n                const i = middleI + ((iGen & 0x01) === 0 ? Math.floor((iGen + 1) / 2) : -Math.floor((iGen + 1) / 2));\n                stateCount[0] = 0;\n                stateCount[1] = 0;\n                stateCount[2] = 0;\n                let j = startX;\n                // Burn off leading white pixels before anything else; if we start in the middle of\n                // a white run, it doesn't make sense to count its length, since we don't know if the\n                // white run continued to the left of the start point\n                while (j < maxJ && !image.get(j, i)) {\n                    j++;\n                }\n                let currentState = 0;\n                while (j < maxJ) {\n                    if (image.get(j, i)) {\n                        // Black pixel\n                        if (currentState === 1) { // Counting black pixels\n                            stateCount[1]++;\n                        }\n                        else { // Counting white pixels\n                            if (currentState === 2) { // A winner?\n                                if (this.foundPatternCross(stateCount)) { // Yes\n                                    const confirmed = this.handlePossibleCenter(stateCount, i, j);\n                                    if (confirmed !== null) {\n                                        return confirmed;\n                                    }\n                                }\n                                stateCount[0] = stateCount[2];\n                                stateCount[1] = 1;\n                                stateCount[2] = 0;\n                                currentState = 1;\n                            }\n                            else {\n                                stateCount[++currentState]++;\n                            }\n                        }\n                    }\n                    else { // White pixel\n                        if (currentState === 1) { // Counting black pixels\n                            currentState++;\n                        }\n                        stateCount[currentState]++;\n                    }\n                    j++;\n                }\n                if (this.foundPatternCross(stateCount)) {\n                    const confirmed = this.handlePossibleCenter(stateCount, i, maxJ);\n                    if (confirmed !== null) {\n                        return confirmed;\n                    }\n                }\n            }\n            // Hmm, nothing we saw was observed and confirmed twice. If we had\n            // any guess at all, return it.\n            if (this.possibleCenters.length !== 0) {\n                return this.possibleCenters[0];\n            }\n            throw new NotFoundException();\n        }\n        /**\n         * Given a count of black/white/black pixels just seen and an end position,\n         * figures the location of the center of this black/white/black run.\n         */\n        static centerFromEnd(stateCount, end /*int*/) {\n            return (end - stateCount[2]) - stateCount[1] / 2.0;\n        }\n        /**\n         * @param stateCount count of black/white/black pixels just read\n         * @return true iff the proportions of the counts is close enough to the 1/1/1 ratios\n         *         used by alignment patterns to be considered a match\n         */\n        foundPatternCross(stateCount) {\n            const moduleSize = this.moduleSize;\n            const maxVariance = moduleSize / 2.0;\n            for (let i = 0; i < 3; i++) {\n                if (Math.abs(moduleSize - stateCount[i]) >= maxVariance) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        /**\n         * <p>After a horizontal scan finds a potential alignment pattern, this method\n         * \"cross-checks\" by scanning down vertically through the center of the possible\n         * alignment pattern to see if the same proportion is detected.</p>\n         *\n         * @param startI row where an alignment pattern was detected\n         * @param centerJ center of the section that appears to cross an alignment pattern\n         * @param maxCount maximum reasonable number of modules that should be\n         * observed in any reading state, based on the results of the horizontal scan\n         * @return vertical center of alignment pattern, or {@link Float#NaN} if not found\n         */\n        crossCheckVertical(startI /*int*/, centerJ /*int*/, maxCount /*int*/, originalStateCountTotal /*int*/) {\n            const image = this.image;\n            const maxI = image.getHeight();\n            const stateCount = this.crossCheckStateCount;\n            stateCount[0] = 0;\n            stateCount[1] = 0;\n            stateCount[2] = 0;\n            // Start counting up from center\n            let i = startI;\n            while (i >= 0 && image.get(centerJ, i) && stateCount[1] <= maxCount) {\n                stateCount[1]++;\n                i--;\n            }\n            // If already too many modules in this state or ran off the edge:\n            if (i < 0 || stateCount[1] > maxCount) {\n                return NaN;\n            }\n            while (i >= 0 && !image.get(centerJ, i) && stateCount[0] <= maxCount) {\n                stateCount[0]++;\n                i--;\n            }\n            if (stateCount[0] > maxCount) {\n                return NaN;\n            }\n            // Now also count down from center\n            i = startI + 1;\n            while (i < maxI && image.get(centerJ, i) && stateCount[1] <= maxCount) {\n                stateCount[1]++;\n                i++;\n            }\n            if (i === maxI || stateCount[1] > maxCount) {\n                return NaN;\n            }\n            while (i < maxI && !image.get(centerJ, i) && stateCount[2] <= maxCount) {\n                stateCount[2]++;\n                i++;\n            }\n            if (stateCount[2] > maxCount) {\n                return NaN;\n            }\n            const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];\n            if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {\n                return NaN;\n            }\n            return this.foundPatternCross(stateCount) ? AlignmentPatternFinder.centerFromEnd(stateCount, i) : NaN;\n        }\n        /**\n         * <p>This is called when a horizontal scan finds a possible alignment pattern. It will\n         * cross check with a vertical scan, and if successful, will see if this pattern had been\n         * found on a previous horizontal scan. If so, we consider it confirmed and conclude we have\n         * found the alignment pattern.</p>\n         *\n         * @param stateCount reading state module counts from horizontal scan\n         * @param i row where alignment pattern may be found\n         * @param j end of possible alignment pattern in row\n         * @return {@link AlignmentPattern} if we have found the same pattern twice, or null if not\n         */\n        handlePossibleCenter(stateCount, i /*int*/, j /*int*/) {\n            const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];\n            const centerJ = AlignmentPatternFinder.centerFromEnd(stateCount, j);\n            const centerI = this.crossCheckVertical(i, /*(int) */ centerJ, 2 * stateCount[1], stateCountTotal);\n            if (!isNaN(centerI)) {\n                const estimatedModuleSize = (stateCount[0] + stateCount[1] + stateCount[2]) / 3.0;\n                for (const center of this.possibleCenters) {\n                    // Look for about the same center and module size:\n                    if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {\n                        return center.combineEstimate(centerI, centerJ, estimatedModuleSize);\n                    }\n                }\n                // Hadn't found this before; save it\n                const point = new AlignmentPattern(centerJ, centerI, estimatedModuleSize);\n                this.possibleCenters.push(point);\n                if (this.resultPointCallback !== null && this.resultPointCallback !== undefined) {\n                    this.resultPointCallback.foundPossibleResultPoint(point);\n                }\n            }\n            return null;\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates a finder pattern, which are the three square patterns found in\n     * the corners of QR Codes. It also encapsulates a count of similar finder patterns,\n     * as a convenience to the finder's bookkeeping.</p>\n     *\n     * @author Sean Owen\n     */\n    class FinderPattern$1 extends ResultPoint {\n        // FinderPattern(posX: number/*float*/, posY: number/*float*/, estimatedModuleSize: number/*float*/) {\n        //   this(posX, posY, estimatedModuleSize, 1)\n        // }\n        constructor(posX /*float*/, posY /*float*/, estimatedModuleSize /*float*/, count /*int*/) {\n            super(posX, posY);\n            this.estimatedModuleSize = estimatedModuleSize;\n            this.count = count;\n            if (undefined === count) {\n                this.count = 1;\n            }\n        }\n        getEstimatedModuleSize() {\n            return this.estimatedModuleSize;\n        }\n        getCount() {\n            return this.count;\n        }\n        /*\n        void incrementCount() {\n          this.count++\n        }\n         */\n        /**\n         * <p>Determines if this finder pattern \"about equals\" a finder pattern at the stated\n         * position and size -- meaning, it is at nearly the same center with nearly the same size.</p>\n         */\n        aboutEquals(moduleSize /*float*/, i /*float*/, j /*float*/) {\n            if (Math.abs(i - this.getY()) <= moduleSize && Math.abs(j - this.getX()) <= moduleSize) {\n                const moduleSizeDiff = Math.abs(moduleSize - this.estimatedModuleSize);\n                return moduleSizeDiff <= 1.0 || moduleSizeDiff <= this.estimatedModuleSize;\n            }\n            return false;\n        }\n        /**\n         * Combines this object's current estimate of a finder pattern position and module size\n         * with a new estimate. It returns a new {@code FinderPattern} containing a weighted average\n         * based on count.\n         */\n        combineEstimate(i /*float*/, j /*float*/, newModuleSize /*float*/) {\n            const combinedCount = this.count + 1;\n            const combinedX = (this.count * this.getX() + j) / combinedCount;\n            const combinedY = (this.count * this.getY() + i) / combinedCount;\n            const combinedModuleSize = (this.count * this.estimatedModuleSize + newModuleSize) / combinedCount;\n            return new FinderPattern$1(combinedX, combinedY, combinedModuleSize, combinedCount);\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates information about finder patterns in an image, including the location of\n     * the three finder patterns, and their estimated module size.</p>\n     *\n     * @author Sean Owen\n     */\n    class FinderPatternInfo {\n        constructor(patternCenters) {\n            this.bottomLeft = patternCenters[0];\n            this.topLeft = patternCenters[1];\n            this.topRight = patternCenters[2];\n        }\n        getBottomLeft() {\n            return this.bottomLeft;\n        }\n        getTopLeft() {\n            return this.topLeft;\n        }\n        getTopRight() {\n            return this.topRight;\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*import java.io.Serializable;*/\n    /*import java.util.ArrayList;*/\n    /*import java.util.Collections;*/\n    /*import java.util.Comparator;*/\n    /*import java.util.List;*/\n    /*import java.util.Map;*/\n    /**\n     * <p>This class attempts to find finder patterns in a QR Code. Finder patterns are the square\n     * markers at three corners of a QR Code.</p>\n     *\n     * <p>This class is thread-safe but not reentrant. Each thread must allocate its own object.\n     *\n     * @author Sean Owen\n     */\n    class FinderPatternFinder {\n        /**\n         * <p>Creates a finder that will search the image for three finder patterns.</p>\n         *\n         * @param image image to search\n         */\n        // public constructor(image: BitMatrix) {\n        //   this(image, null)\n        // }\n        constructor(image, resultPointCallback) {\n            this.image = image;\n            this.resultPointCallback = resultPointCallback;\n            this.possibleCenters = [];\n            this.crossCheckStateCount = new Int32Array(5);\n            this.resultPointCallback = resultPointCallback;\n        }\n        getImage() {\n            return this.image;\n        }\n        getPossibleCenters() {\n            return this.possibleCenters;\n        }\n        find(hints) {\n            const tryHarder = (hints !== null && hints !== undefined) && undefined !== hints.get(DecodeHintType$1.TRY_HARDER);\n            const pureBarcode = (hints !== null && hints !== undefined) && undefined !== hints.get(DecodeHintType$1.PURE_BARCODE);\n            const image = this.image;\n            const maxI = image.getHeight();\n            const maxJ = image.getWidth();\n            // We are looking for black/white/black/white/black modules in\n            // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far\n            // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the\n            // image, and then account for the center being 3 modules in size. This gives the smallest\n            // number of pixels the center could be, so skip this often. When trying harder, look for all\n            // QR versions regardless of how dense they are.\n            let iSkip = Math.floor((3 * maxI) / (4 * FinderPatternFinder.MAX_MODULES));\n            if (iSkip < FinderPatternFinder.MIN_SKIP || tryHarder) {\n                iSkip = FinderPatternFinder.MIN_SKIP;\n            }\n            let done = false;\n            const stateCount = new Int32Array(5);\n            for (let i = iSkip - 1; i < maxI && !done; i += iSkip) {\n                // Get a row of black/white values\n                stateCount[0] = 0;\n                stateCount[1] = 0;\n                stateCount[2] = 0;\n                stateCount[3] = 0;\n                stateCount[4] = 0;\n                let currentState = 0;\n                for (let j = 0; j < maxJ; j++) {\n                    if (image.get(j, i)) {\n                        // Black pixel\n                        if ((currentState & 1) === 1) { // Counting white pixels\n                            currentState++;\n                        }\n                        stateCount[currentState]++;\n                    }\n                    else { // White pixel\n                        if ((currentState & 1) === 0) { // Counting black pixels\n                            if (currentState === 4) { // A winner?\n                                if (FinderPatternFinder.foundPatternCross(stateCount)) { // Yes\n                                    const confirmed = this.handlePossibleCenter(stateCount, i, j, pureBarcode);\n                                    if (confirmed === true) {\n                                        // Start examining every other line. Checking each line turned out to be too\n                                        // expensive and didn't improve performance.\n                                        iSkip = 2;\n                                        if (this.hasSkipped === true) {\n                                            done = this.haveMultiplyConfirmedCenters();\n                                        }\n                                        else {\n                                            const rowSkip = this.findRowSkip();\n                                            if (rowSkip > stateCount[2]) {\n                                                // Skip rows between row of lower confirmed center\n                                                // and top of presumed third confirmed center\n                                                // but back up a bit to get a full chance of detecting\n                                                // it, entire width of center of finder pattern\n                                                // Skip by rowSkip, but back off by stateCount[2] (size of last center\n                                                // of pattern we saw) to be conservative, and also back off by iSkip which\n                                                // is about to be re-added\n                                                i += rowSkip - stateCount[2] - iSkip;\n                                                j = maxJ - 1;\n                                            }\n                                        }\n                                    }\n                                    else {\n                                        stateCount[0] = stateCount[2];\n                                        stateCount[1] = stateCount[3];\n                                        stateCount[2] = stateCount[4];\n                                        stateCount[3] = 1;\n                                        stateCount[4] = 0;\n                                        currentState = 3;\n                                        continue;\n                                    }\n                                    // Clear state to start looking again\n                                    currentState = 0;\n                                    stateCount[0] = 0;\n                                    stateCount[1] = 0;\n                                    stateCount[2] = 0;\n                                    stateCount[3] = 0;\n                                    stateCount[4] = 0;\n                                }\n                                else { // No, shift counts back by two\n                                    stateCount[0] = stateCount[2];\n                                    stateCount[1] = stateCount[3];\n                                    stateCount[2] = stateCount[4];\n                                    stateCount[3] = 1;\n                                    stateCount[4] = 0;\n                                    currentState = 3;\n                                }\n                            }\n                            else {\n                                stateCount[++currentState]++;\n                            }\n                        }\n                        else { // Counting white pixels\n                            stateCount[currentState]++;\n                        }\n                    }\n                }\n                if (FinderPatternFinder.foundPatternCross(stateCount)) {\n                    const confirmed = this.handlePossibleCenter(stateCount, i, maxJ, pureBarcode);\n                    if (confirmed === true) {\n                        iSkip = stateCount[0];\n                        if (this.hasSkipped) {\n                            // Found a third one\n                            done = this.haveMultiplyConfirmedCenters();\n                        }\n                    }\n                }\n            }\n            const patternInfo = this.selectBestPatterns();\n            ResultPoint.orderBestPatterns(patternInfo);\n            return new FinderPatternInfo(patternInfo);\n        }\n        /**\n         * Given a count of black/white/black/white/black pixels just seen and an end position,\n         * figures the location of the center of this run.\n         */\n        static centerFromEnd(stateCount, end /*int*/) {\n            return (end - stateCount[4] - stateCount[3]) - stateCount[2] / 2.0;\n        }\n        /**\n         * @param stateCount count of black/white/black/white/black pixels just read\n         * @return true iff the proportions of the counts is close enough to the 1/1/3/1/1 ratios\n         *         used by finder patterns to be considered a match\n         */\n        static foundPatternCross(stateCount) {\n            let totalModuleSize = 0;\n            for (let i = 0; i < 5; i++) {\n                const count = stateCount[i];\n                if (count === 0) {\n                    return false;\n                }\n                totalModuleSize += count;\n            }\n            if (totalModuleSize < 7) {\n                return false;\n            }\n            const moduleSize = totalModuleSize / 7.0;\n            const maxVariance = moduleSize / 2.0;\n            // Allow less than 50% variance from 1-1-3-1-1 proportions\n            return Math.abs(moduleSize - stateCount[0]) < maxVariance &&\n                Math.abs(moduleSize - stateCount[1]) < maxVariance &&\n                Math.abs(3.0 * moduleSize - stateCount[2]) < 3 * maxVariance &&\n                Math.abs(moduleSize - stateCount[3]) < maxVariance &&\n                Math.abs(moduleSize - stateCount[4]) < maxVariance;\n        }\n        getCrossCheckStateCount() {\n            const crossCheckStateCount = this.crossCheckStateCount;\n            crossCheckStateCount[0] = 0;\n            crossCheckStateCount[1] = 0;\n            crossCheckStateCount[2] = 0;\n            crossCheckStateCount[3] = 0;\n            crossCheckStateCount[4] = 0;\n            return crossCheckStateCount;\n        }\n        /**\n         * After a vertical and horizontal scan finds a potential finder pattern, this method\n         * \"cross-cross-cross-checks\" by scanning down diagonally through the center of the possible\n         * finder pattern to see if the same proportion is detected.\n         *\n         * @param startI row where a finder pattern was detected\n         * @param centerJ center of the section that appears to cross a finder pattern\n         * @param maxCount maximum reasonable number of modules that should be\n         *  observed in any reading state, based on the results of the horizontal scan\n         * @param originalStateCountTotal The original state count total.\n         * @return true if proportions are withing expected limits\n         */\n        crossCheckDiagonal(startI /*int*/, centerJ /*int*/, maxCount /*int*/, originalStateCountTotal /*int*/) {\n            const stateCount = this.getCrossCheckStateCount();\n            // Start counting up, left from center finding black center mass\n            let i = 0;\n            const image = this.image;\n            while (startI >= i && centerJ >= i && image.get(centerJ - i, startI - i)) {\n                stateCount[2]++;\n                i++;\n            }\n            if (startI < i || centerJ < i) {\n                return false;\n            }\n            // Continue up, left finding white space\n            while (startI >= i && centerJ >= i && !image.get(centerJ - i, startI - i) &&\n                stateCount[1] <= maxCount) {\n                stateCount[1]++;\n                i++;\n            }\n            // If already too many modules in this state or ran off the edge:\n            if (startI < i || centerJ < i || stateCount[1] > maxCount) {\n                return false;\n            }\n            // Continue up, left finding black border\n            while (startI >= i && centerJ >= i && image.get(centerJ - i, startI - i) &&\n                stateCount[0] <= maxCount) {\n                stateCount[0]++;\n                i++;\n            }\n            if (stateCount[0] > maxCount) {\n                return false;\n            }\n            const maxI = image.getHeight();\n            const maxJ = image.getWidth();\n            // Now also count down, right from center\n            i = 1;\n            while (startI + i < maxI && centerJ + i < maxJ && image.get(centerJ + i, startI + i)) {\n                stateCount[2]++;\n                i++;\n            }\n            // Ran off the edge?\n            if (startI + i >= maxI || centerJ + i >= maxJ) {\n                return false;\n            }\n            while (startI + i < maxI && centerJ + i < maxJ && !image.get(centerJ + i, startI + i) &&\n                stateCount[3] < maxCount) {\n                stateCount[3]++;\n                i++;\n            }\n            if (startI + i >= maxI || centerJ + i >= maxJ || stateCount[3] >= maxCount) {\n                return false;\n            }\n            while (startI + i < maxI && centerJ + i < maxJ && image.get(centerJ + i, startI + i) &&\n                stateCount[4] < maxCount) {\n                stateCount[4]++;\n                i++;\n            }\n            if (stateCount[4] >= maxCount) {\n                return false;\n            }\n            // If we found a finder-pattern-like section, but its size is more than 100% different than\n            // the original, assume it's a false positive\n            const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4];\n            return Math.abs(stateCountTotal - originalStateCountTotal) < 2 * originalStateCountTotal &&\n                FinderPatternFinder.foundPatternCross(stateCount);\n        }\n        /**\n         * <p>After a horizontal scan finds a potential finder pattern, this method\n         * \"cross-checks\" by scanning down vertically through the center of the possible\n         * finder pattern to see if the same proportion is detected.</p>\n         *\n         * @param startI row where a finder pattern was detected\n         * @param centerJ center of the section that appears to cross a finder pattern\n         * @param maxCount maximum reasonable number of modules that should be\n         * observed in any reading state, based on the results of the horizontal scan\n         * @return vertical center of finder pattern, or {@link Float#NaN} if not found\n         */\n        crossCheckVertical(startI /*int*/, centerJ /*int*/, maxCount /*int*/, originalStateCountTotal /*int*/) {\n            const image = this.image;\n            const maxI = image.getHeight();\n            const stateCount = this.getCrossCheckStateCount();\n            // Start counting up from center\n            let i = startI;\n            while (i >= 0 && image.get(centerJ, i)) {\n                stateCount[2]++;\n                i--;\n            }\n            if (i < 0) {\n                return NaN;\n            }\n            while (i >= 0 && !image.get(centerJ, i) && stateCount[1] <= maxCount) {\n                stateCount[1]++;\n                i--;\n            }\n            // If already too many modules in this state or ran off the edge:\n            if (i < 0 || stateCount[1] > maxCount) {\n                return NaN;\n            }\n            while (i >= 0 && image.get(centerJ, i) && stateCount[0] <= maxCount) {\n                stateCount[0]++;\n                i--;\n            }\n            if (stateCount[0] > maxCount) {\n                return NaN;\n            }\n            // Now also count down from center\n            i = startI + 1;\n            while (i < maxI && image.get(centerJ, i)) {\n                stateCount[2]++;\n                i++;\n            }\n            if (i === maxI) {\n                return NaN;\n            }\n            while (i < maxI && !image.get(centerJ, i) && stateCount[3] < maxCount) {\n                stateCount[3]++;\n                i++;\n            }\n            if (i === maxI || stateCount[3] >= maxCount) {\n                return NaN;\n            }\n            while (i < maxI && image.get(centerJ, i) && stateCount[4] < maxCount) {\n                stateCount[4]++;\n                i++;\n            }\n            if (stateCount[4] >= maxCount) {\n                return NaN;\n            }\n            // If we found a finder-pattern-like section, but its size is more than 40% different than\n            // the original, assume it's a false positive\n            const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +\n                stateCount[4];\n            if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {\n                return NaN;\n            }\n            return FinderPatternFinder.foundPatternCross(stateCount) ? FinderPatternFinder.centerFromEnd(stateCount, i) : NaN;\n        }\n        /**\n         * <p>Like {@link #crossCheckVertical(int, int, int, int)}, and in fact is basically identical,\n         * except it reads horizontally instead of vertically. This is used to cross-cross\n         * check a vertical cross check and locate the real center of the alignment pattern.</p>\n         */\n        crossCheckHorizontal(startJ /*int*/, centerI /*int*/, maxCount /*int*/, originalStateCountTotal /*int*/) {\n            const image = this.image;\n            const maxJ = image.getWidth();\n            const stateCount = this.getCrossCheckStateCount();\n            let j = startJ;\n            while (j >= 0 && image.get(j, centerI)) {\n                stateCount[2]++;\n                j--;\n            }\n            if (j < 0) {\n                return NaN;\n            }\n            while (j >= 0 && !image.get(j, centerI) && stateCount[1] <= maxCount) {\n                stateCount[1]++;\n                j--;\n            }\n            if (j < 0 || stateCount[1] > maxCount) {\n                return NaN;\n            }\n            while (j >= 0 && image.get(j, centerI) && stateCount[0] <= maxCount) {\n                stateCount[0]++;\n                j--;\n            }\n            if (stateCount[0] > maxCount) {\n                return NaN;\n            }\n            j = startJ + 1;\n            while (j < maxJ && image.get(j, centerI)) {\n                stateCount[2]++;\n                j++;\n            }\n            if (j === maxJ) {\n                return NaN;\n            }\n            while (j < maxJ && !image.get(j, centerI) && stateCount[3] < maxCount) {\n                stateCount[3]++;\n                j++;\n            }\n            if (j === maxJ || stateCount[3] >= maxCount) {\n                return NaN;\n            }\n            while (j < maxJ && image.get(j, centerI) && stateCount[4] < maxCount) {\n                stateCount[4]++;\n                j++;\n            }\n            if (stateCount[4] >= maxCount) {\n                return NaN;\n            }\n            // If we found a finder-pattern-like section, but its size is significantly different than\n            // the original, assume it's a false positive\n            const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +\n                stateCount[4];\n            if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) {\n                return NaN;\n            }\n            return FinderPatternFinder.foundPatternCross(stateCount) ? FinderPatternFinder.centerFromEnd(stateCount, j) : NaN;\n        }\n        /**\n         * <p>This is called when a horizontal scan finds a possible alignment pattern. It will\n         * cross check with a vertical scan, and if successful, will, ah, cross-cross-check\n         * with another horizontal scan. This is needed primarily to locate the real horizontal\n         * center of the pattern in cases of extreme skew.\n         * And then we cross-cross-cross check with another diagonal scan.</p>\n         *\n         * <p>If that succeeds the finder pattern location is added to a list that tracks\n         * the number of times each location has been nearly-matched as a finder pattern.\n         * Each additional find is more evidence that the location is in fact a finder\n         * pattern center\n         *\n         * @param stateCount reading state module counts from horizontal scan\n         * @param i row where finder pattern may be found\n         * @param j end of possible finder pattern in row\n         * @param pureBarcode true if in \"pure barcode\" mode\n         * @return true if a finder pattern candidate was found this time\n         */\n        handlePossibleCenter(stateCount, i /*int*/, j /*int*/, pureBarcode) {\n            const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +\n                stateCount[4];\n            let centerJ = FinderPatternFinder.centerFromEnd(stateCount, j);\n            let centerI = this.crossCheckVertical(i, /*(int) */ Math.floor(centerJ), stateCount[2], stateCountTotal);\n            if (!isNaN(centerI)) {\n                // Re-cross check\n                centerJ = this.crossCheckHorizontal(/*(int) */ Math.floor(centerJ), /*(int) */ Math.floor(centerI), stateCount[2], stateCountTotal);\n                if (!isNaN(centerJ) &&\n                    (!pureBarcode || this.crossCheckDiagonal(/*(int) */ Math.floor(centerI), /*(int) */ Math.floor(centerJ), stateCount[2], stateCountTotal))) {\n                    const estimatedModuleSize = stateCountTotal / 7.0;\n                    let found = false;\n                    const possibleCenters = this.possibleCenters;\n                    for (let index = 0, length = possibleCenters.length; index < length; index++) {\n                        const center = possibleCenters[index];\n                        // Look for about the same center and module size:\n                        if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {\n                            possibleCenters[index] = center.combineEstimate(centerI, centerJ, estimatedModuleSize);\n                            found = true;\n                            break;\n                        }\n                    }\n                    if (!found) {\n                        const point = new FinderPattern$1(centerJ, centerI, estimatedModuleSize);\n                        possibleCenters.push(point);\n                        if (this.resultPointCallback !== null && this.resultPointCallback !== undefined) {\n                            this.resultPointCallback.foundPossibleResultPoint(point);\n                        }\n                    }\n                    return true;\n                }\n            }\n            return false;\n        }\n        /**\n         * @return number of rows we could safely skip during scanning, based on the first\n         *         two finder patterns that have been located. In some cases their position will\n         *         allow us to infer that the third pattern must lie below a certain point farther\n         *         down in the image.\n         */\n        findRowSkip() {\n            const max = this.possibleCenters.length;\n            if (max <= 1) {\n                return 0;\n            }\n            let firstConfirmedCenter = null;\n            for (const center of this.possibleCenters) {\n                if (center.getCount() >= FinderPatternFinder.CENTER_QUORUM) {\n                    if (firstConfirmedCenter == null) {\n                        firstConfirmedCenter = center;\n                    }\n                    else {\n                        // We have two confirmed centers\n                        // How far down can we skip before resuming looking for the next\n                        // pattern? In the worst case, only the difference between the\n                        // difference in the x / y coordinates of the two centers.\n                        // This is the case where you find top left last.\n                        this.hasSkipped = true;\n                        return /*(int) */ Math.floor((Math.abs(firstConfirmedCenter.getX() - center.getX()) -\n                            Math.abs(firstConfirmedCenter.getY() - center.getY())) / 2);\n                    }\n                }\n            }\n            return 0;\n        }\n        /**\n         * @return true iff we have found at least 3 finder patterns that have been detected\n         *         at least {@link #CENTER_QUORUM} times each, and, the estimated module size of the\n         *         candidates is \"pretty similar\"\n         */\n        haveMultiplyConfirmedCenters() {\n            let confirmedCount = 0;\n            let totalModuleSize = 0.0;\n            const max = this.possibleCenters.length;\n            for (const pattern of this.possibleCenters) {\n                if (pattern.getCount() >= FinderPatternFinder.CENTER_QUORUM) {\n                    confirmedCount++;\n                    totalModuleSize += pattern.getEstimatedModuleSize();\n                }\n            }\n            if (confirmedCount < 3) {\n                return false;\n            }\n            // OK, we have at least 3 confirmed centers, but, it's possible that one is a \"false positive\"\n            // and that we need to keep looking. We detect this by asking if the estimated module sizes\n            // vary too much. We arbitrarily say that when the total deviation from average exceeds\n            // 5% of the total module size estimates, it's too much.\n            const average = totalModuleSize / max;\n            let totalDeviation = 0.0;\n            for (const pattern of this.possibleCenters) {\n                totalDeviation += Math.abs(pattern.getEstimatedModuleSize() - average);\n            }\n            return totalDeviation <= 0.05 * totalModuleSize;\n        }\n        /**\n         * @return the 3 best {@link FinderPattern}s from our list of candidates. The \"best\" are\n         *         those that have been detected at least {@link #CENTER_QUORUM} times, and whose module\n         *         size differs from the average among those patterns the least\n         * @throws NotFoundException if 3 such finder patterns do not exist\n         */\n        selectBestPatterns() {\n            const startSize = this.possibleCenters.length;\n            if (startSize < 3) {\n                // Couldn't find enough finder patterns\n                throw new NotFoundException();\n            }\n            const possibleCenters = this.possibleCenters;\n            let average;\n            // Filter outlier possibilities whose module size is too different\n            if (startSize > 3) {\n                // But we can only afford to do so if we have at least 4 possibilities to choose from\n                let totalModuleSize = 0.0;\n                let square = 0.0;\n                for (const center of this.possibleCenters) {\n                    const size = center.getEstimatedModuleSize();\n                    totalModuleSize += size;\n                    square += size * size;\n                }\n                average = totalModuleSize / startSize;\n                let stdDev = Math.sqrt(square / startSize - average * average);\n                possibleCenters.sort(\n                /**\n                 * <p>Orders by furthest from average</p>\n                 */\n                // FurthestFromAverageComparator implements Comparator<FinderPattern>\n                (center1, center2) => {\n                    const dA = Math.abs(center2.getEstimatedModuleSize() - average);\n                    const dB = Math.abs(center1.getEstimatedModuleSize() - average);\n                    return dA < dB ? -1 : dA > dB ? 1 : 0;\n                });\n                const limit = Math.max(0.2 * average, stdDev);\n                for (let i = 0; i < possibleCenters.length && possibleCenters.length > 3; i++) {\n                    const pattern = possibleCenters[i];\n                    if (Math.abs(pattern.getEstimatedModuleSize() - average) > limit) {\n                        possibleCenters.splice(i, 1);\n                        i--;\n                    }\n                }\n            }\n            if (possibleCenters.length > 3) {\n                // Throw away all but those first size candidate points we found.\n                let totalModuleSize = 0.0;\n                for (const possibleCenter of possibleCenters) {\n                    totalModuleSize += possibleCenter.getEstimatedModuleSize();\n                }\n                average = totalModuleSize / possibleCenters.length;\n                possibleCenters.sort(\n                /**\n                 * <p>Orders by {@link FinderPattern#getCount()}, descending.</p>\n                 */\n                // CenterComparator implements Comparator<FinderPattern>\n                (center1, center2) => {\n                    if (center2.getCount() === center1.getCount()) {\n                        const dA = Math.abs(center2.getEstimatedModuleSize() - average);\n                        const dB = Math.abs(center1.getEstimatedModuleSize() - average);\n                        return dA < dB ? 1 : dA > dB ? -1 : 0;\n                    }\n                    else {\n                        return center2.getCount() - center1.getCount();\n                    }\n                });\n                possibleCenters.splice(3); // this is not realy necessary as we only return first 3 anyway\n            }\n            return [\n                possibleCenters[0],\n                possibleCenters[1],\n                possibleCenters[2]\n            ];\n        }\n    }\n    FinderPatternFinder.CENTER_QUORUM = 2;\n    FinderPatternFinder.MIN_SKIP = 3; // 1 pixel/module times 3 modules/center\n    FinderPatternFinder.MAX_MODULES = 57; // support up to version 10 for mobile clients\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*import java.util.Map;*/\n    /**\n     * <p>Encapsulates logic that can detect a QR Code in an image, even if the QR Code\n     * is rotated or skewed, or partially obscured.</p>\n     *\n     * @author Sean Owen\n     */\n    class Detector$2 {\n        constructor(image) {\n            this.image = image;\n        }\n        getImage() {\n            return this.image;\n        }\n        getResultPointCallback() {\n            return this.resultPointCallback;\n        }\n        /**\n         * <p>Detects a QR Code in an image.</p>\n         *\n         * @return {@link DetectorResult} encapsulating results of detecting a QR Code\n         * @throws NotFoundException if QR Code cannot be found\n         * @throws FormatException if a QR Code cannot be decoded\n         */\n        // public detect(): DetectorResult /*throws NotFoundException, FormatException*/ {\n        //   return detect(null)\n        // }\n        /**\n         * <p>Detects a QR Code in an image.</p>\n         *\n         * @param hints optional hints to detector\n         * @return {@link DetectorResult} encapsulating results of detecting a QR Code\n         * @throws NotFoundException if QR Code cannot be found\n         * @throws FormatException if a QR Code cannot be decoded\n         */\n        detect(hints) {\n            this.resultPointCallback = (hints === null || hints === undefined) ? null :\n                /*(ResultPointCallback) */ hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n            const finder = new FinderPatternFinder(this.image, this.resultPointCallback);\n            const info = finder.find(hints);\n            return this.processFinderPatternInfo(info);\n        }\n        processFinderPatternInfo(info) {\n            const topLeft = info.getTopLeft();\n            const topRight = info.getTopRight();\n            const bottomLeft = info.getBottomLeft();\n            const moduleSize = this.calculateModuleSize(topLeft, topRight, bottomLeft);\n            if (moduleSize < 1.0) {\n                throw new NotFoundException('No pattern found in proccess finder.');\n            }\n            const dimension = Detector$2.computeDimension(topLeft, topRight, bottomLeft, moduleSize);\n            const provisionalVersion = Version$1.getProvisionalVersionForDimension(dimension);\n            const modulesBetweenFPCenters = provisionalVersion.getDimensionForVersion() - 7;\n            let alignmentPattern = null;\n            // Anything above version 1 has an alignment pattern\n            if (provisionalVersion.getAlignmentPatternCenters().length > 0) {\n                // Guess where a \"bottom right\" finder pattern would have been\n                const bottomRightX = topRight.getX() - topLeft.getX() + bottomLeft.getX();\n                const bottomRightY = topRight.getY() - topLeft.getY() + bottomLeft.getY();\n                // Estimate that alignment pattern is closer by 3 modules\n                // from \"bottom right\" to known top left location\n                const correctionToTopLeft = 1.0 - 3.0 / modulesBetweenFPCenters;\n                const estAlignmentX = /*(int) */ Math.floor(topLeft.getX() + correctionToTopLeft * (bottomRightX - topLeft.getX()));\n                const estAlignmentY = /*(int) */ Math.floor(topLeft.getY() + correctionToTopLeft * (bottomRightY - topLeft.getY()));\n                // Kind of arbitrary -- expand search radius before giving up\n                for (let i = 4; i <= 16; i <<= 1) {\n                    try {\n                        alignmentPattern = this.findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, i);\n                        break;\n                    }\n                    catch (re /*NotFoundException*/) {\n                        if (!(re instanceof NotFoundException)) {\n                            throw re;\n                        }\n                        // try next round\n                    }\n                }\n                // If we didn't find alignment pattern... well try anyway without it\n            }\n            const transform = Detector$2.createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);\n            const bits = Detector$2.sampleGrid(this.image, transform, dimension);\n            let points;\n            if (alignmentPattern === null) {\n                points = [bottomLeft, topLeft, topRight];\n            }\n            else {\n                points = [bottomLeft, topLeft, topRight, alignmentPattern];\n            }\n            return new DetectorResult(bits, points);\n        }\n        static createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension /*int*/) {\n            const dimMinusThree = dimension - 3.5;\n            let bottomRightX; /*float*/\n            let bottomRightY; /*float*/\n            let sourceBottomRightX; /*float*/\n            let sourceBottomRightY; /*float*/\n            if (alignmentPattern !== null) {\n                bottomRightX = alignmentPattern.getX();\n                bottomRightY = alignmentPattern.getY();\n                sourceBottomRightX = dimMinusThree - 3.0;\n                sourceBottomRightY = sourceBottomRightX;\n            }\n            else {\n                // Don't have an alignment pattern, just make up the bottom-right point\n                bottomRightX = (topRight.getX() - topLeft.getX()) + bottomLeft.getX();\n                bottomRightY = (topRight.getY() - topLeft.getY()) + bottomLeft.getY();\n                sourceBottomRightX = dimMinusThree;\n                sourceBottomRightY = dimMinusThree;\n            }\n            return PerspectiveTransform.quadrilateralToQuadrilateral(3.5, 3.5, dimMinusThree, 3.5, sourceBottomRightX, sourceBottomRightY, 3.5, dimMinusThree, topLeft.getX(), topLeft.getY(), topRight.getX(), topRight.getY(), bottomRightX, bottomRightY, bottomLeft.getX(), bottomLeft.getY());\n        }\n        static sampleGrid(image, transform, dimension /*int*/) {\n            const sampler = GridSamplerInstance.getInstance();\n            return sampler.sampleGridWithTransform(image, dimension, dimension, transform);\n        }\n        /**\n         * <p>Computes the dimension (number of modules on a size) of the QR Code based on the position\n         * of the finder patterns and estimated module size.</p>\n         */\n        static computeDimension(topLeft, topRight, bottomLeft, moduleSize /*float*/) {\n            const tltrCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, topRight) / moduleSize);\n            const tlblCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize);\n            let dimension = Math.floor((tltrCentersDimension + tlblCentersDimension) / 2) + 7;\n            switch (dimension & 0x03) { // mod 4\n                case 0:\n                    dimension++;\n                    break;\n                // 1? do nothing\n                case 2:\n                    dimension--;\n                    break;\n                case 3:\n                    throw new NotFoundException('Dimensions could be not found.');\n            }\n            return dimension;\n        }\n        /**\n         * <p>Computes an average estimated module size based on estimated derived from the positions\n         * of the three finder patterns.</p>\n         *\n         * @param topLeft detected top-left finder pattern center\n         * @param topRight detected top-right finder pattern center\n         * @param bottomLeft detected bottom-left finder pattern center\n         * @return estimated module size\n         */\n        calculateModuleSize(topLeft, topRight, bottomLeft) {\n            // Take the average\n            return (this.calculateModuleSizeOneWay(topLeft, topRight) +\n                this.calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0;\n        }\n        /**\n         * <p>Estimates module size based on two finder patterns -- it uses\n         * {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the\n         * width of each, measuring along the axis between their centers.</p>\n         */\n        calculateModuleSizeOneWay(pattern, otherPattern) {\n            const moduleSizeEst1 = this.sizeOfBlackWhiteBlackRunBothWays(/*(int) */ Math.floor(pattern.getX()), \n            /*(int) */ Math.floor(pattern.getY()), \n            /*(int) */ Math.floor(otherPattern.getX()), \n            /*(int) */ Math.floor(otherPattern.getY()));\n            const moduleSizeEst2 = this.sizeOfBlackWhiteBlackRunBothWays(/*(int) */ Math.floor(otherPattern.getX()), \n            /*(int) */ Math.floor(otherPattern.getY()), \n            /*(int) */ Math.floor(pattern.getX()), \n            /*(int) */ Math.floor(pattern.getY()));\n            if (isNaN(moduleSizeEst1)) {\n                return moduleSizeEst2 / 7.0;\n            }\n            if (isNaN(moduleSizeEst2)) {\n                return moduleSizeEst1 / 7.0;\n            }\n            // Average them, and divide by 7 since we've counted the width of 3 black modules,\n            // and 1 white and 1 black module on either side. Ergo, divide sum by 14.\n            return (moduleSizeEst1 + moduleSizeEst2) / 14.0;\n        }\n        /**\n         * See {@link #sizeOfBlackWhiteBlackRun(int, int, int, int)}; computes the total width of\n         * a finder pattern by looking for a black-white-black run from the center in the direction\n         * of another point (another finder pattern center), and in the opposite direction too.\n         */\n        sizeOfBlackWhiteBlackRunBothWays(fromX /*int*/, fromY /*int*/, toX /*int*/, toY /*int*/) {\n            let result = this.sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY);\n            // Now count other way -- don't run off image though of course\n            let scale = 1.0;\n            let otherToX = fromX - (toX - fromX);\n            if (otherToX < 0) {\n                scale = fromX / /*(float) */ (fromX - otherToX);\n                otherToX = 0;\n            }\n            else if (otherToX >= this.image.getWidth()) {\n                scale = (this.image.getWidth() - 1 - fromX) / /*(float) */ (otherToX - fromX);\n                otherToX = this.image.getWidth() - 1;\n            }\n            let otherToY = /*(int) */ Math.floor(fromY - (toY - fromY) * scale);\n            scale = 1.0;\n            if (otherToY < 0) {\n                scale = fromY / /*(float) */ (fromY - otherToY);\n                otherToY = 0;\n            }\n            else if (otherToY >= this.image.getHeight()) {\n                scale = (this.image.getHeight() - 1 - fromY) / /*(float) */ (otherToY - fromY);\n                otherToY = this.image.getHeight() - 1;\n            }\n            otherToX = /*(int) */ Math.floor(fromX + (otherToX - fromX) * scale);\n            result += this.sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY);\n            // Middle pixel is double-counted this way; subtract 1\n            return result - 1.0;\n        }\n        /**\n         * <p>This method traces a line from a point in the image, in the direction towards another point.\n         * It begins in a black region, and keeps going until it finds white, then black, then white again.\n         * It reports the distance from the start to this point.</p>\n         *\n         * <p>This is used when figuring out how wide a finder pattern is, when the finder pattern\n         * may be skewed or rotated.</p>\n         */\n        sizeOfBlackWhiteBlackRun(fromX /*int*/, fromY /*int*/, toX /*int*/, toY /*int*/) {\n            // Mild variant of Bresenham's algorithm\n            // see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm\n            const steep = Math.abs(toY - fromY) > Math.abs(toX - fromX);\n            if (steep) {\n                let temp = fromX;\n                fromX = fromY;\n                fromY = temp;\n                temp = toX;\n                toX = toY;\n                toY = temp;\n            }\n            const dx = Math.abs(toX - fromX);\n            const dy = Math.abs(toY - fromY);\n            let error = -dx / 2;\n            const xstep = fromX < toX ? 1 : -1;\n            const ystep = fromY < toY ? 1 : -1;\n            // In black pixels, looking for white, first or second time.\n            let state = 0;\n            // Loop up until x == toX, but not beyond\n            const xLimit = toX + xstep;\n            for (let x = fromX, y = fromY; x !== xLimit; x += xstep) {\n                const realX = steep ? y : x;\n                const realY = steep ? x : y;\n                // Does current pixel mean we have moved white to black or vice versa?\n                // Scanning black in state 0,2 and white in state 1, so if we find the wrong\n                // color, advance to next state or end if we are in state 2 already\n                if ((state === 1) === this.image.get(realX, realY)) {\n                    if (state === 2) {\n                        return MathUtils.distance(x, y, fromX, fromY);\n                    }\n                    state++;\n                }\n                error += dy;\n                if (error > 0) {\n                    if (y === toY) {\n                        break;\n                    }\n                    y += ystep;\n                    error -= dx;\n                }\n            }\n            // Found black-white-black; give the benefit of the doubt that the next pixel outside the image\n            // is \"white\" so this last point at (toX+xStep,toY) is the right ending. This is really a\n            // small approximation; (toX+xStep,toY+yStep) might be really correct. Ignore this.\n            if (state === 2) {\n                return MathUtils.distance(toX + xstep, toY, fromX, fromY);\n            }\n            // else we didn't find even black-white-black; no estimate is really possible\n            return NaN;\n        }\n        /**\n         * <p>Attempts to locate an alignment pattern in a limited region of the image, which is\n         * guessed to contain it. This method uses {@link AlignmentPattern}.</p>\n         *\n         * @param overallEstModuleSize estimated module size so far\n         * @param estAlignmentX x coordinate of center of area probably containing alignment pattern\n         * @param estAlignmentY y coordinate of above\n         * @param allowanceFactor number of pixels in all directions to search from the center\n         * @return {@link AlignmentPattern} if found, or null otherwise\n         * @throws NotFoundException if an unexpected error occurs during detection\n         */\n        findAlignmentInRegion(overallEstModuleSize /*float*/, estAlignmentX /*int*/, estAlignmentY /*int*/, allowanceFactor /*float*/) {\n            // Look for an alignment pattern (3 modules in size) around where it\n            // should be\n            const allowance = /*(int) */ Math.floor(allowanceFactor * overallEstModuleSize);\n            const alignmentAreaLeftX = Math.max(0, estAlignmentX - allowance);\n            const alignmentAreaRightX = Math.min(this.image.getWidth() - 1, estAlignmentX + allowance);\n            if (alignmentAreaRightX - alignmentAreaLeftX < overallEstModuleSize * 3) {\n                throw new NotFoundException('Alignment top exceeds estimated module size.');\n            }\n            const alignmentAreaTopY = Math.max(0, estAlignmentY - allowance);\n            const alignmentAreaBottomY = Math.min(this.image.getHeight() - 1, estAlignmentY + allowance);\n            if (alignmentAreaBottomY - alignmentAreaTopY < overallEstModuleSize * 3) {\n                throw new NotFoundException('Alignment bottom exceeds estimated module size.');\n            }\n            const alignmentFinder = new AlignmentPatternFinder(this.image, alignmentAreaLeftX, alignmentAreaTopY, alignmentAreaRightX - alignmentAreaLeftX, alignmentAreaBottomY - alignmentAreaTopY, overallEstModuleSize, this.resultPointCallback);\n            return alignmentFinder.find();\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*import java.util.List;*/\n    /*import java.util.Map;*/\n    /**\n     * This implementation can detect and decode QR Codes in an image.\n     *\n     * @author Sean Owen\n     */\n    class QRCodeReader {\n        constructor() {\n            this.decoder = new Decoder$2();\n        }\n        getDecoder() {\n            return this.decoder;\n        }\n        /**\n         * Locates and decodes a QR code in an image.\n         *\n         * @return a representing: string the content encoded by the QR code\n         * @throws NotFoundException if a QR code cannot be found\n         * @throws FormatException if a QR code cannot be decoded\n         * @throws ChecksumException if error correction fails\n         */\n        /*@Override*/\n        // public decode(image: BinaryBitmap): Result /*throws NotFoundException, ChecksumException, FormatException */ {\n        //   return this.decode(image, null)\n        // }\n        /*@Override*/\n        decode(image, hints) {\n            let decoderResult;\n            let points;\n            if (hints !== undefined && hints !== null && undefined !== hints.get(DecodeHintType$1.PURE_BARCODE)) {\n                const bits = QRCodeReader.extractPureBits(image.getBlackMatrix());\n                decoderResult = this.decoder.decodeBitMatrix(bits, hints);\n                points = QRCodeReader.NO_POINTS;\n            }\n            else {\n                const detectorResult = new Detector$2(image.getBlackMatrix()).detect(hints);\n                decoderResult = this.decoder.decodeBitMatrix(detectorResult.getBits(), hints);\n                points = detectorResult.getPoints();\n            }\n            // If the code was mirrored: swap the bottom-left and the top-right points.\n            if (decoderResult.getOther() instanceof QRCodeDecoderMetaData) {\n                decoderResult.getOther().applyMirroredCorrection(points);\n            }\n            const result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), undefined, points, BarcodeFormat$1.QR_CODE, undefined);\n            const byteSegments = decoderResult.getByteSegments();\n            if (byteSegments !== null) {\n                result.putMetadata(ResultMetadataType$1.BYTE_SEGMENTS, byteSegments);\n            }\n            const ecLevel = decoderResult.getECLevel();\n            if (ecLevel !== null) {\n                result.putMetadata(ResultMetadataType$1.ERROR_CORRECTION_LEVEL, ecLevel);\n            }\n            if (decoderResult.hasStructuredAppend()) {\n                result.putMetadata(ResultMetadataType$1.STRUCTURED_APPEND_SEQUENCE, decoderResult.getStructuredAppendSequenceNumber());\n                result.putMetadata(ResultMetadataType$1.STRUCTURED_APPEND_PARITY, decoderResult.getStructuredAppendParity());\n            }\n            return result;\n        }\n        /*@Override*/\n        reset() {\n            // do nothing\n        }\n        /**\n         * This method detects a code in a \"pure\" image -- that is, pure monochrome image\n         * which contains only an unrotated, unskewed, image of a code, with some white border\n         * around it. This is a specialized method that works exceptionally fast in this special\n         * case.\n         *\n         * @see com.google.zxing.datamatrix.DataMatrixReader#extractPureBits(BitMatrix)\n         */\n        static extractPureBits(image) {\n            const leftTopBlack = image.getTopLeftOnBit();\n            const rightBottomBlack = image.getBottomRightOnBit();\n            if (leftTopBlack === null || rightBottomBlack === null) {\n                throw new NotFoundException();\n            }\n            const moduleSize = this.moduleSize(leftTopBlack, image);\n            let top = leftTopBlack[1];\n            let bottom = rightBottomBlack[1];\n            let left = leftTopBlack[0];\n            let right = rightBottomBlack[0];\n            // Sanity check!\n            if (left >= right || top >= bottom) {\n                throw new NotFoundException();\n            }\n            if (bottom - top !== right - left) {\n                // Special case, where bottom-right module wasn't black so we found something else in the last row\n                // Assume it's a square, so use height as the width\n                right = left + (bottom - top);\n                if (right >= image.getWidth()) {\n                    // Abort if that would not make sense -- off image\n                    throw new NotFoundException();\n                }\n            }\n            const matrixWidth = Math.round((right - left + 1) / moduleSize);\n            const matrixHeight = Math.round((bottom - top + 1) / moduleSize);\n            if (matrixWidth <= 0 || matrixHeight <= 0) {\n                throw new NotFoundException();\n            }\n            if (matrixHeight !== matrixWidth) {\n                // Only possibly decode square regions\n                throw new NotFoundException();\n            }\n            // Push in the \"border\" by half the module width so that we start\n            // sampling in the middle of the module. Just in case the image is a\n            // little off, this will help recover.\n            const nudge = /*(int) */ Math.floor(moduleSize / 2.0);\n            top += nudge;\n            left += nudge;\n            // But careful that this does not sample off the edge\n            // \"right\" is the farthest-right valid pixel location -- right+1 is not necessarily\n            // This is positive by how much the inner x loop below would be too large\n            const nudgedTooFarRight = left + /*(int) */ Math.floor((matrixWidth - 1) * moduleSize) - right;\n            if (nudgedTooFarRight > 0) {\n                if (nudgedTooFarRight > nudge) {\n                    // Neither way fits; abort\n                    throw new NotFoundException();\n                }\n                left -= nudgedTooFarRight;\n            }\n            // See logic above\n            const nudgedTooFarDown = top + /*(int) */ Math.floor((matrixHeight - 1) * moduleSize) - bottom;\n            if (nudgedTooFarDown > 0) {\n                if (nudgedTooFarDown > nudge) {\n                    // Neither way fits; abort\n                    throw new NotFoundException();\n                }\n                top -= nudgedTooFarDown;\n            }\n            // Now just read off the bits\n            const bits = new BitMatrix(matrixWidth, matrixHeight);\n            for (let y = 0; y < matrixHeight; y++) {\n                const iOffset = top + /*(int) */ Math.floor(y * moduleSize);\n                for (let x = 0; x < matrixWidth; x++) {\n                    if (image.get(left + /*(int) */ Math.floor(x * moduleSize), iOffset)) {\n                        bits.set(x, y);\n                    }\n                }\n            }\n            return bits;\n        }\n        static moduleSize(leftTopBlack, image) {\n            const height = image.getHeight();\n            const width = image.getWidth();\n            let x = leftTopBlack[0];\n            let y = leftTopBlack[1];\n            let inBlack = true;\n            let transitions = 0;\n            while (x < width && y < height) {\n                if (inBlack !== image.get(x, y)) {\n                    if (++transitions === 5) {\n                        break;\n                    }\n                    inBlack = !inBlack;\n                }\n                x++;\n                y++;\n            }\n            if (x === width || y === height) {\n                throw new NotFoundException();\n            }\n            return (x - leftTopBlack[0]) / 7.0;\n        }\n    }\n    QRCodeReader.NO_POINTS = new Array();\n\n    /*\n    * Copyright 2009 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /**\n     * @author SITA Lab (kevin.osullivan@sita.aero)\n     * @author Guenther Grau\n     */\n    /*public final*/ class PDF417Common {\n        PDF417Common() {\n        }\n        /**\n         * @param moduleBitCount values to sum\n         * @return sum of values\n         * @deprecated call {@link MathUtils#sum(int[])}\n         */\n        // @Deprecated\n        static getBitCountSum(moduleBitCount) {\n            return MathUtils.sum(moduleBitCount);\n        }\n        static toIntArray(list) {\n            if (list == null || !list.length) {\n                return PDF417Common.EMPTY_INT_ARRAY;\n            }\n            const result = new Int32Array(list.length);\n            let i = 0;\n            for (const integer of list) {\n                result[i++] = integer;\n            }\n            return result;\n        }\n        /**\n         * @param symbol encoded symbol to translate to a codeword\n         * @return the codeword corresponding to the symbol.\n         */\n        static getCodeword(symbol /*int*/) {\n            const i = Arrays.binarySearch(PDF417Common.SYMBOL_TABLE, symbol & 0x3FFFF);\n            if (i < 0) {\n                return -1;\n            }\n            return (PDF417Common.CODEWORD_TABLE[i] - 1) % PDF417Common.NUMBER_OF_CODEWORDS;\n        }\n    }\n    PDF417Common.NUMBER_OF_CODEWORDS = 929;\n    // Maximum Codewords (Data + Error).\n    PDF417Common.MAX_CODEWORDS_IN_BARCODE = PDF417Common.NUMBER_OF_CODEWORDS - 1;\n    PDF417Common.MIN_ROWS_IN_BARCODE = 3;\n    PDF417Common.MAX_ROWS_IN_BARCODE = 90;\n    // One left row indication column + max 30 data columns + one right row indicator column\n    // public static /*final*/ MAX_CODEWORDS_IN_ROW: /*int*/ number = 32;\n    PDF417Common.MODULES_IN_CODEWORD = 17;\n    PDF417Common.MODULES_IN_STOP_PATTERN = 18;\n    PDF417Common.BARS_IN_MODULE = 8;\n    PDF417Common.EMPTY_INT_ARRAY = new Int32Array([]);\n    /**\n     * The sorted table of all possible symbols. Extracted from the PDF417\n     * specification. The index of a symbol in this table corresponds to the\n     * index into the codeword table.\n     */\n    PDF417Common.SYMBOL_TABLE = Int32Array.from([\n        0x1025e, 0x1027a, 0x1029e, 0x102bc, 0x102f2, 0x102f4, 0x1032e, 0x1034e, 0x1035c, 0x10396, 0x103a6, 0x103ac,\n        0x10422, 0x10428, 0x10436, 0x10442, 0x10444, 0x10448, 0x10450, 0x1045e, 0x10466, 0x1046c, 0x1047a, 0x10482,\n        0x1049e, 0x104a0, 0x104bc, 0x104c6, 0x104d8, 0x104ee, 0x104f2, 0x104f4, 0x10504, 0x10508, 0x10510, 0x1051e,\n        0x10520, 0x1053c, 0x10540, 0x10578, 0x10586, 0x1058c, 0x10598, 0x105b0, 0x105be, 0x105ce, 0x105dc, 0x105e2,\n        0x105e4, 0x105e8, 0x105f6, 0x1062e, 0x1064e, 0x1065c, 0x1068e, 0x1069c, 0x106b8, 0x106de, 0x106fa, 0x10716,\n        0x10726, 0x1072c, 0x10746, 0x1074c, 0x10758, 0x1076e, 0x10792, 0x10794, 0x107a2, 0x107a4, 0x107a8, 0x107b6,\n        0x10822, 0x10828, 0x10842, 0x10848, 0x10850, 0x1085e, 0x10866, 0x1086c, 0x1087a, 0x10882, 0x10884, 0x10890,\n        0x1089e, 0x108a0, 0x108bc, 0x108c6, 0x108cc, 0x108d8, 0x108ee, 0x108f2, 0x108f4, 0x10902, 0x10908, 0x1091e,\n        0x10920, 0x1093c, 0x10940, 0x10978, 0x10986, 0x10998, 0x109b0, 0x109be, 0x109ce, 0x109dc, 0x109e2, 0x109e4,\n        0x109e8, 0x109f6, 0x10a08, 0x10a10, 0x10a1e, 0x10a20, 0x10a3c, 0x10a40, 0x10a78, 0x10af0, 0x10b06, 0x10b0c,\n        0x10b18, 0x10b30, 0x10b3e, 0x10b60, 0x10b7c, 0x10b8e, 0x10b9c, 0x10bb8, 0x10bc2, 0x10bc4, 0x10bc8, 0x10bd0,\n        0x10bde, 0x10be6, 0x10bec, 0x10c2e, 0x10c4e, 0x10c5c, 0x10c62, 0x10c64, 0x10c68, 0x10c76, 0x10c8e, 0x10c9c,\n        0x10cb8, 0x10cc2, 0x10cc4, 0x10cc8, 0x10cd0, 0x10cde, 0x10ce6, 0x10cec, 0x10cfa, 0x10d0e, 0x10d1c, 0x10d38,\n        0x10d70, 0x10d7e, 0x10d82, 0x10d84, 0x10d88, 0x10d90, 0x10d9e, 0x10da0, 0x10dbc, 0x10dc6, 0x10dcc, 0x10dd8,\n        0x10dee, 0x10df2, 0x10df4, 0x10e16, 0x10e26, 0x10e2c, 0x10e46, 0x10e58, 0x10e6e, 0x10e86, 0x10e8c, 0x10e98,\n        0x10eb0, 0x10ebe, 0x10ece, 0x10edc, 0x10f0a, 0x10f12, 0x10f14, 0x10f22, 0x10f28, 0x10f36, 0x10f42, 0x10f44,\n        0x10f48, 0x10f50, 0x10f5e, 0x10f66, 0x10f6c, 0x10fb2, 0x10fb4, 0x11022, 0x11028, 0x11042, 0x11048, 0x11050,\n        0x1105e, 0x1107a, 0x11082, 0x11084, 0x11090, 0x1109e, 0x110a0, 0x110bc, 0x110c6, 0x110cc, 0x110d8, 0x110ee,\n        0x110f2, 0x110f4, 0x11102, 0x1111e, 0x11120, 0x1113c, 0x11140, 0x11178, 0x11186, 0x11198, 0x111b0, 0x111be,\n        0x111ce, 0x111dc, 0x111e2, 0x111e4, 0x111e8, 0x111f6, 0x11208, 0x1121e, 0x11220, 0x11278, 0x112f0, 0x1130c,\n        0x11330, 0x1133e, 0x11360, 0x1137c, 0x1138e, 0x1139c, 0x113b8, 0x113c2, 0x113c8, 0x113d0, 0x113de, 0x113e6,\n        0x113ec, 0x11408, 0x11410, 0x1141e, 0x11420, 0x1143c, 0x11440, 0x11478, 0x114f0, 0x115e0, 0x1160c, 0x11618,\n        0x11630, 0x1163e, 0x11660, 0x1167c, 0x116c0, 0x116f8, 0x1171c, 0x11738, 0x11770, 0x1177e, 0x11782, 0x11784,\n        0x11788, 0x11790, 0x1179e, 0x117a0, 0x117bc, 0x117c6, 0x117cc, 0x117d8, 0x117ee, 0x1182e, 0x11834, 0x1184e,\n        0x1185c, 0x11862, 0x11864, 0x11868, 0x11876, 0x1188e, 0x1189c, 0x118b8, 0x118c2, 0x118c8, 0x118d0, 0x118de,\n        0x118e6, 0x118ec, 0x118fa, 0x1190e, 0x1191c, 0x11938, 0x11970, 0x1197e, 0x11982, 0x11984, 0x11990, 0x1199e,\n        0x119a0, 0x119bc, 0x119c6, 0x119cc, 0x119d8, 0x119ee, 0x119f2, 0x119f4, 0x11a0e, 0x11a1c, 0x11a38, 0x11a70,\n        0x11a7e, 0x11ae0, 0x11afc, 0x11b08, 0x11b10, 0x11b1e, 0x11b20, 0x11b3c, 0x11b40, 0x11b78, 0x11b8c, 0x11b98,\n        0x11bb0, 0x11bbe, 0x11bce, 0x11bdc, 0x11be2, 0x11be4, 0x11be8, 0x11bf6, 0x11c16, 0x11c26, 0x11c2c, 0x11c46,\n        0x11c4c, 0x11c58, 0x11c6e, 0x11c86, 0x11c98, 0x11cb0, 0x11cbe, 0x11cce, 0x11cdc, 0x11ce2, 0x11ce4, 0x11ce8,\n        0x11cf6, 0x11d06, 0x11d0c, 0x11d18, 0x11d30, 0x11d3e, 0x11d60, 0x11d7c, 0x11d8e, 0x11d9c, 0x11db8, 0x11dc4,\n        0x11dc8, 0x11dd0, 0x11dde, 0x11de6, 0x11dec, 0x11dfa, 0x11e0a, 0x11e12, 0x11e14, 0x11e22, 0x11e24, 0x11e28,\n        0x11e36, 0x11e42, 0x11e44, 0x11e50, 0x11e5e, 0x11e66, 0x11e6c, 0x11e82, 0x11e84, 0x11e88, 0x11e90, 0x11e9e,\n        0x11ea0, 0x11ebc, 0x11ec6, 0x11ecc, 0x11ed8, 0x11eee, 0x11f1a, 0x11f2e, 0x11f32, 0x11f34, 0x11f4e, 0x11f5c,\n        0x11f62, 0x11f64, 0x11f68, 0x11f76, 0x12048, 0x1205e, 0x12082, 0x12084, 0x12090, 0x1209e, 0x120a0, 0x120bc,\n        0x120d8, 0x120f2, 0x120f4, 0x12108, 0x1211e, 0x12120, 0x1213c, 0x12140, 0x12178, 0x12186, 0x12198, 0x121b0,\n        0x121be, 0x121e2, 0x121e4, 0x121e8, 0x121f6, 0x12204, 0x12210, 0x1221e, 0x12220, 0x12278, 0x122f0, 0x12306,\n        0x1230c, 0x12330, 0x1233e, 0x12360, 0x1237c, 0x1238e, 0x1239c, 0x123b8, 0x123c2, 0x123c8, 0x123d0, 0x123e6,\n        0x123ec, 0x1241e, 0x12420, 0x1243c, 0x124f0, 0x125e0, 0x12618, 0x1263e, 0x12660, 0x1267c, 0x126c0, 0x126f8,\n        0x12738, 0x12770, 0x1277e, 0x12782, 0x12784, 0x12790, 0x1279e, 0x127a0, 0x127bc, 0x127c6, 0x127cc, 0x127d8,\n        0x127ee, 0x12820, 0x1283c, 0x12840, 0x12878, 0x128f0, 0x129e0, 0x12bc0, 0x12c18, 0x12c30, 0x12c3e, 0x12c60,\n        0x12c7c, 0x12cc0, 0x12cf8, 0x12df0, 0x12e1c, 0x12e38, 0x12e70, 0x12e7e, 0x12ee0, 0x12efc, 0x12f04, 0x12f08,\n        0x12f10, 0x12f20, 0x12f3c, 0x12f40, 0x12f78, 0x12f86, 0x12f8c, 0x12f98, 0x12fb0, 0x12fbe, 0x12fce, 0x12fdc,\n        0x1302e, 0x1304e, 0x1305c, 0x13062, 0x13068, 0x1308e, 0x1309c, 0x130b8, 0x130c2, 0x130c8, 0x130d0, 0x130de,\n        0x130ec, 0x130fa, 0x1310e, 0x13138, 0x13170, 0x1317e, 0x13182, 0x13184, 0x13190, 0x1319e, 0x131a0, 0x131bc,\n        0x131c6, 0x131cc, 0x131d8, 0x131f2, 0x131f4, 0x1320e, 0x1321c, 0x13270, 0x1327e, 0x132e0, 0x132fc, 0x13308,\n        0x1331e, 0x13320, 0x1333c, 0x13340, 0x13378, 0x13386, 0x13398, 0x133b0, 0x133be, 0x133ce, 0x133dc, 0x133e2,\n        0x133e4, 0x133e8, 0x133f6, 0x1340e, 0x1341c, 0x13438, 0x13470, 0x1347e, 0x134e0, 0x134fc, 0x135c0, 0x135f8,\n        0x13608, 0x13610, 0x1361e, 0x13620, 0x1363c, 0x13640, 0x13678, 0x136f0, 0x1370c, 0x13718, 0x13730, 0x1373e,\n        0x13760, 0x1377c, 0x1379c, 0x137b8, 0x137c2, 0x137c4, 0x137c8, 0x137d0, 0x137de, 0x137e6, 0x137ec, 0x13816,\n        0x13826, 0x1382c, 0x13846, 0x1384c, 0x13858, 0x1386e, 0x13874, 0x13886, 0x13898, 0x138b0, 0x138be, 0x138ce,\n        0x138dc, 0x138e2, 0x138e4, 0x138e8, 0x13906, 0x1390c, 0x13930, 0x1393e, 0x13960, 0x1397c, 0x1398e, 0x1399c,\n        0x139b8, 0x139c8, 0x139d0, 0x139de, 0x139e6, 0x139ec, 0x139fa, 0x13a06, 0x13a0c, 0x13a18, 0x13a30, 0x13a3e,\n        0x13a60, 0x13a7c, 0x13ac0, 0x13af8, 0x13b0e, 0x13b1c, 0x13b38, 0x13b70, 0x13b7e, 0x13b88, 0x13b90, 0x13b9e,\n        0x13ba0, 0x13bbc, 0x13bcc, 0x13bd8, 0x13bee, 0x13bf2, 0x13bf4, 0x13c12, 0x13c14, 0x13c22, 0x13c24, 0x13c28,\n        0x13c36, 0x13c42, 0x13c48, 0x13c50, 0x13c5e, 0x13c66, 0x13c6c, 0x13c82, 0x13c84, 0x13c90, 0x13c9e, 0x13ca0,\n        0x13cbc, 0x13cc6, 0x13ccc, 0x13cd8, 0x13cee, 0x13d02, 0x13d04, 0x13d08, 0x13d10, 0x13d1e, 0x13d20, 0x13d3c,\n        0x13d40, 0x13d78, 0x13d86, 0x13d8c, 0x13d98, 0x13db0, 0x13dbe, 0x13dce, 0x13ddc, 0x13de4, 0x13de8, 0x13df6,\n        0x13e1a, 0x13e2e, 0x13e32, 0x13e34, 0x13e4e, 0x13e5c, 0x13e62, 0x13e64, 0x13e68, 0x13e76, 0x13e8e, 0x13e9c,\n        0x13eb8, 0x13ec2, 0x13ec4, 0x13ec8, 0x13ed0, 0x13ede, 0x13ee6, 0x13eec, 0x13f26, 0x13f2c, 0x13f3a, 0x13f46,\n        0x13f4c, 0x13f58, 0x13f6e, 0x13f72, 0x13f74, 0x14082, 0x1409e, 0x140a0, 0x140bc, 0x14104, 0x14108, 0x14110,\n        0x1411e, 0x14120, 0x1413c, 0x14140, 0x14178, 0x1418c, 0x14198, 0x141b0, 0x141be, 0x141e2, 0x141e4, 0x141e8,\n        0x14208, 0x14210, 0x1421e, 0x14220, 0x1423c, 0x14240, 0x14278, 0x142f0, 0x14306, 0x1430c, 0x14318, 0x14330,\n        0x1433e, 0x14360, 0x1437c, 0x1438e, 0x143c2, 0x143c4, 0x143c8, 0x143d0, 0x143e6, 0x143ec, 0x14408, 0x14410,\n        0x1441e, 0x14420, 0x1443c, 0x14440, 0x14478, 0x144f0, 0x145e0, 0x1460c, 0x14618, 0x14630, 0x1463e, 0x14660,\n        0x1467c, 0x146c0, 0x146f8, 0x1471c, 0x14738, 0x14770, 0x1477e, 0x14782, 0x14784, 0x14788, 0x14790, 0x147a0,\n        0x147bc, 0x147c6, 0x147cc, 0x147d8, 0x147ee, 0x14810, 0x14820, 0x1483c, 0x14840, 0x14878, 0x148f0, 0x149e0,\n        0x14bc0, 0x14c30, 0x14c3e, 0x14c60, 0x14c7c, 0x14cc0, 0x14cf8, 0x14df0, 0x14e38, 0x14e70, 0x14e7e, 0x14ee0,\n        0x14efc, 0x14f04, 0x14f08, 0x14f10, 0x14f1e, 0x14f20, 0x14f3c, 0x14f40, 0x14f78, 0x14f86, 0x14f8c, 0x14f98,\n        0x14fb0, 0x14fce, 0x14fdc, 0x15020, 0x15040, 0x15078, 0x150f0, 0x151e0, 0x153c0, 0x15860, 0x1587c, 0x158c0,\n        0x158f8, 0x159f0, 0x15be0, 0x15c70, 0x15c7e, 0x15ce0, 0x15cfc, 0x15dc0, 0x15df8, 0x15e08, 0x15e10, 0x15e20,\n        0x15e40, 0x15e78, 0x15ef0, 0x15f0c, 0x15f18, 0x15f30, 0x15f60, 0x15f7c, 0x15f8e, 0x15f9c, 0x15fb8, 0x1604e,\n        0x1605c, 0x1608e, 0x1609c, 0x160b8, 0x160c2, 0x160c4, 0x160c8, 0x160de, 0x1610e, 0x1611c, 0x16138, 0x16170,\n        0x1617e, 0x16184, 0x16188, 0x16190, 0x1619e, 0x161a0, 0x161bc, 0x161c6, 0x161cc, 0x161d8, 0x161f2, 0x161f4,\n        0x1620e, 0x1621c, 0x16238, 0x16270, 0x1627e, 0x162e0, 0x162fc, 0x16304, 0x16308, 0x16310, 0x1631e, 0x16320,\n        0x1633c, 0x16340, 0x16378, 0x16386, 0x1638c, 0x16398, 0x163b0, 0x163be, 0x163ce, 0x163dc, 0x163e2, 0x163e4,\n        0x163e8, 0x163f6, 0x1640e, 0x1641c, 0x16438, 0x16470, 0x1647e, 0x164e0, 0x164fc, 0x165c0, 0x165f8, 0x16610,\n        0x1661e, 0x16620, 0x1663c, 0x16640, 0x16678, 0x166f0, 0x16718, 0x16730, 0x1673e, 0x16760, 0x1677c, 0x1678e,\n        0x1679c, 0x167b8, 0x167c2, 0x167c4, 0x167c8, 0x167d0, 0x167de, 0x167e6, 0x167ec, 0x1681c, 0x16838, 0x16870,\n        0x168e0, 0x168fc, 0x169c0, 0x169f8, 0x16bf0, 0x16c10, 0x16c1e, 0x16c20, 0x16c3c, 0x16c40, 0x16c78, 0x16cf0,\n        0x16de0, 0x16e18, 0x16e30, 0x16e3e, 0x16e60, 0x16e7c, 0x16ec0, 0x16ef8, 0x16f1c, 0x16f38, 0x16f70, 0x16f7e,\n        0x16f84, 0x16f88, 0x16f90, 0x16f9e, 0x16fa0, 0x16fbc, 0x16fc6, 0x16fcc, 0x16fd8, 0x17026, 0x1702c, 0x17046,\n        0x1704c, 0x17058, 0x1706e, 0x17086, 0x1708c, 0x17098, 0x170b0, 0x170be, 0x170ce, 0x170dc, 0x170e8, 0x17106,\n        0x1710c, 0x17118, 0x17130, 0x1713e, 0x17160, 0x1717c, 0x1718e, 0x1719c, 0x171b8, 0x171c2, 0x171c4, 0x171c8,\n        0x171d0, 0x171de, 0x171e6, 0x171ec, 0x171fa, 0x17206, 0x1720c, 0x17218, 0x17230, 0x1723e, 0x17260, 0x1727c,\n        0x172c0, 0x172f8, 0x1730e, 0x1731c, 0x17338, 0x17370, 0x1737e, 0x17388, 0x17390, 0x1739e, 0x173a0, 0x173bc,\n        0x173cc, 0x173d8, 0x173ee, 0x173f2, 0x173f4, 0x1740c, 0x17418, 0x17430, 0x1743e, 0x17460, 0x1747c, 0x174c0,\n        0x174f8, 0x175f0, 0x1760e, 0x1761c, 0x17638, 0x17670, 0x1767e, 0x176e0, 0x176fc, 0x17708, 0x17710, 0x1771e,\n        0x17720, 0x1773c, 0x17740, 0x17778, 0x17798, 0x177b0, 0x177be, 0x177dc, 0x177e2, 0x177e4, 0x177e8, 0x17822,\n        0x17824, 0x17828, 0x17836, 0x17842, 0x17844, 0x17848, 0x17850, 0x1785e, 0x17866, 0x1786c, 0x17882, 0x17884,\n        0x17888, 0x17890, 0x1789e, 0x178a0, 0x178bc, 0x178c6, 0x178cc, 0x178d8, 0x178ee, 0x178f2, 0x178f4, 0x17902,\n        0x17904, 0x17908, 0x17910, 0x1791e, 0x17920, 0x1793c, 0x17940, 0x17978, 0x17986, 0x1798c, 0x17998, 0x179b0,\n        0x179be, 0x179ce, 0x179dc, 0x179e2, 0x179e4, 0x179e8, 0x179f6, 0x17a04, 0x17a08, 0x17a10, 0x17a1e, 0x17a20,\n        0x17a3c, 0x17a40, 0x17a78, 0x17af0, 0x17b06, 0x17b0c, 0x17b18, 0x17b30, 0x17b3e, 0x17b60, 0x17b7c, 0x17b8e,\n        0x17b9c, 0x17bb8, 0x17bc4, 0x17bc8, 0x17bd0, 0x17bde, 0x17be6, 0x17bec, 0x17c2e, 0x17c32, 0x17c34, 0x17c4e,\n        0x17c5c, 0x17c62, 0x17c64, 0x17c68, 0x17c76, 0x17c8e, 0x17c9c, 0x17cb8, 0x17cc2, 0x17cc4, 0x17cc8, 0x17cd0,\n        0x17cde, 0x17ce6, 0x17cec, 0x17d0e, 0x17d1c, 0x17d38, 0x17d70, 0x17d82, 0x17d84, 0x17d88, 0x17d90, 0x17d9e,\n        0x17da0, 0x17dbc, 0x17dc6, 0x17dcc, 0x17dd8, 0x17dee, 0x17e26, 0x17e2c, 0x17e3a, 0x17e46, 0x17e4c, 0x17e58,\n        0x17e6e, 0x17e72, 0x17e74, 0x17e86, 0x17e8c, 0x17e98, 0x17eb0, 0x17ece, 0x17edc, 0x17ee2, 0x17ee4, 0x17ee8,\n        0x17ef6, 0x1813a, 0x18172, 0x18174, 0x18216, 0x18226, 0x1823a, 0x1824c, 0x18258, 0x1826e, 0x18272, 0x18274,\n        0x18298, 0x182be, 0x182e2, 0x182e4, 0x182e8, 0x182f6, 0x1835e, 0x1837a, 0x183ae, 0x183d6, 0x18416, 0x18426,\n        0x1842c, 0x1843a, 0x18446, 0x18458, 0x1846e, 0x18472, 0x18474, 0x18486, 0x184b0, 0x184be, 0x184ce, 0x184dc,\n        0x184e2, 0x184e4, 0x184e8, 0x184f6, 0x18506, 0x1850c, 0x18518, 0x18530, 0x1853e, 0x18560, 0x1857c, 0x1858e,\n        0x1859c, 0x185b8, 0x185c2, 0x185c4, 0x185c8, 0x185d0, 0x185de, 0x185e6, 0x185ec, 0x185fa, 0x18612, 0x18614,\n        0x18622, 0x18628, 0x18636, 0x18642, 0x18650, 0x1865e, 0x1867a, 0x18682, 0x18684, 0x18688, 0x18690, 0x1869e,\n        0x186a0, 0x186bc, 0x186c6, 0x186cc, 0x186d8, 0x186ee, 0x186f2, 0x186f4, 0x1872e, 0x1874e, 0x1875c, 0x18796,\n        0x187a6, 0x187ac, 0x187d2, 0x187d4, 0x18826, 0x1882c, 0x1883a, 0x18846, 0x1884c, 0x18858, 0x1886e, 0x18872,\n        0x18874, 0x18886, 0x18898, 0x188b0, 0x188be, 0x188ce, 0x188dc, 0x188e2, 0x188e4, 0x188e8, 0x188f6, 0x1890c,\n        0x18930, 0x1893e, 0x18960, 0x1897c, 0x1898e, 0x189b8, 0x189c2, 0x189c8, 0x189d0, 0x189de, 0x189e6, 0x189ec,\n        0x189fa, 0x18a18, 0x18a30, 0x18a3e, 0x18a60, 0x18a7c, 0x18ac0, 0x18af8, 0x18b1c, 0x18b38, 0x18b70, 0x18b7e,\n        0x18b82, 0x18b84, 0x18b88, 0x18b90, 0x18b9e, 0x18ba0, 0x18bbc, 0x18bc6, 0x18bcc, 0x18bd8, 0x18bee, 0x18bf2,\n        0x18bf4, 0x18c22, 0x18c24, 0x18c28, 0x18c36, 0x18c42, 0x18c48, 0x18c50, 0x18c5e, 0x18c66, 0x18c7a, 0x18c82,\n        0x18c84, 0x18c90, 0x18c9e, 0x18ca0, 0x18cbc, 0x18ccc, 0x18cf2, 0x18cf4, 0x18d04, 0x18d08, 0x18d10, 0x18d1e,\n        0x18d20, 0x18d3c, 0x18d40, 0x18d78, 0x18d86, 0x18d98, 0x18dce, 0x18de2, 0x18de4, 0x18de8, 0x18e2e, 0x18e32,\n        0x18e34, 0x18e4e, 0x18e5c, 0x18e62, 0x18e64, 0x18e68, 0x18e8e, 0x18e9c, 0x18eb8, 0x18ec2, 0x18ec4, 0x18ec8,\n        0x18ed0, 0x18efa, 0x18f16, 0x18f26, 0x18f2c, 0x18f46, 0x18f4c, 0x18f58, 0x18f6e, 0x18f8a, 0x18f92, 0x18f94,\n        0x18fa2, 0x18fa4, 0x18fa8, 0x18fb6, 0x1902c, 0x1903a, 0x19046, 0x1904c, 0x19058, 0x19072, 0x19074, 0x19086,\n        0x19098, 0x190b0, 0x190be, 0x190ce, 0x190dc, 0x190e2, 0x190e8, 0x190f6, 0x19106, 0x1910c, 0x19130, 0x1913e,\n        0x19160, 0x1917c, 0x1918e, 0x1919c, 0x191b8, 0x191c2, 0x191c8, 0x191d0, 0x191de, 0x191e6, 0x191ec, 0x191fa,\n        0x19218, 0x1923e, 0x19260, 0x1927c, 0x192c0, 0x192f8, 0x19338, 0x19370, 0x1937e, 0x19382, 0x19384, 0x19390,\n        0x1939e, 0x193a0, 0x193bc, 0x193c6, 0x193cc, 0x193d8, 0x193ee, 0x193f2, 0x193f4, 0x19430, 0x1943e, 0x19460,\n        0x1947c, 0x194c0, 0x194f8, 0x195f0, 0x19638, 0x19670, 0x1967e, 0x196e0, 0x196fc, 0x19702, 0x19704, 0x19708,\n        0x19710, 0x19720, 0x1973c, 0x19740, 0x19778, 0x19786, 0x1978c, 0x19798, 0x197b0, 0x197be, 0x197ce, 0x197dc,\n        0x197e2, 0x197e4, 0x197e8, 0x19822, 0x19824, 0x19842, 0x19848, 0x19850, 0x1985e, 0x19866, 0x1987a, 0x19882,\n        0x19884, 0x19890, 0x1989e, 0x198a0, 0x198bc, 0x198cc, 0x198f2, 0x198f4, 0x19902, 0x19908, 0x1991e, 0x19920,\n        0x1993c, 0x19940, 0x19978, 0x19986, 0x19998, 0x199ce, 0x199e2, 0x199e4, 0x199e8, 0x19a08, 0x19a10, 0x19a1e,\n        0x19a20, 0x19a3c, 0x19a40, 0x19a78, 0x19af0, 0x19b18, 0x19b3e, 0x19b60, 0x19b9c, 0x19bc2, 0x19bc4, 0x19bc8,\n        0x19bd0, 0x19be6, 0x19c2e, 0x19c34, 0x19c4e, 0x19c5c, 0x19c62, 0x19c64, 0x19c68, 0x19c8e, 0x19c9c, 0x19cb8,\n        0x19cc2, 0x19cc8, 0x19cd0, 0x19ce6, 0x19cfa, 0x19d0e, 0x19d1c, 0x19d38, 0x19d70, 0x19d7e, 0x19d82, 0x19d84,\n        0x19d88, 0x19d90, 0x19da0, 0x19dcc, 0x19df2, 0x19df4, 0x19e16, 0x19e26, 0x19e2c, 0x19e46, 0x19e4c, 0x19e58,\n        0x19e74, 0x19e86, 0x19e8c, 0x19e98, 0x19eb0, 0x19ebe, 0x19ece, 0x19ee2, 0x19ee4, 0x19ee8, 0x19f0a, 0x19f12,\n        0x19f14, 0x19f22, 0x19f24, 0x19f28, 0x19f42, 0x19f44, 0x19f48, 0x19f50, 0x19f5e, 0x19f6c, 0x19f9a, 0x19fae,\n        0x19fb2, 0x19fb4, 0x1a046, 0x1a04c, 0x1a072, 0x1a074, 0x1a086, 0x1a08c, 0x1a098, 0x1a0b0, 0x1a0be, 0x1a0e2,\n        0x1a0e4, 0x1a0e8, 0x1a0f6, 0x1a106, 0x1a10c, 0x1a118, 0x1a130, 0x1a13e, 0x1a160, 0x1a17c, 0x1a18e, 0x1a19c,\n        0x1a1b8, 0x1a1c2, 0x1a1c4, 0x1a1c8, 0x1a1d0, 0x1a1de, 0x1a1e6, 0x1a1ec, 0x1a218, 0x1a230, 0x1a23e, 0x1a260,\n        0x1a27c, 0x1a2c0, 0x1a2f8, 0x1a31c, 0x1a338, 0x1a370, 0x1a37e, 0x1a382, 0x1a384, 0x1a388, 0x1a390, 0x1a39e,\n        0x1a3a0, 0x1a3bc, 0x1a3c6, 0x1a3cc, 0x1a3d8, 0x1a3ee, 0x1a3f2, 0x1a3f4, 0x1a418, 0x1a430, 0x1a43e, 0x1a460,\n        0x1a47c, 0x1a4c0, 0x1a4f8, 0x1a5f0, 0x1a61c, 0x1a638, 0x1a670, 0x1a67e, 0x1a6e0, 0x1a6fc, 0x1a702, 0x1a704,\n        0x1a708, 0x1a710, 0x1a71e, 0x1a720, 0x1a73c, 0x1a740, 0x1a778, 0x1a786, 0x1a78c, 0x1a798, 0x1a7b0, 0x1a7be,\n        0x1a7ce, 0x1a7dc, 0x1a7e2, 0x1a7e4, 0x1a7e8, 0x1a830, 0x1a860, 0x1a87c, 0x1a8c0, 0x1a8f8, 0x1a9f0, 0x1abe0,\n        0x1ac70, 0x1ac7e, 0x1ace0, 0x1acfc, 0x1adc0, 0x1adf8, 0x1ae04, 0x1ae08, 0x1ae10, 0x1ae20, 0x1ae3c, 0x1ae40,\n        0x1ae78, 0x1aef0, 0x1af06, 0x1af0c, 0x1af18, 0x1af30, 0x1af3e, 0x1af60, 0x1af7c, 0x1af8e, 0x1af9c, 0x1afb8,\n        0x1afc4, 0x1afc8, 0x1afd0, 0x1afde, 0x1b042, 0x1b05e, 0x1b07a, 0x1b082, 0x1b084, 0x1b088, 0x1b090, 0x1b09e,\n        0x1b0a0, 0x1b0bc, 0x1b0cc, 0x1b0f2, 0x1b0f4, 0x1b102, 0x1b104, 0x1b108, 0x1b110, 0x1b11e, 0x1b120, 0x1b13c,\n        0x1b140, 0x1b178, 0x1b186, 0x1b198, 0x1b1ce, 0x1b1e2, 0x1b1e4, 0x1b1e8, 0x1b204, 0x1b208, 0x1b210, 0x1b21e,\n        0x1b220, 0x1b23c, 0x1b240, 0x1b278, 0x1b2f0, 0x1b30c, 0x1b33e, 0x1b360, 0x1b39c, 0x1b3c2, 0x1b3c4, 0x1b3c8,\n        0x1b3d0, 0x1b3e6, 0x1b410, 0x1b41e, 0x1b420, 0x1b43c, 0x1b440, 0x1b478, 0x1b4f0, 0x1b5e0, 0x1b618, 0x1b660,\n        0x1b67c, 0x1b6c0, 0x1b738, 0x1b782, 0x1b784, 0x1b788, 0x1b790, 0x1b79e, 0x1b7a0, 0x1b7cc, 0x1b82e, 0x1b84e,\n        0x1b85c, 0x1b88e, 0x1b89c, 0x1b8b8, 0x1b8c2, 0x1b8c4, 0x1b8c8, 0x1b8d0, 0x1b8e6, 0x1b8fa, 0x1b90e, 0x1b91c,\n        0x1b938, 0x1b970, 0x1b97e, 0x1b982, 0x1b984, 0x1b988, 0x1b990, 0x1b99e, 0x1b9a0, 0x1b9cc, 0x1b9f2, 0x1b9f4,\n        0x1ba0e, 0x1ba1c, 0x1ba38, 0x1ba70, 0x1ba7e, 0x1bae0, 0x1bafc, 0x1bb08, 0x1bb10, 0x1bb20, 0x1bb3c, 0x1bb40,\n        0x1bb98, 0x1bbce, 0x1bbe2, 0x1bbe4, 0x1bbe8, 0x1bc16, 0x1bc26, 0x1bc2c, 0x1bc46, 0x1bc4c, 0x1bc58, 0x1bc72,\n        0x1bc74, 0x1bc86, 0x1bc8c, 0x1bc98, 0x1bcb0, 0x1bcbe, 0x1bcce, 0x1bce2, 0x1bce4, 0x1bce8, 0x1bd06, 0x1bd0c,\n        0x1bd18, 0x1bd30, 0x1bd3e, 0x1bd60, 0x1bd7c, 0x1bd9c, 0x1bdc2, 0x1bdc4, 0x1bdc8, 0x1bdd0, 0x1bde6, 0x1bdfa,\n        0x1be12, 0x1be14, 0x1be22, 0x1be24, 0x1be28, 0x1be42, 0x1be44, 0x1be48, 0x1be50, 0x1be5e, 0x1be66, 0x1be82,\n        0x1be84, 0x1be88, 0x1be90, 0x1be9e, 0x1bea0, 0x1bebc, 0x1becc, 0x1bef4, 0x1bf1a, 0x1bf2e, 0x1bf32, 0x1bf34,\n        0x1bf4e, 0x1bf5c, 0x1bf62, 0x1bf64, 0x1bf68, 0x1c09a, 0x1c0b2, 0x1c0b4, 0x1c11a, 0x1c132, 0x1c134, 0x1c162,\n        0x1c164, 0x1c168, 0x1c176, 0x1c1ba, 0x1c21a, 0x1c232, 0x1c234, 0x1c24e, 0x1c25c, 0x1c262, 0x1c264, 0x1c268,\n        0x1c276, 0x1c28e, 0x1c2c2, 0x1c2c4, 0x1c2c8, 0x1c2d0, 0x1c2de, 0x1c2e6, 0x1c2ec, 0x1c2fa, 0x1c316, 0x1c326,\n        0x1c33a, 0x1c346, 0x1c34c, 0x1c372, 0x1c374, 0x1c41a, 0x1c42e, 0x1c432, 0x1c434, 0x1c44e, 0x1c45c, 0x1c462,\n        0x1c464, 0x1c468, 0x1c476, 0x1c48e, 0x1c49c, 0x1c4b8, 0x1c4c2, 0x1c4c8, 0x1c4d0, 0x1c4de, 0x1c4e6, 0x1c4ec,\n        0x1c4fa, 0x1c51c, 0x1c538, 0x1c570, 0x1c57e, 0x1c582, 0x1c584, 0x1c588, 0x1c590, 0x1c59e, 0x1c5a0, 0x1c5bc,\n        0x1c5c6, 0x1c5cc, 0x1c5d8, 0x1c5ee, 0x1c5f2, 0x1c5f4, 0x1c616, 0x1c626, 0x1c62c, 0x1c63a, 0x1c646, 0x1c64c,\n        0x1c658, 0x1c66e, 0x1c672, 0x1c674, 0x1c686, 0x1c68c, 0x1c698, 0x1c6b0, 0x1c6be, 0x1c6ce, 0x1c6dc, 0x1c6e2,\n        0x1c6e4, 0x1c6e8, 0x1c712, 0x1c714, 0x1c722, 0x1c728, 0x1c736, 0x1c742, 0x1c744, 0x1c748, 0x1c750, 0x1c75e,\n        0x1c766, 0x1c76c, 0x1c77a, 0x1c7ae, 0x1c7d6, 0x1c7ea, 0x1c81a, 0x1c82e, 0x1c832, 0x1c834, 0x1c84e, 0x1c85c,\n        0x1c862, 0x1c864, 0x1c868, 0x1c876, 0x1c88e, 0x1c89c, 0x1c8b8, 0x1c8c2, 0x1c8c8, 0x1c8d0, 0x1c8de, 0x1c8e6,\n        0x1c8ec, 0x1c8fa, 0x1c90e, 0x1c938, 0x1c970, 0x1c97e, 0x1c982, 0x1c984, 0x1c990, 0x1c99e, 0x1c9a0, 0x1c9bc,\n        0x1c9c6, 0x1c9cc, 0x1c9d8, 0x1c9ee, 0x1c9f2, 0x1c9f4, 0x1ca38, 0x1ca70, 0x1ca7e, 0x1cae0, 0x1cafc, 0x1cb02,\n        0x1cb04, 0x1cb08, 0x1cb10, 0x1cb20, 0x1cb3c, 0x1cb40, 0x1cb78, 0x1cb86, 0x1cb8c, 0x1cb98, 0x1cbb0, 0x1cbbe,\n        0x1cbce, 0x1cbdc, 0x1cbe2, 0x1cbe4, 0x1cbe8, 0x1cbf6, 0x1cc16, 0x1cc26, 0x1cc2c, 0x1cc3a, 0x1cc46, 0x1cc58,\n        0x1cc72, 0x1cc74, 0x1cc86, 0x1ccb0, 0x1ccbe, 0x1ccce, 0x1cce2, 0x1cce4, 0x1cce8, 0x1cd06, 0x1cd0c, 0x1cd18,\n        0x1cd30, 0x1cd3e, 0x1cd60, 0x1cd7c, 0x1cd9c, 0x1cdc2, 0x1cdc4, 0x1cdc8, 0x1cdd0, 0x1cdde, 0x1cde6, 0x1cdfa,\n        0x1ce22, 0x1ce28, 0x1ce42, 0x1ce50, 0x1ce5e, 0x1ce66, 0x1ce7a, 0x1ce82, 0x1ce84, 0x1ce88, 0x1ce90, 0x1ce9e,\n        0x1cea0, 0x1cebc, 0x1cecc, 0x1cef2, 0x1cef4, 0x1cf2e, 0x1cf32, 0x1cf34, 0x1cf4e, 0x1cf5c, 0x1cf62, 0x1cf64,\n        0x1cf68, 0x1cf96, 0x1cfa6, 0x1cfac, 0x1cfca, 0x1cfd2, 0x1cfd4, 0x1d02e, 0x1d032, 0x1d034, 0x1d04e, 0x1d05c,\n        0x1d062, 0x1d064, 0x1d068, 0x1d076, 0x1d08e, 0x1d09c, 0x1d0b8, 0x1d0c2, 0x1d0c4, 0x1d0c8, 0x1d0d0, 0x1d0de,\n        0x1d0e6, 0x1d0ec, 0x1d0fa, 0x1d11c, 0x1d138, 0x1d170, 0x1d17e, 0x1d182, 0x1d184, 0x1d188, 0x1d190, 0x1d19e,\n        0x1d1a0, 0x1d1bc, 0x1d1c6, 0x1d1cc, 0x1d1d8, 0x1d1ee, 0x1d1f2, 0x1d1f4, 0x1d21c, 0x1d238, 0x1d270, 0x1d27e,\n        0x1d2e0, 0x1d2fc, 0x1d302, 0x1d304, 0x1d308, 0x1d310, 0x1d31e, 0x1d320, 0x1d33c, 0x1d340, 0x1d378, 0x1d386,\n        0x1d38c, 0x1d398, 0x1d3b0, 0x1d3be, 0x1d3ce, 0x1d3dc, 0x1d3e2, 0x1d3e4, 0x1d3e8, 0x1d3f6, 0x1d470, 0x1d47e,\n        0x1d4e0, 0x1d4fc, 0x1d5c0, 0x1d5f8, 0x1d604, 0x1d608, 0x1d610, 0x1d620, 0x1d640, 0x1d678, 0x1d6f0, 0x1d706,\n        0x1d70c, 0x1d718, 0x1d730, 0x1d73e, 0x1d760, 0x1d77c, 0x1d78e, 0x1d79c, 0x1d7b8, 0x1d7c2, 0x1d7c4, 0x1d7c8,\n        0x1d7d0, 0x1d7de, 0x1d7e6, 0x1d7ec, 0x1d826, 0x1d82c, 0x1d83a, 0x1d846, 0x1d84c, 0x1d858, 0x1d872, 0x1d874,\n        0x1d886, 0x1d88c, 0x1d898, 0x1d8b0, 0x1d8be, 0x1d8ce, 0x1d8e2, 0x1d8e4, 0x1d8e8, 0x1d8f6, 0x1d90c, 0x1d918,\n        0x1d930, 0x1d93e, 0x1d960, 0x1d97c, 0x1d99c, 0x1d9c2, 0x1d9c4, 0x1d9c8, 0x1d9d0, 0x1d9e6, 0x1d9fa, 0x1da0c,\n        0x1da18, 0x1da30, 0x1da3e, 0x1da60, 0x1da7c, 0x1dac0, 0x1daf8, 0x1db38, 0x1db82, 0x1db84, 0x1db88, 0x1db90,\n        0x1db9e, 0x1dba0, 0x1dbcc, 0x1dbf2, 0x1dbf4, 0x1dc22, 0x1dc42, 0x1dc44, 0x1dc48, 0x1dc50, 0x1dc5e, 0x1dc66,\n        0x1dc7a, 0x1dc82, 0x1dc84, 0x1dc88, 0x1dc90, 0x1dc9e, 0x1dca0, 0x1dcbc, 0x1dccc, 0x1dcf2, 0x1dcf4, 0x1dd04,\n        0x1dd08, 0x1dd10, 0x1dd1e, 0x1dd20, 0x1dd3c, 0x1dd40, 0x1dd78, 0x1dd86, 0x1dd98, 0x1ddce, 0x1dde2, 0x1dde4,\n        0x1dde8, 0x1de2e, 0x1de32, 0x1de34, 0x1de4e, 0x1de5c, 0x1de62, 0x1de64, 0x1de68, 0x1de8e, 0x1de9c, 0x1deb8,\n        0x1dec2, 0x1dec4, 0x1dec8, 0x1ded0, 0x1dee6, 0x1defa, 0x1df16, 0x1df26, 0x1df2c, 0x1df46, 0x1df4c, 0x1df58,\n        0x1df72, 0x1df74, 0x1df8a, 0x1df92, 0x1df94, 0x1dfa2, 0x1dfa4, 0x1dfa8, 0x1e08a, 0x1e092, 0x1e094, 0x1e0a2,\n        0x1e0a4, 0x1e0a8, 0x1e0b6, 0x1e0da, 0x1e10a, 0x1e112, 0x1e114, 0x1e122, 0x1e124, 0x1e128, 0x1e136, 0x1e142,\n        0x1e144, 0x1e148, 0x1e150, 0x1e166, 0x1e16c, 0x1e17a, 0x1e19a, 0x1e1b2, 0x1e1b4, 0x1e20a, 0x1e212, 0x1e214,\n        0x1e222, 0x1e224, 0x1e228, 0x1e236, 0x1e242, 0x1e248, 0x1e250, 0x1e25e, 0x1e266, 0x1e26c, 0x1e27a, 0x1e282,\n        0x1e284, 0x1e288, 0x1e290, 0x1e2a0, 0x1e2bc, 0x1e2c6, 0x1e2cc, 0x1e2d8, 0x1e2ee, 0x1e2f2, 0x1e2f4, 0x1e31a,\n        0x1e332, 0x1e334, 0x1e35c, 0x1e362, 0x1e364, 0x1e368, 0x1e3ba, 0x1e40a, 0x1e412, 0x1e414, 0x1e422, 0x1e428,\n        0x1e436, 0x1e442, 0x1e448, 0x1e450, 0x1e45e, 0x1e466, 0x1e46c, 0x1e47a, 0x1e482, 0x1e484, 0x1e490, 0x1e49e,\n        0x1e4a0, 0x1e4bc, 0x1e4c6, 0x1e4cc, 0x1e4d8, 0x1e4ee, 0x1e4f2, 0x1e4f4, 0x1e502, 0x1e504, 0x1e508, 0x1e510,\n        0x1e51e, 0x1e520, 0x1e53c, 0x1e540, 0x1e578, 0x1e586, 0x1e58c, 0x1e598, 0x1e5b0, 0x1e5be, 0x1e5ce, 0x1e5dc,\n        0x1e5e2, 0x1e5e4, 0x1e5e8, 0x1e5f6, 0x1e61a, 0x1e62e, 0x1e632, 0x1e634, 0x1e64e, 0x1e65c, 0x1e662, 0x1e668,\n        0x1e68e, 0x1e69c, 0x1e6b8, 0x1e6c2, 0x1e6c4, 0x1e6c8, 0x1e6d0, 0x1e6e6, 0x1e6fa, 0x1e716, 0x1e726, 0x1e72c,\n        0x1e73a, 0x1e746, 0x1e74c, 0x1e758, 0x1e772, 0x1e774, 0x1e792, 0x1e794, 0x1e7a2, 0x1e7a4, 0x1e7a8, 0x1e7b6,\n        0x1e812, 0x1e814, 0x1e822, 0x1e824, 0x1e828, 0x1e836, 0x1e842, 0x1e844, 0x1e848, 0x1e850, 0x1e85e, 0x1e866,\n        0x1e86c, 0x1e87a, 0x1e882, 0x1e884, 0x1e888, 0x1e890, 0x1e89e, 0x1e8a0, 0x1e8bc, 0x1e8c6, 0x1e8cc, 0x1e8d8,\n        0x1e8ee, 0x1e8f2, 0x1e8f4, 0x1e902, 0x1e904, 0x1e908, 0x1e910, 0x1e920, 0x1e93c, 0x1e940, 0x1e978, 0x1e986,\n        0x1e98c, 0x1e998, 0x1e9b0, 0x1e9be, 0x1e9ce, 0x1e9dc, 0x1e9e2, 0x1e9e4, 0x1e9e8, 0x1e9f6, 0x1ea04, 0x1ea08,\n        0x1ea10, 0x1ea20, 0x1ea40, 0x1ea78, 0x1eaf0, 0x1eb06, 0x1eb0c, 0x1eb18, 0x1eb30, 0x1eb3e, 0x1eb60, 0x1eb7c,\n        0x1eb8e, 0x1eb9c, 0x1ebb8, 0x1ebc2, 0x1ebc4, 0x1ebc8, 0x1ebd0, 0x1ebde, 0x1ebe6, 0x1ebec, 0x1ec1a, 0x1ec2e,\n        0x1ec32, 0x1ec34, 0x1ec4e, 0x1ec5c, 0x1ec62, 0x1ec64, 0x1ec68, 0x1ec8e, 0x1ec9c, 0x1ecb8, 0x1ecc2, 0x1ecc4,\n        0x1ecc8, 0x1ecd0, 0x1ece6, 0x1ecfa, 0x1ed0e, 0x1ed1c, 0x1ed38, 0x1ed70, 0x1ed7e, 0x1ed82, 0x1ed84, 0x1ed88,\n        0x1ed90, 0x1ed9e, 0x1eda0, 0x1edcc, 0x1edf2, 0x1edf4, 0x1ee16, 0x1ee26, 0x1ee2c, 0x1ee3a, 0x1ee46, 0x1ee4c,\n        0x1ee58, 0x1ee6e, 0x1ee72, 0x1ee74, 0x1ee86, 0x1ee8c, 0x1ee98, 0x1eeb0, 0x1eebe, 0x1eece, 0x1eedc, 0x1eee2,\n        0x1eee4, 0x1eee8, 0x1ef12, 0x1ef22, 0x1ef24, 0x1ef28, 0x1ef36, 0x1ef42, 0x1ef44, 0x1ef48, 0x1ef50, 0x1ef5e,\n        0x1ef66, 0x1ef6c, 0x1ef7a, 0x1efae, 0x1efb2, 0x1efb4, 0x1efd6, 0x1f096, 0x1f0a6, 0x1f0ac, 0x1f0ba, 0x1f0ca,\n        0x1f0d2, 0x1f0d4, 0x1f116, 0x1f126, 0x1f12c, 0x1f13a, 0x1f146, 0x1f14c, 0x1f158, 0x1f16e, 0x1f172, 0x1f174,\n        0x1f18a, 0x1f192, 0x1f194, 0x1f1a2, 0x1f1a4, 0x1f1a8, 0x1f1da, 0x1f216, 0x1f226, 0x1f22c, 0x1f23a, 0x1f246,\n        0x1f258, 0x1f26e, 0x1f272, 0x1f274, 0x1f286, 0x1f28c, 0x1f298, 0x1f2b0, 0x1f2be, 0x1f2ce, 0x1f2dc, 0x1f2e2,\n        0x1f2e4, 0x1f2e8, 0x1f2f6, 0x1f30a, 0x1f312, 0x1f314, 0x1f322, 0x1f328, 0x1f342, 0x1f344, 0x1f348, 0x1f350,\n        0x1f35e, 0x1f366, 0x1f37a, 0x1f39a, 0x1f3ae, 0x1f3b2, 0x1f3b4, 0x1f416, 0x1f426, 0x1f42c, 0x1f43a, 0x1f446,\n        0x1f44c, 0x1f458, 0x1f46e, 0x1f472, 0x1f474, 0x1f486, 0x1f48c, 0x1f498, 0x1f4b0, 0x1f4be, 0x1f4ce, 0x1f4dc,\n        0x1f4e2, 0x1f4e4, 0x1f4e8, 0x1f4f6, 0x1f506, 0x1f50c, 0x1f518, 0x1f530, 0x1f53e, 0x1f560, 0x1f57c, 0x1f58e,\n        0x1f59c, 0x1f5b8, 0x1f5c2, 0x1f5c4, 0x1f5c8, 0x1f5d0, 0x1f5de, 0x1f5e6, 0x1f5ec, 0x1f5fa, 0x1f60a, 0x1f612,\n        0x1f614, 0x1f622, 0x1f624, 0x1f628, 0x1f636, 0x1f642, 0x1f644, 0x1f648, 0x1f650, 0x1f65e, 0x1f666, 0x1f67a,\n        0x1f682, 0x1f684, 0x1f688, 0x1f690, 0x1f69e, 0x1f6a0, 0x1f6bc, 0x1f6cc, 0x1f6f2, 0x1f6f4, 0x1f71a, 0x1f72e,\n        0x1f732, 0x1f734, 0x1f74e, 0x1f75c, 0x1f762, 0x1f764, 0x1f768, 0x1f776, 0x1f796, 0x1f7a6, 0x1f7ac, 0x1f7ba,\n        0x1f7d2, 0x1f7d4, 0x1f89a, 0x1f8ae, 0x1f8b2, 0x1f8b4, 0x1f8d6, 0x1f8ea, 0x1f91a, 0x1f92e, 0x1f932, 0x1f934,\n        0x1f94e, 0x1f95c, 0x1f962, 0x1f964, 0x1f968, 0x1f976, 0x1f996, 0x1f9a6, 0x1f9ac, 0x1f9ba, 0x1f9ca, 0x1f9d2,\n        0x1f9d4, 0x1fa1a, 0x1fa2e, 0x1fa32, 0x1fa34, 0x1fa4e, 0x1fa5c, 0x1fa62, 0x1fa64, 0x1fa68, 0x1fa76, 0x1fa8e,\n        0x1fa9c, 0x1fab8, 0x1fac2, 0x1fac4, 0x1fac8, 0x1fad0, 0x1fade, 0x1fae6, 0x1faec, 0x1fb16, 0x1fb26, 0x1fb2c,\n        0x1fb3a, 0x1fb46, 0x1fb4c, 0x1fb58, 0x1fb6e, 0x1fb72, 0x1fb74, 0x1fb8a, 0x1fb92, 0x1fb94, 0x1fba2, 0x1fba4,\n        0x1fba8, 0x1fbb6, 0x1fbda\n    ]);\n    /**\n     * This table contains to codewords for all symbols.\n     */\n    PDF417Common.CODEWORD_TABLE = Int32Array.from([\n        2627, 1819, 2622, 2621, 1813, 1812, 2729, 2724, 2723, 2779, 2774, 2773, 902, 896, 908, 868, 865, 861, 859, 2511,\n        873, 871, 1780, 835, 2493, 825, 2491, 842, 837, 844, 1764, 1762, 811, 810, 809, 2483, 807, 2482, 806, 2480, 815,\n        814, 813, 812, 2484, 817, 816, 1745, 1744, 1742, 1746, 2655, 2637, 2635, 2626, 2625, 2623, 2628, 1820, 2752,\n        2739, 2737, 2728, 2727, 2725, 2730, 2785, 2783, 2778, 2777, 2775, 2780, 787, 781, 747, 739, 736, 2413, 754, 752,\n        1719, 692, 689, 681, 2371, 678, 2369, 700, 697, 694, 703, 1688, 1686, 642, 638, 2343, 631, 2341, 627, 2338, 651,\n        646, 643, 2345, 654, 652, 1652, 1650, 1647, 1654, 601, 599, 2322, 596, 2321, 594, 2319, 2317, 611, 610, 608, 606,\n        2324, 603, 2323, 615, 614, 612, 1617, 1616, 1614, 1612, 616, 1619, 1618, 2575, 2538, 2536, 905, 901, 898, 909,\n        2509, 2507, 2504, 870, 867, 864, 860, 2512, 875, 872, 1781, 2490, 2489, 2487, 2485, 1748, 836, 834, 832, 830,\n        2494, 827, 2492, 843, 841, 839, 845, 1765, 1763, 2701, 2676, 2674, 2653, 2648, 2656, 2634, 2633, 2631, 2629,\n        1821, 2638, 2636, 2770, 2763, 2761, 2750, 2745, 2753, 2736, 2735, 2733, 2731, 1848, 2740, 2738, 2786, 2784, 591,\n        588, 576, 569, 566, 2296, 1590, 537, 534, 526, 2276, 522, 2274, 545, 542, 539, 548, 1572, 1570, 481, 2245, 466,\n        2242, 462, 2239, 492, 485, 482, 2249, 496, 494, 1534, 1531, 1528, 1538, 413, 2196, 406, 2191, 2188, 425, 419,\n        2202, 415, 2199, 432, 430, 427, 1472, 1467, 1464, 433, 1476, 1474, 368, 367, 2160, 365, 2159, 362, 2157, 2155,\n        2152, 378, 377, 375, 2166, 372, 2165, 369, 2162, 383, 381, 379, 2168, 1419, 1418, 1416, 1414, 385, 1411, 384,\n        1423, 1422, 1420, 1424, 2461, 802, 2441, 2439, 790, 786, 783, 794, 2409, 2406, 2403, 750, 742, 738, 2414, 756,\n        753, 1720, 2367, 2365, 2362, 2359, 1663, 693, 691, 684, 2373, 680, 2370, 702, 699, 696, 704, 1690, 1687, 2337,\n        2336, 2334, 2332, 1624, 2329, 1622, 640, 637, 2344, 634, 2342, 630, 2340, 650, 648, 645, 2346, 655, 653, 1653,\n        1651, 1649, 1655, 2612, 2597, 2595, 2571, 2568, 2565, 2576, 2534, 2529, 2526, 1787, 2540, 2537, 907, 904, 900,\n        910, 2503, 2502, 2500, 2498, 1768, 2495, 1767, 2510, 2508, 2506, 869, 866, 863, 2513, 876, 874, 1782, 2720, 2713,\n        2711, 2697, 2694, 2691, 2702, 2672, 2670, 2664, 1828, 2678, 2675, 2647, 2646, 2644, 2642, 1823, 2639, 1822, 2654,\n        2652, 2650, 2657, 2771, 1855, 2765, 2762, 1850, 1849, 2751, 2749, 2747, 2754, 353, 2148, 344, 342, 336, 2142,\n        332, 2140, 345, 1375, 1373, 306, 2130, 299, 2128, 295, 2125, 319, 314, 311, 2132, 1354, 1352, 1349, 1356, 262,\n        257, 2101, 253, 2096, 2093, 274, 273, 267, 2107, 263, 2104, 280, 278, 275, 1316, 1311, 1308, 1320, 1318, 2052,\n        202, 2050, 2044, 2040, 219, 2063, 212, 2060, 208, 2055, 224, 221, 2066, 1260, 1258, 1252, 231, 1248, 229, 1266,\n        1264, 1261, 1268, 155, 1998, 153, 1996, 1994, 1991, 1988, 165, 164, 2007, 162, 2006, 159, 2003, 2000, 172, 171,\n        169, 2012, 166, 2010, 1186, 1184, 1182, 1179, 175, 1176, 173, 1192, 1191, 1189, 1187, 176, 1194, 1193, 2313,\n        2307, 2305, 592, 589, 2294, 2292, 2289, 578, 572, 568, 2297, 580, 1591, 2272, 2267, 2264, 1547, 538, 536, 529,\n        2278, 525, 2275, 547, 544, 541, 1574, 1571, 2237, 2235, 2229, 1493, 2225, 1489, 478, 2247, 470, 2244, 465, 2241,\n        493, 488, 484, 2250, 498, 495, 1536, 1533, 1530, 1539, 2187, 2186, 2184, 2182, 1432, 2179, 1430, 2176, 1427, 414,\n        412, 2197, 409, 2195, 405, 2193, 2190, 426, 424, 421, 2203, 418, 2201, 431, 429, 1473, 1471, 1469, 1466, 434,\n        1477, 1475, 2478, 2472, 2470, 2459, 2457, 2454, 2462, 803, 2437, 2432, 2429, 1726, 2443, 2440, 792, 789, 785,\n        2401, 2399, 2393, 1702, 2389, 1699, 2411, 2408, 2405, 745, 741, 2415, 758, 755, 1721, 2358, 2357, 2355, 2353,\n        1661, 2350, 1660, 2347, 1657, 2368, 2366, 2364, 2361, 1666, 690, 687, 2374, 683, 2372, 701, 698, 705, 1691, 1689,\n        2619, 2617, 2610, 2608, 2605, 2613, 2593, 2588, 2585, 1803, 2599, 2596, 2563, 2561, 2555, 1797, 2551, 1795, 2573,\n        2570, 2567, 2577, 2525, 2524, 2522, 2520, 1786, 2517, 1785, 2514, 1783, 2535, 2533, 2531, 2528, 1788, 2541, 2539,\n        906, 903, 911, 2721, 1844, 2715, 2712, 1838, 1836, 2699, 2696, 2693, 2703, 1827, 1826, 1824, 2673, 2671, 2669,\n        2666, 1829, 2679, 2677, 1858, 1857, 2772, 1854, 1853, 1851, 1856, 2766, 2764, 143, 1987, 139, 1986, 135, 133,\n        131, 1984, 128, 1983, 125, 1981, 138, 137, 136, 1985, 1133, 1132, 1130, 112, 110, 1974, 107, 1973, 104, 1971,\n        1969, 122, 121, 119, 117, 1977, 114, 1976, 124, 1115, 1114, 1112, 1110, 1117, 1116, 84, 83, 1953, 81, 1952, 78,\n        1950, 1948, 1945, 94, 93, 91, 1959, 88, 1958, 85, 1955, 99, 97, 95, 1961, 1086, 1085, 1083, 1081, 1078, 100,\n        1090, 1089, 1087, 1091, 49, 47, 1917, 44, 1915, 1913, 1910, 1907, 59, 1926, 56, 1925, 53, 1922, 1919, 66, 64,\n        1931, 61, 1929, 1042, 1040, 1038, 71, 1035, 70, 1032, 68, 1048, 1047, 1045, 1043, 1050, 1049, 12, 10, 1869, 1867,\n        1864, 1861, 21, 1880, 19, 1877, 1874, 1871, 28, 1888, 25, 1886, 22, 1883, 982, 980, 977, 974, 32, 30, 991, 989,\n        987, 984, 34, 995, 994, 992, 2151, 2150, 2147, 2146, 2144, 356, 355, 354, 2149, 2139, 2138, 2136, 2134, 1359,\n        343, 341, 338, 2143, 335, 2141, 348, 347, 346, 1376, 1374, 2124, 2123, 2121, 2119, 1326, 2116, 1324, 310, 308,\n        305, 2131, 302, 2129, 298, 2127, 320, 318, 316, 313, 2133, 322, 321, 1355, 1353, 1351, 1357, 2092, 2091, 2089,\n        2087, 1276, 2084, 1274, 2081, 1271, 259, 2102, 256, 2100, 252, 2098, 2095, 272, 269, 2108, 266, 2106, 281, 279,\n        277, 1317, 1315, 1313, 1310, 282, 1321, 1319, 2039, 2037, 2035, 2032, 1203, 2029, 1200, 1197, 207, 2053, 205,\n        2051, 201, 2049, 2046, 2043, 220, 218, 2064, 215, 2062, 211, 2059, 228, 226, 223, 2069, 1259, 1257, 1254, 232,\n        1251, 230, 1267, 1265, 1263, 2316, 2315, 2312, 2311, 2309, 2314, 2304, 2303, 2301, 2299, 1593, 2308, 2306, 590,\n        2288, 2287, 2285, 2283, 1578, 2280, 1577, 2295, 2293, 2291, 579, 577, 574, 571, 2298, 582, 581, 1592, 2263, 2262,\n        2260, 2258, 1545, 2255, 1544, 2252, 1541, 2273, 2271, 2269, 2266, 1550, 535, 532, 2279, 528, 2277, 546, 543, 549,\n        1575, 1573, 2224, 2222, 2220, 1486, 2217, 1485, 2214, 1482, 1479, 2238, 2236, 2234, 2231, 1496, 2228, 1492, 480,\n        477, 2248, 473, 2246, 469, 2243, 490, 487, 2251, 497, 1537, 1535, 1532, 2477, 2476, 2474, 2479, 2469, 2468, 2466,\n        2464, 1730, 2473, 2471, 2453, 2452, 2450, 2448, 1729, 2445, 1728, 2460, 2458, 2456, 2463, 805, 804, 2428, 2427,\n        2425, 2423, 1725, 2420, 1724, 2417, 1722, 2438, 2436, 2434, 2431, 1727, 2444, 2442, 793, 791, 788, 795, 2388,\n        2386, 2384, 1697, 2381, 1696, 2378, 1694, 1692, 2402, 2400, 2398, 2395, 1703, 2392, 1701, 2412, 2410, 2407, 751,\n        748, 744, 2416, 759, 757, 1807, 2620, 2618, 1806, 1805, 2611, 2609, 2607, 2614, 1802, 1801, 1799, 2594, 2592,\n        2590, 2587, 1804, 2600, 2598, 1794, 1793, 1791, 1789, 2564, 2562, 2560, 2557, 1798, 2554, 1796, 2574, 2572, 2569,\n        2578, 1847, 1846, 2722, 1843, 1842, 1840, 1845, 2716, 2714, 1835, 1834, 1832, 1830, 1839, 1837, 2700, 2698, 2695,\n        2704, 1817, 1811, 1810, 897, 862, 1777, 829, 826, 838, 1760, 1758, 808, 2481, 1741, 1740, 1738, 1743, 2624, 1818,\n        2726, 2776, 782, 740, 737, 1715, 686, 679, 695, 1682, 1680, 639, 628, 2339, 647, 644, 1645, 1643, 1640, 1648,\n        602, 600, 597, 595, 2320, 593, 2318, 609, 607, 604, 1611, 1610, 1608, 1606, 613, 1615, 1613, 2328, 926, 924, 892,\n        886, 899, 857, 850, 2505, 1778, 824, 823, 821, 819, 2488, 818, 2486, 833, 831, 828, 840, 1761, 1759, 2649, 2632,\n        2630, 2746, 2734, 2732, 2782, 2781, 570, 567, 1587, 531, 527, 523, 540, 1566, 1564, 476, 467, 463, 2240, 486,\n        483, 1524, 1521, 1518, 1529, 411, 403, 2192, 399, 2189, 423, 416, 1462, 1457, 1454, 428, 1468, 1465, 2210, 366,\n        363, 2158, 360, 2156, 357, 2153, 376, 373, 370, 2163, 1410, 1409, 1407, 1405, 382, 1402, 380, 1417, 1415, 1412,\n        1421, 2175, 2174, 777, 774, 771, 784, 732, 725, 722, 2404, 743, 1716, 676, 674, 668, 2363, 665, 2360, 685, 1684,\n        1681, 626, 624, 622, 2335, 620, 2333, 617, 2330, 641, 635, 649, 1646, 1644, 1642, 2566, 928, 925, 2530, 2527,\n        894, 891, 888, 2501, 2499, 2496, 858, 856, 854, 851, 1779, 2692, 2668, 2665, 2645, 2643, 2640, 2651, 2768, 2759,\n        2757, 2744, 2743, 2741, 2748, 352, 1382, 340, 337, 333, 1371, 1369, 307, 300, 296, 2126, 315, 312, 1347, 1342,\n        1350, 261, 258, 250, 2097, 246, 2094, 271, 268, 264, 1306, 1301, 1298, 276, 1312, 1309, 2115, 203, 2048, 195,\n        2045, 191, 2041, 213, 209, 2056, 1246, 1244, 1238, 225, 1234, 222, 1256, 1253, 1249, 1262, 2080, 2079, 154, 1997,\n        150, 1995, 147, 1992, 1989, 163, 160, 2004, 156, 2001, 1175, 1174, 1172, 1170, 1167, 170, 1164, 167, 1185, 1183,\n        1180, 1177, 174, 1190, 1188, 2025, 2024, 2022, 587, 586, 564, 559, 556, 2290, 573, 1588, 520, 518, 512, 2268,\n        508, 2265, 530, 1568, 1565, 461, 457, 2233, 450, 2230, 446, 2226, 479, 471, 489, 1526, 1523, 1520, 397, 395,\n        2185, 392, 2183, 389, 2180, 2177, 410, 2194, 402, 422, 1463, 1461, 1459, 1456, 1470, 2455, 799, 2433, 2430, 779,\n        776, 773, 2397, 2394, 2390, 734, 728, 724, 746, 1717, 2356, 2354, 2351, 2348, 1658, 677, 675, 673, 670, 667, 688,\n        1685, 1683, 2606, 2589, 2586, 2559, 2556, 2552, 927, 2523, 2521, 2518, 2515, 1784, 2532, 895, 893, 890, 2718,\n        2709, 2707, 2689, 2687, 2684, 2663, 2662, 2660, 2658, 1825, 2667, 2769, 1852, 2760, 2758, 142, 141, 1139, 1138,\n        134, 132, 129, 126, 1982, 1129, 1128, 1126, 1131, 113, 111, 108, 105, 1972, 101, 1970, 120, 118, 115, 1109, 1108,\n        1106, 1104, 123, 1113, 1111, 82, 79, 1951, 75, 1949, 72, 1946, 92, 89, 86, 1956, 1077, 1076, 1074, 1072, 98,\n        1069, 96, 1084, 1082, 1079, 1088, 1968, 1967, 48, 45, 1916, 42, 1914, 39, 1911, 1908, 60, 57, 54, 1923, 50, 1920,\n        1031, 1030, 1028, 1026, 67, 1023, 65, 1020, 62, 1041, 1039, 1036, 1033, 69, 1046, 1044, 1944, 1943, 1941, 11, 9,\n        1868, 7, 1865, 1862, 1859, 20, 1878, 16, 1875, 13, 1872, 970, 968, 966, 963, 29, 960, 26, 23, 983, 981, 978, 975,\n        33, 971, 31, 990, 988, 985, 1906, 1904, 1902, 993, 351, 2145, 1383, 331, 330, 328, 326, 2137, 323, 2135, 339,\n        1372, 1370, 294, 293, 291, 289, 2122, 286, 2120, 283, 2117, 309, 303, 317, 1348, 1346, 1344, 245, 244, 242, 2090,\n        239, 2088, 236, 2085, 2082, 260, 2099, 249, 270, 1307, 1305, 1303, 1300, 1314, 189, 2038, 186, 2036, 183, 2033,\n        2030, 2026, 206, 198, 2047, 194, 216, 1247, 1245, 1243, 1240, 227, 1237, 1255, 2310, 2302, 2300, 2286, 2284,\n        2281, 565, 563, 561, 558, 575, 1589, 2261, 2259, 2256, 2253, 1542, 521, 519, 517, 514, 2270, 511, 533, 1569,\n        1567, 2223, 2221, 2218, 2215, 1483, 2211, 1480, 459, 456, 453, 2232, 449, 474, 491, 1527, 1525, 1522, 2475, 2467,\n        2465, 2451, 2449, 2446, 801, 800, 2426, 2424, 2421, 2418, 1723, 2435, 780, 778, 775, 2387, 2385, 2382, 2379,\n        1695, 2375, 1693, 2396, 735, 733, 730, 727, 749, 1718, 2616, 2615, 2604, 2603, 2601, 2584, 2583, 2581, 2579,\n        1800, 2591, 2550, 2549, 2547, 2545, 1792, 2542, 1790, 2558, 929, 2719, 1841, 2710, 2708, 1833, 1831, 2690, 2688,\n        2686, 1815, 1809, 1808, 1774, 1756, 1754, 1737, 1736, 1734, 1739, 1816, 1711, 1676, 1674, 633, 629, 1638, 1636,\n        1633, 1641, 598, 1605, 1604, 1602, 1600, 605, 1609, 1607, 2327, 887, 853, 1775, 822, 820, 1757, 1755, 1584, 524,\n        1560, 1558, 468, 464, 1514, 1511, 1508, 1519, 408, 404, 400, 1452, 1447, 1444, 417, 1458, 1455, 2208, 364, 361,\n        358, 2154, 1401, 1400, 1398, 1396, 374, 1393, 371, 1408, 1406, 1403, 1413, 2173, 2172, 772, 726, 723, 1712, 672,\n        669, 666, 682, 1678, 1675, 625, 623, 621, 618, 2331, 636, 632, 1639, 1637, 1635, 920, 918, 884, 880, 889, 849,\n        848, 847, 846, 2497, 855, 852, 1776, 2641, 2742, 2787, 1380, 334, 1367, 1365, 301, 297, 1340, 1338, 1335, 1343,\n        255, 251, 247, 1296, 1291, 1288, 265, 1302, 1299, 2113, 204, 196, 192, 2042, 1232, 1230, 1224, 214, 1220, 210,\n        1242, 1239, 1235, 1250, 2077, 2075, 151, 148, 1993, 144, 1990, 1163, 1162, 1160, 1158, 1155, 161, 1152, 157,\n        1173, 1171, 1168, 1165, 168, 1181, 1178, 2021, 2020, 2018, 2023, 585, 560, 557, 1585, 516, 509, 1562, 1559, 458,\n        447, 2227, 472, 1516, 1513, 1510, 398, 396, 393, 390, 2181, 386, 2178, 407, 1453, 1451, 1449, 1446, 420, 1460,\n        2209, 769, 764, 720, 712, 2391, 729, 1713, 664, 663, 661, 659, 2352, 656, 2349, 671, 1679, 1677, 2553, 922, 919,\n        2519, 2516, 885, 883, 881, 2685, 2661, 2659, 2767, 2756, 2755, 140, 1137, 1136, 130, 127, 1125, 1124, 1122, 1127,\n        109, 106, 102, 1103, 1102, 1100, 1098, 116, 1107, 1105, 1980, 80, 76, 73, 1947, 1068, 1067, 1065, 1063, 90, 1060,\n        87, 1075, 1073, 1070, 1080, 1966, 1965, 46, 43, 40, 1912, 36, 1909, 1019, 1018, 1016, 1014, 58, 1011, 55, 1008,\n        51, 1029, 1027, 1024, 1021, 63, 1037, 1034, 1940, 1939, 1937, 1942, 8, 1866, 4, 1863, 1, 1860, 956, 954, 952,\n        949, 946, 17, 14, 969, 967, 964, 961, 27, 957, 24, 979, 976, 972, 1901, 1900, 1898, 1896, 986, 1905, 1903, 350,\n        349, 1381, 329, 327, 324, 1368, 1366, 292, 290, 287, 284, 2118, 304, 1341, 1339, 1337, 1345, 243, 240, 237, 2086,\n        233, 2083, 254, 1297, 1295, 1293, 1290, 1304, 2114, 190, 187, 184, 2034, 180, 2031, 177, 2027, 199, 1233, 1231,\n        1229, 1226, 217, 1223, 1241, 2078, 2076, 584, 555, 554, 552, 550, 2282, 562, 1586, 507, 506, 504, 502, 2257, 499,\n        2254, 515, 1563, 1561, 445, 443, 441, 2219, 438, 2216, 435, 2212, 460, 454, 475, 1517, 1515, 1512, 2447, 798,\n        797, 2422, 2419, 770, 768, 766, 2383, 2380, 2376, 721, 719, 717, 714, 731, 1714, 2602, 2582, 2580, 2548, 2546,\n        2543, 923, 921, 2717, 2706, 2705, 2683, 2682, 2680, 1771, 1752, 1750, 1733, 1732, 1731, 1735, 1814, 1707, 1670,\n        1668, 1631, 1629, 1626, 1634, 1599, 1598, 1596, 1594, 1603, 1601, 2326, 1772, 1753, 1751, 1581, 1554, 1552, 1504,\n        1501, 1498, 1509, 1442, 1437, 1434, 401, 1448, 1445, 2206, 1392, 1391, 1389, 1387, 1384, 359, 1399, 1397, 1394,\n        1404, 2171, 2170, 1708, 1672, 1669, 619, 1632, 1630, 1628, 1773, 1378, 1363, 1361, 1333, 1328, 1336, 1286, 1281,\n        1278, 248, 1292, 1289, 2111, 1218, 1216, 1210, 197, 1206, 193, 1228, 1225, 1221, 1236, 2073, 2071, 1151, 1150,\n        1148, 1146, 152, 1143, 149, 1140, 145, 1161, 1159, 1156, 1153, 158, 1169, 1166, 2017, 2016, 2014, 2019, 1582,\n        510, 1556, 1553, 452, 448, 1506, 1500, 394, 391, 387, 1443, 1441, 1439, 1436, 1450, 2207, 765, 716, 713, 1709,\n        662, 660, 657, 1673, 1671, 916, 914, 879, 878, 877, 882, 1135, 1134, 1121, 1120, 1118, 1123, 1097, 1096, 1094,\n        1092, 103, 1101, 1099, 1979, 1059, 1058, 1056, 1054, 77, 1051, 74, 1066, 1064, 1061, 1071, 1964, 1963, 1007,\n        1006, 1004, 1002, 999, 41, 996, 37, 1017, 1015, 1012, 1009, 52, 1025, 1022, 1936, 1935, 1933, 1938, 942, 940,\n        938, 935, 932, 5, 2, 955, 953, 950, 947, 18, 943, 15, 965, 962, 958, 1895, 1894, 1892, 1890, 973, 1899, 1897,\n        1379, 325, 1364, 1362, 288, 285, 1334, 1332, 1330, 241, 238, 234, 1287, 1285, 1283, 1280, 1294, 2112, 188, 185,\n        181, 178, 2028, 1219, 1217, 1215, 1212, 200, 1209, 1227, 2074, 2072, 583, 553, 551, 1583, 505, 503, 500, 513,\n        1557, 1555, 444, 442, 439, 436, 2213, 455, 451, 1507, 1505, 1502, 796, 763, 762, 760, 767, 711, 710, 708, 706,\n        2377, 718, 715, 1710, 2544, 917, 915, 2681, 1627, 1597, 1595, 2325, 1769, 1749, 1747, 1499, 1438, 1435, 2204,\n        1390, 1388, 1385, 1395, 2169, 2167, 1704, 1665, 1662, 1625, 1623, 1620, 1770, 1329, 1282, 1279, 2109, 1214, 1207,\n        1222, 2068, 2065, 1149, 1147, 1144, 1141, 146, 1157, 1154, 2013, 2011, 2008, 2015, 1579, 1549, 1546, 1495, 1487,\n        1433, 1431, 1428, 1425, 388, 1440, 2205, 1705, 658, 1667, 1664, 1119, 1095, 1093, 1978, 1057, 1055, 1052, 1062,\n        1962, 1960, 1005, 1003, 1000, 997, 38, 1013, 1010, 1932, 1930, 1927, 1934, 941, 939, 936, 933, 6, 930, 3, 951,\n        948, 944, 1889, 1887, 1884, 1881, 959, 1893, 1891, 35, 1377, 1360, 1358, 1327, 1325, 1322, 1331, 1277, 1275,\n        1272, 1269, 235, 1284, 2110, 1205, 1204, 1201, 1198, 182, 1195, 179, 1213, 2070, 2067, 1580, 501, 1551, 1548,\n        440, 437, 1497, 1494, 1490, 1503, 761, 709, 707, 1706, 913, 912, 2198, 1386, 2164, 2161, 1621, 1766, 2103, 1208,\n        2058, 2054, 1145, 1142, 2005, 2002, 1999, 2009, 1488, 1429, 1426, 2200, 1698, 1659, 1656, 1975, 1053, 1957, 1954,\n        1001, 998, 1924, 1921, 1918, 1928, 937, 934, 931, 1879, 1876, 1873, 1870, 945, 1885, 1882, 1323, 1273, 1270,\n        2105, 1202, 1199, 1196, 1211, 2061, 2057, 1576, 1543, 1540, 1484, 1481, 1478, 1491, 1700\n    ]);\n\n    /*\n    * Copyright 2007 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    // import java.util.List;\n    /**\n     * @author Guenther Grau\n     */\n    /*public final*/ class PDF417DetectorResult {\n        constructor(bits, points) {\n            this.bits = bits;\n            this.points = points;\n        }\n        getBits() {\n            return this.bits;\n        }\n        getPoints() {\n            return this.points;\n        }\n    }\n\n    /*\n    * Copyright 2009 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    // import java.util.ArrayList;\n    // import java.util.Arrays;\n    // import java.util.List;\n    // import java.util.Map;\n    /**\n     * <p>Encapsulates logic that can detect a PDF417 Code in an image, even if the\n     * PDF417 Code is rotated or skewed, or partially obscured.</p>\n     *\n     * @author SITA Lab (kevin.osullivan@sita.aero)\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @author Guenther Grau\n     */\n    /*public*/ /*final*/ class Detector$3 {\n        /**\n         * <p>Detects a PDF417 Code in an image. Only checks 0 and 180 degree rotations.</p>\n         *\n         * @param image barcode image to decode\n         * @param hints optional hints to detector\n         * @param multiple if true, then the image is searched for multiple codes. If false, then at most one code will\n         * be found and returned\n         * @return {@link PDF417DetectorResult} encapsulating results of detecting a PDF417 code\n         * @throws NotFoundException if no PDF417 Code can be found\n         */\n        static detectMultiple(image, hints, multiple) {\n            // TODO detection improvement, tryHarder could try several different luminance thresholds/blackpoints or even\n            // different binarizers\n            // boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);\n            let bitMatrix = image.getBlackMatrix();\n            let barcodeCoordinates = Detector$3.detect(multiple, bitMatrix);\n            if (!barcodeCoordinates.length) {\n                bitMatrix = bitMatrix.clone();\n                bitMatrix.rotate180();\n                barcodeCoordinates = Detector$3.detect(multiple, bitMatrix);\n            }\n            return new PDF417DetectorResult(bitMatrix, barcodeCoordinates);\n        }\n        /**\n         * Detects PDF417 codes in an image. Only checks 0 degree rotation\n         * @param multiple if true, then the image is searched for multiple codes. If false, then at most one code will\n         * be found and returned\n         * @param bitMatrix bit matrix to detect barcodes in\n         * @return List of ResultPoint arrays containing the coordinates of found barcodes\n         */\n        static detect(multiple, bitMatrix) {\n            const barcodeCoordinates = new Array();\n            let row = 0;\n            let column = 0;\n            let foundBarcodeInRow = false;\n            while (row < bitMatrix.getHeight()) {\n                const vertices = Detector$3.findVertices(bitMatrix, row, column);\n                if (vertices[0] == null && vertices[3] == null) {\n                    if (!foundBarcodeInRow) {\n                        // we didn't find any barcode so that's the end of searching\n                        break;\n                    }\n                    // we didn't find a barcode starting at the given column and row. Try again from the first column and slightly\n                    // below the lowest barcode we found so far.\n                    foundBarcodeInRow = false;\n                    column = 0;\n                    for (const barcodeCoordinate of barcodeCoordinates) {\n                        if (barcodeCoordinate[1] != null) {\n                            row = Math.trunc(Math.max(row, barcodeCoordinate[1].getY()));\n                        }\n                        if (barcodeCoordinate[3] != null) {\n                            row = Math.max(row, Math.trunc(barcodeCoordinate[3].getY()));\n                        }\n                    }\n                    row += Detector$3.ROW_STEP;\n                    continue;\n                }\n                foundBarcodeInRow = true;\n                barcodeCoordinates.push(vertices);\n                if (!multiple) {\n                    break;\n                }\n                // if we didn't find a right row indicator column, then continue the search for the next barcode after the\n                // start pattern of the barcode just found.\n                if (vertices[2] != null) {\n                    column = Math.trunc(vertices[2].getX());\n                    row = Math.trunc(vertices[2].getY());\n                }\n                else {\n                    column = Math.trunc(vertices[4].getX());\n                    row = Math.trunc(vertices[4].getY());\n                }\n            }\n            return barcodeCoordinates;\n        }\n        /**\n         * Locate the vertices and the codewords area of a black blob using the Start\n         * and Stop patterns as locators.\n         *\n         * @param matrix the scanned barcode image.\n         * @return an array containing the vertices:\n         *           vertices[0] x, y top left barcode\n         *           vertices[1] x, y bottom left barcode\n         *           vertices[2] x, y top right barcode\n         *           vertices[3] x, y bottom right barcode\n         *           vertices[4] x, y top left codeword area\n         *           vertices[5] x, y bottom left codeword area\n         *           vertices[6] x, y top right codeword area\n         *           vertices[7] x, y bottom right codeword area\n         */\n        static findVertices(matrix, startRow, startColumn) {\n            const height = matrix.getHeight();\n            const width = matrix.getWidth();\n            // const result = new ResultPoint[8];\n            const result = new Array(8);\n            Detector$3.copyToResult(result, Detector$3.findRowsWithPattern(matrix, height, width, startRow, startColumn, Detector$3.START_PATTERN), Detector$3.INDEXES_START_PATTERN);\n            if (result[4] != null) {\n                startColumn = Math.trunc(result[4].getX());\n                startRow = Math.trunc(result[4].getY());\n            }\n            Detector$3.copyToResult(result, Detector$3.findRowsWithPattern(matrix, height, width, startRow, startColumn, Detector$3.STOP_PATTERN), Detector$3.INDEXES_STOP_PATTERN);\n            return result;\n        }\n        static copyToResult(result, tmpResult, destinationIndexes) {\n            for (let i = 0; i < destinationIndexes.length; i++) {\n                result[destinationIndexes[i]] = tmpResult[i];\n            }\n        }\n        static findRowsWithPattern(matrix, height, width, startRow, startColumn, pattern) {\n            // const result = new ResultPoint[4];\n            const result = new Array(4);\n            let found = false;\n            const counters = new Int32Array(pattern.length);\n            for (; startRow < height; startRow += Detector$3.ROW_STEP) {\n                let loc = Detector$3.findGuardPattern(matrix, startColumn, startRow, width, false, pattern, counters);\n                if (loc != null) {\n                    while (startRow > 0) {\n                        const previousRowLoc = Detector$3.findGuardPattern(matrix, startColumn, --startRow, width, false, pattern, counters);\n                        if (previousRowLoc != null) {\n                            loc = previousRowLoc;\n                        }\n                        else {\n                            startRow++;\n                            break;\n                        }\n                    }\n                    result[0] = new ResultPoint(loc[0], startRow);\n                    result[1] = new ResultPoint(loc[1], startRow);\n                    found = true;\n                    break;\n                }\n            }\n            let stopRow = startRow + 1;\n            // Last row of the current symbol that contains pattern\n            if (found) {\n                let skippedRowCount = 0;\n                let previousRowLoc = Int32Array.from([Math.trunc(result[0].getX()), Math.trunc(result[1].getX())]);\n                for (; stopRow < height; stopRow++) {\n                    const loc = Detector$3.findGuardPattern(matrix, previousRowLoc[0], stopRow, width, false, pattern, counters);\n                    // a found pattern is only considered to belong to the same barcode if the start and end positions\n                    // don't differ too much. Pattern drift should be not bigger than two for consecutive rows. With\n                    // a higher number of skipped rows drift could be larger. To keep it simple for now, we allow a slightly\n                    // larger drift and don't check for skipped rows.\n                    if (loc != null &&\n                        Math.abs(previousRowLoc[0] - loc[0]) < Detector$3.MAX_PATTERN_DRIFT &&\n                        Math.abs(previousRowLoc[1] - loc[1]) < Detector$3.MAX_PATTERN_DRIFT) {\n                        previousRowLoc = loc;\n                        skippedRowCount = 0;\n                    }\n                    else {\n                        if (skippedRowCount > Detector$3.SKIPPED_ROW_COUNT_MAX) {\n                            break;\n                        }\n                        else {\n                            skippedRowCount++;\n                        }\n                    }\n                }\n                stopRow -= skippedRowCount + 1;\n                result[2] = new ResultPoint(previousRowLoc[0], stopRow);\n                result[3] = new ResultPoint(previousRowLoc[1], stopRow);\n            }\n            if (stopRow - startRow < Detector$3.BARCODE_MIN_HEIGHT) {\n                Arrays.fill(result, null);\n            }\n            return result;\n        }\n        /**\n         * @param matrix row of black/white values to search\n         * @param column x position to start search\n         * @param row y position to start search\n         * @param width the number of pixels to search on this row\n         * @param pattern pattern of counts of number of black and white pixels that are\n         *                 being searched for as a pattern\n         * @param counters array of counters, as long as pattern, to re-use\n         * @return start/end horizontal offset of guard pattern, as an array of two ints.\n         */\n        static findGuardPattern(matrix, column, row, width, whiteFirst, pattern, counters) {\n            Arrays.fillWithin(counters, 0, counters.length, 0);\n            let patternStart = column;\n            let pixelDrift = 0;\n            // if there are black pixels left of the current pixel shift to the left, but only for MAX_PIXEL_DRIFT pixels\n            while (matrix.get(patternStart, row) && patternStart > 0 && pixelDrift++ < Detector$3.MAX_PIXEL_DRIFT) {\n                patternStart--;\n            }\n            let x = patternStart;\n            let counterPosition = 0;\n            let patternLength = pattern.length;\n            for (let isWhite = whiteFirst; x < width; x++) {\n                let pixel = matrix.get(x, row);\n                if (pixel !== isWhite) {\n                    counters[counterPosition]++;\n                }\n                else {\n                    if (counterPosition === patternLength - 1) {\n                        if (Detector$3.patternMatchVariance(counters, pattern, Detector$3.MAX_INDIVIDUAL_VARIANCE) < Detector$3.MAX_AVG_VARIANCE) {\n                            return new Int32Array([patternStart, x]);\n                        }\n                        patternStart += counters[0] + counters[1];\n                        System.arraycopy(counters, 2, counters, 0, counterPosition - 1);\n                        counters[counterPosition - 1] = 0;\n                        counters[counterPosition] = 0;\n                        counterPosition--;\n                    }\n                    else {\n                        counterPosition++;\n                    }\n                    counters[counterPosition] = 1;\n                    isWhite = !isWhite;\n                }\n            }\n            if (counterPosition === patternLength - 1 &&\n                Detector$3.patternMatchVariance(counters, pattern, Detector$3.MAX_INDIVIDUAL_VARIANCE) < Detector$3.MAX_AVG_VARIANCE) {\n                return new Int32Array([patternStart, x - 1]);\n            }\n            return null;\n        }\n        /**\n         * Determines how closely a set of observed counts of runs of black/white\n         * values matches a given target pattern. This is reported as the ratio of\n         * the total variance from the expected pattern proportions across all\n         * pattern elements, to the length of the pattern.\n         *\n         * @param counters observed counters\n         * @param pattern expected pattern\n         * @param maxIndividualVariance The most any counter can differ before we give up\n         * @return ratio of total variance between counters and pattern compared to total pattern size\n         */\n        static patternMatchVariance(counters, pattern, maxIndividualVariance) {\n            let numCounters = counters.length;\n            let total = 0;\n            let patternLength = 0;\n            for (let i = 0; i < numCounters; i++) {\n                total += counters[i];\n                patternLength += pattern[i];\n            }\n            if (total < patternLength) {\n                // If we don't even have one pixel per unit of bar width, assume this\n                // is too small to reliably match, so fail:\n                return /*Float.POSITIVE_INFINITY*/ Infinity;\n            }\n            // We're going to fake floating-point math in integers. We just need to use more bits.\n            // Scale up patternLength so that intermediate values below like scaledCounter will have\n            // more \"significant digits\".\n            let unitBarWidth = total / patternLength;\n            maxIndividualVariance *= unitBarWidth;\n            let totalVariance = 0.0;\n            for (let x = 0; x < numCounters; x++) {\n                let counter = counters[x];\n                let scaledPattern = pattern[x] * unitBarWidth;\n                let variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter;\n                if (variance > maxIndividualVariance) {\n                    return /*Float.POSITIVE_INFINITY*/ Infinity;\n                }\n                totalVariance += variance;\n            }\n            return totalVariance / total;\n        }\n    }\n    Detector$3.INDEXES_START_PATTERN = Int32Array.from([0, 4, 1, 5]);\n    Detector$3.INDEXES_STOP_PATTERN = Int32Array.from([6, 2, 7, 3]);\n    Detector$3.MAX_AVG_VARIANCE = 0.42;\n    Detector$3.MAX_INDIVIDUAL_VARIANCE = 0.8;\n    // B S B S B S B S Bar/Space pattern\n    // 11111111 0 1 0 1 0 1 000\n    Detector$3.START_PATTERN = Int32Array.from([8, 1, 1, 1, 1, 1, 1, 3]);\n    // 1111111 0 1 000 1 0 1 00 1\n    Detector$3.STOP_PATTERN = Int32Array.from([7, 1, 1, 3, 1, 1, 1, 2, 1]);\n    Detector$3.MAX_PIXEL_DRIFT = 3;\n    Detector$3.MAX_PATTERN_DRIFT = 5;\n    // if we set the value too low, then we don't detect the correct height of the bar if the start patterns are damaged.\n    // if we set the value too high, then we might detect the start pattern from a neighbor barcode.\n    Detector$3.SKIPPED_ROW_COUNT_MAX = 25;\n    // A PDF471 barcode should have at least 3 rows, with each row being >= 3 times the module width. Therefore it should be at least\n    // 9 pixels tall. To be conservative, we use about half the size to ensure we don't miss it.\n    Detector$3.ROW_STEP = 5;\n    Detector$3.BARCODE_MIN_HEIGHT = 10;\n\n    /*\n    * Copyright 2012 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /**\n     * @author Sean Owen\n     * @see com.google.zxing.common.reedsolomon.GenericGFPoly\n     */\n    /*final*/ class ModulusPoly {\n        constructor(field, coefficients) {\n            if (coefficients.length === 0) {\n                throw new IllegalArgumentException();\n            }\n            this.field = field;\n            let coefficientsLength = /*int*/ coefficients.length;\n            if (coefficientsLength > 1 && coefficients[0] === 0) {\n                // Leading term must be non-zero for anything except the constant polynomial \"0\"\n                let firstNonZero = /*int*/ 1;\n                while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) {\n                    firstNonZero++;\n                }\n                if (firstNonZero === coefficientsLength) {\n                    this.coefficients = new Int32Array([0]);\n                }\n                else {\n                    this.coefficients = new Int32Array(coefficientsLength - firstNonZero);\n                    System.arraycopy(coefficients, firstNonZero, this.coefficients, 0, this.coefficients.length);\n                }\n            }\n            else {\n                this.coefficients = coefficients;\n            }\n        }\n        getCoefficients() {\n            return this.coefficients;\n        }\n        /**\n         * @return degree of this polynomial\n         */\n        getDegree() {\n            return this.coefficients.length - 1;\n        }\n        /**\n         * @return true iff this polynomial is the monomial \"0\"\n         */\n        isZero() {\n            return this.coefficients[0] === 0;\n        }\n        /**\n         * @return coefficient of x^degree term in this polynomial\n         */\n        getCoefficient(degree) {\n            return this.coefficients[this.coefficients.length - 1 - degree];\n        }\n        /**\n         * @return evaluation of this polynomial at a given point\n         */\n        evaluateAt(a) {\n            if (a === 0) {\n                // Just return the x^0 coefficient\n                return this.getCoefficient(0);\n            }\n            if (a === 1) {\n                // Just the sum of the coefficients\n                let sum = /*int*/ 0;\n                for (let coefficient /*int*/ of this.coefficients) {\n                    sum = this.field.add(sum, coefficient);\n                }\n                return sum;\n            }\n            let result = /*int*/ this.coefficients[0];\n            let size = /*int*/ this.coefficients.length;\n            for (let i /*int*/ = 1; i < size; i++) {\n                result = this.field.add(this.field.multiply(a, result), this.coefficients[i]);\n            }\n            return result;\n        }\n        add(other) {\n            if (!this.field.equals(other.field)) {\n                throw new IllegalArgumentException('ModulusPolys do not have same ModulusGF field');\n            }\n            if (this.isZero()) {\n                return other;\n            }\n            if (other.isZero()) {\n                return this;\n            }\n            let smallerCoefficients = this.coefficients;\n            let largerCoefficients = other.coefficients;\n            if (smallerCoefficients.length > largerCoefficients.length) {\n                let temp = smallerCoefficients;\n                smallerCoefficients = largerCoefficients;\n                largerCoefficients = temp;\n            }\n            let sumDiff = new Int32Array(largerCoefficients.length);\n            let lengthDiff = /*int*/ largerCoefficients.length - smallerCoefficients.length;\n            // Copy high-order terms only found in higher-degree polynomial's coefficients\n            System.arraycopy(largerCoefficients, 0, sumDiff, 0, lengthDiff);\n            for (let i /*int*/ = lengthDiff; i < largerCoefficients.length; i++) {\n                sumDiff[i] = this.field.add(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);\n            }\n            return new ModulusPoly(this.field, sumDiff);\n        }\n        subtract(other) {\n            if (!this.field.equals(other.field)) {\n                throw new IllegalArgumentException('ModulusPolys do not have same ModulusGF field');\n            }\n            if (other.isZero()) {\n                return this;\n            }\n            return this.add(other.negative());\n        }\n        multiply(other) {\n            if (other instanceof ModulusPoly) {\n                return this.multiplyOther(other);\n            }\n            return this.multiplyScalar(other);\n        }\n        multiplyOther(other) {\n            if (!this.field.equals(other.field)) {\n                throw new IllegalArgumentException('ModulusPolys do not have same ModulusGF field');\n            }\n            if (this.isZero() || other.isZero()) {\n                // return this.field.getZero();\n                return new ModulusPoly(this.field, new Int32Array([0]));\n            }\n            let aCoefficients = this.coefficients;\n            let aLength = /*int*/ aCoefficients.length;\n            let bCoefficients = other.coefficients;\n            let bLength = /*int*/ bCoefficients.length;\n            let product = new Int32Array(aLength + bLength - 1);\n            for (let i /*int*/ = 0; i < aLength; i++) {\n                let aCoeff = /*int*/ aCoefficients[i];\n                for (let j /*int*/ = 0; j < bLength; j++) {\n                    product[i + j] = this.field.add(product[i + j], this.field.multiply(aCoeff, bCoefficients[j]));\n                }\n            }\n            return new ModulusPoly(this.field, product);\n        }\n        negative() {\n            let size = /*int*/ this.coefficients.length;\n            let negativeCoefficients = new Int32Array(size);\n            for (let i /*int*/ = 0; i < size; i++) {\n                negativeCoefficients[i] = this.field.subtract(0, this.coefficients[i]);\n            }\n            return new ModulusPoly(this.field, negativeCoefficients);\n        }\n        multiplyScalar(scalar) {\n            if (scalar === 0) {\n                return new ModulusPoly(this.field, new Int32Array([0]));\n            }\n            if (scalar === 1) {\n                return this;\n            }\n            let size = /*int*/ this.coefficients.length;\n            let product = new Int32Array(size);\n            for (let i /*int*/ = 0; i < size; i++) {\n                product[i] = this.field.multiply(this.coefficients[i], scalar);\n            }\n            return new ModulusPoly(this.field, product);\n        }\n        multiplyByMonomial(degree, coefficient) {\n            if (degree < 0) {\n                throw new IllegalArgumentException();\n            }\n            if (coefficient === 0) {\n                return new ModulusPoly(this.field, new Int32Array([0]));\n            }\n            let size = /*int*/ this.coefficients.length;\n            let product = new Int32Array(size + degree);\n            for (let i /*int*/ = 0; i < size; i++) {\n                product[i] = this.field.multiply(this.coefficients[i], coefficient);\n            }\n            return new ModulusPoly(this.field, product);\n        }\n        /*\n        ModulusPoly[] divide(other: ModulusPoly) {\n          if (!field.equals(other.field)) {\n            throw new IllegalArgumentException(\"ModulusPolys do not have same ModulusGF field\");\n          }\n          if (other.isZero()) {\n            throw new IllegalArgumentException(\"Divide by 0\");\n          }\n      \n          let quotient: ModulusPoly = field.getZero();\n          let remainder: ModulusPoly = this;\n      \n          let denominatorLeadingTerm: /*int/ number = other.getCoefficient(other.getDegree());\n          let inverseDenominatorLeadingTerm: /*int/ number = field.inverse(denominatorLeadingTerm);\n      \n          while (remainder.getDegree() >= other.getDegree() && !remainder.isZero()) {\n            let degreeDifference: /*int/ number = remainder.getDegree() - other.getDegree();\n            let scale: /*int/ number = field.multiply(remainder.getCoefficient(remainder.getDegree()), inverseDenominatorLeadingTerm);\n            let term: ModulusPoly = other.multiplyByMonomial(degreeDifference, scale);\n            let iterationQuotient: ModulusPoly = field.buildMonomial(degreeDifference, scale);\n            quotient = quotient.add(iterationQuotient);\n            remainder = remainder.subtract(term);\n          }\n      \n          return new ModulusPoly[] { quotient, remainder };\n        }\n        */\n        // @Override\n        toString() {\n            let result = new StringBuilder( /*8 * this.getDegree()*/); // dynamic string size in JS\n            for (let degree /*int*/ = this.getDegree(); degree >= 0; degree--) {\n                let coefficient = /*int*/ this.getCoefficient(degree);\n                if (coefficient !== 0) {\n                    if (coefficient < 0) {\n                        result.append(' - ');\n                        coefficient = -coefficient;\n                    }\n                    else {\n                        if (result.length() > 0) {\n                            result.append(' + ');\n                        }\n                    }\n                    if (degree === 0 || coefficient !== 1) {\n                        result.append(coefficient);\n                    }\n                    if (degree !== 0) {\n                        if (degree === 1) {\n                            result.append('x');\n                        }\n                        else {\n                            result.append('x^');\n                            result.append(degree);\n                        }\n                    }\n                }\n            }\n            return result.toString();\n        }\n    }\n\n    class ModulusBase {\n        add(a, b) {\n            return (a + b) % this.modulus;\n        }\n        subtract(a, b) {\n            return (this.modulus + a - b) % this.modulus;\n        }\n        exp(a) {\n            return this.expTable[a];\n        }\n        log(a) {\n            if (a === 0) {\n                throw new IllegalArgumentException();\n            }\n            return this.logTable[a];\n        }\n        inverse(a) {\n            if (a === 0) {\n                throw new ArithmeticException();\n            }\n            return this.expTable[this.modulus - this.logTable[a] - 1];\n        }\n        multiply(a, b) {\n            if (a === 0 || b === 0) {\n                return 0;\n            }\n            return this.expTable[(this.logTable[a] + this.logTable[b]) % (this.modulus - 1)];\n        }\n        getSize() {\n            return this.modulus;\n        }\n        equals(o) {\n            return o === this;\n        }\n    }\n\n    /*\n     * Copyright 2012 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>A field based on powers of a generator integer, modulo some modulus.</p>\n     *\n     * @author Sean Owen\n     * @see com.google.zxing.common.reedsolomon.GenericGF\n     */\n    /*public final*/ class ModulusGF extends ModulusBase {\n        // private /*final*/ modulus: /*int*/ number;\n        constructor(modulus, generator) {\n            super();\n            this.modulus = modulus;\n            this.expTable = new Int32Array(modulus);\n            this.logTable = new Int32Array(modulus);\n            let x = /*int*/ 1;\n            for (let i /*int*/ = 0; i < modulus; i++) {\n                this.expTable[i] = x;\n                x = (x * generator) % modulus;\n            }\n            for (let i /*int*/ = 0; i < modulus - 1; i++) {\n                this.logTable[this.expTable[i]] = i;\n            }\n            // logTable[0] == 0 but this should never be used\n            this.zero = new ModulusPoly(this, new Int32Array([0]));\n            this.one = new ModulusPoly(this, new Int32Array([1]));\n        }\n        getZero() {\n            return this.zero;\n        }\n        getOne() {\n            return this.one;\n        }\n        buildMonomial(degree, coefficient) {\n            if (degree < 0) {\n                throw new IllegalArgumentException();\n            }\n            if (coefficient === 0) {\n                return this.zero;\n            }\n            let coefficients = new Int32Array(degree + 1);\n            coefficients[0] = coefficient;\n            return new ModulusPoly(this, coefficients);\n        }\n    }\n    ModulusGF.PDF417_GF = new ModulusGF(PDF417Common.NUMBER_OF_CODEWORDS, 3);\n\n    /*\n    * Copyright 2012 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /**\n     * <p>PDF417 error correction implementation.</p>\n     *\n     * <p>This <a href=\"http://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction#Example\">example</a>\n     * is quite useful in understanding the algorithm.</p>\n     *\n     * @author Sean Owen\n     * @see com.google.zxing.common.reedsolomon.ReedSolomonDecoder\n     */\n    /*public final*/ class ErrorCorrection {\n        constructor() {\n            this.field = ModulusGF.PDF417_GF;\n        }\n        /**\n         * @param received received codewords\n         * @param numECCodewords number of those codewords used for EC\n         * @param erasures location of erasures\n         * @return number of errors\n         * @throws ChecksumException if errors cannot be corrected, maybe because of too many errors\n         */\n        decode(received, numECCodewords, erasures) {\n            let poly = new ModulusPoly(this.field, received);\n            let S = new Int32Array(numECCodewords);\n            let error = false;\n            for (let i /*int*/ = numECCodewords; i > 0; i--) {\n                let evaluation = poly.evaluateAt(this.field.exp(i));\n                S[numECCodewords - i] = evaluation;\n                if (evaluation !== 0) {\n                    error = true;\n                }\n            }\n            if (!error) {\n                return 0;\n            }\n            let knownErrors = this.field.getOne();\n            if (erasures != null) {\n                for (const erasure of erasures) {\n                    let b = this.field.exp(received.length - 1 - erasure);\n                    // Add (1 - bx) term:\n                    let term = new ModulusPoly(this.field, new Int32Array([this.field.subtract(0, b), 1]));\n                    knownErrors = knownErrors.multiply(term);\n                }\n            }\n            let syndrome = new ModulusPoly(this.field, S);\n            // syndrome = syndrome.multiply(knownErrors);\n            let sigmaOmega = this.runEuclideanAlgorithm(this.field.buildMonomial(numECCodewords, 1), syndrome, numECCodewords);\n            let sigma = sigmaOmega[0];\n            let omega = sigmaOmega[1];\n            // sigma = sigma.multiply(knownErrors);\n            let errorLocations = this.findErrorLocations(sigma);\n            let errorMagnitudes = this.findErrorMagnitudes(omega, sigma, errorLocations);\n            for (let i /*int*/ = 0; i < errorLocations.length; i++) {\n                let position = received.length - 1 - this.field.log(errorLocations[i]);\n                if (position < 0) {\n                    throw ChecksumException.getChecksumInstance();\n                }\n                received[position] = this.field.subtract(received[position], errorMagnitudes[i]);\n            }\n            return errorLocations.length;\n        }\n        /**\n         *\n         * @param ModulusPoly\n         * @param a\n         * @param ModulusPoly\n         * @param b\n         * @param int\n         * @param R\n         * @throws ChecksumException\n         */\n        runEuclideanAlgorithm(a, b, R) {\n            // Assume a's degree is >= b's\n            if (a.getDegree() < b.getDegree()) {\n                let temp = a;\n                a = b;\n                b = temp;\n            }\n            let rLast = a;\n            let r = b;\n            let tLast = this.field.getZero();\n            let t = this.field.getOne();\n            // Run Euclidean algorithm until r's degree is less than R/2\n            while (r.getDegree() >= Math.round(R / 2)) {\n                let rLastLast = rLast;\n                let tLastLast = tLast;\n                rLast = r;\n                tLast = t;\n                // Divide rLastLast by rLast, with quotient in q and remainder in r\n                if (rLast.isZero()) {\n                    // Oops, Euclidean algorithm already terminated?\n                    throw ChecksumException.getChecksumInstance();\n                }\n                r = rLastLast;\n                let q = this.field.getZero();\n                let denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree());\n                let dltInverse = this.field.inverse(denominatorLeadingTerm);\n                while (r.getDegree() >= rLast.getDegree() && !r.isZero()) {\n                    let degreeDiff = r.getDegree() - rLast.getDegree();\n                    let scale = this.field.multiply(r.getCoefficient(r.getDegree()), dltInverse);\n                    q = q.add(this.field.buildMonomial(degreeDiff, scale));\n                    r = r.subtract(rLast.multiplyByMonomial(degreeDiff, scale));\n                }\n                t = q.multiply(tLast).subtract(tLastLast).negative();\n            }\n            let sigmaTildeAtZero = t.getCoefficient(0);\n            if (sigmaTildeAtZero === 0) {\n                throw ChecksumException.getChecksumInstance();\n            }\n            let inverse = this.field.inverse(sigmaTildeAtZero);\n            let sigma = t.multiply(inverse);\n            let omega = r.multiply(inverse);\n            return [sigma, omega];\n        }\n        /**\n         *\n         * @param errorLocator\n         * @throws ChecksumException\n         */\n        findErrorLocations(errorLocator) {\n            // This is a direct application of Chien's search\n            let numErrors = errorLocator.getDegree();\n            let result = new Int32Array(numErrors);\n            let e = 0;\n            for (let i /*int*/ = 1; i < this.field.getSize() && e < numErrors; i++) {\n                if (errorLocator.evaluateAt(i) === 0) {\n                    result[e] = this.field.inverse(i);\n                    e++;\n                }\n            }\n            if (e !== numErrors) {\n                throw ChecksumException.getChecksumInstance();\n            }\n            return result;\n        }\n        findErrorMagnitudes(errorEvaluator, errorLocator, errorLocations) {\n            let errorLocatorDegree = errorLocator.getDegree();\n            let formalDerivativeCoefficients = new Int32Array(errorLocatorDegree);\n            for (let i /*int*/ = 1; i <= errorLocatorDegree; i++) {\n                formalDerivativeCoefficients[errorLocatorDegree - i] =\n                    this.field.multiply(i, errorLocator.getCoefficient(i));\n            }\n            let formalDerivative = new ModulusPoly(this.field, formalDerivativeCoefficients);\n            // This is directly applying Forney's Formula\n            let s = errorLocations.length;\n            let result = new Int32Array(s);\n            for (let i /*int*/ = 0; i < s; i++) {\n                let xiInverse = this.field.inverse(errorLocations[i]);\n                let numerator = this.field.subtract(0, errorEvaluator.evaluateAt(xiInverse));\n                let denominator = this.field.inverse(formalDerivative.evaluateAt(xiInverse));\n                result[i] = this.field.multiply(numerator, denominator);\n            }\n            return result;\n        }\n    }\n\n    /*\n    * Copyright 2013 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /**\n     * @author Guenther Grau\n     */\n    /*final*/ class BoundingBox {\n        constructor(image, topLeft, bottomLeft, topRight, bottomRight) {\n            if (image instanceof BoundingBox) {\n                this.constructor_2(image);\n            }\n            else {\n                this.constructor_1(image, topLeft, bottomLeft, topRight, bottomRight);\n            }\n        }\n        /**\n         *\n         * @param image\n         * @param topLeft\n         * @param bottomLeft\n         * @param topRight\n         * @param bottomRight\n         *\n         * @throws NotFoundException\n         */\n        constructor_1(image, topLeft, bottomLeft, topRight, bottomRight) {\n            const leftUnspecified = topLeft == null || bottomLeft == null;\n            const rightUnspecified = topRight == null || bottomRight == null;\n            if (leftUnspecified && rightUnspecified) {\n                throw new NotFoundException();\n            }\n            if (leftUnspecified) {\n                topLeft = new ResultPoint(0, topRight.getY());\n                bottomLeft = new ResultPoint(0, bottomRight.getY());\n            }\n            else if (rightUnspecified) {\n                topRight = new ResultPoint(image.getWidth() - 1, topLeft.getY());\n                bottomRight = new ResultPoint(image.getWidth() - 1, bottomLeft.getY());\n            }\n            this.image = image;\n            this.topLeft = topLeft;\n            this.bottomLeft = bottomLeft;\n            this.topRight = topRight;\n            this.bottomRight = bottomRight;\n            this.minX = Math.trunc(Math.min(topLeft.getX(), bottomLeft.getX()));\n            this.maxX = Math.trunc(Math.max(topRight.getX(), bottomRight.getX()));\n            this.minY = Math.trunc(Math.min(topLeft.getY(), topRight.getY()));\n            this.maxY = Math.trunc(Math.max(bottomLeft.getY(), bottomRight.getY()));\n        }\n        constructor_2(boundingBox) {\n            this.image = boundingBox.image;\n            this.topLeft = boundingBox.getTopLeft();\n            this.bottomLeft = boundingBox.getBottomLeft();\n            this.topRight = boundingBox.getTopRight();\n            this.bottomRight = boundingBox.getBottomRight();\n            this.minX = boundingBox.getMinX();\n            this.maxX = boundingBox.getMaxX();\n            this.minY = boundingBox.getMinY();\n            this.maxY = boundingBox.getMaxY();\n        }\n        /**\n         * @throws NotFoundException\n         */\n        static merge(leftBox, rightBox) {\n            if (leftBox == null) {\n                return rightBox;\n            }\n            if (rightBox == null) {\n                return leftBox;\n            }\n            return new BoundingBox(leftBox.image, leftBox.topLeft, leftBox.bottomLeft, rightBox.topRight, rightBox.bottomRight);\n        }\n        /**\n         * @throws NotFoundException\n         */\n        addMissingRows(missingStartRows, missingEndRows, isLeft) {\n            let newTopLeft = this.topLeft;\n            let newBottomLeft = this.bottomLeft;\n            let newTopRight = this.topRight;\n            let newBottomRight = this.bottomRight;\n            if (missingStartRows > 0) {\n                let top = isLeft ? this.topLeft : this.topRight;\n                let newMinY = Math.trunc(top.getY() - missingStartRows);\n                if (newMinY < 0) {\n                    newMinY = 0;\n                }\n                let newTop = new ResultPoint(top.getX(), newMinY);\n                if (isLeft) {\n                    newTopLeft = newTop;\n                }\n                else {\n                    newTopRight = newTop;\n                }\n            }\n            if (missingEndRows > 0) {\n                let bottom = isLeft ? this.bottomLeft : this.bottomRight;\n                let newMaxY = Math.trunc(bottom.getY() + missingEndRows);\n                if (newMaxY >= this.image.getHeight()) {\n                    newMaxY = this.image.getHeight() - 1;\n                }\n                let newBottom = new ResultPoint(bottom.getX(), newMaxY);\n                if (isLeft) {\n                    newBottomLeft = newBottom;\n                }\n                else {\n                    newBottomRight = newBottom;\n                }\n            }\n            return new BoundingBox(this.image, newTopLeft, newBottomLeft, newTopRight, newBottomRight);\n        }\n        getMinX() {\n            return this.minX;\n        }\n        getMaxX() {\n            return this.maxX;\n        }\n        getMinY() {\n            return this.minY;\n        }\n        getMaxY() {\n            return this.maxY;\n        }\n        getTopLeft() {\n            return this.topLeft;\n        }\n        getTopRight() {\n            return this.topRight;\n        }\n        getBottomLeft() {\n            return this.bottomLeft;\n        }\n        getBottomRight() {\n            return this.bottomRight;\n        }\n    }\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    // package com.google.zxing.pdf417.decoder;\n    /**\n     * @author Guenther Grau\n     */\n    /*final*/ class BarcodeMetadata {\n        constructor(columnCount, rowCountUpperPart, rowCountLowerPart, errorCorrectionLevel) {\n            this.columnCount = columnCount;\n            this.errorCorrectionLevel = errorCorrectionLevel;\n            this.rowCountUpperPart = rowCountUpperPart;\n            this.rowCountLowerPart = rowCountLowerPart;\n            this.rowCount = rowCountUpperPart + rowCountLowerPart;\n        }\n        getColumnCount() {\n            return this.columnCount;\n        }\n        getErrorCorrectionLevel() {\n            return this.errorCorrectionLevel;\n        }\n        getRowCount() {\n            return this.rowCount;\n        }\n        getRowCountUpperPart() {\n            return this.rowCountUpperPart;\n        }\n        getRowCountLowerPart() {\n            return this.rowCountLowerPart;\n        }\n    }\n\n    /**\n     * Java Formatter class polyfill that works in the JS way.\n     */\n    class Formatter {\n        constructor() {\n            this.buffer = '';\n        }\n        /**\n         *\n         * @see https://stackoverflow.com/a/13439711/4367683\n         *\n         * @param str\n         * @param arr\n         */\n        static form(str, arr) {\n            let i = -1;\n            function callback(exp, p0, p1, p2, p3, p4) {\n                if (exp === '%%')\n                    return '%';\n                if (arr[++i] === undefined)\n                    return undefined;\n                exp = p2 ? parseInt(p2.substr(1)) : undefined;\n                let base = p3 ? parseInt(p3.substr(1)) : undefined;\n                let val;\n                switch (p4) {\n                    case 's':\n                        val = arr[i];\n                        break;\n                    case 'c':\n                        val = arr[i][0];\n                        break;\n                    case 'f':\n                        val = parseFloat(arr[i]).toFixed(exp);\n                        break;\n                    case 'p':\n                        val = parseFloat(arr[i]).toPrecision(exp);\n                        break;\n                    case 'e':\n                        val = parseFloat(arr[i]).toExponential(exp);\n                        break;\n                    case 'x':\n                        val = parseInt(arr[i]).toString(base ? base : 16);\n                        break;\n                    case 'd':\n                        val = parseFloat(parseInt(arr[i], base ? base : 10).toPrecision(exp)).toFixed(0);\n                        break;\n                }\n                val = typeof val === 'object' ? JSON.stringify(val) : (+val).toString(base);\n                let size = parseInt(p1); /* padding size */\n                let ch = p1 && (p1[0] + '') === '0' ? '0' : ' '; /* isnull? */\n                while (val.length < size)\n                    val = p0 !== undefined ? val + ch : ch + val; /* isminus? */\n                return val;\n            }\n            let regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g;\n            return str.replace(regex, callback);\n        }\n        /**\n         *\n         * @param append The new string to append.\n         * @param args Argumets values to be formated.\n         */\n        format(append, ...args) {\n            this.buffer += Formatter.form(append, args);\n        }\n        /**\n         * Returns the Formatter string value.\n         */\n        toString() {\n            return this.buffer;\n        }\n    }\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * @author Guenther Grau\n     */\n    class DetectionResultColumn {\n        constructor(boundingBox) {\n            this.boundingBox = new BoundingBox(boundingBox);\n            // this.codewords = new Codeword[boundingBox.getMaxY() - boundingBox.getMinY() + 1];\n            this.codewords = new Array(boundingBox.getMaxY() - boundingBox.getMinY() + 1);\n        }\n        /*final*/ getCodewordNearby(imageRow) {\n            let codeword = this.getCodeword(imageRow);\n            if (codeword != null) {\n                return codeword;\n            }\n            for (let i = 1; i < DetectionResultColumn.MAX_NEARBY_DISTANCE; i++) {\n                let nearImageRow = this.imageRowToCodewordIndex(imageRow) - i;\n                if (nearImageRow >= 0) {\n                    codeword = this.codewords[nearImageRow];\n                    if (codeword != null) {\n                        return codeword;\n                    }\n                }\n                nearImageRow = this.imageRowToCodewordIndex(imageRow) + i;\n                if (nearImageRow < this.codewords.length) {\n                    codeword = this.codewords[nearImageRow];\n                    if (codeword != null) {\n                        return codeword;\n                    }\n                }\n            }\n            return null;\n        }\n        /*final int*/ imageRowToCodewordIndex(imageRow) {\n            return imageRow - this.boundingBox.getMinY();\n        }\n        /*final void*/ setCodeword(imageRow, codeword) {\n            this.codewords[this.imageRowToCodewordIndex(imageRow)] = codeword;\n        }\n        /*final*/ getCodeword(imageRow) {\n            return this.codewords[this.imageRowToCodewordIndex(imageRow)];\n        }\n        /*final*/ getBoundingBox() {\n            return this.boundingBox;\n        }\n        /*final*/ getCodewords() {\n            return this.codewords;\n        }\n        // @Override\n        toString() {\n            const formatter = new Formatter();\n            let row = 0;\n            for (const codeword of this.codewords) {\n                if (codeword == null) {\n                    formatter.format('%3d:    |   %n', row++);\n                    continue;\n                }\n                formatter.format('%3d: %3d|%3d%n', row++, codeword.getRowNumber(), codeword.getValue());\n            }\n            return formatter.toString();\n        }\n    }\n    DetectionResultColumn.MAX_NEARBY_DISTANCE = 5;\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    // import java.util.ArrayList;\n    // import java.util.Collection;\n    // import java.util.HashMap;\n    // import java.util.Map;\n    // import java.util.Map.Entry;\n    /**\n     * @author Guenther Grau\n     */\n    /*final*/ class BarcodeValue {\n        constructor() {\n            this.values = new Map();\n        }\n        /**\n         * Add an occurrence of a value\n         */\n        setValue(value) {\n            value = Math.trunc(value);\n            let confidence = this.values.get(value);\n            if (confidence == null) {\n                confidence = 0;\n            }\n            confidence++;\n            this.values.set(value, confidence);\n        }\n        /**\n         * Determines the maximum occurrence of a set value and returns all values which were set with this occurrence.\n         * @return an array of int, containing the values with the highest occurrence, or null, if no value was set\n         */\n        getValue() {\n            let maxConfidence = -1;\n            let result = new Array();\n            for (const [key, value] of this.values.entries()) {\n                const entry = {\n                    getKey: () => key,\n                    getValue: () => value,\n                };\n                if (entry.getValue() > maxConfidence) {\n                    maxConfidence = entry.getValue();\n                    result = [];\n                    result.push(entry.getKey());\n                }\n                else if (entry.getValue() === maxConfidence) {\n                    result.push(entry.getKey());\n                }\n            }\n            return PDF417Common.toIntArray(result);\n        }\n        getConfidence(value) {\n            return this.values.get(value);\n        }\n    }\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * @author Guenther Grau\n     */\n    /*final*/ class DetectionResultRowIndicatorColumn extends DetectionResultColumn {\n        constructor(boundingBox, isLeft) {\n            super(boundingBox);\n            this._isLeft = isLeft;\n        }\n        setRowNumbers() {\n            for (let codeword /*Codeword*/ of this.getCodewords()) {\n                if (codeword != null) {\n                    codeword.setRowNumberAsRowIndicatorColumn();\n                }\n            }\n        }\n        // TODO implement properly\n        // TODO maybe we should add missing codewords to store the correct row number to make\n        // finding row numbers for other columns easier\n        // use row height count to make detection of invalid row numbers more reliable\n        adjustCompleteIndicatorColumnRowNumbers(barcodeMetadata) {\n            let codewords = this.getCodewords();\n            this.setRowNumbers();\n            this.removeIncorrectCodewords(codewords, barcodeMetadata);\n            let boundingBox = this.getBoundingBox();\n            let top = this._isLeft ? boundingBox.getTopLeft() : boundingBox.getTopRight();\n            let bottom = this._isLeft ? boundingBox.getBottomLeft() : boundingBox.getBottomRight();\n            let firstRow = this.imageRowToCodewordIndex(Math.trunc(top.getY()));\n            let lastRow = this.imageRowToCodewordIndex(Math.trunc(bottom.getY()));\n            // We need to be careful using the average row height. Barcode could be skewed so that we have smaller and\n            // taller rows\n            // float averageRowHeight = (lastRow - firstRow) / /*(float)*/ barcodeMetadata.getRowCount();\n            let barcodeRow = -1;\n            let maxRowHeight = 1;\n            let currentRowHeight = 0;\n            for (let codewordsRow /*int*/ = firstRow; codewordsRow < lastRow; codewordsRow++) {\n                if (codewords[codewordsRow] == null) {\n                    continue;\n                }\n                let codeword = codewords[codewordsRow];\n                //      float expectedRowNumber = (codewordsRow - firstRow) / averageRowHeight;\n                //      if (Math.abs(codeword.getRowNumber() - expectedRowNumber) > 2) {\n                //        SimpleLog.log(LEVEL.WARNING,\n                //            \"Removing codeword, rowNumberSkew too high, codeword[\" + codewordsRow + \"]: Expected Row: \" +\n                //                expectedRowNumber + \", RealRow: \" + codeword.getRowNumber() + \", value: \" + codeword.getValue());\n                //        codewords[codewordsRow] = null;\n                //      }\n                let rowDifference = codeword.getRowNumber() - barcodeRow;\n                // TODO improve handling with case where first row indicator doesn't start with 0\n                if (rowDifference === 0) {\n                    currentRowHeight++;\n                }\n                else if (rowDifference === 1) {\n                    maxRowHeight = Math.max(maxRowHeight, currentRowHeight);\n                    currentRowHeight = 1;\n                    barcodeRow = codeword.getRowNumber();\n                }\n                else if (rowDifference < 0 ||\n                    codeword.getRowNumber() >= barcodeMetadata.getRowCount() ||\n                    rowDifference > codewordsRow) {\n                    codewords[codewordsRow] = null;\n                }\n                else {\n                    let checkedRows;\n                    if (maxRowHeight > 2) {\n                        checkedRows = (maxRowHeight - 2) * rowDifference;\n                    }\n                    else {\n                        checkedRows = rowDifference;\n                    }\n                    let closePreviousCodewordFound = checkedRows >= codewordsRow;\n                    for (let i /*int*/ = 1; i <= checkedRows && !closePreviousCodewordFound; i++) {\n                        // there must be (height * rowDifference) number of codewords missing. For now we assume height = 1.\n                        // This should hopefully get rid of most problems already.\n                        closePreviousCodewordFound = codewords[codewordsRow - i] != null;\n                    }\n                    if (closePreviousCodewordFound) {\n                        codewords[codewordsRow] = null;\n                    }\n                    else {\n                        barcodeRow = codeword.getRowNumber();\n                        currentRowHeight = 1;\n                    }\n                }\n            }\n            // return (int) (averageRowHeight + 0.5);\n        }\n        getRowHeights() {\n            let barcodeMetadata = this.getBarcodeMetadata();\n            if (barcodeMetadata == null) {\n                return null;\n            }\n            this.adjustIncompleteIndicatorColumnRowNumbers(barcodeMetadata);\n            let result = new Int32Array(barcodeMetadata.getRowCount());\n            for (let codeword /*Codeword*/ of this.getCodewords()) {\n                if (codeword != null) {\n                    let rowNumber = codeword.getRowNumber();\n                    if (rowNumber >= result.length) {\n                        // We have more rows than the barcode metadata allows for, ignore them.\n                        continue;\n                    }\n                    result[rowNumber]++;\n                } // else throw exception?\n            }\n            return result;\n        }\n        // TODO maybe we should add missing codewords to store the correct row number to make\n        // finding row numbers for other columns easier\n        // use row height count to make detection of invalid row numbers more reliable\n        adjustIncompleteIndicatorColumnRowNumbers(barcodeMetadata) {\n            let boundingBox = this.getBoundingBox();\n            let top = this._isLeft ? boundingBox.getTopLeft() : boundingBox.getTopRight();\n            let bottom = this._isLeft ? boundingBox.getBottomLeft() : boundingBox.getBottomRight();\n            let firstRow = this.imageRowToCodewordIndex(Math.trunc(top.getY()));\n            let lastRow = this.imageRowToCodewordIndex(Math.trunc(bottom.getY()));\n            // float averageRowHeight = (lastRow - firstRow) / /*(float)*/ barcodeMetadata.getRowCount();\n            let codewords = this.getCodewords();\n            let barcodeRow = -1;\n            for (let codewordsRow /*int*/ = firstRow; codewordsRow < lastRow; codewordsRow++) {\n                if (codewords[codewordsRow] == null) {\n                    continue;\n                }\n                let codeword = codewords[codewordsRow];\n                codeword.setRowNumberAsRowIndicatorColumn();\n                let rowDifference = codeword.getRowNumber() - barcodeRow;\n                // TODO improve handling with case where first row indicator doesn't start with 0\n                if (rowDifference === 0) ;\n                else if (rowDifference === 1) {\n                    barcodeRow = codeword.getRowNumber();\n                }\n                else if (codeword.getRowNumber() >= barcodeMetadata.getRowCount()) {\n                    codewords[codewordsRow] = null;\n                }\n                else {\n                    barcodeRow = codeword.getRowNumber();\n                }\n            }\n            // return (int) (averageRowHeight + 0.5);\n        }\n        getBarcodeMetadata() {\n            let codewords = this.getCodewords();\n            let barcodeColumnCount = new BarcodeValue();\n            let barcodeRowCountUpperPart = new BarcodeValue();\n            let barcodeRowCountLowerPart = new BarcodeValue();\n            let barcodeECLevel = new BarcodeValue();\n            for (let codeword /*Codeword*/ of codewords) {\n                if (codeword == null) {\n                    continue;\n                }\n                codeword.setRowNumberAsRowIndicatorColumn();\n                let rowIndicatorValue = codeword.getValue() % 30;\n                let codewordRowNumber = codeword.getRowNumber();\n                if (!this._isLeft) {\n                    codewordRowNumber += 2;\n                }\n                switch (codewordRowNumber % 3) {\n                    case 0:\n                        barcodeRowCountUpperPart.setValue(rowIndicatorValue * 3 + 1);\n                        break;\n                    case 1:\n                        barcodeECLevel.setValue(rowIndicatorValue / 3);\n                        barcodeRowCountLowerPart.setValue(rowIndicatorValue % 3);\n                        break;\n                    case 2:\n                        barcodeColumnCount.setValue(rowIndicatorValue + 1);\n                        break;\n                }\n            }\n            // Maybe we should check if we have ambiguous values?\n            if ((barcodeColumnCount.getValue().length === 0) ||\n                (barcodeRowCountUpperPart.getValue().length === 0) ||\n                (barcodeRowCountLowerPart.getValue().length === 0) ||\n                (barcodeECLevel.getValue().length === 0) ||\n                barcodeColumnCount.getValue()[0] < 1 ||\n                barcodeRowCountUpperPart.getValue()[0] + barcodeRowCountLowerPart.getValue()[0] < PDF417Common.MIN_ROWS_IN_BARCODE ||\n                barcodeRowCountUpperPart.getValue()[0] + barcodeRowCountLowerPart.getValue()[0] > PDF417Common.MAX_ROWS_IN_BARCODE) {\n                return null;\n            }\n            let barcodeMetadata = new BarcodeMetadata(barcodeColumnCount.getValue()[0], barcodeRowCountUpperPart.getValue()[0], barcodeRowCountLowerPart.getValue()[0], barcodeECLevel.getValue()[0]);\n            this.removeIncorrectCodewords(codewords, barcodeMetadata);\n            return barcodeMetadata;\n        }\n        removeIncorrectCodewords(codewords, barcodeMetadata) {\n            // Remove codewords which do not match the metadata\n            // TODO Maybe we should keep the incorrect codewords for the start and end positions?\n            for (let codewordRow /*int*/ = 0; codewordRow < codewords.length; codewordRow++) {\n                let codeword = codewords[codewordRow];\n                if (codewords[codewordRow] == null) {\n                    continue;\n                }\n                let rowIndicatorValue = codeword.getValue() % 30;\n                let codewordRowNumber = codeword.getRowNumber();\n                if (codewordRowNumber > barcodeMetadata.getRowCount()) {\n                    codewords[codewordRow] = null;\n                    continue;\n                }\n                if (!this._isLeft) {\n                    codewordRowNumber += 2;\n                }\n                switch (codewordRowNumber % 3) {\n                    case 0:\n                        if (rowIndicatorValue * 3 + 1 !== barcodeMetadata.getRowCountUpperPart()) {\n                            codewords[codewordRow] = null;\n                        }\n                        break;\n                    case 1:\n                        if (Math.trunc(rowIndicatorValue / 3) !== barcodeMetadata.getErrorCorrectionLevel() ||\n                            rowIndicatorValue % 3 !== barcodeMetadata.getRowCountLowerPart()) {\n                            codewords[codewordRow] = null;\n                        }\n                        break;\n                    case 2:\n                        if (rowIndicatorValue + 1 !== barcodeMetadata.getColumnCount()) {\n                            codewords[codewordRow] = null;\n                        }\n                        break;\n                }\n            }\n        }\n        isLeft() {\n            return this._isLeft;\n        }\n        // @Override\n        toString() {\n            return 'IsLeft: ' + this._isLeft + '\\n' + super.toString();\n        }\n    }\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * @author Guenther Grau\n     */\n    /*final*/ class DetectionResult {\n        constructor(barcodeMetadata, boundingBox) {\n            /*final*/ this.ADJUST_ROW_NUMBER_SKIP = 2;\n            this.barcodeMetadata = barcodeMetadata;\n            this.barcodeColumnCount = barcodeMetadata.getColumnCount();\n            this.boundingBox = boundingBox;\n            // this.detectionResultColumns = new DetectionResultColumn[this.barcodeColumnCount + 2];\n            this.detectionResultColumns = new Array(this.barcodeColumnCount + 2);\n        }\n        getDetectionResultColumns() {\n            this.adjustIndicatorColumnRowNumbers(this.detectionResultColumns[0]);\n            this.adjustIndicatorColumnRowNumbers(this.detectionResultColumns[this.barcodeColumnCount + 1]);\n            let unadjustedCodewordCount = PDF417Common.MAX_CODEWORDS_IN_BARCODE;\n            let previousUnadjustedCount;\n            do {\n                previousUnadjustedCount = unadjustedCodewordCount;\n                unadjustedCodewordCount = this.adjustRowNumbersAndGetCount();\n            } while (unadjustedCodewordCount > 0 && unadjustedCodewordCount < previousUnadjustedCount);\n            return this.detectionResultColumns;\n        }\n        adjustIndicatorColumnRowNumbers(detectionResultColumn) {\n            if (detectionResultColumn != null) {\n                detectionResultColumn\n                    .adjustCompleteIndicatorColumnRowNumbers(this.barcodeMetadata);\n            }\n        }\n        // TODO ensure that no detected codewords with unknown row number are left\n        // we should be able to estimate the row height and use it as a hint for the row number\n        // we should also fill the rows top to bottom and bottom to top\n        /**\n         * @return number of codewords which don't have a valid row number. Note that the count is not accurate as codewords\n         * will be counted several times. It just serves as an indicator to see when we can stop adjusting row numbers\n         */\n        adjustRowNumbersAndGetCount() {\n            let unadjustedCount = this.adjustRowNumbersByRow();\n            if (unadjustedCount === 0) {\n                return 0;\n            }\n            for (let barcodeColumn /*int*/ = 1; barcodeColumn < this.barcodeColumnCount + 1; barcodeColumn++) {\n                let codewords = this.detectionResultColumns[barcodeColumn].getCodewords();\n                for (let codewordsRow /*int*/ = 0; codewordsRow < codewords.length; codewordsRow++) {\n                    if (codewords[codewordsRow] == null) {\n                        continue;\n                    }\n                    if (!codewords[codewordsRow].hasValidRowNumber()) {\n                        this.adjustRowNumbers(barcodeColumn, codewordsRow, codewords);\n                    }\n                }\n            }\n            return unadjustedCount;\n        }\n        adjustRowNumbersByRow() {\n            this.adjustRowNumbersFromBothRI();\n            // TODO we should only do full row adjustments if row numbers of left and right row indicator column match.\n            // Maybe it's even better to calculated the height (rows: d) and divide it by the number of barcode\n            // rows. This, together with the LRI and RRI row numbers should allow us to get a good estimate where a row\n            // number starts and ends.\n            let unadjustedCount = this.adjustRowNumbersFromLRI();\n            return unadjustedCount + this.adjustRowNumbersFromRRI();\n        }\n        adjustRowNumbersFromBothRI() {\n            if (this.detectionResultColumns[0] == null || this.detectionResultColumns[this.barcodeColumnCount + 1] == null) {\n                return;\n            }\n            let LRIcodewords = this.detectionResultColumns[0].getCodewords();\n            let RRIcodewords = this.detectionResultColumns[this.barcodeColumnCount + 1].getCodewords();\n            for (let codewordsRow /*int*/ = 0; codewordsRow < LRIcodewords.length; codewordsRow++) {\n                if (LRIcodewords[codewordsRow] != null &&\n                    RRIcodewords[codewordsRow] != null &&\n                    LRIcodewords[codewordsRow].getRowNumber() === RRIcodewords[codewordsRow].getRowNumber()) {\n                    for (let barcodeColumn /*int*/ = 1; barcodeColumn <= this.barcodeColumnCount; barcodeColumn++) {\n                        let codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow];\n                        if (codeword == null) {\n                            continue;\n                        }\n                        codeword.setRowNumber(LRIcodewords[codewordsRow].getRowNumber());\n                        if (!codeword.hasValidRowNumber()) {\n                            this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow] = null;\n                        }\n                    }\n                }\n            }\n        }\n        adjustRowNumbersFromRRI() {\n            if (this.detectionResultColumns[this.barcodeColumnCount + 1] == null) {\n                return 0;\n            }\n            let unadjustedCount = 0;\n            let codewords = this.detectionResultColumns[this.barcodeColumnCount + 1].getCodewords();\n            for (let codewordsRow /*int*/ = 0; codewordsRow < codewords.length; codewordsRow++) {\n                if (codewords[codewordsRow] == null) {\n                    continue;\n                }\n                let rowIndicatorRowNumber = codewords[codewordsRow].getRowNumber();\n                let invalidRowCounts = 0;\n                for (let barcodeColumn /*int*/ = this.barcodeColumnCount + 1; barcodeColumn > 0 && invalidRowCounts < this.ADJUST_ROW_NUMBER_SKIP; barcodeColumn--) {\n                    let codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow];\n                    if (codeword != null) {\n                        invalidRowCounts = DetectionResult.adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword);\n                        if (!codeword.hasValidRowNumber()) {\n                            unadjustedCount++;\n                        }\n                    }\n                }\n            }\n            return unadjustedCount;\n        }\n        adjustRowNumbersFromLRI() {\n            if (this.detectionResultColumns[0] == null) {\n                return 0;\n            }\n            let unadjustedCount = 0;\n            let codewords = this.detectionResultColumns[0].getCodewords();\n            for (let codewordsRow /*int*/ = 0; codewordsRow < codewords.length; codewordsRow++) {\n                if (codewords[codewordsRow] == null) {\n                    continue;\n                }\n                let rowIndicatorRowNumber = codewords[codewordsRow].getRowNumber();\n                let invalidRowCounts = 0;\n                for (let barcodeColumn /*int*/ = 1; barcodeColumn < this.barcodeColumnCount + 1 && invalidRowCounts < this.ADJUST_ROW_NUMBER_SKIP; barcodeColumn++) {\n                    let codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow];\n                    if (codeword != null) {\n                        invalidRowCounts = DetectionResult.adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword);\n                        if (!codeword.hasValidRowNumber()) {\n                            unadjustedCount++;\n                        }\n                    }\n                }\n            }\n            return unadjustedCount;\n        }\n        static adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword) {\n            if (codeword == null) {\n                return invalidRowCounts;\n            }\n            if (!codeword.hasValidRowNumber()) {\n                if (codeword.isValidRowNumber(rowIndicatorRowNumber)) {\n                    codeword.setRowNumber(rowIndicatorRowNumber);\n                    invalidRowCounts = 0;\n                }\n                else {\n                    ++invalidRowCounts;\n                }\n            }\n            return invalidRowCounts;\n        }\n        adjustRowNumbers(barcodeColumn, codewordsRow, codewords) {\n            if (!this.detectionResultColumns[barcodeColumn - 1]) {\n                return;\n            }\n            let codeword = codewords[codewordsRow];\n            let previousColumnCodewords = this.detectionResultColumns[barcodeColumn - 1].getCodewords();\n            let nextColumnCodewords = previousColumnCodewords;\n            if (this.detectionResultColumns[barcodeColumn + 1] != null) {\n                nextColumnCodewords = this.detectionResultColumns[barcodeColumn + 1].getCodewords();\n            }\n            // let otherCodewords: Codeword[] = new Codeword[14];\n            let otherCodewords = new Array(14);\n            otherCodewords[2] = previousColumnCodewords[codewordsRow];\n            otherCodewords[3] = nextColumnCodewords[codewordsRow];\n            if (codewordsRow > 0) {\n                otherCodewords[0] = codewords[codewordsRow - 1];\n                otherCodewords[4] = previousColumnCodewords[codewordsRow - 1];\n                otherCodewords[5] = nextColumnCodewords[codewordsRow - 1];\n            }\n            if (codewordsRow > 1) {\n                otherCodewords[8] = codewords[codewordsRow - 2];\n                otherCodewords[10] = previousColumnCodewords[codewordsRow - 2];\n                otherCodewords[11] = nextColumnCodewords[codewordsRow - 2];\n            }\n            if (codewordsRow < codewords.length - 1) {\n                otherCodewords[1] = codewords[codewordsRow + 1];\n                otherCodewords[6] = previousColumnCodewords[codewordsRow + 1];\n                otherCodewords[7] = nextColumnCodewords[codewordsRow + 1];\n            }\n            if (codewordsRow < codewords.length - 2) {\n                otherCodewords[9] = codewords[codewordsRow + 2];\n                otherCodewords[12] = previousColumnCodewords[codewordsRow + 2];\n                otherCodewords[13] = nextColumnCodewords[codewordsRow + 2];\n            }\n            for (let otherCodeword of otherCodewords) {\n                if (DetectionResult.adjustRowNumber(codeword, otherCodeword)) {\n                    return;\n                }\n            }\n        }\n        /**\n         * @return true, if row number was adjusted, false otherwise\n         */\n        static adjustRowNumber(codeword, otherCodeword) {\n            if (otherCodeword == null) {\n                return false;\n            }\n            if (otherCodeword.hasValidRowNumber() && otherCodeword.getBucket() === codeword.getBucket()) {\n                codeword.setRowNumber(otherCodeword.getRowNumber());\n                return true;\n            }\n            return false;\n        }\n        getBarcodeColumnCount() {\n            return this.barcodeColumnCount;\n        }\n        getBarcodeRowCount() {\n            return this.barcodeMetadata.getRowCount();\n        }\n        getBarcodeECLevel() {\n            return this.barcodeMetadata.getErrorCorrectionLevel();\n        }\n        setBoundingBox(boundingBox) {\n            this.boundingBox = boundingBox;\n        }\n        getBoundingBox() {\n            return this.boundingBox;\n        }\n        setDetectionResultColumn(barcodeColumn, detectionResultColumn) {\n            this.detectionResultColumns[barcodeColumn] = detectionResultColumn;\n        }\n        getDetectionResultColumn(barcodeColumn) {\n            return this.detectionResultColumns[barcodeColumn];\n        }\n        // @Override\n        toString() {\n            let rowIndicatorColumn = this.detectionResultColumns[0];\n            if (rowIndicatorColumn == null) {\n                rowIndicatorColumn = this.detectionResultColumns[this.barcodeColumnCount + 1];\n            }\n            // try (\n            let formatter = new Formatter();\n            // ) {\n            for (let codewordsRow /*int*/ = 0; codewordsRow < rowIndicatorColumn.getCodewords().length; codewordsRow++) {\n                formatter.format('CW %3d:', codewordsRow);\n                for (let barcodeColumn /*int*/ = 0; barcodeColumn < this.barcodeColumnCount + 2; barcodeColumn++) {\n                    if (this.detectionResultColumns[barcodeColumn] == null) {\n                        formatter.format('    |   ');\n                        continue;\n                    }\n                    let codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow];\n                    if (codeword == null) {\n                        formatter.format('    |   ');\n                        continue;\n                    }\n                    formatter.format(' %3d|%3d', codeword.getRowNumber(), codeword.getValue());\n                }\n                formatter.format('%n');\n            }\n            return formatter.toString();\n            // }\n        }\n    }\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    // package com.google.zxing.pdf417.decoder;\n    /**\n     * @author Guenther Grau\n     */\n    /*final*/ class Codeword {\n        constructor(startX, endX, bucket, value) {\n            this.rowNumber = Codeword.BARCODE_ROW_UNKNOWN;\n            this.startX = Math.trunc(startX);\n            this.endX = Math.trunc(endX);\n            this.bucket = Math.trunc(bucket);\n            this.value = Math.trunc(value);\n        }\n        hasValidRowNumber() {\n            return this.isValidRowNumber(this.rowNumber);\n        }\n        isValidRowNumber(rowNumber) {\n            return rowNumber !== Codeword.BARCODE_ROW_UNKNOWN && this.bucket === (rowNumber % 3) * 3;\n        }\n        setRowNumberAsRowIndicatorColumn() {\n            this.rowNumber = Math.trunc((Math.trunc(this.value / 30)) * 3 + Math.trunc(this.bucket / 3));\n        }\n        getWidth() {\n            return this.endX - this.startX;\n        }\n        getStartX() {\n            return this.startX;\n        }\n        getEndX() {\n            return this.endX;\n        }\n        getBucket() {\n            return this.bucket;\n        }\n        getValue() {\n            return this.value;\n        }\n        getRowNumber() {\n            return this.rowNumber;\n        }\n        setRowNumber(rowNumber) {\n            this.rowNumber = rowNumber;\n        }\n        //   @Override\n        toString() {\n            return this.rowNumber + '|' + this.value;\n        }\n    }\n    Codeword.BARCODE_ROW_UNKNOWN = -1;\n\n    /*\n    * Copyright 2013 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /**\n     * @author Guenther Grau\n     * @author creatale GmbH (christoph.schulz@creatale.de)\n     */\n    /*final*/ class PDF417CodewordDecoder {\n        /* @note\n         * this action have to be performed before first use of class\n         * - static constructor\n         * working with 32bit float (based from Java logic)\n        */\n        static initialize() {\n            // Pre-computes the symbol ratio table.\n            for ( /*int*/let i = 0; i < PDF417Common.SYMBOL_TABLE.length; i++) {\n                let currentSymbol = PDF417Common.SYMBOL_TABLE[i];\n                let currentBit = currentSymbol & 0x1;\n                for ( /*int*/let j = 0; j < PDF417Common.BARS_IN_MODULE; j++) {\n                    let size = 0.0;\n                    while ((currentSymbol & 0x1) === currentBit) {\n                        size += 1.0;\n                        currentSymbol >>= 1;\n                    }\n                    currentBit = currentSymbol & 0x1;\n                    if (!PDF417CodewordDecoder.RATIOS_TABLE[i]) {\n                        PDF417CodewordDecoder.RATIOS_TABLE[i] = new Array(PDF417Common.BARS_IN_MODULE);\n                    }\n                    PDF417CodewordDecoder.RATIOS_TABLE[i][PDF417Common.BARS_IN_MODULE - j - 1] = Math.fround(size / PDF417Common.MODULES_IN_CODEWORD);\n                }\n            }\n            this.bSymbolTableReady = true;\n        }\n        static getDecodedValue(moduleBitCount) {\n            let decodedValue = PDF417CodewordDecoder.getDecodedCodewordValue(PDF417CodewordDecoder.sampleBitCounts(moduleBitCount));\n            if (decodedValue !== -1) {\n                return decodedValue;\n            }\n            return PDF417CodewordDecoder.getClosestDecodedValue(moduleBitCount);\n        }\n        static sampleBitCounts(moduleBitCount) {\n            let bitCountSum = MathUtils.sum(moduleBitCount);\n            let result = new Int32Array(PDF417Common.BARS_IN_MODULE);\n            let bitCountIndex = 0;\n            let sumPreviousBits = 0;\n            for ( /*int*/let i = 0; i < PDF417Common.MODULES_IN_CODEWORD; i++) {\n                let sampleIndex = bitCountSum / (2 * PDF417Common.MODULES_IN_CODEWORD) +\n                    (i * bitCountSum) / PDF417Common.MODULES_IN_CODEWORD;\n                if (sumPreviousBits + moduleBitCount[bitCountIndex] <= sampleIndex) {\n                    sumPreviousBits += moduleBitCount[bitCountIndex];\n                    bitCountIndex++;\n                }\n                result[bitCountIndex]++;\n            }\n            return result;\n        }\n        static getDecodedCodewordValue(moduleBitCount) {\n            let decodedValue = PDF417CodewordDecoder.getBitValue(moduleBitCount);\n            return PDF417Common.getCodeword(decodedValue) === -1 ? -1 : decodedValue;\n        }\n        static getBitValue(moduleBitCount) {\n            let result = /*long*/ 0;\n            for (let /*int*/ i = 0; i < moduleBitCount.length; i++) {\n                for ( /*int*/let bit = 0; bit < moduleBitCount[i]; bit++) {\n                    result = (result << 1) | (i % 2 === 0 ? 1 : 0);\n                }\n            }\n            return Math.trunc(result);\n        }\n        // working with 32bit float (as in Java)\n        static getClosestDecodedValue(moduleBitCount) {\n            let bitCountSum = MathUtils.sum(moduleBitCount);\n            let bitCountRatios = new Array(PDF417Common.BARS_IN_MODULE);\n            if (bitCountSum > 1) {\n                for (let /*int*/ i = 0; i < bitCountRatios.length; i++) {\n                    bitCountRatios[i] = Math.fround(moduleBitCount[i] / bitCountSum);\n                }\n            }\n            let bestMatchError = Float.MAX_VALUE;\n            let bestMatch = -1;\n            if (!this.bSymbolTableReady) {\n                PDF417CodewordDecoder.initialize();\n            }\n            for ( /*int*/let j = 0; j < PDF417CodewordDecoder.RATIOS_TABLE.length; j++) {\n                let error = 0.0;\n                let ratioTableRow = PDF417CodewordDecoder.RATIOS_TABLE[j];\n                for ( /*int*/let k = 0; k < PDF417Common.BARS_IN_MODULE; k++) {\n                    let diff = Math.fround(ratioTableRow[k] - bitCountRatios[k]);\n                    error += Math.fround(diff * diff);\n                    if (error >= bestMatchError) {\n                        break;\n                    }\n                }\n                if (error < bestMatchError) {\n                    bestMatchError = error;\n                    bestMatch = PDF417Common.SYMBOL_TABLE[j];\n                }\n            }\n            return bestMatch;\n        }\n    }\n    // flag that the table is ready for use\n    PDF417CodewordDecoder.bSymbolTableReady = false;\n    PDF417CodewordDecoder.RATIOS_TABLE = new Array(PDF417Common.SYMBOL_TABLE.length).map(x => x = new Array(PDF417Common.BARS_IN_MODULE));\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    // package com.google.zxing.pdf417;\n    /**\n     * @author Guenther Grau\n     */\n    /*public final*/ class PDF417ResultMetadata {\n        constructor() {\n            this.segmentCount = -1;\n            this.fileSize = -1;\n            this.timestamp = -1;\n            this.checksum = -1;\n        }\n        /**\n         * The Segment ID represents the segment of the whole file distributed over different symbols.\n         *\n         * @return File segment index\n         */\n        getSegmentIndex() {\n            return this.segmentIndex;\n        }\n        setSegmentIndex(segmentIndex) {\n            this.segmentIndex = segmentIndex;\n        }\n        /**\n         * Is the same for each related PDF417 symbol\n         *\n         * @return File ID\n         */\n        getFileId() {\n            return this.fileId;\n        }\n        setFileId(fileId) {\n            this.fileId = fileId;\n        }\n        /**\n         * @return always null\n         * @deprecated use dedicated already parsed fields\n         */\n        //   @Deprecated\n        getOptionalData() {\n            return this.optionalData;\n        }\n        /**\n         * @param optionalData old optional data format as int array\n         * @deprecated parse and use new fields\n         */\n        //   @Deprecated\n        setOptionalData(optionalData) {\n            this.optionalData = optionalData;\n        }\n        /**\n         * @return true if it is the last segment\n         */\n        isLastSegment() {\n            return this.lastSegment;\n        }\n        setLastSegment(lastSegment) {\n            this.lastSegment = lastSegment;\n        }\n        /**\n         * @return count of segments, -1 if not set\n         */\n        getSegmentCount() {\n            return this.segmentCount;\n        }\n        setSegmentCount(segmentCount /*int*/) {\n            this.segmentCount = segmentCount;\n        }\n        getSender() {\n            return this.sender || null;\n        }\n        setSender(sender) {\n            this.sender = sender;\n        }\n        getAddressee() {\n            return this.addressee || null;\n        }\n        setAddressee(addressee) {\n            this.addressee = addressee;\n        }\n        /**\n         * Filename of the encoded file\n         *\n         * @return filename\n         */\n        getFileName() {\n            return this.fileName;\n        }\n        setFileName(fileName) {\n            this.fileName = fileName;\n        }\n        /**\n         * filesize in bytes of the encoded file\n         *\n         * @return filesize in bytes, -1 if not set\n         */\n        getFileSize() {\n            return this.fileSize;\n        }\n        setFileSize(fileSize /*long*/) {\n            this.fileSize = fileSize;\n        }\n        /**\n         * 16-bit CRC checksum using CCITT-16\n         *\n         * @return crc checksum, -1 if not set\n         */\n        getChecksum() {\n            return this.checksum;\n        }\n        setChecksum(checksum /*int*/) {\n            this.checksum = checksum;\n        }\n        /**\n         * unix epock timestamp, elapsed seconds since 1970-01-01\n         *\n         * @return elapsed seconds, -1 if not set\n         */\n        getTimestamp() {\n            return this.timestamp;\n        }\n        setTimestamp(timestamp /*long*/) {\n            this.timestamp = timestamp;\n        }\n    }\n\n    /**\n     * Ponyfill for Java's Long class.\n     */\n    class Long {\n        /**\n         * Parses a string to a number, since JS has no really Int64.\n         *\n         * @param num Numeric string.\n         * @param radix Destination radix.\n         */\n        static parseLong(num, radix = undefined) {\n            return parseInt(num, radix);\n        }\n    }\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class NullPointerException extends Exception {\n    }\n    NullPointerException.kind = 'NullPointerException';\n\n    /*\n     * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.\n     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n     *\n     * This code is free software; you can redistribute it and/or modify it\n     * under the terms of the GNU General Public License version 2 only, as\n     * published by the Free Software Foundation.  Oracle designates this\n     * particular file as subject to the \"Classpath\" exception as provided\n     * by Oracle in the LICENSE file that accompanied this code.\n     *\n     * This code is distributed in the hope that it will be useful, but WITHOUT\n     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n     * version 2 for more details (a copy is included in the LICENSE file that\n     * accompanied this code).\n     *\n     * You should have received a copy of the GNU General Public License version\n     * 2 along with this work; if not, write to the Free Software Foundation,\n     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n     *\n     * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n     * or visit www.oracle.com if you need additional information or have any\n     * questions.\n     */\n    // package java.io;\n    /**\n     * This abstract class is the superclass of all classes representing\n     * an output stream of bytes. An output stream accepts output bytes\n     * and sends them to some sink.\n     * <p>\n     * Applications that need to define a subclass of\n     * <code>OutputStream</code> must always provide at least a method\n     * that writes one byte of output.\n     *\n     * @author  Arthur van Hoff\n     * @see     java.io.BufferedOutputStream\n     * @see     java.io.ByteArrayOutputStream\n     * @see     java.io.DataOutputStream\n     * @see     java.io.FilterOutputStream\n     * @see     java.io.InputStream\n     * @see     java.io.OutputStream#write(int)\n     * @since   JDK1.0\n     */\n    /*public*/ class OutputStream /*implements Closeable, Flushable*/ {\n        /**\n         * Writes <code>b.length</code> bytes from the specified byte array\n         * to this output stream. The general contract for <code>write(b)</code>\n         * is that it should have exactly the same effect as the call\n         * <code>write(b, 0, b.length)</code>.\n         *\n         * @param      b   the data.\n         * @exception  IOException  if an I/O error occurs.\n         * @see        java.io.OutputStream#write(byte[], int, int)\n         */\n        writeBytes(b) {\n            this.writeBytesOffset(b, 0, b.length);\n        }\n        /**\n         * Writes <code>len</code> bytes from the specified byte array\n         * starting at offset <code>off</code> to this output stream.\n         * The general contract for <code>write(b, off, len)</code> is that\n         * some of the bytes in the array <code>b</code> are written to the\n         * output stream in order; element <code>b[off]</code> is the first\n         * byte written and <code>b[off+len-1]</code> is the last byte written\n         * by this operation.\n         * <p>\n         * The <code>write</code> method of <code>OutputStream</code> calls\n         * the write method of one argument on each of the bytes to be\n         * written out. Subclasses are encouraged to override this method and\n         * provide a more efficient implementation.\n         * <p>\n         * If <code>b</code> is <code>null</code>, a\n         * <code>NullPointerException</code> is thrown.\n         * <p>\n         * If <code>off</code> is negative, or <code>len</code> is negative, or\n         * <code>off+len</code> is greater than the length of the array\n         * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown.\n         *\n         * @param      b     the data.\n         * @param      off   the start offset in the data.\n         * @param      len   the number of bytes to write.\n         * @exception  IOException  if an I/O error occurs. In particular,\n         *             an <code>IOException</code> is thrown if the output\n         *             stream is closed.\n         */\n        writeBytesOffset(b, off, len) {\n            if (b == null) {\n                throw new NullPointerException();\n            }\n            else if ((off < 0) || (off > b.length) || (len < 0) ||\n                ((off + len) > b.length) || ((off + len) < 0)) {\n                throw new IndexOutOfBoundsException();\n            }\n            else if (len === 0) {\n                return;\n            }\n            for (let i = 0; i < len; i++) {\n                this.write(b[off + i]);\n            }\n        }\n        /**\n         * Flushes this output stream and forces any buffered output bytes\n         * to be written out. The general contract of <code>flush</code> is\n         * that calling it is an indication that, if any bytes previously\n         * written have been buffered by the implementation of the output\n         * stream, such bytes should immediately be written to their\n         * intended destination.\n         * <p>\n         * If the intended destination of this stream is an abstraction provided by\n         * the underlying operating system, for example a file, then flushing the\n         * stream guarantees only that bytes previously written to the stream are\n         * passed to the operating system for writing; it does not guarantee that\n         * they are actually written to a physical device such as a disk drive.\n         * <p>\n         * The <code>flush</code> method of <code>OutputStream</code> does nothing.\n         *\n         * @exception  IOException  if an I/O error occurs.\n         */\n        flush() {\n        }\n        /**\n         * Closes this output stream and releases any system resources\n         * associated with this stream. The general contract of <code>close</code>\n         * is that it closes the output stream. A closed stream cannot perform\n         * output operations and cannot be reopened.\n         * <p>\n         * The <code>close</code> method of <code>OutputStream</code> does nothing.\n         *\n         * @exception  IOException  if an I/O error occurs.\n         */\n        close() {\n        }\n    }\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class OutOfMemoryError extends Exception {\n    }\n\n    /*\n     * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.\n     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n     *\n     * This code is free software; you can redistribute it and/or modify it\n     * under the terms of the GNU General Public License version 2 only, as\n     * published by the Free Software Foundation.  Oracle designates this\n     * particular file as subject to the \"Classpath\" exception as provided\n     * by Oracle in the LICENSE file that accompanied this code.\n     *\n     * This code is distributed in the hope that it will be useful, but WITHOUT\n     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n     * version 2 for more details (a copy is included in the LICENSE file that\n     * accompanied this code).\n     *\n     * You should have received a copy of the GNU General Public License version\n     * 2 along with this work; if not, write to the Free Software Foundation,\n     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n     *\n     * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n     * or visit www.oracle.com if you need additional information or have any\n     * questions.\n     */\n    /**\n     * This class implements an output stream in which the data is\n     * written into a byte array. The buffer automatically grows as data\n     * is written to it.\n     * The data can be retrieved using <code>toByteArray()</code> and\n     * <code>toString()</code>.\n     * <p>\n     * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in\n     * this class can be called after the stream has been closed without\n     * generating an <tt>IOException</tt>.\n     *\n     * @author  Arthur van Hoff\n     * @since   JDK1.0\n     */\n    /*public*/ class ByteArrayOutputStream extends OutputStream {\n        /**\n         * Creates a new byte array output stream. The buffer capacity is\n         * initially 32 bytes, though its size increases if necessary.\n         */\n        // public constructor() {\n        //     this(32);\n        // }\n        /**\n         * Creates a new byte array output stream, with a buffer capacity of\n         * the specified size, in bytes.\n         *\n         * @param   size   the initial size.\n         * @exception  IllegalArgumentException if size is negative.\n         */\n        constructor(size = 32) {\n            super();\n            /**\n             * The number of valid bytes in the buffer.\n             */\n            this.count = 0;\n            if (size < 0) {\n                throw new IllegalArgumentException('Negative initial size: '\n                    + size);\n            }\n            this.buf = new Uint8Array(size);\n        }\n        /**\n         * Increases the capacity if necessary to ensure that it can hold\n         * at least the number of elements specified by the minimum\n         * capacity argument.\n         *\n         * @param minCapacity the desired minimum capacity\n         * @throws OutOfMemoryError if {@code minCapacity < 0}.  This is\n         * interpreted as a request for the unsatisfiably large capacity\n         * {@code (long) Integer.MAX_VALUE + (minCapacity - Integer.MAX_VALUE)}.\n         */\n        ensureCapacity(minCapacity) {\n            // overflow-conscious code\n            if (minCapacity - this.buf.length > 0)\n                this.grow(minCapacity);\n        }\n        /**\n         * Increases the capacity to ensure that it can hold at least the\n         * number of elements specified by the minimum capacity argument.\n         *\n         * @param minCapacity the desired minimum capacity\n         */\n        grow(minCapacity) {\n            // overflow-conscious code\n            let oldCapacity = this.buf.length;\n            let newCapacity = oldCapacity << 1;\n            if (newCapacity - minCapacity < 0)\n                newCapacity = minCapacity;\n            if (newCapacity < 0) {\n                if (minCapacity < 0) // overflow\n                    throw new OutOfMemoryError();\n                newCapacity = Integer.MAX_VALUE;\n            }\n            this.buf = Arrays.copyOfUint8Array(this.buf, newCapacity);\n        }\n        /**\n         * Writes the specified byte to this byte array output stream.\n         *\n         * @param   b   the byte to be written.\n         */\n        write(b) {\n            this.ensureCapacity(this.count + 1);\n            this.buf[this.count] = /*(byte)*/ b;\n            this.count += 1;\n        }\n        /**\n         * Writes <code>len</code> bytes from the specified byte array\n         * starting at offset <code>off</code> to this byte array output stream.\n         *\n         * @param   b     the data.\n         * @param   off   the start offset in the data.\n         * @param   len   the number of bytes to write.\n         */\n        writeBytesOffset(b, off, len) {\n            if ((off < 0) || (off > b.length) || (len < 0) ||\n                ((off + len) - b.length > 0)) {\n                throw new IndexOutOfBoundsException();\n            }\n            this.ensureCapacity(this.count + len);\n            System.arraycopy(b, off, this.buf, this.count, len);\n            this.count += len;\n        }\n        /**\n         * Writes the complete contents of this byte array output stream to\n         * the specified output stream argument, as if by calling the output\n         * stream's write method using <code>out.write(buf, 0, count)</code>.\n         *\n         * @param      out   the output stream to which to write the data.\n         * @exception  IOException  if an I/O error occurs.\n         */\n        writeTo(out) {\n            out.writeBytesOffset(this.buf, 0, this.count);\n        }\n        /**\n         * Resets the <code>count</code> field of this byte array output\n         * stream to zero, so that all currently accumulated output in the\n         * output stream is discarded. The output stream can be used again,\n         * reusing the already allocated buffer space.\n         *\n         * @see     java.io.ByteArrayInputStream#count\n         */\n        reset() {\n            this.count = 0;\n        }\n        /**\n         * Creates a newly allocated byte array. Its size is the current\n         * size of this output stream and the valid contents of the buffer\n         * have been copied into it.\n         *\n         * @return  the current contents of this output stream, as a byte array.\n         * @see     java.io.ByteArrayOutputStream#size()\n         */\n        toByteArray() {\n            return Arrays.copyOfUint8Array(this.buf, this.count);\n        }\n        /**\n         * Returns the current size of the buffer.\n         *\n         * @return  the value of the <code>count</code> field, which is the number\n         *          of valid bytes in this output stream.\n         * @see     java.io.ByteArrayOutputStream#count\n         */\n        size() {\n            return this.count;\n        }\n        toString(param) {\n            if (!param) {\n                return this.toString_void();\n            }\n            if (typeof param === 'string') {\n                return this.toString_string(param);\n            }\n            return this.toString_number(param);\n        }\n        /**\n         * Converts the buffer's contents into a string decoding bytes using the\n         * platform's default character set. The length of the new <tt>String</tt>\n         * is a function of the character set, and hence may not be equal to the\n         * size of the buffer.\n         *\n         * <p> This method always replaces malformed-input and unmappable-character\n         * sequences with the default replacement string for the platform's\n         * default character set. The {@linkplain java.nio.charset.CharsetDecoder}\n         * class should be used when more control over the decoding process is\n         * required.\n         *\n         * @return String decoded from the buffer's contents.\n         * @since  JDK1.1\n         */\n        toString_void() {\n            return new String(this.buf /*, 0, this.count*/).toString();\n        }\n        /**\n         * Converts the buffer's contents into a string by decoding the bytes using\n         * the specified {@link java.nio.charset.Charset charsetName}. The length of\n         * the new <tt>String</tt> is a function of the charset, and hence may not be\n         * equal to the length of the byte array.\n         *\n         * <p> This method always replaces malformed-input and unmappable-character\n         * sequences with this charset's default replacement string. The {@link\n         * java.nio.charset.CharsetDecoder} class should be used when more control\n         * over the decoding process is required.\n         *\n         * @param  charsetName  the name of a supported\n         *              {@linkplain java.nio.charset.Charset </code>charset<code>}\n         * @return String decoded from the buffer's contents.\n         * @exception  UnsupportedEncodingException\n         *             If the named charset is not supported\n         * @since   JDK1.1\n         */\n        toString_string(charsetName) {\n            return new String(this.buf /*, 0, this.count, charsetName*/).toString();\n        }\n        /**\n         * Creates a newly allocated string. Its size is the current size of\n         * the output stream and the valid contents of the buffer have been\n         * copied into it. Each character <i>c</i> in the resulting string is\n         * constructed from the corresponding element <i>b</i> in the byte\n         * array such that:\n         * <blockquote><pre>\n         *     c == (char)(((hibyte &amp; 0xff) &lt;&lt; 8) | (b &amp; 0xff))\n         * </pre></blockquote>\n         *\n         * @deprecated This method does not properly convert bytes into characters.\n         * As of JDK&nbsp;1.1, the preferred way to do this is via the\n         * <code>toString(String enc)</code> method, which takes an encoding-name\n         * argument, or the <code>toString()</code> method, which uses the\n         * platform's default character encoding.\n         *\n         * @param      hibyte    the high byte of each resulting Unicode character.\n         * @return     the current contents of the output stream, as a string.\n         * @see        java.io.ByteArrayOutputStream#size()\n         * @see        java.io.ByteArrayOutputStream#toString(String)\n         * @see        java.io.ByteArrayOutputStream#toString()\n         */\n        // @Deprecated\n        toString_number(hibyte) {\n            return new String(this.buf /*, hibyte, 0, this.count*/).toString();\n        }\n        /**\n         * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in\n         * this class can be called after the stream has been closed without\n         * generating an <tt>IOException</tt>.\n         * <p>\n         *\n         * @throws IOException\n         */\n        close() {\n        }\n    }\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*private*/ var Mode$2;\n    (function (Mode) {\n        Mode[Mode[\"ALPHA\"] = 0] = \"ALPHA\";\n        Mode[Mode[\"LOWER\"] = 1] = \"LOWER\";\n        Mode[Mode[\"MIXED\"] = 2] = \"MIXED\";\n        Mode[Mode[\"PUNCT\"] = 3] = \"PUNCT\";\n        Mode[Mode[\"ALPHA_SHIFT\"] = 4] = \"ALPHA_SHIFT\";\n        Mode[Mode[\"PUNCT_SHIFT\"] = 5] = \"PUNCT_SHIFT\";\n    })(Mode$2 || (Mode$2 = {}));\n    /**\n     * Indirectly access the global BigInt constructor, it\n     * allows browsers that doesn't support BigInt to run\n     * the library without breaking due to \"undefined BigInt\"\n     * errors.\n     */\n    function getBigIntConstructor() {\n        if (typeof window !== 'undefined') {\n            return window['BigInt'] || null;\n        }\n        if (typeof __webpack_require__.g !== 'undefined') {\n            return __webpack_require__.g['BigInt'] || null;\n        }\n        if (typeof self !== 'undefined') {\n            return self['BigInt'] || null;\n        }\n        throw new Error('Can\\'t search globals for BigInt!');\n    }\n    /**\n     * Used to store the BigInt constructor.\n     */\n    let BigInteger;\n    /**\n     * This function creates a bigint value. It allows browsers\n     * that doesn't support BigInt to run the rest of the library\n     * by not directly accessing the BigInt constructor.\n     */\n    function createBigInt(num) {\n        if (typeof BigInteger === 'undefined') {\n            BigInteger = getBigIntConstructor();\n        }\n        if (BigInteger === null) {\n            throw new Error('BigInt is not supported!');\n        }\n        return BigInteger(num);\n    }\n    function getEXP900() {\n        // in Java - array with length = 16\n        let EXP900 = [];\n        EXP900[0] = createBigInt(1);\n        let nineHundred = createBigInt(900);\n        EXP900[1] = nineHundred;\n        // in Java - array with length = 16\n        for (let i /*int*/ = 2; i < 16; i++) {\n            EXP900[i] = EXP900[i - 1] * nineHundred;\n        }\n        return EXP900;\n    }\n    /**\n     * <p>This class contains the methods for decoding the PDF417 codewords.</p>\n     *\n     * @author SITA Lab (kevin.osullivan@sita.aero)\n     * @author Guenther Grau\n     */\n    /*final*/ class DecodedBitStreamParser$2 {\n        //   private DecodedBitStreamParser() {\n        // }\n        /**\n         *\n         * @param codewords\n         * @param ecLevel\n         *\n         * @throws FormatException\n         */\n        static decode(codewords, ecLevel) {\n            // pass encoding to result (will be used for decode symbols in byte mode)\n            let result = new StringBuilder('');\n            // let encoding: Charset = StandardCharsets.ISO_8859_1;\n            let encoding = CharacterSetECI.ISO8859_1;\n            /**\n             * @note the next command is specific from this TypeScript library\n             * because TS can't properly cast some values to char and\n             * convert it to string later correctly due to encoding\n             * differences from Java version. As reported here:\n             * https://github.com/zxing-js/library/pull/264/files#r382831593\n             */\n            result.enableDecoding(encoding);\n            // Get compaction mode\n            let codeIndex = 1;\n            let code = codewords[codeIndex++];\n            let resultMetadata = new PDF417ResultMetadata();\n            while (codeIndex < codewords[0]) {\n                switch (code) {\n                    case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                        codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex, result);\n                        break;\n                    case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n                    case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n                        codeIndex = DecodedBitStreamParser$2.byteCompaction(code, codewords, encoding, codeIndex, result);\n                        break;\n                    case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n                        result.append(/*(char)*/ codewords[codeIndex++]);\n                        break;\n                    case DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH:\n                        codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex, result);\n                        break;\n                    case DecodedBitStreamParser$2.ECI_CHARSET:\n                        let charsetECI = CharacterSetECI.getCharacterSetECIByValue(codewords[codeIndex++]);\n                        // encoding = Charset.forName(charsetECI.getName());\n                        break;\n                    case DecodedBitStreamParser$2.ECI_GENERAL_PURPOSE:\n                        // Can't do anything with generic ECI; skip its 2 characters\n                        codeIndex += 2;\n                        break;\n                    case DecodedBitStreamParser$2.ECI_USER_DEFINED:\n                        // Can't do anything with user ECI; skip its 1 character\n                        codeIndex++;\n                        break;\n                    case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n                        codeIndex = DecodedBitStreamParser$2.decodeMacroBlock(codewords, codeIndex, resultMetadata);\n                        break;\n                    case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n                    case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n                        // Should not see these outside a macro block\n                        throw new FormatException();\n                    default:\n                        // Default to text compaction. During testing numerous barcodes\n                        // appeared to be missing the starting mode. In these cases defaulting\n                        // to text compaction seems to work.\n                        codeIndex--;\n                        codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex, result);\n                        break;\n                }\n                if (codeIndex < codewords.length) {\n                    code = codewords[codeIndex++];\n                }\n                else {\n                    throw FormatException.getFormatInstance();\n                }\n            }\n            if (result.length() === 0) {\n                throw FormatException.getFormatInstance();\n            }\n            let decoderResult = new DecoderResult(null, result.toString(), null, ecLevel);\n            decoderResult.setOther(resultMetadata);\n            return decoderResult;\n        }\n        /**\n         *\n         * @param int\n         * @param param1\n         * @param codewords\n         * @param int\n         * @param codeIndex\n         * @param PDF417ResultMetadata\n         * @param resultMetadata\n         *\n         * @throws FormatException\n         */\n        // @SuppressWarnings(\"deprecation\")\n        static decodeMacroBlock(codewords, codeIndex, resultMetadata) {\n            if (codeIndex + DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS > codewords[0]) {\n                // we must have at least two bytes left for the segment index\n                throw FormatException.getFormatInstance();\n            }\n            let segmentIndexArray = new Int32Array(DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS);\n            for (let i /*int*/ = 0; i < DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS; i++, codeIndex++) {\n                segmentIndexArray[i] = codewords[codeIndex];\n            }\n            resultMetadata.setSegmentIndex(Integer.parseInt(DecodedBitStreamParser$2.decodeBase900toBase10(segmentIndexArray, DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS)));\n            let fileId = new StringBuilder();\n            codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex, fileId);\n            resultMetadata.setFileId(fileId.toString());\n            let optionalFieldsStart = -1;\n            if (codewords[codeIndex] === DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD) {\n                optionalFieldsStart = codeIndex + 1;\n            }\n            while (codeIndex < codewords[0]) {\n                switch (codewords[codeIndex]) {\n                    case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n                        codeIndex++;\n                        switch (codewords[codeIndex]) {\n                            case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME:\n                                let fileName = new StringBuilder();\n                                codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex + 1, fileName);\n                                resultMetadata.setFileName(fileName.toString());\n                                break;\n                            case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_SENDER:\n                                let sender = new StringBuilder();\n                                codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex + 1, sender);\n                                resultMetadata.setSender(sender.toString());\n                                break;\n                            case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE:\n                                let addressee = new StringBuilder();\n                                codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex + 1, addressee);\n                                resultMetadata.setAddressee(addressee.toString());\n                                break;\n                            case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT:\n                                let segmentCount = new StringBuilder();\n                                codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex + 1, segmentCount);\n                                resultMetadata.setSegmentCount(Integer.parseInt(segmentCount.toString()));\n                                break;\n                            case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP:\n                                let timestamp = new StringBuilder();\n                                codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex + 1, timestamp);\n                                resultMetadata.setTimestamp(Long.parseLong(timestamp.toString()));\n                                break;\n                            case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM:\n                                let checksum = new StringBuilder();\n                                codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex + 1, checksum);\n                                resultMetadata.setChecksum(Integer.parseInt(checksum.toString()));\n                                break;\n                            case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE:\n                                let fileSize = new StringBuilder();\n                                codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex + 1, fileSize);\n                                resultMetadata.setFileSize(Long.parseLong(fileSize.toString()));\n                                break;\n                            default:\n                                throw FormatException.getFormatInstance();\n                        }\n                        break;\n                    case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n                        codeIndex++;\n                        resultMetadata.setLastSegment(true);\n                        break;\n                    default:\n                        throw FormatException.getFormatInstance();\n                }\n            }\n            // copy optional fields to additional options\n            if (optionalFieldsStart !== -1) {\n                let optionalFieldsLength = codeIndex - optionalFieldsStart;\n                if (resultMetadata.isLastSegment()) {\n                    // do not include terminator\n                    optionalFieldsLength--;\n                }\n                resultMetadata.setOptionalData(Arrays.copyOfRange(codewords, optionalFieldsStart, optionalFieldsStart + optionalFieldsLength));\n            }\n            return codeIndex;\n        }\n        /**\n         * Text Compaction mode (see 5.4.1.5) permits all printable ASCII characters to be\n         * encoded, i.e. values 32 - 126 inclusive in accordance with ISO/IEC 646 (IRV), as\n         * well as selected control characters.\n         *\n         * @param codewords The array of codewords (data + error)\n         * @param codeIndex The current index into the codeword array.\n         * @param result    The decoded data is appended to the result.\n         * @return The next index into the codeword array.\n         */\n        static textCompaction(codewords, codeIndex, result) {\n            // 2 character per codeword\n            let textCompactionData = new Int32Array((codewords[0] - codeIndex) * 2);\n            // Used to hold the byte compaction value if there is a mode shift\n            let byteCompactionData = new Int32Array((codewords[0] - codeIndex) * 2);\n            let index = 0;\n            let end = false;\n            while ((codeIndex < codewords[0]) && !end) {\n                let code = codewords[codeIndex++];\n                if (code < DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH) {\n                    textCompactionData[index] = code / 30;\n                    textCompactionData[index + 1] = code % 30;\n                    index += 2;\n                }\n                else {\n                    switch (code) {\n                        case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                            // reinitialize text compaction mode to alpha sub mode\n                            textCompactionData[index++] = DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH;\n                            break;\n                        case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n                        case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n                        case DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH:\n                        case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n                        case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n                        case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n                            codeIndex--;\n                            end = true;\n                            break;\n                        case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n                            // The Mode Shift codeword 913 shall cause a temporary\n                            // switch from Text Compaction mode to Byte Compaction mode.\n                            // This switch shall be in effect for only the next codeword,\n                            // after which the mode shall revert to the prevailing sub-mode\n                            // of the Text Compaction mode. Codeword 913 is only available\n                            // in Text Compaction mode; its use is described in 5.4.2.4.\n                            textCompactionData[index] = DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE;\n                            code = codewords[codeIndex++];\n                            byteCompactionData[index] = code;\n                            index++;\n                            break;\n                    }\n                }\n            }\n            DecodedBitStreamParser$2.decodeTextCompaction(textCompactionData, byteCompactionData, index, result);\n            return codeIndex;\n        }\n        /**\n         * The Text Compaction mode includes all the printable ASCII characters\n         * (i.e. values from 32 to 126) and three ASCII control characters: HT or tab\n         * (9: e), LF or line feed (10: e), and CR or carriage\n         * return (13: e). The Text Compaction mode also includes various latch\n         * and shift characters which are used exclusively within the mode. The Text\n         * Compaction mode encodes up to 2 characters per codeword. The compaction rules\n         * for converting data into PDF417 codewords are defined in 5.4.2.2. The sub-mode\n         * switches are defined in 5.4.2.3.\n         *\n         * @param textCompactionData The text compaction data.\n         * @param byteCompactionData The byte compaction data if there\n         *                           was a mode shift.\n         * @param length             The size of the text compaction and byte compaction data.\n         * @param result             The decoded data is appended to the result.\n         */\n        static decodeTextCompaction(textCompactionData, byteCompactionData, length, result) {\n            // Beginning from an initial state of the Alpha sub-mode\n            // The default compaction mode for PDF417 in effect at the start of each symbol shall always be Text\n            // Compaction mode Alpha sub-mode (alphabetic: uppercase). A latch codeword from another mode to the Text\n            // Compaction mode shall always switch to the Text Compaction Alpha sub-mode.\n            let subMode = Mode$2.ALPHA;\n            let priorToShiftMode = Mode$2.ALPHA;\n            let i = 0;\n            while (i < length) {\n                let subModeCh = textCompactionData[i];\n                let ch = /*char*/ '';\n                switch (subMode) {\n                    case Mode$2.ALPHA:\n                        // Alpha (alphabetic: uppercase)\n                        if (subModeCh < 26) {\n                            // Upper case Alpha Character\n                            // Note: 65 = 'A' ASCII -> there is byte code of symbol\n                            ch = /*(char)('A' + subModeCh) */ String.fromCharCode(65 + subModeCh);\n                        }\n                        else {\n                            switch (subModeCh) {\n                                case 26:\n                                    ch = ' ';\n                                    break;\n                                case DecodedBitStreamParser$2.LL:\n                                    subMode = Mode$2.LOWER;\n                                    break;\n                                case DecodedBitStreamParser$2.ML:\n                                    subMode = Mode$2.MIXED;\n                                    break;\n                                case DecodedBitStreamParser$2.PS:\n                                    // Shift to punctuation\n                                    priorToShiftMode = subMode;\n                                    subMode = Mode$2.PUNCT_SHIFT;\n                                    break;\n                                case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n                                    result.append(/*(char)*/ byteCompactionData[i]);\n                                    break;\n                                case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                            }\n                        }\n                        break;\n                    case Mode$2.LOWER:\n                        // Lower (alphabetic: lowercase)\n                        if (subModeCh < 26) {\n                            ch = /*(char)('a' + subModeCh)*/ String.fromCharCode(97 + subModeCh);\n                        }\n                        else {\n                            switch (subModeCh) {\n                                case 26:\n                                    ch = ' ';\n                                    break;\n                                case DecodedBitStreamParser$2.AS:\n                                    // Shift to alpha\n                                    priorToShiftMode = subMode;\n                                    subMode = Mode$2.ALPHA_SHIFT;\n                                    break;\n                                case DecodedBitStreamParser$2.ML:\n                                    subMode = Mode$2.MIXED;\n                                    break;\n                                case DecodedBitStreamParser$2.PS:\n                                    // Shift to punctuation\n                                    priorToShiftMode = subMode;\n                                    subMode = Mode$2.PUNCT_SHIFT;\n                                    break;\n                                case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n                                    // TODO Does this need to use the current character encoding? See other occurrences below\n                                    result.append(/*(char)*/ byteCompactionData[i]);\n                                    break;\n                                case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                            }\n                        }\n                        break;\n                    case Mode$2.MIXED:\n                        // Mixed (punctuation: e)\n                        if (subModeCh < DecodedBitStreamParser$2.PL) {\n                            ch = DecodedBitStreamParser$2.MIXED_CHARS[subModeCh];\n                        }\n                        else {\n                            switch (subModeCh) {\n                                case DecodedBitStreamParser$2.PL:\n                                    subMode = Mode$2.PUNCT;\n                                    break;\n                                case 26:\n                                    ch = ' ';\n                                    break;\n                                case DecodedBitStreamParser$2.LL:\n                                    subMode = Mode$2.LOWER;\n                                    break;\n                                case DecodedBitStreamParser$2.AL:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                                case DecodedBitStreamParser$2.PS:\n                                    // Shift to punctuation\n                                    priorToShiftMode = subMode;\n                                    subMode = Mode$2.PUNCT_SHIFT;\n                                    break;\n                                case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n                                    result.append(/*(char)*/ byteCompactionData[i]);\n                                    break;\n                                case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                            }\n                        }\n                        break;\n                    case Mode$2.PUNCT:\n                        // Punctuation\n                        if (subModeCh < DecodedBitStreamParser$2.PAL) {\n                            ch = DecodedBitStreamParser$2.PUNCT_CHARS[subModeCh];\n                        }\n                        else {\n                            switch (subModeCh) {\n                                case DecodedBitStreamParser$2.PAL:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                                case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n                                    result.append(/*(char)*/ byteCompactionData[i]);\n                                    break;\n                                case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                            }\n                        }\n                        break;\n                    case Mode$2.ALPHA_SHIFT:\n                        // Restore sub-mode\n                        subMode = priorToShiftMode;\n                        if (subModeCh < 26) {\n                            ch = /*(char)('A' + subModeCh)*/ String.fromCharCode(65 + subModeCh);\n                        }\n                        else {\n                            switch (subModeCh) {\n                                case 26:\n                                    ch = ' ';\n                                    break;\n                                case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                            }\n                        }\n                        break;\n                    case Mode$2.PUNCT_SHIFT:\n                        // Restore sub-mode\n                        subMode = priorToShiftMode;\n                        if (subModeCh < DecodedBitStreamParser$2.PAL) {\n                            ch = DecodedBitStreamParser$2.PUNCT_CHARS[subModeCh];\n                        }\n                        else {\n                            switch (subModeCh) {\n                                case DecodedBitStreamParser$2.PAL:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                                case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n                                    // PS before Shift-to-Byte is used as a padding character,\n                                    // see 5.4.2.4 of the specification\n                                    result.append(/*(char)*/ byteCompactionData[i]);\n                                    break;\n                                case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                            }\n                        }\n                        break;\n                }\n                // if (ch !== 0) {\n                if (ch !== '') {\n                    // Append decoded character to result\n                    result.append(ch);\n                }\n                i++;\n            }\n        }\n        /**\n         * Byte Compaction mode (see 5.4.3) permits all 256 possible 8-bit byte values to be encoded.\n         * This includes all ASCII characters value 0 to 127 inclusive and provides for international\n         * character set support.\n         *\n         * @param mode      The byte compaction mode i.e. 901 or 924\n         * @param codewords The array of codewords (data + error)\n         * @param encoding  Currently active character encoding\n         * @param codeIndex The current index into the codeword array.\n         * @param result    The decoded data is appended to the result.\n         * @return The next index into the codeword array.\n         */\n        static /*int*/ byteCompaction(mode, codewords, encoding, codeIndex, result) {\n            let decodedBytes = new ByteArrayOutputStream();\n            let count = 0;\n            let value = /*long*/ 0;\n            let end = false;\n            switch (mode) {\n                case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n                    // Total number of Byte Compaction characters to be encoded\n                    // is not a multiple of 6\n                    let byteCompactedCodewords = new Int32Array(6);\n                    let nextCode = codewords[codeIndex++];\n                    while ((codeIndex < codewords[0]) && !end) {\n                        byteCompactedCodewords[count++] = nextCode;\n                        // Base 900\n                        value = 900 * value + nextCode;\n                        nextCode = codewords[codeIndex++];\n                        // perhaps it should be ok to check only nextCode >= TEXT_COMPACTION_MODE_LATCH\n                        switch (nextCode) {\n                            case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                            case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n                            case DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH:\n                            case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n                            case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n                            case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n                            case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n                                codeIndex--;\n                                end = true;\n                                break;\n                            default:\n                                if ((count % 5 === 0) && (count > 0)) {\n                                    // Decode every 5 codewords\n                                    // Convert to Base 256\n                                    for (let j /*int*/ = 0; j < 6; ++j) {\n                                        /* @note\n                                         * JavaScript stores numbers as 64 bits floating point numbers, but all bitwise operations are performed on 32 bits binary numbers.\n                                         * So the next bitwise operation could not be done with simple numbers\n                                         */\n                                        decodedBytes.write(/*(byte)*/ Number(createBigInt(value) >> createBigInt(8 * (5 - j))));\n                                    }\n                                    value = 0;\n                                    count = 0;\n                                }\n                                break;\n                        }\n                    }\n                    // if the end of all codewords is reached the last codeword needs to be added\n                    if (codeIndex === codewords[0] && nextCode < DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH) {\n                        byteCompactedCodewords[count++] = nextCode;\n                    }\n                    // If Byte Compaction mode is invoked with codeword 901,\n                    // the last group of codewords is interpreted directly\n                    // as one byte per codeword, without compaction.\n                    for (let i /*int*/ = 0; i < count; i++) {\n                        decodedBytes.write(/*(byte)*/ byteCompactedCodewords[i]);\n                    }\n                    break;\n                case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n                    // Total number of Byte Compaction characters to be encoded\n                    // is an integer multiple of 6\n                    while (codeIndex < codewords[0] && !end) {\n                        let code = codewords[codeIndex++];\n                        if (code < DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH) {\n                            count++;\n                            // Base 900\n                            value = 900 * value + code;\n                        }\n                        else {\n                            switch (code) {\n                                case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                                case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n                                case DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH:\n                                case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n                                case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n                                case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n                                case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n                                    codeIndex--;\n                                    end = true;\n                                    break;\n                            }\n                        }\n                        if ((count % 5 === 0) && (count > 0)) {\n                            // Decode every 5 codewords\n                            // Convert to Base 256\n                            /* @note\n                             * JavaScript stores numbers as 64 bits floating point numbers, but all bitwise operations are performed on 32 bits binary numbers.\n                             * So the next bitwise operation could not be done with simple numbers\n                            */\n                            for (let j /*int*/ = 0; j < 6; ++j) {\n                                decodedBytes.write(/*(byte)*/ Number(createBigInt(value) >> createBigInt(8 * (5 - j))));\n                            }\n                            value = 0;\n                            count = 0;\n                        }\n                    }\n                    break;\n            }\n            result.append(StringEncoding.decode(decodedBytes.toByteArray(), encoding));\n            return codeIndex;\n        }\n        /**\n         * Numeric Compaction mode (see 5.4.4) permits efficient encoding of numeric data strings.\n         *\n         * @param codewords The array of codewords (data + error)\n         * @param codeIndex The current index into the codeword array.\n         * @param result    The decoded data is appended to the result.\n         * @return The next index into the codeword array.\n         *\n         * @throws FormatException\n         */\n        static numericCompaction(codewords, codeIndex /*int*/, result) {\n            let count = 0;\n            let end = false;\n            let numericCodewords = new Int32Array(DecodedBitStreamParser$2.MAX_NUMERIC_CODEWORDS);\n            while (codeIndex < codewords[0] && !end) {\n                let code = codewords[codeIndex++];\n                if (codeIndex === codewords[0]) {\n                    end = true;\n                }\n                if (code < DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH) {\n                    numericCodewords[count] = code;\n                    count++;\n                }\n                else {\n                    switch (code) {\n                        case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                        case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n                        case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n                        case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n                        case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n                        case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n                            codeIndex--;\n                            end = true;\n                            break;\n                    }\n                }\n                if ((count % DecodedBitStreamParser$2.MAX_NUMERIC_CODEWORDS === 0 || code === DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH || end) && count > 0) {\n                    // Re-invoking Numeric Compaction mode (by using codeword 902\n                    // while in Numeric Compaction mode) serves  to terminate the\n                    // current Numeric Compaction mode grouping as described in 5.4.4.2,\n                    // and then to start a new one grouping.\n                    result.append(DecodedBitStreamParser$2.decodeBase900toBase10(numericCodewords, count));\n                    count = 0;\n                }\n            }\n            return codeIndex;\n        }\n        /**\n         * Convert a list of Numeric Compacted codewords from Base 900 to Base 10.\n         *\n         * @param codewords The array of codewords\n         * @param count     The number of codewords\n         * @return The decoded string representing the Numeric data.\n         *\n         * EXAMPLE\n         * Encode the fifteen digit numeric string 000213298174000\n         * Prefix the numeric string with a 1 and set the initial value of\n         * t = 1 000 213 298 174 000\n         * Calculate codeword 0\n         * d0 = 1 000 213 298 174 000 mod 900 = 200\n         *\n         * t = 1 000 213 298 174 000 div 900 = 1 111 348 109 082\n         * Calculate codeword 1\n         * d1 = 1 111 348 109 082 mod 900 = 282\n         *\n         * t = 1 111 348 109 082 div 900 = 1 234 831 232\n         * Calculate codeword 2\n         * d2 = 1 234 831 232 mod 900 = 632\n         *\n         * t = 1 234 831 232 div 900 = 1 372 034\n         * Calculate codeword 3\n         * d3 = 1 372 034 mod 900 = 434\n         *\n         * t = 1 372 034 div 900 = 1 524\n         * Calculate codeword 4\n         * d4 = 1 524 mod 900 = 624\n         *\n         * t = 1 524 div 900 = 1\n         * Calculate codeword 5\n         * d5 = 1 mod 900 = 1\n         * t = 1 div 900 = 0\n         * Codeword sequence is: 1, 624, 434, 632, 282, 200\n         *\n         * Decode the above codewords involves\n         *   1 x 900 power of 5 + 624 x 900 power of 4 + 434 x 900 power of 3 +\n         * 632 x 900 power of 2 + 282 x 900 power of 1 + 200 x 900 power of 0 = 1000213298174000\n         *\n         * Remove leading 1 =>  Result is 000213298174000\n         *\n         * @throws FormatException\n         */\n        static decodeBase900toBase10(codewords, count) {\n            let result = createBigInt(0);\n            for (let i /*int*/ = 0; i < count; i++) {\n                result += DecodedBitStreamParser$2.EXP900[count - i - 1] * createBigInt(codewords[i]);\n            }\n            let resultString = result.toString();\n            if (resultString.charAt(0) !== '1') {\n                throw new FormatException();\n            }\n            return resultString.substring(1);\n        }\n    }\n    DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH = 900;\n    DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH = 901;\n    DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH = 902;\n    DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6 = 924;\n    DecodedBitStreamParser$2.ECI_USER_DEFINED = 925;\n    DecodedBitStreamParser$2.ECI_GENERAL_PURPOSE = 926;\n    DecodedBitStreamParser$2.ECI_CHARSET = 927;\n    DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK = 928;\n    DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD = 923;\n    DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR = 922;\n    DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE = 913;\n    DecodedBitStreamParser$2.MAX_NUMERIC_CODEWORDS = 15;\n    DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME = 0;\n    DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT = 1;\n    DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP = 2;\n    DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_SENDER = 3;\n    DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE = 4;\n    DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE = 5;\n    DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM = 6;\n    DecodedBitStreamParser$2.PL = 25;\n    DecodedBitStreamParser$2.LL = 27;\n    DecodedBitStreamParser$2.AS = 27;\n    DecodedBitStreamParser$2.ML = 28;\n    DecodedBitStreamParser$2.AL = 28;\n    DecodedBitStreamParser$2.PS = 29;\n    DecodedBitStreamParser$2.PAL = 29;\n    DecodedBitStreamParser$2.PUNCT_CHARS = ';<>@[\\\\]_`~!\\r\\t,:\\n-.$/\"|*()?{}\\'';\n    DecodedBitStreamParser$2.MIXED_CHARS = '0123456789&\\r\\t,:#-.$/+%*=^';\n    /**\n     * Table containing values for the exponent of 900.\n     * This is used in the numeric compaction decode algorithm.\n     */\n    DecodedBitStreamParser$2.EXP900 = getBigIntConstructor() ? getEXP900() : [];\n    DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS = 2;\n\n    /*\n    * Copyright 2013 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    // import java.util.ArrayList;\n    // import java.util.Collection;\n    // import java.util.Formatter;\n    // import java.util.List;\n    /**\n     * @author Guenther Grau\n     */\n    /*public final*/ class PDF417ScanningDecoder {\n        constructor() { }\n        /**\n         * @TODO don't pass in minCodewordWidth and maxCodewordWidth, pass in barcode columns for start and stop pattern\n         *\n         * columns. That way width can be deducted from the pattern column.\n         * This approach also allows to detect more details about the barcode, e.g. if a bar type (white or black) is wider\n         * than it should be. This can happen if the scanner used a bad blackpoint.\n         *\n         * @param BitMatrix\n         * @param image\n         * @param ResultPoint\n         * @param imageTopLeft\n         * @param ResultPoint\n         * @param imageBottomLeft\n         * @param ResultPoint\n         * @param imageTopRight\n         * @param ResultPoint\n         * @param imageBottomRight\n         * @param int\n         * @param minCodewordWidth\n         * @param int\n         * @param maxCodewordWidth\n         *\n         * @throws NotFoundException\n         * @throws FormatException\n         * @throws ChecksumException\n         */\n        static decode(image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight, minCodewordWidth, maxCodewordWidth) {\n            let boundingBox = new BoundingBox(image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight);\n            let leftRowIndicatorColumn = null;\n            let rightRowIndicatorColumn = null;\n            let detectionResult;\n            for (let firstPass /*boolean*/ = true;; firstPass = false) {\n                if (imageTopLeft != null) {\n                    leftRowIndicatorColumn = PDF417ScanningDecoder.getRowIndicatorColumn(image, boundingBox, imageTopLeft, true, minCodewordWidth, maxCodewordWidth);\n                }\n                if (imageTopRight != null) {\n                    rightRowIndicatorColumn = PDF417ScanningDecoder.getRowIndicatorColumn(image, boundingBox, imageTopRight, false, minCodewordWidth, maxCodewordWidth);\n                }\n                detectionResult = PDF417ScanningDecoder.merge(leftRowIndicatorColumn, rightRowIndicatorColumn);\n                if (detectionResult == null) {\n                    throw NotFoundException.getNotFoundInstance();\n                }\n                let resultBox = detectionResult.getBoundingBox();\n                if (firstPass && resultBox != null &&\n                    (resultBox.getMinY() < boundingBox.getMinY() || resultBox.getMaxY() > boundingBox.getMaxY())) {\n                    boundingBox = resultBox;\n                }\n                else {\n                    break;\n                }\n            }\n            detectionResult.setBoundingBox(boundingBox);\n            let maxBarcodeColumn = detectionResult.getBarcodeColumnCount() + 1;\n            detectionResult.setDetectionResultColumn(0, leftRowIndicatorColumn);\n            detectionResult.setDetectionResultColumn(maxBarcodeColumn, rightRowIndicatorColumn);\n            let leftToRight = leftRowIndicatorColumn != null;\n            for (let barcodeColumnCount /*int*/ = 1; barcodeColumnCount <= maxBarcodeColumn; barcodeColumnCount++) {\n                let barcodeColumn = leftToRight ? barcodeColumnCount : maxBarcodeColumn - barcodeColumnCount;\n                if (detectionResult.getDetectionResultColumn(barcodeColumn) !== /* null */ undefined) {\n                    // This will be the case for the opposite row indicator column, which doesn't need to be decoded again.\n                    continue;\n                }\n                let detectionResultColumn;\n                if (barcodeColumn === 0 || barcodeColumn === maxBarcodeColumn) {\n                    detectionResultColumn = new DetectionResultRowIndicatorColumn(boundingBox, barcodeColumn === 0);\n                }\n                else {\n                    detectionResultColumn = new DetectionResultColumn(boundingBox);\n                }\n                detectionResult.setDetectionResultColumn(barcodeColumn, detectionResultColumn);\n                let startColumn = -1;\n                let previousStartColumn = startColumn;\n                // TODO start at a row for which we know the start position, then detect upwards and downwards from there.\n                for (let imageRow /*int*/ = boundingBox.getMinY(); imageRow <= boundingBox.getMaxY(); imageRow++) {\n                    startColumn = PDF417ScanningDecoder.getStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight);\n                    if (startColumn < 0 || startColumn > boundingBox.getMaxX()) {\n                        if (previousStartColumn === -1) {\n                            continue;\n                        }\n                        startColumn = previousStartColumn;\n                    }\n                    let codeword = PDF417ScanningDecoder.detectCodeword(image, boundingBox.getMinX(), boundingBox.getMaxX(), leftToRight, startColumn, imageRow, minCodewordWidth, maxCodewordWidth);\n                    if (codeword != null) {\n                        detectionResultColumn.setCodeword(imageRow, codeword);\n                        previousStartColumn = startColumn;\n                        minCodewordWidth = Math.min(minCodewordWidth, codeword.getWidth());\n                        maxCodewordWidth = Math.max(maxCodewordWidth, codeword.getWidth());\n                    }\n                }\n            }\n            return PDF417ScanningDecoder.createDecoderResult(detectionResult);\n        }\n        /**\n         *\n         * @param leftRowIndicatorColumn\n         * @param rightRowIndicatorColumn\n         *\n         * @throws NotFoundException\n         */\n        static merge(leftRowIndicatorColumn, rightRowIndicatorColumn) {\n            if (leftRowIndicatorColumn == null && rightRowIndicatorColumn == null) {\n                return null;\n            }\n            let barcodeMetadata = PDF417ScanningDecoder.getBarcodeMetadata(leftRowIndicatorColumn, rightRowIndicatorColumn);\n            if (barcodeMetadata == null) {\n                return null;\n            }\n            let boundingBox = BoundingBox.merge(PDF417ScanningDecoder.adjustBoundingBox(leftRowIndicatorColumn), PDF417ScanningDecoder.adjustBoundingBox(rightRowIndicatorColumn));\n            return new DetectionResult(barcodeMetadata, boundingBox);\n        }\n        /**\n         *\n         * @param rowIndicatorColumn\n         *\n         * @throws NotFoundException\n         */\n        static adjustBoundingBox(rowIndicatorColumn) {\n            if (rowIndicatorColumn == null) {\n                return null;\n            }\n            let rowHeights = rowIndicatorColumn.getRowHeights();\n            if (rowHeights == null) {\n                return null;\n            }\n            let maxRowHeight = PDF417ScanningDecoder.getMax(rowHeights);\n            let missingStartRows = 0;\n            for (let rowHeight /*int*/ of rowHeights) {\n                missingStartRows += maxRowHeight - rowHeight;\n                if (rowHeight > 0) {\n                    break;\n                }\n            }\n            let codewords = rowIndicatorColumn.getCodewords();\n            for (let row /*int*/ = 0; missingStartRows > 0 && codewords[row] == null; row++) {\n                missingStartRows--;\n            }\n            let missingEndRows = 0;\n            for (let row /*int*/ = rowHeights.length - 1; row >= 0; row--) {\n                missingEndRows += maxRowHeight - rowHeights[row];\n                if (rowHeights[row] > 0) {\n                    break;\n                }\n            }\n            for (let row /*int*/ = codewords.length - 1; missingEndRows > 0 && codewords[row] == null; row--) {\n                missingEndRows--;\n            }\n            return rowIndicatorColumn.getBoundingBox().addMissingRows(missingStartRows, missingEndRows, rowIndicatorColumn.isLeft());\n        }\n        static getMax(values) {\n            let maxValue = -1;\n            for (let value /*int*/ of values) {\n                maxValue = Math.max(maxValue, value);\n            }\n            return maxValue;\n        }\n        static getBarcodeMetadata(leftRowIndicatorColumn, rightRowIndicatorColumn) {\n            let leftBarcodeMetadata;\n            if (leftRowIndicatorColumn == null ||\n                (leftBarcodeMetadata = leftRowIndicatorColumn.getBarcodeMetadata()) == null) {\n                return rightRowIndicatorColumn == null ? null : rightRowIndicatorColumn.getBarcodeMetadata();\n            }\n            let rightBarcodeMetadata;\n            if (rightRowIndicatorColumn == null ||\n                (rightBarcodeMetadata = rightRowIndicatorColumn.getBarcodeMetadata()) == null) {\n                return leftBarcodeMetadata;\n            }\n            if (leftBarcodeMetadata.getColumnCount() !== rightBarcodeMetadata.getColumnCount() &&\n                leftBarcodeMetadata.getErrorCorrectionLevel() !== rightBarcodeMetadata.getErrorCorrectionLevel() &&\n                leftBarcodeMetadata.getRowCount() !== rightBarcodeMetadata.getRowCount()) {\n                return null;\n            }\n            return leftBarcodeMetadata;\n        }\n        static getRowIndicatorColumn(image, boundingBox, startPoint, leftToRight, minCodewordWidth, maxCodewordWidth) {\n            let rowIndicatorColumn = new DetectionResultRowIndicatorColumn(boundingBox, leftToRight);\n            for (let i /*int*/ = 0; i < 2; i++) {\n                let increment = i === 0 ? 1 : -1;\n                let startColumn = Math.trunc(Math.trunc(startPoint.getX()));\n                for (let imageRow /*int*/ = Math.trunc(Math.trunc(startPoint.getY())); imageRow <= boundingBox.getMaxY() &&\n                    imageRow >= boundingBox.getMinY(); imageRow += increment) {\n                    let codeword = PDF417ScanningDecoder.detectCodeword(image, 0, image.getWidth(), leftToRight, startColumn, imageRow, minCodewordWidth, maxCodewordWidth);\n                    if (codeword != null) {\n                        rowIndicatorColumn.setCodeword(imageRow, codeword);\n                        if (leftToRight) {\n                            startColumn = codeword.getStartX();\n                        }\n                        else {\n                            startColumn = codeword.getEndX();\n                        }\n                    }\n                }\n            }\n            return rowIndicatorColumn;\n        }\n        /**\n         *\n         * @param detectionResult\n         * @param BarcodeValue\n         * @param param2\n         * @param param3\n         * @param barcodeMatrix\n         *\n         * @throws NotFoundException\n         */\n        static adjustCodewordCount(detectionResult, barcodeMatrix) {\n            let barcodeMatrix01 = barcodeMatrix[0][1];\n            let numberOfCodewords = barcodeMatrix01.getValue();\n            let calculatedNumberOfCodewords = detectionResult.getBarcodeColumnCount() *\n                detectionResult.getBarcodeRowCount() -\n                PDF417ScanningDecoder.getNumberOfECCodeWords(detectionResult.getBarcodeECLevel());\n            if (numberOfCodewords.length === 0) {\n                if (calculatedNumberOfCodewords < 1 || calculatedNumberOfCodewords > PDF417Common.MAX_CODEWORDS_IN_BARCODE) {\n                    throw NotFoundException.getNotFoundInstance();\n                }\n                barcodeMatrix01.setValue(calculatedNumberOfCodewords);\n            }\n            else if (numberOfCodewords[0] !== calculatedNumberOfCodewords) {\n                // The calculated one is more reliable as it is derived from the row indicator columns\n                barcodeMatrix01.setValue(calculatedNumberOfCodewords);\n            }\n        }\n        /**\n         *\n         * @param detectionResult\n         *\n         * @throws FormatException\n         * @throws ChecksumException\n         * @throws NotFoundException\n         */\n        static createDecoderResult(detectionResult) {\n            let barcodeMatrix = PDF417ScanningDecoder.createBarcodeMatrix(detectionResult);\n            PDF417ScanningDecoder.adjustCodewordCount(detectionResult, barcodeMatrix);\n            let erasures /*Collection<Integer>*/ = new Array();\n            let codewords = new Int32Array(detectionResult.getBarcodeRowCount() * detectionResult.getBarcodeColumnCount());\n            let ambiguousIndexValuesList = /*List<int[]>*/ [];\n            let ambiguousIndexesList = /*Collection<Integer>*/ new Array();\n            for (let row /*int*/ = 0; row < detectionResult.getBarcodeRowCount(); row++) {\n                for (let column /*int*/ = 0; column < detectionResult.getBarcodeColumnCount(); column++) {\n                    let values = barcodeMatrix[row][column + 1].getValue();\n                    let codewordIndex = row * detectionResult.getBarcodeColumnCount() + column;\n                    if (values.length === 0) {\n                        erasures.push(codewordIndex);\n                    }\n                    else if (values.length === 1) {\n                        codewords[codewordIndex] = values[0];\n                    }\n                    else {\n                        ambiguousIndexesList.push(codewordIndex);\n                        ambiguousIndexValuesList.push(values);\n                    }\n                }\n            }\n            let ambiguousIndexValues = new Array(ambiguousIndexValuesList.length);\n            for (let i /*int*/ = 0; i < ambiguousIndexValues.length; i++) {\n                ambiguousIndexValues[i] = ambiguousIndexValuesList[i];\n            }\n            return PDF417ScanningDecoder.createDecoderResultFromAmbiguousValues(detectionResult.getBarcodeECLevel(), codewords, PDF417Common.toIntArray(erasures), PDF417Common.toIntArray(ambiguousIndexesList), ambiguousIndexValues);\n        }\n        /**\n         * This method deals with the fact, that the decoding process doesn't always yield a single most likely value. The\n         * current error correction implementation doesn't deal with erasures very well, so it's better to provide a value\n         * for these ambiguous codewords instead of treating it as an erasure. The problem is that we don't know which of\n         * the ambiguous values to choose. We try decode using the first value, and if that fails, we use another of the\n         * ambiguous values and try to decode again. This usually only happens on very hard to read and decode barcodes,\n         * so decoding the normal barcodes is not affected by this.\n         *\n         * @param erasureArray contains the indexes of erasures\n         * @param ambiguousIndexes array with the indexes that have more than one most likely value\n         * @param ambiguousIndexValues two dimensional array that contains the ambiguous values. The first dimension must\n         * be the same length as the ambiguousIndexes array\n         *\n         * @throws FormatException\n         * @throws ChecksumException\n         */\n        static createDecoderResultFromAmbiguousValues(ecLevel, codewords, erasureArray, ambiguousIndexes, ambiguousIndexValues) {\n            let ambiguousIndexCount = new Int32Array(ambiguousIndexes.length);\n            let tries = 100;\n            while (tries-- > 0) {\n                for (let i /*int*/ = 0; i < ambiguousIndexCount.length; i++) {\n                    codewords[ambiguousIndexes[i]] = ambiguousIndexValues[i][ambiguousIndexCount[i]];\n                }\n                try {\n                    return PDF417ScanningDecoder.decodeCodewords(codewords, ecLevel, erasureArray);\n                }\n                catch (err) {\n                    let ignored = err instanceof ChecksumException;\n                    if (!ignored) {\n                        throw err;\n                    }\n                }\n                if (ambiguousIndexCount.length === 0) {\n                    throw ChecksumException.getChecksumInstance();\n                }\n                for (let i /*int*/ = 0; i < ambiguousIndexCount.length; i++) {\n                    if (ambiguousIndexCount[i] < ambiguousIndexValues[i].length - 1) {\n                        ambiguousIndexCount[i]++;\n                        break;\n                    }\n                    else {\n                        ambiguousIndexCount[i] = 0;\n                        if (i === ambiguousIndexCount.length - 1) {\n                            throw ChecksumException.getChecksumInstance();\n                        }\n                    }\n                }\n            }\n            throw ChecksumException.getChecksumInstance();\n        }\n        static createBarcodeMatrix(detectionResult) {\n            // let barcodeMatrix: BarcodeValue[][] =\n            // new BarcodeValue[detectionResult.getBarcodeRowCount()][detectionResult.getBarcodeColumnCount() + 2];\n            let barcodeMatrix = Array.from({ length: detectionResult.getBarcodeRowCount() }, () => new Array(detectionResult.getBarcodeColumnCount() + 2));\n            for (let row /*int*/ = 0; row < barcodeMatrix.length; row++) {\n                for (let column /*int*/ = 0; column < barcodeMatrix[row].length; column++) {\n                    barcodeMatrix[row][column] = new BarcodeValue();\n                }\n            }\n            let column = 0;\n            for (let detectionResultColumn /*DetectionResultColumn*/ of detectionResult.getDetectionResultColumns()) {\n                if (detectionResultColumn != null) {\n                    for (let codeword /*Codeword*/ of detectionResultColumn.getCodewords()) {\n                        if (codeword != null) {\n                            let rowNumber = codeword.getRowNumber();\n                            if (rowNumber >= 0) {\n                                if (rowNumber >= barcodeMatrix.length) {\n                                    // We have more rows than the barcode metadata allows for, ignore them.\n                                    continue;\n                                }\n                                barcodeMatrix[rowNumber][column].setValue(codeword.getValue());\n                            }\n                        }\n                    }\n                }\n                column++;\n            }\n            return barcodeMatrix;\n        }\n        static isValidBarcodeColumn(detectionResult, barcodeColumn) {\n            return barcodeColumn >= 0 && barcodeColumn <= detectionResult.getBarcodeColumnCount() + 1;\n        }\n        static getStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight) {\n            let offset = leftToRight ? 1 : -1;\n            let codeword = null;\n            if (PDF417ScanningDecoder.isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) {\n                codeword = detectionResult.getDetectionResultColumn(barcodeColumn - offset).getCodeword(imageRow);\n            }\n            if (codeword != null) {\n                return leftToRight ? codeword.getEndX() : codeword.getStartX();\n            }\n            codeword = detectionResult.getDetectionResultColumn(barcodeColumn).getCodewordNearby(imageRow);\n            if (codeword != null) {\n                return leftToRight ? codeword.getStartX() : codeword.getEndX();\n            }\n            if (PDF417ScanningDecoder.isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) {\n                codeword = detectionResult.getDetectionResultColumn(barcodeColumn - offset).getCodewordNearby(imageRow);\n            }\n            if (codeword != null) {\n                return leftToRight ? codeword.getEndX() : codeword.getStartX();\n            }\n            let skippedColumns = 0;\n            while (PDF417ScanningDecoder.isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) {\n                barcodeColumn -= offset;\n                for (let previousRowCodeword /*Codeword*/ of detectionResult.getDetectionResultColumn(barcodeColumn).getCodewords()) {\n                    if (previousRowCodeword != null) {\n                        return (leftToRight ? previousRowCodeword.getEndX() : previousRowCodeword.getStartX()) +\n                            offset *\n                                skippedColumns *\n                                (previousRowCodeword.getEndX() - previousRowCodeword.getStartX());\n                    }\n                }\n                skippedColumns++;\n            }\n            return leftToRight ? detectionResult.getBoundingBox().getMinX() : detectionResult.getBoundingBox().getMaxX();\n        }\n        static detectCodeword(image, minColumn, maxColumn, leftToRight, startColumn, imageRow, minCodewordWidth, maxCodewordWidth) {\n            startColumn = PDF417ScanningDecoder.adjustCodewordStartColumn(image, minColumn, maxColumn, leftToRight, startColumn, imageRow);\n            // we usually know fairly exact now how long a codeword is. We should provide minimum and maximum expected length\n            // and try to adjust the read pixels, e.g. remove single pixel errors or try to cut off exceeding pixels.\n            // min and maxCodewordWidth should not be used as they are calculated for the whole barcode an can be inaccurate\n            // for the current position\n            let moduleBitCount = PDF417ScanningDecoder.getModuleBitCount(image, minColumn, maxColumn, leftToRight, startColumn, imageRow);\n            if (moduleBitCount == null) {\n                return null;\n            }\n            let endColumn;\n            let codewordBitCount = MathUtils.sum(moduleBitCount);\n            if (leftToRight) {\n                endColumn = startColumn + codewordBitCount;\n            }\n            else {\n                for (let i /*int*/ = 0; i < moduleBitCount.length / 2; i++) {\n                    let tmpCount = moduleBitCount[i];\n                    moduleBitCount[i] = moduleBitCount[moduleBitCount.length - 1 - i];\n                    moduleBitCount[moduleBitCount.length - 1 - i] = tmpCount;\n                }\n                endColumn = startColumn;\n                startColumn = endColumn - codewordBitCount;\n            }\n            // TODO implement check for width and correction of black and white bars\n            // use start (and maybe stop pattern) to determine if black bars are wider than white bars. If so, adjust.\n            // should probably done only for codewords with a lot more than 17 bits.\n            // The following fixes 10-1.png, which has wide black bars and small white bars\n            //    for (let i /*int*/ = 0; i < moduleBitCount.length; i++) {\n            //      if (i % 2 === 0) {\n            //        moduleBitCount[i]--;\n            //      } else {\n            //        moduleBitCount[i]++;\n            //      }\n            //    }\n            // We could also use the width of surrounding codewords for more accurate results, but this seems\n            // sufficient for now\n            if (!PDF417ScanningDecoder.checkCodewordSkew(codewordBitCount, minCodewordWidth, maxCodewordWidth)) {\n                // We could try to use the startX and endX position of the codeword in the same column in the previous row,\n                // create the bit count from it and normalize it to 8. This would help with single pixel errors.\n                return null;\n            }\n            let decodedValue = PDF417CodewordDecoder.getDecodedValue(moduleBitCount);\n            let codeword = PDF417Common.getCodeword(decodedValue);\n            if (codeword === -1) {\n                return null;\n            }\n            return new Codeword(startColumn, endColumn, PDF417ScanningDecoder.getCodewordBucketNumber(decodedValue), codeword);\n        }\n        static getModuleBitCount(image, minColumn, maxColumn, leftToRight, startColumn, imageRow) {\n            let imageColumn = startColumn;\n            let moduleBitCount = new Int32Array(8);\n            let moduleNumber = 0;\n            let increment = leftToRight ? 1 : -1;\n            let previousPixelValue = leftToRight;\n            while ((leftToRight ? imageColumn < maxColumn : imageColumn >= minColumn) &&\n                moduleNumber < moduleBitCount.length) {\n                if (image.get(imageColumn, imageRow) === previousPixelValue) {\n                    moduleBitCount[moduleNumber]++;\n                    imageColumn += increment;\n                }\n                else {\n                    moduleNumber++;\n                    previousPixelValue = !previousPixelValue;\n                }\n            }\n            if (moduleNumber === moduleBitCount.length ||\n                ((imageColumn === (leftToRight ? maxColumn : minColumn)) &&\n                    moduleNumber === moduleBitCount.length - 1)) {\n                return moduleBitCount;\n            }\n            return null;\n        }\n        static getNumberOfECCodeWords(barcodeECLevel) {\n            return 2 << barcodeECLevel;\n        }\n        static adjustCodewordStartColumn(image, minColumn, maxColumn, leftToRight, codewordStartColumn, imageRow) {\n            let correctedStartColumn = codewordStartColumn;\n            let increment = leftToRight ? -1 : 1;\n            // there should be no black pixels before the start column. If there are, then we need to start earlier.\n            for (let i /*int*/ = 0; i < 2; i++) {\n                while ((leftToRight ? correctedStartColumn >= minColumn : correctedStartColumn < maxColumn) &&\n                    leftToRight === image.get(correctedStartColumn, imageRow)) {\n                    if (Math.abs(codewordStartColumn - correctedStartColumn) > PDF417ScanningDecoder.CODEWORD_SKEW_SIZE) {\n                        return codewordStartColumn;\n                    }\n                    correctedStartColumn += increment;\n                }\n                increment = -increment;\n                leftToRight = !leftToRight;\n            }\n            return correctedStartColumn;\n        }\n        static checkCodewordSkew(codewordSize, minCodewordWidth, maxCodewordWidth) {\n            return minCodewordWidth - PDF417ScanningDecoder.CODEWORD_SKEW_SIZE <= codewordSize &&\n                codewordSize <= maxCodewordWidth + PDF417ScanningDecoder.CODEWORD_SKEW_SIZE;\n        }\n        /**\n         * @throws FormatException,\n         * @throws ChecksumException\n         */\n        static decodeCodewords(codewords, ecLevel, erasures) {\n            if (codewords.length === 0) {\n                throw FormatException.getFormatInstance();\n            }\n            let numECCodewords = 1 << (ecLevel + 1);\n            let correctedErrorsCount = PDF417ScanningDecoder.correctErrors(codewords, erasures, numECCodewords);\n            PDF417ScanningDecoder.verifyCodewordCount(codewords, numECCodewords);\n            // Decode the codewords\n            let decoderResult = DecodedBitStreamParser$2.decode(codewords, '' + ecLevel);\n            decoderResult.setErrorsCorrected(correctedErrorsCount);\n            decoderResult.setErasures(erasures.length);\n            return decoderResult;\n        }\n        /**\n         * <p>Given data and error-correction codewords received, possibly corrupted by errors, attempts to\n         * correct the errors in-place.</p>\n         *\n         * @param codewords   data and error correction codewords\n         * @param erasures positions of any known erasures\n         * @param numECCodewords number of error correction codewords that are available in codewords\n         * @throws ChecksumException if error correction fails\n         */\n        static correctErrors(codewords, erasures, numECCodewords) {\n            if (erasures != null &&\n                erasures.length > numECCodewords / 2 + PDF417ScanningDecoder.MAX_ERRORS ||\n                numECCodewords < 0 ||\n                numECCodewords > PDF417ScanningDecoder.MAX_EC_CODEWORDS) {\n                // Too many errors or EC Codewords is corrupted\n                throw ChecksumException.getChecksumInstance();\n            }\n            return PDF417ScanningDecoder.errorCorrection.decode(codewords, numECCodewords, erasures);\n        }\n        /**\n         * Verify that all is OK with the codeword array.\n         * @throws FormatException\n         */\n        static verifyCodewordCount(codewords, numECCodewords) {\n            if (codewords.length < 4) {\n                // Codeword array size should be at least 4 allowing for\n                // Count CW, At least one Data CW, Error Correction CW, Error Correction CW\n                throw FormatException.getFormatInstance();\n            }\n            // The first codeword, the Symbol Length Descriptor, shall always encode the total number of data\n            // codewords in the symbol, including the Symbol Length Descriptor itself, data codewords and pad\n            // codewords, but excluding the number of error correction codewords.\n            let numberOfCodewords = codewords[0];\n            if (numberOfCodewords > codewords.length) {\n                throw FormatException.getFormatInstance();\n            }\n            if (numberOfCodewords === 0) {\n                // Reset to the length of the array - 8 (Allow for at least level 3 Error Correction (8 Error Codewords)\n                if (numECCodewords < codewords.length) {\n                    codewords[0] = codewords.length - numECCodewords;\n                }\n                else {\n                    throw FormatException.getFormatInstance();\n                }\n            }\n        }\n        static getBitCountForCodeword(codeword) {\n            let result = new Int32Array(8);\n            let previousValue = 0;\n            let i = result.length - 1;\n            while (true) {\n                if ((codeword & 0x1) !== previousValue) {\n                    previousValue = codeword & 0x1;\n                    i--;\n                    if (i < 0) {\n                        break;\n                    }\n                }\n                result[i]++;\n                codeword >>= 1;\n            }\n            return result;\n        }\n        static getCodewordBucketNumber(codeword) {\n            if (codeword instanceof Int32Array) {\n                return this.getCodewordBucketNumber_Int32Array(codeword);\n            }\n            return this.getCodewordBucketNumber_number(codeword);\n        }\n        static getCodewordBucketNumber_number(codeword) {\n            return PDF417ScanningDecoder.getCodewordBucketNumber(PDF417ScanningDecoder.getBitCountForCodeword(codeword));\n        }\n        static getCodewordBucketNumber_Int32Array(moduleBitCount) {\n            return (moduleBitCount[0] - moduleBitCount[2] + moduleBitCount[4] - moduleBitCount[6] + 9) % 9;\n        }\n        static toString(barcodeMatrix) {\n            let formatter = new Formatter();\n            // try (let formatter = new Formatter()) {\n            for (let row /*int*/ = 0; row < barcodeMatrix.length; row++) {\n                formatter.format('Row %2d: ', row);\n                for (let column /*int*/ = 0; column < barcodeMatrix[row].length; column++) {\n                    let barcodeValue = barcodeMatrix[row][column];\n                    if (barcodeValue.getValue().length === 0) {\n                        formatter.format('        ', null);\n                    }\n                    else {\n                        formatter.format('%4d(%2d)', barcodeValue.getValue()[0], barcodeValue.getConfidence(barcodeValue.getValue()[0]));\n                    }\n                }\n                formatter.format('%n');\n            }\n            return formatter.toString();\n            // }\n        }\n    }\n    /*final*/ PDF417ScanningDecoder.CODEWORD_SKEW_SIZE = 2;\n    /*final*/ PDF417ScanningDecoder.MAX_ERRORS = 3;\n    /*final*/ PDF417ScanningDecoder.MAX_EC_CODEWORDS = 512;\n    /*final*/ PDF417ScanningDecoder.errorCorrection = new ErrorCorrection();\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    // import java.util.ArrayList;\n    // import java.util.List;\n    // import java.util.Map;\n    /**\n     * This implementation can detect and decode PDF417 codes in an image.\n     *\n     * @author Guenther Grau\n     */\n    /*public final*/ class PDF417Reader {\n        // private static /*final Result[]*/ EMPTY_RESULT_ARRAY: Result[] = new Result([0]);\n        /**\n         * Locates and decodes a PDF417 code in an image.\n         *\n         * @return a String representing the content encoded by the PDF417 code\n         * @throws NotFoundException if a PDF417 code cannot be found,\n         * @throws FormatException if a PDF417 cannot be decoded\n         * @throws ChecksumException\n         */\n        // @Override\n        decode(image, hints = null) {\n            let result = PDF417Reader.decode(image, hints, false);\n            if (result == null || result.length === 0 || result[0] == null) {\n                throw NotFoundException.getNotFoundInstance();\n            }\n            return result[0];\n        }\n        /**\n         *\n         * @param BinaryBitmap\n         * @param image\n         * @throws NotFoundException\n         */\n        //   @Override\n        decodeMultiple(image, hints = null) {\n            try {\n                return PDF417Reader.decode(image, hints, true);\n            }\n            catch (ignored) {\n                if (ignored instanceof FormatException || ignored instanceof ChecksumException) {\n                    throw NotFoundException.getNotFoundInstance();\n                }\n                throw ignored;\n            }\n        }\n        /**\n         *\n         * @param image\n         * @param hints\n         * @param multiple\n         *\n         * @throws NotFoundException\n         * @throws FormatExceptionß\n         * @throws ChecksumException\n         */\n        static decode(image, hints, multiple) {\n            const results = new Array();\n            const detectorResult = Detector$3.detectMultiple(image, hints, multiple);\n            for (const points of detectorResult.getPoints()) {\n                const decoderResult = PDF417ScanningDecoder.decode(detectorResult.getBits(), points[4], points[5], points[6], points[7], PDF417Reader.getMinCodewordWidth(points), PDF417Reader.getMaxCodewordWidth(points));\n                const result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), undefined, points, BarcodeFormat$1.PDF_417);\n                result.putMetadata(ResultMetadataType$1.ERROR_CORRECTION_LEVEL, decoderResult.getECLevel());\n                const pdf417ResultMetadata = decoderResult.getOther();\n                if (pdf417ResultMetadata != null) {\n                    result.putMetadata(ResultMetadataType$1.PDF417_EXTRA_METADATA, pdf417ResultMetadata);\n                }\n                results.push(result);\n            }\n            return results.map(x => x);\n        }\n        static getMaxWidth(p1, p2) {\n            if (p1 == null || p2 == null) {\n                return 0;\n            }\n            return Math.trunc(Math.abs(p1.getX() - p2.getX()));\n        }\n        static getMinWidth(p1, p2) {\n            if (p1 == null || p2 == null) {\n                return Integer.MAX_VALUE;\n            }\n            return Math.trunc(Math.abs(p1.getX() - p2.getX()));\n        }\n        static getMaxCodewordWidth(p) {\n            return Math.floor(Math.max(Math.max(PDF417Reader.getMaxWidth(p[0], p[4]), PDF417Reader.getMaxWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD /\n                PDF417Common.MODULES_IN_STOP_PATTERN), Math.max(PDF417Reader.getMaxWidth(p[1], p[5]), PDF417Reader.getMaxWidth(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD /\n                PDF417Common.MODULES_IN_STOP_PATTERN)));\n        }\n        static getMinCodewordWidth(p) {\n            return Math.floor(Math.min(Math.min(PDF417Reader.getMinWidth(p[0], p[4]), PDF417Reader.getMinWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD /\n                PDF417Common.MODULES_IN_STOP_PATTERN), Math.min(PDF417Reader.getMinWidth(p[1], p[5]), PDF417Reader.getMinWidth(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD /\n                PDF417Common.MODULES_IN_STOP_PATTERN)));\n        }\n        // @Override\n        reset() {\n            // nothing needs to be reset\n        }\n    }\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class ReaderException extends Exception {\n    }\n    ReaderException.kind = 'ReaderException';\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing {*/\n    /**\n     * MultiFormatReader is a convenience class and the main entry point into the library for most uses.\n     * By default it attempts to decode all barcode formats that the library supports. Optionally, you\n     * can provide a hints object to request different behavior, for example only decoding QR codes.\n     *\n     * @author Sean Owen\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class MultiFormatReader {\n        /**\n         * Creates an instance of this class\n         * \n         * @param {Boolean} verbose if 'true' logs will be dumped to console, otherwise hidden.\n         * @param hints The hints to use, clearing the previous state.\n         */\n        constructor(verbose, hints) {\n            this.verbose = (verbose === true);\n            if (hints) {\n                this.setHints(hints);\n            }\n        }\n        /**\n         * This version of decode honors the intent of Reader.decode(BinaryBitmap) in that it\n         * passes null as a hint to the decoders. However, that makes it inefficient to call repeatedly.\n         * Use setHints() followed by decodeWithState() for continuous scan applications.\n         *\n         * @param image The pixel data to decode\n         * @return The contents of the image\n         *\n         * @throws NotFoundException Any errors which occurred\n         */\n        /*@Override*/\n        // public decode(image: BinaryBitmap): Result {\n        //   setHints(null)\n        //   return decodeInternal(image)\n        // }\n        /**\n         * Decode an image using the hints provided. Does not honor existing state.\n         *\n         * @param image The pixel data to decode\n         * @param hints The hints to use, clearing the previous state.\n         * @return The contents of the image\n         *\n         * @throws NotFoundException Any errors which occurred\n         */\n        /*@Override*/\n        decode(image, hints) {\n            if (hints) {\n                this.setHints(hints);\n            }\n            return this.decodeInternal(image);\n        }\n        /**\n         * Decode an image using the state set up by calling setHints() previously. Continuous scan\n         * clients will get a <b>large</b> speed increase by using this instead of decode().\n         *\n         * @param image The pixel data to decode\n         * @return The contents of the image\n         *\n         * @throws NotFoundException Any errors which occurred\n         */\n        decodeWithState(image) {\n            // Make sure to set up the default state so we don't crash\n            if (this.readers === null || this.readers === undefined) {\n                this.setHints(null);\n            }\n            return this.decodeInternal(image);\n        }\n        /**\n         * This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls\n         * to decodeWithState(image) can reuse the same set of readers without reallocating memory. This\n         * is important for performance in continuous scan clients.\n         *\n         * @param hints The set of hints to use for subsequent calls to decode(image)\n         */\n        setHints(hints) {\n            this.hints = hints;\n            const tryHarder = !isNullOrUndefined(hints)\n                && hints.get(DecodeHintType$1.TRY_HARDER) === true;\n            const formats = isNullOrUndefined(hints) ? null : hints.get(DecodeHintType$1.POSSIBLE_FORMATS);\n            const readers = new Array();\n            if (!isNullOrUndefined(formats)) {\n                const addOneDReader = formats.some(f => {\n                    return (\n                        f === BarcodeFormat$1.UPC_A ||\n                        f === BarcodeFormat$1.UPC_E ||\n                        f === BarcodeFormat$1.EAN_13 ||\n                        f === BarcodeFormat$1.EAN_8 ||\n                        f === BarcodeFormat$1.CODABAR ||\n                        f === BarcodeFormat$1.CODE_39 ||\n                        f === BarcodeFormat$1.CODE_93 ||\n                        f === BarcodeFormat$1.CODE_128 ||\n                        f === BarcodeFormat$1.ITF ||\n                        f === BarcodeFormat$1.RSS_14 ||\n                        f === BarcodeFormat$1.RSS_EXPANDED);\n                });\n                // Put 1D readers upfront in \"normal\" mode\n                if (addOneDReader && !tryHarder) {\n                    readers.push(new MultiFormatOneDReader(hints, this.verbose));\n                }\n                if (formats.includes(BarcodeFormat$1.QR_CODE)) {\n                    readers.push(new QRCodeReader());\n                }\n                if (formats.includes(BarcodeFormat$1.DATA_MATRIX)) {\n                    readers.push(new DataMatrixReader());\n                }\n                if (formats.includes(BarcodeFormat$1.AZTEC)) {\n                    readers.push(new AztecReader());\n                }\n                if (formats.includes(BarcodeFormat$1.PDF_417)) {\n                    readers.push(new PDF417Reader());\n                }\n                // if (formats.includes(BarcodeFormat.MAXICODE)) {\n                //    readers.push(new MaxiCodeReader())\n                // }\n                // At end in \"try harder\" mode\n                if (addOneDReader && tryHarder) {\n                    readers.push(new MultiFormatOneDReader(hints, this.verbose));\n                }\n            }\n            if (readers.length === 0) {\n                if (!tryHarder) {\n                    readers.push(new MultiFormatOneDReader(hints, this.verbose));\n                }\n                readers.push(new QRCodeReader());\n                readers.push(new DataMatrixReader());\n                readers.push(new AztecReader());\n                readers.push(new PDF417Reader());\n                // readers.push(new MaxiCodeReader())\n                if (tryHarder) {\n                    readers.push(new MultiFormatOneDReader(hints, this.verbose));\n                }\n            }\n            this.readers = readers; // .toArray(new Reader[readers.size()])\n        }\n        /*@Override*/\n        reset() {\n            if (this.readers !== null) {\n                for (const reader of this.readers) {\n                    reader.reset();\n                }\n            }\n        }\n        /**\n         * @throws NotFoundException\n         */\n        decodeInternal(image) {\n            if (this.readers === null) {\n                throw new ReaderException('No readers where selected, nothing can be read.');\n            }\n            for (const reader of this.readers) {\n                // Trying to decode with ${reader} reader.\n                try {\n                    return reader.decode(image, this.hints);\n                }\n                catch (ex) {\n                    if (ex instanceof ReaderException) {\n                        continue;\n                    }\n                    // Bad Exception.\n                }\n            }\n            throw new NotFoundException('No MultiFormat Readers were able to detect the code.');\n        }\n    }\n\n    class BrowserMultiFormatReader extends BrowserCodeReader {\n        constructor(hints = null, timeBetweenScansMillis = 500) {\n            const reader = new MultiFormatReader();\n            reader.setHints(hints);\n            super(reader, timeBetweenScansMillis);\n        }\n        /**\n         * Overwrite decodeBitmap to call decodeWithState, which will pay\n         * attention to the hints set in the constructor function\n         */\n        decodeBitmap(binaryBitmap) {\n            return this.reader.decodeWithState(binaryBitmap);\n        }\n    }\n\n    /**\n     * @deprecated Moving to @zxing/browser\n     *\n     * QR Code reader to use from browser.\n     */\n    class BrowserPDF417Reader extends BrowserCodeReader {\n        /**\n         * Creates an instance of BrowserPDF417Reader.\n         * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n         */\n        constructor(timeBetweenScansMillis = 500) {\n            super(new PDF417Reader(), timeBetweenScansMillis);\n        }\n    }\n\n    /**\n     * @deprecated Moving to @zxing/browser\n     *\n     * QR Code reader to use from browser.\n     */\n    class BrowserQRCodeReader extends BrowserCodeReader {\n        /**\n         * Creates an instance of BrowserQRCodeReader.\n         * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n         */\n        constructor(timeBetweenScansMillis = 500) {\n            super(new QRCodeReader(), timeBetweenScansMillis);\n        }\n    }\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing {*/\n    /**\n     * These are a set of hints that you may pass to Writers to specify their behavior.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    var EncodeHintType;\n    (function (EncodeHintType) {\n        /**\n         * Specifies what degree of error correction to use, for example in QR Codes.\n         * Type depends on the encoder. For example for QR codes it's type\n         * {@link com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ErrorCorrectionLevel}.\n         * For Aztec it is of type {@link Integer}, representing the minimal percentage of error correction words.\n         * For PDF417 it is of type {@link Integer}, valid values being 0 to 8.\n         * In all cases, it can also be a {@link String} representation of the desired value as well.\n         * Note: an Aztec symbol should have a minimum of 25% EC words.\n         */\n        EncodeHintType[EncodeHintType[\"ERROR_CORRECTION\"] = 0] = \"ERROR_CORRECTION\";\n        /**\n         * Specifies what character encoding to use where applicable (type {@link String})\n         */\n        EncodeHintType[EncodeHintType[\"CHARACTER_SET\"] = 1] = \"CHARACTER_SET\";\n        /**\n         * Specifies the matrix shape for Data Matrix (type {@link com.google.zxing.datamatrix.encoder.SymbolShapeHint})\n         */\n        EncodeHintType[EncodeHintType[\"DATA_MATRIX_SHAPE\"] = 2] = \"DATA_MATRIX_SHAPE\";\n        /**\n         * Specifies a minimum barcode size (type {@link Dimension}). Only applicable to Data Matrix now.\n         *\n         * @deprecated use width/height params in\n         * {@link com.google.zxing.datamatrix.DataMatrixWriter#encode(String, BarcodeFormat, int, int)}\n         */\n        /*@Deprecated*/\n        EncodeHintType[EncodeHintType[\"MIN_SIZE\"] = 3] = \"MIN_SIZE\";\n        /**\n         * Specifies a maximum barcode size (type {@link Dimension}). Only applicable to Data Matrix now.\n         *\n         * @deprecated without replacement\n         */\n        /*@Deprecated*/\n        EncodeHintType[EncodeHintType[\"MAX_SIZE\"] = 4] = \"MAX_SIZE\";\n        /**\n         * Specifies margin, in pixels, to use when generating the barcode. The meaning can vary\n         * by format; for example it controls margin before and after the barcode horizontally for\n         * most 1D formats. (Type {@link Integer}, or {@link String} representation of the integer value).\n         */\n        EncodeHintType[EncodeHintType[\"MARGIN\"] = 5] = \"MARGIN\";\n        /**\n         * Specifies whether to use compact mode for PDF417 (type {@link Boolean}, or \"true\" or \"false\"\n         * {@link String} value).\n         */\n        EncodeHintType[EncodeHintType[\"PDF417_COMPACT\"] = 6] = \"PDF417_COMPACT\";\n        /**\n         * Specifies what compaction mode to use for PDF417 (type\n         * {@link com.google.zxing.pdf417.encoder.Compaction Compaction} or {@link String} value of one of its\n         * enum values).\n         */\n        EncodeHintType[EncodeHintType[\"PDF417_COMPACTION\"] = 7] = \"PDF417_COMPACTION\";\n        /**\n         * Specifies the minimum and maximum number of rows and columns for PDF417 (type\n         * {@link com.google.zxing.pdf417.encoder.Dimensions Dimensions}).\n         */\n        EncodeHintType[EncodeHintType[\"PDF417_DIMENSIONS\"] = 8] = \"PDF417_DIMENSIONS\";\n        /**\n         * Specifies the required number of layers for an Aztec code.\n         * A negative number (-1, -2, -3, -4) specifies a compact Aztec code.\n         * 0 indicates to use the minimum number of layers (the default).\n         * A positive number (1, 2, .. 32) specifies a normal (non-compact) Aztec code.\n         * (Type {@link Integer}, or {@link String} representation of the integer value).\n         */\n        EncodeHintType[EncodeHintType[\"AZTEC_LAYERS\"] = 9] = \"AZTEC_LAYERS\";\n        /**\n         * Specifies the exact version of QR code to be encoded.\n         * (Type {@link Integer}, or {@link String} representation of the integer value).\n         */\n        EncodeHintType[EncodeHintType[\"QR_VERSION\"] = 10] = \"QR_VERSION\";\n    })(EncodeHintType || (EncodeHintType = {}));\n    var EncodeHintType$1 = EncodeHintType;\n\n    /**\n     * <p>Implements Reed-Solomon encoding, as the name implies.</p>\n     *\n     * @author Sean Owen\n     * @author William Rucklidge\n     */\n    class ReedSolomonEncoder {\n        /**\n         * A reed solomon error-correcting encoding constructor is created by\n         * passing as Galois Field with of size equal to the number of code\n         * words (symbols) in the alphabet (the number of values in each\n         * element of arrays that are encoded/decoded).\n         * @param field A galois field with a number of elements equal to the size\n         * of the alphabet of symbols to encode.\n         */\n        constructor(field) {\n            this.field = field;\n            this.cachedGenerators = [];\n            this.cachedGenerators.push(new GenericGFPoly(field, Int32Array.from([1])));\n        }\n        buildGenerator(degree /*int*/) {\n            const cachedGenerators = this.cachedGenerators;\n            if (degree >= cachedGenerators.length) {\n                let lastGenerator = cachedGenerators[cachedGenerators.length - 1];\n                const field = this.field;\n                for (let d = cachedGenerators.length; d <= degree; d++) {\n                    const nextGenerator = lastGenerator.multiply(new GenericGFPoly(field, Int32Array.from([1, field.exp(d - 1 + field.getGeneratorBase())])));\n                    cachedGenerators.push(nextGenerator);\n                    lastGenerator = nextGenerator;\n                }\n            }\n            return cachedGenerators[degree];\n        }\n        /**\n         * <p>Encode a sequence of code words (symbols) using Reed-Solomon to allow decoders\n         * to detect and correct errors that may have been introduced when the resulting\n         * data is stored or transmitted.</p>\n         *\n         * @param toEncode array used for both and output. Caller initializes the array with\n         * the code words (symbols) to be encoded followed by empty elements allocated to make\n         * space for error-correction code words in the encoded output. The array contains\n         * the encdoded output when encode returns. Code words are encoded as numbers from\n         * 0 to n-1, where n is the number of possible code words (symbols), as determined\n         * by the size of the Galois Field passed in the constructor of this object.\n         * @param ecBytes the number of elements reserved in the array (first parameter)\n         * to store error-correction code words. Thus, the number of code words (symbols)\n         * to encode in the first parameter is thus toEncode.length - ecBytes.\n         * Note, the use of \"bytes\" in the name of this parameter is misleading, as there may\n         * be more or fewer than 256 symbols being encoded, as determined by the number of\n         * elements in the Galois Field passed as a constructor to this object.\n         * @throws IllegalArgumentException thrown in response to validation errros.\n         */\n        encode(toEncode, ecBytes /*int*/) {\n            if (ecBytes === 0) {\n                throw new IllegalArgumentException('No error correction bytes');\n            }\n            const dataBytes = toEncode.length - ecBytes;\n            if (dataBytes <= 0) {\n                throw new IllegalArgumentException('No data bytes provided');\n            }\n            const generator = this.buildGenerator(ecBytes);\n            const infoCoefficients = new Int32Array(dataBytes);\n            System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes);\n            let info = new GenericGFPoly(this.field, infoCoefficients);\n            info = info.multiplyByMonomial(ecBytes, 1);\n            const remainder = info.divide(generator)[1];\n            const coefficients = remainder.getCoefficients();\n            const numZeroCoefficients = ecBytes - coefficients.length;\n            for (let i = 0; i < numZeroCoefficients; i++) {\n                toEncode[dataBytes + i] = 0;\n            }\n            System.arraycopy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.length);\n        }\n    }\n\n    /**\n     * @author Satoru Takabayashi\n     * @author Daniel Switkin\n     * @author Sean Owen\n     */\n    class MaskUtil {\n        constructor() {\n            // do nothing\n        }\n        /**\n         * Apply mask penalty rule 1 and return the penalty. Find repetitive cells with the same color and\n         * give penalty to them. Example: 00000 or 11111.\n         */\n        static applyMaskPenaltyRule1(matrix) {\n            return MaskUtil.applyMaskPenaltyRule1Internal(matrix, true) + MaskUtil.applyMaskPenaltyRule1Internal(matrix, false);\n        }\n        /**\n         * Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give\n         * penalty to them. This is actually equivalent to the spec's rule, which is to find MxN blocks and give a\n         * penalty proportional to (M-1)x(N-1), because this is the number of 2x2 blocks inside such a block.\n         */\n        static applyMaskPenaltyRule2(matrix) {\n            let penalty = 0;\n            const array = matrix.getArray();\n            const width = matrix.getWidth();\n            const height = matrix.getHeight();\n            for (let y = 0; y < height - 1; y++) {\n                const arrayY = array[y];\n                for (let x = 0; x < width - 1; x++) {\n                    const value = arrayY[x];\n                    if (value === arrayY[x + 1] && value === array[y + 1][x] && value === array[y + 1][x + 1]) {\n                        penalty++;\n                    }\n                }\n            }\n            return MaskUtil.N2 * penalty;\n        }\n        /**\n         * Apply mask penalty rule 3 and return the penalty. Find consecutive runs of 1:1:3:1:1:4\n         * starting with black, or 4:1:1:3:1:1 starting with white, and give penalty to them.  If we\n         * find patterns like 000010111010000, we give penalty once.\n         */\n        static applyMaskPenaltyRule3(matrix) {\n            let numPenalties = 0;\n            const array = matrix.getArray();\n            const width = matrix.getWidth();\n            const height = matrix.getHeight();\n            for (let y = 0; y < height; y++) {\n                for (let x = 0; x < width; x++) {\n                    const arrayY = array[y]; // We can at least optimize this access\n                    if (x + 6 < width &&\n                        arrayY[x] === 1 &&\n                        arrayY[x + 1] === 0 &&\n                        arrayY[x + 2] === 1 &&\n                        arrayY[x + 3] === 1 &&\n                        arrayY[x + 4] === 1 &&\n                        arrayY[x + 5] === 0 &&\n                        arrayY[x + 6] === 1 &&\n                        (MaskUtil.isWhiteHorizontal(arrayY, x - 4, x) || MaskUtil.isWhiteHorizontal(arrayY, x + 7, x + 11))) {\n                        numPenalties++;\n                    }\n                    if (y + 6 < height &&\n                        array[y][x] === 1 &&\n                        array[y + 1][x] === 0 &&\n                        array[y + 2][x] === 1 &&\n                        array[y + 3][x] === 1 &&\n                        array[y + 4][x] === 1 &&\n                        array[y + 5][x] === 0 &&\n                        array[y + 6][x] === 1 &&\n                        (MaskUtil.isWhiteVertical(array, x, y - 4, y) || MaskUtil.isWhiteVertical(array, x, y + 7, y + 11))) {\n                        numPenalties++;\n                    }\n                }\n            }\n            return numPenalties * MaskUtil.N3;\n        }\n        static isWhiteHorizontal(rowArray, from /*int*/, to /*int*/) {\n            from = Math.max(from, 0);\n            to = Math.min(to, rowArray.length);\n            for (let i = from; i < to; i++) {\n                if (rowArray[i] === 1) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        static isWhiteVertical(array, col /*int*/, from /*int*/, to /*int*/) {\n            from = Math.max(from, 0);\n            to = Math.min(to, array.length);\n            for (let i = from; i < to; i++) {\n                if (array[i][col] === 1) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        /**\n         * Apply mask penalty rule 4 and return the penalty. Calculate the ratio of dark cells and give\n         * penalty if the ratio is far from 50%. It gives 10 penalty for 5% distance.\n         */\n        static applyMaskPenaltyRule4(matrix) {\n            let numDarkCells = 0;\n            const array = matrix.getArray();\n            const width = matrix.getWidth();\n            const height = matrix.getHeight();\n            for (let y = 0; y < height; y++) {\n                const arrayY = array[y];\n                for (let x = 0; x < width; x++) {\n                    if (arrayY[x] === 1) {\n                        numDarkCells++;\n                    }\n                }\n            }\n            const numTotalCells = matrix.getHeight() * matrix.getWidth();\n            const fivePercentVariances = Math.floor(Math.abs(numDarkCells * 2 - numTotalCells) * 10 / numTotalCells);\n            return fivePercentVariances * MaskUtil.N4;\n        }\n        /**\n         * Return the mask bit for \"getMaskPattern\" at \"x\" and \"y\". See 8.8 of JISX0510:2004 for mask\n         * pattern conditions.\n         */\n        static getDataMaskBit(maskPattern /*int*/, x /*int*/, y /*int*/) {\n            let intermediate; /*int*/\n            let temp; /*int*/\n            switch (maskPattern) {\n                case 0:\n                    intermediate = (y + x) & 0x1;\n                    break;\n                case 1:\n                    intermediate = y & 0x1;\n                    break;\n                case 2:\n                    intermediate = x % 3;\n                    break;\n                case 3:\n                    intermediate = (y + x) % 3;\n                    break;\n                case 4:\n                    intermediate = (Math.floor(y / 2) + Math.floor(x / 3)) & 0x1;\n                    break;\n                case 5:\n                    temp = y * x;\n                    intermediate = (temp & 0x1) + (temp % 3);\n                    break;\n                case 6:\n                    temp = y * x;\n                    intermediate = ((temp & 0x1) + (temp % 3)) & 0x1;\n                    break;\n                case 7:\n                    temp = y * x;\n                    intermediate = ((temp % 3) + ((y + x) & 0x1)) & 0x1;\n                    break;\n                default:\n                    throw new IllegalArgumentException('Invalid mask pattern: ' + maskPattern);\n            }\n            return intermediate === 0;\n        }\n        /**\n         * Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both\n         * vertical and horizontal orders respectively.\n         */\n        static applyMaskPenaltyRule1Internal(matrix, isHorizontal) {\n            let penalty = 0;\n            const iLimit = isHorizontal ? matrix.getHeight() : matrix.getWidth();\n            const jLimit = isHorizontal ? matrix.getWidth() : matrix.getHeight();\n            const array = matrix.getArray();\n            for (let i = 0; i < iLimit; i++) {\n                let numSameBitCells = 0;\n                let prevBit = -1;\n                for (let j = 0; j < jLimit; j++) {\n                    const bit = isHorizontal ? array[i][j] : array[j][i];\n                    if (bit === prevBit) {\n                        numSameBitCells++;\n                    }\n                    else {\n                        if (numSameBitCells >= 5) {\n                            penalty += MaskUtil.N1 + (numSameBitCells - 5);\n                        }\n                        numSameBitCells = 1; // Include the cell itself.\n                        prevBit = bit;\n                    }\n                }\n                if (numSameBitCells >= 5) {\n                    penalty += MaskUtil.N1 + (numSameBitCells - 5);\n                }\n            }\n            return penalty;\n        }\n    }\n    // Penalty weights from section 6.8.2.1\n    MaskUtil.N1 = 3;\n    MaskUtil.N2 = 3;\n    MaskUtil.N3 = 40;\n    MaskUtil.N4 = 10;\n\n    /**\n     * JAVAPORT: The original code was a 2D array of ints, but since it only ever gets assigned\n     * -1, 0, and 1, I'm going to use less memory and go with bytes.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class ByteMatrix {\n        constructor(width /*int*/, height /*int*/) {\n            this.width = width;\n            this.height = height;\n            const bytes = new Array(height); // [height][width]\n            for (let i = 0; i !== height; i++) {\n                bytes[i] = new Uint8Array(width);\n            }\n            this.bytes = bytes;\n        }\n        getHeight() {\n            return this.height;\n        }\n        getWidth() {\n            return this.width;\n        }\n        get(x /*int*/, y /*int*/) {\n            return this.bytes[y][x];\n        }\n        /**\n         * @return an internal representation as bytes, in row-major order. array[y][x] represents point (x,y)\n         */\n        getArray() {\n            return this.bytes;\n        }\n        // TYPESCRIPTPORT: preffer to let two methods instead of override to avoid type comparison inside\n        setNumber(x /*int*/, y /*int*/, value /*byte|int*/) {\n            this.bytes[y][x] = value;\n        }\n        // public set(x: number /*int*/, y: number /*int*/, value: number /*int*/): void {\n        //   bytes[y][x] = (byte) value\n        // }\n        setBoolean(x /*int*/, y /*int*/, value) {\n            this.bytes[y][x] = /*(byte) */ (value ? 1 : 0);\n        }\n        clear(value /*byte*/) {\n            for (const aByte of this.bytes) {\n                Arrays.fill(aByte, value);\n            }\n        }\n        equals(o) {\n            if (!(o instanceof ByteMatrix)) {\n                return false;\n            }\n            const other = o;\n            if (this.width !== other.width) {\n                return false;\n            }\n            if (this.height !== other.height) {\n                return false;\n            }\n            for (let y = 0, height = this.height; y < height; ++y) {\n                const bytesY = this.bytes[y];\n                const otherBytesY = other.bytes[y];\n                for (let x = 0, width = this.width; x < width; ++x) {\n                    if (bytesY[x] !== otherBytesY[x]) {\n                        return false;\n                    }\n                }\n            }\n            return true;\n        }\n        /*@Override*/\n        toString() {\n            const result = new StringBuilder(); // (2 * width * height + 2)\n            for (let y = 0, height = this.height; y < height; ++y) {\n                const bytesY = this.bytes[y];\n                for (let x = 0, width = this.width; x < width; ++x) {\n                    switch (bytesY[x]) {\n                        case 0:\n                            result.append(' 0');\n                            break;\n                        case 1:\n                            result.append(' 1');\n                            break;\n                        default:\n                            result.append('  ');\n                            break;\n                    }\n                }\n                result.append('\\n');\n            }\n            return result.toString();\n        }\n    }\n\n    /**\n     * @author satorux@google.com (Satoru Takabayashi) - creator\n     * @author dswitkin@google.com (Daniel Switkin) - ported from C++\n     */\n    class QRCode {\n        constructor() {\n            this.maskPattern = -1;\n        }\n        getMode() {\n            return this.mode;\n        }\n        getECLevel() {\n            return this.ecLevel;\n        }\n        getVersion() {\n            return this.version;\n        }\n        getMaskPattern() {\n            return this.maskPattern;\n        }\n        getMatrix() {\n            return this.matrix;\n        }\n        /*@Override*/\n        toString() {\n            const result = new StringBuilder(); // (200)\n            result.append('<<\\n');\n            result.append(' mode: ');\n            result.append(this.mode ? this.mode.toString() : 'null');\n            result.append('\\n ecLevel: ');\n            result.append(this.ecLevel ? this.ecLevel.toString() : 'null');\n            result.append('\\n version: ');\n            result.append(this.version ? this.version.toString() : 'null');\n            result.append('\\n maskPattern: ');\n            result.append(this.maskPattern.toString());\n            if (this.matrix) {\n                result.append('\\n matrix:\\n');\n                result.append(this.matrix.toString());\n            }\n            else {\n                result.append('\\n matrix: null\\n');\n            }\n            result.append('>>\\n');\n            return result.toString();\n        }\n        setMode(value) {\n            this.mode = value;\n        }\n        setECLevel(value) {\n            this.ecLevel = value;\n        }\n        setVersion(version) {\n            this.version = version;\n        }\n        setMaskPattern(value /*int*/) {\n            this.maskPattern = value;\n        }\n        setMatrix(value) {\n            this.matrix = value;\n        }\n        // Check if \"mask_pattern\" is valid.\n        static isValidMaskPattern(maskPattern /*int*/) {\n            return maskPattern >= 0 && maskPattern < QRCode.NUM_MASK_PATTERNS;\n        }\n    }\n    QRCode.NUM_MASK_PATTERNS = 8;\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class WriterException extends Exception {\n    }\n    WriterException.kind = 'WriterException';\n\n    /**\n     * @author satorux@google.com (Satoru Takabayashi) - creator\n     * @author dswitkin@google.com (Daniel Switkin) - ported from C++\n     */\n    class MatrixUtil {\n        constructor() {\n            // do nothing\n        }\n        // Set all cells to -1 (TYPESCRIPTPORT: 255).  -1 (TYPESCRIPTPORT: 255) means that the cell is empty (not set yet).\n        //\n        // JAVAPORT: We shouldn't need to do this at all. The code should be rewritten to begin encoding\n        // with the ByteMatrix initialized all to zero.\n        static clearMatrix(matrix) {\n            // TYPESCRIPTPORT: we use UintArray se changed here from -1 to 255\n            matrix.clear(/*(byte) */ /*-1*/ 255);\n        }\n        // Build 2D matrix of QR Code from \"dataBits\" with \"ecLevel\", \"version\" and \"getMaskPattern\". On\n        // success, store the result in \"matrix\" and return true.\n        static buildMatrix(dataBits, ecLevel, version, maskPattern /*int*/, matrix) {\n            MatrixUtil.clearMatrix(matrix);\n            MatrixUtil.embedBasicPatterns(version, matrix);\n            // Type information appear with any version.\n            MatrixUtil.embedTypeInfo(ecLevel, maskPattern, matrix);\n            // Version info appear if version >= 7.\n            MatrixUtil.maybeEmbedVersionInfo(version, matrix);\n            // Data should be embedded at end.\n            MatrixUtil.embedDataBits(dataBits, maskPattern, matrix);\n        }\n        // Embed basic patterns. On success, modify the matrix and return true.\n        // The basic patterns are:\n        // - Position detection patterns\n        // - Timing patterns\n        // - Dark dot at the left bottom corner\n        // - Position adjustment patterns, if need be\n        static embedBasicPatterns(version, matrix) {\n            // Let's get started with embedding big squares at corners.\n            MatrixUtil.embedPositionDetectionPatternsAndSeparators(matrix);\n            // Then, embed the dark dot at the left bottom corner.\n            MatrixUtil.embedDarkDotAtLeftBottomCorner(matrix);\n            // Position adjustment patterns appear if version >= 2.\n            MatrixUtil.maybeEmbedPositionAdjustmentPatterns(version, matrix);\n            // Timing patterns should be embedded after position adj. patterns.\n            MatrixUtil.embedTimingPatterns(matrix);\n        }\n        // Embed type information. On success, modify the matrix.\n        static embedTypeInfo(ecLevel, maskPattern /*int*/, matrix) {\n            const typeInfoBits = new BitArray();\n            MatrixUtil.makeTypeInfoBits(ecLevel, maskPattern, typeInfoBits);\n            for (let i = 0, size = typeInfoBits.getSize(); i < size; ++i) {\n                // Place bits in LSB to MSB order.  LSB (least significant bit) is the last value in\n                // \"typeInfoBits\".\n                const bit = typeInfoBits.get(typeInfoBits.getSize() - 1 - i);\n                // Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46).\n                const coordinates = MatrixUtil.TYPE_INFO_COORDINATES[i];\n                const x1 = coordinates[0];\n                const y1 = coordinates[1];\n                matrix.setBoolean(x1, y1, bit);\n                if (i < 8) {\n                    // Right top corner.\n                    const x2 = matrix.getWidth() - i - 1;\n                    const y2 = 8;\n                    matrix.setBoolean(x2, y2, bit);\n                }\n                else {\n                    // Left bottom corner.\n                    const x2 = 8;\n                    const y2 = matrix.getHeight() - 7 + (i - 8);\n                    matrix.setBoolean(x2, y2, bit);\n                }\n            }\n        }\n        // Embed version information if need be. On success, modify the matrix and return true.\n        // See 8.10 of JISX0510:2004 (p.47) for how to embed version information.\n        static maybeEmbedVersionInfo(version, matrix) {\n            if (version.getVersionNumber() < 7) { // Version info is necessary if version >= 7.\n                return; // Don't need version info.\n            }\n            const versionInfoBits = new BitArray();\n            MatrixUtil.makeVersionInfoBits(version, versionInfoBits);\n            let bitIndex = 6 * 3 - 1; // It will decrease from 17 to 0.\n            for (let i = 0; i < 6; ++i) {\n                for (let j = 0; j < 3; ++j) {\n                    // Place bits in LSB (least significant bit) to MSB order.\n                    const bit = versionInfoBits.get(bitIndex);\n                    bitIndex--;\n                    // Left bottom corner.\n                    matrix.setBoolean(i, matrix.getHeight() - 11 + j, bit);\n                    // Right bottom corner.\n                    matrix.setBoolean(matrix.getHeight() - 11 + j, i, bit);\n                }\n            }\n        }\n        // Embed \"dataBits\" using \"getMaskPattern\". On success, modify the matrix and return true.\n        // For debugging purposes, it skips masking process if \"getMaskPattern\" is -1(TYPESCRIPTPORT: 255).\n        // See 8.7 of JISX0510:2004 (p.38) for how to embed data bits.\n        static embedDataBits(dataBits, maskPattern /*int*/, matrix) {\n            let bitIndex = 0;\n            let direction = -1;\n            // Start from the right bottom cell.\n            let x = matrix.getWidth() - 1;\n            let y = matrix.getHeight() - 1;\n            while (x > 0) {\n                // Skip the vertical timing pattern.\n                if (x === 6) {\n                    x -= 1;\n                }\n                while (y >= 0 && y < matrix.getHeight()) {\n                    for (let i = 0; i < 2; ++i) {\n                        const xx = x - i;\n                        // Skip the cell if it's not empty.\n                        if (!MatrixUtil.isEmpty(matrix.get(xx, y))) {\n                            continue;\n                        }\n                        let bit;\n                        if (bitIndex < dataBits.getSize()) {\n                            bit = dataBits.get(bitIndex);\n                            ++bitIndex;\n                        }\n                        else {\n                            // Padding bit. If there is no bit left, we'll fill the left cells with 0, as described\n                            // in 8.4.9 of JISX0510:2004 (p. 24).\n                            bit = false;\n                        }\n                        // Skip masking if mask_pattern is -1 (TYPESCRIPTPORT: 255).\n                        if (maskPattern !== 255 && MaskUtil.getDataMaskBit(maskPattern, xx, y)) {\n                            bit = !bit;\n                        }\n                        matrix.setBoolean(xx, y, bit);\n                    }\n                    y += direction;\n                }\n                direction = -direction; // Reverse the direction.\n                y += direction;\n                x -= 2; // Move to the left.\n            }\n            // All bits should be consumed.\n            if (bitIndex !== dataBits.getSize()) {\n                throw new WriterException('Not all bits consumed: ' + bitIndex + '/' + dataBits.getSize());\n            }\n        }\n        // Return the position of the most significant bit set (one: to) in the \"value\". The most\n        // significant bit is position 32. If there is no bit set, return 0. Examples:\n        // - findMSBSet(0) => 0\n        // - findMSBSet(1) => 1\n        // - findMSBSet(255) => 8\n        static findMSBSet(value /*int*/) {\n            return 32 - Integer.numberOfLeadingZeros(value);\n        }\n        // Calculate BCH (Bose-Chaudhuri-Hocquenghem) code for \"value\" using polynomial \"poly\". The BCH\n        // code is used for encoding type information and version information.\n        // Example: Calculation of version information of 7.\n        // f(x) is created from 7.\n        //   - 7 = 000111 in 6 bits\n        //   - f(x) = x^2 + x^1 + x^0\n        // g(x) is given by the standard (p. 67)\n        //   - g(x) = x^12 + x^11 + x^10 + x^9 + x^8 + x^5 + x^2 + 1\n        // Multiply f(x) by x^(18 - 6)\n        //   - f'(x) = f(x) * x^(18 - 6)\n        //   - f'(x) = x^14 + x^13 + x^12\n        // Calculate the remainder of f'(x) / g(x)\n        //         x^2\n        //         __________________________________________________\n        //   g(x) )x^14 + x^13 + x^12\n        //         x^14 + x^13 + x^12 + x^11 + x^10 + x^7 + x^4 + x^2\n        //         --------------------------------------------------\n        //                              x^11 + x^10 + x^7 + x^4 + x^2\n        //\n        // The remainder is x^11 + x^10 + x^7 + x^4 + x^2\n        // Encode it in binary: 110010010100\n        // The return value is 0xc94 (1100 1001 0100)\n        //\n        // Since all coefficients in the polynomials are 1 or 0, we can do the calculation by bit\n        // operations. We don't care if coefficients are positive or negative.\n        static calculateBCHCode(value /*int*/, poly /*int*/) {\n            if (poly === 0) {\n                throw new IllegalArgumentException('0 polynomial');\n            }\n            // If poly is \"1 1111 0010 0101\" (version info poly), msbSetInPoly is 13. We'll subtract 1\n            // from 13 to make it 12.\n            const msbSetInPoly = MatrixUtil.findMSBSet(poly);\n            value <<= msbSetInPoly - 1;\n            // Do the division business using exclusive-or operations.\n            while (MatrixUtil.findMSBSet(value) >= msbSetInPoly) {\n                value ^= poly << (MatrixUtil.findMSBSet(value) - msbSetInPoly);\n            }\n            // Now the \"value\" is the remainder (i.e. the BCH code)\n            return value;\n        }\n        // Make bit vector of type information. On success, store the result in \"bits\" and return true.\n        // Encode error correction level and mask pattern. See 8.9 of\n        // JISX0510:2004 (p.45) for details.\n        static makeTypeInfoBits(ecLevel, maskPattern /*int*/, bits) {\n            if (!QRCode.isValidMaskPattern(maskPattern)) {\n                throw new WriterException('Invalid mask pattern');\n            }\n            const typeInfo = (ecLevel.getBits() << 3) | maskPattern;\n            bits.appendBits(typeInfo, 5);\n            const bchCode = MatrixUtil.calculateBCHCode(typeInfo, MatrixUtil.TYPE_INFO_POLY);\n            bits.appendBits(bchCode, 10);\n            const maskBits = new BitArray();\n            maskBits.appendBits(MatrixUtil.TYPE_INFO_MASK_PATTERN, 15);\n            bits.xor(maskBits);\n            if (bits.getSize() !== 15) { // Just in case.\n                throw new WriterException('should not happen but we got: ' + bits.getSize());\n            }\n        }\n        // Make bit vector of version information. On success, store the result in \"bits\" and return true.\n        // See 8.10 of JISX0510:2004 (p.45) for details.\n        static makeVersionInfoBits(version, bits) {\n            bits.appendBits(version.getVersionNumber(), 6);\n            const bchCode = MatrixUtil.calculateBCHCode(version.getVersionNumber(), MatrixUtil.VERSION_INFO_POLY);\n            bits.appendBits(bchCode, 12);\n            if (bits.getSize() !== 18) { // Just in case.\n                throw new WriterException('should not happen but we got: ' + bits.getSize());\n            }\n        }\n        // Check if \"value\" is empty.\n        static isEmpty(value /*int*/) {\n            return value === 255; // -1\n        }\n        static embedTimingPatterns(matrix) {\n            // -8 is for skipping position detection patterns (7: size), and two horizontal/vertical\n            // separation patterns (1: size). Thus, 8 = 7 + 1.\n            for (let i = 8; i < matrix.getWidth() - 8; ++i) {\n                const bit = (i + 1) % 2;\n                // Horizontal line.\n                if (MatrixUtil.isEmpty(matrix.get(i, 6))) {\n                    matrix.setNumber(i, 6, bit);\n                }\n                // Vertical line.\n                if (MatrixUtil.isEmpty(matrix.get(6, i))) {\n                    matrix.setNumber(6, i, bit);\n                }\n            }\n        }\n        // Embed the lonely dark dot at left bottom corner. JISX0510:2004 (p.46)\n        static embedDarkDotAtLeftBottomCorner(matrix) {\n            if (matrix.get(8, matrix.getHeight() - 8) === 0) {\n                throw new WriterException();\n            }\n            matrix.setNumber(8, matrix.getHeight() - 8, 1);\n        }\n        static embedHorizontalSeparationPattern(xStart /*int*/, yStart /*int*/, matrix) {\n            for (let x = 0; x < 8; ++x) {\n                if (!MatrixUtil.isEmpty(matrix.get(xStart + x, yStart))) {\n                    throw new WriterException();\n                }\n                matrix.setNumber(xStart + x, yStart, 0);\n            }\n        }\n        static embedVerticalSeparationPattern(xStart /*int*/, yStart /*int*/, matrix) {\n            for (let y = 0; y < 7; ++y) {\n                if (!MatrixUtil.isEmpty(matrix.get(xStart, yStart + y))) {\n                    throw new WriterException();\n                }\n                matrix.setNumber(xStart, yStart + y, 0);\n            }\n        }\n        static embedPositionAdjustmentPattern(xStart /*int*/, yStart /*int*/, matrix) {\n            for (let y = 0; y < 5; ++y) {\n                const patternY = MatrixUtil.POSITION_ADJUSTMENT_PATTERN[y];\n                for (let x = 0; x < 5; ++x) {\n                    matrix.setNumber(xStart + x, yStart + y, patternY[x]);\n                }\n            }\n        }\n        static embedPositionDetectionPattern(xStart /*int*/, yStart /*int*/, matrix) {\n            for (let y = 0; y < 7; ++y) {\n                const patternY = MatrixUtil.POSITION_DETECTION_PATTERN[y];\n                for (let x = 0; x < 7; ++x) {\n                    matrix.setNumber(xStart + x, yStart + y, patternY[x]);\n                }\n            }\n        }\n        // Embed position detection patterns and surrounding vertical/horizontal separators.\n        static embedPositionDetectionPatternsAndSeparators(matrix) {\n            // Embed three big squares at corners.\n            const pdpWidth = MatrixUtil.POSITION_DETECTION_PATTERN[0].length;\n            // Left top corner.\n            MatrixUtil.embedPositionDetectionPattern(0, 0, matrix);\n            // Right top corner.\n            MatrixUtil.embedPositionDetectionPattern(matrix.getWidth() - pdpWidth, 0, matrix);\n            // Left bottom corner.\n            MatrixUtil.embedPositionDetectionPattern(0, matrix.getWidth() - pdpWidth, matrix);\n            // Embed horizontal separation patterns around the squares.\n            const hspWidth = 8;\n            // Left top corner.\n            MatrixUtil.embedHorizontalSeparationPattern(0, hspWidth - 1, matrix);\n            // Right top corner.\n            MatrixUtil.embedHorizontalSeparationPattern(matrix.getWidth() - hspWidth, hspWidth - 1, matrix);\n            // Left bottom corner.\n            MatrixUtil.embedHorizontalSeparationPattern(0, matrix.getWidth() - hspWidth, matrix);\n            // Embed vertical separation patterns around the squares.\n            const vspSize = 7;\n            // Left top corner.\n            MatrixUtil.embedVerticalSeparationPattern(vspSize, 0, matrix);\n            // Right top corner.\n            MatrixUtil.embedVerticalSeparationPattern(matrix.getHeight() - vspSize - 1, 0, matrix);\n            // Left bottom corner.\n            MatrixUtil.embedVerticalSeparationPattern(vspSize, matrix.getHeight() - vspSize, matrix);\n        }\n        // Embed position adjustment patterns if need be.\n        static maybeEmbedPositionAdjustmentPatterns(version, matrix) {\n            if (version.getVersionNumber() < 2) { // The patterns appear if version >= 2\n                return;\n            }\n            const index = version.getVersionNumber() - 1;\n            const coordinates = MatrixUtil.POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index];\n            for (let i = 0, length = coordinates.length; i !== length; i++) {\n                const y = coordinates[i];\n                if (y >= 0) {\n                    for (let j = 0; j !== length; j++) {\n                        const x = coordinates[j];\n                        if (x >= 0 && MatrixUtil.isEmpty(matrix.get(x, y))) {\n                            // If the cell is unset, we embed the position adjustment pattern here.\n                            // -2 is necessary since the x/y coordinates point to the center of the pattern, not the\n                            // left top corner.\n                            MatrixUtil.embedPositionAdjustmentPattern(x - 2, y - 2, matrix);\n                        }\n                    }\n                }\n            }\n        }\n    }\n    MatrixUtil.POSITION_DETECTION_PATTERN = Array.from([\n        Int32Array.from([1, 1, 1, 1, 1, 1, 1]),\n        Int32Array.from([1, 0, 0, 0, 0, 0, 1]),\n        Int32Array.from([1, 0, 1, 1, 1, 0, 1]),\n        Int32Array.from([1, 0, 1, 1, 1, 0, 1]),\n        Int32Array.from([1, 0, 1, 1, 1, 0, 1]),\n        Int32Array.from([1, 0, 0, 0, 0, 0, 1]),\n        Int32Array.from([1, 1, 1, 1, 1, 1, 1]),\n    ]);\n    MatrixUtil.POSITION_ADJUSTMENT_PATTERN = Array.from([\n        Int32Array.from([1, 1, 1, 1, 1]),\n        Int32Array.from([1, 0, 0, 0, 1]),\n        Int32Array.from([1, 0, 1, 0, 1]),\n        Int32Array.from([1, 0, 0, 0, 1]),\n        Int32Array.from([1, 1, 1, 1, 1]),\n    ]);\n    // From Appendix E. Table 1, JIS0510X:2004 (71: p). The table was double-checked by komatsu.\n    MatrixUtil.POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE = Array.from([\n        Int32Array.from([-1, -1, -1, -1, -1, -1, -1]),\n        Int32Array.from([6, 18, -1, -1, -1, -1, -1]),\n        Int32Array.from([6, 22, -1, -1, -1, -1, -1]),\n        Int32Array.from([6, 26, -1, -1, -1, -1, -1]),\n        Int32Array.from([6, 30, -1, -1, -1, -1, -1]),\n        Int32Array.from([6, 34, -1, -1, -1, -1, -1]),\n        Int32Array.from([6, 22, 38, -1, -1, -1, -1]),\n        Int32Array.from([6, 24, 42, -1, -1, -1, -1]),\n        Int32Array.from([6, 26, 46, -1, -1, -1, -1]),\n        Int32Array.from([6, 28, 50, -1, -1, -1, -1]),\n        Int32Array.from([6, 30, 54, -1, -1, -1, -1]),\n        Int32Array.from([6, 32, 58, -1, -1, -1, -1]),\n        Int32Array.from([6, 34, 62, -1, -1, -1, -1]),\n        Int32Array.from([6, 26, 46, 66, -1, -1, -1]),\n        Int32Array.from([6, 26, 48, 70, -1, -1, -1]),\n        Int32Array.from([6, 26, 50, 74, -1, -1, -1]),\n        Int32Array.from([6, 30, 54, 78, -1, -1, -1]),\n        Int32Array.from([6, 30, 56, 82, -1, -1, -1]),\n        Int32Array.from([6, 30, 58, 86, -1, -1, -1]),\n        Int32Array.from([6, 34, 62, 90, -1, -1, -1]),\n        Int32Array.from([6, 28, 50, 72, 94, -1, -1]),\n        Int32Array.from([6, 26, 50, 74, 98, -1, -1]),\n        Int32Array.from([6, 30, 54, 78, 102, -1, -1]),\n        Int32Array.from([6, 28, 54, 80, 106, -1, -1]),\n        Int32Array.from([6, 32, 58, 84, 110, -1, -1]),\n        Int32Array.from([6, 30, 58, 86, 114, -1, -1]),\n        Int32Array.from([6, 34, 62, 90, 118, -1, -1]),\n        Int32Array.from([6, 26, 50, 74, 98, 122, -1]),\n        Int32Array.from([6, 30, 54, 78, 102, 126, -1]),\n        Int32Array.from([6, 26, 52, 78, 104, 130, -1]),\n        Int32Array.from([6, 30, 56, 82, 108, 134, -1]),\n        Int32Array.from([6, 34, 60, 86, 112, 138, -1]),\n        Int32Array.from([6, 30, 58, 86, 114, 142, -1]),\n        Int32Array.from([6, 34, 62, 90, 118, 146, -1]),\n        Int32Array.from([6, 30, 54, 78, 102, 126, 150]),\n        Int32Array.from([6, 24, 50, 76, 102, 128, 154]),\n        Int32Array.from([6, 28, 54, 80, 106, 132, 158]),\n        Int32Array.from([6, 32, 58, 84, 110, 136, 162]),\n        Int32Array.from([6, 26, 54, 82, 110, 138, 166]),\n        Int32Array.from([6, 30, 58, 86, 114, 142, 170]),\n    ]);\n    // Type info cells at the left top corner.\n    MatrixUtil.TYPE_INFO_COORDINATES = Array.from([\n        Int32Array.from([8, 0]),\n        Int32Array.from([8, 1]),\n        Int32Array.from([8, 2]),\n        Int32Array.from([8, 3]),\n        Int32Array.from([8, 4]),\n        Int32Array.from([8, 5]),\n        Int32Array.from([8, 7]),\n        Int32Array.from([8, 8]),\n        Int32Array.from([7, 8]),\n        Int32Array.from([5, 8]),\n        Int32Array.from([4, 8]),\n        Int32Array.from([3, 8]),\n        Int32Array.from([2, 8]),\n        Int32Array.from([1, 8]),\n        Int32Array.from([0, 8]),\n    ]);\n    // From Appendix D in JISX0510:2004 (p. 67)\n    MatrixUtil.VERSION_INFO_POLY = 0x1f25; // 1 1111 0010 0101\n    // From Appendix C in JISX0510:2004 (p.65).\n    MatrixUtil.TYPE_INFO_POLY = 0x537;\n    MatrixUtil.TYPE_INFO_MASK_PATTERN = 0x5412;\n\n    /*namespace com.google.zxing.qrcode.encoder {*/\n    class BlockPair {\n        constructor(dataBytes, errorCorrectionBytes) {\n            this.dataBytes = dataBytes;\n            this.errorCorrectionBytes = errorCorrectionBytes;\n        }\n        getDataBytes() {\n            return this.dataBytes;\n        }\n        getErrorCorrectionBytes() {\n            return this.errorCorrectionBytes;\n        }\n    }\n\n    /*import java.io.UnsupportedEncodingException;*/\n    /*import java.util.ArrayList;*/\n    /*import java.util.Collection;*/\n    /*import java.util.Map;*/\n    /**\n     * @author satorux@google.com (Satoru Takabayashi) - creator\n     * @author dswitkin@google.com (Daniel Switkin) - ported from C++\n     */\n    class Encoder {\n        // TYPESCRIPTPORT: changed to UTF8, the default for js\n        constructor() { }\n        // The mask penalty calculation is complicated.  See Table 21 of JISX0510:2004 (p.45) for details.\n        // Basically it applies four rules and summate all penalties.\n        static calculateMaskPenalty(matrix) {\n            return MaskUtil.applyMaskPenaltyRule1(matrix)\n                + MaskUtil.applyMaskPenaltyRule2(matrix)\n                + MaskUtil.applyMaskPenaltyRule3(matrix)\n                + MaskUtil.applyMaskPenaltyRule4(matrix);\n        }\n        /**\n         * @param content text to encode\n         * @param ecLevel error correction level to use\n         * @return {@link QRCode} representing the encoded QR code\n         * @throws WriterException if encoding can't succeed, because of for example invalid content\n         *   or configuration\n         */\n        // public static encode(content: string, ecLevel: ErrorCorrectionLevel): QRCode /*throws WriterException*/ {\n        //   return encode(content, ecLevel, null)\n        // }\n        static encode(content, ecLevel, hints = null) {\n            // Determine what character encoding has been specified by the caller, if any\n            let encoding = Encoder.DEFAULT_BYTE_MODE_ENCODING;\n            const hasEncodingHint = hints !== null && undefined !== hints.get(EncodeHintType$1.CHARACTER_SET);\n            if (hasEncodingHint) {\n                encoding = hints.get(EncodeHintType$1.CHARACTER_SET).toString();\n            }\n            // Pick an encoding mode appropriate for the content. Note that this will not attempt to use\n            // multiple modes / segments even if that were more efficient. Twould be nice.\n            const mode = this.chooseMode(content, encoding);\n            // This will store the header information, like mode and\n            // length, as well as \"header\" segments like an ECI segment.\n            const headerBits = new BitArray();\n            // Append ECI segment if applicable\n            if (mode === Mode$1.BYTE && (hasEncodingHint || Encoder.DEFAULT_BYTE_MODE_ENCODING !== encoding)) {\n                const eci = CharacterSetECI.getCharacterSetECIByName(encoding);\n                if (eci !== undefined) {\n                    this.appendECI(eci, headerBits);\n                }\n            }\n            // (With ECI in place,) Write the mode marker\n            this.appendModeInfo(mode, headerBits);\n            // Collect data within the main segment, separately, to count its size if needed. Don't add it to\n            // main payload yet.\n            const dataBits = new BitArray();\n            this.appendBytes(content, mode, dataBits, encoding);\n            let version;\n            if (hints !== null && undefined !== hints.get(EncodeHintType$1.QR_VERSION)) {\n                const versionNumber = Number.parseInt(hints.get(EncodeHintType$1.QR_VERSION).toString(), 10);\n                version = Version$1.getVersionForNumber(versionNumber);\n                const bitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, version);\n                if (!this.willFit(bitsNeeded, version, ecLevel)) {\n                    throw new WriterException('Data too big for requested version');\n                }\n            }\n            else {\n                version = this.recommendVersion(ecLevel, mode, headerBits, dataBits);\n            }\n            const headerAndDataBits = new BitArray();\n            headerAndDataBits.appendBitArray(headerBits);\n            // Find \"length\" of main segment and write it\n            const numLetters = mode === Mode$1.BYTE ? dataBits.getSizeInBytes() : content.length;\n            this.appendLengthInfo(numLetters, version, mode, headerAndDataBits);\n            // Put data together into the overall payload\n            headerAndDataBits.appendBitArray(dataBits);\n            const ecBlocks = version.getECBlocksForLevel(ecLevel);\n            const numDataBytes = version.getTotalCodewords() - ecBlocks.getTotalECCodewords();\n            // Terminate the bits properly.\n            this.terminateBits(numDataBytes, headerAndDataBits);\n            // Interleave data bits with error correction code.\n            const finalBits = this.interleaveWithECBytes(headerAndDataBits, version.getTotalCodewords(), numDataBytes, ecBlocks.getNumBlocks());\n            const qrCode = new QRCode();\n            qrCode.setECLevel(ecLevel);\n            qrCode.setMode(mode);\n            qrCode.setVersion(version);\n            //  Choose the mask pattern and set to \"qrCode\".\n            const dimension = version.getDimensionForVersion();\n            const matrix = new ByteMatrix(dimension, dimension);\n            const maskPattern = this.chooseMaskPattern(finalBits, ecLevel, version, matrix);\n            qrCode.setMaskPattern(maskPattern);\n            // Build the matrix and set it to \"qrCode\".\n            MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix);\n            qrCode.setMatrix(matrix);\n            return qrCode;\n        }\n        /**\n         * Decides the smallest version of QR code that will contain all of the provided data.\n         *\n         * @throws WriterException if the data cannot fit in any version\n         */\n        static recommendVersion(ecLevel, mode, headerBits, dataBits) {\n            // Hard part: need to know version to know how many bits length takes. But need to know how many\n            // bits it takes to know version. First we take a guess at version by assuming version will be\n            // the minimum, 1:\n            const provisionalBitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, Version$1.getVersionForNumber(1));\n            const provisionalVersion = this.chooseVersion(provisionalBitsNeeded, ecLevel);\n            // Use that guess to calculate the right version. I am still not sure this works in 100% of cases.\n            const bitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, provisionalVersion);\n            return this.chooseVersion(bitsNeeded, ecLevel);\n        }\n        static calculateBitsNeeded(mode, headerBits, dataBits, version) {\n            return headerBits.getSize() + mode.getCharacterCountBits(version) + dataBits.getSize();\n        }\n        /**\n         * @return the code point of the table used in alphanumeric mode or\n         *  -1 if there is no corresponding code in the table.\n         */\n        static getAlphanumericCode(code /*int*/) {\n            if (code < Encoder.ALPHANUMERIC_TABLE.length) {\n                return Encoder.ALPHANUMERIC_TABLE[code];\n            }\n            return -1;\n        }\n        // public static chooseMode(content: string): Mode {\n        //   return chooseMode(content, null);\n        // }\n        /**\n         * Choose the best mode by examining the content. Note that 'encoding' is used as a hint;\n         * if it is Shift_JIS, and the input is only double-byte Kanji, then we return {@link Mode#KANJI}.\n         */\n        static chooseMode(content, encoding = null) {\n            if (CharacterSetECI.SJIS.getName() === encoding && this.isOnlyDoubleByteKanji(content)) {\n                // Choose Kanji mode if all input are double-byte characters\n                return Mode$1.KANJI;\n            }\n            let hasNumeric = false;\n            let hasAlphanumeric = false;\n            for (let i = 0, length = content.length; i < length; ++i) {\n                const c = content.charAt(i);\n                if (Encoder.isDigit(c)) {\n                    hasNumeric = true;\n                }\n                else if (this.getAlphanumericCode(c.charCodeAt(0)) !== -1) {\n                    hasAlphanumeric = true;\n                }\n                else {\n                    return Mode$1.BYTE;\n                }\n            }\n            if (hasAlphanumeric) {\n                return Mode$1.ALPHANUMERIC;\n            }\n            if (hasNumeric) {\n                return Mode$1.NUMERIC;\n            }\n            return Mode$1.BYTE;\n        }\n        static isOnlyDoubleByteKanji(content) {\n            let bytes;\n            try {\n                bytes = StringEncoding.encode(content, CharacterSetECI.SJIS); // content.getBytes(\"Shift_JIS\"))\n            }\n            catch (ignored /*: UnsupportedEncodingException*/) {\n                return false;\n            }\n            const length = bytes.length;\n            if (length % 2 !== 0) {\n                return false;\n            }\n            for (let i = 0; i < length; i += 2) {\n                const byte1 = bytes[i] & 0xFF;\n                if ((byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB)) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        static chooseMaskPattern(bits, ecLevel, version, matrix) {\n            let minPenalty = Number.MAX_SAFE_INTEGER; // Lower penalty is better.\n            let bestMaskPattern = -1;\n            // We try all mask patterns to choose the best one.\n            for (let maskPattern = 0; maskPattern < QRCode.NUM_MASK_PATTERNS; maskPattern++) {\n                MatrixUtil.buildMatrix(bits, ecLevel, version, maskPattern, matrix);\n                let penalty = this.calculateMaskPenalty(matrix);\n                if (penalty < minPenalty) {\n                    minPenalty = penalty;\n                    bestMaskPattern = maskPattern;\n                }\n            }\n            return bestMaskPattern;\n        }\n        static chooseVersion(numInputBits /*int*/, ecLevel) {\n            for (let versionNum = 1; versionNum <= 40; versionNum++) {\n                const version = Version$1.getVersionForNumber(versionNum);\n                if (Encoder.willFit(numInputBits, version, ecLevel)) {\n                    return version;\n                }\n            }\n            throw new WriterException('Data too big');\n        }\n        /**\n         * @return true if the number of input bits will fit in a code with the specified version and\n         * error correction level.\n         */\n        static willFit(numInputBits /*int*/, version, ecLevel) {\n            // In the following comments, we use numbers of Version 7-H.\n            // numBytes = 196\n            const numBytes = version.getTotalCodewords();\n            // getNumECBytes = 130\n            const ecBlocks = version.getECBlocksForLevel(ecLevel);\n            const numEcBytes = ecBlocks.getTotalECCodewords();\n            // getNumDataBytes = 196 - 130 = 66\n            const numDataBytes = numBytes - numEcBytes;\n            const totalInputBytes = (numInputBits + 7) / 8;\n            return numDataBytes >= totalInputBytes;\n        }\n        /**\n         * Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24).\n         */\n        static terminateBits(numDataBytes /*int*/, bits) {\n            const capacity = numDataBytes * 8;\n            if (bits.getSize() > capacity) {\n                throw new WriterException('data bits cannot fit in the QR Code' + bits.getSize() + ' > ' +\n                    capacity);\n            }\n            for (let i = 0; i < 4 && bits.getSize() < capacity; ++i) {\n                bits.appendBit(false);\n            }\n            // Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details.\n            // If the last byte isn't 8-bit aligned, we'll add padding bits.\n            const numBitsInLastByte = bits.getSize() & 0x07;\n            if (numBitsInLastByte > 0) {\n                for (let i = numBitsInLastByte; i < 8; i++) {\n                    bits.appendBit(false);\n                }\n            }\n            // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24).\n            const numPaddingBytes = numDataBytes - bits.getSizeInBytes();\n            for (let i = 0; i < numPaddingBytes; ++i) {\n                bits.appendBits((i & 0x01) === 0 ? 0xEC : 0x11, 8);\n            }\n            if (bits.getSize() !== capacity) {\n                throw new WriterException('Bits size does not equal capacity');\n            }\n        }\n        /**\n         * Get number of data bytes and number of error correction bytes for block id \"blockID\". Store\n         * the result in \"numDataBytesInBlock\", and \"numECBytesInBlock\". See table 12 in 8.5.1 of\n         * JISX0510:2004 (p.30)\n         */\n        static getNumDataBytesAndNumECBytesForBlockID(numTotalBytes /*int*/, numDataBytes /*int*/, numRSBlocks /*int*/, blockID /*int*/, numDataBytesInBlock, numECBytesInBlock) {\n            if (blockID >= numRSBlocks) {\n                throw new WriterException('Block ID too large');\n            }\n            // numRsBlocksInGroup2 = 196 % 5 = 1\n            const numRsBlocksInGroup2 = numTotalBytes % numRSBlocks;\n            // numRsBlocksInGroup1 = 5 - 1 = 4\n            const numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2;\n            // numTotalBytesInGroup1 = 196 / 5 = 39\n            const numTotalBytesInGroup1 = Math.floor(numTotalBytes / numRSBlocks);\n            // numTotalBytesInGroup2 = 39 + 1 = 40\n            const numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1;\n            // numDataBytesInGroup1 = 66 / 5 = 13\n            const numDataBytesInGroup1 = Math.floor(numDataBytes / numRSBlocks);\n            // numDataBytesInGroup2 = 13 + 1 = 14\n            const numDataBytesInGroup2 = numDataBytesInGroup1 + 1;\n            // numEcBytesInGroup1 = 39 - 13 = 26\n            const numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1;\n            // numEcBytesInGroup2 = 40 - 14 = 26\n            const numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2;\n            // Sanity checks.\n            // 26 = 26\n            if (numEcBytesInGroup1 !== numEcBytesInGroup2) {\n                throw new WriterException('EC bytes mismatch');\n            }\n            // 5 = 4 + 1.\n            if (numRSBlocks !== numRsBlocksInGroup1 + numRsBlocksInGroup2) {\n                throw new WriterException('RS blocks mismatch');\n            }\n            // 196 = (13 + 26) * 4 + (14 + 26) * 1\n            if (numTotalBytes !==\n                ((numDataBytesInGroup1 + numEcBytesInGroup1) *\n                    numRsBlocksInGroup1) +\n                    ((numDataBytesInGroup2 + numEcBytesInGroup2) *\n                        numRsBlocksInGroup2)) {\n                throw new WriterException('Total bytes mismatch');\n            }\n            if (blockID < numRsBlocksInGroup1) {\n                numDataBytesInBlock[0] = numDataBytesInGroup1;\n                numECBytesInBlock[0] = numEcBytesInGroup1;\n            }\n            else {\n                numDataBytesInBlock[0] = numDataBytesInGroup2;\n                numECBytesInBlock[0] = numEcBytesInGroup2;\n            }\n        }\n        /**\n         * Interleave \"bits\" with corresponding error correction bytes. On success, store the result in\n         * \"result\". The interleave rule is complicated. See 8.6 of JISX0510:2004 (p.37) for details.\n         */\n        static interleaveWithECBytes(bits, numTotalBytes /*int*/, numDataBytes /*int*/, numRSBlocks /*int*/) {\n            // \"bits\" must have \"getNumDataBytes\" bytes of data.\n            if (bits.getSizeInBytes() !== numDataBytes) {\n                throw new WriterException('Number of bits and data bytes does not match');\n            }\n            // Step 1.  Divide data bytes into blocks and generate error correction bytes for them. We'll\n            // store the divided data bytes blocks and error correction bytes blocks into \"blocks\".\n            let dataBytesOffset = 0;\n            let maxNumDataBytes = 0;\n            let maxNumEcBytes = 0;\n            // Since, we know the number of reedsolmon blocks, we can initialize the vector with the number.\n            const blocks = new Array(); // new Array<BlockPair>(numRSBlocks)\n            for (let i = 0; i < numRSBlocks; ++i) {\n                const numDataBytesInBlock = new Int32Array(1);\n                const numEcBytesInBlock = new Int32Array(1);\n                Encoder.getNumDataBytesAndNumECBytesForBlockID(numTotalBytes, numDataBytes, numRSBlocks, i, numDataBytesInBlock, numEcBytesInBlock);\n                const size = numDataBytesInBlock[0];\n                const dataBytes = new Uint8Array(size);\n                bits.toBytes(8 * dataBytesOffset, dataBytes, 0, size);\n                const ecBytes = Encoder.generateECBytes(dataBytes, numEcBytesInBlock[0]);\n                blocks.push(new BlockPair(dataBytes, ecBytes));\n                maxNumDataBytes = Math.max(maxNumDataBytes, size);\n                maxNumEcBytes = Math.max(maxNumEcBytes, ecBytes.length);\n                dataBytesOffset += numDataBytesInBlock[0];\n            }\n            if (numDataBytes !== dataBytesOffset) {\n                throw new WriterException('Data bytes does not match offset');\n            }\n            const result = new BitArray();\n            // First, place data blocks.\n            for (let i = 0; i < maxNumDataBytes; ++i) {\n                for (const block of blocks) {\n                    const dataBytes = block.getDataBytes();\n                    if (i < dataBytes.length) {\n                        result.appendBits(dataBytes[i], 8);\n                    }\n                }\n            }\n            // Then, place error correction blocks.\n            for (let i = 0; i < maxNumEcBytes; ++i) {\n                for (const block of blocks) {\n                    const ecBytes = block.getErrorCorrectionBytes();\n                    if (i < ecBytes.length) {\n                        result.appendBits(ecBytes[i], 8);\n                    }\n                }\n            }\n            if (numTotalBytes !== result.getSizeInBytes()) { // Should be same.\n                throw new WriterException('Interleaving error: ' + numTotalBytes + ' and ' +\n                    result.getSizeInBytes() + ' differ.');\n            }\n            return result;\n        }\n        static generateECBytes(dataBytes, numEcBytesInBlock /*int*/) {\n            const numDataBytes = dataBytes.length;\n            const toEncode = new Int32Array(numDataBytes + numEcBytesInBlock); // int[numDataBytes + numEcBytesInBlock]\n            for (let i = 0; i < numDataBytes; i++) {\n                toEncode[i] = dataBytes[i] & 0xFF;\n            }\n            new ReedSolomonEncoder(GenericGF.QR_CODE_FIELD_256).encode(toEncode, numEcBytesInBlock);\n            const ecBytes = new Uint8Array(numEcBytesInBlock);\n            for (let i = 0; i < numEcBytesInBlock; i++) {\n                ecBytes[i] = /*(byte) */ toEncode[numDataBytes + i];\n            }\n            return ecBytes;\n        }\n        /**\n         * Append mode info. On success, store the result in \"bits\".\n         */\n        static appendModeInfo(mode, bits) {\n            bits.appendBits(mode.getBits(), 4);\n        }\n        /**\n         * Append length info. On success, store the result in \"bits\".\n         */\n        static appendLengthInfo(numLetters /*int*/, version, mode, bits) {\n            const numBits = mode.getCharacterCountBits(version);\n            if (numLetters >= (1 << numBits)) {\n                throw new WriterException(numLetters + ' is bigger than ' + ((1 << numBits) - 1));\n            }\n            bits.appendBits(numLetters, numBits);\n        }\n        /**\n         * Append \"bytes\" in \"mode\" mode (encoding) into \"bits\". On success, store the result in \"bits\".\n         */\n        static appendBytes(content, mode, bits, encoding) {\n            switch (mode) {\n                case Mode$1.NUMERIC:\n                    Encoder.appendNumericBytes(content, bits);\n                    break;\n                case Mode$1.ALPHANUMERIC:\n                    Encoder.appendAlphanumericBytes(content, bits);\n                    break;\n                case Mode$1.BYTE:\n                    Encoder.append8BitBytes(content, bits, encoding);\n                    break;\n                case Mode$1.KANJI:\n                    Encoder.appendKanjiBytes(content, bits);\n                    break;\n                default:\n                    throw new WriterException('Invalid mode: ' + mode);\n            }\n        }\n        static getDigit(singleCharacter) {\n            return singleCharacter.charCodeAt(0) - 48;\n        }\n        static isDigit(singleCharacter) {\n            const cn = Encoder.getDigit(singleCharacter);\n            return cn >= 0 && cn <= 9;\n        }\n        static appendNumericBytes(content, bits) {\n            const length = content.length;\n            let i = 0;\n            while (i < length) {\n                const num1 = Encoder.getDigit(content.charAt(i));\n                if (i + 2 < length) {\n                    // Encode three numeric letters in ten bits.\n                    const num2 = Encoder.getDigit(content.charAt(i + 1));\n                    const num3 = Encoder.getDigit(content.charAt(i + 2));\n                    bits.appendBits(num1 * 100 + num2 * 10 + num3, 10);\n                    i += 3;\n                }\n                else if (i + 1 < length) {\n                    // Encode two numeric letters in seven bits.\n                    const num2 = Encoder.getDigit(content.charAt(i + 1));\n                    bits.appendBits(num1 * 10 + num2, 7);\n                    i += 2;\n                }\n                else {\n                    // Encode one numeric letter in four bits.\n                    bits.appendBits(num1, 4);\n                    i++;\n                }\n            }\n        }\n        static appendAlphanumericBytes(content, bits) {\n            const length = content.length;\n            let i = 0;\n            while (i < length) {\n                const code1 = Encoder.getAlphanumericCode(content.charCodeAt(i));\n                if (code1 === -1) {\n                    throw new WriterException();\n                }\n                if (i + 1 < length) {\n                    const code2 = Encoder.getAlphanumericCode(content.charCodeAt(i + 1));\n                    if (code2 === -1) {\n                        throw new WriterException();\n                    }\n                    // Encode two alphanumeric letters in 11 bits.\n                    bits.appendBits(code1 * 45 + code2, 11);\n                    i += 2;\n                }\n                else {\n                    // Encode one alphanumeric letter in six bits.\n                    bits.appendBits(code1, 6);\n                    i++;\n                }\n            }\n        }\n        static append8BitBytes(content, bits, encoding) {\n            let bytes;\n            try {\n                bytes = StringEncoding.encode(content, encoding);\n            }\n            catch (uee /*: UnsupportedEncodingException*/) {\n                throw new WriterException(uee);\n            }\n            for (let i = 0, length = bytes.length; i !== length; i++) {\n                const b = bytes[i];\n                bits.appendBits(b, 8);\n            }\n        }\n        /**\n         * @throws WriterException\n         */\n        static appendKanjiBytes(content, bits) {\n            let bytes;\n            try {\n                bytes = StringEncoding.encode(content, CharacterSetECI.SJIS);\n            }\n            catch (uee /*: UnsupportedEncodingException*/) {\n                throw new WriterException(uee);\n            }\n            const length = bytes.length;\n            for (let i = 0; i < length; i += 2) {\n                const byte1 = bytes[i] & 0xFF;\n                const byte2 = bytes[i + 1] & 0xFF;\n                const code = ((byte1 << 8) & 0xFFFFFFFF) | byte2;\n                let subtracted = -1;\n                if (code >= 0x8140 && code <= 0x9ffc) {\n                    subtracted = code - 0x8140;\n                }\n                else if (code >= 0xe040 && code <= 0xebbf) {\n                    subtracted = code - 0xc140;\n                }\n                if (subtracted === -1) {\n                    throw new WriterException('Invalid byte sequence');\n                }\n                const encoded = ((subtracted >> 8) * 0xc0) + (subtracted & 0xff);\n                bits.appendBits(encoded, 13);\n            }\n        }\n        static appendECI(eci, bits) {\n            bits.appendBits(Mode$1.ECI.getBits(), 4);\n            // This is correct for values up to 127, which is all we need now.\n            bits.appendBits(eci.getValue(), 8);\n        }\n    }\n    // The original table is defined in the table 5 of JISX0510:2004 (p.19).\n    Encoder.ALPHANUMERIC_TABLE = Int32Array.from([\n        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n        36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,\n        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1,\n        -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n        25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,\n    ]);\n    Encoder.DEFAULT_BYTE_MODE_ENCODING = CharacterSetECI.UTF8.getName(); // \"ISO-8859-1\"\n\n    /**\n     * @deprecated Moving to @zxing/browser\n     */\n    class BrowserQRCodeSvgWriter {\n        /**\n         * Writes and renders a QRCode SVG element.\n         *\n         * @param contents\n         * @param width\n         * @param height\n         * @param hints\n         */\n        write(contents, width, height, hints = null) {\n            if (contents.length === 0) {\n                throw new IllegalArgumentException('Found empty contents');\n            }\n            // if (format != BarcodeFormat.QR_CODE) {\n            //   throw new IllegalArgumentException(\"Can only encode QR_CODE, but got \" + format)\n            // }\n            if (width < 0 || height < 0) {\n                throw new IllegalArgumentException('Requested dimensions are too small: ' + width + 'x' + height);\n            }\n            let errorCorrectionLevel = ErrorCorrectionLevel.L;\n            let quietZone = BrowserQRCodeSvgWriter.QUIET_ZONE_SIZE;\n            if (hints !== null) {\n                if (undefined !== hints.get(EncodeHintType$1.ERROR_CORRECTION)) {\n                    errorCorrectionLevel = ErrorCorrectionLevel.fromString(hints.get(EncodeHintType$1.ERROR_CORRECTION).toString());\n                }\n                if (undefined !== hints.get(EncodeHintType$1.MARGIN)) {\n                    quietZone = Number.parseInt(hints.get(EncodeHintType$1.MARGIN).toString(), 10);\n                }\n            }\n            const code = Encoder.encode(contents, errorCorrectionLevel, hints);\n            return this.renderResult(code, width, height, quietZone);\n        }\n        /**\n         * Renders the result and then appends it to the DOM.\n         */\n        writeToDom(containerElement, contents, width, height, hints = null) {\n            if (typeof containerElement === 'string') {\n                containerElement = document.querySelector(containerElement);\n            }\n            const svgElement = this.write(contents, width, height, hints);\n            if (containerElement)\n                containerElement.appendChild(svgElement);\n        }\n        /**\n         * Note that the input matrix uses 0 == white, 1 == black.\n         * The output matrix uses 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).\n         */\n        renderResult(code, width /*int*/, height /*int*/, quietZone /*int*/) {\n            const input = code.getMatrix();\n            if (input === null) {\n                throw new IllegalStateException();\n            }\n            const inputWidth = input.getWidth();\n            const inputHeight = input.getHeight();\n            const qrWidth = inputWidth + (quietZone * 2);\n            const qrHeight = inputHeight + (quietZone * 2);\n            const outputWidth = Math.max(width, qrWidth);\n            const outputHeight = Math.max(height, qrHeight);\n            const multiple = Math.min(Math.floor(outputWidth / qrWidth), Math.floor(outputHeight / qrHeight));\n            // Padding includes both the quiet zone and the extra white pixels to accommodate the requested\n            // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone.\n            // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will\n            // handle all the padding from 100x100 (the actual QR) up to 200x160.\n            const leftPadding = Math.floor((outputWidth - (inputWidth * multiple)) / 2);\n            const topPadding = Math.floor((outputHeight - (inputHeight * multiple)) / 2);\n            const svgElement = this.createSVGElement(outputWidth, outputHeight);\n            for (let inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {\n                // Write the contents of this row of the barcode\n                for (let inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {\n                    if (input.get(inputX, inputY) === 1) {\n                        const svgRectElement = this.createSvgRectElement(outputX, outputY, multiple, multiple);\n                        svgElement.appendChild(svgRectElement);\n                    }\n                }\n            }\n            return svgElement;\n        }\n        /**\n         * Creates a SVG element.\n         *\n         * @param w SVG's width attribute\n         * @param h SVG's height attribute\n         */\n        createSVGElement(w, h) {\n            const svgElement = document.createElementNS(BrowserQRCodeSvgWriter.SVG_NS, 'svg');\n            svgElement.setAttributeNS(null, 'height', w.toString());\n            svgElement.setAttributeNS(null, 'width', h.toString());\n            return svgElement;\n        }\n        /**\n         * Creates a SVG rect element.\n         *\n         * @param x Element's x coordinate\n         * @param y Element's y coordinate\n         * @param w Element's width attribute\n         * @param h Element's height attribute\n         */\n        createSvgRectElement(x, y, w, h) {\n            const rect = document.createElementNS(BrowserQRCodeSvgWriter.SVG_NS, 'rect');\n            rect.setAttributeNS(null, 'x', x.toString());\n            rect.setAttributeNS(null, 'y', y.toString());\n            rect.setAttributeNS(null, 'height', w.toString());\n            rect.setAttributeNS(null, 'width', h.toString());\n            rect.setAttributeNS(null, 'fill', '#000000');\n            return rect;\n        }\n    }\n    BrowserQRCodeSvgWriter.QUIET_ZONE_SIZE = 4;\n    /**\n     * SVG markup NameSpace\n     */\n    BrowserQRCodeSvgWriter.SVG_NS = 'http://www.w3.org/2000/svg';\n\n    /*import java.util.Map;*/\n    /**\n     * This object renders a QR Code as a BitMatrix 2D array of greyscale values.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class QRCodeWriter {\n        /*@Override*/\n        // public encode(contents: string, format: BarcodeFormat, width: number /*int*/, height: number /*int*/): BitMatrix\n        //     /*throws WriterException */ {\n        //   return encode(contents, format, width, height, null)\n        // }\n        /*@Override*/\n        encode(contents, format, width /*int*/, height /*int*/, hints) {\n            if (contents.length === 0) {\n                throw new IllegalArgumentException('Found empty contents');\n            }\n            if (format !== BarcodeFormat$1.QR_CODE) {\n                throw new IllegalArgumentException('Can only encode QR_CODE, but got ' + format);\n            }\n            if (width < 0 || height < 0) {\n                throw new IllegalArgumentException(`Requested dimensions are too small: ${width}x${height}`);\n            }\n            let errorCorrectionLevel = ErrorCorrectionLevel.L;\n            let quietZone = QRCodeWriter.QUIET_ZONE_SIZE;\n            if (hints !== null) {\n                if (undefined !== hints.get(EncodeHintType$1.ERROR_CORRECTION)) {\n                    errorCorrectionLevel = ErrorCorrectionLevel.fromString(hints.get(EncodeHintType$1.ERROR_CORRECTION).toString());\n                }\n                if (undefined !== hints.get(EncodeHintType$1.MARGIN)) {\n                    quietZone = Number.parseInt(hints.get(EncodeHintType$1.MARGIN).toString(), 10);\n                }\n            }\n            const code = Encoder.encode(contents, errorCorrectionLevel, hints);\n            return QRCodeWriter.renderResult(code, width, height, quietZone);\n        }\n        // Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses\n        // 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).\n        static renderResult(code, width /*int*/, height /*int*/, quietZone /*int*/) {\n            const input = code.getMatrix();\n            if (input === null) {\n                throw new IllegalStateException();\n            }\n            const inputWidth = input.getWidth();\n            const inputHeight = input.getHeight();\n            const qrWidth = inputWidth + (quietZone * 2);\n            const qrHeight = inputHeight + (quietZone * 2);\n            const outputWidth = Math.max(width, qrWidth);\n            const outputHeight = Math.max(height, qrHeight);\n            const multiple = Math.min(Math.floor(outputWidth / qrWidth), Math.floor(outputHeight / qrHeight));\n            // Padding includes both the quiet zone and the extra white pixels to accommodate the requested\n            // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone.\n            // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will\n            // handle all the padding from 100x100 (the actual QR) up to 200x160.\n            const leftPadding = Math.floor((outputWidth - (inputWidth * multiple)) / 2);\n            const topPadding = Math.floor((outputHeight - (inputHeight * multiple)) / 2);\n            const output = new BitMatrix(outputWidth, outputHeight);\n            for (let inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {\n                // Write the contents of this row of the barcode\n                for (let inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {\n                    if (input.get(inputX, inputY) === 1) {\n                        output.setRegion(outputX, outputY, multiple, multiple);\n                    }\n                }\n            }\n            return output;\n        }\n    }\n    QRCodeWriter.QUIET_ZONE_SIZE = 4;\n\n    /*import java.util.Map;*/\n    /**\n     * This is a factory class which finds the appropriate Writer subclass for the BarcodeFormat\n     * requested and encodes the barcode with the supplied contents.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class MultiFormatWriter {\n        /*@Override*/\n        // public encode(contents: string,\n        //                         format: BarcodeFormat,\n        //                         width: number /*int*/,\n        //                         height: number /*int*/): BitMatrix /*throws WriterException */ {\n        //   return encode(contents, format, width, height, null)\n        // }\n        /*@Override*/\n        encode(contents, format, width /*int*/, height /*int*/, hints) {\n            let writer;\n            switch (format) {\n                // case BarcodeFormat.EAN_8:\n                //   writer = new EAN8Writer()\n                //   break\n                // case BarcodeFormat.UPC_E:\n                //   writer = new UPCEWriter()\n                //   break\n                // case BarcodeFormat.EAN_13:\n                //   writer = new EAN13Writer()\n                //   break\n                // case BarcodeFormat.UPC_A:\n                //   writer = new UPCAWriter()\n                //   break\n                case BarcodeFormat$1.QR_CODE:\n                    writer = new QRCodeWriter();\n                    break;\n                // case BarcodeFormat.CODE_39:\n                //   writer = new Code39Writer()\n                //   break\n                // case BarcodeFormat.CODE_93:\n                //   writer = new Code93Writer()\n                //   break\n                // case BarcodeFormat.CODE_128:\n                //   writer = new Code128Writer()\n                //   break\n                // case BarcodeFormat.ITF:\n                //   writer = new ITFWriter()\n                //   break\n                // case BarcodeFormat.PDF_417:\n                //   writer = new PDF417Writer()\n                //   break\n                // case BarcodeFormat.CODABAR:\n                //   writer = new CodaBarWriter()\n                //   break\n                // case BarcodeFormat.DATA_MATRIX:\n                //   writer = new DataMatrixWriter()\n                //   break\n                // case BarcodeFormat.AZTEC:\n                //   writer = new AztecWriter()\n                //   break\n                default:\n                    throw new IllegalArgumentException('No encoder available for format ' + format);\n            }\n            return writer.encode(contents, format, width, height, hints);\n        }\n    }\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * This object extends LuminanceSource around an array of YUV data returned from the camera driver,\n     * with the option to crop to a rectangle within the full data. This can be used to exclude\n     * superfluous pixels around the perimeter and speed up decoding.\n     *\n     * It works for any pixel format where the Y channel is planar and appears first, including\n     * YCbCr_420_SP and YCbCr_422_SP.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class PlanarYUVLuminanceSource extends LuminanceSource {\n        constructor(yuvData, dataWidth /*int*/, dataHeight /*int*/, left /*int*/, top /*int*/, width /*int*/, height /*int*/, reverseHorizontal) {\n            super(width, height);\n            this.yuvData = yuvData;\n            this.dataWidth = dataWidth;\n            this.dataHeight = dataHeight;\n            this.left = left;\n            this.top = top;\n            if (left + width > dataWidth || top + height > dataHeight) {\n                throw new IllegalArgumentException('Crop rectangle does not fit within image data.');\n            }\n            if (reverseHorizontal) {\n                this.reverseHorizontal(width, height);\n            }\n        }\n        /*@Override*/\n        getRow(y /*int*/, row) {\n            if (y < 0 || y >= this.getHeight()) {\n                throw new IllegalArgumentException('Requested row is outside the image: ' + y);\n            }\n            const width = this.getWidth();\n            if (row === null || row === undefined || row.length < width) {\n                row = new Uint8ClampedArray(width);\n            }\n            const offset = (y + this.top) * this.dataWidth + this.left;\n            System.arraycopy(this.yuvData, offset, row, 0, width);\n            return row;\n        }\n        /*@Override*/\n        getMatrix() {\n            const width = this.getWidth();\n            const height = this.getHeight();\n            // If the caller asks for the entire underlying image, save the copy and give them the\n            // original data. The docs specifically warn that result.length must be ignored.\n            if (width === this.dataWidth && height === this.dataHeight) {\n                return this.yuvData;\n            }\n            const area = width * height;\n            const matrix = new Uint8ClampedArray(area);\n            let inputOffset = this.top * this.dataWidth + this.left;\n            // If the width matches the full width of the underlying data, perform a single copy.\n            if (width === this.dataWidth) {\n                System.arraycopy(this.yuvData, inputOffset, matrix, 0, area);\n                return matrix;\n            }\n            // Otherwise copy one cropped row at a time.\n            for (let y = 0; y < height; y++) {\n                const outputOffset = y * width;\n                System.arraycopy(this.yuvData, inputOffset, matrix, outputOffset, width);\n                inputOffset += this.dataWidth;\n            }\n            return matrix;\n        }\n        /*@Override*/\n        isCropSupported() {\n            return true;\n        }\n        /*@Override*/\n        crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n            return new PlanarYUVLuminanceSource(this.yuvData, this.dataWidth, this.dataHeight, this.left + left, this.top + top, width, height, false);\n        }\n        renderThumbnail() {\n            const width = this.getWidth() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n            const height = this.getHeight() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n            const pixels = new Int32Array(width * height);\n            const yuv = this.yuvData;\n            let inputOffset = this.top * this.dataWidth + this.left;\n            for (let y = 0; y < height; y++) {\n                const outputOffset = y * width;\n                for (let x = 0; x < width; x++) {\n                    const grey = yuv[inputOffset + x * PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR] & 0xff;\n                    pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101);\n                }\n                inputOffset += this.dataWidth * PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n            }\n            return pixels;\n        }\n        /**\n         * @return width of image from {@link #renderThumbnail()}\n         */\n        getThumbnailWidth() {\n            return this.getWidth() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n        }\n        /**\n         * @return height of image from {@link #renderThumbnail()}\n         */\n        getThumbnailHeight() {\n            return this.getHeight() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n        }\n        reverseHorizontal(width /*int*/, height /*int*/) {\n            const yuvData = this.yuvData;\n            for (let y = 0, rowStart = this.top * this.dataWidth + this.left; y < height; y++, rowStart += this.dataWidth) {\n                const middle = rowStart + width / 2;\n                for (let x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) {\n                    const temp = yuvData[x1];\n                    yuvData[x1] = yuvData[x2];\n                    yuvData[x2] = temp;\n                }\n            }\n        }\n        invert() {\n            return new InvertedLuminanceSource(this);\n        }\n    }\n    PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR = 2;\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * This class is used to help decode images from files which arrive as RGB data from\n     * an ARGB pixel array. It does not support rotation.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @author Betaminos\n     */\n    class RGBLuminanceSource extends LuminanceSource {\n        constructor(luminances, width /*int*/, height /*int*/, dataWidth /*int*/, dataHeight /*int*/, left /*int*/, top /*int*/) {\n            super(width, height);\n            this.dataWidth = dataWidth;\n            this.dataHeight = dataHeight;\n            this.left = left;\n            this.top = top;\n            if (luminances.BYTES_PER_ELEMENT === 4) { // Int32Array\n                const size = width * height;\n                const luminancesUint8Array = new Uint8ClampedArray(size);\n                for (let offset = 0; offset < size; offset++) {\n                    const pixel = luminances[offset];\n                    const r = (pixel >> 16) & 0xff; // red\n                    const g2 = (pixel >> 7) & 0x1fe; // 2 * green\n                    const b = pixel & 0xff; // blue\n                    // Calculate green-favouring average cheaply\n                    luminancesUint8Array[offset] = /*(byte) */ ((r + g2 + b) / 4) & 0xFF;\n                }\n                this.luminances = luminancesUint8Array;\n            }\n            else {\n                this.luminances = luminances;\n            }\n            if (undefined === dataWidth) {\n                this.dataWidth = width;\n            }\n            if (undefined === dataHeight) {\n                this.dataHeight = height;\n            }\n            if (undefined === left) {\n                this.left = 0;\n            }\n            if (undefined === top) {\n                this.top = 0;\n            }\n            if (this.left + width > this.dataWidth || this.top + height > this.dataHeight) {\n                throw new IllegalArgumentException('Crop rectangle does not fit within image data.');\n            }\n        }\n        /*@Override*/\n        getRow(y /*int*/, row) {\n            if (y < 0 || y >= this.getHeight()) {\n                throw new IllegalArgumentException('Requested row is outside the image: ' + y);\n            }\n            const width = this.getWidth();\n            if (row === null || row === undefined || row.length < width) {\n                row = new Uint8ClampedArray(width);\n            }\n            const offset = (y + this.top) * this.dataWidth + this.left;\n            System.arraycopy(this.luminances, offset, row, 0, width);\n            return row;\n        }\n        /*@Override*/\n        getMatrix() {\n            const width = this.getWidth();\n            const height = this.getHeight();\n            // If the caller asks for the entire underlying image, save the copy and give them the\n            // original data. The docs specifically warn that result.length must be ignored.\n            if (width === this.dataWidth && height === this.dataHeight) {\n                return this.luminances;\n            }\n            const area = width * height;\n            const matrix = new Uint8ClampedArray(area);\n            let inputOffset = this.top * this.dataWidth + this.left;\n            // If the width matches the full width of the underlying data, perform a single copy.\n            if (width === this.dataWidth) {\n                System.arraycopy(this.luminances, inputOffset, matrix, 0, area);\n                return matrix;\n            }\n            // Otherwise copy one cropped row at a time.\n            for (let y = 0; y < height; y++) {\n                const outputOffset = y * width;\n                System.arraycopy(this.luminances, inputOffset, matrix, outputOffset, width);\n                inputOffset += this.dataWidth;\n            }\n            return matrix;\n        }\n        /*@Override*/\n        isCropSupported() {\n            return true;\n        }\n        /*@Override*/\n        crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n            return new RGBLuminanceSource(this.luminances, width, height, this.dataWidth, this.dataHeight, this.left + left, this.top + top);\n        }\n        invert() {\n            return new InvertedLuminanceSource(this);\n        }\n    }\n\n    /**\n     * Just to make a shortcut between Java code and TS code.\n     */\n    class Charset extends CharacterSetECI {\n        static forName(name) {\n            return this.getCharacterSetECIByName(name);\n        }\n    }\n\n    /**\n     * Just to make a shortcut between Java code and TS code.\n     */\n    class StandardCharsets {\n    }\n    StandardCharsets.ISO_8859_1 = CharacterSetECI.ISO8859_1;\n\n    /*\n    * Copyright 2013 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /**\n     * Aztec 2D code representation\n     *\n     * @author Rustam Abdullaev\n     */\n    /*public final*/ class AztecCode {\n        /**\n         * @return {@code true} if compact instead of full mode\n         */\n        isCompact() {\n            return this.compact;\n        }\n        setCompact(compact) {\n            this.compact = compact;\n        }\n        /**\n         * @return size in pixels (width and height)\n         */\n        getSize() {\n            return this.size;\n        }\n        setSize(size) {\n            this.size = size;\n        }\n        /**\n         * @return number of levels\n         */\n        getLayers() {\n            return this.layers;\n        }\n        setLayers(layers) {\n            this.layers = layers;\n        }\n        /**\n         * @return number of data codewords\n         */\n        getCodeWords() {\n            return this.codeWords;\n        }\n        setCodeWords(codeWords) {\n            this.codeWords = codeWords;\n        }\n        /**\n         * @return the symbol image\n         */\n        getMatrix() {\n            return this.matrix;\n        }\n        setMatrix(matrix) {\n            this.matrix = matrix;\n        }\n    }\n\n    class Collections {\n        /**\n         * The singletonList(T) method is used to return an immutable list containing only the specified object.\n         */\n        static singletonList(item) {\n            return [item];\n        }\n        /**\n         * The min(Collection<? extends T>, Comparator<? super T>) method is used to return the minimum element of the given collection, according to the order induced by the specified comparator.\n         */\n        static min(collection, comparator) {\n            return collection.sort(comparator)[0];\n        }\n    }\n\n    /*\n    * Copyright 2013 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    class Token {\n        constructor(previous) {\n            this.previous = previous;\n        }\n        getPrevious() {\n            return this.previous;\n        }\n    }\n\n    /*\n    * Copyright 2013 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /*final*/ class SimpleToken extends Token {\n        constructor(previous, value, bitCount) {\n            super(previous);\n            this.value = value;\n            this.bitCount = bitCount;\n        }\n        /**\n         * @Override\n         */\n        appendTo(bitArray, text) {\n            bitArray.appendBits(this.value, this.bitCount);\n        }\n        add(value, bitCount) {\n            return new SimpleToken(this, value, bitCount);\n        }\n        addBinaryShift(start, byteCount) {\n            // no-op can't binary shift a simple token\n            console.warn('addBinaryShift on SimpleToken, this simply returns a copy of this token');\n            return new SimpleToken(this, start, byteCount);\n        }\n        /**\n         * @Override\n         */\n        toString() {\n            let value = this.value & ((1 << this.bitCount) - 1);\n            value |= 1 << this.bitCount;\n            return '<' + Integer.toBinaryString(value | (1 << this.bitCount)).substring(1) + '>';\n        }\n    }\n\n    /*\n    * Copyright 2013 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /*final*/ class BinaryShiftToken extends SimpleToken {\n        constructor(previous, binaryShiftStart, binaryShiftByteCount) {\n            super(previous, 0, 0);\n            this.binaryShiftStart = binaryShiftStart;\n            this.binaryShiftByteCount = binaryShiftByteCount;\n        }\n        /**\n         * @Override\n         */\n        appendTo(bitArray, text) {\n            for (let i = 0; i < this.binaryShiftByteCount; i++) {\n                if (i === 0 || (i === 31 && this.binaryShiftByteCount <= 62)) {\n                    // We need a header before the first character, and before\n                    // character 31 when the total byte code is <= 62\n                    bitArray.appendBits(31, 5); // BINARY_SHIFT\n                    if (this.binaryShiftByteCount > 62) {\n                        bitArray.appendBits(this.binaryShiftByteCount - 31, 16);\n                    }\n                    else if (i === 0) {\n                        // 1 <= binaryShiftByteCode <= 62\n                        bitArray.appendBits(Math.min(this.binaryShiftByteCount, 31), 5);\n                    }\n                    else {\n                        // 32 <= binaryShiftCount <= 62 and i == 31\n                        bitArray.appendBits(this.binaryShiftByteCount - 31, 5);\n                    }\n                }\n                bitArray.appendBits(text[this.binaryShiftStart + i], 8);\n            }\n        }\n        addBinaryShift(start, byteCount) {\n            // int bitCount = (byteCount * 8) + (byteCount <= 31 ? 10 : byteCount <= 62 ? 20 : 21);\n            return new BinaryShiftToken(this, start, byteCount);\n        }\n        /**\n         * @Override\n         */\n        toString() {\n            return '<' + this.binaryShiftStart + '::' + (this.binaryShiftStart + this.binaryShiftByteCount - 1) + '>';\n        }\n    }\n\n    function addBinaryShift(token, start, byteCount) {\n        // int bitCount = (byteCount * 8) + (byteCount <= 31 ? 10 : byteCount <= 62 ? 20 : 21);\n        return new BinaryShiftToken(token, start, byteCount);\n    }\n    function add(token, value, bitCount) {\n        return new SimpleToken(token, value, bitCount);\n    }\n\n    const /*final*/ MODE_NAMES = [\n        'UPPER',\n        'LOWER',\n        'DIGIT',\n        'MIXED',\n        'PUNCT'\n    ];\n    const /*final*/ MODE_UPPER = 0; // 5 bits\n    const /*final*/ MODE_LOWER = 1; // 5 bits\n    const /*final*/ MODE_DIGIT = 2; // 4 bits\n    const /*final*/ MODE_MIXED = 3; // 5 bits\n    const /*final*/ MODE_PUNCT = 4; // 5 bits\n    const EMPTY_TOKEN = new SimpleToken(null, 0, 0);\n\n    // The Latch Table shows, for each pair of Modes, the optimal method for\n    // getting from one mode to another.  In the worst possible case, this can\n    // be up to 14 bits.  In the best possible case, we are already there!\n    // The high half-word of each entry gives the number of bits.\n    // The low half-word of each entry are the actual bits necessary to change\n    const LATCH_TABLE = [\n        Int32Array.from([\n            0,\n            (5 << 16) + 28,\n            (5 << 16) + 30,\n            (5 << 16) + 29,\n            (10 << 16) + (29 << 5) + 30 // UPPER -> MIXED -> PUNCT\n        ]),\n        Int32Array.from([\n            (9 << 16) + (30 << 4) + 14,\n            0,\n            (5 << 16) + 30,\n            (5 << 16) + 29,\n            (10 << 16) + (29 << 5) + 30 // LOWER -> MIXED -> PUNCT\n        ]),\n        Int32Array.from([\n            (4 << 16) + 14,\n            (9 << 16) + (14 << 5) + 28,\n            0,\n            (9 << 16) + (14 << 5) + 29,\n            (14 << 16) + (14 << 10) + (29 << 5) + 30\n            // DIGIT -> UPPER -> MIXED -> PUNCT\n        ]),\n        Int32Array.from([\n            (5 << 16) + 29,\n            (5 << 16) + 28,\n            (10 << 16) + (29 << 5) + 30,\n            0,\n            (5 << 16) + 30 // MIXED -> PUNCT\n        ]),\n        Int32Array.from([\n            (5 << 16) + 31,\n            (10 << 16) + (31 << 5) + 28,\n            (10 << 16) + (31 << 5) + 30,\n            (10 << 16) + (31 << 5) + 29,\n            0\n        ])\n    ];\n\n    function static_SHIFT_TABLE(SHIFT_TABLE) {\n        for (let table /*Int32Array*/ of SHIFT_TABLE) {\n            Arrays.fill(table, -1);\n        }\n        SHIFT_TABLE[MODE_UPPER][MODE_PUNCT] = 0;\n        SHIFT_TABLE[MODE_LOWER][MODE_PUNCT] = 0;\n        SHIFT_TABLE[MODE_LOWER][MODE_UPPER] = 28;\n        SHIFT_TABLE[MODE_MIXED][MODE_PUNCT] = 0;\n        SHIFT_TABLE[MODE_DIGIT][MODE_PUNCT] = 0;\n        SHIFT_TABLE[MODE_DIGIT][MODE_UPPER] = 15;\n        return SHIFT_TABLE;\n    }\n    const /*final*/ SHIFT_TABLE = static_SHIFT_TABLE(Arrays.createInt32Array(6, 6)); // mode shift codes, per table\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * State represents all information about a sequence necessary to generate the current output.\n     * Note that a state is immutable.\n     */\n    /*final*/ class State {\n        constructor(token, mode, binaryBytes, bitCount) {\n            this.token = token;\n            this.mode = mode;\n            this.binaryShiftByteCount = binaryBytes;\n            this.bitCount = bitCount;\n            // Make sure we match the token\n            // int binaryShiftBitCount = (binaryShiftByteCount * 8) +\n            //    (binaryShiftByteCount === 0 ? 0 :\n            //     binaryShiftByteCount <= 31 ? 10 :\n            //     binaryShiftByteCount <= 62 ? 20 : 21);\n            // assert this.bitCount === token.getTotalBitCount() + binaryShiftBitCount;\n        }\n        getMode() {\n            return this.mode;\n        }\n        getToken() {\n            return this.token;\n        }\n        getBinaryShiftByteCount() {\n            return this.binaryShiftByteCount;\n        }\n        getBitCount() {\n            return this.bitCount;\n        }\n        // Create a new state representing this state with a latch to a (not\n        // necessary different) mode, and then a code.\n        latchAndAppend(mode, value) {\n            // assert binaryShiftByteCount === 0;\n            let bitCount = this.bitCount;\n            let token = this.token;\n            if (mode !== this.mode) {\n                let latch = LATCH_TABLE[this.mode][mode];\n                token = add(token, latch & 0xffff, latch >> 16);\n                bitCount += latch >> 16;\n            }\n            let latchModeBitCount = mode === MODE_DIGIT ? 4 : 5;\n            token = add(token, value, latchModeBitCount);\n            return new State(token, mode, 0, bitCount + latchModeBitCount);\n        }\n        // Create a new state representing this state, with a temporary shift\n        // to a different mode to output a single value.\n        shiftAndAppend(mode, value) {\n            // assert binaryShiftByteCount === 0 && this.mode !== mode;\n            let token = this.token;\n            let thisModeBitCount = this.mode === MODE_DIGIT ? 4 : 5;\n            // Shifts exist only to UPPER and PUNCT, both with tokens size 5.\n            token = add(token, SHIFT_TABLE[this.mode][mode], thisModeBitCount);\n            token = add(token, value, 5);\n            return new State(token, this.mode, 0, this.bitCount + thisModeBitCount + 5);\n        }\n        // Create a new state representing this state, but an additional character\n        // output in Binary Shift mode.\n        addBinaryShiftChar(index) {\n            let token = this.token;\n            let mode = this.mode;\n            let bitCount = this.bitCount;\n            if (this.mode === MODE_PUNCT || this.mode === MODE_DIGIT) {\n                // assert binaryShiftByteCount === 0;\n                let latch = LATCH_TABLE[mode][MODE_UPPER];\n                token = add(token, latch & 0xffff, latch >> 16);\n                bitCount += latch >> 16;\n                mode = MODE_UPPER;\n            }\n            let deltaBitCount = this.binaryShiftByteCount === 0 || this.binaryShiftByteCount === 31\n                ? 18\n                : this.binaryShiftByteCount === 62\n                    ? 9\n                    : 8;\n            let result = new State(token, mode, this.binaryShiftByteCount + 1, bitCount + deltaBitCount);\n            if (result.binaryShiftByteCount === 2047 + 31) {\n                // The string is as long as it's allowed to be.  We should end it.\n                result = result.endBinaryShift(index + 1);\n            }\n            return result;\n        }\n        // Create the state identical to this one, but we are no longer in\n        // Binary Shift mode.\n        endBinaryShift(index) {\n            if (this.binaryShiftByteCount === 0) {\n                return this;\n            }\n            let token = this.token;\n            token = addBinaryShift(token, index - this.binaryShiftByteCount, this.binaryShiftByteCount);\n            // assert token.getTotalBitCount() === this.bitCount;\n            return new State(token, this.mode, 0, this.bitCount);\n        }\n        // Returns true if \"this\" state is better (equal: or) to be in than \"that\"\n        // state under all possible circumstances.\n        isBetterThanOrEqualTo(other) {\n            let newModeBitCount = this.bitCount + (LATCH_TABLE[this.mode][other.mode] >> 16);\n            if (this.binaryShiftByteCount < other.binaryShiftByteCount) {\n                // add additional B/S encoding cost of other, if any\n                newModeBitCount +=\n                    State.calculateBinaryShiftCost(other) -\n                        State.calculateBinaryShiftCost(this);\n            }\n            else if (this.binaryShiftByteCount > other.binaryShiftByteCount &&\n                other.binaryShiftByteCount > 0) {\n                // maximum possible additional cost (it: h)\n                newModeBitCount += 10;\n            }\n            return newModeBitCount <= other.bitCount;\n        }\n        toBitArray(text) {\n            // Reverse the tokens, so that they are in the order that they should\n            // be output\n            let symbols = [];\n            for (let token = this.endBinaryShift(text.length).token; token !== null; token = token.getPrevious()) {\n                symbols.unshift(token);\n            }\n            let bitArray = new BitArray();\n            // Add each token to the result.\n            for (const symbol of symbols) {\n                symbol.appendTo(bitArray, text);\n            }\n            // assert bitArray.getSize() === this.bitCount;\n            return bitArray;\n        }\n        /**\n         * @Override\n         */\n        toString() {\n            return StringUtils.format('%s bits=%d bytes=%d', MODE_NAMES[this.mode], this.bitCount, this.binaryShiftByteCount);\n        }\n        static calculateBinaryShiftCost(state) {\n            if (state.binaryShiftByteCount > 62) {\n                return 21; // B/S with extended length\n            }\n            if (state.binaryShiftByteCount > 31) {\n                return 20; // two B/S\n            }\n            if (state.binaryShiftByteCount > 0) {\n                return 10; // one B/S\n            }\n            return 0;\n        }\n    }\n    State.INITIAL_STATE = new State(EMPTY_TOKEN, MODE_UPPER, 0, 0);\n\n    function static_CHAR_MAP(CHAR_MAP) {\n        const spaceCharCode = StringUtils.getCharCode(' ');\n        const pointCharCode = StringUtils.getCharCode('.');\n        const commaCharCode = StringUtils.getCharCode(',');\n        CHAR_MAP[MODE_UPPER][spaceCharCode] = 1;\n        const zUpperCharCode = StringUtils.getCharCode('Z');\n        const aUpperCharCode = StringUtils.getCharCode('A');\n        for (let c = aUpperCharCode; c <= zUpperCharCode; c++) {\n            CHAR_MAP[MODE_UPPER][c] = c - aUpperCharCode + 2;\n        }\n        CHAR_MAP[MODE_LOWER][spaceCharCode] = 1;\n        const zLowerCharCode = StringUtils.getCharCode('z');\n        const aLowerCharCode = StringUtils.getCharCode('a');\n        for (let c = aLowerCharCode; c <= zLowerCharCode; c++) {\n            CHAR_MAP[MODE_LOWER][c] = c - aLowerCharCode + 2;\n        }\n        CHAR_MAP[MODE_DIGIT][spaceCharCode] = 1;\n        const nineCharCode = StringUtils.getCharCode('9');\n        const zeroCharCode = StringUtils.getCharCode('0');\n        for (let c = zeroCharCode; c <= nineCharCode; c++) {\n            CHAR_MAP[MODE_DIGIT][c] = c - zeroCharCode + 2;\n        }\n        CHAR_MAP[MODE_DIGIT][commaCharCode] = 12;\n        CHAR_MAP[MODE_DIGIT][pointCharCode] = 13;\n        const mixedTable = [\n            '\\x00',\n            ' ',\n            '\\x01',\n            '\\x02',\n            '\\x03',\n            '\\x04',\n            '\\x05',\n            '\\x06',\n            '\\x07',\n            '\\b',\n            '\\t',\n            '\\n',\n            '\\x0b',\n            '\\f',\n            '\\r',\n            '\\x1b',\n            '\\x1c',\n            '\\x1d',\n            '\\x1e',\n            '\\x1f',\n            '@',\n            '\\\\',\n            '^',\n            '_',\n            '`',\n            '|',\n            '~',\n            '\\x7f'\n        ];\n        for (let i = 0; i < mixedTable.length; i++) {\n            CHAR_MAP[MODE_MIXED][StringUtils.getCharCode(mixedTable[i])] = i;\n        }\n        const punctTable = [\n            '\\x00',\n            '\\r',\n            '\\x00',\n            '\\x00',\n            '\\x00',\n            '\\x00',\n            '!',\n            '\\'',\n            '#',\n            '$',\n            '%',\n            '&',\n            '\\'',\n            '(',\n            ')',\n            '*',\n            '+',\n            ',',\n            '-',\n            '.',\n            '/',\n            ':',\n            ';',\n            '<',\n            '=',\n            '>',\n            '?',\n            '[',\n            ']',\n            '{',\n            '}'\n        ];\n        for (let i = 0; i < punctTable.length; i++) {\n            if (StringUtils.getCharCode(punctTable[i]) > 0) {\n                CHAR_MAP[MODE_PUNCT][StringUtils.getCharCode(punctTable[i])] = i;\n            }\n        }\n        return CHAR_MAP;\n    }\n    const CHAR_MAP = static_CHAR_MAP(Arrays.createInt32Array(5, 256));\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * This produces nearly optimal encodings of text into the first-level of\n     * encoding used by Aztec code.\n     *\n     * It uses a dynamic algorithm.  For each prefix of the string, it determines\n     * a set of encodings that could lead to this prefix.  We repeatedly add a\n     * character and generate a new set of optimal encodings until we have read\n     * through the entire input.\n     *\n     * @author Frank Yellin\n     * @author Rustam Abdullaev\n     */\n    /*public final*/ class HighLevelEncoder {\n        constructor(text) {\n            this.text = text;\n        }\n        /**\n         * @return text represented by this encoder encoded as a {@link BitArray}\n         */\n        encode() {\n            const spaceCharCode = StringUtils.getCharCode(' ');\n            const lineBreakCharCode = StringUtils.getCharCode('\\n');\n            let states = Collections.singletonList(State.INITIAL_STATE);\n            for (let index = 0; index < this.text.length; index++) {\n                let pairCode;\n                let nextChar = index + 1 < this.text.length ? this.text[index + 1] : 0;\n                switch (this.text[index]) {\n                    case StringUtils.getCharCode('\\r'):\n                        pairCode = nextChar === lineBreakCharCode ? 2 : 0;\n                        break;\n                    case StringUtils.getCharCode('.'):\n                        pairCode = nextChar === spaceCharCode ? 3 : 0;\n                        break;\n                    case StringUtils.getCharCode(','):\n                        pairCode = nextChar === spaceCharCode ? 4 : 0;\n                        break;\n                    case StringUtils.getCharCode(':'):\n                        pairCode = nextChar === spaceCharCode ? 5 : 0;\n                        break;\n                    default:\n                        pairCode = 0;\n                }\n                if (pairCode > 0) {\n                    // We have one of the four special PUNCT pairs.  Treat them specially.\n                    // Get a new set of states for the two new characters.\n                    states = HighLevelEncoder.updateStateListForPair(states, index, pairCode);\n                    index++;\n                }\n                else {\n                    // Get a new set of states for the new character.\n                    states = this.updateStateListForChar(states, index);\n                }\n            }\n            // We are left with a set of states.  Find the shortest one.\n            const minState = Collections.min(states, (a, b) => {\n                return a.getBitCount() - b.getBitCount();\n            });\n            // Convert it to a bit array, and return.\n            return minState.toBitArray(this.text);\n        }\n        // We update a set of states for a new character by updating each state\n        // for the new character, merging the results, and then removing the\n        // non-optimal states.\n        updateStateListForChar(states, index) {\n            const result = [];\n            for (let state /*State*/ of states) {\n                this.updateStateForChar(state, index, result);\n            }\n            return HighLevelEncoder.simplifyStates(result);\n        }\n        // Return a set of states that represent the possible ways of updating this\n        // state for the next character.  The resulting set of states are added to\n        // the \"result\" list.\n        updateStateForChar(state, index, result) {\n            let ch = (this.text[index] & 0xff);\n            let charInCurrentTable = CHAR_MAP[state.getMode()][ch] > 0;\n            let stateNoBinary = null;\n            for (let mode /*int*/ = 0; mode <= MODE_PUNCT; mode++) {\n                let charInMode = CHAR_MAP[mode][ch];\n                if (charInMode > 0) {\n                    if (stateNoBinary == null) {\n                        // Only create stateNoBinary the first time it's required.\n                        stateNoBinary = state.endBinaryShift(index);\n                    }\n                    // Try generating the character by latching to its mode\n                    if (!charInCurrentTable ||\n                        mode === state.getMode() ||\n                        mode === MODE_DIGIT) {\n                        // If the character is in the current table, we don't want to latch to\n                        // any other mode except possibly digit (which uses only 4 bits).  Any\n                        // other latch would be equally successful *after* this character, and\n                        // so wouldn't save any bits.\n                        const latchState = stateNoBinary.latchAndAppend(mode, charInMode);\n                        result.push(latchState);\n                    }\n                    // Try generating the character by switching to its mode.\n                    if (!charInCurrentTable &&\n                        SHIFT_TABLE[state.getMode()][mode] >= 0) {\n                        // It never makes sense to temporarily shift to another mode if the\n                        // character exists in the current mode.  That can never save bits.\n                        const shiftState = stateNoBinary.shiftAndAppend(mode, charInMode);\n                        result.push(shiftState);\n                    }\n                }\n            }\n            if (state.getBinaryShiftByteCount() > 0 ||\n                CHAR_MAP[state.getMode()][ch] === 0) {\n                // It's never worthwhile to go into binary shift mode if you're not already\n                // in binary shift mode, and the character exists in your current mode.\n                // That can never save bits over just outputting the char in the current mode.\n                let binaryState = state.addBinaryShiftChar(index);\n                result.push(binaryState);\n            }\n        }\n        static updateStateListForPair(states, index, pairCode) {\n            const result = [];\n            for (let state /*State*/ of states) {\n                this.updateStateForPair(state, index, pairCode, result);\n            }\n            return this.simplifyStates(result);\n        }\n        static updateStateForPair(state, index, pairCode, result) {\n            let stateNoBinary = state.endBinaryShift(index);\n            // Possibility 1.  Latch to C.MODE_PUNCT, and then append this code\n            result.push(stateNoBinary.latchAndAppend(MODE_PUNCT, pairCode));\n            if (state.getMode() !== MODE_PUNCT) {\n                // Possibility 2.  Shift to C.MODE_PUNCT, and then append this code.\n                // Every state except C.MODE_PUNCT (handled above) can shift\n                result.push(stateNoBinary.shiftAndAppend(MODE_PUNCT, pairCode));\n            }\n            if (pairCode === 3 || pairCode === 4) {\n                // both characters are in DIGITS.  Sometimes better to just add two digits\n                let digitState = stateNoBinary\n                    .latchAndAppend(MODE_DIGIT, 16 - pairCode) // period or comma in DIGIT\n                    .latchAndAppend(MODE_DIGIT, 1); // space in DIGIT\n                result.push(digitState);\n            }\n            if (state.getBinaryShiftByteCount() > 0) {\n                // It only makes sense to do the characters as binary if we're already\n                // in binary mode.\n                let binaryState = state\n                    .addBinaryShiftChar(index)\n                    .addBinaryShiftChar(index + 1);\n                result.push(binaryState);\n            }\n        }\n        static simplifyStates(states) {\n            let result = [];\n            for (const newState of states) {\n                let add = true;\n                for (const oldState of result) {\n                    if (oldState.isBetterThanOrEqualTo(newState)) {\n                        add = false;\n                        break;\n                    }\n                    if (newState.isBetterThanOrEqualTo(oldState)) {\n                        // iterator.remove();\n                        result = result.filter(x => x !== oldState); // remove old state\n                    }\n                }\n                if (add) {\n                    result.push(newState);\n                }\n            }\n            return result;\n        }\n    }\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    // package com.google.zxing.aztec.encoder;\n    // import com.google.zxing.common.BitArray;\n    // import com.google.zxing.common.BitMatrix;\n    // import com.google.zxing.common.reedsolomon.GenericGF;\n    // import com.google.zxing.common.reedsolomon.ReedSolomonEncoder;\n    /**\n     * Generates Aztec 2D barcodes.\n     *\n     * @author Rustam Abdullaev\n     */\n    /*public final*/ class Encoder$1 {\n        constructor() {\n        }\n        /**\n         * Encodes the given binary content as an Aztec symbol\n         *\n         * @param data input data string\n         * @return Aztec symbol matrix with metadata\n         */\n        static encodeBytes(data) {\n            return Encoder$1.encode(data, Encoder$1.DEFAULT_EC_PERCENT, Encoder$1.DEFAULT_AZTEC_LAYERS);\n        }\n        /**\n         * Encodes the given binary content as an Aztec symbol\n         *\n         * @param data input data string\n         * @param minECCPercent minimal percentage of error check words (According to ISO/IEC 24778:2008,\n         *                      a minimum of 23% + 3 words is recommended)\n         * @param userSpecifiedLayers if non-zero, a user-specified value for the number of layers\n         * @return Aztec symbol matrix with metadata\n         */\n        static encode(data, minECCPercent, userSpecifiedLayers) {\n            // High-level encode\n            let bits = new HighLevelEncoder(data).encode();\n            // stuff bits and choose symbol size\n            let eccBits = Integer.truncDivision((bits.getSize() * minECCPercent), 100) + 11;\n            let totalSizeBits = bits.getSize() + eccBits;\n            let compact;\n            let layers;\n            let totalBitsInLayer;\n            let wordSize;\n            let stuffedBits;\n            if (userSpecifiedLayers !== Encoder$1.DEFAULT_AZTEC_LAYERS) {\n                compact = userSpecifiedLayers < 0;\n                layers = Math.abs(userSpecifiedLayers);\n                if (layers > (compact ? Encoder$1.MAX_NB_BITS_COMPACT : Encoder$1.MAX_NB_BITS)) {\n                    throw new IllegalArgumentException(StringUtils.format('Illegal value %s for layers', userSpecifiedLayers));\n                }\n                totalBitsInLayer = Encoder$1.totalBitsInLayer(layers, compact);\n                wordSize = Encoder$1.WORD_SIZE[layers];\n                let usableBitsInLayers = totalBitsInLayer - (totalBitsInLayer % wordSize);\n                stuffedBits = Encoder$1.stuffBits(bits, wordSize);\n                if (stuffedBits.getSize() + eccBits > usableBitsInLayers) {\n                    throw new IllegalArgumentException('Data to large for user specified layer');\n                }\n                if (compact && stuffedBits.getSize() > wordSize * 64) {\n                    // Compact format only allows 64 data words, though C4 can hold more words than that\n                    throw new IllegalArgumentException('Data to large for user specified layer');\n                }\n            }\n            else {\n                wordSize = 0;\n                stuffedBits = null;\n                // We look at the possible table sizes in the order Compact1, Compact2, Compact3,\n                // Compact4, Normal4,...  Normal(i) for i < 4 isn't typically used since Compact(i+1)\n                // is the same size, but has more data.\n                for (let i /*int*/ = 0;; i++) {\n                    if (i > Encoder$1.MAX_NB_BITS) {\n                        throw new IllegalArgumentException('Data too large for an Aztec code');\n                    }\n                    compact = i <= 3;\n                    layers = compact ? i + 1 : i;\n                    totalBitsInLayer = Encoder$1.totalBitsInLayer(layers, compact);\n                    if (totalSizeBits > totalBitsInLayer) {\n                        continue;\n                    }\n                    // [Re]stuff the bits if this is the first opportunity, or if the\n                    // wordSize has changed\n                    if (stuffedBits == null || wordSize !== Encoder$1.WORD_SIZE[layers]) {\n                        wordSize = Encoder$1.WORD_SIZE[layers];\n                        stuffedBits = Encoder$1.stuffBits(bits, wordSize);\n                    }\n                    let usableBitsInLayers = totalBitsInLayer - (totalBitsInLayer % wordSize);\n                    if (compact && stuffedBits.getSize() > wordSize * 64) {\n                        // Compact format only allows 64 data words, though C4 can hold more words than that\n                        continue;\n                    }\n                    if (stuffedBits.getSize() + eccBits <= usableBitsInLayers) {\n                        break;\n                    }\n                }\n            }\n            let messageBits = Encoder$1.generateCheckWords(stuffedBits, totalBitsInLayer, wordSize);\n            // generate mode message\n            let messageSizeInWords = stuffedBits.getSize() / wordSize;\n            let modeMessage = Encoder$1.generateModeMessage(compact, layers, messageSizeInWords);\n            // allocate symbol\n            let baseMatrixSize = (compact ? 11 : 14) + layers * 4; // not including alignment lines\n            let alignmentMap = new Int32Array(baseMatrixSize);\n            let matrixSize;\n            if (compact) {\n                // no alignment marks in compact mode, alignmentMap is a no-op\n                matrixSize = baseMatrixSize;\n                for (let i /*int*/ = 0; i < alignmentMap.length; i++) {\n                    alignmentMap[i] = i;\n                }\n            }\n            else {\n                matrixSize = baseMatrixSize + 1 + 2 * Integer.truncDivision((Integer.truncDivision(baseMatrixSize, 2) - 1), 15);\n                let origCenter = Integer.truncDivision(baseMatrixSize, 2);\n                let center = Integer.truncDivision(matrixSize, 2);\n                for (let i /*int*/ = 0; i < origCenter; i++) {\n                    let newOffset = i + Integer.truncDivision(i, 15);\n                    alignmentMap[origCenter - i - 1] = center - newOffset - 1;\n                    alignmentMap[origCenter + i] = center + newOffset + 1;\n                }\n            }\n            let matrix = new BitMatrix(matrixSize);\n            // draw data bits\n            for (let i /*int*/ = 0, rowOffset = 0; i < layers; i++) {\n                let rowSize = (layers - i) * 4 + (compact ? 9 : 12);\n                for (let j /*int*/ = 0; j < rowSize; j++) {\n                    let columnOffset = j * 2;\n                    for (let k /*int*/ = 0; k < 2; k++) {\n                        if (messageBits.get(rowOffset + columnOffset + k)) {\n                            matrix.set(alignmentMap[i * 2 + k], alignmentMap[i * 2 + j]);\n                        }\n                        if (messageBits.get(rowOffset + rowSize * 2 + columnOffset + k)) {\n                            matrix.set(alignmentMap[i * 2 + j], alignmentMap[baseMatrixSize - 1 - i * 2 - k]);\n                        }\n                        if (messageBits.get(rowOffset + rowSize * 4 + columnOffset + k)) {\n                            matrix.set(alignmentMap[baseMatrixSize - 1 - i * 2 - k], alignmentMap[baseMatrixSize - 1 - i * 2 - j]);\n                        }\n                        if (messageBits.get(rowOffset + rowSize * 6 + columnOffset + k)) {\n                            matrix.set(alignmentMap[baseMatrixSize - 1 - i * 2 - j], alignmentMap[i * 2 + k]);\n                        }\n                    }\n                }\n                rowOffset += rowSize * 8;\n            }\n            // draw mode message\n            Encoder$1.drawModeMessage(matrix, compact, matrixSize, modeMessage);\n            // draw alignment marks\n            if (compact) {\n                Encoder$1.drawBullsEye(matrix, Integer.truncDivision(matrixSize, 2), 5);\n            }\n            else {\n                Encoder$1.drawBullsEye(matrix, Integer.truncDivision(matrixSize, 2), 7);\n                for (let i /*int*/ = 0, j = 0; i < Integer.truncDivision(baseMatrixSize, 2) - 1; i += 15, j += 16) {\n                    for (let k /*int*/ = Integer.truncDivision(matrixSize, 2) & 1; k < matrixSize; k += 2) {\n                        matrix.set(Integer.truncDivision(matrixSize, 2) - j, k);\n                        matrix.set(Integer.truncDivision(matrixSize, 2) + j, k);\n                        matrix.set(k, Integer.truncDivision(matrixSize, 2) - j);\n                        matrix.set(k, Integer.truncDivision(matrixSize, 2) + j);\n                    }\n                }\n            }\n            let aztec = new AztecCode();\n            aztec.setCompact(compact);\n            aztec.setSize(matrixSize);\n            aztec.setLayers(layers);\n            aztec.setCodeWords(messageSizeInWords);\n            aztec.setMatrix(matrix);\n            return aztec;\n        }\n        static drawBullsEye(matrix, center, size) {\n            for (let i /*int*/ = 0; i < size; i += 2) {\n                for (let j /*int*/ = center - i; j <= center + i; j++) {\n                    matrix.set(j, center - i);\n                    matrix.set(j, center + i);\n                    matrix.set(center - i, j);\n                    matrix.set(center + i, j);\n                }\n            }\n            matrix.set(center - size, center - size);\n            matrix.set(center - size + 1, center - size);\n            matrix.set(center - size, center - size + 1);\n            matrix.set(center + size, center - size);\n            matrix.set(center + size, center - size + 1);\n            matrix.set(center + size, center + size - 1);\n        }\n        static generateModeMessage(compact, layers, messageSizeInWords) {\n            let modeMessage = new BitArray();\n            if (compact) {\n                modeMessage.appendBits(layers - 1, 2);\n                modeMessage.appendBits(messageSizeInWords - 1, 6);\n                modeMessage = Encoder$1.generateCheckWords(modeMessage, 28, 4);\n            }\n            else {\n                modeMessage.appendBits(layers - 1, 5);\n                modeMessage.appendBits(messageSizeInWords - 1, 11);\n                modeMessage = Encoder$1.generateCheckWords(modeMessage, 40, 4);\n            }\n            return modeMessage;\n        }\n        static drawModeMessage(matrix, compact, matrixSize, modeMessage) {\n            let center = Integer.truncDivision(matrixSize, 2);\n            if (compact) {\n                for (let i /*int*/ = 0; i < 7; i++) {\n                    let offset = center - 3 + i;\n                    if (modeMessage.get(i)) {\n                        matrix.set(offset, center - 5);\n                    }\n                    if (modeMessage.get(i + 7)) {\n                        matrix.set(center + 5, offset);\n                    }\n                    if (modeMessage.get(20 - i)) {\n                        matrix.set(offset, center + 5);\n                    }\n                    if (modeMessage.get(27 - i)) {\n                        matrix.set(center - 5, offset);\n                    }\n                }\n            }\n            else {\n                for (let i /*int*/ = 0; i < 10; i++) {\n                    let offset = center - 5 + i + Integer.truncDivision(i, 5);\n                    if (modeMessage.get(i)) {\n                        matrix.set(offset, center - 7);\n                    }\n                    if (modeMessage.get(i + 10)) {\n                        matrix.set(center + 7, offset);\n                    }\n                    if (modeMessage.get(29 - i)) {\n                        matrix.set(offset, center + 7);\n                    }\n                    if (modeMessage.get(39 - i)) {\n                        matrix.set(center - 7, offset);\n                    }\n                }\n            }\n        }\n        static generateCheckWords(bitArray, totalBits, wordSize) {\n            // bitArray is guaranteed to be a multiple of the wordSize, so no padding needed\n            let messageSizeInWords = bitArray.getSize() / wordSize;\n            let rs = new ReedSolomonEncoder(Encoder$1.getGF(wordSize));\n            let totalWords = Integer.truncDivision(totalBits, wordSize);\n            let messageWords = Encoder$1.bitsToWords(bitArray, wordSize, totalWords);\n            rs.encode(messageWords, totalWords - messageSizeInWords);\n            let startPad = totalBits % wordSize;\n            let messageBits = new BitArray();\n            messageBits.appendBits(0, startPad);\n            for (const messageWord /*: int*/ of Array.from(messageWords)) {\n                messageBits.appendBits(messageWord, wordSize);\n            }\n            return messageBits;\n        }\n        static bitsToWords(stuffedBits, wordSize, totalWords) {\n            let message = new Int32Array(totalWords);\n            let i;\n            let n;\n            for (i = 0, n = stuffedBits.getSize() / wordSize; i < n; i++) {\n                let value = 0;\n                for (let j /*int*/ = 0; j < wordSize; j++) {\n                    value |= stuffedBits.get(i * wordSize + j) ? (1 << wordSize - j - 1) : 0;\n                }\n                message[i] = value;\n            }\n            return message;\n        }\n        static getGF(wordSize) {\n            switch (wordSize) {\n                case 4:\n                    return GenericGF.AZTEC_PARAM;\n                case 6:\n                    return GenericGF.AZTEC_DATA_6;\n                case 8:\n                    return GenericGF.AZTEC_DATA_8;\n                case 10:\n                    return GenericGF.AZTEC_DATA_10;\n                case 12:\n                    return GenericGF.AZTEC_DATA_12;\n                default:\n                    throw new IllegalArgumentException('Unsupported word size ' + wordSize);\n            }\n        }\n        static stuffBits(bits, wordSize) {\n            let out = new BitArray();\n            let n = bits.getSize();\n            let mask = (1 << wordSize) - 2;\n            for (let i /*int*/ = 0; i < n; i += wordSize) {\n                let word = 0;\n                for (let j /*int*/ = 0; j < wordSize; j++) {\n                    if (i + j >= n || bits.get(i + j)) {\n                        word |= 1 << (wordSize - 1 - j);\n                    }\n                }\n                if ((word & mask) === mask) {\n                    out.appendBits(word & mask, wordSize);\n                    i--;\n                }\n                else if ((word & mask) === 0) {\n                    out.appendBits(word | 1, wordSize);\n                    i--;\n                }\n                else {\n                    out.appendBits(word, wordSize);\n                }\n            }\n            return out;\n        }\n        static totalBitsInLayer(layers, compact) {\n            return ((compact ? 88 : 112) + 16 * layers) * layers;\n        }\n    }\n    Encoder$1.DEFAULT_EC_PERCENT = 33; // default minimal percentage of error check words\n    Encoder$1.DEFAULT_AZTEC_LAYERS = 0;\n    Encoder$1.MAX_NB_BITS = 32;\n    Encoder$1.MAX_NB_BITS_COMPACT = 4;\n    Encoder$1.WORD_SIZE = Int32Array.from([\n        4, 6, 6, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,\n        12, 12, 12, 12, 12, 12, 12, 12, 12, 12\n    ]);\n\n    /*\n    * Copyright 2013 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /**\n     * Renders an Aztec code as a {@link BitMatrix}.\n     */\n    /*public final*/ class AztecWriter {\n        // @Override\n        encode(contents, format, width, height) {\n            return this.encodeWithHints(contents, format, width, height, null);\n        }\n        // @Override\n        encodeWithHints(contents, format, width, height, hints) {\n            let charset = StandardCharsets.ISO_8859_1;\n            let eccPercent = Encoder$1.DEFAULT_EC_PERCENT;\n            let layers = Encoder$1.DEFAULT_AZTEC_LAYERS;\n            if (hints != null) {\n                if (hints.has(EncodeHintType$1.CHARACTER_SET)) {\n                    charset = Charset.forName(hints.get(EncodeHintType$1.CHARACTER_SET).toString());\n                }\n                if (hints.has(EncodeHintType$1.ERROR_CORRECTION)) {\n                    eccPercent = Integer.parseInt(hints.get(EncodeHintType$1.ERROR_CORRECTION).toString());\n                }\n                if (hints.has(EncodeHintType$1.AZTEC_LAYERS)) {\n                    layers = Integer.parseInt(hints.get(EncodeHintType$1.AZTEC_LAYERS).toString());\n                }\n            }\n            return AztecWriter.encodeLayers(contents, format, width, height, charset, eccPercent, layers);\n        }\n        static encodeLayers(contents, format, width, height, charset, eccPercent, layers) {\n            if (format !== BarcodeFormat$1.AZTEC) {\n                throw new IllegalArgumentException('Can only encode AZTEC, but got ' + format);\n            }\n            let aztec = Encoder$1.encode(StringUtils.getBytes(contents, charset), eccPercent, layers);\n            return AztecWriter.renderResult(aztec, width, height);\n        }\n        static renderResult(code, width, height) {\n            let input = code.getMatrix();\n            if (input == null) {\n                throw new IllegalStateException();\n            }\n            let inputWidth = input.getWidth();\n            let inputHeight = input.getHeight();\n            let outputWidth = Math.max(width, inputWidth);\n            let outputHeight = Math.max(height, inputHeight);\n            let multiple = Math.min(outputWidth / inputWidth, outputHeight / inputHeight);\n            let leftPadding = (outputWidth - (inputWidth * multiple)) / 2;\n            let topPadding = (outputHeight - (inputHeight * multiple)) / 2;\n            let output = new BitMatrix(outputWidth, outputHeight);\n            for (let inputY /*int*/ = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {\n                // Write the contents of this row of the barcode\n                for (let inputX /*int*/ = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {\n                    if (input.get(inputX, inputY)) {\n                        output.setRegion(outputX, outputY, multiple, multiple);\n                    }\n                }\n            }\n            return output;\n        }\n    }\n\n    exports.AbstractExpandedDecoder = AbstractExpandedDecoder;\n    exports.ArgumentException = ArgumentException;\n    exports.ArithmeticException = ArithmeticException;\n    exports.AztecCode = AztecCode;\n    exports.AztecCodeReader = AztecReader;\n    exports.AztecCodeWriter = AztecWriter;\n    exports.AztecDecoder = Decoder;\n    exports.AztecDetector = Detector;\n    exports.AztecDetectorResult = AztecDetectorResult;\n    exports.AztecEncoder = Encoder$1;\n    exports.AztecHighLevelEncoder = HighLevelEncoder;\n    exports.AztecPoint = Point;\n    exports.BarcodeFormat = BarcodeFormat$1;\n    exports.Binarizer = Binarizer;\n    exports.BinaryBitmap = BinaryBitmap;\n    exports.BitArray = BitArray;\n    exports.BitMatrix = BitMatrix;\n    exports.BitSource = BitSource;\n    exports.BrowserAztecCodeReader = BrowserAztecCodeReader;\n    exports.BrowserBarcodeReader = BrowserBarcodeReader;\n    exports.BrowserCodeReader = BrowserCodeReader;\n    exports.BrowserDatamatrixCodeReader = BrowserDatamatrixCodeReader;\n    exports.BrowserMultiFormatReader = BrowserMultiFormatReader;\n    exports.BrowserPDF417Reader = BrowserPDF417Reader;\n    exports.BrowserQRCodeReader = BrowserQRCodeReader;\n    exports.BrowserQRCodeSvgWriter = BrowserQRCodeSvgWriter;\n    exports.CharacterSetECI = CharacterSetECI;\n    exports.ChecksumException = ChecksumException;\n    exports.Code128Reader = Code128Reader;\n    exports.Code39Reader = Code39Reader;\n    exports.DataMatrixDecodedBitStreamParser = DecodedBitStreamParser;\n    exports.DataMatrixReader = DataMatrixReader;\n    exports.DecodeHintType = DecodeHintType$1;\n    exports.DecoderResult = DecoderResult;\n    exports.DefaultGridSampler = DefaultGridSampler;\n    exports.DetectorResult = DetectorResult;\n    exports.EAN13Reader = EAN13Reader;\n    exports.EncodeHintType = EncodeHintType$1;\n    exports.Exception = Exception;\n    exports.FormatException = FormatException;\n    exports.GenericGF = GenericGF;\n    exports.GenericGFPoly = GenericGFPoly;\n    exports.GlobalHistogramBinarizer = GlobalHistogramBinarizer;\n    exports.GridSampler = GridSampler;\n    exports.GridSamplerInstance = GridSamplerInstance;\n    exports.HTMLCanvasElementLuminanceSource = HTMLCanvasElementLuminanceSource;\n    exports.HybridBinarizer = HybridBinarizer;\n    exports.ITFReader = ITFReader;\n    exports.IllegalArgumentException = IllegalArgumentException;\n    exports.IllegalStateException = IllegalStateException;\n    exports.InvertedLuminanceSource = InvertedLuminanceSource;\n    exports.LuminanceSource = LuminanceSource;\n    exports.MathUtils = MathUtils;\n    exports.MultiFormatOneDReader = MultiFormatOneDReader;\n    exports.MultiFormatReader = MultiFormatReader;\n    exports.MultiFormatWriter = MultiFormatWriter;\n    exports.NotFoundException = NotFoundException;\n    exports.OneDReader = OneDReader;\n    exports.PDF417DecodedBitStreamParser = DecodedBitStreamParser$2;\n    exports.PDF417DecoderErrorCorrection = ErrorCorrection;\n    exports.PDF417Reader = PDF417Reader;\n    exports.PDF417ResultMetadata = PDF417ResultMetadata;\n    exports.PerspectiveTransform = PerspectiveTransform;\n    exports.PlanarYUVLuminanceSource = PlanarYUVLuminanceSource;\n    exports.QRCodeByteMatrix = ByteMatrix;\n    exports.QRCodeDataMask = DataMask;\n    exports.QRCodeDecodedBitStreamParser = DecodedBitStreamParser$1;\n    exports.QRCodeDecoderErrorCorrectionLevel = ErrorCorrectionLevel;\n    exports.QRCodeDecoderFormatInformation = FormatInformation;\n    exports.QRCodeEncoder = Encoder;\n    exports.QRCodeEncoderQRCode = QRCode;\n    exports.QRCodeMaskUtil = MaskUtil;\n    exports.QRCodeMatrixUtil = MatrixUtil;\n    exports.QRCodeMode = Mode$1;\n    exports.QRCodeReader = QRCodeReader;\n    exports.QRCodeVersion = Version$1;\n    exports.QRCodeWriter = QRCodeWriter;\n    exports.RGBLuminanceSource = RGBLuminanceSource;\n    exports.RSS14Reader = RSS14Reader;\n    exports.RSSExpandedReader = RSSExpandedReader;\n    exports.ReaderException = ReaderException;\n    exports.ReedSolomonDecoder = ReedSolomonDecoder;\n    exports.ReedSolomonEncoder = ReedSolomonEncoder;\n    exports.ReedSolomonException = ReedSolomonException;\n    exports.Result = Result;\n    exports.ResultMetadataType = ResultMetadataType$1;\n    exports.ResultPoint = ResultPoint;\n    exports.StringUtils = StringUtils;\n    exports.UnsupportedOperationException = UnsupportedOperationException;\n    exports.VideoInputDevice = VideoInputDevice;\n    exports.WhiteRectangleDetector = WhiteRectangleDetector;\n    exports.WriterException = WriterException;\n    exports.ZXingArrays = Arrays;\n    exports.ZXingCharset = Charset;\n    exports.ZXingInteger = Integer;\n    exports.ZXingStandardCharsets = StandardCharsets;\n    exports.ZXingStringBuilder = StringBuilder;\n    exports.ZXingStringEncoding = StringEncoding;\n    exports.ZXingSystem = System;\n    exports.createAbstractExpandedDecoder = createDecoder;\n\n    Object.defineProperty(exports, '__esModule', { value: true });\n\n})));\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiODE3LmpzIiwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS90aGlyZF9wYXJ0eS96eGluZy1qcy51bWQuanM/ZjNhNiJdLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cykgOlxuICAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuICAgIChnbG9iYWwgPSB0eXBlb2YgZ2xvYmFsVGhpcyAhPT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWxUaGlzIDogZ2xvYmFsIHx8IHNlbGYsIGZhY3RvcnkoZ2xvYmFsLlpYaW5nID0ge30pKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxuICAgIGZ1bmN0aW9uIGlzTnVsbE9yVW5kZWZpbmVkKG9iaikge1xuICAgICAgICByZXR1cm4gb2JqID09PSBudWxsIHx8IG9iaiA9PT0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDggWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyogZ2xvYmFsIFJlZmxlY3QsIFByb21pc2UgKi9cblxuICAgIHZhciBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG5cbiAgICBmdW5jdGlvbiBfX2V4dGVuZHMoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZpeFByb3RvKHRhcmdldCwgcHJvdG90eXBlKSB7XG4gICAgICAgIHZhciBzZXRQcm90b3R5cGVPZiA9IE9iamVjdC5zZXRQcm90b3R5cGVPZjtcbiAgICAgICAgc2V0UHJvdG90eXBlT2YgPyBzZXRQcm90b3R5cGVPZih0YXJnZXQsIHByb3RvdHlwZSkgOiAodGFyZ2V0Ll9fcHJvdG9fXyA9IHByb3RvdHlwZSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZml4U3RhY2sodGFyZ2V0LCBmbikge1xuICAgICAgICBpZiAoZm4gPT09IHZvaWQgMCkge1xuICAgICAgICAgICAgZm4gPSB0YXJnZXQuY29uc3RydWN0b3I7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNhcHR1cmVTdGFja1RyYWNlID0gRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2U7XG4gICAgICAgIGNhcHR1cmVTdGFja1RyYWNlICYmIGNhcHR1cmVTdGFja1RyYWNlKHRhcmdldCwgZm4pO1xuICAgIH1cblxuICAgIHZhciBDdXN0b21FcnJvciA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgICAgIF9fZXh0ZW5kcyhDdXN0b21FcnJvciwgX3N1cGVyKTtcbiAgICAgICAgZnVuY3Rpb24gQ3VzdG9tRXJyb3IobWVzc2FnZSkge1xuICAgICAgICAgICAgdmFyIF9uZXdUYXJnZXQgPSB0aGlzLmNvbnN0cnVjdG9yO1xuICAgICAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgbWVzc2FnZSkgfHwgdGhpcztcbiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfdGhpcywgJ25hbWUnLCB7XG4gICAgICAgICAgICAgICAgdmFsdWU6IF9uZXdUYXJnZXQubmFtZSxcbiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBmaXhQcm90byhfdGhpcywgX25ld1RhcmdldC5wcm90b3R5cGUpO1xuICAgICAgICAgICAgZml4U3RhY2soX3RoaXMpO1xuICAgICAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICByZXR1cm4gQ3VzdG9tRXJyb3I7XG4gICAgfSkoRXJyb3IpO1xuXG4gICAgLyoqXG4gICAgICogQ3VzdG9tIEVycm9yIGNsYXNzIG9mIHR5cGUgRXhjZXB0aW9uLlxuICAgICAqL1xuICAgIGNsYXNzIEV4Y2VwdGlvbiBleHRlbmRzIEN1c3RvbUVycm9yIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEFsbG93cyBFeGNlcHRpb24gdG8gYmUgY29uc3RydWN0ZWQgZGlyZWN0bHlcbiAgICAgICAgICogd2l0aCBzb21lIG1lc3NhZ2UgYW5kIHByb3RvdHlwZSBkZWZpbml0aW9uLlxuICAgICAgICAgKi9cbiAgICAgICAgY29uc3RydWN0b3IobWVzc2FnZSA9IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgc3VwZXIobWVzc2FnZSk7XG4gICAgICAgICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgICAgICB9XG4gICAgICAgIGdldEtpbmQoKSB7XG4gICAgICAgICAgICBjb25zdCBleCA9IHRoaXMuY29uc3RydWN0b3I7XG4gICAgICAgICAgICByZXR1cm4gZXgua2luZDtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBJdCdzIHR5cGVkIGFzIHN0cmluZyBzbyBpdCBjYW4gYmUgZXh0ZW5kZWQgYW5kIG92ZXJyaWRlbi5cbiAgICAgKi9cbiAgICBFeGNlcHRpb24ua2luZCA9ICdFeGNlcHRpb24nO1xuXG4gICAgLyoqXG4gICAgICogQ3VzdG9tIEVycm9yIGNsYXNzIG9mIHR5cGUgRXhjZXB0aW9uLlxuICAgICAqL1xuICAgIGNsYXNzIEFyZ3VtZW50RXhjZXB0aW9uIGV4dGVuZHMgRXhjZXB0aW9uIHtcbiAgICB9XG4gICAgQXJndW1lbnRFeGNlcHRpb24ua2luZCA9ICdBcmd1bWVudEV4Y2VwdGlvbic7XG5cbiAgICAvKipcbiAgICAgKiBDdXN0b20gRXJyb3IgY2xhc3Mgb2YgdHlwZSBFeGNlcHRpb24uXG4gICAgICovXG4gICAgY2xhc3MgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uIGV4dGVuZHMgRXhjZXB0aW9uIHtcbiAgICB9XG4gICAgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uLmtpbmQgPSAnSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uJztcblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDkgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgY2xhc3MgQmluYXJ5Qml0bWFwIHtcbiAgICAgICAgY29uc3RydWN0b3IoYmluYXJpemVyKSB7XG4gICAgICAgICAgICB0aGlzLmJpbmFyaXplciA9IGJpbmFyaXplcjtcbiAgICAgICAgICAgIGlmIChiaW5hcml6ZXIgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdCaW5hcml6ZXIgbXVzdCBiZSBub24tbnVsbC4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBUaGUgd2lkdGggb2YgdGhlIGJpdG1hcC5cbiAgICAgICAgICovXG4gICAgICAgIGdldFdpZHRoKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmluYXJpemVyLmdldFdpZHRoKCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gVGhlIGhlaWdodCBvZiB0aGUgYml0bWFwLlxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0SGVpZ2h0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmluYXJpemVyLmdldEhlaWdodCgpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb252ZXJ0cyBvbmUgcm93IG9mIGx1bWluYW5jZSBkYXRhIHRvIDEgYml0IGRhdGEuIE1heSBhY3R1YWxseSBkbyB0aGUgY29udmVyc2lvbiwgb3IgcmV0dXJuXG4gICAgICAgICAqIGNhY2hlZCBkYXRhLiBDYWxsZXJzIHNob3VsZCBhc3N1bWUgdGhpcyBtZXRob2QgaXMgZXhwZW5zaXZlIGFuZCBjYWxsIGl0IGFzIHNlbGRvbSBhcyBwb3NzaWJsZS5cbiAgICAgICAgICogVGhpcyBtZXRob2QgaXMgaW50ZW5kZWQgZm9yIGRlY29kaW5nIDFEIGJhcmNvZGVzIGFuZCBtYXkgY2hvb3NlIHRvIGFwcGx5IHNoYXJwZW5pbmcuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB5IFRoZSByb3cgdG8gZmV0Y2gsIHdoaWNoIG11c3QgYmUgaW4gWzAsIGJpdG1hcCBoZWlnaHQpXG4gICAgICAgICAqIEBwYXJhbSByb3cgQW4gb3B0aW9uYWwgcHJlYWxsb2NhdGVkIGFycmF5LiBJZiBudWxsIG9yIHRvbyBzbWFsbCwgaXQgd2lsbCBiZSBpZ25vcmVkLlxuICAgICAgICAgKiAgICAgICAgICAgIElmIHVzZWQsIHRoZSBCaW5hcml6ZXIgd2lsbCBjYWxsIEJpdEFycmF5LmNsZWFyKCkuIEFsd2F5cyB1c2UgdGhlIHJldHVybmVkIG9iamVjdC5cbiAgICAgICAgICogQHJldHVybiBUaGUgYXJyYXkgb2YgYml0cyBmb3IgdGhpcyByb3cgKHRydWUgbWVhbnMgYmxhY2spLlxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIHJvdyBjYW4ndCBiZSBiaW5hcml6ZWRcbiAgICAgICAgICovXG4gICAgICAgIGdldEJsYWNrUm93KHkgLyppbnQqLywgcm93KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5iaW5hcml6ZXIuZ2V0QmxhY2tSb3coeSwgcm93KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ29udmVydHMgYSAyRCBhcnJheSBvZiBsdW1pbmFuY2UgZGF0YSB0byAxIGJpdC4gQXMgYWJvdmUsIGFzc3VtZSB0aGlzIG1ldGhvZCBpcyBleHBlbnNpdmVcbiAgICAgICAgICogYW5kIGRvIG5vdCBjYWxsIGl0IHJlcGVhdGVkbHkuIFRoaXMgbWV0aG9kIGlzIGludGVuZGVkIGZvciBkZWNvZGluZyAyRCBiYXJjb2RlcyBhbmQgbWF5IG9yXG4gICAgICAgICAqIG1heSBub3QgYXBwbHkgc2hhcnBlbmluZy4gVGhlcmVmb3JlLCBhIHJvdyBmcm9tIHRoaXMgbWF0cml4IG1heSBub3QgYmUgaWRlbnRpY2FsIHRvIG9uZVxuICAgICAgICAgKiBmZXRjaGVkIHVzaW5nIGdldEJsYWNrUm93KCksIHNvIGRvbid0IG1peCBhbmQgbWF0Y2ggYmV0d2VlbiB0aGVtLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIFRoZSAyRCBhcnJheSBvZiBiaXRzIGZvciB0aGUgaW1hZ2UgKHRydWUgbWVhbnMgYmxhY2spLlxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIGltYWdlIGNhbid0IGJlIGJpbmFyaXplZCB0byBtYWtlIGEgbWF0cml4XG4gICAgICAgICAqL1xuICAgICAgICBnZXRCbGFja01hdHJpeCgpIHtcbiAgICAgICAgICAgIC8vIFRoZSBtYXRyaXggaXMgY3JlYXRlZCBvbiBkZW1hbmQgdGhlIGZpcnN0IHRpbWUgaXQgaXMgcmVxdWVzdGVkLCB0aGVuIGNhY2hlZC4gVGhlcmUgYXJlIHR3b1xuICAgICAgICAgICAgLy8gcmVhc29ucyBmb3IgdGhpczpcbiAgICAgICAgICAgIC8vIDEuIFRoaXMgd29yayB3aWxsIG5ldmVyIGJlIGRvbmUgaWYgdGhlIGNhbGxlciBvbmx5IGluc3RhbGxzIDFEIFJlYWRlciBvYmplY3RzLCBvciBpZiBhXG4gICAgICAgICAgICAvLyAgICAxRCBSZWFkZXIgZmluZHMgYSBiYXJjb2RlIGJlZm9yZSB0aGUgMkQgUmVhZGVycyBydW4uXG4gICAgICAgICAgICAvLyAyLiBUaGlzIHdvcmsgd2lsbCBvbmx5IGJlIGRvbmUgb25jZSBldmVuIGlmIHRoZSBjYWxsZXIgaW5zdGFsbHMgbXVsdGlwbGUgMkQgUmVhZGVycy5cbiAgICAgICAgICAgIGlmICh0aGlzLm1hdHJpeCA9PT0gbnVsbCB8fCB0aGlzLm1hdHJpeCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tYXRyaXggPSB0aGlzLmJpbmFyaXplci5nZXRCbGFja01hdHJpeCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubWF0cml4O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhpcyBiaXRtYXAgY2FuIGJlIGNyb3BwZWQuXG4gICAgICAgICAqL1xuICAgICAgICBpc0Nyb3BTdXBwb3J0ZWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5iaW5hcml6ZXIuZ2V0THVtaW5hbmNlU291cmNlKCkuaXNDcm9wU3VwcG9ydGVkKCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldHVybnMgYSBuZXcgb2JqZWN0IHdpdGggY3JvcHBlZCBpbWFnZSBkYXRhLiBJbXBsZW1lbnRhdGlvbnMgbWF5IGtlZXAgYSByZWZlcmVuY2UgdG8gdGhlXG4gICAgICAgICAqIG9yaWdpbmFsIGRhdGEgcmF0aGVyIHRoYW4gYSBjb3B5LiBPbmx5IGNhbGxhYmxlIGlmIGlzQ3JvcFN1cHBvcnRlZCgpIGlzIHRydWUuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBsZWZ0IFRoZSBsZWZ0IGNvb3JkaW5hdGUsIHdoaWNoIG11c3QgYmUgaW4gWzAsZ2V0V2lkdGgoKSlcbiAgICAgICAgICogQHBhcmFtIHRvcCBUaGUgdG9wIGNvb3JkaW5hdGUsIHdoaWNoIG11c3QgYmUgaW4gWzAsZ2V0SGVpZ2h0KCkpXG4gICAgICAgICAqIEBwYXJhbSB3aWR0aCBUaGUgd2lkdGggb2YgdGhlIHJlY3RhbmdsZSB0byBjcm9wLlxuICAgICAgICAgKiBAcGFyYW0gaGVpZ2h0IFRoZSBoZWlnaHQgb2YgdGhlIHJlY3RhbmdsZSB0byBjcm9wLlxuICAgICAgICAgKiBAcmV0dXJuIEEgY3JvcHBlZCB2ZXJzaW9uIG9mIHRoaXMgb2JqZWN0LlxuICAgICAgICAgKi9cbiAgICAgICAgY3JvcChsZWZ0IC8qaW50Ki8sIHRvcCAvKmludCovLCB3aWR0aCAvKmludCovLCBoZWlnaHQgLyppbnQqLykge1xuICAgICAgICAgICAgY29uc3QgbmV3U291cmNlID0gdGhpcy5iaW5hcml6ZXIuZ2V0THVtaW5hbmNlU291cmNlKCkuY3JvcChsZWZ0LCB0b3AsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBCaW5hcnlCaXRtYXAodGhpcy5iaW5hcml6ZXIuY3JlYXRlQmluYXJpemVyKG5ld1NvdXJjZSkpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIFdoZXRoZXIgdGhpcyBiaXRtYXAgc3VwcG9ydHMgY291bnRlci1jbG9ja3dpc2Ugcm90YXRpb24uXG4gICAgICAgICAqL1xuICAgICAgICBpc1JvdGF0ZVN1cHBvcnRlZCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJpbmFyaXplci5nZXRMdW1pbmFuY2VTb3VyY2UoKS5pc1JvdGF0ZVN1cHBvcnRlZCgpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXR1cm5zIGEgbmV3IG9iamVjdCB3aXRoIHJvdGF0ZWQgaW1hZ2UgZGF0YSBieSA5MCBkZWdyZWVzIGNvdW50ZXJjbG9ja3dpc2UuXG4gICAgICAgICAqIE9ubHkgY2FsbGFibGUgaWYge0BsaW5rICNpc1JvdGF0ZVN1cHBvcnRlZCgpfSBpcyB0cnVlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIEEgcm90YXRlZCB2ZXJzaW9uIG9mIHRoaXMgb2JqZWN0LlxuICAgICAgICAgKi9cbiAgICAgICAgcm90YXRlQ291bnRlckNsb2Nrd2lzZSgpIHtcbiAgICAgICAgICAgIGNvbnN0IG5ld1NvdXJjZSA9IHRoaXMuYmluYXJpemVyLmdldEx1bWluYW5jZVNvdXJjZSgpLnJvdGF0ZUNvdW50ZXJDbG9ja3dpc2UoKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgQmluYXJ5Qml0bWFwKHRoaXMuYmluYXJpemVyLmNyZWF0ZUJpbmFyaXplcihuZXdTb3VyY2UpKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogUmV0dXJucyBhIG5ldyBvYmplY3Qgd2l0aCByb3RhdGVkIGltYWdlIGRhdGEgYnkgNDUgZGVncmVlcyBjb3VudGVyY2xvY2t3aXNlLlxuICAgICAgICAgKiBPbmx5IGNhbGxhYmxlIGlmIHtAbGluayAjaXNSb3RhdGVTdXBwb3J0ZWQoKX0gaXMgdHJ1ZS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiBBIHJvdGF0ZWQgdmVyc2lvbiBvZiB0aGlzIG9iamVjdC5cbiAgICAgICAgICovXG4gICAgICAgIHJvdGF0ZUNvdW50ZXJDbG9ja3dpc2U0NSgpIHtcbiAgICAgICAgICAgIGNvbnN0IG5ld1NvdXJjZSA9IHRoaXMuYmluYXJpemVyLmdldEx1bWluYW5jZVNvdXJjZSgpLnJvdGF0ZUNvdW50ZXJDbG9ja3dpc2U0NSgpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBCaW5hcnlCaXRtYXAodGhpcy5iaW5hcml6ZXIuY3JlYXRlQmluYXJpemVyKG5ld1NvdXJjZSkpO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldEJsYWNrTWF0cml4KCkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlIC8qOiBOb3RGb3VuZEV4Y2VwdGlvbiovKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3VzdG9tIEVycm9yIGNsYXNzIG9mIHR5cGUgRXhjZXB0aW9uLlxuICAgICAqL1xuICAgIGNsYXNzIENoZWNrc3VtRXhjZXB0aW9uIGV4dGVuZHMgRXhjZXB0aW9uIHtcbiAgICAgICAgc3RhdGljIGdldENoZWNrc3VtSW5zdGFuY2UoKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IENoZWNrc3VtRXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgQ2hlY2tzdW1FeGNlcHRpb24ua2luZCA9ICdDaGVja3N1bUV4Y2VwdGlvbic7XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA5IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIFRoaXMgY2xhc3MgaGllcmFyY2h5IHByb3ZpZGVzIGEgc2V0IG9mIG1ldGhvZHMgdG8gY29udmVydCBsdW1pbmFuY2UgZGF0YSB0byAxIGJpdCBkYXRhLlxuICAgICAqIEl0IGFsbG93cyB0aGUgYWxnb3JpdGhtIHRvIHZhcnkgcG9seW1vcnBoaWNhbGx5LCBmb3IgZXhhbXBsZSBhbGxvd2luZyBhIHZlcnkgZXhwZW5zaXZlXG4gICAgICogdGhyZXNob2xkaW5nIHRlY2huaXF1ZSBmb3Igc2VydmVycyBhbmQgYSBmYXN0IG9uZSBmb3IgbW9iaWxlLiBJdCBhbHNvIHBlcm1pdHMgdGhlIGltcGxlbWVudGF0aW9uXG4gICAgICogdG8gdmFyeSwgZS5nLiBhIEpOSSB2ZXJzaW9uIGZvciBBbmRyb2lkIGFuZCBhIEphdmEgZmFsbGJhY2sgdmVyc2lvbiBmb3Igb3RoZXIgcGxhdGZvcm1zLlxuICAgICAqXG4gICAgICogQGF1dGhvciBkc3dpdGtpbkBnb29nbGUuY29tIChEYW5pZWwgU3dpdGtpbilcbiAgICAgKi9cbiAgICBjbGFzcyBCaW5hcml6ZXIge1xuICAgICAgICBjb25zdHJ1Y3Rvcihzb3VyY2UpIHtcbiAgICAgICAgICAgIHRoaXMuc291cmNlID0gc291cmNlO1xuICAgICAgICB9XG4gICAgICAgIGdldEx1bWluYW5jZVNvdXJjZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNvdXJjZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRXaWR0aCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNvdXJjZS5nZXRXaWR0aCgpO1xuICAgICAgICB9XG4gICAgICAgIGdldEhlaWdodCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNvdXJjZS5nZXRIZWlnaHQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNsYXNzIFN5c3RlbSB7XG4gICAgICAgIC8vIHB1YmxpYyBzdGF0aWMgdm9pZCBhcnJheWNvcHkoT2JqZWN0IHNyYywgaW50IHNyY1BvcywgT2JqZWN0IGRlc3QsIGludCBkZXN0UG9zLCBpbnQgbGVuZ3RoKVxuICAgICAgICAvKipcbiAgICAgICAgICogTWFrZXMgYSBjb3B5IG9mIGEgYXJyYXkuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgYXJyYXljb3B5KHNyYywgc3JjUG9zLCBkZXN0LCBkZXN0UG9zLCBsZW5ndGgpIHtcbiAgICAgICAgICAgIC8vIFRPRE86IGJldHRlciB1c2Ugc3BsaXQgb3Igc2V0P1xuICAgICAgICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgICAgICAgICAgZGVzdFtkZXN0UG9zKytdID0gc3JjW3NyY1BvcysrXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogUmV0dXJucyB0aGUgY3VycmVudCB0aW1lIGluIG1pbGxpc2Vjb25kcy5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBjdXJyZW50VGltZU1pbGxpcygpIHtcbiAgICAgICAgICAgIHJldHVybiBEYXRlLm5vdygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3VzdG9tIEVycm9yIGNsYXNzIG9mIHR5cGUgRXhjZXB0aW9uLlxuICAgICAqL1xuICAgIGNsYXNzIEluZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb24gZXh0ZW5kcyBFeGNlcHRpb24ge1xuICAgIH1cbiAgICBJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uLmtpbmQgPSAnSW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbic7XG5cbiAgICAvKipcbiAgICAgKiBDdXN0b20gRXJyb3IgY2xhc3Mgb2YgdHlwZSBFeGNlcHRpb24uXG4gICAgICovXG4gICAgY2xhc3MgQXJyYXlJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uIGV4dGVuZHMgSW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbiB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGluZGV4ID0gdW5kZWZpbmVkLCBtZXNzYWdlID0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBzdXBlcihtZXNzYWdlKTtcbiAgICAgICAgICAgIHRoaXMuaW5kZXggPSBpbmRleDtcbiAgICAgICAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgQXJyYXlJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uLmtpbmQgPSAnQXJyYXlJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uJztcblxuICAgIGNsYXNzIEFycmF5cyB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBc3NpZ25zIHRoZSBzcGVjaWZpZWQgaW50IHZhbHVlIHRvIGVhY2ggZWxlbWVudCBvZiB0aGUgc3BlY2lmaWVkIGFycmF5XG4gICAgICAgICAqIG9mIGludHMuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBhIHRoZSBhcnJheSB0byBiZSBmaWxsZWRcbiAgICAgICAgICogQHBhcmFtIHZhbCB0aGUgdmFsdWUgdG8gYmUgc3RvcmVkIGluIGFsbCBlbGVtZW50cyBvZiB0aGUgYXJyYXlcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBmaWxsKGEsIHZhbCkge1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IGEubGVuZ3RoOyBpIDwgbGVuOyBpKyspXG4gICAgICAgICAgICAgICAgYVtpXSA9IHZhbDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQXNzaWducyB0aGUgc3BlY2lmaWVkIGludCB2YWx1ZSB0byBlYWNoIGVsZW1lbnQgb2YgdGhlIHNwZWNpZmllZFxuICAgICAgICAgKiByYW5nZSBvZiB0aGUgc3BlY2lmaWVkIGFycmF5IG9mIGludHMuICBUaGUgcmFuZ2UgdG8gYmUgZmlsbGVkXG4gICAgICAgICAqIGV4dGVuZHMgZnJvbSBpbmRleCB7QGNvZGUgZnJvbUluZGV4fSwgaW5jbHVzaXZlLCB0byBpbmRleFxuICAgICAgICAgKiB7QGNvZGUgdG9JbmRleH0sIGV4Y2x1c2l2ZS4gIChJZiB7QGNvZGUgZnJvbUluZGV4PT10b0luZGV4fSwgdGhlXG4gICAgICAgICAqIHJhbmdlIHRvIGJlIGZpbGxlZCBpcyBlbXB0eS4pXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBhIHRoZSBhcnJheSB0byBiZSBmaWxsZWRcbiAgICAgICAgICogQHBhcmFtIGZyb21JbmRleCB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IGVsZW1lbnQgKGluY2x1c2l2ZSkgdG8gYmVcbiAgICAgICAgICogICAgICAgIGZpbGxlZCB3aXRoIHRoZSBzcGVjaWZpZWQgdmFsdWVcbiAgICAgICAgICogQHBhcmFtIHRvSW5kZXggdGhlIGluZGV4IG9mIHRoZSBsYXN0IGVsZW1lbnQgKGV4Y2x1c2l2ZSkgdG8gYmVcbiAgICAgICAgICogICAgICAgIGZpbGxlZCB3aXRoIHRoZSBzcGVjaWZpZWQgdmFsdWVcbiAgICAgICAgICogQHBhcmFtIHZhbCB0aGUgdmFsdWUgdG8gYmUgc3RvcmVkIGluIGFsbCBlbGVtZW50cyBvZiB0aGUgYXJyYXlcbiAgICAgICAgICogQHRocm93cyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24gaWYge0Bjb2RlIGZyb21JbmRleCA+IHRvSW5kZXh9XG4gICAgICAgICAqIEB0aHJvd3MgQXJyYXlJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uIGlmIHtAY29kZSBmcm9tSW5kZXggPCAwfSBvclxuICAgICAgICAgKiAgICAgICAgIHtAY29kZSB0b0luZGV4ID4gYS5sZW5ndGh9XG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZmlsbFdpdGhpbihhLCBmcm9tSW5kZXgsIHRvSW5kZXgsIHZhbCkge1xuICAgICAgICAgICAgQXJyYXlzLnJhbmdlQ2hlY2soYS5sZW5ndGgsIGZyb21JbmRleCwgdG9JbmRleCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gZnJvbUluZGV4OyBpIDwgdG9JbmRleDsgaSsrKVxuICAgICAgICAgICAgICAgIGFbaV0gPSB2YWw7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENoZWNrcyB0aGF0IHtAY29kZSBmcm9tSW5kZXh9IGFuZCB7QGNvZGUgdG9JbmRleH0gYXJlIGluXG4gICAgICAgICAqIHRoZSByYW5nZSBhbmQgdGhyb3dzIGFuIGV4Y2VwdGlvbiBpZiB0aGV5IGFyZW4ndC5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyByYW5nZUNoZWNrKGFycmF5TGVuZ3RoLCBmcm9tSW5kZXgsIHRvSW5kZXgpIHtcbiAgICAgICAgICAgIGlmIChmcm9tSW5kZXggPiB0b0luZGV4KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignZnJvbUluZGV4KCcgKyBmcm9tSW5kZXggKyAnKSA+IHRvSW5kZXgoJyArIHRvSW5kZXggKyAnKScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZyb21JbmRleCA8IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQXJyYXlJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uKGZyb21JbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodG9JbmRleCA+IGFycmF5TGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEFycmF5SW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbih0b0luZGV4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgYXNMaXN0KC4uLmFyZ3MpIHtcbiAgICAgICAgICAgIHJldHVybiBhcmdzO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBjcmVhdGUocm93cywgY29scywgdmFsdWUpIHtcbiAgICAgICAgICAgIGxldCBhcnIgPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiByb3dzIH0pO1xuICAgICAgICAgICAgcmV0dXJuIGFyci5tYXAoeCA9PiBBcnJheS5mcm9tKHsgbGVuZ3RoOiBjb2xzIH0pLmZpbGwodmFsdWUpKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgY3JlYXRlSW50MzJBcnJheShyb3dzLCBjb2xzLCB2YWx1ZSkge1xuICAgICAgICAgICAgbGV0IGFyciA9IEFycmF5LmZyb20oeyBsZW5ndGg6IHJvd3MgfSk7XG4gICAgICAgICAgICByZXR1cm4gYXJyLm1hcCh4ID0+IEludDMyQXJyYXkuZnJvbSh7IGxlbmd0aDogY29scyB9KS5maWxsKHZhbHVlKSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGVxdWFscyhmaXJzdCwgc2Vjb25kKSB7XG4gICAgICAgICAgICBpZiAoIWZpcnN0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFzZWNvbmQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWZpcnN0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghc2Vjb25kLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmaXJzdC5sZW5ndGggIT09IHNlY29uZC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgbGVuZ3RoID0gZmlyc3QubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoZmlyc3RbaV0gIT09IHNlY29uZFtpXSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGhhc2hDb2RlKGEpIHtcbiAgICAgICAgICAgIGlmIChhID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gMTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBhKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gMzEgKiByZXN1bHQgKyBlbGVtZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZmlsbFVpbnQ4QXJyYXkoYSwgdmFsdWUpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpICE9PSBhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgYVtpXSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBjb3B5T2Yob3JpZ2luYWwsIG5ld0xlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsLnNsaWNlKDAsIG5ld0xlbmd0aCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGNvcHlPZlVpbnQ4QXJyYXkob3JpZ2luYWwsIG5ld0xlbmd0aCkge1xuICAgICAgICAgICAgaWYgKG9yaWdpbmFsLmxlbmd0aCA8PSBuZXdMZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdBcnJheSA9IG5ldyBVaW50OEFycmF5KG5ld0xlbmd0aCk7XG4gICAgICAgICAgICAgICAgbmV3QXJyYXkuc2V0KG9yaWdpbmFsKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3QXJyYXk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3JpZ2luYWwuc2xpY2UoMCwgbmV3TGVuZ3RoKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgY29weU9mUmFuZ2Uob3JpZ2luYWwsIGZyb20sIHRvKSB7XG4gICAgICAgICAgICBjb25zdCBuZXdMZW5ndGggPSB0byAtIGZyb207XG4gICAgICAgICAgICBjb25zdCBjb3B5ID0gbmV3IEludDMyQXJyYXkobmV3TGVuZ3RoKTtcbiAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkob3JpZ2luYWwsIGZyb20sIGNvcHksIDAsIG5ld0xlbmd0aCk7XG4gICAgICAgICAgICByZXR1cm4gY29weTtcbiAgICAgICAgfVxuICAgICAgICAvKlxuICAgICAgICAqIFJldHVybnMgdGhlIGluZGV4IG9mIG9mIHRoZSBlbGVtZW50IGluIGEgc29ydGVkIGFycmF5IG9yICgtbi0xKSB3aGVyZSBuIGlzIHRoZSBpbnNlcnRpb24gcG9pbnRcbiAgICAgICAgKiBmb3IgdGhlIG5ldyBlbGVtZW50LlxuICAgICAgICAqIFBhcmFtZXRlcnM6XG4gICAgICAgICogICAgIGFyIC0gQSBzb3J0ZWQgYXJyYXlcbiAgICAgICAgKiAgICAgZWwgLSBBbiBlbGVtZW50IHRvIHNlYXJjaCBmb3JcbiAgICAgICAgKiAgICAgY29tcGFyYXRvciAtIEEgY29tcGFyYXRvciBmdW5jdGlvbi4gVGhlIGZ1bmN0aW9uIHRha2VzIHR3byBhcmd1bWVudHM6IChhLCBiKSBhbmQgcmV0dXJuczpcbiAgICAgICAgKiAgICAgICAgYSBuZWdhdGl2ZSBudW1iZXIgIGlmIGEgaXMgbGVzcyB0aGFuIGI7XG4gICAgICAgICogICAgICAgIDAgaWYgYSBpcyBlcXVhbCB0byBiO1xuICAgICAgICAqICAgICAgICBhIHBvc2l0aXZlIG51bWJlciBvZiBhIGlzIGdyZWF0ZXIgdGhhbiBiLlxuICAgICAgICAqIFRoZSBhcnJheSBtYXkgY29udGFpbiBkdXBsaWNhdGUgZWxlbWVudHMuIElmIHRoZXJlIGFyZSBtb3JlIHRoYW4gb25lIGVxdWFsIGVsZW1lbnRzIGluIHRoZSBhcnJheSxcbiAgICAgICAgKiB0aGUgcmV0dXJuZWQgdmFsdWUgY2FuIGJlIHRoZSBpbmRleCBvZiBhbnkgb25lIG9mIHRoZSBlcXVhbCBlbGVtZW50cy5cbiAgICAgICAgKlxuICAgICAgICAqIGh0dHA6Ly9qc2ZpZGRsZS5uZXQvYXJ5emhvdi9wa2ZzdDU1MC9cbiAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGJpbmFyeVNlYXJjaChhciwgZWwsIGNvbXBhcmF0b3IpIHtcbiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IGNvbXBhcmF0b3IpIHtcbiAgICAgICAgICAgICAgICBjb21wYXJhdG9yID0gQXJyYXlzLm51bWJlckNvbXBhcmF0b3I7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgbSA9IDA7XG4gICAgICAgICAgICBsZXQgbiA9IGFyLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICB3aGlsZSAobSA8PSBuKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgayA9IChuICsgbSkgPj4gMTtcbiAgICAgICAgICAgICAgICBjb25zdCBjbXAgPSBjb21wYXJhdG9yKGVsLCBhcltrXSk7XG4gICAgICAgICAgICAgICAgaWYgKGNtcCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgbSA9IGsgKyAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChjbXAgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG4gPSBrIC0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAtbSAtIDE7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIG51bWJlckNvbXBhcmF0b3IoYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIGEgLSBiO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUG9ueWZpbGwgZm9yIEphdmEncyBJbnRlZ2VyIGNsYXNzLlxuICAgICAqL1xuICAgIGNsYXNzIEludGVnZXIge1xuICAgICAgICBzdGF0aWMgbnVtYmVyT2ZUcmFpbGluZ1plcm9zKGkpIHtcbiAgICAgICAgICAgIGxldCB5O1xuICAgICAgICAgICAgaWYgKGkgPT09IDApXG4gICAgICAgICAgICAgICAgcmV0dXJuIDMyO1xuICAgICAgICAgICAgbGV0IG4gPSAzMTtcbiAgICAgICAgICAgIHkgPSBpIDw8IDE2O1xuICAgICAgICAgICAgaWYgKHkgIT09IDApIHtcbiAgICAgICAgICAgICAgICBuIC09IDE2O1xuICAgICAgICAgICAgICAgIGkgPSB5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgeSA9IGkgPDwgODtcbiAgICAgICAgICAgIGlmICh5ICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgbiAtPSA4O1xuICAgICAgICAgICAgICAgIGkgPSB5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgeSA9IGkgPDwgNDtcbiAgICAgICAgICAgIGlmICh5ICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgbiAtPSA0O1xuICAgICAgICAgICAgICAgIGkgPSB5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgeSA9IGkgPDwgMjtcbiAgICAgICAgICAgIGlmICh5ICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgbiAtPSAyO1xuICAgICAgICAgICAgICAgIGkgPSB5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG4gLSAoKGkgPDwgMSkgPj4+IDMxKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgbnVtYmVyT2ZMZWFkaW5nWmVyb3MoaSkge1xuICAgICAgICAgICAgLy8gSEQsIEZpZ3VyZSA1LTZcbiAgICAgICAgICAgIGlmIChpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDMyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IG4gPSAxO1xuICAgICAgICAgICAgaWYgKGkgPj4+IDE2ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgbiArPSAxNjtcbiAgICAgICAgICAgICAgICBpIDw8PSAxNjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpID4+PiAyNCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIG4gKz0gODtcbiAgICAgICAgICAgICAgICBpIDw8PSA4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGkgPj4+IDI4ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgbiArPSA0O1xuICAgICAgICAgICAgICAgIGkgPDw9IDQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaSA+Pj4gMzAgPT09IDApIHtcbiAgICAgICAgICAgICAgICBuICs9IDI7XG4gICAgICAgICAgICAgICAgaSA8PD0gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG4gLT0gaSA+Pj4gMzE7XG4gICAgICAgICAgICByZXR1cm4gbjtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgdG9IZXhTdHJpbmcoaSkge1xuICAgICAgICAgICAgcmV0dXJuIGkudG9TdHJpbmcoMTYpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyB0b0JpbmFyeVN0cmluZyhpbnROdW1iZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBTdHJpbmcocGFyc2VJbnQoU3RyaW5nKGludE51bWJlciksIDIpKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBSZXR1cm5zIHRoZSBudW1iZXIgb2Ygb25lLWJpdHMgaW4gdGhlIHR3bydzIGNvbXBsZW1lbnQgYmluYXJ5IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBzcGVjaWZpZWQgaW50IHZhbHVlLiBUaGlzIGZ1bmN0aW9uIGlzIHNvbWV0aW1lcyByZWZlcnJlZCB0byBhcyB0aGUgcG9wdWxhdGlvbiBjb3VudC5cbiAgICAgICAgLy8gUmV0dXJuczpcbiAgICAgICAgLy8gdGhlIG51bWJlciBvZiBvbmUtYml0cyBpbiB0aGUgdHdvJ3MgY29tcGxlbWVudCBiaW5hcnkgcmVwcmVzZW50YXRpb24gb2YgdGhlIHNwZWNpZmllZCBpbnQgdmFsdWUuXG4gICAgICAgIHN0YXRpYyBiaXRDb3VudChpKSB7XG4gICAgICAgICAgICAvLyBIRCwgRmlndXJlIDUtMlxuICAgICAgICAgICAgaSA9IGkgLSAoKGkgPj4+IDEpICYgMHg1NTU1NTU1NSk7XG4gICAgICAgICAgICBpID0gKGkgJiAweDMzMzMzMzMzKSArICgoaSA+Pj4gMikgJiAweDMzMzMzMzMzKTtcbiAgICAgICAgICAgIGkgPSAoaSArIChpID4+PiA0KSkgJiAweDBmMGYwZjBmO1xuICAgICAgICAgICAgaSA9IGkgKyAoaSA+Pj4gOCk7XG4gICAgICAgICAgICBpID0gaSArIChpID4+PiAxNik7XG4gICAgICAgICAgICByZXR1cm4gaSAmIDB4M2Y7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHRydW5jRGl2aXNpb24oZGl2aWRlbmQsIGRpdmlzb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLnRydW5jKGRpdmlkZW5kIC8gZGl2aXNvcik7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnZlcnRzIEEgc3RyaW5nIHRvIGFuIGludGVnZXIuXG4gICAgICAgICAqIEBwYXJhbSBzIEEgc3RyaW5nIHRvIGNvbnZlcnQgaW50byBhIG51bWJlci5cbiAgICAgICAgICogQHBhcmFtIHJhZGl4IEEgdmFsdWUgYmV0d2VlbiAyIGFuZCAzNiB0aGF0IHNwZWNpZmllcyB0aGUgYmFzZSBvZiB0aGUgbnVtYmVyIGluIG51bVN0cmluZy4gSWYgdGhpcyBhcmd1bWVudCBpcyBub3Qgc3VwcGxpZWQsIHN0cmluZ3Mgd2l0aCBhIHByZWZpeCBvZiAnMHgnIGFyZSBjb25zaWRlcmVkIGhleGFkZWNpbWFsLiBBbGwgb3RoZXIgc3RyaW5ncyBhcmUgY29uc2lkZXJlZCBkZWNpbWFsLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIHBhcnNlSW50KG51bSwgcmFkaXggPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZUludChudW0sIHJhZGl4KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBJbnRlZ2VyLk1JTl9WQUxVRV8zMl9CSVRTID0gLTIxNDc0ODM2NDg7XG4gICAgSW50ZWdlci5NQVhfVkFMVUUgPSBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUjtcblxuICAgIC8qKlxuICAgICAqIDxwPkEgc2ltcGxlLCBmYXN0IGFycmF5IG9mIGJpdHMsIHJlcHJlc2VudGVkIGNvbXBhY3RseSBieSBhbiBhcnJheSBvZiBpbnRzIGludGVybmFsbHkuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBCaXRBcnJheSAvKmltcGxlbWVudHMgQ2xvbmVhYmxlKi8ge1xuICAgICAgICAvLyBGb3IgdGVzdGluZyBvbmx5XG4gICAgICAgIGNvbnN0cnVjdG9yKHNpemUgLyppbnQqLywgYml0cykge1xuICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCA9PT0gc2l6ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2l6ZSA9IDA7XG4gICAgICAgICAgICAgICAgdGhpcy5iaXRzID0gbmV3IEludDMyQXJyYXkoMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNpemUgPSBzaXplO1xuICAgICAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IGJpdHMgfHwgbnVsbCA9PT0gYml0cykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmJpdHMgPSBCaXRBcnJheS5tYWtlQXJyYXkoc2l6ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmJpdHMgPSBiaXRzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBnZXRTaXplKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2l6ZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRTaXplSW5CeXRlcygpIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKCh0aGlzLnNpemUgKyA3KSAvIDgpO1xuICAgICAgICB9XG4gICAgICAgIGVuc3VyZUNhcGFjaXR5KHNpemUgLyppbnQqLykge1xuICAgICAgICAgICAgaWYgKHNpemUgPiB0aGlzLmJpdHMubGVuZ3RoICogMzIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdCaXRzID0gQml0QXJyYXkubWFrZUFycmF5KHNpemUpO1xuICAgICAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkodGhpcy5iaXRzLCAwLCBuZXdCaXRzLCAwLCB0aGlzLmJpdHMubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICB0aGlzLmJpdHMgPSBuZXdCaXRzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gaSBiaXQgdG8gZ2V0XG4gICAgICAgICAqIEByZXR1cm4gdHJ1ZSBpZmYgYml0IGkgaXMgc2V0XG4gICAgICAgICAqL1xuICAgICAgICBnZXQoaSAvKmludCovKSB7XG4gICAgICAgICAgICByZXR1cm4gKHRoaXMuYml0c1tNYXRoLmZsb29yKGkgLyAzMildICYgKDEgPDwgKGkgJiAweDFGKSkpICE9PSAwO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZXRzIGJpdCBpLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gaSBiaXQgdG8gc2V0XG4gICAgICAgICAqL1xuICAgICAgICBzZXQoaSAvKmludCovKSB7XG4gICAgICAgICAgICB0aGlzLmJpdHNbTWF0aC5mbG9vcihpIC8gMzIpXSB8PSAxIDw8IChpICYgMHgxRik7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEZsaXBzIGJpdCBpLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gaSBiaXQgdG8gc2V0XG4gICAgICAgICAqL1xuICAgICAgICBmbGlwKGkgLyppbnQqLykge1xuICAgICAgICAgICAgdGhpcy5iaXRzW01hdGguZmxvb3IoaSAvIDMyKV0gXj0gMSA8PCAoaSAmIDB4MUYpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gZnJvbSBmaXJzdCBiaXQgdG8gY2hlY2tcbiAgICAgICAgICogQHJldHVybiBpbmRleCBvZiBmaXJzdCBiaXQgdGhhdCBpcyBzZXQsIHN0YXJ0aW5nIGZyb20gdGhlIGdpdmVuIGluZGV4LCBvciBzaXplIGlmIG5vbmUgYXJlIHNldFxuICAgICAgICAgKiAgYXQgb3IgYmV5b25kIHRoaXMgZ2l2ZW4gaW5kZXhcbiAgICAgICAgICogQHNlZSAjZ2V0TmV4dFVuc2V0KGludClcbiAgICAgICAgICovXG4gICAgICAgIGdldE5leHRTZXQoZnJvbSAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBzaXplID0gdGhpcy5zaXplO1xuICAgICAgICAgICAgaWYgKGZyb20gPj0gc2l6ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzaXplO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYml0cyA9IHRoaXMuYml0cztcbiAgICAgICAgICAgIGxldCBiaXRzT2Zmc2V0ID0gTWF0aC5mbG9vcihmcm9tIC8gMzIpO1xuICAgICAgICAgICAgbGV0IGN1cnJlbnRCaXRzID0gYml0c1tiaXRzT2Zmc2V0XTtcbiAgICAgICAgICAgIC8vIG1hc2sgb2ZmIGxlc3NlciBiaXRzIGZpcnN0XG4gICAgICAgICAgICBjdXJyZW50Qml0cyAmPSB+KCgxIDw8IChmcm9tICYgMHgxRikpIC0gMSk7XG4gICAgICAgICAgICBjb25zdCBsZW5ndGggPSBiaXRzLmxlbmd0aDtcbiAgICAgICAgICAgIHdoaWxlIChjdXJyZW50Qml0cyA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGlmICgrK2JpdHNPZmZzZXQgPT09IGxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2l6ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY3VycmVudEJpdHMgPSBiaXRzW2JpdHNPZmZzZXRdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gKGJpdHNPZmZzZXQgKiAzMikgKyBJbnRlZ2VyLm51bWJlck9mVHJhaWxpbmdaZXJvcyhjdXJyZW50Qml0cyk7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0ID4gc2l6ZSA/IHNpemUgOiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBmcm9tIGluZGV4IHRvIHN0YXJ0IGxvb2tpbmcgZm9yIHVuc2V0IGJpdFxuICAgICAgICAgKiBAcmV0dXJuIGluZGV4IG9mIG5leHQgdW5zZXQgYml0LCBvciB7QGNvZGUgc2l6ZX0gaWYgbm9uZSBhcmUgdW5zZXQgdW50aWwgdGhlIGVuZFxuICAgICAgICAgKiBAc2VlICNnZXROZXh0U2V0KGludClcbiAgICAgICAgICovXG4gICAgICAgIGdldE5leHRVbnNldChmcm9tIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IHNpemUgPSB0aGlzLnNpemU7XG4gICAgICAgICAgICBpZiAoZnJvbSA+PSBzaXplKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNpemU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBiaXRzID0gdGhpcy5iaXRzO1xuICAgICAgICAgICAgbGV0IGJpdHNPZmZzZXQgPSBNYXRoLmZsb29yKGZyb20gLyAzMik7XG4gICAgICAgICAgICBsZXQgY3VycmVudEJpdHMgPSB+Yml0c1tiaXRzT2Zmc2V0XTtcbiAgICAgICAgICAgIC8vIG1hc2sgb2ZmIGxlc3NlciBiaXRzIGZpcnN0XG4gICAgICAgICAgICBjdXJyZW50Qml0cyAmPSB+KCgxIDw8IChmcm9tICYgMHgxRikpIC0gMSk7XG4gICAgICAgICAgICBjb25zdCBsZW5ndGggPSBiaXRzLmxlbmd0aDtcbiAgICAgICAgICAgIHdoaWxlIChjdXJyZW50Qml0cyA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGlmICgrK2JpdHNPZmZzZXQgPT09IGxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2l6ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY3VycmVudEJpdHMgPSB+Yml0c1tiaXRzT2Zmc2V0XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IChiaXRzT2Zmc2V0ICogMzIpICsgSW50ZWdlci5udW1iZXJPZlRyYWlsaW5nWmVyb3MoY3VycmVudEJpdHMpO1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCA+IHNpemUgPyBzaXplIDogcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZXRzIGEgYmxvY2sgb2YgMzIgYml0cywgc3RhcnRpbmcgYXQgYml0IGkuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBpIGZpcnN0IGJpdCB0byBzZXRcbiAgICAgICAgICogQHBhcmFtIG5ld0JpdHMgdGhlIG5ldyB2YWx1ZSBvZiB0aGUgbmV4dCAzMiBiaXRzLiBOb3RlIGFnYWluIHRoYXQgdGhlIGxlYXN0LXNpZ25pZmljYW50IGJpdFxuICAgICAgICAgKiBjb3JyZXNwb25kcyB0byBiaXQgaSwgdGhlIG5leHQtbGVhc3Qtc2lnbmlmaWNhbnQgdG8gaSsxLCBhbmQgc28gb24uXG4gICAgICAgICAqL1xuICAgICAgICBzZXRCdWxrKGkgLyppbnQqLywgbmV3Qml0cyAvKmludCovKSB7XG4gICAgICAgICAgICB0aGlzLmJpdHNbTWF0aC5mbG9vcihpIC8gMzIpXSA9IG5ld0JpdHM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNldHMgYSByYW5nZSBvZiBiaXRzLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gc3RhcnQgc3RhcnQgb2YgcmFuZ2UsIGluY2x1c2l2ZS5cbiAgICAgICAgICogQHBhcmFtIGVuZCBlbmQgb2YgcmFuZ2UsIGV4Y2x1c2l2ZVxuICAgICAgICAgKi9cbiAgICAgICAgc2V0UmFuZ2Uoc3RhcnQgLyppbnQqLywgZW5kIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGlmIChlbmQgPCBzdGFydCB8fCBzdGFydCA8IDAgfHwgZW5kID4gdGhpcy5zaXplKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGVuZCA9PT0gc3RhcnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbmQtLTsgLy8gd2lsbCBiZSBlYXNpZXIgdG8gdHJlYXQgdGhpcyBhcyB0aGUgbGFzdCBhY3R1YWxseSBzZXQgYml0IC0tIGluY2x1c2l2ZVxuICAgICAgICAgICAgY29uc3QgZmlyc3RJbnQgPSBNYXRoLmZsb29yKHN0YXJ0IC8gMzIpO1xuICAgICAgICAgICAgY29uc3QgbGFzdEludCA9IE1hdGguZmxvb3IoZW5kIC8gMzIpO1xuICAgICAgICAgICAgY29uc3QgYml0cyA9IHRoaXMuYml0cztcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBmaXJzdEludDsgaSA8PSBsYXN0SW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmaXJzdEJpdCA9IGkgPiBmaXJzdEludCA/IDAgOiBzdGFydCAmIDB4MUY7XG4gICAgICAgICAgICAgICAgY29uc3QgbGFzdEJpdCA9IGkgPCBsYXN0SW50ID8gMzEgOiBlbmQgJiAweDFGO1xuICAgICAgICAgICAgICAgIC8vIE9uZXMgZnJvbSBmaXJzdEJpdCB0byBsYXN0Qml0LCBpbmNsdXNpdmVcbiAgICAgICAgICAgICAgICBjb25zdCBtYXNrID0gKDIgPDwgbGFzdEJpdCkgLSAoMSA8PCBmaXJzdEJpdCk7XG4gICAgICAgICAgICAgICAgYml0c1tpXSB8PSBtYXNrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDbGVhcnMgYWxsIGJpdHMgKHNldHMgdG8gZmFsc2UpLlxuICAgICAgICAgKi9cbiAgICAgICAgY2xlYXIoKSB7XG4gICAgICAgICAgICBjb25zdCBtYXggPSB0aGlzLmJpdHMubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3QgYml0cyA9IHRoaXMuYml0cztcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbWF4OyBpKyspIHtcbiAgICAgICAgICAgICAgICBiaXRzW2ldID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRWZmaWNpZW50IG1ldGhvZCB0byBjaGVjayBpZiBhIHJhbmdlIG9mIGJpdHMgaXMgc2V0LCBvciBub3Qgc2V0LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gc3RhcnQgc3RhcnQgb2YgcmFuZ2UsIGluY2x1c2l2ZS5cbiAgICAgICAgICogQHBhcmFtIGVuZCBlbmQgb2YgcmFuZ2UsIGV4Y2x1c2l2ZVxuICAgICAgICAgKiBAcGFyYW0gdmFsdWUgaWYgdHJ1ZSwgY2hlY2tzIHRoYXQgYml0cyBpbiByYW5nZSBhcmUgc2V0LCBvdGhlcndpc2UgY2hlY2tzIHRoYXQgdGhleSBhcmUgbm90IHNldFxuICAgICAgICAgKiBcbiAgICAgICAgICogQHJldHVybiB0cnVlIGlmZiBhbGwgYml0cyBhcmUgc2V0IG9yIG5vdCBzZXQgaW4gcmFuZ2UsIGFjY29yZGluZyB0byB2YWx1ZSBhcmd1bWVudFxuICAgICAgICAgKiBAdGhyb3dzIElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbiBpZiBlbmQgaXMgbGVzcyB0aGFuIHN0YXJ0IG9yIHRoZSByYW5nZSBpcyBub3QgY29udGFpbmVkIGluIHRoZSBhcnJheVxuICAgICAgICAgKi9cbiAgICAgICAgaXNSYW5nZShzdGFydCAvKmludCovLCBlbmQgLyppbnQqLywgdmFsdWUpIHtcbiAgICAgICAgICAgIGlmIChlbmQgPCBzdGFydCB8fCBzdGFydCA8IDAgfHwgZW5kID4gdGhpcy5zaXplKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGVuZCA9PT0gc3RhcnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsgLy8gZW1wdHkgcmFuZ2UgbWF0Y2hlc1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZW5kLS07IC8vIHdpbGwgYmUgZWFzaWVyIHRvIHRyZWF0IHRoaXMgYXMgdGhlIGxhc3QgYWN0dWFsbHkgc2V0IGJpdCAtLSBpbmNsdXNpdmVcbiAgICAgICAgICAgIGNvbnN0IGZpcnN0SW50ID0gTWF0aC5mbG9vcihzdGFydCAvIDMyKTtcbiAgICAgICAgICAgIGNvbnN0IGxhc3RJbnQgPSBNYXRoLmZsb29yKGVuZCAvIDMyKTtcbiAgICAgICAgICAgIGNvbnN0IGJpdHMgPSB0aGlzLmJpdHM7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gZmlyc3RJbnQ7IGkgPD0gbGFzdEludDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZmlyc3RCaXQgPSBpID4gZmlyc3RJbnQgPyAwIDogc3RhcnQgJiAweDFGO1xuICAgICAgICAgICAgICAgIGNvbnN0IGxhc3RCaXQgPSBpIDwgbGFzdEludCA/IDMxIDogZW5kICYgMHgxRjtcbiAgICAgICAgICAgICAgICAvLyBPbmVzIGZyb20gZmlyc3RCaXQgdG8gbGFzdEJpdCwgaW5jbHVzaXZlXG4gICAgICAgICAgICAgICAgY29uc3QgbWFzayA9ICgyIDw8IGxhc3RCaXQpIC0gKDEgPDwgZmlyc3RCaXQpICYgMHhGRkZGRkZGRjtcbiAgICAgICAgICAgICAgICAvLyBUWVBFU0NSSVBUUE9SVDogJiAweEZGRkZGRkZGIGFkZGVkIHRvIGRpc2NhcmQgYW55dGhpbmcgYWZ0ZXIgMzIgYml0cywgYXMgRVMgaGFzIDUzIGJpdHNcbiAgICAgICAgICAgICAgICAvLyBSZXR1cm4gZmFsc2UgaWYgd2UncmUgbG9va2luZyBmb3IgMXMgYW5kIHRoZSBtYXNrZWQgYml0c1tpXSBpc24ndCBhbGwgMXMgKGlzOiB0aGF0LFxuICAgICAgICAgICAgICAgIC8vIGVxdWFscyB0aGUgbWFzaywgb3Igd2UncmUgbG9va2luZyBmb3IgMHMgYW5kIHRoZSBtYXNrZWQgcG9ydGlvbiBpcyBub3QgYWxsIDBzXG4gICAgICAgICAgICAgICAgaWYgKChiaXRzW2ldICYgbWFzaykgIT09ICh2YWx1ZSA/IG1hc2sgOiAwKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgYXBwZW5kQml0KGJpdCkge1xuICAgICAgICAgICAgdGhpcy5lbnN1cmVDYXBhY2l0eSh0aGlzLnNpemUgKyAxKTtcbiAgICAgICAgICAgIGlmIChiaXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmJpdHNbTWF0aC5mbG9vcih0aGlzLnNpemUgLyAzMildIHw9IDEgPDwgKHRoaXMuc2l6ZSAmIDB4MUYpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zaXplKys7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEFwcGVuZHMgdGhlIGxlYXN0LXNpZ25pZmljYW50IGJpdHMsIGZyb20gdmFsdWUsIGluIG9yZGVyIGZyb20gbW9zdC1zaWduaWZpY2FudCB0b1xuICAgICAgICAgKiBsZWFzdC1zaWduaWZpY2FudC4gRm9yIGV4YW1wbGUsIGFwcGVuZGluZyA2IGJpdHMgZnJvbSAweDAwMDAwMUUgd2lsbCBhcHBlbmQgdGhlIGJpdHNcbiAgICAgICAgICogMCwgMSwgMSwgMSwgMSwgMCBpbiB0aGF0IG9yZGVyLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gdmFsdWUge0Bjb2RlIGludH0gY29udGFpbmluZyBiaXRzIHRvIGFwcGVuZFxuICAgICAgICAgKiBAcGFyYW0gbnVtQml0cyBiaXRzIGZyb20gdmFsdWUgdG8gYXBwZW5kXG4gICAgICAgICAqL1xuICAgICAgICBhcHBlbmRCaXRzKHZhbHVlIC8qaW50Ki8sIG51bUJpdHMgLyppbnQqLykge1xuICAgICAgICAgICAgaWYgKG51bUJpdHMgPCAwIHx8IG51bUJpdHMgPiAzMikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ051bSBiaXRzIG11c3QgYmUgYmV0d2VlbiAwIGFuZCAzMicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5lbnN1cmVDYXBhY2l0eSh0aGlzLnNpemUgKyBudW1CaXRzKTtcbiAgICAgICAgICAgIC8vIGNvbnN0IGFwcGVuZEJpdCA9IHRoaXMuYXBwZW5kQml0O1xuICAgICAgICAgICAgZm9yIChsZXQgbnVtQml0c0xlZnQgPSBudW1CaXRzOyBudW1CaXRzTGVmdCA+IDA7IG51bUJpdHNMZWZ0LS0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFwcGVuZEJpdCgoKHZhbHVlID4+IChudW1CaXRzTGVmdCAtIDEpKSAmIDB4MDEpID09PSAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBhcHBlbmRCaXRBcnJheShvdGhlcikge1xuICAgICAgICAgICAgY29uc3Qgb3RoZXJTaXplID0gb3RoZXIuc2l6ZTtcbiAgICAgICAgICAgIHRoaXMuZW5zdXJlQ2FwYWNpdHkodGhpcy5zaXplICsgb3RoZXJTaXplKTtcbiAgICAgICAgICAgIC8vIGNvbnN0IGFwcGVuZEJpdCA9IHRoaXMuYXBwZW5kQml0O1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvdGhlclNpemU7IGkrKykge1xuICAgICAgICAgICAgICAgIHRoaXMuYXBwZW5kQml0KG90aGVyLmdldChpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgeG9yKG90aGVyKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zaXplICE9PSBvdGhlci5zaXplKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignU2l6ZXMgZG9uXFwndCBtYXRjaCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYml0cyA9IHRoaXMuYml0cztcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBsZW5ndGggPSBiaXRzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlIGxhc3QgaW50IGNvdWxkIGJlIGluY29tcGxldGUgKGkuZS4gbm90IGhhdmUgMzIgYml0cyBpblxuICAgICAgICAgICAgICAgIC8vIGl0KSBidXQgdGhlcmUgaXMgbm8gcHJvYmxlbSBzaW5jZSAwIFhPUiAwID09IDAuXG4gICAgICAgICAgICAgICAgYml0c1tpXSBePSBvdGhlci5iaXRzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gYml0T2Zmc2V0IGZpcnN0IGJpdCB0byBzdGFydCB3cml0aW5nXG4gICAgICAgICAqIEBwYXJhbSBhcnJheSBhcnJheSB0byB3cml0ZSBpbnRvLiBCeXRlcyBhcmUgd3JpdHRlbiBtb3N0LXNpZ25pZmljYW50IGJ5dGUgZmlyc3QuIFRoaXMgaXMgdGhlIG9wcG9zaXRlXG4gICAgICAgICAqICBvZiB0aGUgaW50ZXJuYWwgcmVwcmVzZW50YXRpb24sIHdoaWNoIGlzIGV4cG9zZWQgYnkge0BsaW5rICNnZXRCaXRBcnJheSgpfVxuICAgICAgICAgKiBAcGFyYW0gb2Zmc2V0IHBvc2l0aW9uIGluIGFycmF5IHRvIHN0YXJ0IHdyaXRpbmdcbiAgICAgICAgICogQHBhcmFtIG51bUJ5dGVzIGhvdyBtYW55IGJ5dGVzIHRvIHdyaXRlXG4gICAgICAgICAqL1xuICAgICAgICB0b0J5dGVzKGJpdE9mZnNldCAvKmludCovLCBhcnJheSwgb2Zmc2V0IC8qaW50Ki8sIG51bUJ5dGVzIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtQnl0ZXM7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCB0aGVCeXRlID0gMDtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IDg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5nZXQoYml0T2Zmc2V0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhlQnl0ZSB8PSAxIDw8ICg3IC0gaik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYml0T2Zmc2V0Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGFycmF5W29mZnNldCArIGldID0gLyooYnl0ZSkqLyB0aGVCeXRlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHVuZGVybHlpbmcgYXJyYXkgb2YgaW50cy4gVGhlIGZpcnN0IGVsZW1lbnQgaG9sZHMgdGhlIGZpcnN0IDMyIGJpdHMsIGFuZCB0aGUgbGVhc3RcbiAgICAgICAgICogICAgICAgICBzaWduaWZpY2FudCBiaXQgaXMgYml0IDAuXG4gICAgICAgICAqL1xuICAgICAgICBnZXRCaXRBcnJheSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJpdHM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldmVyc2VzIGFsbCBiaXRzIGluIHRoZSBhcnJheS5cbiAgICAgICAgICovXG4gICAgICAgIHJldmVyc2UoKSB7XG4gICAgICAgICAgICBjb25zdCBuZXdCaXRzID0gbmV3IEludDMyQXJyYXkodGhpcy5iaXRzLmxlbmd0aCk7XG4gICAgICAgICAgICAvLyByZXZlcnNlIGFsbCBpbnQncyBmaXJzdFxuICAgICAgICAgICAgY29uc3QgbGVuID0gTWF0aC5mbG9vcigodGhpcy5zaXplIC0gMSkgLyAzMik7XG4gICAgICAgICAgICBjb25zdCBvbGRCaXRzTGVuID0gbGVuICsgMTtcbiAgICAgICAgICAgIGNvbnN0IGJpdHMgPSB0aGlzLmJpdHM7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9sZEJpdHNMZW47IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCB4ID0gYml0c1tpXTtcbiAgICAgICAgICAgICAgICB4ID0gKCh4ID4+IDEpICYgMHg1NTU1NTU1NSkgfCAoKHggJiAweDU1NTU1NTU1KSA8PCAxKTtcbiAgICAgICAgICAgICAgICB4ID0gKCh4ID4+IDIpICYgMHgzMzMzMzMzMykgfCAoKHggJiAweDMzMzMzMzMzKSA8PCAyKTtcbiAgICAgICAgICAgICAgICB4ID0gKCh4ID4+IDQpICYgMHgwZjBmMGYwZikgfCAoKHggJiAweDBmMGYwZjBmKSA8PCA0KTtcbiAgICAgICAgICAgICAgICB4ID0gKCh4ID4+IDgpICYgMHgwMGZmMDBmZikgfCAoKHggJiAweDAwZmYwMGZmKSA8PCA4KTtcbiAgICAgICAgICAgICAgICB4ID0gKCh4ID4+IDE2KSAmIDB4MDAwMGZmZmYpIHwgKCh4ICYgMHgwMDAwZmZmZikgPDwgMTYpO1xuICAgICAgICAgICAgICAgIG5ld0JpdHNbbGVuIC0gaV0gPSAvKihpbnQpKi8geDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIG5vdyBjb3JyZWN0IHRoZSBpbnQncyBpZiB0aGUgYml0IHNpemUgaXNuJ3QgYSBtdWx0aXBsZSBvZiAzMlxuICAgICAgICAgICAgaWYgKHRoaXMuc2l6ZSAhPT0gb2xkQml0c0xlbiAqIDMyKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbGVmdE9mZnNldCA9IG9sZEJpdHNMZW4gKiAzMiAtIHRoaXMuc2l6ZTtcbiAgICAgICAgICAgICAgICBsZXQgY3VycmVudEludCA9IG5ld0JpdHNbMF0gPj4+IGxlZnRPZmZzZXQ7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBvbGRCaXRzTGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV4dEludCA9IG5ld0JpdHNbaV07XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbnQgfD0gbmV4dEludCA8PCAoMzIgLSBsZWZ0T2Zmc2V0KTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Qml0c1tpIC0gMV0gPSBjdXJyZW50SW50O1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SW50ID0gbmV4dEludCA+Pj4gbGVmdE9mZnNldDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbmV3Qml0c1tvbGRCaXRzTGVuIC0gMV0gPSBjdXJyZW50SW50O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5iaXRzID0gbmV3Qml0cztcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgbWFrZUFycmF5KHNpemUgLyppbnQqLykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBJbnQzMkFycmF5KE1hdGguZmxvb3IoKHNpemUgKyAzMSkgLyAzMikpO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgZXF1YWxzKG8pIHtcbiAgICAgICAgICAgIGlmICghKG8gaW5zdGFuY2VvZiBCaXRBcnJheSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBvdGhlciA9IG87XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zaXplID09PSBvdGhlci5zaXplICYmIEFycmF5cy5lcXVhbHModGhpcy5iaXRzLCBvdGhlci5iaXRzKTtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGhhc2hDb2RlKCkge1xuICAgICAgICAgICAgcmV0dXJuIDMxICogdGhpcy5zaXplICsgQXJyYXlzLmhhc2hDb2RlKHRoaXMuYml0cyk7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICB0b1N0cmluZygpIHtcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSAnJztcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBzaXplID0gdGhpcy5zaXplOyBpIDwgc2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKChpICYgMHgwNykgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICcgJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHRoaXMuZ2V0KGkpID8gJ1gnIDogJy4nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGNsb25lKCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBCaXRBcnJheSh0aGlzLnNpemUsIHRoaXMuYml0cy5zbGljZSgpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDkgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLypuYW1lc3BhY2UgY29tLmdvb2dsZS56eGluZyB7Ki9cbiAgICAvKipcbiAgICAgKiBFbmNhcHN1bGF0ZXMgYSB0eXBlIG9mIGhpbnQgdGhhdCBhIGNhbGxlciBtYXkgcGFzcyB0byBhIGJhcmNvZGUgcmVhZGVyIHRvIGhlbHAgaXRcbiAgICAgKiBtb3JlIHF1aWNrbHkgb3IgYWNjdXJhdGVseSBkZWNvZGUgaXQuIEl0IGlzIHVwIHRvIGltcGxlbWVudGF0aW9ucyB0byBkZWNpZGUgd2hhdCxcbiAgICAgKiBpZiBhbnl0aGluZywgdG8gZG8gd2l0aCB0aGUgaW5mb3JtYXRpb24gdGhhdCBpcyBzdXBwbGllZC5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICogQGF1dGhvciBkc3dpdGtpbkBnb29nbGUuY29tIChEYW5pZWwgU3dpdGtpbilcbiAgICAgKiBAc2VlIFJlYWRlciNkZWNvZGUoQmluYXJ5Qml0bWFwLGphdmEudXRpbC5NYXApXG4gICAgICovXG4gICAgdmFyIERlY29kZUhpbnRUeXBlO1xuICAgIChmdW5jdGlvbiAoRGVjb2RlSGludFR5cGUpIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFVuc3BlY2lmaWVkLCBhcHBsaWNhdGlvbi1zcGVjaWZpYyBoaW50LiBNYXBzIHRvIGFuIHVuc3BlY2lmaWVkIHtAbGluayBPYmplY3R9LlxuICAgICAgICAgKi9cbiAgICAgICAgRGVjb2RlSGludFR5cGVbRGVjb2RlSGludFR5cGVbXCJPVEhFUlwiXSA9IDBdID0gXCJPVEhFUlwiOyAvKihPYmplY3QuY2xhc3MpKi9cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEltYWdlIGlzIGEgcHVyZSBtb25vY2hyb21lIGltYWdlIG9mIGEgYmFyY29kZS4gRG9lc24ndCBtYXR0ZXIgd2hhdCBpdCBtYXBzIHRvO1xuICAgICAgICAgKiB1c2Uge0BsaW5rIEJvb2xlYW4jVFJVRX0uXG4gICAgICAgICAqL1xuICAgICAgICBEZWNvZGVIaW50VHlwZVtEZWNvZGVIaW50VHlwZVtcIlBVUkVfQkFSQ09ERVwiXSA9IDFdID0gXCJQVVJFX0JBUkNPREVcIjsgLyooVm9pZC5jbGFzcykqL1xuICAgICAgICAvKipcbiAgICAgICAgICogSW1hZ2UgaXMga25vd24gdG8gYmUgb2Ygb25lIG9mIGEgZmV3IHBvc3NpYmxlIGZvcm1hdHMuXG4gICAgICAgICAqIE1hcHMgdG8gYSB7QGxpbmsgTGlzdH0gb2Yge0BsaW5rIEJhcmNvZGVGb3JtYXR9cy5cbiAgICAgICAgICovXG4gICAgICAgIERlY29kZUhpbnRUeXBlW0RlY29kZUhpbnRUeXBlW1wiUE9TU0lCTEVfRk9STUFUU1wiXSA9IDJdID0gXCJQT1NTSUJMRV9GT1JNQVRTXCI7IC8qKExpc3QuY2xhc3MpKi9cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNwZW5kIG1vcmUgdGltZSB0byB0cnkgdG8gZmluZCBhIGJhcmNvZGU7IG9wdGltaXplIGZvciBhY2N1cmFjeSwgbm90IHNwZWVkLlxuICAgICAgICAgKiBEb2Vzbid0IG1hdHRlciB3aGF0IGl0IG1hcHMgdG87IHVzZSB7QGxpbmsgQm9vbGVhbiNUUlVFfS5cbiAgICAgICAgICovXG4gICAgICAgIERlY29kZUhpbnRUeXBlW0RlY29kZUhpbnRUeXBlW1wiVFJZX0hBUkRFUlwiXSA9IDNdID0gXCJUUllfSEFSREVSXCI7IC8qKFZvaWQuY2xhc3MpKi9cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNwZWNpZmllcyB3aGF0IGNoYXJhY3RlciBlbmNvZGluZyB0byB1c2Ugd2hlbiBkZWNvZGluZywgd2hlcmUgYXBwbGljYWJsZSAodHlwZSBTdHJpbmcpXG4gICAgICAgICAqL1xuICAgICAgICBEZWNvZGVIaW50VHlwZVtEZWNvZGVIaW50VHlwZVtcIkNIQVJBQ1RFUl9TRVRcIl0gPSA0XSA9IFwiQ0hBUkFDVEVSX1NFVFwiOyAvKihTdHJpbmcuY2xhc3MpKi9cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEFsbG93ZWQgbGVuZ3RocyBvZiBlbmNvZGVkIGRhdGEgLS0gcmVqZWN0IGFueXRoaW5nIGVsc2UuIE1hcHMgdG8gYW4ge0Bjb2RlIEludDMyQXJyYXl9LlxuICAgICAgICAgKi9cbiAgICAgICAgRGVjb2RlSGludFR5cGVbRGVjb2RlSGludFR5cGVbXCJBTExPV0VEX0xFTkdUSFNcIl0gPSA1XSA9IFwiQUxMT1dFRF9MRU5HVEhTXCI7IC8qKEludDMyQXJyYXkuY2xhc3MpKi9cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEFzc3VtZSBDb2RlIDM5IGNvZGVzIGVtcGxveSBhIGNoZWNrIGRpZ2l0LiBEb2Vzbid0IG1hdHRlciB3aGF0IGl0IG1hcHMgdG87XG4gICAgICAgICAqIHVzZSB7QGxpbmsgQm9vbGVhbiNUUlVFfS5cbiAgICAgICAgICovXG4gICAgICAgIERlY29kZUhpbnRUeXBlW0RlY29kZUhpbnRUeXBlW1wiQVNTVU1FX0NPREVfMzlfQ0hFQ0tfRElHSVRcIl0gPSA2XSA9IFwiQVNTVU1FX0NPREVfMzlfQ0hFQ0tfRElHSVRcIjsgLyooVm9pZC5jbGFzcykqL1xuICAgICAgICAvKipcbiAgICAgICAgICogQXNzdW1lIHRoZSBiYXJjb2RlIGlzIGJlaW5nIHByb2Nlc3NlZCBhcyBhIEdTMSBiYXJjb2RlLCBhbmQgbW9kaWZ5IGJlaGF2aW9yIGFzIG5lZWRlZC5cbiAgICAgICAgICogRm9yIGV4YW1wbGUgdGhpcyBhZmZlY3RzIEZOQzEgaGFuZGxpbmcgZm9yIENvZGUgMTI4IChha2EgR1MxLTEyOCkuIERvZXNuJ3QgbWF0dGVyIHdoYXQgaXQgbWFwcyB0bztcbiAgICAgICAgICogdXNlIHtAbGluayBCb29sZWFuI1RSVUV9LlxuICAgICAgICAgKi9cbiAgICAgICAgRGVjb2RlSGludFR5cGVbRGVjb2RlSGludFR5cGVbXCJBU1NVTUVfR1MxXCJdID0gN10gPSBcIkFTU1VNRV9HUzFcIjsgLyooVm9pZC5jbGFzcykqL1xuICAgICAgICAvKipcbiAgICAgICAgICogSWYgdHJ1ZSwgcmV0dXJuIHRoZSBzdGFydCBhbmQgZW5kIGRpZ2l0cyBpbiBhIENvZGFiYXIgYmFyY29kZSBpbnN0ZWFkIG9mIHN0cmlwcGluZyB0aGVtLiBUaGV5XG4gICAgICAgICAqIGFyZSBhbHBoYSwgd2hlcmVhcyB0aGUgcmVzdCBhcmUgbnVtZXJpYy4gQnkgZGVmYXVsdCwgdGhleSBhcmUgc3RyaXBwZWQsIGJ1dCB0aGlzIGNhdXNlcyB0aGVtXG4gICAgICAgICAqIHRvIG5vdCBiZS4gRG9lc24ndCBtYXR0ZXIgd2hhdCBpdCBtYXBzIHRvOyB1c2Uge0BsaW5rIEJvb2xlYW4jVFJVRX0uXG4gICAgICAgICAqL1xuICAgICAgICBEZWNvZGVIaW50VHlwZVtEZWNvZGVIaW50VHlwZVtcIlJFVFVSTl9DT0RBQkFSX1NUQVJUX0VORFwiXSA9IDhdID0gXCJSRVRVUk5fQ09EQUJBUl9TVEFSVF9FTkRcIjsgLyooVm9pZC5jbGFzcykqL1xuICAgICAgICAvKipcbiAgICAgICAgICogVGhlIGNhbGxlciBuZWVkcyB0byBiZSBub3RpZmllZCB2aWEgY2FsbGJhY2sgd2hlbiBhIHBvc3NpYmxlIHtAbGluayBSZXN1bHRQb2ludH1cbiAgICAgICAgICogaXMgZm91bmQuIE1hcHMgdG8gYSB7QGxpbmsgUmVzdWx0UG9pbnRDYWxsYmFja30uXG4gICAgICAgICAqL1xuICAgICAgICBEZWNvZGVIaW50VHlwZVtEZWNvZGVIaW50VHlwZVtcIk5FRURfUkVTVUxUX1BPSU5UX0NBTExCQUNLXCJdID0gOV0gPSBcIk5FRURfUkVTVUxUX1BPSU5UX0NBTExCQUNLXCI7IC8qKFJlc3VsdFBvaW50Q2FsbGJhY2suY2xhc3MpKi9cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEFsbG93ZWQgZXh0ZW5zaW9uIGxlbmd0aHMgZm9yIEVBTiBvciBVUEMgYmFyY29kZXMuIE90aGVyIGZvcm1hdHMgd2lsbCBpZ25vcmUgdGhpcy5cbiAgICAgICAgICogTWFwcyB0byBhbiB7QGNvZGUgSW50MzJBcnJheX0gb2YgdGhlIGFsbG93ZWQgZXh0ZW5zaW9uIGxlbmd0aHMsIGZvciBleGFtcGxlIFsyXSwgWzVdLCBvciBbMiwgNV0uXG4gICAgICAgICAqIElmIGl0IGlzIG9wdGlvbmFsIHRvIGhhdmUgYW4gZXh0ZW5zaW9uLCBkbyBub3Qgc2V0IHRoaXMgaGludC4gSWYgdGhpcyBpcyBzZXQsXG4gICAgICAgICAqIGFuZCBhIFVQQyBvciBFQU4gYmFyY29kZSBpcyBmb3VuZCBidXQgYW4gZXh0ZW5zaW9uIGlzIG5vdCwgdGhlbiBubyByZXN1bHQgd2lsbCBiZSByZXR1cm5lZFxuICAgICAgICAgKiBhdCBhbGwuXG4gICAgICAgICAqL1xuICAgICAgICBEZWNvZGVIaW50VHlwZVtEZWNvZGVIaW50VHlwZVtcIkFMTE9XRURfRUFOX0VYVEVOU0lPTlNcIl0gPSAxMF0gPSBcIkFMTE9XRURfRUFOX0VYVEVOU0lPTlNcIjsgLyooSW50MzJBcnJheS5jbGFzcykqL1xuICAgICAgICAvLyBFbmQgb2YgZW51bWVyYXRpb24gdmFsdWVzLlxuICAgICAgICAvKipcbiAgICAgICAgICogRGF0YSB0eXBlIHRoZSBoaW50IGlzIGV4cGVjdGluZy5cbiAgICAgICAgICogQW1vbmcgdGhlIHBvc3NpYmxlIHZhbHVlcyB0aGUge0BsaW5rIFZvaWR9IHN0YW5kcyBvdXQgYXMgYmVpbmcgdXNlZCBmb3JcbiAgICAgICAgICogaGludHMgdGhhdCBkbyBub3QgZXhwZWN0IGEgdmFsdWUgdG8gYmUgc3VwcGxpZWQgKGZsYWcgaGludHMpLiBTdWNoIGhpbnRzXG4gICAgICAgICAqIHdpbGwgcG9zc2libHkgaGF2ZSB0aGVpciB2YWx1ZSBpZ25vcmVkLCBvciByZXBsYWNlZCBieSBhXG4gICAgICAgICAqIHtAbGluayBCb29sZWFuI1RSVUV9LiBIaW50IHN1cHBsaWVycyBzaG91bGQgcHJvYmFibHkgdXNlXG4gICAgICAgICAqIHtAbGluayBCb29sZWFuI1RSVUV9IGFzIGRpcmVjdGVkIGJ5IHRoZSBhY3R1YWwgaGludCBkb2N1bWVudGF0aW9uLlxuICAgICAgICAgKi9cbiAgICAgICAgLy8gcHJpdmF0ZSB2YWx1ZVR5cGU6IENsYXNzPD8+XG4gICAgICAgIC8vIERlY29kZUhpbnRUeXBlKHZhbHVlVHlwZTogQ2xhc3M8Pz4pIHtcbiAgICAgICAgLy8gICB0aGlzLnZhbHVlVHlwZSA9IHZhbHVlVHlwZVxuICAgICAgICAvLyB9XG4gICAgICAgIC8vIHB1YmxpYyBnZXRWYWx1ZVR5cGUoKTogQ2xhc3M8Pz4ge1xuICAgICAgICAvLyAgIHJldHVybiB2YWx1ZVR5cGVcbiAgICAgICAgLy8gfVxuICAgIH0pKERlY29kZUhpbnRUeXBlIHx8IChEZWNvZGVIaW50VHlwZSA9IHt9KSk7XG4gICAgdmFyIERlY29kZUhpbnRUeXBlJDEgPSBEZWNvZGVIaW50VHlwZTtcblxuICAgIC8qKlxuICAgICAqIEN1c3RvbSBFcnJvciBjbGFzcyBvZiB0eXBlIEV4Y2VwdGlvbi5cbiAgICAgKi9cbiAgICBjbGFzcyBGb3JtYXRFeGNlcHRpb24gZXh0ZW5kcyBFeGNlcHRpb24ge1xuICAgICAgICBzdGF0aWMgZ2V0Rm9ybWF0SW5zdGFuY2UoKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgfVxuICAgIEZvcm1hdEV4Y2VwdGlvbi5raW5kID0gJ0Zvcm1hdEV4Y2VwdGlvbic7XG5cbiAgICAvKmltcG9ydCBqYXZhLnV0aWwuSGFzaE1hcDsqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5NYXA7Ki9cbiAgICB2YXIgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycztcbiAgICAoZnVuY3Rpb24gKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMpIHtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiQ3A0MzdcIl0gPSAwXSA9IFwiQ3A0MzdcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiSVNPODg1OV8xXCJdID0gMV0gPSBcIklTTzg4NTlfMVwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJJU084ODU5XzJcIl0gPSAyXSA9IFwiSVNPODg1OV8yXCI7XG4gICAgICAgIENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tcIklTTzg4NTlfM1wiXSA9IDNdID0gXCJJU084ODU5XzNcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiSVNPODg1OV80XCJdID0gNF0gPSBcIklTTzg4NTlfNFwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJJU084ODU5XzVcIl0gPSA1XSA9IFwiSVNPODg1OV81XCI7XG4gICAgICAgIENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tcIklTTzg4NTlfNlwiXSA9IDZdID0gXCJJU084ODU5XzZcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiSVNPODg1OV83XCJdID0gN10gPSBcIklTTzg4NTlfN1wiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJJU084ODU5XzhcIl0gPSA4XSA9IFwiSVNPODg1OV84XCI7XG4gICAgICAgIENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tcIklTTzg4NTlfOVwiXSA9IDldID0gXCJJU084ODU5XzlcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiSVNPODg1OV8xMFwiXSA9IDEwXSA9IFwiSVNPODg1OV8xMFwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJJU084ODU5XzExXCJdID0gMTFdID0gXCJJU084ODU5XzExXCI7XG4gICAgICAgIENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tcIklTTzg4NTlfMTNcIl0gPSAxMl0gPSBcIklTTzg4NTlfMTNcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiSVNPODg1OV8xNFwiXSA9IDEzXSA9IFwiSVNPODg1OV8xNFwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJJU084ODU5XzE1XCJdID0gMTRdID0gXCJJU084ODU5XzE1XCI7XG4gICAgICAgIENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tcIklTTzg4NTlfMTZcIl0gPSAxNV0gPSBcIklTTzg4NTlfMTZcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiU0pJU1wiXSA9IDE2XSA9IFwiU0pJU1wiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJDcDEyNTBcIl0gPSAxN10gPSBcIkNwMTI1MFwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJDcDEyNTFcIl0gPSAxOF0gPSBcIkNwMTI1MVwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJDcDEyNTJcIl0gPSAxOV0gPSBcIkNwMTI1MlwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJDcDEyNTZcIl0gPSAyMF0gPSBcIkNwMTI1NlwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJVbmljb2RlQmlnVW5tYXJrZWRcIl0gPSAyMV0gPSBcIlVuaWNvZGVCaWdVbm1hcmtlZFwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJVVEY4XCJdID0gMjJdID0gXCJVVEY4XCI7XG4gICAgICAgIENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tcIkFTQ0lJXCJdID0gMjNdID0gXCJBU0NJSVwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJCaWc1XCJdID0gMjRdID0gXCJCaWc1XCI7XG4gICAgICAgIENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tcIkdCMTgwMzBcIl0gPSAyNV0gPSBcIkdCMTgwMzBcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiRVVDX0tSXCJdID0gMjZdID0gXCJFVUNfS1JcIjtcbiAgICB9KShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzIHx8IChDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzID0ge30pKTtcbiAgICAvKipcbiAgICAgKiBFbmNhcHN1bGF0ZXMgYSBDaGFyYWN0ZXIgU2V0IEVDSSwgYWNjb3JkaW5nIHRvIFwiRXh0ZW5kZWQgQ2hhbm5lbCBJbnRlcnByZXRhdGlvbnNcIiA1LjMuMS4xXG4gICAgICogb2YgSVNPIDE4MDA0LlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBDaGFyYWN0ZXJTZXRFQ0kge1xuICAgICAgICBjb25zdHJ1Y3Rvcih2YWx1ZUlkZW50aWZpZXIsIHZhbHVlc1BhcmFtLCBuYW1lLCAuLi5vdGhlckVuY29kaW5nTmFtZXMpIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWVJZGVudGlmaWVyID0gdmFsdWVJZGVudGlmaWVyO1xuICAgICAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWVzUGFyYW0gPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZXMgPSBJbnQzMkFycmF5LmZyb20oW3ZhbHVlc1BhcmFtXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlcyA9IHZhbHVlc1BhcmFtO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5vdGhlckVuY29kaW5nTmFtZXMgPSBvdGhlckVuY29kaW5nTmFtZXM7XG4gICAgICAgICAgICBDaGFyYWN0ZXJTZXRFQ0kuVkFMVUVfSURFTlRJRklFUl9UT19FQ0kuc2V0KHZhbHVlSWRlbnRpZmllciwgdGhpcyk7XG4gICAgICAgICAgICBDaGFyYWN0ZXJTZXRFQ0kuTkFNRV9UT19FQ0kuc2V0KG5hbWUsIHRoaXMpO1xuICAgICAgICAgICAgY29uc3QgdmFsdWVzID0gdGhpcy52YWx1ZXM7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgbGVuZ3RoID0gdmFsdWVzLmxlbmd0aDsgaSAhPT0gbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCB2ID0gdmFsdWVzW2ldO1xuICAgICAgICAgICAgICAgIENoYXJhY3RlclNldEVDSS5WQUxVRVNfVE9fRUNJLnNldCh2LCB0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAoY29uc3Qgb3RoZXJOYW1lIG9mIG90aGVyRW5jb2RpbmdOYW1lcykge1xuICAgICAgICAgICAgICAgIENoYXJhY3RlclNldEVDSS5OQU1FX1RPX0VDSS5zZXQob3RoZXJOYW1lLCB0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBDaGFyYWN0ZXJTZXRFQ0kodmFsdWU6IG51bWJlciAvKmludCovKSB7XG4gICAgICAgIC8vICAgdGhpcyhuZXcgSW50MzJBcnJheSB7dmFsdWV9KVxuICAgICAgICAvLyB9XG4gICAgICAgIC8vIENoYXJhY3RlclNldEVDSSh2YWx1ZTogbnVtYmVyIC8qaW50Ki8sIFN0cmluZy4uLiBvdGhlckVuY29kaW5nTmFtZXMpIHtcbiAgICAgICAgLy8gICB0aGlzLnZhbHVlcyA9IG5ldyBJbnQzMkFycmF5IHt2YWx1ZX1cbiAgICAgICAgLy8gICB0aGlzLm90aGVyRW5jb2RpbmdOYW1lcyA9IG90aGVyRW5jb2RpbmdOYW1lc1xuICAgICAgICAvLyB9XG4gICAgICAgIC8vIENoYXJhY3RlclNldEVDSSh2YWx1ZXM6IEludDMyQXJyYXksIFN0cmluZy4uLiBvdGhlckVuY29kaW5nTmFtZXMpIHtcbiAgICAgICAgLy8gICB0aGlzLnZhbHVlcyA9IHZhbHVlc1xuICAgICAgICAvLyAgIHRoaXMub3RoZXJFbmNvZGluZ05hbWVzID0gb3RoZXJFbmNvZGluZ05hbWVzXG4gICAgICAgIC8vIH1cbiAgICAgICAgZ2V0VmFsdWVJZGVudGlmaWVyKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWVJZGVudGlmaWVyO1xuICAgICAgICB9XG4gICAgICAgIGdldE5hbWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5uYW1lO1xuICAgICAgICB9XG4gICAgICAgIGdldFZhbHVlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWVzWzBdO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gdmFsdWUgY2hhcmFjdGVyIHNldCBFQ0kgdmFsdWVcbiAgICAgICAgICogQHJldHVybiB7QGNvZGUgQ2hhcmFjdGVyU2V0RUNJfSByZXByZXNlbnRpbmcgRUNJIG9mIGdpdmVuIHZhbHVlLCBvciBudWxsIGlmIGl0IGlzIGxlZ2FsIGJ1dFxuICAgICAgICAgKiAgIHVuc3VwcG9ydGVkXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uIGlmIEVDSSB2YWx1ZSBpcyBpbnZhbGlkXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZ2V0Q2hhcmFjdGVyU2V0RUNJQnlWYWx1ZSh2YWx1ZSAvKmludCovKSB7XG4gICAgICAgICAgICBpZiAodmFsdWUgPCAwIHx8IHZhbHVlID49IDkwMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oJ2luY29yZWN0IHZhbHVlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBjaGFyYWN0ZXJTZXQgPSBDaGFyYWN0ZXJTZXRFQ0kuVkFMVUVTX1RPX0VDSS5nZXQodmFsdWUpO1xuICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCA9PT0gY2hhcmFjdGVyU2V0KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbignaW5jb3JlY3QgdmFsdWUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBjaGFyYWN0ZXJTZXQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBuYW1lIGNoYXJhY3RlciBzZXQgRUNJIGVuY29kaW5nIG5hbWVcbiAgICAgICAgICogQHJldHVybiBDaGFyYWN0ZXJTZXRFQ0kgcmVwcmVzZW50aW5nIEVDSSBmb3IgY2hhcmFjdGVyIGVuY29kaW5nLCBvciBudWxsIGlmIGl0IGlzIGxlZ2FsXG4gICAgICAgICAqICAgYnV0IHVuc3VwcG9ydGVkXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZ2V0Q2hhcmFjdGVyU2V0RUNJQnlOYW1lKG5hbWUpIHtcbiAgICAgICAgICAgIGNvbnN0IGNoYXJhY3RlclNldCA9IENoYXJhY3RlclNldEVDSS5OQU1FX1RPX0VDSS5nZXQobmFtZSk7XG4gICAgICAgICAgICBpZiAodW5kZWZpbmVkID09PSBjaGFyYWN0ZXJTZXQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCdpbmNvcmVjdCB2YWx1ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGNoYXJhY3RlclNldDtcbiAgICAgICAgfVxuICAgICAgICBlcXVhbHMobykge1xuICAgICAgICAgICAgaWYgKCEobyBpbnN0YW5jZW9mIENoYXJhY3RlclNldEVDSSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBvdGhlciA9IG87XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXROYW1lKCkgPT09IG90aGVyLmdldE5hbWUoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBDaGFyYWN0ZXJTZXRFQ0kuVkFMVUVfSURFTlRJRklFUl9UT19FQ0kgPSBuZXcgTWFwKCk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLlZBTFVFU19UT19FQ0kgPSBuZXcgTWFwKCk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLk5BTUVfVE9fRUNJID0gbmV3IE1hcCgpO1xuICAgIC8vIEVudW0gbmFtZSBpcyBhIEphdmEgZW5jb2RpbmcgdmFsaWQgZm9yIGphdmEubGFuZyBhbmQgamF2YS5pb1xuICAgIC8vIFRZUEVTQ1JJUFRQT1JUOiBjaGFuZ2VkIHRoZSBtYWluIGxhYmVsIGZvciBJU08gYXMgdGhlIFRleHRFbmNvZGVyIGRpZCBub3QgcmVjb2duaXplZCB0aGVtIGluIHRoZSBmb3JtIGZyb20gamF2YVxuICAgIC8vIChlZyBJU084ODU5XzEgbXVzdCBiZSBJU084ODU5MSBvciBJU084ODU5LTEgb3IgSVNPLTg4NTktMSlcbiAgICAvLyBsYXRlciBvbjogd2VsbCwgZXhjZXB0IDE2IHdpY2ggZG9lcyBub3Qgd29yayB3aXRoIElTTzg4NTkxNiBzbyB1c2VkIElTTy04ODU5LTEgZm9ybSBmb3IgZGVmYXVsdFxuICAgIENoYXJhY3RlclNldEVDSS5DcDQzNyA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5DcDQzNywgSW50MzJBcnJheS5mcm9tKFswLCAyXSksICdDcDQzNycpO1xuICAgIENoYXJhY3RlclNldEVDSS5JU084ODU5XzEgPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuSVNPODg1OV8xLCBJbnQzMkFycmF5LmZyb20oWzEsIDNdKSwgJ0lTTy04ODU5LTEnLCAnSVNPODg1OTEnLCAnSVNPODg1OV8xJyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLklTTzg4NTlfMiA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5JU084ODU5XzIsIDQsICdJU08tODg1OS0yJywgJ0lTTzg4NTkyJywgJ0lTTzg4NTlfMicpO1xuICAgIENoYXJhY3RlclNldEVDSS5JU084ODU5XzMgPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuSVNPODg1OV8zLCA1LCAnSVNPLTg4NTktMycsICdJU084ODU5MycsICdJU084ODU5XzMnKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuSVNPODg1OV80ID0gbmV3IENoYXJhY3RlclNldEVDSShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzLklTTzg4NTlfNCwgNiwgJ0lTTy04ODU5LTQnLCAnSVNPODg1OTQnLCAnSVNPODg1OV80Jyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLklTTzg4NTlfNSA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5JU084ODU5XzUsIDcsICdJU08tODg1OS01JywgJ0lTTzg4NTk1JywgJ0lTTzg4NTlfNScpO1xuICAgIENoYXJhY3RlclNldEVDSS5JU084ODU5XzYgPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuSVNPODg1OV82LCA4LCAnSVNPLTg4NTktNicsICdJU084ODU5NicsICdJU084ODU5XzYnKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuSVNPODg1OV83ID0gbmV3IENoYXJhY3RlclNldEVDSShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzLklTTzg4NTlfNywgOSwgJ0lTTy04ODU5LTcnLCAnSVNPODg1OTcnLCAnSVNPODg1OV83Jyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLklTTzg4NTlfOCA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5JU084ODU5XzgsIDEwLCAnSVNPLTg4NTktOCcsICdJU084ODU5OCcsICdJU084ODU5XzgnKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuSVNPODg1OV85ID0gbmV3IENoYXJhY3RlclNldEVDSShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzLklTTzg4NTlfOSwgMTEsICdJU08tODg1OS05JywgJ0lTTzg4NTk5JywgJ0lTTzg4NTlfOScpO1xuICAgIENoYXJhY3RlclNldEVDSS5JU084ODU5XzEwID0gbmV3IENoYXJhY3RlclNldEVDSShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzLklTTzg4NTlfMTAsIDEyLCAnSVNPLTg4NTktMTAnLCAnSVNPODg1OTEwJywgJ0lTTzg4NTlfMTAnKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuSVNPODg1OV8xMSA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5JU084ODU5XzExLCAxMywgJ0lTTy04ODU5LTExJywgJ0lTTzg4NTkxMScsICdJU084ODU5XzExJyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLklTTzg4NTlfMTMgPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuSVNPODg1OV8xMywgMTUsICdJU08tODg1OS0xMycsICdJU084ODU5MTMnLCAnSVNPODg1OV8xMycpO1xuICAgIENoYXJhY3RlclNldEVDSS5JU084ODU5XzE0ID0gbmV3IENoYXJhY3RlclNldEVDSShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzLklTTzg4NTlfMTQsIDE2LCAnSVNPLTg4NTktMTQnLCAnSVNPODg1OTE0JywgJ0lTTzg4NTlfMTQnKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuSVNPODg1OV8xNSA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5JU084ODU5XzE1LCAxNywgJ0lTTy04ODU5LTE1JywgJ0lTTzg4NTkxNScsICdJU084ODU5XzE1Jyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLklTTzg4NTlfMTYgPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuSVNPODg1OV8xNiwgMTgsICdJU08tODg1OS0xNicsICdJU084ODU5MTYnLCAnSVNPODg1OV8xNicpO1xuICAgIENoYXJhY3RlclNldEVDSS5TSklTID0gbmV3IENoYXJhY3RlclNldEVDSShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzLlNKSVMsIDIwLCAnU0pJUycsICdTaGlmdF9KSVMnKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuQ3AxMjUwID0gbmV3IENoYXJhY3RlclNldEVDSShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzLkNwMTI1MCwgMjEsICdDcDEyNTAnLCAnd2luZG93cy0xMjUwJyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLkNwMTI1MSA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5DcDEyNTEsIDIyLCAnQ3AxMjUxJywgJ3dpbmRvd3MtMTI1MScpO1xuICAgIENoYXJhY3RlclNldEVDSS5DcDEyNTIgPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuQ3AxMjUyLCAyMywgJ0NwMTI1MicsICd3aW5kb3dzLTEyNTInKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuQ3AxMjU2ID0gbmV3IENoYXJhY3RlclNldEVDSShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzLkNwMTI1NiwgMjQsICdDcDEyNTYnLCAnd2luZG93cy0xMjU2Jyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLlVuaWNvZGVCaWdVbm1hcmtlZCA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5Vbmljb2RlQmlnVW5tYXJrZWQsIDI1LCAnVW5pY29kZUJpZ1VubWFya2VkJywgJ1VURi0xNkJFJywgJ1VuaWNvZGVCaWcnKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuVVRGOCA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5VVEY4LCAyNiwgJ1VURjgnLCAnVVRGLTgnKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuQVNDSUkgPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuQVNDSUksIEludDMyQXJyYXkuZnJvbShbMjcsIDE3MF0pLCAnQVNDSUknLCAnVVMtQVNDSUknKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuQmlnNSA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5CaWc1LCAyOCwgJ0JpZzUnKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuR0IxODAzMCA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5HQjE4MDMwLCAyOSwgJ0dCMTgwMzAnLCAnR0IyMzEyJywgJ0VVQ19DTicsICdHQksnKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuRVVDX0tSID0gbmV3IENoYXJhY3RlclNldEVDSShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzLkVVQ19LUiwgMzAsICdFVUNfS1InLCAnRVVDLUtSJyk7XG5cbiAgICAvKipcbiAgICAgKiBDdXN0b20gRXJyb3IgY2xhc3Mgb2YgdHlwZSBFeGNlcHRpb24uXG4gICAgICovXG4gICAgY2xhc3MgVW5zdXBwb3J0ZWRPcGVyYXRpb25FeGNlcHRpb24gZXh0ZW5kcyBFeGNlcHRpb24ge1xuICAgIH1cbiAgICBVbnN1cHBvcnRlZE9wZXJhdGlvbkV4Y2VwdGlvbi5raW5kID0gJ1Vuc3VwcG9ydGVkT3BlcmF0aW9uRXhjZXB0aW9uJztcblxuICAgIC8qKlxuICAgICAqIFJlc3BvbnNpYmxlIGZvciBlbi9kZWNvZGluZyBzdHJpbmdzLlxuICAgICAqL1xuICAgIGNsYXNzIFN0cmluZ0VuY29kaW5nIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgc29tZSBVaW50OEFycmF5IHRvIGEgc3RyaW5nIGZvcm1hdC5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBkZWNvZGUoYnl0ZXMsIGVuY29kaW5nKSB7XG4gICAgICAgICAgICBjb25zdCBlbmNvZGluZ05hbWUgPSB0aGlzLmVuY29kaW5nTmFtZShlbmNvZGluZyk7XG4gICAgICAgICAgICBpZiAodGhpcy5jdXN0b21EZWNvZGVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY3VzdG9tRGVjb2RlcihieXRlcywgZW5jb2RpbmdOYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEluY3JlYXNlcyBicm93c2VyIHN1cHBvcnQuXG4gICAgICAgICAgICBpZiAodHlwZW9mIFRleHREZWNvZGVyID09PSAndW5kZWZpbmVkJyB8fCB0aGlzLnNob3VsZERlY29kZU9uRmFsbGJhY2soZW5jb2RpbmdOYW1lKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZUZhbGxiYWNrKGJ5dGVzLCBlbmNvZGluZ05hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBUZXh0RGVjb2RlcihlbmNvZGluZ05hbWUpLmRlY29kZShieXRlcyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENoZWNrcyBpZiB0aGUgZGVjb2RpbmcgbWV0aG9kIHNob3VsZCB1c2UgdGhlIGZhbGxiYWNrIGZvciBkZWNvZGluZ1xuICAgICAgICAgKiBvbmNlIE5vZGUgVGV4dERlY29kZXIgZG9lc24ndCBzdXBwb3J0IGFsbCBlbmNvZGluZyBmb3JtYXRzLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gZW5jb2RpbmdOYW1lXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgc2hvdWxkRGVjb2RlT25GYWxsYmFjayhlbmNvZGluZ05hbWUpIHtcbiAgICAgICAgICAgIHJldHVybiAhU3RyaW5nRW5jb2RpbmcuaXNCcm93c2VyKCkgJiYgZW5jb2RpbmdOYW1lID09PSAnSVNPLTg4NTktMSc7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgc29tZSBzdHJpbmcgaW50byBhIFVpbnQ4QXJyYXkuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZW5jb2RlKHMsIGVuY29kaW5nKSB7XG4gICAgICAgICAgICBjb25zdCBlbmNvZGluZ05hbWUgPSB0aGlzLmVuY29kaW5nTmFtZShlbmNvZGluZyk7XG4gICAgICAgICAgICBpZiAodGhpcy5jdXN0b21FbmNvZGVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY3VzdG9tRW5jb2RlcihzLCBlbmNvZGluZ05hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSW5jcmVhc2VzIGJyb3dzZXIgc3VwcG9ydC5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgVGV4dEVuY29kZXIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2RlRmFsbGJhY2socyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBUZXh0RW5jb2RlciBvbmx5IGVuY29kZXMgdG8gVVRGOCBieSBkZWZhdWx0IGFzIHNwZWNpZmllZCBieSBlbmNvZGluZy5zcGVjLndoYXR3Zy5vcmdcbiAgICAgICAgICAgIHJldHVybiBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUocyk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGlzQnJvd3NlcigpIHtcbiAgICAgICAgICAgIHJldHVybiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYge30udG9TdHJpbmcuY2FsbCh3aW5kb3cpID09PSAnW29iamVjdCBXaW5kb3ddJyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldHVybnMgdGhlIHN0cmluZyB2YWx1ZSBmcm9tIHNvbWUgZW5jb2RpbmcgY2hhcmFjdGVyIHNldC5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBlbmNvZGluZ05hbWUoZW5jb2RpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiB0eXBlb2YgZW5jb2RpbmcgPT09ICdzdHJpbmcnXG4gICAgICAgICAgICAgICAgPyBlbmNvZGluZ1xuICAgICAgICAgICAgICAgIDogZW5jb2RpbmcuZ2V0TmFtZSgpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXR1cm5zIGNoYXJhY3RlciBzZXQgZnJvbSBzb21lIGVuY29kaW5nIGNoYXJhY3RlciBzZXQuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZW5jb2RpbmdDaGFyYWN0ZXJTZXQoZW5jb2RpbmcpIHtcbiAgICAgICAgICAgIGlmIChlbmNvZGluZyBpbnN0YW5jZW9mIENoYXJhY3RlclNldEVDSSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBlbmNvZGluZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBDaGFyYWN0ZXJTZXRFQ0kuZ2V0Q2hhcmFjdGVyU2V0RUNJQnlOYW1lKGVuY29kaW5nKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogUnVucyBhIGZhbGxiYWNrIGZvciB0aGUgbmF0aXZlIGRlY29kaW5nIGZ1bmNpb24uXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGVjb2RlRmFsbGJhY2soYnl0ZXMsIGVuY29kaW5nKSB7XG4gICAgICAgICAgICBjb25zdCBjaGFyYWN0ZXJTZXQgPSB0aGlzLmVuY29kaW5nQ2hhcmFjdGVyU2V0KGVuY29kaW5nKTtcbiAgICAgICAgICAgIGlmIChTdHJpbmdFbmNvZGluZy5pc0RlY29kZUZhbGxiYWNrU3VwcG9ydGVkKGNoYXJhY3RlclNldCkpIHtcbiAgICAgICAgICAgICAgICBsZXQgcyA9ICcnO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBsZW5ndGggPSBieXRlcy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgaCA9IGJ5dGVzW2ldLnRvU3RyaW5nKDE2KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGgubGVuZ3RoIDwgMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaCA9ICcwJyArIGg7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcyArPSAnJScgKyBoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNoYXJhY3RlclNldC5lcXVhbHMoQ2hhcmFjdGVyU2V0RUNJLlVuaWNvZGVCaWdVbm1hcmtlZCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBuZXcgVWludDE2QXJyYXkoYnl0ZXMuYnVmZmVyKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgVW5zdXBwb3J0ZWRPcGVyYXRpb25FeGNlcHRpb24oYEVuY29kaW5nICR7dGhpcy5lbmNvZGluZ05hbWUoZW5jb2RpbmcpfSBub3Qgc3VwcG9ydGVkIGJ5IGZhbGxiYWNrLmApO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBpc0RlY29kZUZhbGxiYWNrU3VwcG9ydGVkKGNoYXJhY3RlclNldCkge1xuICAgICAgICAgICAgcmV0dXJuIGNoYXJhY3RlclNldC5lcXVhbHMoQ2hhcmFjdGVyU2V0RUNJLlVURjgpIHx8XG4gICAgICAgICAgICAgICAgY2hhcmFjdGVyU2V0LmVxdWFscyhDaGFyYWN0ZXJTZXRFQ0kuSVNPODg1OV8xKSB8fFxuICAgICAgICAgICAgICAgIGNoYXJhY3RlclNldC5lcXVhbHMoQ2hhcmFjdGVyU2V0RUNJLkFTQ0lJKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogUnVucyBhIGZhbGxiYWNrIGZvciB0aGUgbmF0aXZlIGVuY29kaW5nIGZ1bmNpb24uXG4gICAgICAgICAqXG4gICAgICAgICAqIEBzZWUgaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzE3MTkyODQ1LzQzNjc2ODNcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBlbmNvZGVGYWxsYmFjayhzKSB7XG4gICAgICAgICAgICBjb25zdCBlbmNvZGVkVVJJc3RyaW5nID0gYnRvYSh1bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQocykpKTtcbiAgICAgICAgICAgIGNvbnN0IGNoYXJMaXN0ID0gZW5jb2RlZFVSSXN0cmluZy5zcGxpdCgnJyk7XG4gICAgICAgICAgICBjb25zdCB1aW50QXJyYXkgPSBbXTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hhckxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB1aW50QXJyYXkucHVzaChjaGFyTGlzdFtpXS5jaGFyQ29kZUF0KDApKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheSh1aW50QXJyYXkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgKEMpIDIwMTAgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogQ29tbW9uIHN0cmluZy1yZWxhdGVkIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICogQGF1dGhvciBBbGV4IER1cHJlXG4gICAgICovXG4gICAgY2xhc3MgU3RyaW5nVXRpbHMge1xuICAgICAgICAvLyBTSElGVF9KSVMuZXF1YWxzSWdub3JlQ2FzZShQTEFURk9STV9ERUZBVUxUX0VOQ09ESU5HKSB8fFxuICAgICAgICAvLyBFVUNfSlAuZXF1YWxzSWdub3JlQ2FzZShQTEFURk9STV9ERUZBVUxUX0VOQ09ESU5HKTtcbiAgICAgICAgc3RhdGljIGNhc3RBc05vblV0ZjhDaGFyKGNvZGUsIGVuY29kaW5nID0gbnVsbCkge1xuICAgICAgICAgICAgLy8gSVNPIDg4NTktMSBpcyB0aGUgSmF2YSBkZWZhdWx0IGFzIFVURi04IGlzIEphdmFTY3JpcHRzXG4gICAgICAgICAgICAvLyB5b3UgY2FuIHNlZSB0aGlzIG1ldGhvZCBhcyBhIEphdmEgdmVyc2lvbiBvZiBTdHJpbmcuZnJvbUNoYXJDb2RlXG4gICAgICAgICAgICBjb25zdCBlID0gZW5jb2RpbmcgPyBlbmNvZGluZy5nZXROYW1lKCkgOiB0aGlzLklTTzg4NTkxO1xuICAgICAgICAgICAgLy8gdXNlIHBhc3NlZCBmb3JtYXQgKGZyb21DaGFyQ29kZSB3aWxsIHJldHVybiBVVEY4IGVuY29kaW5nKVxuICAgICAgICAgICAgcmV0dXJuIFN0cmluZ0VuY29kaW5nLmRlY29kZShuZXcgVWludDhBcnJheShbY29kZV0pLCBlKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIGJ5dGVzIGJ5dGVzIGVuY29kaW5nIGEgc3RyaW5nLCB3aG9zZSBlbmNvZGluZyBzaG91bGQgYmUgZ3Vlc3NlZFxuICAgICAgICAgKiBAcGFyYW0gaGludHMgZGVjb2RlIGhpbnRzIGlmIGFwcGxpY2FibGVcbiAgICAgICAgICogQHJldHVybiBuYW1lIG9mIGd1ZXNzZWQgZW5jb2Rpbmc7IGF0IHRoZSBtb21lbnQgd2lsbCBvbmx5IGd1ZXNzIG9uZSBvZjpcbiAgICAgICAgICogIHtAbGluayAjU0hJRlRfSklTfSwge0BsaW5rICNVVEY4fSwge0BsaW5rICNJU084ODU5MX0sIG9yIHRoZSBwbGF0Zm9ybVxuICAgICAgICAgKiAgZGVmYXVsdCBlbmNvZGluZyBpZiBub25lIG9mIHRoZXNlIGNhbiBwb3NzaWJseSBiZSBjb3JyZWN0XG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZ3Vlc3NFbmNvZGluZyhieXRlcywgaGludHMpIHtcbiAgICAgICAgICAgIGlmIChoaW50cyAhPT0gbnVsbCAmJiBoaW50cyAhPT0gdW5kZWZpbmVkICYmIHVuZGVmaW5lZCAhPT0gaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuQ0hBUkFDVEVSX1NFVCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuQ0hBUkFDVEVSX1NFVCkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEZvciBub3csIG1lcmVseSB0cmllcyB0byBkaXN0aW5ndWlzaCBJU08tODg1OS0xLCBVVEYtOCBhbmQgU2hpZnRfSklTLFxuICAgICAgICAgICAgLy8gd2hpY2ggc2hvdWxkIGJlIGJ5IGZhciB0aGUgbW9zdCBjb21tb24gZW5jb2RpbmdzLlxuICAgICAgICAgICAgY29uc3QgbGVuZ3RoID0gYnl0ZXMubGVuZ3RoO1xuICAgICAgICAgICAgbGV0IGNhbkJlSVNPODg1OTEgPSB0cnVlO1xuICAgICAgICAgICAgbGV0IGNhbkJlU2hpZnRKSVMgPSB0cnVlO1xuICAgICAgICAgICAgbGV0IGNhbkJlVVRGOCA9IHRydWU7XG4gICAgICAgICAgICBsZXQgdXRmOEJ5dGVzTGVmdCA9IDA7XG4gICAgICAgICAgICAvLyBpbnQgdXRmOExvd0NoYXJzID0gMFxuICAgICAgICAgICAgbGV0IHV0ZjJCeXRlc0NoYXJzID0gMDtcbiAgICAgICAgICAgIGxldCB1dGYzQnl0ZXNDaGFycyA9IDA7XG4gICAgICAgICAgICBsZXQgdXRmNEJ5dGVzQ2hhcnMgPSAwO1xuICAgICAgICAgICAgbGV0IHNqaXNCeXRlc0xlZnQgPSAwO1xuICAgICAgICAgICAgLy8gaW50IHNqaXNMb3dDaGFycyA9IDBcbiAgICAgICAgICAgIGxldCBzamlzS2F0YWthbmFDaGFycyA9IDA7XG4gICAgICAgICAgICAvLyBpbnQgc2ppc0RvdWJsZUJ5dGVzQ2hhcnMgPSAwXG4gICAgICAgICAgICBsZXQgc2ppc0N1ckthdGFrYW5hV29yZExlbmd0aCA9IDA7XG4gICAgICAgICAgICBsZXQgc2ppc0N1ckRvdWJsZUJ5dGVzV29yZExlbmd0aCA9IDA7XG4gICAgICAgICAgICBsZXQgc2ppc01heEthdGFrYW5hV29yZExlbmd0aCA9IDA7XG4gICAgICAgICAgICBsZXQgc2ppc01heERvdWJsZUJ5dGVzV29yZExlbmd0aCA9IDA7XG4gICAgICAgICAgICAvLyBpbnQgaXNvTG93Q2hhcnMgPSAwXG4gICAgICAgICAgICAvLyBpbnQgaXNvSGlnaENoYXJzID0gMFxuICAgICAgICAgICAgbGV0IGlzb0hpZ2hPdGhlciA9IDA7XG4gICAgICAgICAgICBjb25zdCB1dGY4Ym9tID0gYnl0ZXMubGVuZ3RoID4gMyAmJlxuICAgICAgICAgICAgICAgIGJ5dGVzWzBdID09PSAvKihieXRlKSAqLyAweEVGICYmXG4gICAgICAgICAgICAgICAgYnl0ZXNbMV0gPT09IC8qKGJ5dGUpICovIDB4QkIgJiZcbiAgICAgICAgICAgICAgICBieXRlc1syXSA9PT0gLyooYnl0ZSkgKi8gMHhCRjtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoICYmIChjYW5CZUlTTzg4NTkxIHx8IGNhbkJlU2hpZnRKSVMgfHwgY2FuQmVVVEY4KTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBieXRlc1tpXSAmIDB4RkY7XG4gICAgICAgICAgICAgICAgLy8gVVRGLTggc3R1ZmZcbiAgICAgICAgICAgICAgICBpZiAoY2FuQmVVVEY4KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh1dGY4Qnl0ZXNMZWZ0ID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCh2YWx1ZSAmIDB4ODApID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FuQmVVVEY4ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1dGY4Qnl0ZXNMZWZ0LS07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoKHZhbHVlICYgMHg4MCkgIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgodmFsdWUgJiAweDQwKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbkJlVVRGOCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXRmOEJ5dGVzTGVmdCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgodmFsdWUgJiAweDIwKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1dGYyQnl0ZXNDaGFycysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXRmOEJ5dGVzTGVmdCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKHZhbHVlICYgMHgxMCkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHV0ZjNCeXRlc0NoYXJzKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1dGY4Qnl0ZXNMZWZ0Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKHZhbHVlICYgMHgwOCkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1dGY0Qnl0ZXNDaGFycysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FuQmVVVEY4ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gLy8gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHV0ZjhMb3dDaGFycysrXG4gICAgICAgICAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gSVNPLTg4NTktMSBzdHVmZlxuICAgICAgICAgICAgICAgIGlmIChjYW5CZUlTTzg4NTkxKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA+IDB4N0YgJiYgdmFsdWUgPCAweEEwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYW5CZUlTTzg4NTkxID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodmFsdWUgPiAweDlGKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUgPCAweEMwIHx8IHZhbHVlID09PSAweEQ3IHx8IHZhbHVlID09PSAweEY3KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNvSGlnaE90aGVyKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IC8vIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXNvSGlnaENoYXJzKytcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgICAgICAgICAgfSAvLyBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gaXNvTG93Q2hhcnMrK1xuICAgICAgICAgICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIFNoaWZ0X0pJUyBzdHVmZlxuICAgICAgICAgICAgICAgIGlmIChjYW5CZVNoaWZ0SklTKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzamlzQnl0ZXNMZWZ0ID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlIDwgMHg0MCB8fCB2YWx1ZSA9PT0gMHg3RiB8fCB2YWx1ZSA+IDB4RkMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYW5CZVNoaWZ0SklTID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzamlzQnl0ZXNMZWZ0LS07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodmFsdWUgPT09IDB4ODAgfHwgdmFsdWUgPT09IDB4QTAgfHwgdmFsdWUgPiAweEVGKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYW5CZVNoaWZ0SklTID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodmFsdWUgPiAweEEwICYmIHZhbHVlIDwgMHhFMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ppc0thdGFrYW5hQ2hhcnMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIHNqaXNDdXJEb3VibGVCeXRlc1dvcmRMZW5ndGggPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ppc0N1ckthdGFrYW5hV29yZExlbmd0aCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNqaXNDdXJLYXRha2FuYVdvcmRMZW5ndGggPiBzamlzTWF4S2F0YWthbmFXb3JkTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ppc01heEthdGFrYW5hV29yZExlbmd0aCA9IHNqaXNDdXJLYXRha2FuYVdvcmRMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodmFsdWUgPiAweDdGKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzamlzQnl0ZXNMZWZ0Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzamlzRG91YmxlQnl0ZXNDaGFycysrXG4gICAgICAgICAgICAgICAgICAgICAgICBzamlzQ3VyS2F0YWthbmFXb3JkTGVuZ3RoID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNqaXNDdXJEb3VibGVCeXRlc1dvcmRMZW5ndGgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzamlzQ3VyRG91YmxlQnl0ZXNXb3JkTGVuZ3RoID4gc2ppc01heERvdWJsZUJ5dGVzV29yZExlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNqaXNNYXhEb3VibGVCeXRlc1dvcmRMZW5ndGggPSBzamlzQ3VyRG91YmxlQnl0ZXNXb3JkTGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2ppc0xvd0NoYXJzKytcbiAgICAgICAgICAgICAgICAgICAgICAgIHNqaXNDdXJLYXRha2FuYVdvcmRMZW5ndGggPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ppc0N1ckRvdWJsZUJ5dGVzV29yZExlbmd0aCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FuQmVVVEY4ICYmIHV0ZjhCeXRlc0xlZnQgPiAwKSB7XG4gICAgICAgICAgICAgICAgY2FuQmVVVEY4ID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FuQmVTaGlmdEpJUyAmJiBzamlzQnl0ZXNMZWZ0ID4gMCkge1xuICAgICAgICAgICAgICAgIGNhbkJlU2hpZnRKSVMgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEVhc3kgLS0gaWYgdGhlcmUgaXMgQk9NIG9yIGF0IGxlYXN0IDEgdmFsaWQgbm90LXNpbmdsZSBieXRlIGNoYXJhY3RlciAoYW5kIG5vIGV2aWRlbmNlIGl0IGNhbid0IGJlIFVURi04KSwgZG9uZVxuICAgICAgICAgICAgaWYgKGNhbkJlVVRGOCAmJiAodXRmOGJvbSB8fCB1dGYyQnl0ZXNDaGFycyArIHV0ZjNCeXRlc0NoYXJzICsgdXRmNEJ5dGVzQ2hhcnMgPiAwKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmdVdGlscy5VVEY4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRWFzeSAtLSBpZiBhc3N1bWluZyBTaGlmdF9KSVMgb3IgYXQgbGVhc3QgMyB2YWxpZCBjb25zZWN1dGl2ZSBub3QtYXNjaWkgY2hhcmFjdGVycyAoYW5kIG5vIGV2aWRlbmNlIGl0IGNhbid0IGJlKSwgZG9uZVxuICAgICAgICAgICAgaWYgKGNhbkJlU2hpZnRKSVMgJiYgKFN0cmluZ1V0aWxzLkFTU1VNRV9TSElGVF9KSVMgfHwgc2ppc01heEthdGFrYW5hV29yZExlbmd0aCA+PSAzIHx8IHNqaXNNYXhEb3VibGVCeXRlc1dvcmRMZW5ndGggPj0gMykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nVXRpbHMuU0hJRlRfSklTO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRGlzdGluZ3Vpc2hpbmcgU2hpZnRfSklTIGFuZCBJU08tODg1OS0xIGNhbiBiZSBhIGxpdHRsZSB0b3VnaCBmb3Igc2hvcnQgd29yZHMuIFRoZSBjcnVkZSBoZXVyaXN0aWMgaXM6XG4gICAgICAgICAgICAvLyAtIElmIHdlIHNhd1xuICAgICAgICAgICAgLy8gICAtIG9ubHkgdHdvIGNvbnNlY3V0aXZlIGthdGFrYW5hIGNoYXJzIGluIHRoZSB3aG9sZSB0ZXh0LCBvclxuICAgICAgICAgICAgLy8gICAtIGF0IGxlYXN0IDEwJSBvZiBieXRlcyB0aGF0IGNvdWxkIGJlIFwidXBwZXJcIiBub3QtYWxwaGFudW1lcmljIExhdGluMSxcbiAgICAgICAgICAgIC8vIC0gdGhlbiB3ZSBjb25jbHVkZSBTaGlmdF9KSVMsIGVsc2UgSVNPLTg4NTktMVxuICAgICAgICAgICAgaWYgKGNhbkJlSVNPODg1OTEgJiYgY2FuQmVTaGlmdEpJUykge1xuICAgICAgICAgICAgICAgIHJldHVybiAoc2ppc01heEthdGFrYW5hV29yZExlbmd0aCA9PT0gMiAmJiBzamlzS2F0YWthbmFDaGFycyA9PT0gMikgfHwgaXNvSGlnaE90aGVyICogMTAgPj0gbGVuZ3RoXG4gICAgICAgICAgICAgICAgICAgID8gU3RyaW5nVXRpbHMuU0hJRlRfSklTIDogU3RyaW5nVXRpbHMuSVNPODg1OTE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBPdGhlcndpc2UsIHRyeSBpbiBvcmRlciBJU08tODg1OS0xLCBTaGlmdCBKSVMsIFVURi04IGFuZCBmYWxsIGJhY2sgdG8gZGVmYXVsdCBwbGF0Zm9ybSBlbmNvZGluZ1xuICAgICAgICAgICAgaWYgKGNhbkJlSVNPODg1OTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nVXRpbHMuSVNPODg1OTE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FuQmVTaGlmdEpJUykge1xuICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmdVdGlscy5TSElGVF9KSVM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FuQmVVVEY4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZ1V0aWxzLlVURjg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBPdGhlcndpc2UsIHdlIHRha2UgYSB3aWxkIGd1ZXNzIHdpdGggcGxhdGZvcm0gZW5jb2RpbmdcbiAgICAgICAgICAgIHJldHVybiBTdHJpbmdVdGlscy5QTEFURk9STV9ERUZBVUxUX0VOQ09ESU5HO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKlxuICAgICAgICAgKiBAc2VlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8xMzQzOTcxMS80MzY3NjgzXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBhcHBlbmQgVGhlIG5ldyBzdHJpbmcgdG8gYXBwZW5kLlxuICAgICAgICAgKiBAcGFyYW0gYXJncyBBcmd1bWV0cyB2YWx1ZXMgdG8gYmUgZm9ybWF0ZWQuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZm9ybWF0KGFwcGVuZCwgLi4uYXJncykge1xuICAgICAgICAgICAgbGV0IGkgPSAtMTtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGNhbGxiYWNrKGV4cCwgcDAsIHAxLCBwMiwgcDMsIHA0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGV4cCA9PT0gJyUlJylcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICclJztcbiAgICAgICAgICAgICAgICBpZiAoYXJnc1srK2ldID09PSB1bmRlZmluZWQpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgZXhwID0gcDIgPyBwYXJzZUludChwMi5zdWJzdHIoMSkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGxldCBiYXNlID0gcDMgPyBwYXJzZUludChwMy5zdWJzdHIoMSkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGxldCB2YWw7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChwNCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdzJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbCA9IGFyZ3NbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnYyc6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWwgPSBhcmdzW2ldWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2YnOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsID0gcGFyc2VGbG9hdChhcmdzW2ldKS50b0ZpeGVkKGV4cCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAncCc6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWwgPSBwYXJzZUZsb2F0KGFyZ3NbaV0pLnRvUHJlY2lzaW9uKGV4cCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWwgPSBwYXJzZUZsb2F0KGFyZ3NbaV0pLnRvRXhwb25lbnRpYWwoZXhwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICd4JzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbCA9IHBhcnNlSW50KGFyZ3NbaV0pLnRvU3RyaW5nKGJhc2UgPyBiYXNlIDogMTYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsID0gcGFyc2VGbG9hdChwYXJzZUludChhcmdzW2ldLCBiYXNlID8gYmFzZSA6IDEwKS50b1ByZWNpc2lvbihleHApKS50b0ZpeGVkKDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhbCA9IHR5cGVvZiB2YWwgPT09ICdvYmplY3QnID8gSlNPTi5zdHJpbmdpZnkodmFsKSA6ICgrdmFsKS50b1N0cmluZyhiYXNlKTtcbiAgICAgICAgICAgICAgICBsZXQgc2l6ZSA9IHBhcnNlSW50KHAxKTsgLyogcGFkZGluZyBzaXplICovXG4gICAgICAgICAgICAgICAgbGV0IGNoID0gcDEgJiYgKHAxWzBdICsgJycpID09PSAnMCcgPyAnMCcgOiAnICc7IC8qIGlzbnVsbD8gKi9cbiAgICAgICAgICAgICAgICB3aGlsZSAodmFsLmxlbmd0aCA8IHNpemUpXG4gICAgICAgICAgICAgICAgICAgIHZhbCA9IHAwICE9PSB1bmRlZmluZWQgPyB2YWwgKyBjaCA6IGNoICsgdmFsOyAvKiBpc21pbnVzPyAqL1xuICAgICAgICAgICAgICAgIHJldHVybiB2YWw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcmVnZXggPSAvJSgtKT8oMD9bMC05XSspPyhbLl1bMC05XSspPyhbI11bMC05XSspPyhbc2NmcGV4ZCVdKS9nO1xuICAgICAgICAgICAgcmV0dXJuIGFwcGVuZC5yZXBsYWNlKHJlZ2V4LCBjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZ2V0Qnl0ZXMoc3RyLCBlbmNvZGluZykge1xuICAgICAgICAgICAgcmV0dXJuIFN0cmluZ0VuY29kaW5nLmVuY29kZShzdHIsIGVuY29kaW5nKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogUmV0dXJucyB0aGUgY2hhcmNvZGUgYXQgdGhlIHNwZWNpZmllZCBpbmRleCBvciBhdCBpbmRleCB6ZXJvLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGdldENoYXJDb2RlKHN0ciwgaW5kZXggPSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyLmNoYXJDb2RlQXQoaW5kZXgpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXR1cm5zIGNoYXIgZm9yIGdpdmVuIGNoYXJjb2RlXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZ2V0Q2hhckF0KGNoYXJDb2RlKSB7XG4gICAgICAgICAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShjaGFyQ29kZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgU3RyaW5nVXRpbHMuU0hJRlRfSklTID0gQ2hhcmFjdGVyU2V0RUNJLlNKSVMuZ2V0TmFtZSgpOyAvLyBcIlNKSVNcIlxuICAgIFN0cmluZ1V0aWxzLkdCMjMxMiA9ICdHQjIzMTInO1xuICAgIFN0cmluZ1V0aWxzLklTTzg4NTkxID0gQ2hhcmFjdGVyU2V0RUNJLklTTzg4NTlfMS5nZXROYW1lKCk7IC8vIFwiSVNPODg1OV8xXCJcbiAgICBTdHJpbmdVdGlscy5FVUNfSlAgPSAnRVVDX0pQJztcbiAgICBTdHJpbmdVdGlscy5VVEY4ID0gQ2hhcmFjdGVyU2V0RUNJLlVURjguZ2V0TmFtZSgpOyAvLyBcIlVURjhcIlxuICAgIFN0cmluZ1V0aWxzLlBMQVRGT1JNX0RFRkFVTFRfRU5DT0RJTkcgPSBTdHJpbmdVdGlscy5VVEY4OyAvLyBcIlVURjhcIi8vQ2hhcnNldC5kZWZhdWx0Q2hhcnNldCgpLm5hbWUoKVxuICAgIFN0cmluZ1V0aWxzLkFTU1VNRV9TSElGVF9KSVMgPSBmYWxzZTtcblxuICAgIGNsYXNzIFN0cmluZ0J1aWxkZXIge1xuICAgICAgICBjb25zdHJ1Y3Rvcih2YWx1ZSA9ICcnKSB7XG4gICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgZW5hYmxlRGVjb2RpbmcoZW5jb2RpbmcpIHtcbiAgICAgICAgICAgIHRoaXMuZW5jb2RpbmcgPSBlbmNvZGluZztcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGFwcGVuZChzKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSArPSBzLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLmVuY29kaW5nKSB7XG4gICAgICAgICAgICAgICAgLy8gdXNlIHBhc3NlZCBmb3JtYXQgKGZyb21DaGFyQ29kZSB3aWxsIHJldHVybiBVVEY4IGVuY29kaW5nKVxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgKz0gU3RyaW5nVXRpbHMuY2FzdEFzTm9uVXRmOENoYXIocywgdGhpcy5lbmNvZGluZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBjb3JyZWN0bHkgY29udmVydHMgZnJvbSBVVEYtOCwgYnV0IG5vdCBvdGhlciBlbmNvZGluZ3NcbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlICs9IFN0cmluZy5mcm9tQ2hhckNvZGUocyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICBhcHBlbmRDaGFycyhzdHIsIG9mZnNldCwgbGVuKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gb2Zmc2V0OyBvZmZzZXQgPCBvZmZzZXQgKyBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgIHRoaXMuYXBwZW5kKHN0cltpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICBsZW5ndGgoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgICAgY2hhckF0KG4pIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlLmNoYXJBdChuKTtcbiAgICAgICAgfVxuICAgICAgICBkZWxldGVDaGFyQXQobikge1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHRoaXMudmFsdWUuc3Vic3RyKDAsIG4pICsgdGhpcy52YWx1ZS5zdWJzdHJpbmcobiArIDEpO1xuICAgICAgICB9XG4gICAgICAgIHNldENoYXJBdChuLCBjKSB7XG4gICAgICAgICAgICB0aGlzLnZhbHVlID0gdGhpcy52YWx1ZS5zdWJzdHIoMCwgbikgKyBjICsgdGhpcy52YWx1ZS5zdWJzdHIobiArIDEpO1xuICAgICAgICB9XG4gICAgICAgIHN1YnN0cmluZyhzdGFydCwgZW5kKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZS5zdWJzdHJpbmcoc3RhcnQsIGVuZCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBub3RlIGhlbHBlciBtZXRob2QgZm9yIFJTUyBFeHBhbmRlZFxuICAgICAgICAgKi9cbiAgICAgICAgc2V0TGVuZ3RoVG9aZXJvKCkge1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9ICcnO1xuICAgICAgICB9XG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaW5zZXJ0KG4sIGMpIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB0aGlzLnZhbHVlLnN1YnN0cigwLCBuKSArIGMgKyB0aGlzLnZhbHVlLnN1YnN0cihuICsgYy5sZW5ndGgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiA8cD5SZXByZXNlbnRzIGEgMkQgbWF0cml4IG9mIGJpdHMuIEluIGZ1bmN0aW9uIGFyZ3VtZW50cyBiZWxvdywgYW5kIHRocm91Z2hvdXQgdGhlIGNvbW1vblxuICAgICAqIG1vZHVsZSwgeCBpcyB0aGUgY29sdW1uIHBvc2l0aW9uLCBhbmQgeSBpcyB0aGUgcm93IHBvc2l0aW9uLiBUaGUgb3JkZXJpbmcgaXMgYWx3YXlzIHgsIHkuXG4gICAgICogVGhlIG9yaWdpbiBpcyBhdCB0aGUgdG9wLWxlZnQuPC9wPlxuICAgICAqXG4gICAgICogPHA+SW50ZXJuYWxseSB0aGUgYml0cyBhcmUgcmVwcmVzZW50ZWQgaW4gYSAxLUQgYXJyYXkgb2YgMzItYml0IGludHMuIEhvd2V2ZXIsIGVhY2ggcm93IGJlZ2luc1xuICAgICAqIHdpdGggYSBuZXcgaW50LiBUaGlzIGlzIGRvbmUgaW50ZW50aW9uYWxseSBzbyB0aGF0IHdlIGNhbiBjb3B5IG91dCBhIHJvdyBpbnRvIGEgQml0QXJyYXkgdmVyeVxuICAgICAqIGVmZmljaWVudGx5LjwvcD5cbiAgICAgKlxuICAgICAqIDxwPlRoZSBvcmRlcmluZyBvZiBiaXRzIGlzIHJvdy1tYWpvci4gV2l0aGluIGVhY2ggaW50LCB0aGUgbGVhc3Qgc2lnbmlmaWNhbnQgYml0cyBhcmUgdXNlZCBmaXJzdCxcbiAgICAgKiBtZWFuaW5nIHRoZXkgcmVwcmVzZW50IGxvd2VyIHggdmFsdWVzLiBUaGlzIGlzIGNvbXBhdGlibGUgd2l0aCBCaXRBcnJheSdzIGltcGxlbWVudGF0aW9uLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICogQGF1dGhvciBkc3dpdGtpbkBnb29nbGUuY29tIChEYW5pZWwgU3dpdGtpbilcbiAgICAgKi9cbiAgICBjbGFzcyBCaXRNYXRyaXggLyppbXBsZW1lbnRzIENsb25lYWJsZSovIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYW4gZW1wdHkgc3F1YXJlIHtAbGluayBCaXRNYXRyaXh9LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gZGltZW5zaW9uIGhlaWdodCBhbmQgd2lkdGhcbiAgICAgICAgICovXG4gICAgICAgIC8vIHB1YmxpYyBjb25zdHJ1Y3RvcihkaW1lbnNpb246IG51bWJlciAvKmludCovKSB7XG4gICAgICAgIC8vICAgdGhpcyhkaW1lbnNpb24sIGRpbWVuc2lvbilcbiAgICAgICAgLy8gfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhbiBlbXB0eSB7QGxpbmsgQml0TWF0cml4fS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHdpZHRoIGJpdCBtYXRyaXggd2lkdGhcbiAgICAgICAgICogQHBhcmFtIGhlaWdodCBiaXQgbWF0cml4IGhlaWdodFxuICAgICAgICAgKi9cbiAgICAgICAgLy8gcHVibGljIGNvbnN0cnVjdG9yKHdpZHRoOiBudW1iZXIgLyppbnQqLywgaGVpZ2h0OiBudW1iZXIgLyppbnQqLykge1xuICAgICAgICAvLyAgIGlmICh3aWR0aCA8IDEgfHwgaGVpZ2h0IDwgMSkge1xuICAgICAgICAvLyAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbihcIkJvdGggZGltZW5zaW9ucyBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwXCIpXG4gICAgICAgIC8vICAgfVxuICAgICAgICAvLyAgIHRoaXMud2lkdGggPSB3aWR0aFxuICAgICAgICAvLyAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0XG4gICAgICAgIC8vICAgdGhpcy5yb3dTaXplID0gKHdpZHRoICsgMzEpIC8gMzJcbiAgICAgICAgLy8gICBiaXRzID0gbmV3IGludFtyb3dTaXplICogaGVpZ2h0XTtcbiAgICAgICAgLy8gfVxuICAgICAgICBjb25zdHJ1Y3Rvcih3aWR0aCAvKmludCovLCBoZWlnaHQgLyppbnQqLywgcm93U2l6ZSAvKmludCovLCBiaXRzKSB7XG4gICAgICAgICAgICB0aGlzLndpZHRoID0gd2lkdGg7XG4gICAgICAgICAgICB0aGlzLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgICAgIHRoaXMucm93U2l6ZSA9IHJvd1NpemU7XG4gICAgICAgICAgICB0aGlzLmJpdHMgPSBiaXRzO1xuICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCA9PT0gaGVpZ2h0IHx8IG51bGwgPT09IGhlaWdodCkge1xuICAgICAgICAgICAgICAgIGhlaWdodCA9IHdpZHRoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgICAgICBpZiAod2lkdGggPCAxIHx8IGhlaWdodCA8IDEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdCb3RoIGRpbWVuc2lvbnMgbXVzdCBiZSBncmVhdGVyIHRoYW4gMCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCA9PT0gcm93U2l6ZSB8fCBudWxsID09PSByb3dTaXplKSB7XG4gICAgICAgICAgICAgICAgcm93U2l6ZSA9IE1hdGguZmxvb3IoKHdpZHRoICsgMzEpIC8gMzIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yb3dTaXplID0gcm93U2l6ZTtcbiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IGJpdHMgfHwgbnVsbCA9PT0gYml0cykge1xuICAgICAgICAgICAgICAgIHRoaXMuYml0cyA9IG5ldyBJbnQzMkFycmF5KHRoaXMucm93U2l6ZSAqIHRoaXMuaGVpZ2h0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogSW50ZXJwcmV0cyBhIDJEIGFycmF5IG9mIGJvb2xlYW5zIGFzIGEge0BsaW5rIEJpdE1hdHJpeH0sIHdoZXJlIFwidHJ1ZVwiIG1lYW5zIGFuIFwib25cIiBiaXQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBmdW5jdGlvbiBwYXJzZVxuICAgICAgICAgKiBAcGFyYW0gaW1hZ2UgYml0cyBvZiB0aGUgaW1hZ2UsIGFzIGEgcm93LW1ham9yIDJEIGFycmF5LiBFbGVtZW50cyBhcmUgYXJyYXlzIHJlcHJlc2VudGluZyByb3dzXG4gICAgICAgICAqIEByZXR1cm4ge0BsaW5rIEJpdE1hdHJpeH0gcmVwcmVzZW50YXRpb24gb2YgaW1hZ2VcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBwYXJzZUZyb21Cb29sZWFuQXJyYXkoaW1hZ2UpIHtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IGltYWdlLmxlbmd0aDtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gaW1hZ2VbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3QgYml0cyA9IG5ldyBCaXRNYXRyaXgod2lkdGgsIGhlaWdodCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGhlaWdodDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaW1hZ2VJID0gaW1hZ2VbaV07XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB3aWR0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbWFnZUlbal0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJpdHMuc2V0KGosIGkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGJpdHM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqXG4gICAgICAgICAqIEBmdW5jdGlvbiBwYXJzZVxuICAgICAgICAgKiBAcGFyYW0gc3RyaW5nUmVwcmVzZW50YXRpb25cbiAgICAgICAgICogQHBhcmFtIHNldFN0cmluZ1xuICAgICAgICAgKiBAcGFyYW0gdW5zZXRTdHJpbmdcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBwYXJzZUZyb21TdHJpbmcoc3RyaW5nUmVwcmVzZW50YXRpb24sIHNldFN0cmluZywgdW5zZXRTdHJpbmcpIHtcbiAgICAgICAgICAgIGlmIChzdHJpbmdSZXByZXNlbnRhdGlvbiA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ3N0cmluZ1JlcHJlc2VudGF0aW9uIGNhbm5vdCBiZSBudWxsJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBiaXRzID0gbmV3IEFycmF5KHN0cmluZ1JlcHJlc2VudGF0aW9uLmxlbmd0aCk7XG4gICAgICAgICAgICBsZXQgYml0c1BvcyA9IDA7XG4gICAgICAgICAgICBsZXQgcm93U3RhcnRQb3MgPSAwO1xuICAgICAgICAgICAgbGV0IHJvd0xlbmd0aCA9IC0xO1xuICAgICAgICAgICAgbGV0IG5Sb3dzID0gMDtcbiAgICAgICAgICAgIGxldCBwb3MgPSAwO1xuICAgICAgICAgICAgd2hpbGUgKHBvcyA8IHN0cmluZ1JlcHJlc2VudGF0aW9uLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGlmIChzdHJpbmdSZXByZXNlbnRhdGlvbi5jaGFyQXQocG9zKSA9PT0gJ1xcbicgfHxcbiAgICAgICAgICAgICAgICAgICAgc3RyaW5nUmVwcmVzZW50YXRpb24uY2hhckF0KHBvcykgPT09ICdcXHInKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChiaXRzUG9zID4gcm93U3RhcnRQb3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyb3dMZW5ndGggPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93TGVuZ3RoID0gYml0c1BvcyAtIHJvd1N0YXJ0UG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoYml0c1BvcyAtIHJvd1N0YXJ0UG9zICE9PSByb3dMZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdyb3cgbGVuZ3RocyBkbyBub3QgbWF0Y2gnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJvd1N0YXJ0UG9zID0gYml0c1BvcztcbiAgICAgICAgICAgICAgICAgICAgICAgIG5Sb3dzKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcG9zKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHN0cmluZ1JlcHJlc2VudGF0aW9uLnN1YnN0cmluZyhwb3MsIHBvcyArIHNldFN0cmluZy5sZW5ndGgpID09PSBzZXRTdHJpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgcG9zICs9IHNldFN0cmluZy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGJpdHNbYml0c1Bvc10gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBiaXRzUG9zKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHN0cmluZ1JlcHJlc2VudGF0aW9uLnN1YnN0cmluZyhwb3MsIHBvcyArIHVuc2V0U3RyaW5nLmxlbmd0aCkgPT09IHVuc2V0U3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvcyArPSB1bnNldFN0cmluZy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGJpdHNbYml0c1Bvc10gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgYml0c1BvcysrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignaWxsZWdhbCBjaGFyYWN0ZXIgZW5jb3VudGVyZWQ6ICcgKyBzdHJpbmdSZXByZXNlbnRhdGlvbi5zdWJzdHJpbmcocG9zKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gbm8gRU9MIGF0IGVuZD9cbiAgICAgICAgICAgIGlmIChiaXRzUG9zID4gcm93U3RhcnRQb3MpIHtcbiAgICAgICAgICAgICAgICBpZiAocm93TGVuZ3RoID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICByb3dMZW5ndGggPSBiaXRzUG9zIC0gcm93U3RhcnRQb3M7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGJpdHNQb3MgLSByb3dTdGFydFBvcyAhPT0gcm93TGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ3JvdyBsZW5ndGhzIGRvIG5vdCBtYXRjaCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBuUm93cysrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbWF0cml4ID0gbmV3IEJpdE1hdHJpeChyb3dMZW5ndGgsIG5Sb3dzKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYml0c1BvczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGJpdHNbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChNYXRoLmZsb29yKGkgJSByb3dMZW5ndGgpLCBNYXRoLmZsb29yKGkgLyByb3dMZW5ndGgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWF0cml4O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5HZXRzIHRoZSByZXF1ZXN0ZWQgYml0LCB3aGVyZSB0cnVlIG1lYW5zIGJsYWNrLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHggVGhlIGhvcml6b250YWwgY29tcG9uZW50IChpLmUuIHdoaWNoIGNvbHVtbilcbiAgICAgICAgICogQHBhcmFtIHkgVGhlIHZlcnRpY2FsIGNvbXBvbmVudCAoaS5lLiB3aGljaCByb3cpXG4gICAgICAgICAqIEByZXR1cm4gdmFsdWUgb2YgZ2l2ZW4gYml0IGluIG1hdHJpeFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0KHggLyppbnQqLywgeSAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBvZmZzZXQgPSB5ICogdGhpcy5yb3dTaXplICsgTWF0aC5mbG9vcih4IC8gMzIpO1xuICAgICAgICAgICAgcmV0dXJuICgodGhpcy5iaXRzW29mZnNldF0gPj4+ICh4ICYgMHgxZikpICYgMSkgIT09IDA7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPlNldHMgdGhlIGdpdmVuIGJpdCB0byB0cnVlLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHggVGhlIGhvcml6b250YWwgY29tcG9uZW50IChpLmUuIHdoaWNoIGNvbHVtbilcbiAgICAgICAgICogQHBhcmFtIHkgVGhlIHZlcnRpY2FsIGNvbXBvbmVudCAoaS5lLiB3aGljaCByb3cpXG4gICAgICAgICAqL1xuICAgICAgICBzZXQoeCAvKmludCovLCB5IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHkgKiB0aGlzLnJvd1NpemUgKyBNYXRoLmZsb29yKHggLyAzMik7XG4gICAgICAgICAgICB0aGlzLmJpdHNbb2Zmc2V0XSB8PSAoMSA8PCAoeCAmIDB4MWYpKSAmIDB4RkZGRkZGRkY7XG4gICAgICAgIH1cbiAgICAgICAgdW5zZXQoeCAvKmludCovLCB5IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHkgKiB0aGlzLnJvd1NpemUgKyBNYXRoLmZsb29yKHggLyAzMik7XG4gICAgICAgICAgICB0aGlzLmJpdHNbb2Zmc2V0XSAmPSB+KCgxIDw8ICh4ICYgMHgxZikpICYgMHhGRkZGRkZGRik7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkZsaXBzIHRoZSBnaXZlbiBiaXQuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0geCBUaGUgaG9yaXpvbnRhbCBjb21wb25lbnQgKGkuZS4gd2hpY2ggY29sdW1uKVxuICAgICAgICAgKiBAcGFyYW0geSBUaGUgdmVydGljYWwgY29tcG9uZW50IChpLmUuIHdoaWNoIHJvdylcbiAgICAgICAgICovXG4gICAgICAgIGZsaXAoeCAvKmludCovLCB5IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHkgKiB0aGlzLnJvd1NpemUgKyBNYXRoLmZsb29yKHggLyAzMik7XG4gICAgICAgICAgICB0aGlzLmJpdHNbb2Zmc2V0XSBePSAoKDEgPDwgKHggJiAweDFmKSkgJiAweEZGRkZGRkZGKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRXhjbHVzaXZlLW9yIChYT1IpOiBGbGlwIHRoZSBiaXQgaW4gdGhpcyB7QGNvZGUgQml0TWF0cml4fSBpZiB0aGUgY29ycmVzcG9uZGluZ1xuICAgICAgICAgKiBtYXNrIGJpdCBpcyBzZXQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBtYXNrIFhPUiBtYXNrXG4gICAgICAgICAqL1xuICAgICAgICB4b3IobWFzaykge1xuICAgICAgICAgICAgaWYgKHRoaXMud2lkdGggIT09IG1hc2suZ2V0V2lkdGgoKSB8fCB0aGlzLmhlaWdodCAhPT0gbWFzay5nZXRIZWlnaHQoKVxuICAgICAgICAgICAgICAgIHx8IHRoaXMucm93U2l6ZSAhPT0gbWFzay5nZXRSb3dTaXplKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdpbnB1dCBtYXRyaXggZGltZW5zaW9ucyBkbyBub3QgbWF0Y2gnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJvd0FycmF5ID0gbmV3IEJpdEFycmF5KE1hdGguZmxvb3IodGhpcy53aWR0aCAvIDMyKSArIDEpO1xuICAgICAgICAgICAgY29uc3Qgcm93U2l6ZSA9IHRoaXMucm93U2l6ZTtcbiAgICAgICAgICAgIGNvbnN0IGJpdHMgPSB0aGlzLmJpdHM7XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMCwgaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7IHkgPCBoZWlnaHQ7IHkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHkgKiByb3dTaXplO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJvdyA9IG1hc2suZ2V0Um93KHksIHJvd0FycmF5KS5nZXRCaXRBcnJheSgpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgcm93U2l6ZTsgeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGJpdHNbb2Zmc2V0ICsgeF0gXj0gcm93W3hdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ2xlYXJzIGFsbCBiaXRzIChzZXRzIHRvIGZhbHNlKS5cbiAgICAgICAgICovXG4gICAgICAgIGNsZWFyKCkge1xuICAgICAgICAgICAgY29uc3QgYml0cyA9IHRoaXMuYml0cztcbiAgICAgICAgICAgIGNvbnN0IG1heCA9IGJpdHMubGVuZ3RoO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXg7IGkrKykge1xuICAgICAgICAgICAgICAgIGJpdHNbaV0gPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5TZXRzIGEgc3F1YXJlIHJlZ2lvbiBvZiB0aGUgYml0IG1hdHJpeCB0byB0cnVlLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGxlZnQgVGhlIGhvcml6b250YWwgcG9zaXRpb24gdG8gYmVnaW4gYXQgKGluY2x1c2l2ZSlcbiAgICAgICAgICogQHBhcmFtIHRvcCBUaGUgdmVydGljYWwgcG9zaXRpb24gdG8gYmVnaW4gYXQgKGluY2x1c2l2ZSlcbiAgICAgICAgICogQHBhcmFtIHdpZHRoIFRoZSB3aWR0aCBvZiB0aGUgcmVnaW9uXG4gICAgICAgICAqIEBwYXJhbSBoZWlnaHQgVGhlIGhlaWdodCBvZiB0aGUgcmVnaW9uXG4gICAgICAgICAqL1xuICAgICAgICBzZXRSZWdpb24obGVmdCAvKmludCovLCB0b3AgLyppbnQqLywgd2lkdGggLyppbnQqLywgaGVpZ2h0IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGlmICh0b3AgPCAwIHx8IGxlZnQgPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignTGVmdCBhbmQgdG9wIG11c3QgYmUgbm9ubmVnYXRpdmUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChoZWlnaHQgPCAxIHx8IHdpZHRoIDwgMSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ0hlaWdodCBhbmQgd2lkdGggbXVzdCBiZSBhdCBsZWFzdCAxJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByaWdodCA9IGxlZnQgKyB3aWR0aDtcbiAgICAgICAgICAgIGNvbnN0IGJvdHRvbSA9IHRvcCArIGhlaWdodDtcbiAgICAgICAgICAgIGlmIChib3R0b20gPiB0aGlzLmhlaWdodCB8fCByaWdodCA+IHRoaXMud2lkdGgpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdUaGUgcmVnaW9uIG11c3QgZml0IGluc2lkZSB0aGUgbWF0cml4Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByb3dTaXplID0gdGhpcy5yb3dTaXplO1xuICAgICAgICAgICAgY29uc3QgYml0cyA9IHRoaXMuYml0cztcbiAgICAgICAgICAgIGZvciAobGV0IHkgPSB0b3A7IHkgPCBib3R0b207IHkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHkgKiByb3dTaXplO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSBsZWZ0OyB4IDwgcmlnaHQ7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICBiaXRzW29mZnNldCArIE1hdGguZmxvb3IoeCAvIDMyKV0gfD0gKCgxIDw8ICh4ICYgMHgxZikpICYgMHhGRkZGRkZGRik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBIGZhc3QgbWV0aG9kIHRvIHJldHJpZXZlIG9uZSByb3cgb2YgZGF0YSBmcm9tIHRoZSBtYXRyaXggYXMgYSBCaXRBcnJheS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHkgVGhlIHJvdyB0byByZXRyaWV2ZVxuICAgICAgICAgKiBAcGFyYW0gcm93IEFuIG9wdGlvbmFsIGNhbGxlci1hbGxvY2F0ZWQgQml0QXJyYXksIHdpbGwgYmUgYWxsb2NhdGVkIGlmIG51bGwgb3IgdG9vIHNtYWxsXG4gICAgICAgICAqIEByZXR1cm4gVGhlIHJlc3VsdGluZyBCaXRBcnJheSAtIHRoaXMgcmVmZXJlbmNlIHNob3VsZCBhbHdheXMgYmUgdXNlZCBldmVuIHdoZW4gcGFzc2luZ1xuICAgICAgICAgKiAgICAgICAgIHlvdXIgb3duIHJvd1xuICAgICAgICAgKi9cbiAgICAgICAgZ2V0Um93KHkgLyppbnQqLywgcm93KSB7XG4gICAgICAgICAgICBpZiAocm93ID09PSBudWxsIHx8IHJvdyA9PT0gdW5kZWZpbmVkIHx8IHJvdy5nZXRTaXplKCkgPCB0aGlzLndpZHRoKSB7XG4gICAgICAgICAgICAgICAgcm93ID0gbmV3IEJpdEFycmF5KHRoaXMud2lkdGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcm93LmNsZWFyKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByb3dTaXplID0gdGhpcy5yb3dTaXplO1xuICAgICAgICAgICAgY29uc3QgYml0cyA9IHRoaXMuYml0cztcbiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHkgKiByb3dTaXplO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCByb3dTaXplOyB4KyspIHtcbiAgICAgICAgICAgICAgICByb3cuc2V0QnVsayh4ICogMzIsIGJpdHNbb2Zmc2V0ICsgeF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJvdztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHkgcm93IHRvIHNldFxuICAgICAgICAgKiBAcGFyYW0gcm93IHtAbGluayBCaXRBcnJheX0gdG8gY29weSBmcm9tXG4gICAgICAgICAqL1xuICAgICAgICBzZXRSb3coeSAvKmludCovLCByb3cpIHtcbiAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkocm93LmdldEJpdEFycmF5KCksIDAsIHRoaXMuYml0cywgeSAqIHRoaXMucm93U2l6ZSwgdGhpcy5yb3dTaXplKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogTW9kaWZpZXMgdGhpcyB7QGNvZGUgQml0TWF0cml4fSB0byByZXByZXNlbnQgdGhlIHNhbWUgYnV0IHJvdGF0ZWQgMTgwIGRlZ3JlZXNcbiAgICAgICAgICovXG4gICAgICAgIHJvdGF0ZTE4MCgpIHtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGxldCB0b3BSb3cgPSBuZXcgQml0QXJyYXkod2lkdGgpO1xuICAgICAgICAgICAgbGV0IGJvdHRvbVJvdyA9IG5ldyBCaXRBcnJheSh3aWR0aCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgbGVuZ3RoID0gTWF0aC5mbG9vcigoaGVpZ2h0ICsgMSkgLyAyKTsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdG9wUm93ID0gdGhpcy5nZXRSb3coaSwgdG9wUm93KTtcbiAgICAgICAgICAgICAgICBib3R0b21Sb3cgPSB0aGlzLmdldFJvdyhoZWlnaHQgLSAxIC0gaSwgYm90dG9tUm93KTtcbiAgICAgICAgICAgICAgICB0b3BSb3cucmV2ZXJzZSgpO1xuICAgICAgICAgICAgICAgIGJvdHRvbVJvdy5yZXZlcnNlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRSb3coaSwgYm90dG9tUm93KTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFJvdyhoZWlnaHQgLSAxIC0gaSwgdG9wUm93KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogVGhpcyBpcyB1c2VmdWwgaW4gZGV0ZWN0aW5nIHRoZSBlbmNsb3NpbmcgcmVjdGFuZ2xlIG9mIGEgJ3B1cmUnIGJhcmNvZGUuXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4ge0Bjb2RlIGxlZnQsdG9wLHdpZHRoLGhlaWdodH0gZW5jbG9zaW5nIHJlY3RhbmdsZSBvZiBhbGwgMSBiaXRzLCBvciBudWxsIGlmIGl0IGlzIGFsbCB3aGl0ZVxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0RW5jbG9zaW5nUmVjdGFuZ2xlKCkge1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSB0aGlzLndpZHRoO1xuICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7XG4gICAgICAgICAgICBjb25zdCByb3dTaXplID0gdGhpcy5yb3dTaXplO1xuICAgICAgICAgICAgY29uc3QgYml0cyA9IHRoaXMuYml0cztcbiAgICAgICAgICAgIGxldCBsZWZ0ID0gd2lkdGg7XG4gICAgICAgICAgICBsZXQgdG9wID0gaGVpZ2h0O1xuICAgICAgICAgICAgbGV0IHJpZ2h0ID0gLTE7XG4gICAgICAgICAgICBsZXQgYm90dG9tID0gLTE7XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeDMyID0gMDsgeDMyIDwgcm93U2l6ZTsgeDMyKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGhlQml0cyA9IGJpdHNbeSAqIHJvd1NpemUgKyB4MzJdO1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhlQml0cyAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHkgPCB0b3ApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3AgPSB5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHkgPiBib3R0b20pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBib3R0b20gPSB5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHgzMiAqIDMyIDwgbGVmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBiaXQgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlICgoKHRoZUJpdHMgPDwgKDMxIC0gYml0KSkgJiAweEZGRkZGRkZGKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaXQrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCh4MzIgKiAzMiArIGJpdCkgPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQgPSB4MzIgKiAzMiArIGJpdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoeDMyICogMzIgKyAzMSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGJpdCA9IDMxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlICgodGhlQml0cyA+Pj4gYml0KSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaXQtLTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCh4MzIgKiAzMiArIGJpdCkgPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByaWdodCA9IHgzMiAqIDMyICsgYml0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyaWdodCA8IGxlZnQgfHwgYm90dG9tIDwgdG9wKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gSW50MzJBcnJheS5mcm9tKFtsZWZ0LCB0b3AsIHJpZ2h0IC0gbGVmdCArIDEsIGJvdHRvbSAtIHRvcCArIDFdKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogVGhpcyBpcyB1c2VmdWwgaW4gZGV0ZWN0aW5nIGEgY29ybmVyIG9mIGEgJ3B1cmUnIGJhcmNvZGUuXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4ge0Bjb2RlIHgseX0gY29vcmRpbmF0ZSBvZiB0b3AtbGVmdC1tb3N0IDEgYml0LCBvciBudWxsIGlmIGl0IGlzIGFsbCB3aGl0ZVxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0VG9wTGVmdE9uQml0KCkge1xuICAgICAgICAgICAgY29uc3Qgcm93U2l6ZSA9IHRoaXMucm93U2l6ZTtcbiAgICAgICAgICAgIGNvbnN0IGJpdHMgPSB0aGlzLmJpdHM7XG4gICAgICAgICAgICBsZXQgYml0c09mZnNldCA9IDA7XG4gICAgICAgICAgICB3aGlsZSAoYml0c09mZnNldCA8IGJpdHMubGVuZ3RoICYmIGJpdHNbYml0c09mZnNldF0gPT09IDApIHtcbiAgICAgICAgICAgICAgICBiaXRzT2Zmc2V0Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYml0c09mZnNldCA9PT0gYml0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHkgPSBiaXRzT2Zmc2V0IC8gcm93U2l6ZTtcbiAgICAgICAgICAgIGxldCB4ID0gKGJpdHNPZmZzZXQgJSByb3dTaXplKSAqIDMyO1xuICAgICAgICAgICAgY29uc3QgdGhlQml0cyA9IGJpdHNbYml0c09mZnNldF07XG4gICAgICAgICAgICBsZXQgYml0ID0gMDtcbiAgICAgICAgICAgIHdoaWxlICgoKHRoZUJpdHMgPDwgKDMxIC0gYml0KSkgJiAweEZGRkZGRkZGKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGJpdCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgeCArPSBiaXQ7XG4gICAgICAgICAgICByZXR1cm4gSW50MzJBcnJheS5mcm9tKFt4LCB5XSk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Qm90dG9tUmlnaHRPbkJpdCgpIHtcbiAgICAgICAgICAgIGNvbnN0IHJvd1NpemUgPSB0aGlzLnJvd1NpemU7XG4gICAgICAgICAgICBjb25zdCBiaXRzID0gdGhpcy5iaXRzO1xuICAgICAgICAgICAgbGV0IGJpdHNPZmZzZXQgPSBiaXRzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICB3aGlsZSAoYml0c09mZnNldCA+PSAwICYmIGJpdHNbYml0c09mZnNldF0gPT09IDApIHtcbiAgICAgICAgICAgICAgICBiaXRzT2Zmc2V0LS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYml0c09mZnNldCA8IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHkgPSBNYXRoLmZsb29yKGJpdHNPZmZzZXQgLyByb3dTaXplKTtcbiAgICAgICAgICAgIGxldCB4ID0gTWF0aC5mbG9vcihiaXRzT2Zmc2V0ICUgcm93U2l6ZSkgKiAzMjtcbiAgICAgICAgICAgIGNvbnN0IHRoZUJpdHMgPSBiaXRzW2JpdHNPZmZzZXRdO1xuICAgICAgICAgICAgbGV0IGJpdCA9IDMxO1xuICAgICAgICAgICAgd2hpbGUgKCh0aGVCaXRzID4+PiBiaXQpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgYml0LS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB4ICs9IGJpdDtcbiAgICAgICAgICAgIHJldHVybiBJbnQzMkFycmF5LmZyb20oW3gsIHldKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBUaGUgd2lkdGggb2YgdGhlIG1hdHJpeFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0V2lkdGgoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aWR0aDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBUaGUgaGVpZ2h0IG9mIHRoZSBtYXRyaXhcbiAgICAgICAgICovXG4gICAgICAgIGdldEhlaWdodCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmhlaWdodDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBUaGUgcm93IHNpemUgb2YgdGhlIG1hdHJpeFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0Um93U2l6ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJvd1NpemU7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBlcXVhbHMobykge1xuICAgICAgICAgICAgaWYgKCEobyBpbnN0YW5jZW9mIEJpdE1hdHJpeCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBvdGhlciA9IG87XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aWR0aCA9PT0gb3RoZXIud2lkdGggJiYgdGhpcy5oZWlnaHQgPT09IG90aGVyLmhlaWdodCAmJiB0aGlzLnJvd1NpemUgPT09IG90aGVyLnJvd1NpemUgJiZcbiAgICAgICAgICAgICAgICBBcnJheXMuZXF1YWxzKHRoaXMuYml0cywgb3RoZXIuYml0cyk7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBoYXNoQ29kZSgpIHtcbiAgICAgICAgICAgIGxldCBoYXNoID0gdGhpcy53aWR0aDtcbiAgICAgICAgICAgIGhhc2ggPSAzMSAqIGhhc2ggKyB0aGlzLndpZHRoO1xuICAgICAgICAgICAgaGFzaCA9IDMxICogaGFzaCArIHRoaXMuaGVpZ2h0O1xuICAgICAgICAgICAgaGFzaCA9IDMxICogaGFzaCArIHRoaXMucm93U2l6ZTtcbiAgICAgICAgICAgIGhhc2ggPSAzMSAqIGhhc2ggKyBBcnJheXMuaGFzaENvZGUodGhpcy5iaXRzKTtcbiAgICAgICAgICAgIHJldHVybiBoYXNoO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHN0cmluZyByZXByZXNlbnRhdGlvbiB1c2luZyBcIlhcIiBmb3Igc2V0IGFuZCBcIiBcIiBmb3IgdW5zZXQgYml0c1xuICAgICAgICAgKi9cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICAvLyBwdWJsaWMgdG9TdHJpbmcoKTogc3RyaW5nIHtcbiAgICAgICAgLy8gICByZXR1cm4gdG9TdHJpbmcoXCI6IFwiWCwgXCIgIFwiKVxuICAgICAgICAvLyB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gc2V0U3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgc2V0IGJpdFxuICAgICAgICAgKiBAcGFyYW0gdW5zZXRTdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYW4gdW5zZXQgYml0XG4gICAgICAgICAqIEByZXR1cm4gc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGVudGlyZSBtYXRyaXggdXRpbGl6aW5nIGdpdmVuIHN0cmluZ3NcbiAgICAgICAgICovXG4gICAgICAgIC8vIHB1YmxpYyB0b1N0cmluZyhzZXRTdHJpbmc6IHN0cmluZyA9IFwiWCBcIiwgdW5zZXRTdHJpbmc6IHN0cmluZyA9IFwiICBcIik6IHN0cmluZyB7XG4gICAgICAgIC8vICAgcmV0dXJuIHRoaXMuYnVpbGRUb1N0cmluZyhzZXRTdHJpbmcsIHVuc2V0U3RyaW5nLCBcIlxcblwiKVxuICAgICAgICAvLyB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gc2V0U3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgc2V0IGJpdFxuICAgICAgICAgKiBAcGFyYW0gdW5zZXRTdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYW4gdW5zZXQgYml0XG4gICAgICAgICAqIEBwYXJhbSBsaW5lU2VwYXJhdG9yIG5ld2xpbmUgY2hhcmFjdGVyIGluIHN0cmluZyByZXByZXNlbnRhdGlvblxuICAgICAgICAgKiBAcmV0dXJuIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBlbnRpcmUgbWF0cml4IHV0aWxpemluZyBnaXZlbiBzdHJpbmdzIGFuZCBsaW5lIHNlcGFyYXRvclxuICAgICAgICAgKiBAZGVwcmVjYXRlZCBjYWxsIHtAbGluayAjdG9TdHJpbmcoU3RyaW5nLFN0cmluZyl9IG9ubHksIHdoaWNoIHVzZXMgXFxuIGxpbmUgc2VwYXJhdG9yIGFsd2F5c1xuICAgICAgICAgKi9cbiAgICAgICAgLy8gQERlcHJlY2F0ZWRcbiAgICAgICAgdG9TdHJpbmcoc2V0U3RyaW5nID0gJ1ggJywgdW5zZXRTdHJpbmcgPSAnICAnLCBsaW5lU2VwYXJhdG9yID0gJ1xcbicpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJ1aWxkVG9TdHJpbmcoc2V0U3RyaW5nLCB1bnNldFN0cmluZywgbGluZVNlcGFyYXRvcik7XG4gICAgICAgIH1cbiAgICAgICAgYnVpbGRUb1N0cmluZyhzZXRTdHJpbmcsIHVuc2V0U3RyaW5nLCBsaW5lU2VwYXJhdG9yKSB7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gbmV3IFN0cmluZ0J1aWxkZXIoKTtcbiAgICAgICAgICAgIC8vIHJlc3VsdC5hcHBlbmQobGluZVNlcGFyYXRvcik7XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMCwgaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7IHkgPCBoZWlnaHQ7IHkrKykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAwLCB3aWR0aCA9IHRoaXMud2lkdGg7IHggPCB3aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQodGhpcy5nZXQoeCwgeSkgPyBzZXRTdHJpbmcgOiB1bnNldFN0cmluZyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQobGluZVNlcGFyYXRvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0LnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBjbG9uZSgpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgQml0TWF0cml4KHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0LCB0aGlzLnJvd1NpemUsIHRoaXMuYml0cy5zbGljZSgpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEN1c3RvbSBFcnJvciBjbGFzcyBvZiB0eXBlIEV4Y2VwdGlvbi5cbiAgICAgKi9cbiAgICBjbGFzcyBOb3RGb3VuZEV4Y2VwdGlvbiBleHRlbmRzIEV4Y2VwdGlvbiB7XG4gICAgICAgIHN0YXRpYyBnZXROb3RGb3VuZEluc3RhbmNlKCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgfVxuICAgIE5vdEZvdW5kRXhjZXB0aW9uLmtpbmQgPSAnTm90Rm91bmRFeGNlcHRpb24nO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwOSBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiBUaGlzIEJpbmFyaXplciBpbXBsZW1lbnRhdGlvbiB1c2VzIHRoZSBvbGQgWlhpbmcgZ2xvYmFsIGhpc3RvZ3JhbSBhcHByb2FjaC4gSXQgaXMgc3VpdGFibGVcbiAgICAgKiBmb3IgbG93LWVuZCBtb2JpbGUgZGV2aWNlcyB3aGljaCBkb24ndCBoYXZlIGVub3VnaCBDUFUgb3IgbWVtb3J5IHRvIHVzZSBhIGxvY2FsIHRocmVzaG9sZGluZ1xuICAgICAqIGFsZ29yaXRobS4gSG93ZXZlciwgYmVjYXVzZSBpdCBwaWNrcyBhIGdsb2JhbCBibGFjayBwb2ludCwgaXQgY2Fubm90IGhhbmRsZSBkaWZmaWN1bHQgc2hhZG93c1xuICAgICAqIGFuZCBncmFkaWVudHMuXG4gICAgICpcbiAgICAgKiBGYXN0ZXIgbW9iaWxlIGRldmljZXMgYW5kIGFsbCBkZXNrdG9wIGFwcGxpY2F0aW9ucyBzaG91bGQgcHJvYmFibHkgdXNlIEh5YnJpZEJpbmFyaXplciBpbnN0ZWFkLlxuICAgICAqXG4gICAgICogQGF1dGhvciBkc3dpdGtpbkBnb29nbGUuY29tIChEYW5pZWwgU3dpdGtpbilcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIEdsb2JhbEhpc3RvZ3JhbUJpbmFyaXplciBleHRlbmRzIEJpbmFyaXplciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHNvdXJjZSkge1xuICAgICAgICAgICAgc3VwZXIoc291cmNlKTtcbiAgICAgICAgICAgIHRoaXMubHVtaW5hbmNlcyA9IEdsb2JhbEhpc3RvZ3JhbUJpbmFyaXplci5FTVBUWTtcbiAgICAgICAgICAgIHRoaXMuYnVja2V0cyA9IG5ldyBJbnQzMkFycmF5KEdsb2JhbEhpc3RvZ3JhbUJpbmFyaXplci5MVU1JTkFOQ0VfQlVDS0VUUyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQXBwbGllcyBzaW1wbGUgc2hhcnBlbmluZyB0byB0aGUgcm93IGRhdGEgdG8gaW1wcm92ZSBwZXJmb3JtYW5jZSBvZiB0aGUgMUQgUmVhZGVycy5cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBnZXRCbGFja1Jvdyh5IC8qaW50Ki8sIHJvdykge1xuICAgICAgICAgICAgY29uc3Qgc291cmNlID0gdGhpcy5nZXRMdW1pbmFuY2VTb3VyY2UoKTtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gc291cmNlLmdldFdpZHRoKCk7XG4gICAgICAgICAgICBpZiAocm93ID09PSB1bmRlZmluZWQgfHwgcm93ID09PSBudWxsIHx8IHJvdy5nZXRTaXplKCkgPCB3aWR0aCkge1xuICAgICAgICAgICAgICAgIHJvdyA9IG5ldyBCaXRBcnJheSh3aWR0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByb3cuY2xlYXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuaW5pdEFycmF5cyh3aWR0aCk7XG4gICAgICAgICAgICBjb25zdCBsb2NhbEx1bWluYW5jZXMgPSBzb3VyY2UuZ2V0Um93KHksIHRoaXMubHVtaW5hbmNlcyk7XG4gICAgICAgICAgICBjb25zdCBsb2NhbEJ1Y2tldHMgPSB0aGlzLmJ1Y2tldHM7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IHdpZHRoOyB4KyspIHtcbiAgICAgICAgICAgICAgICBsb2NhbEJ1Y2tldHNbKGxvY2FsTHVtaW5hbmNlc1t4XSAmIDB4ZmYpID4+IEdsb2JhbEhpc3RvZ3JhbUJpbmFyaXplci5MVU1JTkFOQ0VfU0hJRlRdKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBibGFja1BvaW50ID0gR2xvYmFsSGlzdG9ncmFtQmluYXJpemVyLmVzdGltYXRlQmxhY2tQb2ludChsb2NhbEJ1Y2tldHMpO1xuICAgICAgICAgICAgaWYgKHdpZHRoIDwgMykge1xuICAgICAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZSBmb3IgdmVyeSBzbWFsbCBpbWFnZXNcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IHdpZHRoOyB4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKChsb2NhbEx1bWluYW5jZXNbeF0gJiAweGZmKSA8IGJsYWNrUG9pbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvdy5zZXQoeCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBsZXQgbGVmdCA9IGxvY2FsTHVtaW5hbmNlc1swXSAmIDB4ZmY7XG4gICAgICAgICAgICAgICAgbGV0IGNlbnRlciA9IGxvY2FsTHVtaW5hbmNlc1sxXSAmIDB4ZmY7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeCA9IDE7IHggPCB3aWR0aCAtIDE7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByaWdodCA9IGxvY2FsTHVtaW5hbmNlc1t4ICsgMV0gJiAweGZmO1xuICAgICAgICAgICAgICAgICAgICAvLyBBIHNpbXBsZSAtMSA0IC0xIGJveCBmaWx0ZXIgd2l0aCBhIHdlaWdodCBvZiAyLlxuICAgICAgICAgICAgICAgICAgICBpZiAoKChjZW50ZXIgKiA0KSAtIGxlZnQgLSByaWdodCkgLyAyIDwgYmxhY2tQb2ludCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm93LnNldCh4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBsZWZ0ID0gY2VudGVyO1xuICAgICAgICAgICAgICAgICAgICBjZW50ZXIgPSByaWdodDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcm93O1xuICAgICAgICB9XG4gICAgICAgIC8vIERvZXMgbm90IHNoYXJwZW4gdGhlIGRhdGEsIGFzIHRoaXMgY2FsbCBpcyBpbnRlbmRlZCB0byBvbmx5IGJlIHVzZWQgYnkgMkQgUmVhZGVycy5cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBnZXRCbGFja01hdHJpeCgpIHtcbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZSA9IHRoaXMuZ2V0THVtaW5hbmNlU291cmNlKCk7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IHNvdXJjZS5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gc291cmNlLmdldEhlaWdodCgpO1xuICAgICAgICAgICAgY29uc3QgbWF0cml4ID0gbmV3IEJpdE1hdHJpeCh3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgICAgIC8vIFF1aWNrbHkgY2FsY3VsYXRlcyB0aGUgaGlzdG9ncmFtIGJ5IHNhbXBsaW5nIGZvdXIgcm93cyBmcm9tIHRoZSBpbWFnZS4gVGhpcyBwcm92ZWQgdG8gYmVcbiAgICAgICAgICAgIC8vIG1vcmUgcm9idXN0IG9uIHRoZSBibGFja2JveCB0ZXN0cyB0aGFuIHNhbXBsaW5nIGEgZGlhZ29uYWwgYXMgd2UgdXNlZCB0byBkby5cbiAgICAgICAgICAgIHRoaXMuaW5pdEFycmF5cyh3aWR0aCk7XG4gICAgICAgICAgICBjb25zdCBsb2NhbEJ1Y2tldHMgPSB0aGlzLmJ1Y2tldHM7XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMTsgeSA8IDU7IHkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJvdyA9IE1hdGguZmxvb3IoKGhlaWdodCAqIHkpIC8gNSk7XG4gICAgICAgICAgICAgICAgY29uc3QgbG9jYWxMdW1pbmFuY2VzID0gc291cmNlLmdldFJvdyhyb3csIHRoaXMubHVtaW5hbmNlcyk7XG4gICAgICAgICAgICAgICAgY29uc3QgcmlnaHQgPSBNYXRoLmZsb29yKCh3aWR0aCAqIDQpIC8gNSk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeCA9IE1hdGguZmxvb3Iod2lkdGggLyA1KTsgeCA8IHJpZ2h0OyB4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGl4ZWwgPSBsb2NhbEx1bWluYW5jZXNbeF0gJiAweGZmO1xuICAgICAgICAgICAgICAgICAgICBsb2NhbEJ1Y2tldHNbcGl4ZWwgPj4gR2xvYmFsSGlzdG9ncmFtQmluYXJpemVyLkxVTUlOQU5DRV9TSElGVF0rKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBibGFja1BvaW50ID0gR2xvYmFsSGlzdG9ncmFtQmluYXJpemVyLmVzdGltYXRlQmxhY2tQb2ludChsb2NhbEJ1Y2tldHMpO1xuICAgICAgICAgICAgLy8gV2UgZGVsYXkgcmVhZGluZyB0aGUgZW50aXJlIGltYWdlIGx1bWluYW5jZSB1bnRpbCB0aGUgYmxhY2sgcG9pbnQgZXN0aW1hdGlvbiBzdWNjZWVkcy5cbiAgICAgICAgICAgIC8vIEFsdGhvdWdoIHdlIGVuZCB1cCByZWFkaW5nIGZvdXIgcm93cyB0d2ljZSwgaXQgaXMgY29uc2lzdGVudCB3aXRoIG91ciBtb3R0byBvZlxuICAgICAgICAgICAgLy8gXCJmYWlsIHF1aWNrbHlcIiB3aGljaCBpcyBuZWNlc3NhcnkgZm9yIGNvbnRpbnVvdXMgc2Nhbm5pbmcuXG4gICAgICAgICAgICBjb25zdCBsb2NhbEx1bWluYW5jZXMgPSBzb3VyY2UuZ2V0TWF0cml4KCk7XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0geSAqIHdpZHRoO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgd2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwaXhlbCA9IGxvY2FsTHVtaW5hbmNlc1tvZmZzZXQgKyB4XSAmIDB4ZmY7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwaXhlbCA8IGJsYWNrUG9pbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXQoeCwgeSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWF0cml4O1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgY3JlYXRlQmluYXJpemVyKHNvdXJjZSkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBHbG9iYWxIaXN0b2dyYW1CaW5hcml6ZXIoc291cmNlKTtcbiAgICAgICAgfVxuICAgICAgICBpbml0QXJyYXlzKGx1bWluYW5jZVNpemUgLyppbnQqLykge1xuICAgICAgICAgICAgaWYgKHRoaXMubHVtaW5hbmNlcy5sZW5ndGggPCBsdW1pbmFuY2VTaXplKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sdW1pbmFuY2VzID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KGx1bWluYW5jZVNpemUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYnVja2V0cyA9IHRoaXMuYnVja2V0cztcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgR2xvYmFsSGlzdG9ncmFtQmluYXJpemVyLkxVTUlOQU5DRV9CVUNLRVRTOyB4KyspIHtcbiAgICAgICAgICAgICAgICBidWNrZXRzW3hdID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZXN0aW1hdGVCbGFja1BvaW50KGJ1Y2tldHMpIHtcbiAgICAgICAgICAgIC8vIEZpbmQgdGhlIHRhbGxlc3QgcGVhayBpbiB0aGUgaGlzdG9ncmFtLlxuICAgICAgICAgICAgY29uc3QgbnVtQnVja2V0cyA9IGJ1Y2tldHMubGVuZ3RoO1xuICAgICAgICAgICAgbGV0IG1heEJ1Y2tldENvdW50ID0gMDtcbiAgICAgICAgICAgIGxldCBmaXJzdFBlYWsgPSAwO1xuICAgICAgICAgICAgbGV0IGZpcnN0UGVha1NpemUgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCBudW1CdWNrZXRzOyB4KyspIHtcbiAgICAgICAgICAgICAgICBpZiAoYnVja2V0c1t4XSA+IGZpcnN0UGVha1NpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgZmlyc3RQZWFrID0geDtcbiAgICAgICAgICAgICAgICAgICAgZmlyc3RQZWFrU2l6ZSA9IGJ1Y2tldHNbeF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChidWNrZXRzW3hdID4gbWF4QnVja2V0Q291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgbWF4QnVja2V0Q291bnQgPSBidWNrZXRzW3hdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEZpbmQgdGhlIHNlY29uZC10YWxsZXN0IHBlYWsgd2hpY2ggaXMgc29tZXdoYXQgZmFyIGZyb20gdGhlIHRhbGxlc3QgcGVhay5cbiAgICAgICAgICAgIGxldCBzZWNvbmRQZWFrID0gMDtcbiAgICAgICAgICAgIGxldCBzZWNvbmRQZWFrU2NvcmUgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCBudW1CdWNrZXRzOyB4KyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkaXN0YW5jZVRvQmlnZ2VzdCA9IHggLSBmaXJzdFBlYWs7XG4gICAgICAgICAgICAgICAgLy8gRW5jb3VyYWdlIG1vcmUgZGlzdGFudCBzZWNvbmQgcGVha3MgYnkgbXVsdGlwbHlpbmcgYnkgc3F1YXJlIG9mIGRpc3RhbmNlLlxuICAgICAgICAgICAgICAgIGNvbnN0IHNjb3JlID0gYnVja2V0c1t4XSAqIGRpc3RhbmNlVG9CaWdnZXN0ICogZGlzdGFuY2VUb0JpZ2dlc3Q7XG4gICAgICAgICAgICAgICAgaWYgKHNjb3JlID4gc2Vjb25kUGVha1Njb3JlKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlY29uZFBlYWsgPSB4O1xuICAgICAgICAgICAgICAgICAgICBzZWNvbmRQZWFrU2NvcmUgPSBzY29yZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgZmlyc3RQZWFrIGNvcnJlc3BvbmRzIHRvIHRoZSBibGFjayBwZWFrLlxuICAgICAgICAgICAgaWYgKGZpcnN0UGVhayA+IHNlY29uZFBlYWspIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0ZW1wID0gZmlyc3RQZWFrO1xuICAgICAgICAgICAgICAgIGZpcnN0UGVhayA9IHNlY29uZFBlYWs7XG4gICAgICAgICAgICAgICAgc2Vjb25kUGVhayA9IHRlbXA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBpcyB0b28gbGl0dGxlIGNvbnRyYXN0IGluIHRoZSBpbWFnZSB0byBwaWNrIGEgbWVhbmluZ2Z1bCBibGFjayBwb2ludCwgdGhyb3cgcmF0aGVyXG4gICAgICAgICAgICAvLyB0aGFuIHdhc3RlIHRpbWUgdHJ5aW5nIHRvIGRlY29kZSB0aGUgaW1hZ2UsIGFuZCByaXNrIGZhbHNlIHBvc2l0aXZlcy5cbiAgICAgICAgICAgIGlmIChzZWNvbmRQZWFrIC0gZmlyc3RQZWFrIDw9IG51bUJ1Y2tldHMgLyAxNikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRmluZCBhIHZhbGxleSBiZXR3ZWVuIHRoZW0gdGhhdCBpcyBsb3cgYW5kIGNsb3NlciB0byB0aGUgd2hpdGUgcGVhay5cbiAgICAgICAgICAgIGxldCBiZXN0VmFsbGV5ID0gc2Vjb25kUGVhayAtIDE7XG4gICAgICAgICAgICBsZXQgYmVzdFZhbGxleVNjb3JlID0gLTE7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gc2Vjb25kUGVhayAtIDE7IHggPiBmaXJzdFBlYWs7IHgtLSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZyb21GaXJzdCA9IHggLSBmaXJzdFBlYWs7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2NvcmUgPSBmcm9tRmlyc3QgKiBmcm9tRmlyc3QgKiAoc2Vjb25kUGVhayAtIHgpICogKG1heEJ1Y2tldENvdW50IC0gYnVja2V0c1t4XSk7XG4gICAgICAgICAgICAgICAgaWYgKHNjb3JlID4gYmVzdFZhbGxleVNjb3JlKSB7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RWYWxsZXkgPSB4O1xuICAgICAgICAgICAgICAgICAgICBiZXN0VmFsbGV5U2NvcmUgPSBzY29yZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYmVzdFZhbGxleSA8PCBHbG9iYWxIaXN0b2dyYW1CaW5hcml6ZXIuTFVNSU5BTkNFX1NISUZUO1xuICAgICAgICB9XG4gICAgfVxuICAgIEdsb2JhbEhpc3RvZ3JhbUJpbmFyaXplci5MVU1JTkFOQ0VfQklUUyA9IDU7XG4gICAgR2xvYmFsSGlzdG9ncmFtQmluYXJpemVyLkxVTUlOQU5DRV9TSElGVCA9IDggLSBHbG9iYWxIaXN0b2dyYW1CaW5hcml6ZXIuTFVNSU5BTkNFX0JJVFM7XG4gICAgR2xvYmFsSGlzdG9ncmFtQmluYXJpemVyLkxVTUlOQU5DRV9CVUNLRVRTID0gMSA8PCBHbG9iYWxIaXN0b2dyYW1CaW5hcml6ZXIuTFVNSU5BTkNFX0JJVFM7XG4gICAgR2xvYmFsSGlzdG9ncmFtQmluYXJpemVyLkVNUFRZID0gVWludDhDbGFtcGVkQXJyYXkuZnJvbShbMF0pO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwOSBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiBUaGlzIGNsYXNzIGltcGxlbWVudHMgYSBsb2NhbCB0aHJlc2hvbGRpbmcgYWxnb3JpdGhtLCB3aGljaCB3aGlsZSBzbG93ZXIgdGhhbiB0aGVcbiAgICAgKiBHbG9iYWxIaXN0b2dyYW1CaW5hcml6ZXIsIGlzIGZhaXJseSBlZmZpY2llbnQgZm9yIHdoYXQgaXQgZG9lcy4gSXQgaXMgZGVzaWduZWQgZm9yXG4gICAgICogaGlnaCBmcmVxdWVuY3kgaW1hZ2VzIG9mIGJhcmNvZGVzIHdpdGggYmxhY2sgZGF0YSBvbiB3aGl0ZSBiYWNrZ3JvdW5kcy4gRm9yIHRoaXMgYXBwbGljYXRpb24sXG4gICAgICogaXQgZG9lcyBhIG11Y2ggYmV0dGVyIGpvYiB0aGFuIGEgZ2xvYmFsIGJsYWNrcG9pbnQgd2l0aCBzZXZlcmUgc2hhZG93cyBhbmQgZ3JhZGllbnRzLlxuICAgICAqIEhvd2V2ZXIgaXQgdGVuZHMgdG8gcHJvZHVjZSBhcnRpZmFjdHMgb24gbG93ZXIgZnJlcXVlbmN5IGltYWdlcyBhbmQgaXMgdGhlcmVmb3JlIG5vdFxuICAgICAqIGEgZ29vZCBnZW5lcmFsIHB1cnBvc2UgYmluYXJpemVyIGZvciB1c2VzIG91dHNpZGUgWlhpbmcuXG4gICAgICpcbiAgICAgKiBUaGlzIGNsYXNzIGV4dGVuZHMgR2xvYmFsSGlzdG9ncmFtQmluYXJpemVyLCB1c2luZyB0aGUgb2xkZXIgaGlzdG9ncmFtIGFwcHJvYWNoIGZvciAxRCByZWFkZXJzLFxuICAgICAqIGFuZCB0aGUgbmV3ZXIgbG9jYWwgYXBwcm9hY2ggZm9yIDJEIHJlYWRlcnMuIDFEIGRlY29kaW5nIHVzaW5nIGEgcGVyLXJvdyBoaXN0b2dyYW0gaXMgYWxyZWFkeVxuICAgICAqIGluaGVyZW50bHkgbG9jYWwsIGFuZCBvbmx5IGZhaWxzIGZvciBob3Jpem9udGFsIGdyYWRpZW50cy4gV2UgY2FuIHJldmlzaXQgdGhhdCBwcm9ibGVtIGxhdGVyLFxuICAgICAqIGJ1dCBmb3Igbm93IGl0IHdhcyBub3QgYSB3aW4gdG8gdXNlIGxvY2FsIGJsb2NrcyBmb3IgMUQuXG4gICAgICpcbiAgICAgKiBUaGlzIEJpbmFyaXplciBpcyB0aGUgZGVmYXVsdCBmb3IgdGhlIHVuaXQgdGVzdHMgYW5kIHRoZSByZWNvbW1lbmRlZCBjbGFzcyBmb3IgbGlicmFyeSB1c2Vycy5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pXG4gICAgICovXG4gICAgY2xhc3MgSHlicmlkQmluYXJpemVyIGV4dGVuZHMgR2xvYmFsSGlzdG9ncmFtQmluYXJpemVyIHtcbiAgICAgICAgY29uc3RydWN0b3Ioc291cmNlKSB7XG4gICAgICAgICAgICBzdXBlcihzb3VyY2UpO1xuICAgICAgICAgICAgdGhpcy5tYXRyaXggPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDYWxjdWxhdGVzIHRoZSBmaW5hbCBCaXRNYXRyaXggb25jZSBmb3IgYWxsIHJlcXVlc3RzLiBUaGlzIGNvdWxkIGJlIGNhbGxlZCBvbmNlIGZyb20gdGhlXG4gICAgICAgICAqIGNvbnN0cnVjdG9yIGluc3RlYWQsIGJ1dCB0aGVyZSBhcmUgc29tZSBhZHZhbnRhZ2VzIHRvIGRvaW5nIGl0IGxhemlseSwgc3VjaCBhcyBtYWtpbmdcbiAgICAgICAgICogcHJvZmlsaW5nIGVhc2llciwgYW5kIG5vdCBkb2luZyBoZWF2eSBsaWZ0aW5nIHdoZW4gY2FsbGVycyBkb24ndCBleHBlY3QgaXQuXG4gICAgICAgICAqL1xuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGdldEJsYWNrTWF0cml4KCkge1xuICAgICAgICAgICAgaWYgKHRoaXMubWF0cml4ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubWF0cml4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgc291cmNlID0gdGhpcy5nZXRMdW1pbmFuY2VTb3VyY2UoKTtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gc291cmNlLmdldFdpZHRoKCk7XG4gICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBzb3VyY2UuZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICBpZiAod2lkdGggPj0gSHlicmlkQmluYXJpemVyLk1JTklNVU1fRElNRU5TSU9OICYmIGhlaWdodCA+PSBIeWJyaWRCaW5hcml6ZXIuTUlOSU1VTV9ESU1FTlNJT04pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBsdW1pbmFuY2VzID0gc291cmNlLmdldE1hdHJpeCgpO1xuICAgICAgICAgICAgICAgIGxldCBzdWJXaWR0aCA9IHdpZHRoID4+IEh5YnJpZEJpbmFyaXplci5CTE9DS19TSVpFX1BPV0VSO1xuICAgICAgICAgICAgICAgIGlmICgod2lkdGggJiBIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRV9NQVNLKSAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBzdWJXaWR0aCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgc3ViSGVpZ2h0ID0gaGVpZ2h0ID4+IEh5YnJpZEJpbmFyaXplci5CTE9DS19TSVpFX1BPV0VSO1xuICAgICAgICAgICAgICAgIGlmICgoaGVpZ2h0ICYgSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkVfTUFTSykgIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgc3ViSGVpZ2h0Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGJsYWNrUG9pbnRzID0gSHlicmlkQmluYXJpemVyLmNhbGN1bGF0ZUJsYWNrUG9pbnRzKGx1bWluYW5jZXMsIHN1YldpZHRoLCBzdWJIZWlnaHQsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgICAgIGNvbnN0IG5ld01hdHJpeCA9IG5ldyBCaXRNYXRyaXgod2lkdGgsIGhlaWdodCk7XG4gICAgICAgICAgICAgICAgSHlicmlkQmluYXJpemVyLmNhbGN1bGF0ZVRocmVzaG9sZEZvckJsb2NrKGx1bWluYW5jZXMsIHN1YldpZHRoLCBzdWJIZWlnaHQsIHdpZHRoLCBoZWlnaHQsIGJsYWNrUG9pbnRzLCBuZXdNYXRyaXgpO1xuICAgICAgICAgICAgICAgIHRoaXMubWF0cml4ID0gbmV3TWF0cml4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIGltYWdlIGlzIHRvbyBzbWFsbCwgZmFsbCBiYWNrIHRvIHRoZSBnbG9iYWwgaGlzdG9ncmFtIGFwcHJvYWNoLlxuICAgICAgICAgICAgICAgIHRoaXMubWF0cml4ID0gc3VwZXIuZ2V0QmxhY2tNYXRyaXgoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1hdHJpeDtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGNyZWF0ZUJpbmFyaXplcihzb3VyY2UpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgSHlicmlkQmluYXJpemVyKHNvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEZvciBlYWNoIGJsb2NrIGluIHRoZSBpbWFnZSwgY2FsY3VsYXRlIHRoZSBhdmVyYWdlIGJsYWNrIHBvaW50IHVzaW5nIGEgNXg1IGdyaWRcbiAgICAgICAgICogb2YgdGhlIGJsb2NrcyBhcm91bmQgaXQuIEFsc28gaGFuZGxlcyB0aGUgY29ybmVyIGNhc2VzIChmcmFjdGlvbmFsIGJsb2NrcyBhcmUgY29tcHV0ZWQgYmFzZWRcbiAgICAgICAgICogb24gdGhlIGxhc3QgcGl4ZWxzIGluIHRoZSByb3cvY29sdW1uIHdoaWNoIGFyZSBhbHNvIHVzZWQgaW4gdGhlIHByZXZpb3VzIGJsb2NrKS5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBjYWxjdWxhdGVUaHJlc2hvbGRGb3JCbG9jayhsdW1pbmFuY2VzLCBzdWJXaWR0aCAvKmludCovLCBzdWJIZWlnaHQgLyppbnQqLywgd2lkdGggLyppbnQqLywgaGVpZ2h0IC8qaW50Ki8sIGJsYWNrUG9pbnRzLCBtYXRyaXgpIHtcbiAgICAgICAgICAgIGNvbnN0IG1heFlPZmZzZXQgPSBoZWlnaHQgLSBIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRTtcbiAgICAgICAgICAgIGNvbnN0IG1heFhPZmZzZXQgPSB3aWR0aCAtIEh5YnJpZEJpbmFyaXplci5CTE9DS19TSVpFO1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCBzdWJIZWlnaHQ7IHkrKykge1xuICAgICAgICAgICAgICAgIGxldCB5b2Zmc2V0ID0geSA8PCBIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRV9QT1dFUjtcbiAgICAgICAgICAgICAgICBpZiAoeW9mZnNldCA+IG1heFlPZmZzZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgeW9mZnNldCA9IG1heFlPZmZzZXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IHRvcCA9IEh5YnJpZEJpbmFyaXplci5jYXAoeSwgMiwgc3ViSGVpZ2h0IC0gMyk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCBzdWJXaWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCB4b2Zmc2V0ID0geCA8PCBIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRV9QT1dFUjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHhvZmZzZXQgPiBtYXhYT2Zmc2V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB4b2Zmc2V0ID0gbWF4WE9mZnNldDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb25zdCBsZWZ0ID0gSHlicmlkQmluYXJpemVyLmNhcCh4LCAyLCBzdWJXaWR0aCAtIDMpO1xuICAgICAgICAgICAgICAgICAgICBsZXQgc3VtID0gMDtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgeiA9IC0yOyB6IDw9IDI7IHorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYmxhY2tSb3cgPSBibGFja1BvaW50c1t0b3AgKyB6XTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1bSArPSBibGFja1Jvd1tsZWZ0IC0gMl0gKyBibGFja1Jvd1tsZWZ0IC0gMV0gKyBibGFja1Jvd1tsZWZ0XSArIGJsYWNrUm93W2xlZnQgKyAxXSArIGJsYWNrUm93W2xlZnQgKyAyXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb25zdCBhdmVyYWdlID0gc3VtIC8gMjU7XG4gICAgICAgICAgICAgICAgICAgIEh5YnJpZEJpbmFyaXplci50aHJlc2hvbGRCbG9jayhsdW1pbmFuY2VzLCB4b2Zmc2V0LCB5b2Zmc2V0LCBhdmVyYWdlLCB3aWR0aCwgbWF0cml4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGNhcCh2YWx1ZSAvKmludCovLCBtaW4gLyppbnQqLywgbWF4IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZSA8IG1pbiA/IG1pbiA6IHZhbHVlID4gbWF4ID8gbWF4IDogdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEFwcGxpZXMgYSBzaW5nbGUgdGhyZXNob2xkIHRvIGEgYmxvY2sgb2YgcGl4ZWxzLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIHRocmVzaG9sZEJsb2NrKGx1bWluYW5jZXMsIHhvZmZzZXQgLyppbnQqLywgeW9mZnNldCAvKmludCovLCB0aHJlc2hvbGQgLyppbnQqLywgc3RyaWRlIC8qaW50Ki8sIG1hdHJpeCkge1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDAsIG9mZnNldCA9IHlvZmZzZXQgKiBzdHJpZGUgKyB4b2Zmc2V0OyB5IDwgSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkU7IHkrKywgb2Zmc2V0ICs9IHN0cmlkZSkge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkU7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICAvLyBDb21wYXJpc29uIG5lZWRzIHRvIGJlIDw9IHNvIHRoYXQgYmxhY2sgPT0gMCBwaXhlbHMgYXJlIGJsYWNrIGV2ZW4gaWYgdGhlIHRocmVzaG9sZCBpcyAwLlxuICAgICAgICAgICAgICAgICAgICBpZiAoKGx1bWluYW5jZXNbb2Zmc2V0ICsgeF0gJiAweEZGKSA8PSB0aHJlc2hvbGQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXQoeG9mZnNldCArIHgsIHlvZmZzZXQgKyB5KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ2FsY3VsYXRlcyBhIHNpbmdsZSBibGFjayBwb2ludCBmb3IgZWFjaCBibG9jayBvZiBwaXhlbHMgYW5kIHNhdmVzIGl0IGF3YXkuXG4gICAgICAgICAqIFNlZSB0aGUgZm9sbG93aW5nIHRocmVhZCBmb3IgYSBkaXNjdXNzaW9uIG9mIHRoaXMgYWxnb3JpdGhtOlxuICAgICAgICAgKiAgaHR0cDovL2dyb3Vwcy5nb29nbGUuY29tL2dyb3VwL3p4aW5nL2Jyb3dzZV90aHJlYWQvdGhyZWFkL2QwNmVmYTJjMzVhN2RkYzBcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBjYWxjdWxhdGVCbGFja1BvaW50cyhsdW1pbmFuY2VzLCBzdWJXaWR0aCAvKmludCovLCBzdWJIZWlnaHQgLyppbnQqLywgd2lkdGggLyppbnQqLywgaGVpZ2h0IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IG1heFlPZmZzZXQgPSBoZWlnaHQgLSBIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRTtcbiAgICAgICAgICAgIGNvbnN0IG1heFhPZmZzZXQgPSB3aWR0aCAtIEh5YnJpZEJpbmFyaXplci5CTE9DS19TSVpFO1xuICAgICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOndoaXRlc3BhY2VcbiAgICAgICAgICAgIGNvbnN0IGJsYWNrUG9pbnRzID0gbmV3IEFycmF5KHN1YkhlaWdodCk7IC8vIHN1YldpZHRoXG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IHN1YkhlaWdodDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgYmxhY2tQb2ludHNbeV0gPSBuZXcgSW50MzJBcnJheShzdWJXaWR0aCk7XG4gICAgICAgICAgICAgICAgbGV0IHlvZmZzZXQgPSB5IDw8IEh5YnJpZEJpbmFyaXplci5CTE9DS19TSVpFX1BPV0VSO1xuICAgICAgICAgICAgICAgIGlmICh5b2Zmc2V0ID4gbWF4WU9mZnNldCkge1xuICAgICAgICAgICAgICAgICAgICB5b2Zmc2V0ID0gbWF4WU9mZnNldDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCBzdWJXaWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCB4b2Zmc2V0ID0geCA8PCBIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRV9QT1dFUjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHhvZmZzZXQgPiBtYXhYT2Zmc2V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB4b2Zmc2V0ID0gbWF4WE9mZnNldDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBsZXQgc3VtID0gMDtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG1pbiA9IDB4RkY7XG4gICAgICAgICAgICAgICAgICAgIGxldCBtYXggPSAwO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCB5eSA9IDAsIG9mZnNldCA9IHlvZmZzZXQgKiB3aWR0aCArIHhvZmZzZXQ7IHl5IDwgSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkU7IHl5KyssIG9mZnNldCArPSB3aWR0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgeHggPSAwOyB4eCA8IEh5YnJpZEJpbmFyaXplci5CTE9DS19TSVpFOyB4eCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcGl4ZWwgPSBsdW1pbmFuY2VzW29mZnNldCArIHh4XSAmIDB4RkY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtICs9IHBpeGVsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0aWxsIGxvb2tpbmcgZm9yIGdvb2QgY29udHJhc3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocGl4ZWwgPCBtaW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluID0gcGl4ZWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwaXhlbCA+IG1heCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXggPSBwaXhlbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzaG9ydC1jaXJjdWl0IG1pbi9tYXggdGVzdHMgb25jZSBkeW5hbWljIHJhbmdlIGlzIG1ldFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1heCAtIG1pbiA+IEh5YnJpZEJpbmFyaXplci5NSU5fRFlOQU1JQ19SQU5HRSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZpbmlzaCB0aGUgcmVzdCBvZiB0aGUgcm93cyBxdWlja2x5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh5eSsrLCBvZmZzZXQgKz0gd2lkdGg7IHl5IDwgSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkU7IHl5KyssIG9mZnNldCArPSB3aWR0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCB4eCA9IDA7IHh4IDwgSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkU7IHh4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1bSArPSBsdW1pbmFuY2VzW29mZnNldCArIHh4XSAmIDB4RkY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGRlZmF1bHQgZXN0aW1hdGUgaXMgdGhlIGF2ZXJhZ2Ugb2YgdGhlIHZhbHVlcyBpbiB0aGUgYmxvY2suXG4gICAgICAgICAgICAgICAgICAgIGxldCBhdmVyYWdlID0gc3VtID4+IChIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRV9QT1dFUiAqIDIpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobWF4IC0gbWluIDw9IEh5YnJpZEJpbmFyaXplci5NSU5fRFlOQU1JQ19SQU5HRSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgdmFyaWF0aW9uIHdpdGhpbiB0aGUgYmxvY2sgaXMgbG93LCBhc3N1bWUgdGhpcyBpcyBhIGJsb2NrIHdpdGggb25seSBsaWdodCBvciBvbmx5XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBkYXJrIHBpeGVscy4gSW4gdGhhdCBjYXNlIHdlIGRvIG5vdCB3YW50IHRvIHVzZSB0aGUgYXZlcmFnZSwgYXMgaXQgd291bGQgZGl2aWRlIHRoaXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxvdyBjb250cmFzdCBhcmVhIGludG8gYmxhY2sgYW5kIHdoaXRlIHBpeGVscywgZXNzZW50aWFsbHkgY3JlYXRpbmcgZGF0YSBvdXQgb2Ygbm9pc2UuXG4gICAgICAgICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGRlZmF1bHQgYXNzdW1wdGlvbiBpcyB0aGF0IHRoZSBibG9jayBpcyBsaWdodC9iYWNrZ3JvdW5kLiBTaW5jZSBubyBlc3RpbWF0ZSBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBsZXZlbCBvZiBkYXJrIHBpeGVscyBleGlzdHMgbG9jYWxseSwgdXNlIGhhbGYgdGhlIG1pbiBmb3IgdGhlIGJsb2NrLlxuICAgICAgICAgICAgICAgICAgICAgICAgYXZlcmFnZSA9IG1pbiAvIDI7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoeSA+IDAgJiYgeCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDb3JyZWN0IHRoZSBcIndoaXRlIGJhY2tncm91bmRcIiBhc3N1bXB0aW9uIGZvciBibG9ja3MgdGhhdCBoYXZlIG5laWdoYm9ycyBieSBjb21wYXJpbmdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgcGl4ZWxzIGluIHRoaXMgYmxvY2sgdG8gdGhlIHByZXZpb3VzbHkgY2FsY3VsYXRlZCBibGFjayBwb2ludHMuIFRoaXMgaXMgYmFzZWQgb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZmFjdCB0aGF0IGRhcmsgYmFyY29kZSBzeW1ib2xvZ3kgaXMgYWx3YXlzIHN1cnJvdW5kZWQgYnkgc29tZSBhbW91bnQgb2YgbGlnaHRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBiYWNrZ3JvdW5kIGZvciB3aGljaCByZWFzb25hYmxlIGJsYWNrIHBvaW50IGVzdGltYXRlcyB3ZXJlIG1hZGUuIFRoZSBicCBlc3RpbWF0ZWQgYXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgYm91bmRhcmllcyBpcyB1c2VkIGZvciB0aGUgaW50ZXJpb3IuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlIChtaW4gPCBicCkgaXMgYXJiaXRyYXJ5IGJ1dCB3b3JrcyBiZXR0ZXIgdGhhbiBvdGhlciBoZXVyaXN0aWNzIHRoYXQgd2VyZSB0cmllZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhdmVyYWdlTmVpZ2hib3JCbGFja1BvaW50ID0gKGJsYWNrUG9pbnRzW3kgLSAxXVt4XSArICgyICogYmxhY2tQb2ludHNbeV1beCAtIDFdKSArIGJsYWNrUG9pbnRzW3kgLSAxXVt4IC0gMV0pIC8gNDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWluIDwgYXZlcmFnZU5laWdoYm9yQmxhY2tQb2ludCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdmVyYWdlID0gYXZlcmFnZU5laWdoYm9yQmxhY2tQb2ludDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYmxhY2tQb2ludHNbeV1beF0gPSBhdmVyYWdlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBibGFja1BvaW50cztcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBUaGlzIGNsYXNzIHVzZXMgNXg1IGJsb2NrcyB0byBjb21wdXRlIGxvY2FsIGx1bWluYW5jZSwgd2hlcmUgZWFjaCBibG9jayBpcyA4eDggcGl4ZWxzLlxuICAgIC8vIFNvIHRoaXMgaXMgdGhlIHNtYWxsZXN0IGRpbWVuc2lvbiBpbiBlYWNoIGF4aXMgd2UgY2FuIGFjY2VwdC5cbiAgICBIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRV9QT1dFUiA9IDM7XG4gICAgSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkUgPSAxIDw8IEh5YnJpZEJpbmFyaXplci5CTE9DS19TSVpFX1BPV0VSOyAvLyAuLi4wMTAwLi4uMDBcbiAgICBIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRV9NQVNLID0gSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkUgLSAxOyAvLyAuLi4wMDExLi4uMTFcbiAgICBIeWJyaWRCaW5hcml6ZXIuTUlOSU1VTV9ESU1FTlNJT04gPSBIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRSAqIDU7XG4gICAgSHlicmlkQmluYXJpemVyLk1JTl9EWU5BTUlDX1JBTkdFID0gMjQ7XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA5IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qbmFtZXNwYWNlIGNvbS5nb29nbGUuenhpbmcgeyovXG4gICAgLyoqXG4gICAgICogVGhlIHB1cnBvc2Ugb2YgdGhpcyBjbGFzcyBoaWVyYXJjaHkgaXMgdG8gYWJzdHJhY3QgZGlmZmVyZW50IGJpdG1hcCBpbXBsZW1lbnRhdGlvbnMgYWNyb3NzXG4gICAgICogcGxhdGZvcm1zIGludG8gYSBzdGFuZGFyZCBpbnRlcmZhY2UgZm9yIHJlcXVlc3RpbmcgZ3JleXNjYWxlIGx1bWluYW5jZSB2YWx1ZXMuIFRoZSBpbnRlcmZhY2VcbiAgICAgKiBvbmx5IHByb3ZpZGVzIGltbXV0YWJsZSBtZXRob2RzOyB0aGVyZWZvcmUgY3JvcCBhbmQgcm90YXRpb24gY3JlYXRlIGNvcGllcy4gVGhpcyBpcyB0byBlbnN1cmVcbiAgICAgKiB0aGF0IG9uZSBSZWFkZXIgZG9lcyBub3QgbW9kaWZ5IHRoZSBvcmlnaW5hbCBsdW1pbmFuY2Ugc291cmNlIGFuZCBsZWF2ZSBpdCBpbiBhbiB1bmtub3duIHN0YXRlXG4gICAgICogZm9yIG90aGVyIFJlYWRlcnMgaW4gdGhlIGNoYWluLlxuICAgICAqXG4gICAgICogQGF1dGhvciBkc3dpdGtpbkBnb29nbGUuY29tIChEYW5pZWwgU3dpdGtpbilcbiAgICAgKi9cbiAgICBjbGFzcyBMdW1pbmFuY2VTb3VyY2Uge1xuICAgICAgICBjb25zdHJ1Y3Rvcih3aWR0aCAvKmludCovLCBoZWlnaHQgLyppbnQqLykge1xuICAgICAgICAgICAgdGhpcy53aWR0aCA9IHdpZHRoO1xuICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gVGhlIHdpZHRoIG9mIHRoZSBiaXRtYXAuXG4gICAgICAgICAqL1xuICAgICAgICBnZXRXaWR0aCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndpZHRoO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIFRoZSBoZWlnaHQgb2YgdGhlIGJpdG1hcC5cbiAgICAgICAgICovXG4gICAgICAgIGdldEhlaWdodCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmhlaWdodDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoaXMgc3ViY2xhc3Mgc3VwcG9ydHMgY3JvcHBpbmcuXG4gICAgICAgICAqL1xuICAgICAgICBpc0Nyb3BTdXBwb3J0ZWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldHVybnMgYSBuZXcgb2JqZWN0IHdpdGggY3JvcHBlZCBpbWFnZSBkYXRhLiBJbXBsZW1lbnRhdGlvbnMgbWF5IGtlZXAgYSByZWZlcmVuY2UgdG8gdGhlXG4gICAgICAgICAqIG9yaWdpbmFsIGRhdGEgcmF0aGVyIHRoYW4gYSBjb3B5LiBPbmx5IGNhbGxhYmxlIGlmIGlzQ3JvcFN1cHBvcnRlZCgpIGlzIHRydWUuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBsZWZ0IFRoZSBsZWZ0IGNvb3JkaW5hdGUsIHdoaWNoIG11c3QgYmUgaW4gWzAsZ2V0V2lkdGgoKSlcbiAgICAgICAgICogQHBhcmFtIHRvcCBUaGUgdG9wIGNvb3JkaW5hdGUsIHdoaWNoIG11c3QgYmUgaW4gWzAsZ2V0SGVpZ2h0KCkpXG4gICAgICAgICAqIEBwYXJhbSB3aWR0aCBUaGUgd2lkdGggb2YgdGhlIHJlY3RhbmdsZSB0byBjcm9wLlxuICAgICAgICAgKiBAcGFyYW0gaGVpZ2h0IFRoZSBoZWlnaHQgb2YgdGhlIHJlY3RhbmdsZSB0byBjcm9wLlxuICAgICAgICAgKiBAcmV0dXJuIEEgY3JvcHBlZCB2ZXJzaW9uIG9mIHRoaXMgb2JqZWN0LlxuICAgICAgICAgKi9cbiAgICAgICAgY3JvcChsZWZ0IC8qaW50Ki8sIHRvcCAvKmludCovLCB3aWR0aCAvKmludCovLCBoZWlnaHQgLyppbnQqLykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkT3BlcmF0aW9uRXhjZXB0aW9uKCdUaGlzIGx1bWluYW5jZSBzb3VyY2UgZG9lcyBub3Qgc3VwcG9ydCBjcm9wcGluZy4nKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoaXMgc3ViY2xhc3Mgc3VwcG9ydHMgY291bnRlci1jbG9ja3dpc2Ugcm90YXRpb24uXG4gICAgICAgICAqL1xuICAgICAgICBpc1JvdGF0ZVN1cHBvcnRlZCgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogUmV0dXJucyBhIG5ldyBvYmplY3Qgd2l0aCByb3RhdGVkIGltYWdlIGRhdGEgYnkgOTAgZGVncmVlcyBjb3VudGVyY2xvY2t3aXNlLlxuICAgICAgICAgKiBPbmx5IGNhbGxhYmxlIGlmIHtAbGluayAjaXNSb3RhdGVTdXBwb3J0ZWQoKX0gaXMgdHJ1ZS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiBBIHJvdGF0ZWQgdmVyc2lvbiBvZiB0aGlzIG9iamVjdC5cbiAgICAgICAgICovXG4gICAgICAgIHJvdGF0ZUNvdW50ZXJDbG9ja3dpc2UoKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVW5zdXBwb3J0ZWRPcGVyYXRpb25FeGNlcHRpb24oJ1RoaXMgbHVtaW5hbmNlIHNvdXJjZSBkb2VzIG5vdCBzdXBwb3J0IHJvdGF0aW9uIGJ5IDkwIGRlZ3JlZXMuJyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldHVybnMgYSBuZXcgb2JqZWN0IHdpdGggcm90YXRlZCBpbWFnZSBkYXRhIGJ5IDQ1IGRlZ3JlZXMgY291bnRlcmNsb2Nrd2lzZS5cbiAgICAgICAgICogT25seSBjYWxsYWJsZSBpZiB7QGxpbmsgI2lzUm90YXRlU3VwcG9ydGVkKCl9IGlzIHRydWUuXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gQSByb3RhdGVkIHZlcnNpb24gb2YgdGhpcyBvYmplY3QuXG4gICAgICAgICAqL1xuICAgICAgICByb3RhdGVDb3VudGVyQ2xvY2t3aXNlNDUoKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVW5zdXBwb3J0ZWRPcGVyYXRpb25FeGNlcHRpb24oJ1RoaXMgbHVtaW5hbmNlIHNvdXJjZSBkb2VzIG5vdCBzdXBwb3J0IHJvdGF0aW9uIGJ5IDQ1IGRlZ3JlZXMuJyk7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICB0b1N0cmluZygpIHtcbiAgICAgICAgICAgIGNvbnN0IHJvdyA9IG5ldyBVaW50OENsYW1wZWRBcnJheSh0aGlzLndpZHRoKTtcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSBuZXcgU3RyaW5nQnVpbGRlcigpO1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCB0aGlzLmhlaWdodDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc291cmNlUm93ID0gdGhpcy5nZXRSb3coeSwgcm93KTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IHRoaXMud2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBsdW1pbmFuY2UgPSBzb3VyY2VSb3dbeF0gJiAweEZGO1xuICAgICAgICAgICAgICAgICAgICBsZXQgYztcbiAgICAgICAgICAgICAgICAgICAgaWYgKGx1bWluYW5jZSA8IDB4NDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGMgPSAnIyc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobHVtaW5hbmNlIDwgMHg4MCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYyA9ICcrJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChsdW1pbmFuY2UgPCAweEMwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjID0gJy4nO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYyA9ICcgJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKGMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCdcXG4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDkgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLypuYW1lc3BhY2UgY29tLmdvb2dsZS56eGluZyB7Ki9cbiAgICAvKipcbiAgICAgKiBBIHdyYXBwZXIgaW1wbGVtZW50YXRpb24gb2Yge0BsaW5rIEx1bWluYW5jZVNvdXJjZX0gd2hpY2ggaW52ZXJ0cyB0aGUgbHVtaW5hbmNlcyBpdCByZXR1cm5zIC0tIGJsYWNrIGJlY29tZXNcbiAgICAgKiB3aGl0ZSBhbmQgdmljZSB2ZXJzYSwgYW5kIGVhY2ggdmFsdWUgYmVjb21lcyAoMjU1LXZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgSW52ZXJ0ZWRMdW1pbmFuY2VTb3VyY2UgZXh0ZW5kcyBMdW1pbmFuY2VTb3VyY2Uge1xuICAgICAgICBjb25zdHJ1Y3RvcihkZWxlZ2F0ZSkge1xuICAgICAgICAgICAgc3VwZXIoZGVsZWdhdGUuZ2V0V2lkdGgoKSwgZGVsZWdhdGUuZ2V0SGVpZ2h0KCkpO1xuICAgICAgICAgICAgdGhpcy5kZWxlZ2F0ZSA9IGRlbGVnYXRlO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgZ2V0Um93KHkgLyppbnQqLywgcm93KSB7XG4gICAgICAgICAgICBjb25zdCBzb3VyY2VSb3cgPSB0aGlzLmRlbGVnYXRlLmdldFJvdyh5LCByb3cpO1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSB0aGlzLmdldFdpZHRoKCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHdpZHRoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBzb3VyY2VSb3dbaV0gPSAvKihieXRlKSovICgyNTUgLSAoc291cmNlUm93W2ldICYgMHhGRikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHNvdXJjZVJvdztcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGdldE1hdHJpeCgpIHtcbiAgICAgICAgICAgIGNvbnN0IG1hdHJpeCA9IHRoaXMuZGVsZWdhdGUuZ2V0TWF0cml4KCk7XG4gICAgICAgICAgICBjb25zdCBsZW5ndGggPSB0aGlzLmdldFdpZHRoKCkgKiB0aGlzLmdldEhlaWdodCgpO1xuICAgICAgICAgICAgY29uc3QgaW52ZXJ0ZWRNYXRyaXggPSBuZXcgVWludDhDbGFtcGVkQXJyYXkobGVuZ3RoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpbnZlcnRlZE1hdHJpeFtpXSA9IC8qKGJ5dGUpKi8gKDI1NSAtIChtYXRyaXhbaV0gJiAweEZGKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaW52ZXJ0ZWRNYXRyaXg7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBpc0Nyb3BTdXBwb3J0ZWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWxlZ2F0ZS5pc0Nyb3BTdXBwb3J0ZWQoKTtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGNyb3AobGVmdCAvKmludCovLCB0b3AgLyppbnQqLywgd2lkdGggLyppbnQqLywgaGVpZ2h0IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgSW52ZXJ0ZWRMdW1pbmFuY2VTb3VyY2UodGhpcy5kZWxlZ2F0ZS5jcm9wKGxlZnQsIHRvcCwgd2lkdGgsIGhlaWdodCkpO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgaXNSb3RhdGVTdXBwb3J0ZWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWxlZ2F0ZS5pc1JvdGF0ZVN1cHBvcnRlZCgpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIG9yaWdpbmFsIGRlbGVnYXRlIHtAbGluayBMdW1pbmFuY2VTb3VyY2V9IHNpbmNlIGludmVydCB1bmRvZXMgaXRzZWxmXG4gICAgICAgICAqL1xuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGludmVydCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlbGVnYXRlO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgcm90YXRlQ291bnRlckNsb2Nrd2lzZSgpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgSW52ZXJ0ZWRMdW1pbmFuY2VTb3VyY2UodGhpcy5kZWxlZ2F0ZS5yb3RhdGVDb3VudGVyQ2xvY2t3aXNlKCkpO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgcm90YXRlQ291bnRlckNsb2Nrd2lzZTQ1KCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBJbnZlcnRlZEx1bWluYW5jZVNvdXJjZSh0aGlzLmRlbGVnYXRlLnJvdGF0ZUNvdW50ZXJDbG9ja3dpc2U0NSgpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBkZXByZWNhdGVkIE1vdmluZyB0byBAenhpbmcvYnJvd3NlclxuICAgICAqL1xuICAgIGNsYXNzIEhUTUxDYW52YXNFbGVtZW50THVtaW5hbmNlU291cmNlIGV4dGVuZHMgTHVtaW5hbmNlU291cmNlIHtcbiAgICAgICAgY29uc3RydWN0b3IoY2FudmFzKSB7XG4gICAgICAgICAgICBzdXBlcihjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xuICAgICAgICAgICAgdGhpcy5jYW52YXMgPSBjYW52YXM7XG4gICAgICAgICAgICB0aGlzLnRlbXBDYW52YXNFbGVtZW50ID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuYnVmZmVyID0gSFRNTENhbnZhc0VsZW1lbnRMdW1pbmFuY2VTb3VyY2UubWFrZUJ1ZmZlckZyb21DYW52YXNJbWFnZURhdGEoY2FudmFzKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgbWFrZUJ1ZmZlckZyb21DYW52YXNJbWFnZURhdGEoY2FudmFzKSB7XG4gICAgICAgICAgICBjb25zdCBpbWFnZURhdGEgPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKS5nZXRJbWFnZURhdGEoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgICAgICAgIHJldHVybiBIVE1MQ2FudmFzRWxlbWVudEx1bWluYW5jZVNvdXJjZS50b0dyYXlzY2FsZUJ1ZmZlcihpbWFnZURhdGEuZGF0YSwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgdG9HcmF5c2NhbGVCdWZmZXIoaW1hZ2VCdWZmZXIsIHdpZHRoLCBoZWlnaHQpIHtcbiAgICAgICAgICAgIGNvbnN0IGdyYXlzY2FsZUJ1ZmZlciA9IG5ldyBVaW50OENsYW1wZWRBcnJheSh3aWR0aCAqIGhlaWdodCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaiA9IDAsIGxlbmd0aCA9IGltYWdlQnVmZmVyLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSArPSA0LCBqKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgZ3JheTtcbiAgICAgICAgICAgICAgICBjb25zdCBhbHBoYSA9IGltYWdlQnVmZmVyW2kgKyAzXTtcbiAgICAgICAgICAgICAgICAvLyBUaGUgY29sb3Igb2YgZnVsbHktdHJhbnNwYXJlbnQgcGl4ZWxzIGlzIGlycmVsZXZhbnQuIFRoZXkgYXJlIG9mdGVuLCB0ZWNobmljYWxseSwgZnVsbHktdHJhbnNwYXJlbnRcbiAgICAgICAgICAgICAgICAvLyBibGFjayAoMCBhbHBoYSwgYW5kIHRoZW4gMCBSR0IpLiBUaGV5IGFyZSBvZnRlbiB1c2VkLCBvZiBjb3Vyc2UgYXMgdGhlIFwid2hpdGVcIiBhcmVhIGluIGFcbiAgICAgICAgICAgICAgICAvLyBiYXJjb2RlIGltYWdlLiBGb3JjZSBhbnkgc3VjaCBwaXhlbCB0byBiZSB3aGl0ZTpcbiAgICAgICAgICAgICAgICBpZiAoYWxwaGEgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgZ3JheSA9IDB4RkY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwaXhlbFIgPSBpbWFnZUJ1ZmZlcltpXTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGl4ZWxHID0gaW1hZ2VCdWZmZXJbaSArIDFdO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwaXhlbEIgPSBpbWFnZUJ1ZmZlcltpICsgMl07XG4gICAgICAgICAgICAgICAgICAgIC8vIC4yOTlSICsgMC41ODdHICsgMC4xMTRCIChZVVYvWUlRIGZvciBQQUwgYW5kIE5UU0MpLFxuICAgICAgICAgICAgICAgICAgICAvLyAoMzA2KlIpID4+IDEwIGlzIGFwcHJveGltYXRlbHkgZXF1YWwgdG8gUiowLjI5OSwgYW5kIHNvIG9uLlxuICAgICAgICAgICAgICAgICAgICAvLyAweDIwMCA+PiAxMCBpcyAwLjUsIGl0IGltcGxlbWVudHMgcm91bmRpbmcuXG4gICAgICAgICAgICAgICAgICAgIGdyYXkgPSAoMzA2ICogcGl4ZWxSICtcbiAgICAgICAgICAgICAgICAgICAgICAgIDYwMSAqIHBpeGVsRyArXG4gICAgICAgICAgICAgICAgICAgICAgICAxMTcgKiBwaXhlbEIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgMHgyMDApID4+IDEwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBncmF5c2NhbGVCdWZmZXJbal0gPSBncmF5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGdyYXlzY2FsZUJ1ZmZlcjtcbiAgICAgICAgfVxuICAgICAgICBnZXRSb3coeSAvKmludCovLCByb3cpIHtcbiAgICAgICAgICAgIGlmICh5IDwgMCB8fCB5ID49IHRoaXMuZ2V0SGVpZ2h0KCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdSZXF1ZXN0ZWQgcm93IGlzIG91dHNpZGUgdGhlIGltYWdlOiAnICsgeSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMuZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0ID0geSAqIHdpZHRoO1xuICAgICAgICAgICAgaWYgKHJvdyA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJvdyA9IHRoaXMuYnVmZmVyLnNsaWNlKHN0YXJ0LCBzdGFydCArIHdpZHRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChyb3cubGVuZ3RoIDwgd2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcm93ID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHdpZHRoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gVGhlIHVuZGVybHlpbmcgcmFzdGVyIG9mIGltYWdlIGNvbnNpc3RzIG9mIGJ5dGVzIHdpdGggdGhlIGx1bWluYW5jZSB2YWx1ZXNcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBjYW4gYXZvaWQgc2V0L3NsaWNlP1xuICAgICAgICAgICAgICAgIHJvdy5zZXQodGhpcy5idWZmZXIuc2xpY2Uoc3RhcnQsIHN0YXJ0ICsgd2lkdGgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByb3c7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0TWF0cml4KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYnVmZmVyO1xuICAgICAgICB9XG4gICAgICAgIGlzQ3JvcFN1cHBvcnRlZCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGNyb3AobGVmdCAvKmludCovLCB0b3AgLyppbnQqLywgd2lkdGggLyppbnQqLywgaGVpZ2h0IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHN1cGVyLmNyb3AobGVmdCwgdG9wLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGlzIGlzIGFsd2F5cyB0cnVlLCBzaW5jZSB0aGUgaW1hZ2UgaXMgYSBncmF5LXNjYWxlIGltYWdlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIHRydWVcbiAgICAgICAgICovXG4gICAgICAgIGlzUm90YXRlU3VwcG9ydGVkKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcm90YXRlQ291bnRlckNsb2Nrd2lzZSgpIHtcbiAgICAgICAgICAgIHRoaXMucm90YXRlKC05MCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICByb3RhdGVDb3VudGVyQ2xvY2t3aXNlNDUoKSB7XG4gICAgICAgICAgICB0aGlzLnJvdGF0ZSgtNDUpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0VGVtcENhbnZhc0VsZW1lbnQoKSB7XG4gICAgICAgICAgICBpZiAobnVsbCA9PT0gdGhpcy50ZW1wQ2FudmFzRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHRlbXBDYW52YXNFbGVtZW50ID0gdGhpcy5jYW52YXMub3duZXJEb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgICAgICAgICB0ZW1wQ2FudmFzRWxlbWVudC53aWR0aCA9IHRoaXMuY2FudmFzLndpZHRoO1xuICAgICAgICAgICAgICAgIHRlbXBDYW52YXNFbGVtZW50LmhlaWdodCA9IHRoaXMuY2FudmFzLmhlaWdodDtcbiAgICAgICAgICAgICAgICB0aGlzLnRlbXBDYW52YXNFbGVtZW50ID0gdGVtcENhbnZhc0VsZW1lbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50ZW1wQ2FudmFzRWxlbWVudDtcbiAgICAgICAgfVxuICAgICAgICByb3RhdGUoYW5nbGUpIHtcbiAgICAgICAgICAgIGNvbnN0IHRlbXBDYW52YXNFbGVtZW50ID0gdGhpcy5nZXRUZW1wQ2FudmFzRWxlbWVudCgpO1xuICAgICAgICAgICAgY29uc3QgdGVtcENvbnRleHQgPSB0ZW1wQ2FudmFzRWxlbWVudC5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgICAgICAgY29uc3QgYW5nbGVSYWRpYW5zID0gYW5nbGUgKiBIVE1MQ2FudmFzRWxlbWVudEx1bWluYW5jZVNvdXJjZS5ERUdSRUVfVE9fUkFESUFOUztcbiAgICAgICAgICAgIC8vIENhbGN1bGF0ZSBhbmQgc2V0IG5ldyBkaW1lbnNpb25zIGZvciB0ZW1wIGNhbnZhc1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSB0aGlzLmNhbnZhcy53aWR0aDtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuY2FudmFzLmhlaWdodDtcbiAgICAgICAgICAgIGNvbnN0IG5ld1dpZHRoID0gTWF0aC5jZWlsKE1hdGguYWJzKE1hdGguY29zKGFuZ2xlUmFkaWFucykpICogd2lkdGggKyBNYXRoLmFicyhNYXRoLnNpbihhbmdsZVJhZGlhbnMpKSAqIGhlaWdodCk7XG4gICAgICAgICAgICBjb25zdCBuZXdIZWlnaHQgPSBNYXRoLmNlaWwoTWF0aC5hYnMoTWF0aC5zaW4oYW5nbGVSYWRpYW5zKSkgKiB3aWR0aCArIE1hdGguYWJzKE1hdGguY29zKGFuZ2xlUmFkaWFucykpICogaGVpZ2h0KTtcbiAgICAgICAgICAgIHRlbXBDYW52YXNFbGVtZW50LndpZHRoID0gbmV3V2lkdGg7XG4gICAgICAgICAgICB0ZW1wQ2FudmFzRWxlbWVudC5oZWlnaHQgPSBuZXdIZWlnaHQ7XG4gICAgICAgICAgICAvLyBEcmF3IGF0IGNlbnRlciBvZiB0ZW1wIGNhbnZhcyB0byBwcmV2ZW50IGNsaXBwaW5nIG9mIGltYWdlIGRhdGFcbiAgICAgICAgICAgIHRlbXBDb250ZXh0LnRyYW5zbGF0ZShuZXdXaWR0aCAvIDIsIG5ld0hlaWdodCAvIDIpO1xuICAgICAgICAgICAgdGVtcENvbnRleHQucm90YXRlKGFuZ2xlUmFkaWFucyk7XG4gICAgICAgICAgICB0ZW1wQ29udGV4dC5kcmF3SW1hZ2UodGhpcy5jYW52YXMsIHdpZHRoIC8gLTIsIGhlaWdodCAvIC0yKTtcbiAgICAgICAgICAgIHRoaXMuYnVmZmVyID0gSFRNTENhbnZhc0VsZW1lbnRMdW1pbmFuY2VTb3VyY2UubWFrZUJ1ZmZlckZyb21DYW52YXNJbWFnZURhdGEodGVtcENhbnZhc0VsZW1lbnQpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgaW52ZXJ0KCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBJbnZlcnRlZEx1bWluYW5jZVNvdXJjZSh0aGlzKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBIVE1MQ2FudmFzRWxlbWVudEx1bWluYW5jZVNvdXJjZS5ERUdSRUVfVE9fUkFESUFOUyA9IE1hdGguUEkgLyAxODA7XG5cbiAgICAvKipcbiAgICAgKiBAZGVwcmVjYXRlZCBNb3ZpbmcgdG8gQHp4aW5nL2Jyb3dzZXJcbiAgICAgKlxuICAgICAqIFZpZGVvIGlucHV0IGRldmljZSBtZXRhZGF0YSBjb250YWluaW5nIHRoZSBpZCBhbmQgbGFiZWwgb2YgdGhlIGRldmljZSBpZiBhdmFpbGFibGUuXG4gICAgICovXG4gICAgY2xhc3MgVmlkZW9JbnB1dERldmljZSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIFZpZGVvSW5wdXREZXZpY2UuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBkZXZpY2VJZCB0aGUgdmlkZW8gaW5wdXQgZGV2aWNlIGlkXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBsYWJlbCB0aGUgbGFiZWwgb2YgdGhlIGRldmljZSBpZiBhdmFpbGFibGVcbiAgICAgICAgICovXG4gICAgICAgIGNvbnN0cnVjdG9yKGRldmljZUlkLCBsYWJlbCwgZ3JvdXBJZCkge1xuICAgICAgICAgICAgdGhpcy5kZXZpY2VJZCA9IGRldmljZUlkO1xuICAgICAgICAgICAgdGhpcy5sYWJlbCA9IGxhYmVsO1xuICAgICAgICAgICAgLyoqIEBpbmhlcml0ZG9jICovXG4gICAgICAgICAgICB0aGlzLmtpbmQgPSAndmlkZW9pbnB1dCc7XG4gICAgICAgICAgICB0aGlzLmdyb3VwSWQgPSBncm91cElkIHx8IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICAvKiogQGluaGVyaXRkb2MgKi9cbiAgICAgICAgdG9KU09OKCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBraW5kOiB0aGlzLmtpbmQsXG4gICAgICAgICAgICAgICAgZ3JvdXBJZDogdGhpcy5ncm91cElkLFxuICAgICAgICAgICAgICAgIGRldmljZUlkOiB0aGlzLmRldmljZUlkLFxuICAgICAgICAgICAgICAgIGxhYmVsOiB0aGlzLmxhYmVsLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBfX2F3YWl0ZXIgPSAoKGdsb2JhbFRoaXMgfHwgZ2xvYmFsIHx8IHNlbGYgfHwgd2luZG93IHx8IHVuZGVmaW5lZCkgJiYgKGdsb2JhbFRoaXMgfHwgZ2xvYmFsIHx8IHNlbGYgfHwgd2luZG93IHx8IHVuZGVmaW5lZCkuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XG4gICAgICAgIGZ1bmN0aW9uIGFkb3B0KHZhbHVlKSB7IHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUodmFsdWUpOyB9KTsgfVxuICAgICAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cbiAgICAgICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBAZGVwcmVjYXRlZCBNb3ZpbmcgdG8gQHp4aW5nL2Jyb3dzZXJcbiAgICAgKlxuICAgICAqIEJhc2UgY2xhc3MgZm9yIGJyb3dzZXIgY29kZSByZWFkZXIuXG4gICAgICovXG4gICAgY2xhc3MgQnJvd3NlckNvZGVSZWFkZXIge1xuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBCcm93c2VyQ29kZVJlYWRlci5cbiAgICAgICAgICogQHBhcmFtIHtSZWFkZXJ9IHJlYWRlciBUaGUgcmVhZGVyIGluc3RhbmNlIHRvIGRlY29kZSB0aGUgYmFyY29kZVxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gW3RpbWVCZXR3ZWVuU2NhbnNNaWxsaXM9NTAwXSB0aGUgdGltZSBkZWxheSBiZXR3ZWVuIHN1YnNlcXVlbnQgc3VjY2Vzc2Z1bCBkZWNvZGUgdHJpZXNcbiAgICAgICAgICpcbiAgICAgICAgICogQG1lbWJlck9mIEJyb3dzZXJDb2RlUmVhZGVyXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3RvcihyZWFkZXIsIHRpbWVCZXR3ZWVuU2NhbnNNaWxsaXMgPSA1MDAsIF9oaW50cykge1xuICAgICAgICAgICAgdGhpcy5yZWFkZXIgPSByZWFkZXI7XG4gICAgICAgICAgICB0aGlzLnRpbWVCZXR3ZWVuU2NhbnNNaWxsaXMgPSB0aW1lQmV0d2VlblNjYW5zTWlsbGlzO1xuICAgICAgICAgICAgdGhpcy5faGludHMgPSBfaGludHM7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFRoaXMgd2lsbCBicmVhayB0aGUgbG9vcC5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgdGhpcy5fc3RvcENvbnRpbnVvdXNEZWNvZGUgPSBmYWxzZTtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogVGhpcyB3aWxsIGJyZWFrIHRoZSBsb29wLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICB0aGlzLl9zdG9wQXN5bmNEZWNvZGUgPSBmYWxzZTtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogRGVsYXkgdGltZSBiZXR3ZWVuIGRlY29kZSBhdHRlbXB0cyBtYWRlIGJ5IHRoZSBzY2FubmVyLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICB0aGlzLl90aW1lQmV0d2VlbkRlY29kaW5nQXR0ZW1wdHMgPSAwO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJZiBuYXZpZ2F0b3IgaXMgcHJlc2VudC5cbiAgICAgICAgICovXG4gICAgICAgIGdldCBoYXNOYXZpZ2F0b3IoKSB7XG4gICAgICAgICAgICByZXR1cm4gdHlwZW9mIG5hdmlnYXRvciAhPT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIElmIG1lZGlhRGV2aWNlcyB1bmRlciBuYXZpZ2F0b3IgaXMgc3VwcG9ydGVkLlxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0IGlzTWVkaWFEZXZpY2VzU3Vwb3J0ZWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5oYXNOYXZpZ2F0b3IgJiYgISFuYXZpZ2F0b3IubWVkaWFEZXZpY2VzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJZiBlbnVtZXJhdGVEZXZpY2VzIHVuZGVyIG5hdmlnYXRvciBpcyBzdXBwb3J0ZWQuXG4gICAgICAgICAqL1xuICAgICAgICBnZXQgY2FuRW51bWVyYXRlRGV2aWNlcygpIHtcbiAgICAgICAgICAgIHJldHVybiAhISh0aGlzLmlzTWVkaWFEZXZpY2VzU3Vwb3J0ZWQgJiYgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKTtcbiAgICAgICAgfVxuICAgICAgICAvKiogVGltZSBiZXR3ZWVuIHR3byBkZWNvZGluZyB0cmllcyBpbiBtaWxsaSBzZWNvbmRzLiAqL1xuICAgICAgICBnZXQgdGltZUJldHdlZW5EZWNvZGluZ0F0dGVtcHRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3RpbWVCZXR3ZWVuRGVjb2RpbmdBdHRlbXB0cztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ2hhbmdlIHRoZSB0aW1lIHNwYW4gdGhlIGRlY29kZXIgd2FpdHMgYmV0d2VlbiB0d28gZGVjb2RpbmcgdHJpZXMuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBtaWxsaXMgVGltZSBiZXR3ZWVuIHR3byBkZWNvZGluZyB0cmllcyBpbiBtaWxsaSBzZWNvbmRzLlxuICAgICAgICAgKi9cbiAgICAgICAgc2V0IHRpbWVCZXR3ZWVuRGVjb2RpbmdBdHRlbXB0cyhtaWxsaXMpIHtcbiAgICAgICAgICAgIHRoaXMuX3RpbWVCZXR3ZWVuRGVjb2RpbmdBdHRlbXB0cyA9IG1pbGxpcyA8IDAgPyAwIDogbWlsbGlzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZXRzIHRoZSBoaW50cy5cbiAgICAgICAgICovXG4gICAgICAgIHNldCBoaW50cyhoaW50cykge1xuICAgICAgICAgICAgdGhpcy5faGludHMgPSBoaW50cyB8fCBudWxsO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZXRzIHRoZSBoaW50cy5cbiAgICAgICAgICovXG4gICAgICAgIGdldCBoaW50cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9oaW50cztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogTGlzdHMgYWxsIHRoZSBhdmFpbGFibGUgdmlkZW8gaW5wdXQgZGV2aWNlcy5cbiAgICAgICAgICovXG4gICAgICAgIGxpc3RWaWRlb0lucHV0RGV2aWNlcygpIHtcbiAgICAgICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmhhc05hdmlnYXRvcikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcJ3QgZW51bWVyYXRlIGRldmljZXMsIG5hdmlnYXRvciBpcyBub3QgcHJlc2VudC4nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNhbkVudW1lcmF0ZURldmljZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXCd0IGVudW1lcmF0ZSBkZXZpY2VzLCBtZXRob2Qgbm90IHN1cHBvcnRlZC4nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgZGV2aWNlcyA9IHlpZWxkIG5hdmlnYXRvci5tZWRpYURldmljZXMuZW51bWVyYXRlRGV2aWNlcygpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHZpZGVvRGV2aWNlcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZGV2aWNlIG9mIGRldmljZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qga2luZCA9IGRldmljZS5raW5kID09PSAndmlkZW8nID8gJ3ZpZGVvaW5wdXQnIDogZGV2aWNlLmtpbmQ7XG4gICAgICAgICAgICAgICAgICAgIGlmIChraW5kICE9PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGRldmljZUlkID0gZGV2aWNlLmRldmljZUlkIHx8IGRldmljZS5pZDtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGFiZWwgPSBkZXZpY2UubGFiZWwgfHwgYFZpZGVvIGRldmljZSAke3ZpZGVvRGV2aWNlcy5sZW5ndGggKyAxfWA7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGdyb3VwSWQgPSBkZXZpY2UuZ3JvdXBJZDtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdmlkZW9EZXZpY2UgPSB7IGRldmljZUlkLCBsYWJlbCwga2luZCwgZ3JvdXBJZCB9O1xuICAgICAgICAgICAgICAgICAgICB2aWRlb0RldmljZXMucHVzaCh2aWRlb0RldmljZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB2aWRlb0RldmljZXM7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogT2J0YWluIHRoZSBsaXN0IG9mIGF2YWlsYWJsZSBkZXZpY2VzIHdpdGggdHlwZSAndmlkZW9pbnB1dCcuXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm5zIHtQcm9taXNlPFZpZGVvSW5wdXREZXZpY2VbXT59IGFuIGFycmF5IG9mIGF2YWlsYWJsZSB2aWRlbyBpbnB1dCBkZXZpY2VzXG4gICAgICAgICAqXG4gICAgICAgICAqIEBtZW1iZXJPZiBCcm93c2VyQ29kZVJlYWRlclxuICAgICAgICAgKlxuICAgICAgICAgKiBAZGVwcmVjYXRlZCBVc2UgYGxpc3RWaWRlb0lucHV0RGV2aWNlc2AgaW5zdGVhZC5cbiAgICAgICAgICovXG4gICAgICAgIGdldFZpZGVvSW5wdXREZXZpY2VzKCkge1xuICAgICAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkZXZpY2VzID0geWllbGQgdGhpcy5saXN0VmlkZW9JbnB1dERldmljZXMoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGV2aWNlcy5tYXAoZCA9PiBuZXcgVmlkZW9JbnB1dERldmljZShkLmRldmljZUlkLCBkLmxhYmVsKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogTGV0J3MgeW91IGZpbmQgYSBkZXZpY2UgdXNpbmcgaXQncyBJZC5cbiAgICAgICAgICovXG4gICAgICAgIGZpbmREZXZpY2VCeUlkKGRldmljZUlkKSB7XG4gICAgICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRldmljZXMgPSB5aWVsZCB0aGlzLmxpc3RWaWRlb0lucHV0RGV2aWNlcygpO1xuICAgICAgICAgICAgICAgIGlmICghZGV2aWNlcykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRldmljZXMuZmluZCh4ID0+IHguZGV2aWNlSWQgPT09IGRldmljZUlkKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIHRoZSBiYXJjb2RlIGZyb20gdGhlIGRldmljZSBzcGVjaWZpZWQgYnkgZGV2aWNlSWQgd2hpbGUgc2hvd2luZyB0aGUgdmlkZW8gaW4gdGhlIHNwZWNpZmllZCB2aWRlbyBlbGVtZW50LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gZGV2aWNlSWQgdGhlIGlkIG9mIG9uZSBvZiB0aGUgZGV2aWNlcyBvYnRhaW5lZCBhZnRlciBjYWxsaW5nIGdldFZpZGVvSW5wdXREZXZpY2VzLiBDYW4gYmUgdW5kZWZpbmVkLCBpbiB0aGlzIGNhc2UgaXQgd2lsbCBkZWNvZGUgZnJvbSBvbmUgb2YgdGhlIGF2YWlsYWJsZSBkZXZpY2VzLCBwcmVmZmVyaW5nIHRoZSBtYWluIGNhbWVyYSAoZW52aXJvbm1lbnQgZmFjaW5nKSBpZiBhdmFpbGFibGUuXG4gICAgICAgICAqIEBwYXJhbSB2aWRlbyB0aGUgdmlkZW8gZWxlbWVudCBpbiBwYWdlIHdoZXJlIHRvIHNob3cgdGhlIHZpZGVvIHdoaWxlIGRlY29kaW5nLiBDYW4gYmUgZWl0aGVyIGFuIGVsZW1lbnQgaWQgb3IgZGlyZWN0bHkgYW4gSFRNTFZpZGVvRWxlbWVudC4gQ2FuIGJlIHVuZGVmaW5lZCwgaW4gd2hpY2ggY2FzZSBubyB2aWRlbyB3aWxsIGJlIHNob3duLlxuICAgICAgICAgKiBAcmV0dXJucyBUaGUgZGVjb2RpbmcgcmVzdWx0LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAbWVtYmVyT2YgQnJvd3NlckNvZGVSZWFkZXJcbiAgICAgICAgICpcbiAgICAgICAgICogQGRlcHJlY2F0ZWQgVXNlIGBkZWNvZGVPbmNlRnJvbVZpZGVvRGV2aWNlYCBpbnN0ZWFkLlxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlRnJvbUlucHV0VmlkZW9EZXZpY2UoZGV2aWNlSWQsIHZpZGVvU291cmNlKSB7XG4gICAgICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB5aWVsZCB0aGlzLmRlY29kZU9uY2VGcm9tVmlkZW9EZXZpY2UoZGV2aWNlSWQsIHZpZGVvU291cmNlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJbiBvbmUgYXR0ZW1wdCwgdHJpZXMgdG8gZGVjb2RlIHRoZSBiYXJjb2RlIGZyb20gdGhlIGRldmljZSBzcGVjaWZpZWQgYnkgZGV2aWNlSWQgd2hpbGUgc2hvd2luZyB0aGUgdmlkZW8gaW4gdGhlIHNwZWNpZmllZCB2aWRlbyBlbGVtZW50LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gZGV2aWNlSWQgdGhlIGlkIG9mIG9uZSBvZiB0aGUgZGV2aWNlcyBvYnRhaW5lZCBhZnRlciBjYWxsaW5nIGdldFZpZGVvSW5wdXREZXZpY2VzLiBDYW4gYmUgdW5kZWZpbmVkLCBpbiB0aGlzIGNhc2UgaXQgd2lsbCBkZWNvZGUgZnJvbSBvbmUgb2YgdGhlIGF2YWlsYWJsZSBkZXZpY2VzLCBwcmVmZmVyaW5nIHRoZSBtYWluIGNhbWVyYSAoZW52aXJvbm1lbnQgZmFjaW5nKSBpZiBhdmFpbGFibGUuXG4gICAgICAgICAqIEBwYXJhbSB2aWRlbyB0aGUgdmlkZW8gZWxlbWVudCBpbiBwYWdlIHdoZXJlIHRvIHNob3cgdGhlIHZpZGVvIHdoaWxlIGRlY29kaW5nLiBDYW4gYmUgZWl0aGVyIGFuIGVsZW1lbnQgaWQgb3IgZGlyZWN0bHkgYW4gSFRNTFZpZGVvRWxlbWVudC4gQ2FuIGJlIHVuZGVmaW5lZCwgaW4gd2hpY2ggY2FzZSBubyB2aWRlbyB3aWxsIGJlIHNob3duLlxuICAgICAgICAgKiBAcmV0dXJucyBUaGUgZGVjb2RpbmcgcmVzdWx0LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAbWVtYmVyT2YgQnJvd3NlckNvZGVSZWFkZXJcbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZU9uY2VGcm9tVmlkZW9EZXZpY2UoZGV2aWNlSWQsIHZpZGVvU291cmNlKSB7XG4gICAgICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgICAgICAgICBsZXQgdmlkZW9Db25zdHJhaW50cztcbiAgICAgICAgICAgICAgICBpZiAoIWRldmljZUlkKSB7XG4gICAgICAgICAgICAgICAgICAgIHZpZGVvQ29uc3RyYWludHMgPSB7IGZhY2luZ01vZGU6ICdlbnZpcm9ubWVudCcgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZpZGVvQ29uc3RyYWludHMgPSB7IGRldmljZUlkOiB7IGV4YWN0OiBkZXZpY2VJZCB9IH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGNvbnN0cmFpbnRzID0geyB2aWRlbzogdmlkZW9Db25zdHJhaW50cyB9O1xuICAgICAgICAgICAgICAgIHJldHVybiB5aWVsZCB0aGlzLmRlY29kZU9uY2VGcm9tQ29uc3RyYWludHMoY29uc3RyYWludHMsIHZpZGVvU291cmNlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJbiBvbmUgYXR0ZW1wdCwgdHJpZXMgdG8gZGVjb2RlIHRoZSBiYXJjb2RlIGZyb20gYSBzdHJlYW0gb2J0YWluZWQgZnJvbSB0aGUgZ2l2ZW4gY29uc3RyYWludHMgd2hpbGUgc2hvd2luZyB0aGUgdmlkZW8gaW4gdGhlIHNwZWNpZmllZCB2aWRlbyBlbGVtZW50LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gY29uc3RyYWludHMgdGhlIG1lZGlhIHN0cmVhbSBjb25zdHJhaW50cyB0byBnZXQgcyB2YWxpZCBtZWRpYSBzdHJlYW0gdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHBhcmFtIHZpZGVvIHRoZSB2aWRlbyBlbGVtZW50IGluIHBhZ2Ugd2hlcmUgdG8gc2hvdyB0aGUgdmlkZW8gd2hpbGUgZGVjb2RpbmcuIENhbiBiZSBlaXRoZXIgYW4gZWxlbWVudCBpZCBvciBkaXJlY3RseSBhbiBIVE1MVmlkZW9FbGVtZW50LiBDYW4gYmUgdW5kZWZpbmVkLCBpbiB3aGljaCBjYXNlIG5vIHZpZGVvIHdpbGwgYmUgc2hvd24uXG4gICAgICAgICAqIEByZXR1cm5zIFRoZSBkZWNvZGluZyByZXN1bHQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBtZW1iZXJPZiBCcm93c2VyQ29kZVJlYWRlclxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlT25jZUZyb21Db25zdHJhaW50cyhjb25zdHJhaW50cywgdmlkZW9Tb3VyY2UpIHtcbiAgICAgICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0geWllbGQgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoY29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgIHJldHVybiB5aWVsZCB0aGlzLmRlY29kZU9uY2VGcm9tU3RyZWFtKHN0cmVhbSwgdmlkZW9Tb3VyY2UpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEluIG9uZSBhdHRlbXB0LCB0cmllcyB0byBkZWNvZGUgdGhlIGJhcmNvZGUgZnJvbSBhIHN0cmVhbSBvYnRhaW5lZCBmcm9tIHRoZSBnaXZlbiBjb25zdHJhaW50cyB3aGlsZSBzaG93aW5nIHRoZSB2aWRlbyBpbiB0aGUgc3BlY2lmaWVkIHZpZGVvIGVsZW1lbnQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB7TWVkaWFTdHJlYW19IFtjb25zdHJhaW50c10gdGhlIG1lZGlhIHN0cmVhbSBjb25zdHJhaW50cyB0byBnZXQgcyB2YWxpZCBtZWRpYSBzdHJlYW0gdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd8SFRNTFZpZGVvRWxlbWVudH0gW3ZpZGVvXSB0aGUgdmlkZW8gZWxlbWVudCBpbiBwYWdlIHdoZXJlIHRvIHNob3cgdGhlIHZpZGVvIHdoaWxlIGRlY29kaW5nLiBDYW4gYmUgZWl0aGVyIGFuIGVsZW1lbnQgaWQgb3IgZGlyZWN0bHkgYW4gSFRNTFZpZGVvRWxlbWVudC4gQ2FuIGJlIHVuZGVmaW5lZCwgaW4gd2hpY2ggY2FzZSBubyB2aWRlbyB3aWxsIGJlIHNob3duLlxuICAgICAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZXN1bHQ+fSBUaGUgZGVjb2RpbmcgcmVzdWx0LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAbWVtYmVyT2YgQnJvd3NlckNvZGVSZWFkZXJcbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZU9uY2VGcm9tU3RyZWFtKHN0cmVhbSwgdmlkZW9Tb3VyY2UpIHtcbiAgICAgICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNldCgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHZpZGVvID0geWllbGQgdGhpcy5hdHRhY2hTdHJlYW1Ub1ZpZGVvKHN0cmVhbSwgdmlkZW9Tb3VyY2UpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHlpZWxkIHRoaXMuZGVjb2RlT25jZSh2aWRlbyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb250aW51b3VzbHkgZGVjb2RlcyB0aGUgYmFyY29kZSBmcm9tIHRoZSBkZXZpY2Ugc3BlY2lmaWVkIGJ5IGRldmljZSB3aGlsZSBzaG93aW5nIHRoZSB2aWRlbyBpbiB0aGUgc3BlY2lmaWVkIHZpZGVvIGVsZW1lbnQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bGx9IFtkZXZpY2VJZF0gdGhlIGlkIG9mIG9uZSBvZiB0aGUgZGV2aWNlcyBvYnRhaW5lZCBhZnRlciBjYWxsaW5nIGdldFZpZGVvSW5wdXREZXZpY2VzLiBDYW4gYmUgdW5kZWZpbmVkLCBpbiB0aGlzIGNhc2UgaXQgd2lsbCBkZWNvZGUgZnJvbSBvbmUgb2YgdGhlIGF2YWlsYWJsZSBkZXZpY2VzLCBwcmVmZmVyaW5nIHRoZSBtYWluIGNhbWVyYSAoZW52aXJvbm1lbnQgZmFjaW5nKSBpZiBhdmFpbGFibGUuXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfEhUTUxWaWRlb0VsZW1lbnR8bnVsbH0gW3ZpZGVvXSB0aGUgdmlkZW8gZWxlbWVudCBpbiBwYWdlIHdoZXJlIHRvIHNob3cgdGhlIHZpZGVvIHdoaWxlIGRlY29kaW5nLiBDYW4gYmUgZWl0aGVyIGFuIGVsZW1lbnQgaWQgb3IgZGlyZWN0bHkgYW4gSFRNTFZpZGVvRWxlbWVudC4gQ2FuIGJlIHVuZGVmaW5lZCwgaW4gd2hpY2ggY2FzZSBubyB2aWRlbyB3aWxsIGJlIHNob3duLlxuICAgICAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICAgICAgICpcbiAgICAgICAgICogQG1lbWJlck9mIEJyb3dzZXJDb2RlUmVhZGVyXG4gICAgICAgICAqXG4gICAgICAgICAqIEBkZXByZWNhdGVkIFVzZSBgZGVjb2RlRnJvbVZpZGVvRGV2aWNlYCBpbnN0ZWFkLlxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlRnJvbUlucHV0VmlkZW9EZXZpY2VDb250aW51b3VzbHkoZGV2aWNlSWQsIHZpZGVvU291cmNlLCBjYWxsYmFja0ZuKSB7XG4gICAgICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB5aWVsZCB0aGlzLmRlY29kZUZyb21WaWRlb0RldmljZShkZXZpY2VJZCwgdmlkZW9Tb3VyY2UsIGNhbGxiYWNrRm4pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnRpbnVvdXNseSB0cmllcyB0byBkZWNvZGUgdGhlIGJhcmNvZGUgZnJvbSB0aGUgZGV2aWNlIHNwZWNpZmllZCBieSBkZXZpY2Ugd2hpbGUgc2hvd2luZyB0aGUgdmlkZW8gaW4gdGhlIHNwZWNpZmllZCB2aWRlbyBlbGVtZW50LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ3xudWxsfSBbZGV2aWNlSWRdIHRoZSBpZCBvZiBvbmUgb2YgdGhlIGRldmljZXMgb2J0YWluZWQgYWZ0ZXIgY2FsbGluZyBnZXRWaWRlb0lucHV0RGV2aWNlcy4gQ2FuIGJlIHVuZGVmaW5lZCwgaW4gdGhpcyBjYXNlIGl0IHdpbGwgZGVjb2RlIGZyb20gb25lIG9mIHRoZSBhdmFpbGFibGUgZGV2aWNlcywgcHJlZmZlcmluZyB0aGUgbWFpbiBjYW1lcmEgKGVudmlyb25tZW50IGZhY2luZykgaWYgYXZhaWxhYmxlLlxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ3xIVE1MVmlkZW9FbGVtZW50fG51bGx9IFt2aWRlb10gdGhlIHZpZGVvIGVsZW1lbnQgaW4gcGFnZSB3aGVyZSB0byBzaG93IHRoZSB2aWRlbyB3aGlsZSBkZWNvZGluZy4gQ2FuIGJlIGVpdGhlciBhbiBlbGVtZW50IGlkIG9yIGRpcmVjdGx5IGFuIEhUTUxWaWRlb0VsZW1lbnQuIENhbiBiZSB1bmRlZmluZWQsIGluIHdoaWNoIGNhc2Ugbm8gdmlkZW8gd2lsbCBiZSBzaG93bi5cbiAgICAgICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAgICAgICAqXG4gICAgICAgICAqIEBtZW1iZXJPZiBCcm93c2VyQ29kZVJlYWRlclxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlRnJvbVZpZGVvRGV2aWNlKGRldmljZUlkLCB2aWRlb1NvdXJjZSwgY2FsbGJhY2tGbikge1xuICAgICAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgICAgICAgICAgICBsZXQgdmlkZW9Db25zdHJhaW50cztcbiAgICAgICAgICAgICAgICBpZiAoIWRldmljZUlkKSB7XG4gICAgICAgICAgICAgICAgICAgIHZpZGVvQ29uc3RyYWludHMgPSB7IGZhY2luZ01vZGU6ICdlbnZpcm9ubWVudCcgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZpZGVvQ29uc3RyYWludHMgPSB7IGRldmljZUlkOiB7IGV4YWN0OiBkZXZpY2VJZCB9IH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGNvbnN0cmFpbnRzID0geyB2aWRlbzogdmlkZW9Db25zdHJhaW50cyB9O1xuICAgICAgICAgICAgICAgIHJldHVybiB5aWVsZCB0aGlzLmRlY29kZUZyb21Db25zdHJhaW50cyhjb25zdHJhaW50cywgdmlkZW9Tb3VyY2UsIGNhbGxiYWNrRm4pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnRpbnVvdXNseSB0cmllcyB0byBkZWNvZGUgdGhlIGJhcmNvZGUgZnJvbSBhIHN0cmVhbSBvYnRhaW5lZCBmcm9tIHRoZSBnaXZlbiBjb25zdHJhaW50cyB3aGlsZSBzaG93aW5nIHRoZSB2aWRlbyBpbiB0aGUgc3BlY2lmaWVkIHZpZGVvIGVsZW1lbnQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB7TWVkaWFTdHJlYW19IFtjb25zdHJhaW50c10gdGhlIG1lZGlhIHN0cmVhbSBjb25zdHJhaW50cyB0byBnZXQgcyB2YWxpZCBtZWRpYSBzdHJlYW0gdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd8SFRNTFZpZGVvRWxlbWVudH0gW3ZpZGVvXSB0aGUgdmlkZW8gZWxlbWVudCBpbiBwYWdlIHdoZXJlIHRvIHNob3cgdGhlIHZpZGVvIHdoaWxlIGRlY29kaW5nLiBDYW4gYmUgZWl0aGVyIGFuIGVsZW1lbnQgaWQgb3IgZGlyZWN0bHkgYW4gSFRNTFZpZGVvRWxlbWVudC4gQ2FuIGJlIHVuZGVmaW5lZCwgaW4gd2hpY2ggY2FzZSBubyB2aWRlbyB3aWxsIGJlIHNob3duLlxuICAgICAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZXN1bHQ+fSBUaGUgZGVjb2RpbmcgcmVzdWx0LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAbWVtYmVyT2YgQnJvd3NlckNvZGVSZWFkZXJcbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZUZyb21Db25zdHJhaW50cyhjb25zdHJhaW50cywgdmlkZW9Tb3VyY2UsIGNhbGxiYWNrRm4pIHtcbiAgICAgICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0geWllbGQgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoY29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgIHJldHVybiB5aWVsZCB0aGlzLmRlY29kZUZyb21TdHJlYW0oc3RyZWFtLCB2aWRlb1NvdXJjZSwgY2FsbGJhY2tGbik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogSW4gb25lIGF0dGVtcHQsIHRyaWVzIHRvIGRlY29kZSB0aGUgYmFyY29kZSBmcm9tIGEgc3RyZWFtIG9idGFpbmVkIGZyb20gdGhlIGdpdmVuIGNvbnN0cmFpbnRzIHdoaWxlIHNob3dpbmcgdGhlIHZpZGVvIGluIHRoZSBzcGVjaWZpZWQgdmlkZW8gZWxlbWVudC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHtNZWRpYVN0cmVhbX0gW2NvbnN0cmFpbnRzXSB0aGUgbWVkaWEgc3RyZWFtIGNvbnN0cmFpbnRzIHRvIGdldCBzIHZhbGlkIG1lZGlhIHN0cmVhbSB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ3xIVE1MVmlkZW9FbGVtZW50fSBbdmlkZW9dIHRoZSB2aWRlbyBlbGVtZW50IGluIHBhZ2Ugd2hlcmUgdG8gc2hvdyB0aGUgdmlkZW8gd2hpbGUgZGVjb2RpbmcuIENhbiBiZSBlaXRoZXIgYW4gZWxlbWVudCBpZCBvciBkaXJlY3RseSBhbiBIVE1MVmlkZW9FbGVtZW50LiBDYW4gYmUgdW5kZWZpbmVkLCBpbiB3aGljaCBjYXNlIG5vIHZpZGVvIHdpbGwgYmUgc2hvd24uXG4gICAgICAgICAqIEByZXR1cm5zIHtQcm9taXNlPFJlc3VsdD59IFRoZSBkZWNvZGluZyByZXN1bHQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBtZW1iZXJPZiBCcm93c2VyQ29kZVJlYWRlclxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlRnJvbVN0cmVhbShzdHJlYW0sIHZpZGVvU291cmNlLCBjYWxsYmFja0ZuKSB7XG4gICAgICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgICAgICAgICBjb25zdCB2aWRlbyA9IHlpZWxkIHRoaXMuYXR0YWNoU3RyZWFtVG9WaWRlbyhzdHJlYW0sIHZpZGVvU291cmNlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4geWllbGQgdGhpcy5kZWNvZGVDb250aW51b3VzbHkodmlkZW8sIGNhbGxiYWNrRm4pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEJyZWFrcyB0aGUgZGVjb2RpbmcgbG9vcC5cbiAgICAgICAgICovXG4gICAgICAgIHN0b3BBc3luY0RlY29kZSgpIHtcbiAgICAgICAgICAgIHRoaXMuX3N0b3BBc3luY0RlY29kZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEJyZWFrcyB0aGUgZGVjb2RpbmcgbG9vcC5cbiAgICAgICAgICovXG4gICAgICAgIHN0b3BDb250aW51b3VzRGVjb2RlKCkge1xuICAgICAgICAgICAgdGhpcy5fc3RvcENvbnRpbnVvdXNEZWNvZGUgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZXRzIHRoZSBuZXcgc3RyZWFtIGFuZCByZXF1ZXN0IGEgbmV3IGRlY29kaW5nLXdpdGgtZGVsYXkuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBzdHJlYW0gVGhlIHN0cmVhbSB0byBiZSBzaG93biBpbiB0aGUgdmlkZW8gZWxlbWVudC5cbiAgICAgICAgICogQHBhcmFtIGRlY29kZUZuIEEgY2FsbGJhY2sgZm9yIHRoZSBkZWNvZGUgbWV0aG9kLlxuICAgICAgICAgKi9cbiAgICAgICAgYXR0YWNoU3RyZWFtVG9WaWRlbyhzdHJlYW0sIHZpZGVvU291cmNlKSB7XG4gICAgICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZpZGVvRWxlbWVudCA9IHRoaXMucHJlcGFyZVZpZGVvRWxlbWVudCh2aWRlb1NvdXJjZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRWaWRlb1NvdXJjZSh2aWRlb0VsZW1lbnQsIHN0cmVhbSk7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0VsZW1lbnQgPSB2aWRlb0VsZW1lbnQ7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgICAgICAgICAgeWllbGQgdGhpcy5wbGF5VmlkZW9PbkxvYWRBc3luYyh2aWRlb0VsZW1lbnQpO1xuICAgICAgICAgICAgICAgIHJldHVybiB2aWRlb0VsZW1lbnQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHZpZGVvRWxlbWVudFxuICAgICAgICAgKi9cbiAgICAgICAgcGxheVZpZGVvT25Mb2FkQXN5bmModmlkZW9FbGVtZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4gdGhpcy5wbGF5VmlkZW9PbkxvYWQodmlkZW9FbGVtZW50LCAoKSA9PiByZXNvbHZlKCkpKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQmluZHMgbGlzdGVuZXJzIGFuZCBjYWxsYmFja3MgdG8gdGhlIHZpZGVvRWxlbWVudC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGVsZW1lbnRcbiAgICAgICAgICogQHBhcmFtIGNhbGxiYWNrRm5cbiAgICAgICAgICovXG4gICAgICAgIHBsYXlWaWRlb09uTG9hZChlbGVtZW50LCBjYWxsYmFja0ZuKSB7XG4gICAgICAgICAgICB0aGlzLnZpZGVvRW5kZWRMaXN0ZW5lciA9ICgpID0+IHRoaXMuc3RvcFN0cmVhbXMoKTtcbiAgICAgICAgICAgIHRoaXMudmlkZW9DYW5QbGF5TGlzdGVuZXIgPSAoKSA9PiB0aGlzLnRyeVBsYXlWaWRlbyhlbGVtZW50KTtcbiAgICAgICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZW5kZWQnLCB0aGlzLnZpZGVvRW5kZWRMaXN0ZW5lcik7XG4gICAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NhbnBsYXknLCB0aGlzLnZpZGVvQ2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncGxheWluZycsIGNhbGxiYWNrRm4pO1xuICAgICAgICAgICAgLy8gaWYgY2FucGxheSB3YXMgYWxyZWFkeSBmaXJlZCwgd2Ugd29uJ3Qga25vdyB3aGVuIHRvIHBsYXksIHNvIGp1c3QgZ2l2ZSBpdCBhIHRyeVxuICAgICAgICAgICAgdGhpcy50cnlQbGF5VmlkZW8oZWxlbWVudCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gdmlkZW8gZWxlbWVudCBpcyBjdXJyZW50bHkgcGxheWluZy5cbiAgICAgICAgICovXG4gICAgICAgIGlzVmlkZW9QbGF5aW5nKHZpZGVvKSB7XG4gICAgICAgICAgICByZXR1cm4gdmlkZW8uY3VycmVudFRpbWUgPiAwICYmICF2aWRlby5wYXVzZWQgJiYgIXZpZGVvLmVuZGVkICYmIHZpZGVvLnJlYWR5U3RhdGUgPiAyO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBKdXN0IHRyaWVzIHRvIHBsYXkgdGhlIHZpZGVvIGFuZCBsb2dzIGFueSBlcnJvcnMuXG4gICAgICAgICAqIFRoZSBwbGF5IGNhbGwgaXMgb25seSBtYWRlIGlzIHRoZSB2aWRlbyBpcyBub3QgYWxyZWFkeSBwbGF5aW5nLlxuICAgICAgICAgKi9cbiAgICAgICAgdHJ5UGxheVZpZGVvKHZpZGVvRWxlbWVudCkge1xuICAgICAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc1ZpZGVvUGxheWluZyh2aWRlb0VsZW1lbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignVHJ5aW5nIHRvIHBsYXkgdmlkZW8gdGhhdCBpcyBhbHJlYWR5IHBsYXlpbmcuJyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgeWllbGQgdmlkZW9FbGVtZW50LnBsYXkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKF9hKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignSXQgd2FzIG5vdCBwb3NzaWJsZSB0byBwbGF5IHRoZSB2aWRlby4nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogU2VhcmNoZXMgYW5kIHZhbGlkYXRlcyBhIG1lZGlhIGVsZW1lbnQuXG4gICAgICAgICAqL1xuICAgICAgICBnZXRNZWRpYUVsZW1lbnQobWVkaWFFbGVtZW50SWQsIHR5cGUpIHtcbiAgICAgICAgICAgIGNvbnN0IG1lZGlhRWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKG1lZGlhRWxlbWVudElkKTtcbiAgICAgICAgICAgIGlmICghbWVkaWFFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEFyZ3VtZW50RXhjZXB0aW9uKGBlbGVtZW50IHdpdGggaWQgJyR7bWVkaWFFbGVtZW50SWR9JyBub3QgZm91bmRgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZWRpYUVsZW1lbnQubm9kZU5hbWUudG9Mb3dlckNhc2UoKSAhPT0gdHlwZS50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEFyZ3VtZW50RXhjZXB0aW9uKGBlbGVtZW50IHdpdGggaWQgJyR7bWVkaWFFbGVtZW50SWR9JyBtdXN0IGJlIGFuICR7dHlwZX0gZWxlbWVudGApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1lZGlhRWxlbWVudDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyB0aGUgYmFyY29kZSBmcm9tIGFuIGltYWdlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0geyhzdHJpbmd8SFRNTEltYWdlRWxlbWVudCl9IFtzb3VyY2VdIFRoZSBpbWFnZSBlbGVtZW50IHRoYXQgY2FuIGJlIGVpdGhlciBhbiBlbGVtZW50IGlkIG9yIHRoZSBlbGVtZW50IGl0c2VsZi4gQ2FuIGJlIHVuZGVmaW5lZCBpbiB3aGljaCBjYXNlIHRoZSBkZWNvZGluZyB3aWxsIGJlIGRvbmUgZnJvbSB0aGUgaW1hZ2VVcmwgcGFyYW1ldGVyLlxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3VybF1cbiAgICAgICAgICogQHJldHVybnMge1Byb21pc2U8UmVzdWx0Pn0gVGhlIGRlY29kaW5nIHJlc3VsdC5cbiAgICAgICAgICpcbiAgICAgICAgICogQG1lbWJlck9mIEJyb3dzZXJDb2RlUmVhZGVyXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGVGcm9tSW1hZ2Uoc291cmNlLCB1cmwpIHtcbiAgICAgICAgICAgIGlmICghc291cmNlICYmICF1cmwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQXJndW1lbnRFeGNlcHRpb24oJ2VpdGhlciBpbWFnZUVsZW1lbnQgd2l0aCBhIHNyYyBzZXQgb3IgYW4gdXJsIG11c3QgYmUgcHJvdmlkZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh1cmwgJiYgIXNvdXJjZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZUZyb21JbWFnZVVybCh1cmwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlRnJvbUltYWdlRWxlbWVudChzb3VyY2UpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIHRoZSBiYXJjb2RlIGZyb20gYSB2aWRlby5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHsoc3RyaW5nfEhUTUxJbWFnZUVsZW1lbnQpfSBbc291cmNlXSBUaGUgaW1hZ2UgZWxlbWVudCB0aGF0IGNhbiBiZSBlaXRoZXIgYW4gZWxlbWVudCBpZCBvciB0aGUgZWxlbWVudCBpdHNlbGYuIENhbiBiZSB1bmRlZmluZWQgaW4gd2hpY2ggY2FzZSB0aGUgZGVjb2Rpbmcgd2lsbCBiZSBkb25lIGZyb20gdGhlIGltYWdlVXJsIHBhcmFtZXRlci5cbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IFt1cmxdXG4gICAgICAgICAqIEByZXR1cm5zIHtQcm9taXNlPFJlc3VsdD59IFRoZSBkZWNvZGluZyByZXN1bHQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBtZW1iZXJPZiBCcm93c2VyQ29kZVJlYWRlclxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlRnJvbVZpZGVvKHNvdXJjZSwgdXJsKSB7XG4gICAgICAgICAgICBpZiAoIXNvdXJjZSAmJiAhdXJsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEFyZ3VtZW50RXhjZXB0aW9uKCdFaXRoZXIgYW4gZWxlbWVudCB3aXRoIGEgc3JjIHNldCBvciBhbiBVUkwgbXVzdCBiZSBwcm92aWRlZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHVybCAmJiAhc291cmNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlRnJvbVZpZGVvVXJsKHVybCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGVGcm9tVmlkZW9FbGVtZW50KHNvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgY29udGludW91c2x5IHRoZSBiYXJjb2RlIGZyb20gYSB2aWRlby5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHsoc3RyaW5nfEhUTUxJbWFnZUVsZW1lbnQpfSBbc291cmNlXSBUaGUgaW1hZ2UgZWxlbWVudCB0aGF0IGNhbiBiZSBlaXRoZXIgYW4gZWxlbWVudCBpZCBvciB0aGUgZWxlbWVudCBpdHNlbGYuIENhbiBiZSB1bmRlZmluZWQgaW4gd2hpY2ggY2FzZSB0aGUgZGVjb2Rpbmcgd2lsbCBiZSBkb25lIGZyb20gdGhlIGltYWdlVXJsIHBhcmFtZXRlci5cbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IFt1cmxdXG4gICAgICAgICAqIEByZXR1cm5zIHtQcm9taXNlPFJlc3VsdD59IFRoZSBkZWNvZGluZyByZXN1bHQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBtZW1iZXJPZiBCcm93c2VyQ29kZVJlYWRlclxuICAgICAgICAgKlxuICAgICAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGVGcm9tVmlkZW9Db250aW51b3VzbHkoc291cmNlLCB1cmwsIGNhbGxiYWNrRm4pIHtcbiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IHNvdXJjZSAmJiB1bmRlZmluZWQgPT09IHVybCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBBcmd1bWVudEV4Y2VwdGlvbignRWl0aGVyIGFuIGVsZW1lbnQgd2l0aCBhIHNyYyBzZXQgb3IgYW4gVVJMIG11c3QgYmUgcHJvdmlkZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh1cmwgJiYgIXNvdXJjZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZUZyb21WaWRlb1VybENvbnRpbnVvdXNseSh1cmwsIGNhbGxiYWNrRm4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlRnJvbVZpZGVvRWxlbWVudENvbnRpbnVvdXNseShzb3VyY2UsIGNhbGxiYWNrRm4pO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIHNvbWV0aGluZyBmcm9tIGFuIGltYWdlIEhUTUwgZWxlbWVudC5cbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZUZyb21JbWFnZUVsZW1lbnQoc291cmNlKSB7XG4gICAgICAgICAgICBpZiAoIXNvdXJjZSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBBcmd1bWVudEV4Y2VwdGlvbignQW4gaW1hZ2UgZWxlbWVudCBtdXN0IGJlIHByb3ZpZGVkLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yZXNldCgpO1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMucHJlcGFyZUltYWdlRWxlbWVudChzb3VyY2UpO1xuICAgICAgICAgICAgdGhpcy5pbWFnZUVsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgICAgICAgbGV0IHRhc2s7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0ltYWdlTG9hZGVkKGVsZW1lbnQpKSB7XG4gICAgICAgICAgICAgICAgdGFzayA9IHRoaXMuZGVjb2RlT25jZShlbGVtZW50LCBmYWxzZSwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0YXNrID0gdGhpcy5fZGVjb2RlT25Mb2FkSW1hZ2UoZWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGFzaztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBzb21ldGhpbmcgZnJvbSBhbiBpbWFnZSBIVE1MIGVsZW1lbnQuXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGVGcm9tVmlkZW9FbGVtZW50KHNvdXJjZSkge1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuX2RlY29kZUZyb21WaWRlb0VsZW1lbnRTZXR1cChzb3VyY2UpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2RlY29kZU9uTG9hZFZpZGVvKGVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIHNvbWV0aGluZyBmcm9tIGFuIGltYWdlIEhUTUwgZWxlbWVudC5cbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZUZyb21WaWRlb0VsZW1lbnRDb250aW51b3VzbHkoc291cmNlLCBjYWxsYmFja0ZuKSB7XG4gICAgICAgICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5fZGVjb2RlRnJvbVZpZGVvRWxlbWVudFNldHVwKHNvdXJjZSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fZGVjb2RlT25Mb2FkVmlkZW9Db250aW51b3VzbHkoZWxlbWVudCwgY2FsbGJhY2tGbik7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNldHMgdXAgdGhlIHZpZGVvIHNvdXJjZSBzbyBpdCBjYW4gYmUgZGVjb2RlZCB3aGVuIGxvYWRlZC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHNvdXJjZSBUaGUgdmlkZW8gc291cmNlIGVsZW1lbnQuXG4gICAgICAgICAqL1xuICAgICAgICBfZGVjb2RlRnJvbVZpZGVvRWxlbWVudFNldHVwKHNvdXJjZSkge1xuICAgICAgICAgICAgaWYgKCFzb3VyY2UpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQXJndW1lbnRFeGNlcHRpb24oJ0EgdmlkZW8gZWxlbWVudCBtdXN0IGJlIHByb3ZpZGVkLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yZXNldCgpO1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMucHJlcGFyZVZpZGVvRWxlbWVudChzb3VyY2UpO1xuICAgICAgICAgICAgLy8gZGVmaW5lcyB0aGUgdmlkZW8gZWxlbWVudCBiZWZvcmUgc3RhcnRzIGRlY29kaW5nXG4gICAgICAgICAgICB0aGlzLnZpZGVvRWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgICAgICByZXR1cm4gZWxlbWVudDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhbiBpbWFnZSBmcm9tIGEgVVJMLlxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlRnJvbUltYWdlVXJsKHVybCkge1xuICAgICAgICAgICAgaWYgKCF1cmwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQXJndW1lbnRFeGNlcHRpb24oJ0FuIFVSTCBtdXN0IGJlIHByb3ZpZGVkLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yZXNldCgpO1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMucHJlcGFyZUltYWdlRWxlbWVudCgpO1xuICAgICAgICAgICAgdGhpcy5pbWFnZUVsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgICAgICAgY29uc3QgZGVjb2RlVGFzayA9IHRoaXMuX2RlY29kZU9uTG9hZEltYWdlKGVsZW1lbnQpO1xuICAgICAgICAgICAgZWxlbWVudC5zcmMgPSB1cmw7XG4gICAgICAgICAgICByZXR1cm4gZGVjb2RlVGFzaztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhbiBpbWFnZSBmcm9tIGEgVVJMLlxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlRnJvbVZpZGVvVXJsKHVybCkge1xuICAgICAgICAgICAgaWYgKCF1cmwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQXJndW1lbnRFeGNlcHRpb24oJ0FuIFVSTCBtdXN0IGJlIHByb3ZpZGVkLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yZXNldCgpO1xuICAgICAgICAgICAgLy8gY3JlYXRlcyBhIG5ldyBlbGVtZW50XG4gICAgICAgICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5wcmVwYXJlVmlkZW9FbGVtZW50KCk7XG4gICAgICAgICAgICBjb25zdCBkZWNvZGVUYXNrID0gdGhpcy5kZWNvZGVGcm9tVmlkZW9FbGVtZW50KGVsZW1lbnQpO1xuICAgICAgICAgICAgZWxlbWVudC5zcmMgPSB1cmw7XG4gICAgICAgICAgICByZXR1cm4gZGVjb2RlVGFzaztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhbiBpbWFnZSBmcm9tIGEgVVJMLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGVGcm9tVmlkZW9VcmxDb250aW51b3VzbHkodXJsLCBjYWxsYmFja0ZuKSB7XG4gICAgICAgICAgICBpZiAoIXVybCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBBcmd1bWVudEV4Y2VwdGlvbignQW4gVVJMIG11c3QgYmUgcHJvdmlkZWQuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgICAgICAgICAvLyBjcmVhdGVzIGEgbmV3IGVsZW1lbnRcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLnByZXBhcmVWaWRlb0VsZW1lbnQoKTtcbiAgICAgICAgICAgIGNvbnN0IGRlY29kZVRhc2sgPSB0aGlzLmRlY29kZUZyb21WaWRlb0VsZW1lbnRDb250aW51b3VzbHkoZWxlbWVudCwgY2FsbGJhY2tGbik7XG4gICAgICAgICAgICBlbGVtZW50LnNyYyA9IHVybDtcbiAgICAgICAgICAgIHJldHVybiBkZWNvZGVUYXNrO1xuICAgICAgICB9XG4gICAgICAgIF9kZWNvZGVPbkxvYWRJbWFnZShlbGVtZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuaW1hZ2VMb2FkZWRMaXN0ZW5lciA9ICgpID0+IHRoaXMuZGVjb2RlT25jZShlbGVtZW50LCBmYWxzZSwgdHJ1ZSkudGhlbihyZXNvbHZlLCByZWplY3QpO1xuICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIHRoaXMuaW1hZ2VMb2FkZWRMaXN0ZW5lcik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBfZGVjb2RlT25Mb2FkVmlkZW8odmlkZW9FbGVtZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgICAgICAgICAgIC8vIHBsYXlzIHRoZSB2aWRlb1xuICAgICAgICAgICAgICAgIHlpZWxkIHRoaXMucGxheVZpZGVvT25Mb2FkQXN5bmModmlkZW9FbGVtZW50KTtcbiAgICAgICAgICAgICAgICAvLyBzdGFydHMgZGVjb2RpbmcgYWZ0ZXIgcGxheWVkIHRoZSB2aWRlb1xuICAgICAgICAgICAgICAgIHJldHVybiB5aWVsZCB0aGlzLmRlY29kZU9uY2UodmlkZW9FbGVtZW50KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIF9kZWNvZGVPbkxvYWRWaWRlb0NvbnRpbnVvdXNseSh2aWRlb0VsZW1lbnQsIGNhbGxiYWNrRm4pIHtcbiAgICAgICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgICAgICAgICAgLy8gcGxheXMgdGhlIHZpZGVvXG4gICAgICAgICAgICAgICAgeWllbGQgdGhpcy5wbGF5VmlkZW9PbkxvYWRBc3luYyh2aWRlb0VsZW1lbnQpO1xuICAgICAgICAgICAgICAgIC8vIHN0YXJ0cyBkZWNvZGluZyBhZnRlciBwbGF5ZWQgdGhlIHZpZGVvXG4gICAgICAgICAgICAgICAgdGhpcy5kZWNvZGVDb250aW51b3VzbHkodmlkZW9FbGVtZW50LCBjYWxsYmFja0ZuKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlzSW1hZ2VMb2FkZWQoaW1nKSB7XG4gICAgICAgICAgICAvLyBEdXJpbmcgdGhlIG9ubG9hZCBldmVudCwgSUUgY29ycmVjdGx5IGlkZW50aWZpZXMgYW55IGltYWdlcyB0aGF0XG4gICAgICAgICAgICAvLyB3ZXJlbuKAmXQgZG93bmxvYWRlZCBhcyBub3QgY29tcGxldGUuIE90aGVycyBzaG91bGQgdG9vLiBHZWNrby1iYXNlZFxuICAgICAgICAgICAgLy8gYnJvd3NlcnMgYWN0IGxpa2UgTlM0IGluIHRoYXQgdGhleSByZXBvcnQgdGhpcyBpbmNvcnJlY3RseS5cbiAgICAgICAgICAgIGlmICghaW1nLmNvbXBsZXRlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSG93ZXZlciwgdGhleSBkbyBoYXZlIHR3byB2ZXJ5IHVzZWZ1bCBwcm9wZXJ0aWVzOiBuYXR1cmFsV2lkdGggYW5kXG4gICAgICAgICAgICAvLyBuYXR1cmFsSGVpZ2h0LiBUaGVzZSBnaXZlIHRoZSB0cnVlIHNpemUgb2YgdGhlIGltYWdlLiBJZiBpdCBmYWlsZWRcbiAgICAgICAgICAgIC8vIHRvIGxvYWQsIGVpdGhlciBvZiB0aGVzZSBzaG91bGQgYmUgemVyby5cbiAgICAgICAgICAgIGlmIChpbWcubmF0dXJhbFdpZHRoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gTm8gb3RoZXIgd2F5IG9mIGNoZWNraW5nOiBhc3N1bWUgaXTigJlzIG9rLlxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcHJlcGFyZUltYWdlRWxlbWVudChpbWFnZVNvdXJjZSkge1xuICAgICAgICAgICAgbGV0IGltYWdlRWxlbWVudDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgaW1hZ2VTb3VyY2UgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgaW1hZ2VFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW1nJyk7XG4gICAgICAgICAgICAgICAgaW1hZ2VFbGVtZW50LndpZHRoID0gMjAwO1xuICAgICAgICAgICAgICAgIGltYWdlRWxlbWVudC5oZWlnaHQgPSAyMDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIGltYWdlU291cmNlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIGltYWdlRWxlbWVudCA9IHRoaXMuZ2V0TWVkaWFFbGVtZW50KGltYWdlU291cmNlLCAnaW1nJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaW1hZ2VTb3VyY2UgaW5zdGFuY2VvZiBIVE1MSW1hZ2VFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgaW1hZ2VFbGVtZW50ID0gaW1hZ2VTb3VyY2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaW1hZ2VFbGVtZW50O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZXRzIGEgSFRNTFZpZGVvRWxlbWVudCBmb3Igc2Nhbm5pbmcgb3IgY3JlYXRlcyBhIG5ldyBvbmUuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB2aWRlb1NvdXJjZSBUaGUgSFRNTFZpZGVvRWxlbWVudCB0byBiZSBzZXQuXG4gICAgICAgICAqL1xuICAgICAgICBwcmVwYXJlVmlkZW9FbGVtZW50KHZpZGVvU291cmNlKSB7XG4gICAgICAgICAgICBsZXQgdmlkZW9FbGVtZW50O1xuICAgICAgICAgICAgaWYgKCF2aWRlb1NvdXJjZSAmJiB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgdmlkZW9FbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcbiAgICAgICAgICAgICAgICB2aWRlb0VsZW1lbnQud2lkdGggPSAyMDA7XG4gICAgICAgICAgICAgICAgdmlkZW9FbGVtZW50LmhlaWdodCA9IDIwMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdmlkZW9Tb3VyY2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdmlkZW9FbGVtZW50ID0gdGhpcy5nZXRNZWRpYUVsZW1lbnQodmlkZW9Tb3VyY2UsICd2aWRlbycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHZpZGVvU291cmNlIGluc3RhbmNlb2YgSFRNTFZpZGVvRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHZpZGVvRWxlbWVudCA9IHZpZGVvU291cmNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gTmVlZGVkIGZvciBpT1MgMTFcbiAgICAgICAgICAgIHZpZGVvRWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2F1dG9wbGF5JywgJ3RydWUnKTtcbiAgICAgICAgICAgIHZpZGVvRWxlbWVudC5zZXRBdHRyaWJ1dGUoJ211dGVkJywgJ3RydWUnKTtcbiAgICAgICAgICAgIHZpZGVvRWxlbWVudC5zZXRBdHRyaWJ1dGUoJ3BsYXlzaW5saW5lJywgJ3RydWUnKTtcbiAgICAgICAgICAgIHJldHVybiB2aWRlb0VsZW1lbnQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRyaWVzIHRvIGRlY29kZSBmcm9tIHRoZSB2aWRlbyBpbnB1dCB1bnRpbCBpdCBmaW5kcyBzb21lIHZhbHVlLlxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlT25jZShlbGVtZW50LCByZXRyeUlmTm90Rm91bmQgPSB0cnVlLCByZXRyeUlmQ2hlY2tzdW1PckZvcm1hdEVycm9yID0gdHJ1ZSkge1xuICAgICAgICAgICAgdGhpcy5fc3RvcEFzeW5jRGVjb2RlID0gZmFsc2U7XG4gICAgICAgICAgICBjb25zdCBsb29wID0gKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9zdG9wQXN5bmNEZWNvZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBOb3RGb3VuZEV4Y2VwdGlvbignVmlkZW8gc3RyZWFtIGhhcyBlbmRlZCBiZWZvcmUgYW55IGNvZGUgY291bGQgYmUgZGV0ZWN0ZWQuJykpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zdG9wQXN5bmNEZWNvZGUgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5kZWNvZGUoZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUocmVzdWx0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaWZOb3RGb3VuZCA9IHJldHJ5SWZOb3RGb3VuZCAmJiBlIGluc3RhbmNlb2YgTm90Rm91bmRFeGNlcHRpb247XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGlzQ2hlY2tzdW1PckZvcm1hdEVycm9yID0gZSBpbnN0YW5jZW9mIENoZWNrc3VtRXhjZXB0aW9uIHx8IGUgaW5zdGFuY2VvZiBGb3JtYXRFeGNlcHRpb247XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGlmQ2hlY2tzdW1PckZvcm1hdCA9IGlzQ2hlY2tzdW1PckZvcm1hdEVycm9yICYmIHJldHJ5SWZDaGVja3N1bU9yRm9ybWF0RXJyb3I7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpZk5vdEZvdW5kIHx8IGlmQ2hlY2tzdW1PckZvcm1hdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdHJ5aW5nIGFnYWluXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2V0VGltZW91dChsb29wLCB0aGlzLl90aW1lQmV0d2VlbkRlY29kaW5nQXR0ZW1wdHMsIHJlc29sdmUsIHJlamVjdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4gbG9vcChyZXNvbHZlLCByZWplY3QpKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ29udGludW91c2x5IGRlY29kZXMgZnJvbSB2aWRlbyBpbnB1dC5cbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZUNvbnRpbnVvdXNseShlbGVtZW50LCBjYWxsYmFja0ZuKSB7XG4gICAgICAgICAgICB0aGlzLl9zdG9wQ29udGludW91c0RlY29kZSA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3QgbG9vcCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fc3RvcENvbnRpbnVvdXNEZWNvZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc3RvcENvbnRpbnVvdXNEZWNvZGUgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5kZWNvZGUoZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrRm4ocmVzdWx0LCBudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChsb29wLCB0aGlzLnRpbWVCZXR3ZWVuU2NhbnNNaWxsaXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFja0ZuKG51bGwsIGUpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBpc0NoZWNrc3VtT3JGb3JtYXRFcnJvciA9IGUgaW5zdGFuY2VvZiBDaGVja3N1bUV4Y2VwdGlvbiB8fCBlIGluc3RhbmNlb2YgRm9ybWF0RXhjZXB0aW9uO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBpc05vdEZvdW5kID0gZSBpbnN0YW5jZW9mIE5vdEZvdW5kRXhjZXB0aW9uO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNDaGVja3N1bU9yRm9ybWF0RXJyb3IgfHwgaXNOb3RGb3VuZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdHJ5aW5nIGFnYWluXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGxvb3AsIHRoaXMuX3RpbWVCZXR3ZWVuRGVjb2RpbmdBdHRlbXB0cyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgbG9vcCgpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHZXRzIHRoZSBCaW5hcnlCaXRtYXAgZm9yIHlhISAoYW5kIGRlY29kZXMgaXQpXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGUoZWxlbWVudCkge1xuICAgICAgICAgICAgLy8gZ2V0IGJpbmFyeSBiaXRtYXAgZm9yIGRlY29kZSBmdW5jdGlvblxuICAgICAgICAgICAgY29uc3QgYmluYXJ5Qml0bWFwID0gdGhpcy5jcmVhdGVCaW5hcnlCaXRtYXAoZWxlbWVudCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGVCaXRtYXAoYmluYXJ5Qml0bWFwKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogUmV0dXJucyB0cnVlIGlmIG1lZGlhIGVsZW1lbnQgaXMgaW5kZWVkIGEge0BsaW5rIEh0bWxWaWRlb0VsZW1lbnR9LlxuICAgICAgICAgKi9cbiAgICAgICAgX2lzSFRNTFZpZGVvRWxlbWVudChtZWRpYUVsZW1lbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHBvdGVudGlhbFZpZGVvID0gbWVkaWFFbGVtZW50O1xuICAgICAgICAgICAgcmV0dXJuIHBvdGVudGlhbFZpZGVvLnZpZGVvV2lkdGggIT09IDA7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE92ZXJ3cml0aW5nIHRoaXMgYWxsb3dzIHlvdSB0byBtYW5pcHVsYXRlIHRoZSBuZXh0IGZyYW1lIGluIGFueXdheVxuICAgICAgICAgKiB5b3Ugd2FudCBiZWZvcmUgZGVjb2RlLlxuICAgICAgICAgKi9cbiAgICAgICAgZHJhd0ZyYW1lT25DYW52YXMoXG4gICAgICAgICAgICBzcmNFbGVtZW50LCBkaW1lbnNpb25zLCBjYW52YXNFbGVtZW50Q29udGV4dCkge1xuICAgICAgICAgICAgaWYgKCFkaW1lbnNpb25zKSB7XG4gICAgICAgICAgICAgICAgZGltZW5zaW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgc3g6IDAsXG4gICAgICAgICAgICAgICAgICAgIHN5OiAwLFxuICAgICAgICAgICAgICAgICAgICBzV2lkdGg6IHNyY0VsZW1lbnQudmlkZW9XaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgc0hlaWdodDogc3JjRWxlbWVudC52aWRlb0hlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgZHg6IDAsXG4gICAgICAgICAgICAgICAgICAgIGR5OiAwLFxuICAgICAgICAgICAgICAgICAgICBkV2lkdGg6IHNyY0VsZW1lbnQudmlkZW9XaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgZEhlaWdodDogc3JjRWxlbWVudC52aWRlb0hlaWdodH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWNhbnZhc0VsZW1lbnRDb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgY2FudmFzRWxlbWVudENvbnRleHQgPSB0aGlzLmNhcHR1cmVDYW52YXNDb250ZXh0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FudmFzRWxlbWVudENvbnRleHQuZHJhd0ltYWdlKFxuICAgICAgICAgICAgICAgIHNyY0VsZW1lbnQsXG4gICAgICAgICAgICAgICAgZGltZW5zaW9ucy5zeCxcbiAgICAgICAgICAgICAgICBkaW1lbnNpb25zLnN5LFxuICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMuc1dpZHRoLFxuICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMuc0hlaWdodCxcbiAgICAgICAgICAgICAgICBkaW1lbnNpb25zLmR4LFxuICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMuZHksXG4gICAgICAgICAgICAgICAgZGltZW5zaW9ucy5kV2lkdGgsXG4gICAgICAgICAgICAgICAgZGltZW5zaW9ucy5kSGVpZ2h0KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogT3Zld3JpdGluZyB0aGlzIGFsbG93cyB5b3UgdG8gbWFuaXB1bGF0ZSB0aGUgc25hcHNob3QgaW1hZ2UgaW4gYW55d2F5XG4gICAgICAgICAqICB5b3Ugd2FudCBiZWZvcmUgZGVjb2RlLlxuICAgICAgICAgKi9cbiAgICAgICAgZHJhd0ltYWdlT25DYW52YXMoXG4gICAgICAgICAgICBzcmNFbGVtZW50LFxuICAgICAgICAgICAgZGltZW5zaW9ucyxcbiAgICAgICAgICAgIGNhbnZhc0VsZW1lbnRDb250ZXh0ID0gdGhpcy5jYXB0dXJlQ2FudmFzQ29udGV4dCkge1xuICAgICAgICAgICAgaWYgKCFkaW1lbnNpb25zKSB7XG4gICAgICAgICAgICAgICAgZGltZW5zaW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgc3g6IDAsXG4gICAgICAgICAgICAgICAgICAgIHN5OiAwLFxuICAgICAgICAgICAgICAgICAgICBzV2lkdGg6IHNyY0VsZW1lbnQubmF0dXJhbFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICBzSGVpZ2h0OiBzcmNFbGVtZW50Lm5hdHVyYWxIZWlnaHQsXG4gICAgICAgICAgICAgICAgICAgIGR4OiAwLFxuICAgICAgICAgICAgICAgICAgICBkeTogMCxcbiAgICAgICAgICAgICAgICAgICAgZFdpZHRoOiBzcmNFbGVtZW50Lm5hdHVyYWxXaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgZEhlaWdodDogc3JjRWxlbWVudC5uYXR1cmFsSGVpZ2h0XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghY2FudmFzRWxlbWVudENvbnRleHQpIHtcbiAgICAgICAgICAgICAgICBjYW52YXNFbGVtZW50Q29udGV4dCA9IHRoaXMuY2FwdHVyZUNhbnZhc0NvbnRleHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYW52YXNFbGVtZW50Q29udGV4dC5kcmF3SW1hZ2UoXG4gICAgICAgICAgICAgICAgc3JjRWxlbWVudCxcbiAgICAgICAgICAgICAgICBkaW1lbnNpb25zLnN4LFxuICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMuc3ksXG4gICAgICAgICAgICAgICAgZGltZW5zaW9ucy5zV2lkdGgsXG4gICAgICAgICAgICAgICAgZGltZW5zaW9ucy5zSGVpZ2h0LFxuICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMuZHgsXG4gICAgICAgICAgICAgICAgZGltZW5zaW9ucy5keSxcbiAgICAgICAgICAgICAgICBkaW1lbnNpb25zLmRXaWR0aCxcbiAgICAgICAgICAgICAgICBkaW1lbnNpb25zLmRIZWlnaHQpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgYmluYXJ5Qml0bWFwIGJhc2VkIGluIHNvbWUgaW1hZ2Ugc291cmNlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gbWVkaWFFbGVtZW50IEhUTUwgZWxlbWVudCBjb250YWluaW5nIGRyYXdhYmxlIGltYWdlIHNvdXJjZS5cbiAgICAgICAgICovXG4gICAgICAgIGNyZWF0ZUJpbmFyeUJpdG1hcChtZWRpYUVsZW1lbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuZ2V0Q2FwdHVyZUNhbnZhc0NvbnRleHQobWVkaWFFbGVtZW50KTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9pc0hUTUxWaWRlb0VsZW1lbnQobWVkaWFFbGVtZW50KSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZHJhd0ZyYW1lT25DYW52YXMobWVkaWFFbGVtZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kcmF3SW1hZ2VPbkNhbnZhcyhtZWRpYUVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgY2FudmFzID0gdGhpcy5nZXRDYXB0dXJlQ2FudmFzKG1lZGlhRWxlbWVudCk7XG4gICAgICAgICAgICBjb25zdCBsdW1pbmFuY2VTb3VyY2UgPSBuZXcgSFRNTENhbnZhc0VsZW1lbnRMdW1pbmFuY2VTb3VyY2UoY2FudmFzKTtcbiAgICAgICAgICAgIGNvbnN0IGh5YnJpZEJpbmFyaXplciA9IG5ldyBIeWJyaWRCaW5hcml6ZXIobHVtaW5hbmNlU291cmNlKTtcblxuICAgICAgICAgICAgcmV0dXJuIG5ldyBCaW5hcnlCaXRtYXAoaHlicmlkQmluYXJpemVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGdldENhcHR1cmVDYW52YXNDb250ZXh0KG1lZGlhRWxlbWVudCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNhcHR1cmVDYW52YXNDb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZWxlbSA9IHRoaXMuZ2V0Q2FwdHVyZUNhbnZhcyhtZWRpYUVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGN0eCA9IGVsZW0uZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhcHR1cmVDYW52YXNDb250ZXh0ID0gY3R4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2FwdHVyZUNhbnZhc0NvbnRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Q2FwdHVyZUNhbnZhcyhtZWRpYUVsZW1lbnQpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5jYXB0dXJlQ2FudmFzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZWxlbSA9IHRoaXMuY3JlYXRlQ2FwdHVyZUNhbnZhcyhtZWRpYUVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FwdHVyZUNhbnZhcyA9IGVsZW07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jYXB0dXJlQ2FudmFzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDYWxsIHRoZSBlbmNhcHN1bGF0ZWQgcmVhZGVycyBkZWNvZGVcbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZUJpdG1hcChiaW5hcnlCaXRtYXApIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlYWRlci5kZWNvZGUoYmluYXJ5Qml0bWFwLCB0aGlzLl9oaW50cyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIPCflowgUHJlcGFyZXMgdGhlIGNhbnZhcyBmb3IgY2FwdHVyZSBhbmQgc2NhbiBmcmFtZXMuXG4gICAgICAgICAqL1xuICAgICAgICBjcmVhdGVDYXB0dXJlQ2FudmFzKG1lZGlhRWxlbWVudCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9kZXN0cm95Q2FwdHVyZUNhbnZhcygpO1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgY2FudmFzRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICAgICAgbGV0IHdpZHRoO1xuICAgICAgICAgICAgbGV0IGhlaWdodDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWVkaWFFbGVtZW50ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGlmIChtZWRpYUVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MVmlkZW9FbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHdpZHRoID0gbWVkaWFFbGVtZW50LnZpZGVvV2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIGhlaWdodCA9IG1lZGlhRWxlbWVudC52aWRlb0hlaWdodDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAobWVkaWFFbGVtZW50IGluc3RhbmNlb2YgSFRNTEltYWdlRWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICB3aWR0aCA9IG1lZGlhRWxlbWVudC5uYXR1cmFsV2lkdGggfHwgbWVkaWFFbGVtZW50LndpZHRoO1xuICAgICAgICAgICAgICAgICAgICBoZWlnaHQgPSBtZWRpYUVsZW1lbnQubmF0dXJhbEhlaWdodCB8fCBtZWRpYUVsZW1lbnQuaGVpZ2h0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbnZhc0VsZW1lbnQuc3R5bGUud2lkdGggPSB3aWR0aCArICdweCc7XG4gICAgICAgICAgICBjYW52YXNFbGVtZW50LnN0eWxlLmhlaWdodCA9IGhlaWdodCArICdweCc7XG4gICAgICAgICAgICBjYW52YXNFbGVtZW50LndpZHRoID0gd2lkdGg7XG4gICAgICAgICAgICBjYW52YXNFbGVtZW50LmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgICAgIHJldHVybiBjYW52YXNFbGVtZW50O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTdG9wcyB0aGUgY29udGludW91cyBzY2FuIGFuZCBjbGVhbnMgdGhlIHN0cmVhbS5cbiAgICAgICAgICovXG4gICAgICAgIHN0b3BTdHJlYW1zKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKHQgPT4gdC5zdG9wKCkpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX3N0b3BBc3luY0RlY29kZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0b3BBc3luY0RlY29kZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX3N0b3BDb250aW51b3VzRGVjb2RlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RvcENvbnRpbnVvdXNEZWNvZGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogUmVzZXRzIHRoZSBjb2RlIHJlYWRlciB0byB0aGUgaW5pdGlhbCBzdGF0ZS4gQ2FuY2VscyBhbnkgb25nb2luZyBiYXJjb2RlIHNjYW5uaW5nIGZyb20gdmlkZW8gb3IgY2FtZXJhLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAbWVtYmVyT2YgQnJvd3NlckNvZGVSZWFkZXJcbiAgICAgICAgICovXG4gICAgICAgIHJlc2V0KCkge1xuICAgICAgICAgICAgLy8gc3RvcHMgdGhlIGNhbWVyYSwgcHJldmlldyBhbmQgc2NhbiDwn5S0XG4gICAgICAgICAgICB0aGlzLnN0b3BTdHJlYW1zKCk7XG4gICAgICAgICAgICAvLyBjbGVhbiBhbmQgZm9yZ2V0IGFib3V0IEhUTUwgZWxlbWVudHNcbiAgICAgICAgICAgIHRoaXMuX2Rlc3Ryb3lWaWRlb0VsZW1lbnQoKTtcbiAgICAgICAgICAgIHRoaXMuX2Rlc3Ryb3lJbWFnZUVsZW1lbnQoKTtcbiAgICAgICAgICAgIHRoaXMuX2Rlc3Ryb3lDYXB0dXJlQ2FudmFzKCk7XG4gICAgICAgIH1cbiAgICAgICAgX2Rlc3Ryb3lWaWRlb0VsZW1lbnQoKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMudmlkZW9FbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZmlyc3QgZ2l2ZXMgZnJlZWRvbiB0byB0aGUgZWxlbWVudCDwn5WKXG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMudmlkZW9FbmRlZExpc3RlbmVyICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9FbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2VuZGVkJywgdGhpcy52aWRlb0VuZGVkTGlzdGVuZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLnZpZGVvUGxheWluZ0V2ZW50TGlzdGVuZXIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0VsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigncGxheWluZycsIHRoaXMudmlkZW9QbGF5aW5nRXZlbnRMaXN0ZW5lcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMudmlkZW9DYW5QbGF5TGlzdGVuZXIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0VsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbG9hZGVkbWV0YWRhdGEnLCB0aGlzLnZpZGVvQ2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHRoZW4gZm9yZ2V0cyBhYm91dCB0aGF0IGVsZW1lbnQg8J+YolxuICAgICAgICAgICAgdGhpcy5jbGVhblZpZGVvU291cmNlKHRoaXMudmlkZW9FbGVtZW50KTtcbiAgICAgICAgICAgIHRoaXMudmlkZW9FbGVtZW50ID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIF9kZXN0cm95SW1hZ2VFbGVtZW50KCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmltYWdlRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGZpcnN0IGdpdmVzIGZyZWVkb24gdG8gdGhlIGVsZW1lbnQg8J+VilxuICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCAhPT0gdGhpcy5pbWFnZUxvYWRlZExpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbWFnZUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbG9hZCcsIHRoaXMuaW1hZ2VMb2FkZWRMaXN0ZW5lcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyB0aGVuIGZvcmdldCBhYm91dCB0aGF0IGVsZW1lbnQg8J+YolxuICAgICAgICAgICAgdGhpcy5pbWFnZUVsZW1lbnQuc3JjID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgdGhpcy5pbWFnZUVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKCdzcmMnKTtcbiAgICAgICAgICAgIHRoaXMuaW1hZ2VFbGVtZW50ID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDbGVhbnMgY2FudmFzIHJlZmVyZW5jZXMg8J+WjFxuICAgICAgICAgKi9cbiAgICAgICAgX2Rlc3Ryb3lDYXB0dXJlQ2FudmFzKCkge1xuICAgICAgICAgICAgLy8gdGhlbiBmb3JnZXQgYWJvdXQgdGhhdCBlbGVtZW50IPCfmKJcbiAgICAgICAgICAgIHRoaXMuY2FwdHVyZUNhbnZhc0NvbnRleHQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLmNhcHR1cmVDYW52YXMgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlZmluZXMgd2hhdCB0aGUgdmlkZW9FbGVtZW50IHNyYyB3aWxsIGJlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gdmlkZW9FbGVtZW50XG4gICAgICAgICAqIEBwYXJhbSBzdHJlYW1cbiAgICAgICAgICovXG4gICAgICAgIGFkZFZpZGVvU291cmNlKHZpZGVvRWxlbWVudCwgc3RyZWFtKSB7XG4gICAgICAgICAgICAvLyBPbGRlciBicm93c2VycyBtYXkgbm90IGhhdmUgYHNyY09iamVjdGBcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgLy8gQG5vdGUgVGhyb3dzIEV4Y2VwdGlvbiBpZiBpbnRlcnJ1cHRlZCBieSBhIG5ldyBsb2FkZWQgcmVxdWVzdFxuICAgICAgICAgICAgICAgIHZpZGVvRWxlbWVudC5zcmNPYmplY3QgPSBzdHJlYW07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgLy8gQG5vdGUgQXZvaWQgdXNpbmcgdGhpcyBpbiBuZXcgYnJvd3NlcnMsIGFzIGl0IGlzIGdvaW5nIGF3YXkuXG4gICAgICAgICAgICAgICAgdmlkZW9FbGVtZW50LnNyYyA9IFVSTC5jcmVhdGVPYmplY3RVUkwoc3RyZWFtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogVW5iaW5kcyBhIEhUTUwgdmlkZW8gc3JjIHByb3BlcnR5LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gdmlkZW9FbGVtZW50XG4gICAgICAgICAqL1xuICAgICAgICBjbGVhblZpZGVvU291cmNlKHZpZGVvRWxlbWVudCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2aWRlb0VsZW1lbnQuc3JjT2JqZWN0ID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICB2aWRlb0VsZW1lbnQuc3JjID0gJyc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnZpZGVvRWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoJ3NyYycpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiA8cD5FbmNhcHN1bGF0ZXMgdGhlIHJlc3VsdCBvZiBkZWNvZGluZyBhIGJhcmNvZGUgd2l0aGluIGFuIGltYWdlLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgUmVzdWx0IHtcbiAgICAgICAgLy8gcHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgdGV4dDogc3RyaW5nLFxuICAgICAgICAvLyAgICAgICAgICAgICAgIFVpbnQ4QXJyYXkgcmF3Qnl0ZXMsXG4gICAgICAgIC8vICAgICAgICAgICAgICAgUmVzdWx0UG9jb25zdCByZXN1bHRQb2ludHM6IEludDMyQXJyYXksXG4gICAgICAgIC8vICAgICAgICAgICAgICAgQmFyY29kZUZvcm1hdCBmb3JtYXQpIHtcbiAgICAgICAgLy8gICB0aGlzKHRleHQsIHJhd0J5dGVzLCByZXN1bHRQb2ludHMsIGZvcm1hdCwgU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCkpXG4gICAgICAgIC8vIH1cbiAgICAgICAgLy8gcHVibGljIGNvbnN0cnVjdG9yKHRleHQ6IHN0cmluZyxcbiAgICAgICAgLy8gICAgICAgICAgICAgICBVaW50OEFycmF5IHJhd0J5dGVzLFxuICAgICAgICAvLyAgICAgICAgICAgICAgIFJlc3VsdFBvY29uc3QgcmVzdWx0UG9pbnRzOiBJbnQzMkFycmF5LFxuICAgICAgICAvLyAgICAgICAgICAgICAgIEJhcmNvZGVGb3JtYXQgZm9ybWF0LFxuICAgICAgICAvLyAgICAgICAgICAgICAgIGxvbmcgdGltZXN0YW1wKSB7XG4gICAgICAgIC8vICAgdGhpcyh0ZXh0LCByYXdCeXRlcywgcmF3Qnl0ZXMgPT0gbnVsbCA/IDAgOiA4ICogcmF3Qnl0ZXMubGVuZ3RoLFxuICAgICAgICAvLyAgICAgICAgcmVzdWx0UG9pbnRzLCBmb3JtYXQsIHRpbWVzdGFtcClcbiAgICAgICAgLy8gfVxuICAgICAgICBjb25zdHJ1Y3Rvcih0ZXh0LCByYXdCeXRlcywgbnVtQml0cyA9IHJhd0J5dGVzID09IG51bGwgPyAwIDogOCAqIHJhd0J5dGVzLmxlbmd0aCwgcmVzdWx0UG9pbnRzLCBmb3JtYXQsIHRpbWVzdGFtcCA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpKSB7XG4gICAgICAgICAgICB0aGlzLnRleHQgPSB0ZXh0O1xuICAgICAgICAgICAgdGhpcy5yYXdCeXRlcyA9IHJhd0J5dGVzO1xuICAgICAgICAgICAgdGhpcy5udW1CaXRzID0gbnVtQml0cztcbiAgICAgICAgICAgIHRoaXMucmVzdWx0UG9pbnRzID0gcmVzdWx0UG9pbnRzO1xuICAgICAgICAgICAgdGhpcy5mb3JtYXQgPSBmb3JtYXQ7XG4gICAgICAgICAgICB0aGlzLnRpbWVzdGFtcCA9IHRpbWVzdGFtcDtcbiAgICAgICAgICAgIHRoaXMudGV4dCA9IHRleHQ7XG4gICAgICAgICAgICB0aGlzLnJhd0J5dGVzID0gcmF3Qnl0ZXM7XG4gICAgICAgICAgICBpZiAodW5kZWZpbmVkID09PSBudW1CaXRzIHx8IG51bGwgPT09IG51bUJpdHMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm51bUJpdHMgPSAocmF3Qnl0ZXMgPT09IG51bGwgfHwgcmF3Qnl0ZXMgPT09IHVuZGVmaW5lZCkgPyAwIDogOCAqIHJhd0J5dGVzLmxlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMubnVtQml0cyA9IG51bUJpdHM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnJlc3VsdFBvaW50cyA9IHJlc3VsdFBvaW50cztcbiAgICAgICAgICAgIHRoaXMuZm9ybWF0ID0gZm9ybWF0O1xuICAgICAgICAgICAgdGhpcy5yZXN1bHRNZXRhZGF0YSA9IG51bGw7XG4gICAgICAgICAgICBpZiAodW5kZWZpbmVkID09PSB0aW1lc3RhbXAgfHwgbnVsbCA9PT0gdGltZXN0YW1wKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50aW1lc3RhbXAgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMudGltZXN0YW1wID0gdGltZXN0YW1wO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHJhdyB0ZXh0IGVuY29kZWQgYnkgdGhlIGJhcmNvZGVcbiAgICAgICAgICovXG4gICAgICAgIGdldFRleHQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50ZXh0O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHJhdyBieXRlcyBlbmNvZGVkIGJ5IHRoZSBiYXJjb2RlLCBpZiBhcHBsaWNhYmxlLCBvdGhlcndpc2Uge0Bjb2RlIG51bGx9XG4gICAgICAgICAqL1xuICAgICAgICBnZXRSYXdCeXRlcygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJhd0J5dGVzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIGhvdyBtYW55IGJpdHMgb2Yge0BsaW5rICNnZXRSYXdCeXRlcygpfSBhcmUgdmFsaWQ7IHR5cGljYWxseSA4IHRpbWVzIGl0cyBsZW5ndGhcbiAgICAgICAgICogQHNpbmNlIDMuMy4wXG4gICAgICAgICAqL1xuICAgICAgICBnZXROdW1CaXRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubnVtQml0cztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBwb2ludHMgcmVsYXRlZCB0byB0aGUgYmFyY29kZSBpbiB0aGUgaW1hZ2UuIFRoZXNlIGFyZSB0eXBpY2FsbHkgcG9pbnRzXG4gICAgICAgICAqICAgICAgICAgaWRlbnRpZnlpbmcgZmluZGVyIHBhdHRlcm5zIG9yIHRoZSBjb3JuZXJzIG9mIHRoZSBiYXJjb2RlLiBUaGUgZXhhY3QgbWVhbmluZyBpc1xuICAgICAgICAgKiAgICAgICAgIHNwZWNpZmljIHRvIHRoZSB0eXBlIG9mIGJhcmNvZGUgdGhhdCB3YXMgZGVjb2RlZC5cbiAgICAgICAgICovXG4gICAgICAgIGdldFJlc3VsdFBvaW50cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlc3VsdFBvaW50cztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7QGxpbmsgQmFyY29kZUZvcm1hdH0gcmVwcmVzZW50aW5nIHRoZSBmb3JtYXQgb2YgdGhlIGJhcmNvZGUgdGhhdCB3YXMgZGVjb2RlZFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0QmFyY29kZUZvcm1hdCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZvcm1hdDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7QGxpbmsgTWFwfSBtYXBwaW5nIHtAbGluayBSZXN1bHRNZXRhZGF0YVR5cGV9IGtleXMgdG8gdmFsdWVzLiBNYXkgYmVcbiAgICAgICAgICogICB7QGNvZGUgbnVsbH0uIFRoaXMgY29udGFpbnMgb3B0aW9uYWwgbWV0YWRhdGEgYWJvdXQgd2hhdCB3YXMgZGV0ZWN0ZWQgYWJvdXQgdGhlIGJhcmNvZGUsXG4gICAgICAgICAqICAgbGlrZSBvcmllbnRhdGlvbi5cbiAgICAgICAgICovXG4gICAgICAgIGdldFJlc3VsdE1ldGFkYXRhKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVzdWx0TWV0YWRhdGE7XG4gICAgICAgIH1cbiAgICAgICAgcHV0TWV0YWRhdGEodHlwZSwgdmFsdWUpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlc3VsdE1ldGFkYXRhID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXN1bHRNZXRhZGF0YSA9IG5ldyBNYXAoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucmVzdWx0TWV0YWRhdGEuc2V0KHR5cGUsIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBwdXRBbGxNZXRhZGF0YShtZXRhZGF0YSkge1xuICAgICAgICAgICAgaWYgKG1ldGFkYXRhICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucmVzdWx0TWV0YWRhdGEgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXN1bHRNZXRhZGF0YSA9IG1ldGFkYXRhO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXN1bHRNZXRhZGF0YSA9IG5ldyBNYXAobWV0YWRhdGEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBhZGRSZXN1bHRQb2ludHMobmV3UG9pbnRzKSB7XG4gICAgICAgICAgICBjb25zdCBvbGRQb2ludHMgPSB0aGlzLnJlc3VsdFBvaW50cztcbiAgICAgICAgICAgIGlmIChvbGRQb2ludHMgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc3VsdFBvaW50cyA9IG5ld1BvaW50cztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKG5ld1BvaW50cyAhPT0gbnVsbCAmJiBuZXdQb2ludHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFsbFBvaW50cyA9IG5ldyBBcnJheShvbGRQb2ludHMubGVuZ3RoICsgbmV3UG9pbnRzLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weShvbGRQb2ludHMsIDAsIGFsbFBvaW50cywgMCwgb2xkUG9pbnRzLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weShuZXdQb2ludHMsIDAsIGFsbFBvaW50cywgb2xkUG9pbnRzLmxlbmd0aCwgbmV3UG9pbnRzLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXN1bHRQb2ludHMgPSBhbGxQb2ludHM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZ2V0VGltZXN0YW1wKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudGltZXN0YW1wO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50ZXh0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBEaXJlY3QgcG9ydCB0byBUeXBlU2NyaXB0IG9mIFpYaW5nIGJ5IEFkcmlhbiBUb8iZY8SDXG4gICAgICovXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwOSBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKm5hbWVzcGFjZSBjb20uZ29vZ2xlLnp4aW5nIHsqL1xuICAgIC8qKlxuICAgICAqIEVudW1lcmF0ZXMgYmFyY29kZSBmb3JtYXRzIGtub3duIHRvIHRoaXMgcGFja2FnZS4gUGxlYXNlIGtlZXAgYWxwaGFiZXRpemVkLlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICB2YXIgQmFyY29kZUZvcm1hdDtcbiAgICAoZnVuY3Rpb24gKEJhcmNvZGVGb3JtYXQpIHtcbiAgICAgICAgLyoqIEF6dGVjIDJEIGJhcmNvZGUgZm9ybWF0LiAqL1xuICAgICAgICBCYXJjb2RlRm9ybWF0W0JhcmNvZGVGb3JtYXRbXCJBWlRFQ1wiXSA9IDBdID0gXCJBWlRFQ1wiO1xuICAgICAgICAvKiogQ09EQUJBUiAxRCBmb3JtYXQuICovXG4gICAgICAgIEJhcmNvZGVGb3JtYXRbQmFyY29kZUZvcm1hdFtcIkNPREFCQVJcIl0gPSAxXSA9IFwiQ09EQUJBUlwiO1xuICAgICAgICAvKiogQ29kZSAzOSAxRCBmb3JtYXQuICovXG4gICAgICAgIEJhcmNvZGVGb3JtYXRbQmFyY29kZUZvcm1hdFtcIkNPREVfMzlcIl0gPSAyXSA9IFwiQ09ERV8zOVwiO1xuICAgICAgICAvKiogQ29kZSA5MyAxRCBmb3JtYXQuICovXG4gICAgICAgIEJhcmNvZGVGb3JtYXRbQmFyY29kZUZvcm1hdFtcIkNPREVfOTNcIl0gPSAzXSA9IFwiQ09ERV85M1wiO1xuICAgICAgICAvKiogQ29kZSAxMjggMUQgZm9ybWF0LiAqL1xuICAgICAgICBCYXJjb2RlRm9ybWF0W0JhcmNvZGVGb3JtYXRbXCJDT0RFXzEyOFwiXSA9IDRdID0gXCJDT0RFXzEyOFwiO1xuICAgICAgICAvKiogRGF0YSBNYXRyaXggMkQgYmFyY29kZSBmb3JtYXQuICovXG4gICAgICAgIEJhcmNvZGVGb3JtYXRbQmFyY29kZUZvcm1hdFtcIkRBVEFfTUFUUklYXCJdID0gNV0gPSBcIkRBVEFfTUFUUklYXCI7XG4gICAgICAgIC8qKiBFQU4tOCAxRCBmb3JtYXQuICovXG4gICAgICAgIEJhcmNvZGVGb3JtYXRbQmFyY29kZUZvcm1hdFtcIkVBTl84XCJdID0gNl0gPSBcIkVBTl84XCI7XG4gICAgICAgIC8qKiBFQU4tMTMgMUQgZm9ybWF0LiAqL1xuICAgICAgICBCYXJjb2RlRm9ybWF0W0JhcmNvZGVGb3JtYXRbXCJFQU5fMTNcIl0gPSA3XSA9IFwiRUFOXzEzXCI7XG4gICAgICAgIC8qKiBJVEYgKEludGVybGVhdmVkIFR3byBvZiBGaXZlKSAxRCBmb3JtYXQuICovXG4gICAgICAgIEJhcmNvZGVGb3JtYXRbQmFyY29kZUZvcm1hdFtcIklURlwiXSA9IDhdID0gXCJJVEZcIjtcbiAgICAgICAgLyoqIE1heGlDb2RlIDJEIGJhcmNvZGUgZm9ybWF0LiAqL1xuICAgICAgICBCYXJjb2RlRm9ybWF0W0JhcmNvZGVGb3JtYXRbXCJNQVhJQ09ERVwiXSA9IDldID0gXCJNQVhJQ09ERVwiO1xuICAgICAgICAvKiogUERGNDE3IGZvcm1hdC4gKi9cbiAgICAgICAgQmFyY29kZUZvcm1hdFtCYXJjb2RlRm9ybWF0W1wiUERGXzQxN1wiXSA9IDEwXSA9IFwiUERGXzQxN1wiO1xuICAgICAgICAvKiogUVIgQ29kZSAyRCBiYXJjb2RlIGZvcm1hdC4gKi9cbiAgICAgICAgQmFyY29kZUZvcm1hdFtCYXJjb2RlRm9ybWF0W1wiUVJfQ09ERVwiXSA9IDExXSA9IFwiUVJfQ09ERVwiO1xuICAgICAgICAvKiogUlNTIDE0ICovXG4gICAgICAgIEJhcmNvZGVGb3JtYXRbQmFyY29kZUZvcm1hdFtcIlJTU18xNFwiXSA9IDEyXSA9IFwiUlNTXzE0XCI7XG4gICAgICAgIC8qKiBSU1MgRVhQQU5ERUQgKi9cbiAgICAgICAgQmFyY29kZUZvcm1hdFtCYXJjb2RlRm9ybWF0W1wiUlNTX0VYUEFOREVEXCJdID0gMTNdID0gXCJSU1NfRVhQQU5ERURcIjtcbiAgICAgICAgLyoqIFVQQy1BIDFEIGZvcm1hdC4gKi9cbiAgICAgICAgQmFyY29kZUZvcm1hdFtCYXJjb2RlRm9ybWF0W1wiVVBDX0FcIl0gPSAxNF0gPSBcIlVQQ19BXCI7XG4gICAgICAgIC8qKiBVUEMtRSAxRCBmb3JtYXQuICovXG4gICAgICAgIEJhcmNvZGVGb3JtYXRbQmFyY29kZUZvcm1hdFtcIlVQQ19FXCJdID0gMTVdID0gXCJVUENfRVwiO1xuICAgICAgICAvKiogVVBDL0VBTiBleHRlbnNpb24gZm9ybWF0LiBOb3QgYSBzdGFuZC1hbG9uZSBmb3JtYXQuICovXG4gICAgICAgIEJhcmNvZGVGb3JtYXRbQmFyY29kZUZvcm1hdFtcIlVQQ19FQU5fRVhURU5TSU9OXCJdID0gMTZdID0gXCJVUENfRUFOX0VYVEVOU0lPTlwiO1xuICAgIH0pKEJhcmNvZGVGb3JtYXQgfHwgKEJhcmNvZGVGb3JtYXQgPSB7fSkpO1xuICAgIHZhciBCYXJjb2RlRm9ybWF0JDEgPSBCYXJjb2RlRm9ybWF0O1xuXG4gICAgLypuYW1lc3BhY2UgY29tLmdvb2dsZS56eGluZyB7Ki9cbiAgICAvKipcbiAgICAgKiBSZXByZXNlbnRzIHNvbWUgdHlwZSBvZiBtZXRhZGF0YSBhYm91dCB0aGUgcmVzdWx0IG9mIHRoZSBkZWNvZGluZyB0aGF0IHRoZSBkZWNvZGVyXG4gICAgICogd2lzaGVzIHRvIGNvbW11bmljYXRlIGJhY2sgdG8gdGhlIGNhbGxlci5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgdmFyIFJlc3VsdE1ldGFkYXRhVHlwZTtcbiAgICAoZnVuY3Rpb24gKFJlc3VsdE1ldGFkYXRhVHlwZSkge1xuICAgICAgICAvKipcbiAgICAgICAgICogVW5zcGVjaWZpZWQsIGFwcGxpY2F0aW9uLXNwZWNpZmljIG1ldGFkYXRhLiBNYXBzIHRvIGFuIHVuc3BlY2lmaWVkIHtAbGluayBPYmplY3R9LlxuICAgICAgICAgKi9cbiAgICAgICAgUmVzdWx0TWV0YWRhdGFUeXBlW1Jlc3VsdE1ldGFkYXRhVHlwZVtcIk9USEVSXCJdID0gMF0gPSBcIk9USEVSXCI7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZW5vdGVzIHRoZSBsaWtlbHkgYXBwcm94aW1hdGUgb3JpZW50YXRpb24gb2YgdGhlIGJhcmNvZGUgaW4gdGhlIGltYWdlLiBUaGlzIHZhbHVlXG4gICAgICAgICAqIGlzIGdpdmVuIGFzIGRlZ3JlZXMgcm90YXRlZCBjbG9ja3dpc2UgZnJvbSB0aGUgbm9ybWFsLCB1cHJpZ2h0IG9yaWVudGF0aW9uLlxuICAgICAgICAgKiBGb3IgZXhhbXBsZSBhIDFEIGJhcmNvZGUgd2hpY2ggd2FzIGZvdW5kIGJ5IHJlYWRpbmcgdG9wLXRvLWJvdHRvbSB3b3VsZCBiZVxuICAgICAgICAgKiBzYWlkIHRvIGhhdmUgb3JpZW50YXRpb24gXCI5MFwiLiBUaGlzIGtleSBtYXBzIHRvIGFuIHtAbGluayBJbnRlZ2VyfSB3aG9zZVxuICAgICAgICAgKiB2YWx1ZSBpcyBpbiB0aGUgcmFuZ2UgWzAsMzYwKS5cbiAgICAgICAgICovXG4gICAgICAgIFJlc3VsdE1ldGFkYXRhVHlwZVtSZXN1bHRNZXRhZGF0YVR5cGVbXCJPUklFTlRBVElPTlwiXSA9IDFdID0gXCJPUklFTlRBVElPTlwiO1xuICAgICAgICAvKipcbiAgICAgICAgICogPHA+MkQgYmFyY29kZSBmb3JtYXRzIHR5cGljYWxseSBlbmNvZGUgdGV4dCwgYnV0IGFsbG93IGZvciBhIHNvcnQgb2YgJ2J5dGUgbW9kZSdcbiAgICAgICAgICogd2hpY2ggaXMgc29tZXRpbWVzIHVzZWQgdG8gZW5jb2RlIGJpbmFyeSBkYXRhLiBXaGlsZSB7QGxpbmsgUmVzdWx0fSBtYWtlcyBhdmFpbGFibGVcbiAgICAgICAgICogdGhlIGNvbXBsZXRlIHJhdyBieXRlcyBpbiB0aGUgYmFyY29kZSBmb3IgdGhlc2UgZm9ybWF0cywgaXQgZG9lcyBub3Qgb2ZmZXIgdGhlIGJ5dGVzXG4gICAgICAgICAqIGZyb20gdGhlIGJ5dGUgc2VnbWVudHMgYWxvbmUuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiA8cD5UaGlzIG1hcHMgdG8gYSB7QGxpbmsgamF2YS51dGlsLkxpc3R9IG9mIGJ5dGUgYXJyYXlzIGNvcnJlc3BvbmRpbmcgdG8gdGhlXG4gICAgICAgICAqIHJhdyBieXRlcyBpbiB0aGUgYnl0ZSBzZWdtZW50cyBpbiB0aGUgYmFyY29kZSwgaW4gb3JkZXIuPC9wPlxuICAgICAgICAgKi9cbiAgICAgICAgUmVzdWx0TWV0YWRhdGFUeXBlW1Jlc3VsdE1ldGFkYXRhVHlwZVtcIkJZVEVfU0VHTUVOVFNcIl0gPSAyXSA9IFwiQllURV9TRUdNRU5UU1wiO1xuICAgICAgICAvKipcbiAgICAgICAgICogRXJyb3IgY29ycmVjdGlvbiBsZXZlbCB1c2VkLCBpZiBhcHBsaWNhYmxlLiBUaGUgdmFsdWUgdHlwZSBkZXBlbmRzIG9uIHRoZVxuICAgICAgICAgKiBmb3JtYXQsIGJ1dCBpcyB0eXBpY2FsbHkgYSBTdHJpbmcuXG4gICAgICAgICAqL1xuICAgICAgICBSZXN1bHRNZXRhZGF0YVR5cGVbUmVzdWx0TWV0YWRhdGFUeXBlW1wiRVJST1JfQ09SUkVDVElPTl9MRVZFTFwiXSA9IDNdID0gXCJFUlJPUl9DT1JSRUNUSU9OX0xFVkVMXCI7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBGb3Igc29tZSBwZXJpb2RpY2FscywgaW5kaWNhdGVzIHRoZSBpc3N1ZSBudW1iZXIgYXMgYW4ge0BsaW5rIEludGVnZXJ9LlxuICAgICAgICAgKi9cbiAgICAgICAgUmVzdWx0TWV0YWRhdGFUeXBlW1Jlc3VsdE1ldGFkYXRhVHlwZVtcIklTU1VFX05VTUJFUlwiXSA9IDRdID0gXCJJU1NVRV9OVU1CRVJcIjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEZvciBzb21lIHByb2R1Y3RzLCBpbmRpY2F0ZXMgdGhlIHN1Z2dlc3RlZCByZXRhaWwgcHJpY2UgaW4gdGhlIGJhcmNvZGUgYXMgYVxuICAgICAgICAgKiBmb3JtYXR0ZWQge0BsaW5rIFN0cmluZ30uXG4gICAgICAgICAqL1xuICAgICAgICBSZXN1bHRNZXRhZGF0YVR5cGVbUmVzdWx0TWV0YWRhdGFUeXBlW1wiU1VHR0VTVEVEX1BSSUNFXCJdID0gNV0gPSBcIlNVR0dFU1RFRF9QUklDRVwiO1xuICAgICAgICAvKipcbiAgICAgICAgICogRm9yIHNvbWUgcHJvZHVjdHMsIHRoZSBwb3NzaWJsZSBjb3VudHJ5IG9mIG1hbnVmYWN0dXJlIGFzIGEge0BsaW5rIFN0cmluZ30gZGVub3RpbmcgdGhlXG4gICAgICAgICAqIElTTyBjb3VudHJ5IGNvZGUuIFNvbWUgbWFwIHRvIG11bHRpcGxlIHBvc3NpYmxlIGNvdW50cmllcywgbGlrZSBcIlVTL0NBXCIuXG4gICAgICAgICAqL1xuICAgICAgICBSZXN1bHRNZXRhZGF0YVR5cGVbUmVzdWx0TWV0YWRhdGFUeXBlW1wiUE9TU0lCTEVfQ09VTlRSWVwiXSA9IDZdID0gXCJQT1NTSUJMRV9DT1VOVFJZXCI7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBGb3Igc29tZSBwcm9kdWN0cywgdGhlIGV4dGVuc2lvbiB0ZXh0XG4gICAgICAgICAqL1xuICAgICAgICBSZXN1bHRNZXRhZGF0YVR5cGVbUmVzdWx0TWV0YWRhdGFUeXBlW1wiVVBDX0VBTl9FWFRFTlNJT05cIl0gPSA3XSA9IFwiVVBDX0VBTl9FWFRFTlNJT05cIjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFBERjQxNy1zcGVjaWZpYyBtZXRhZGF0YVxuICAgICAgICAgKi9cbiAgICAgICAgUmVzdWx0TWV0YWRhdGFUeXBlW1Jlc3VsdE1ldGFkYXRhVHlwZVtcIlBERjQxN19FWFRSQV9NRVRBREFUQVwiXSA9IDhdID0gXCJQREY0MTdfRVhUUkFfTUVUQURBVEFcIjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIElmIHRoZSBjb2RlIGZvcm1hdCBzdXBwb3J0cyBzdHJ1Y3R1cmVkIGFwcGVuZCBhbmQgdGhlIGN1cnJlbnQgc2Nhbm5lZCBjb2RlIGlzIHBhcnQgb2Ygb25lIHRoZW4gdGhlXG4gICAgICAgICAqIHNlcXVlbmNlIG51bWJlciBpcyBnaXZlbiB3aXRoIGl0LlxuICAgICAgICAgKi9cbiAgICAgICAgUmVzdWx0TWV0YWRhdGFUeXBlW1Jlc3VsdE1ldGFkYXRhVHlwZVtcIlNUUlVDVFVSRURfQVBQRU5EX1NFUVVFTkNFXCJdID0gOV0gPSBcIlNUUlVDVFVSRURfQVBQRU5EX1NFUVVFTkNFXCI7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJZiB0aGUgY29kZSBmb3JtYXQgc3VwcG9ydHMgc3RydWN0dXJlZCBhcHBlbmQgYW5kIHRoZSBjdXJyZW50IHNjYW5uZWQgY29kZSBpcyBwYXJ0IG9mIG9uZSB0aGVuIHRoZVxuICAgICAgICAgKiBwYXJpdHkgaXMgZ2l2ZW4gd2l0aCBpdC5cbiAgICAgICAgICovXG4gICAgICAgIFJlc3VsdE1ldGFkYXRhVHlwZVtSZXN1bHRNZXRhZGF0YVR5cGVbXCJTVFJVQ1RVUkVEX0FQUEVORF9QQVJJVFlcIl0gPSAxMF0gPSBcIlNUUlVDVFVSRURfQVBQRU5EX1BBUklUWVwiO1xuICAgIH0pKFJlc3VsdE1ldGFkYXRhVHlwZSB8fCAoUmVzdWx0TWV0YWRhdGFUeXBlID0ge30pKTtcbiAgICB2YXIgUmVzdWx0TWV0YWRhdGFUeXBlJDEgPSBSZXN1bHRNZXRhZGF0YVR5cGU7XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qbmFtZXNwYWNlIGNvbS5nb29nbGUuenhpbmcuY29tbW9uIHsqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5MaXN0OyovXG4gICAgLyoqXG4gICAgICogPHA+RW5jYXBzdWxhdGVzIHRoZSByZXN1bHQgb2YgZGVjb2RpbmcgYSBtYXRyaXggb2YgYml0cy4gVGhpcyB0eXBpY2FsbHlcbiAgICAgKiBhcHBsaWVzIHRvIDJEIGJhcmNvZGUgZm9ybWF0cy4gRm9yIG5vdyBpdCBjb250YWlucyB0aGUgcmF3IGJ5dGVzIG9idGFpbmVkLFxuICAgICAqIGFzIHdlbGwgYXMgYSBTdHJpbmcgaW50ZXJwcmV0YXRpb24gb2YgdGhvc2UgYnl0ZXMsIGlmIGFwcGxpY2FibGUuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBEZWNvZGVyUmVzdWx0IHtcbiAgICAgICAgLy8gcHVibGljIGNvbnN0cnVjdG9yKHJhd0J5dGVzOiBVaW50OEFycmF5LFxuICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgICB0ZXh0OiBzdHJpbmcsXG4gICAgICAgIC8vICAgICAgICAgICAgICAgICAgICAgIExpc3Q8VWludDhBcnJheT4gYnl0ZVNlZ21lbnRzLFxuICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgICBTdHJpbmcgZWNMZXZlbCkge1xuICAgICAgICAvLyAgIHRoaXMocmF3Qnl0ZXMsIHRleHQsIGJ5dGVTZWdtZW50cywgZWNMZXZlbCwgLTEsIC0xKVxuICAgICAgICAvLyB9XG4gICAgICAgIGNvbnN0cnVjdG9yKHJhd0J5dGVzLCB0ZXh0LCBieXRlU2VnbWVudHMsIGVjTGV2ZWwsIHN0cnVjdHVyZWRBcHBlbmRTZXF1ZW5jZU51bWJlciA9IC0xLCBzdHJ1Y3R1cmVkQXBwZW5kUGFyaXR5ID0gLTEpIHtcbiAgICAgICAgICAgIHRoaXMucmF3Qnl0ZXMgPSByYXdCeXRlcztcbiAgICAgICAgICAgIHRoaXMudGV4dCA9IHRleHQ7XG4gICAgICAgICAgICB0aGlzLmJ5dGVTZWdtZW50cyA9IGJ5dGVTZWdtZW50cztcbiAgICAgICAgICAgIHRoaXMuZWNMZXZlbCA9IGVjTGV2ZWw7XG4gICAgICAgICAgICB0aGlzLnN0cnVjdHVyZWRBcHBlbmRTZXF1ZW5jZU51bWJlciA9IHN0cnVjdHVyZWRBcHBlbmRTZXF1ZW5jZU51bWJlcjtcbiAgICAgICAgICAgIHRoaXMuc3RydWN0dXJlZEFwcGVuZFBhcml0eSA9IHN0cnVjdHVyZWRBcHBlbmRQYXJpdHk7XG4gICAgICAgICAgICB0aGlzLm51bUJpdHMgPSAocmF3Qnl0ZXMgPT09IHVuZGVmaW5lZCB8fCByYXdCeXRlcyA9PT0gbnVsbCkgPyAwIDogOCAqIHJhd0J5dGVzLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiByYXcgYnl0ZXMgcmVwcmVzZW50aW5nIHRoZSByZXN1bHQsIG9yIHtAY29kZSBudWxsfSBpZiBub3QgYXBwbGljYWJsZVxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0UmF3Qnl0ZXMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yYXdCeXRlcztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBob3cgbWFueSBiaXRzIG9mIHtAbGluayAjZ2V0UmF3Qnl0ZXMoKX0gYXJlIHZhbGlkOyB0eXBpY2FsbHkgOCB0aW1lcyBpdHMgbGVuZ3RoXG4gICAgICAgICAqIEBzaW5jZSAzLjMuMFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0TnVtQml0cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm51bUJpdHM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBudW1CaXRzIG92ZXJyaWRlcyB0aGUgbnVtYmVyIG9mIGJpdHMgdGhhdCBhcmUgdmFsaWQgaW4ge0BsaW5rICNnZXRSYXdCeXRlcygpfVxuICAgICAgICAgKiBAc2luY2UgMy4zLjBcbiAgICAgICAgICovXG4gICAgICAgIHNldE51bUJpdHMobnVtQml0cyAvKmludCovKSB7XG4gICAgICAgICAgICB0aGlzLm51bUJpdHMgPSBudW1CaXRzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHRleHQgcmVwcmVzZW50YXRpb24gb2YgdGhlIHJlc3VsdFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0VGV4dCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gbGlzdCBvZiBieXRlIHNlZ21lbnRzIGluIHRoZSByZXN1bHQsIG9yIHtAY29kZSBudWxsfSBpZiBub3QgYXBwbGljYWJsZVxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0Qnl0ZVNlZ21lbnRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYnl0ZVNlZ21lbnRzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIG5hbWUgb2YgZXJyb3IgY29ycmVjdGlvbiBsZXZlbCB1c2VkLCBvciB7QGNvZGUgbnVsbH0gaWYgbm90IGFwcGxpY2FibGVcbiAgICAgICAgICovXG4gICAgICAgIGdldEVDTGV2ZWwoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lY0xldmVsO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIG51bWJlciBvZiBlcnJvcnMgY29ycmVjdGVkLCBvciB7QGNvZGUgbnVsbH0gaWYgbm90IGFwcGxpY2FibGVcbiAgICAgICAgICovXG4gICAgICAgIGdldEVycm9yc0NvcnJlY3RlZCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVycm9yc0NvcnJlY3RlZDtcbiAgICAgICAgfVxuICAgICAgICBzZXRFcnJvcnNDb3JyZWN0ZWQoZXJyb3JzQ29ycmVjdGVkIC8qSW50ZWdlciovKSB7XG4gICAgICAgICAgICB0aGlzLmVycm9yc0NvcnJlY3RlZCA9IGVycm9yc0NvcnJlY3RlZDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBudW1iZXIgb2YgZXJhc3VyZXMgY29ycmVjdGVkLCBvciB7QGNvZGUgbnVsbH0gaWYgbm90IGFwcGxpY2FibGVcbiAgICAgICAgICovXG4gICAgICAgIGdldEVyYXN1cmVzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXJhc3VyZXM7XG4gICAgICAgIH1cbiAgICAgICAgc2V0RXJhc3VyZXMoZXJhc3VyZXMgLypJbnRlZ2VyKi8pIHtcbiAgICAgICAgICAgIHRoaXMuZXJhc3VyZXMgPSBlcmFzdXJlcztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBhcmJpdHJhcnkgYWRkaXRpb25hbCBtZXRhZGF0YVxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0T3RoZXIoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vdGhlcjtcbiAgICAgICAgfVxuICAgICAgICBzZXRPdGhlcihvdGhlcikge1xuICAgICAgICAgICAgdGhpcy5vdGhlciA9IG90aGVyO1xuICAgICAgICB9XG4gICAgICAgIGhhc1N0cnVjdHVyZWRBcHBlbmQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zdHJ1Y3R1cmVkQXBwZW5kUGFyaXR5ID49IDAgJiYgdGhpcy5zdHJ1Y3R1cmVkQXBwZW5kU2VxdWVuY2VOdW1iZXIgPj0gMDtcbiAgICAgICAgfVxuICAgICAgICBnZXRTdHJ1Y3R1cmVkQXBwZW5kUGFyaXR5KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RydWN0dXJlZEFwcGVuZFBhcml0eTtcbiAgICAgICAgfVxuICAgICAgICBnZXRTdHJ1Y3R1cmVkQXBwZW5kU2VxdWVuY2VOdW1iZXIoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zdHJ1Y3R1cmVkQXBwZW5kU2VxdWVuY2VOdW1iZXI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIDxwPlRoaXMgY2xhc3MgY29udGFpbnMgdXRpbGl0eSBtZXRob2RzIGZvciBwZXJmb3JtaW5nIG1hdGhlbWF0aWNhbCBvcGVyYXRpb25zIG92ZXJcbiAgICAgKiB0aGUgR2Fsb2lzIEZpZWxkcy4gT3BlcmF0aW9ucyB1c2UgYSBnaXZlbiBwcmltaXRpdmUgcG9seW5vbWlhbCBpbiBjYWxjdWxhdGlvbnMuPC9wPlxuICAgICAqXG4gICAgICogPHA+VGhyb3VnaG91dCB0aGlzIHBhY2thZ2UsIGVsZW1lbnRzIG9mIHRoZSBHRiBhcmUgcmVwcmVzZW50ZWQgYXMgYW4ge0Bjb2RlIGludH1cbiAgICAgKiBmb3IgY29udmVuaWVuY2UgYW5kIHNwZWVkIChidXQgYXQgdGhlIGNvc3Qgb2YgbWVtb3J5KS5cbiAgICAgKiA8L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqIEBhdXRob3IgRGF2aWQgT2xpdmllclxuICAgICAqL1xuICAgIGNsYXNzIEFic3RyYWN0R2VuZXJpY0dGIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gMiB0byB0aGUgcG93ZXIgb2YgYSBpbiBHRihzaXplKVxuICAgICAgICAgKi9cbiAgICAgICAgZXhwKGEpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmV4cFRhYmxlW2FdO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIGJhc2UgMiBsb2cgb2YgYSBpbiBHRihzaXplKVxuICAgICAgICAgKi9cbiAgICAgICAgbG9nKGEgLyppbnQqLykge1xuICAgICAgICAgICAgaWYgKGEgPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sb2dUYWJsZVthXTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogSW1wbGVtZW50cyBib3RoIGFkZGl0aW9uIGFuZCBzdWJ0cmFjdGlvbiAtLSB0aGV5IGFyZSB0aGUgc2FtZSBpbiBHRihzaXplKS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiBzdW0vZGlmZmVyZW5jZSBvZiBhIGFuZCBiXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgYWRkT3JTdWJ0cmFjdChhIC8qaW50Ki8sIGIgLyppbnQqLykge1xuICAgICAgICAgICAgcmV0dXJuIGEgXiBiO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiA8cD5SZXByZXNlbnRzIGEgcG9seW5vbWlhbCB3aG9zZSBjb2VmZmljaWVudHMgYXJlIGVsZW1lbnRzIG9mIGEgR0YuXG4gICAgICogSW5zdGFuY2VzIG9mIHRoaXMgY2xhc3MgYXJlIGltbXV0YWJsZS48L3A+XG4gICAgICpcbiAgICAgKiA8cD5NdWNoIGNyZWRpdCBpcyBkdWUgdG8gV2lsbGlhbSBSdWNrbGlkZ2Ugc2luY2UgcG9ydGlvbnMgb2YgdGhpcyBjb2RlIGFyZSBhbiBpbmRpcmVjdFxuICAgICAqIHBvcnQgb2YgaGlzIEMrKyBSZWVkLVNvbG9tb24gaW1wbGVtZW50YXRpb24uPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBHZW5lcmljR0ZQb2x5IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBmaWVsZCB0aGUge0BsaW5rIEdlbmVyaWNHRn0gaW5zdGFuY2UgcmVwcmVzZW50aW5nIHRoZSBmaWVsZCB0byB1c2VcbiAgICAgICAgICogdG8gcGVyZm9ybSBjb21wdXRhdGlvbnNcbiAgICAgICAgICogQHBhcmFtIGNvZWZmaWNpZW50cyBjb2VmZmljaWVudHMgYXMgaW50cyByZXByZXNlbnRpbmcgZWxlbWVudHMgb2YgR0Yoc2l6ZSksIGFycmFuZ2VkXG4gICAgICAgICAqIGZyb20gbW9zdCBzaWduaWZpY2FudCAoaGlnaGVzdC1wb3dlciB0ZXJtKSBjb2VmZmljaWVudCB0byBsZWFzdCBzaWduaWZpY2FudFxuICAgICAgICAgKiBAdGhyb3dzIElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbiBpZiBhcmd1bWVudCBpcyBudWxsIG9yIGVtcHR5LFxuICAgICAgICAgKiBvciBpZiBsZWFkaW5nIGNvZWZmaWNpZW50IGlzIDAgYW5kIHRoaXMgaXMgbm90IGFcbiAgICAgICAgICogY29uc3RhbnQgcG9seW5vbWlhbCAodGhhdCBpcywgaXQgaXMgbm90IHRoZSBtb25vbWlhbCBcIjBcIilcbiAgICAgICAgICovXG4gICAgICAgIGNvbnN0cnVjdG9yKGZpZWxkLCBjb2VmZmljaWVudHMpIHtcbiAgICAgICAgICAgIGlmIChjb2VmZmljaWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5maWVsZCA9IGZpZWxkO1xuICAgICAgICAgICAgY29uc3QgY29lZmZpY2llbnRzTGVuZ3RoID0gY29lZmZpY2llbnRzLmxlbmd0aDtcbiAgICAgICAgICAgIGlmIChjb2VmZmljaWVudHNMZW5ndGggPiAxICYmIGNvZWZmaWNpZW50c1swXSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIC8vIExlYWRpbmcgdGVybSBtdXN0IGJlIG5vbi16ZXJvIGZvciBhbnl0aGluZyBleGNlcHQgdGhlIGNvbnN0YW50IHBvbHlub21pYWwgXCIwXCJcbiAgICAgICAgICAgICAgICBsZXQgZmlyc3ROb25aZXJvID0gMTtcbiAgICAgICAgICAgICAgICB3aGlsZSAoZmlyc3ROb25aZXJvIDwgY29lZmZpY2llbnRzTGVuZ3RoICYmIGNvZWZmaWNpZW50c1tmaXJzdE5vblplcm9dID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpcnN0Tm9uWmVybysrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZmlyc3ROb25aZXJvID09PSBjb2VmZmljaWVudHNMZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb2VmZmljaWVudHMgPSBJbnQzMkFycmF5LmZyb20oWzBdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29lZmZpY2llbnRzID0gbmV3IEludDMyQXJyYXkoY29lZmZpY2llbnRzTGVuZ3RoIC0gZmlyc3ROb25aZXJvKTtcbiAgICAgICAgICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weShjb2VmZmljaWVudHMsIGZpcnN0Tm9uWmVybywgdGhpcy5jb2VmZmljaWVudHMsIDAsIHRoaXMuY29lZmZpY2llbnRzLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb2VmZmljaWVudHMgPSBjb2VmZmljaWVudHM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Q29lZmZpY2llbnRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29lZmZpY2llbnRzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIGRlZ3JlZSBvZiB0aGlzIHBvbHlub21pYWxcbiAgICAgICAgICovXG4gICAgICAgIGdldERlZ3JlZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvZWZmaWNpZW50cy5sZW5ndGggLSAxO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHRydWUgaWZmIHRoaXMgcG9seW5vbWlhbCBpcyB0aGUgbW9ub21pYWwgXCIwXCJcbiAgICAgICAgICovXG4gICAgICAgIGlzWmVybygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvZWZmaWNpZW50c1swXSA9PT0gMDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBjb2VmZmljaWVudCBvZiB4XmRlZ3JlZSB0ZXJtIGluIHRoaXMgcG9seW5vbWlhbFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0Q29lZmZpY2llbnQoZGVncmVlIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvZWZmaWNpZW50c1t0aGlzLmNvZWZmaWNpZW50cy5sZW5ndGggLSAxIC0gZGVncmVlXTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBldmFsdWF0aW9uIG9mIHRoaXMgcG9seW5vbWlhbCBhdCBhIGdpdmVuIHBvaW50XG4gICAgICAgICAqL1xuICAgICAgICBldmFsdWF0ZUF0KGEgLyppbnQqLykge1xuICAgICAgICAgICAgaWYgKGEgPT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyBKdXN0IHJldHVybiB0aGUgeF4wIGNvZWZmaWNpZW50XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29lZmZpY2llbnQoMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBjb2VmZmljaWVudHMgPSB0aGlzLmNvZWZmaWNpZW50cztcbiAgICAgICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgICAgICBpZiAoYSA9PT0gMSkge1xuICAgICAgICAgICAgICAgIC8vIEp1c3QgdGhlIHN1bSBvZiB0aGUgY29lZmZpY2llbnRzXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gMDtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgbGVuZ3RoID0gY29lZmZpY2llbnRzLmxlbmd0aDsgaSAhPT0gbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29lZmZpY2llbnQgPSBjb2VmZmljaWVudHNbaV07XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEFic3RyYWN0R2VuZXJpY0dGLmFkZE9yU3VidHJhY3QocmVzdWx0LCBjb2VmZmljaWVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXN1bHQgPSBjb2VmZmljaWVudHNbMF07XG4gICAgICAgICAgICBjb25zdCBzaXplID0gY29lZmZpY2llbnRzLmxlbmd0aDtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gdGhpcy5maWVsZDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgc2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gQWJzdHJhY3RHZW5lcmljR0YuYWRkT3JTdWJ0cmFjdChmaWVsZC5tdWx0aXBseShhLCByZXN1bHQpLCBjb2VmZmljaWVudHNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBhZGRPclN1YnRyYWN0KG90aGVyKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZmllbGQuZXF1YWxzKG90aGVyLmZpZWxkKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ0dlbmVyaWNHRlBvbHlzIGRvIG5vdCBoYXZlIHNhbWUgR2VuZXJpY0dGIGZpZWxkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5pc1plcm8oKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBvdGhlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvdGhlci5pc1plcm8oKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHNtYWxsZXJDb2VmZmljaWVudHMgPSB0aGlzLmNvZWZmaWNpZW50cztcbiAgICAgICAgICAgIGxldCBsYXJnZXJDb2VmZmljaWVudHMgPSBvdGhlci5jb2VmZmljaWVudHM7XG4gICAgICAgICAgICBpZiAoc21hbGxlckNvZWZmaWNpZW50cy5sZW5ndGggPiBsYXJnZXJDb2VmZmljaWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdGVtcCA9IHNtYWxsZXJDb2VmZmljaWVudHM7XG4gICAgICAgICAgICAgICAgc21hbGxlckNvZWZmaWNpZW50cyA9IGxhcmdlckNvZWZmaWNpZW50cztcbiAgICAgICAgICAgICAgICBsYXJnZXJDb2VmZmljaWVudHMgPSB0ZW1wO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHN1bURpZmYgPSBuZXcgSW50MzJBcnJheShsYXJnZXJDb2VmZmljaWVudHMubGVuZ3RoKTtcbiAgICAgICAgICAgIGNvbnN0IGxlbmd0aERpZmYgPSBsYXJnZXJDb2VmZmljaWVudHMubGVuZ3RoIC0gc21hbGxlckNvZWZmaWNpZW50cy5sZW5ndGg7XG4gICAgICAgICAgICAvLyBDb3B5IGhpZ2gtb3JkZXIgdGVybXMgb25seSBmb3VuZCBpbiBoaWdoZXItZGVncmVlIHBvbHlub21pYWwncyBjb2VmZmljaWVudHNcbiAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkobGFyZ2VyQ29lZmZpY2llbnRzLCAwLCBzdW1EaWZmLCAwLCBsZW5ndGhEaWZmKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBsZW5ndGhEaWZmOyBpIDwgbGFyZ2VyQ29lZmZpY2llbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgc3VtRGlmZltpXSA9IEFic3RyYWN0R2VuZXJpY0dGLmFkZE9yU3VidHJhY3Qoc21hbGxlckNvZWZmaWNpZW50c1tpIC0gbGVuZ3RoRGlmZl0sIGxhcmdlckNvZWZmaWNpZW50c1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IEdlbmVyaWNHRlBvbHkodGhpcy5maWVsZCwgc3VtRGlmZik7XG4gICAgICAgIH1cbiAgICAgICAgbXVsdGlwbHkob3RoZXIpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5maWVsZC5lcXVhbHMob3RoZXIuZmllbGQpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignR2VuZXJpY0dGUG9seXMgZG8gbm90IGhhdmUgc2FtZSBHZW5lcmljR0YgZmllbGQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmlzWmVybygpIHx8IG90aGVyLmlzWmVybygpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmllbGQuZ2V0WmVybygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYUNvZWZmaWNpZW50cyA9IHRoaXMuY29lZmZpY2llbnRzO1xuICAgICAgICAgICAgY29uc3QgYUxlbmd0aCA9IGFDb2VmZmljaWVudHMubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3QgYkNvZWZmaWNpZW50cyA9IG90aGVyLmNvZWZmaWNpZW50cztcbiAgICAgICAgICAgIGNvbnN0IGJMZW5ndGggPSBiQ29lZmZpY2llbnRzLmxlbmd0aDtcbiAgICAgICAgICAgIGNvbnN0IHByb2R1Y3QgPSBuZXcgSW50MzJBcnJheShhTGVuZ3RoICsgYkxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpZWxkO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhTGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBhQ29lZmYgPSBhQ29lZmZpY2llbnRzW2ldO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgYkxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb2R1Y3RbaSArIGpdID0gQWJzdHJhY3RHZW5lcmljR0YuYWRkT3JTdWJ0cmFjdChwcm9kdWN0W2kgKyBqXSwgZmllbGQubXVsdGlwbHkoYUNvZWZmLCBiQ29lZmZpY2llbnRzW2pdKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBHZW5lcmljR0ZQb2x5KGZpZWxkLCBwcm9kdWN0KTtcbiAgICAgICAgfVxuICAgICAgICBtdWx0aXBseVNjYWxhcihzY2FsYXIgLyppbnQqLykge1xuICAgICAgICAgICAgaWYgKHNjYWxhciA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmZpZWxkLmdldFplcm8oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzY2FsYXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHNpemUgPSB0aGlzLmNvZWZmaWNpZW50cy5sZW5ndGg7XG4gICAgICAgICAgICBjb25zdCBmaWVsZCA9IHRoaXMuZmllbGQ7XG4gICAgICAgICAgICBjb25zdCBwcm9kdWN0ID0gbmV3IEludDMyQXJyYXkoc2l6ZSk7XG4gICAgICAgICAgICBjb25zdCBjb2VmZmljaWVudHMgPSB0aGlzLmNvZWZmaWNpZW50cztcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcHJvZHVjdFtpXSA9IGZpZWxkLm11bHRpcGx5KGNvZWZmaWNpZW50c1tpXSwgc2NhbGFyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgR2VuZXJpY0dGUG9seShmaWVsZCwgcHJvZHVjdCk7XG4gICAgICAgIH1cbiAgICAgICAgbXVsdGlwbHlCeU1vbm9taWFsKGRlZ3JlZSAvKmludCovLCBjb2VmZmljaWVudCAvKmludCovKSB7XG4gICAgICAgICAgICBpZiAoZGVncmVlIDwgMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjb2VmZmljaWVudCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmZpZWxkLmdldFplcm8oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGNvZWZmaWNpZW50cyA9IHRoaXMuY29lZmZpY2llbnRzO1xuICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IGNvZWZmaWNpZW50cy5sZW5ndGg7XG4gICAgICAgICAgICBjb25zdCBwcm9kdWN0ID0gbmV3IEludDMyQXJyYXkoc2l6ZSArIGRlZ3JlZSk7XG4gICAgICAgICAgICBjb25zdCBmaWVsZCA9IHRoaXMuZmllbGQ7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykge1xuICAgICAgICAgICAgICAgIHByb2R1Y3RbaV0gPSBmaWVsZC5tdWx0aXBseShjb2VmZmljaWVudHNbaV0sIGNvZWZmaWNpZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgR2VuZXJpY0dGUG9seShmaWVsZCwgcHJvZHVjdCk7XG4gICAgICAgIH1cbiAgICAgICAgZGl2aWRlKG90aGVyKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZmllbGQuZXF1YWxzKG90aGVyLmZpZWxkKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ0dlbmVyaWNHRlBvbHlzIGRvIG5vdCBoYXZlIHNhbWUgR2VuZXJpY0dGIGZpZWxkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob3RoZXIuaXNaZXJvKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdEaXZpZGUgYnkgMCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpZWxkO1xuICAgICAgICAgICAgbGV0IHF1b3RpZW50ID0gZmllbGQuZ2V0WmVybygpO1xuICAgICAgICAgICAgbGV0IHJlbWFpbmRlciA9IHRoaXM7XG4gICAgICAgICAgICBjb25zdCBkZW5vbWluYXRvckxlYWRpbmdUZXJtID0gb3RoZXIuZ2V0Q29lZmZpY2llbnQob3RoZXIuZ2V0RGVncmVlKCkpO1xuICAgICAgICAgICAgY29uc3QgaW52ZXJzZURlbm9taW5hdG9yTGVhZGluZ1Rlcm0gPSBmaWVsZC5pbnZlcnNlKGRlbm9taW5hdG9yTGVhZGluZ1Rlcm0pO1xuICAgICAgICAgICAgd2hpbGUgKHJlbWFpbmRlci5nZXREZWdyZWUoKSA+PSBvdGhlci5nZXREZWdyZWUoKSAmJiAhcmVtYWluZGVyLmlzWmVybygpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGVncmVlRGlmZmVyZW5jZSA9IHJlbWFpbmRlci5nZXREZWdyZWUoKSAtIG90aGVyLmdldERlZ3JlZSgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHNjYWxlID0gZmllbGQubXVsdGlwbHkocmVtYWluZGVyLmdldENvZWZmaWNpZW50KHJlbWFpbmRlci5nZXREZWdyZWUoKSksIGludmVyc2VEZW5vbWluYXRvckxlYWRpbmdUZXJtKTtcbiAgICAgICAgICAgICAgICBjb25zdCB0ZXJtID0gb3RoZXIubXVsdGlwbHlCeU1vbm9taWFsKGRlZ3JlZURpZmZlcmVuY2UsIHNjYWxlKTtcbiAgICAgICAgICAgICAgICBjb25zdCBpdGVyYXRpb25RdW90aWVudCA9IGZpZWxkLmJ1aWxkTW9ub21pYWwoZGVncmVlRGlmZmVyZW5jZSwgc2NhbGUpO1xuICAgICAgICAgICAgICAgIHF1b3RpZW50ID0gcXVvdGllbnQuYWRkT3JTdWJ0cmFjdChpdGVyYXRpb25RdW90aWVudCk7XG4gICAgICAgICAgICAgICAgcmVtYWluZGVyID0gcmVtYWluZGVyLmFkZE9yU3VidHJhY3QodGVybSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gW3F1b3RpZW50LCByZW1haW5kZXJdO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gJyc7XG4gICAgICAgICAgICBmb3IgKGxldCBkZWdyZWUgPSB0aGlzLmdldERlZ3JlZSgpOyBkZWdyZWUgPj0gMDsgZGVncmVlLS0pIHtcbiAgICAgICAgICAgICAgICBsZXQgY29lZmZpY2llbnQgPSB0aGlzLmdldENvZWZmaWNpZW50KGRlZ3JlZSk7XG4gICAgICAgICAgICAgICAgaWYgKGNvZWZmaWNpZW50ICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb2VmZmljaWVudCA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnIC0gJztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZWZmaWNpZW50ID0gLWNvZWZmaWNpZW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICcgKyAnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChkZWdyZWUgPT09IDAgfHwgY29lZmZpY2llbnQgIT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFscGhhUG93ZXIgPSB0aGlzLmZpZWxkLmxvZyhjb2VmZmljaWVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWxwaGFQb3dlciA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnMSc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChhbHBoYVBvd2VyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdhJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnYV4nO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSBhbHBoYVBvd2VyO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChkZWdyZWUgIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkZWdyZWUgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3gnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICd4Xic7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IGRlZ3JlZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDdXN0b20gRXJyb3IgY2xhc3Mgb2YgdHlwZSBFeGNlcHRpb24uXG4gICAgICovXG4gICAgY2xhc3MgQXJpdGhtZXRpY0V4Y2VwdGlvbiBleHRlbmRzIEV4Y2VwdGlvbiB7XG4gICAgfVxuICAgIEFyaXRobWV0aWNFeGNlcHRpb24ua2luZCA9ICdBcml0aG1ldGljRXhjZXB0aW9uJztcblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogPHA+VGhpcyBjbGFzcyBjb250YWlucyB1dGlsaXR5IG1ldGhvZHMgZm9yIHBlcmZvcm1pbmcgbWF0aGVtYXRpY2FsIG9wZXJhdGlvbnMgb3ZlclxuICAgICAqIHRoZSBHYWxvaXMgRmllbGRzLiBPcGVyYXRpb25zIHVzZSBhIGdpdmVuIHByaW1pdGl2ZSBwb2x5bm9taWFsIGluIGNhbGN1bGF0aW9ucy48L3A+XG4gICAgICpcbiAgICAgKiA8cD5UaHJvdWdob3V0IHRoaXMgcGFja2FnZSwgZWxlbWVudHMgb2YgdGhlIEdGIGFyZSByZXByZXNlbnRlZCBhcyBhbiB7QGNvZGUgaW50fVxuICAgICAqIGZvciBjb252ZW5pZW5jZSBhbmQgc3BlZWQgKGJ1dCBhdCB0aGUgY29zdCBvZiBtZW1vcnkpLlxuICAgICAqIDwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICogQGF1dGhvciBEYXZpZCBPbGl2aWVyXG4gICAgICovXG4gICAgY2xhc3MgR2VuZXJpY0dGIGV4dGVuZHMgQWJzdHJhY3RHZW5lcmljR0Yge1xuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlIGEgcmVwcmVzZW50YXRpb24gb2YgR0Yoc2l6ZSkgdXNpbmcgdGhlIGdpdmVuIHByaW1pdGl2ZSBwb2x5bm9taWFsLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gcHJpbWl0aXZlIGlycmVkdWNpYmxlIHBvbHlub21pYWwgd2hvc2UgY29lZmZpY2llbnRzIGFyZSByZXByZXNlbnRlZCBieVxuICAgICAgICAgKiAgdGhlIGJpdHMgb2YgYW4gaW50LCB3aGVyZSB0aGUgbGVhc3Qtc2lnbmlmaWNhbnQgYml0IHJlcHJlc2VudHMgdGhlIGNvbnN0YW50XG4gICAgICAgICAqICBjb2VmZmljaWVudFxuICAgICAgICAgKiBAcGFyYW0gc2l6ZSB0aGUgc2l6ZSBvZiB0aGUgZmllbGRcbiAgICAgICAgICogQHBhcmFtIGIgdGhlIGZhY3RvciBiIGluIHRoZSBnZW5lcmF0b3IgcG9seW5vbWlhbCBjYW4gYmUgMC0gb3IgMS1iYXNlZFxuICAgICAgICAgKiAgKGcoeCkgPSAoeCthXmIpKHgrYV4oYisxKSkuLi4oeCthXihiKzJ0LTEpKSkuXG4gICAgICAgICAqICBJbiBtb3N0IGNhc2VzIGl0IHNob3VsZCBiZSAxLCBidXQgZm9yIFFSIGNvZGUgaXQgaXMgMC5cbiAgICAgICAgICovXG4gICAgICAgIGNvbnN0cnVjdG9yKHByaW1pdGl2ZSAvKmludCovLCBzaXplIC8qaW50Ki8sIGdlbmVyYXRvckJhc2UgLyppbnQqLykge1xuICAgICAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgICAgIHRoaXMucHJpbWl0aXZlID0gcHJpbWl0aXZlO1xuICAgICAgICAgICAgdGhpcy5zaXplID0gc2l6ZTtcbiAgICAgICAgICAgIHRoaXMuZ2VuZXJhdG9yQmFzZSA9IGdlbmVyYXRvckJhc2U7XG4gICAgICAgICAgICBjb25zdCBleHBUYWJsZSA9IG5ldyBJbnQzMkFycmF5KHNpemUpO1xuICAgICAgICAgICAgbGV0IHggPSAxO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgICAgICAgICAgICBleHBUYWJsZVtpXSA9IHg7XG4gICAgICAgICAgICAgICAgeCAqPSAyOyAvLyB3ZSdyZSBhc3N1bWluZyB0aGUgZ2VuZXJhdG9yIGFscGhhIGlzIDJcbiAgICAgICAgICAgICAgICBpZiAoeCA+PSBzaXplKSB7XG4gICAgICAgICAgICAgICAgICAgIHggXj0gcHJpbWl0aXZlO1xuICAgICAgICAgICAgICAgICAgICB4ICY9IHNpemUgLSAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZXhwVGFibGUgPSBleHBUYWJsZTtcbiAgICAgICAgICAgIGNvbnN0IGxvZ1RhYmxlID0gbmV3IEludDMyQXJyYXkoc2l6ZSk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemUgLSAxOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsb2dUYWJsZVtleHBUYWJsZVtpXV0gPSBpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5sb2dUYWJsZSA9IGxvZ1RhYmxlO1xuICAgICAgICAgICAgLy8gbG9nVGFibGVbMF0gPT0gMCBidXQgdGhpcyBzaG91bGQgbmV2ZXIgYmUgdXNlZFxuICAgICAgICAgICAgdGhpcy56ZXJvID0gbmV3IEdlbmVyaWNHRlBvbHkodGhpcywgSW50MzJBcnJheS5mcm9tKFswXSkpO1xuICAgICAgICAgICAgdGhpcy5vbmUgPSBuZXcgR2VuZXJpY0dGUG9seSh0aGlzLCBJbnQzMkFycmF5LmZyb20oWzFdKSk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0WmVybygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnplcm87XG4gICAgICAgIH1cbiAgICAgICAgZ2V0T25lKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMub25lO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHRoZSBtb25vbWlhbCByZXByZXNlbnRpbmcgY29lZmZpY2llbnQgKiB4XmRlZ3JlZVxuICAgICAgICAgKi9cbiAgICAgICAgYnVpbGRNb25vbWlhbChkZWdyZWUgLyppbnQqLywgY29lZmZpY2llbnQgLyppbnQqLykge1xuICAgICAgICAgICAgaWYgKGRlZ3JlZSA8IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29lZmZpY2llbnQgPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy56ZXJvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgY29lZmZpY2llbnRzID0gbmV3IEludDMyQXJyYXkoZGVncmVlICsgMSk7XG4gICAgICAgICAgICBjb2VmZmljaWVudHNbMF0gPSBjb2VmZmljaWVudDtcbiAgICAgICAgICAgIHJldHVybiBuZXcgR2VuZXJpY0dGUG9seSh0aGlzLCBjb2VmZmljaWVudHMpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIG11bHRpcGxpY2F0aXZlIGludmVyc2Ugb2YgYVxuICAgICAgICAgKi9cbiAgICAgICAgaW52ZXJzZShhIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGlmIChhID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEFyaXRobWV0aWNFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmV4cFRhYmxlW3RoaXMuc2l6ZSAtIHRoaXMubG9nVGFibGVbYV0gLSAxXTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBwcm9kdWN0IG9mIGEgYW5kIGIgaW4gR0Yoc2l6ZSlcbiAgICAgICAgICovXG4gICAgICAgIG11bHRpcGx5KGEgLyppbnQqLywgYiAvKmludCovKSB7XG4gICAgICAgICAgICBpZiAoYSA9PT0gMCB8fCBiID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5leHBUYWJsZVsodGhpcy5sb2dUYWJsZVthXSArIHRoaXMubG9nVGFibGVbYl0pICUgKHRoaXMuc2l6ZSAtIDEpXTtcbiAgICAgICAgfVxuICAgICAgICBnZXRTaXplKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2l6ZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRHZW5lcmF0b3JCYXNlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2VuZXJhdG9yQmFzZTtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgcmV0dXJuICgnR0YoMHgnICsgSW50ZWdlci50b0hleFN0cmluZyh0aGlzLnByaW1pdGl2ZSkgKyAnLCcgKyB0aGlzLnNpemUgKyAnKScpO1xuICAgICAgICB9XG4gICAgICAgIGVxdWFscyhvKSB7XG4gICAgICAgICAgICByZXR1cm4gbyA9PT0gdGhpcztcbiAgICAgICAgfVxuICAgIH1cbiAgICBHZW5lcmljR0YuQVpURUNfREFUQV8xMiA9IG5ldyBHZW5lcmljR0YoMHgxMDY5LCA0MDk2LCAxKTsgLy8geF4xMiArIHheNiArIHheNSArIHheMyArIDFcbiAgICBHZW5lcmljR0YuQVpURUNfREFUQV8xMCA9IG5ldyBHZW5lcmljR0YoMHg0MDksIDEwMjQsIDEpOyAvLyB4XjEwICsgeF4zICsgMVxuICAgIEdlbmVyaWNHRi5BWlRFQ19EQVRBXzYgPSBuZXcgR2VuZXJpY0dGKDB4NDMsIDY0LCAxKTsgLy8geF42ICsgeCArIDFcbiAgICBHZW5lcmljR0YuQVpURUNfUEFSQU0gPSBuZXcgR2VuZXJpY0dGKDB4MTMsIDE2LCAxKTsgLy8geF40ICsgeCArIDFcbiAgICBHZW5lcmljR0YuUVJfQ09ERV9GSUVMRF8yNTYgPSBuZXcgR2VuZXJpY0dGKDB4MDExZCwgMjU2LCAwKTsgLy8geF44ICsgeF40ICsgeF4zICsgeF4yICsgMVxuICAgIEdlbmVyaWNHRi5EQVRBX01BVFJJWF9GSUVMRF8yNTYgPSBuZXcgR2VuZXJpY0dGKDB4MDEyZCwgMjU2LCAxKTsgLy8geF44ICsgeF41ICsgeF4zICsgeF4yICsgMVxuICAgIEdlbmVyaWNHRi5BWlRFQ19EQVRBXzggPSBHZW5lcmljR0YuREFUQV9NQVRSSVhfRklFTERfMjU2O1xuICAgIEdlbmVyaWNHRi5NQVhJQ09ERV9GSUVMRF82NCA9IEdlbmVyaWNHRi5BWlRFQ19EQVRBXzY7XG5cbiAgICAvKipcbiAgICAgKiBDdXN0b20gRXJyb3IgY2xhc3Mgb2YgdHlwZSBFeGNlcHRpb24uXG4gICAgICovXG4gICAgY2xhc3MgUmVlZFNvbG9tb25FeGNlcHRpb24gZXh0ZW5kcyBFeGNlcHRpb24ge1xuICAgIH1cbiAgICBSZWVkU29sb21vbkV4Y2VwdGlvbi5raW5kID0gJ1JlZWRTb2xvbW9uRXhjZXB0aW9uJztcblxuICAgIC8qKlxuICAgICAqIEN1c3RvbSBFcnJvciBjbGFzcyBvZiB0eXBlIEV4Y2VwdGlvbi5cbiAgICAgKi9cbiAgICBjbGFzcyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24gZXh0ZW5kcyBFeGNlcHRpb24ge1xuICAgIH1cbiAgICBJbGxlZ2FsU3RhdGVFeGNlcHRpb24ua2luZCA9ICdJbGxlZ2FsU3RhdGVFeGNlcHRpb24nO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiA8cD5JbXBsZW1lbnRzIFJlZWQtU29sb21vbiBkZWNvZGluZywgYXMgdGhlIG5hbWUgaW1wbGllcy48L3A+XG4gICAgICpcbiAgICAgKiA8cD5UaGUgYWxnb3JpdGhtIHdpbGwgbm90IGJlIGV4cGxhaW5lZCBoZXJlLCBidXQgdGhlIGZvbGxvd2luZyByZWZlcmVuY2VzIHdlcmUgaGVscGZ1bFxuICAgICAqIGluIGNyZWF0aW5nIHRoaXMgaW1wbGVtZW50YXRpb246PC9wPlxuICAgICAqXG4gICAgICogPHVsPlxuICAgICAqIDxsaT5CcnVjZSBNYWdncy5cbiAgICAgKiA8YSBocmVmPVwiaHR0cDovL3d3dy5jcy5jbXUuZWR1L2Fmcy9jcy5jbXUuZWR1L3Byb2plY3QvcHNjaWNvLWd1eWIvcmVhbHdvcmxkL3d3dy9yc19kZWNvZGUucHNcIj5cbiAgICAgKiBcIkRlY29kaW5nIFJlZWQtU29sb21vbiBDb2Rlc1wiPC9hPiAoc2VlIGRpc2N1c3Npb24gb2YgRm9ybmV5J3MgRm9ybXVsYSk8L2xpPlxuICAgICAqIDxsaT5KLkkuIEhhbGwuIDxhIGhyZWY9XCJ3d3cubXRoLm1zdS5lZHUvfmpoYWxsL2NsYXNzZXMvY29kZW5vdGVzL0dSUy5wZGZcIj5cbiAgICAgKiBcIkNoYXB0ZXIgNS4gR2VuZXJhbGl6ZWQgUmVlZC1Tb2xvbW9uIENvZGVzXCI8L2E+XG4gICAgICogKHNlZSBkaXNjdXNzaW9uIG9mIEV1Y2xpZGVhbiBhbGdvcml0aG0pPC9saT5cbiAgICAgKiA8L3VsPlxuICAgICAqXG4gICAgICogPHA+TXVjaCBjcmVkaXQgaXMgZHVlIHRvIFdpbGxpYW0gUnVja2xpZGdlIHNpbmNlIHBvcnRpb25zIG9mIHRoaXMgY29kZSBhcmUgYW4gaW5kaXJlY3RcbiAgICAgKiBwb3J0IG9mIGhpcyBDKysgUmVlZC1Tb2xvbW9uIGltcGxlbWVudGF0aW9uLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICogQGF1dGhvciBXaWxsaWFtIFJ1Y2tsaWRnZVxuICAgICAqIEBhdXRob3Igc2FuZm9yZHNxdWlyZXNcbiAgICAgKi9cbiAgICBjbGFzcyBSZWVkU29sb21vbkRlY29kZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcihmaWVsZCkge1xuICAgICAgICAgICAgdGhpcy5maWVsZCA9IGZpZWxkO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5EZWNvZGVzIGdpdmVuIHNldCBvZiByZWNlaXZlZCBjb2Rld29yZHMsIHdoaWNoIGluY2x1ZGUgYm90aCBkYXRhIGFuZCBlcnJvci1jb3JyZWN0aW9uXG4gICAgICAgICAqIGNvZGV3b3Jkcy4gUmVhbGx5LCB0aGlzIG1lYW5zIGl0IHVzZXMgUmVlZC1Tb2xvbW9uIHRvIGRldGVjdCBhbmQgY29ycmVjdCBlcnJvcnMsIGluLXBsYWNlLFxuICAgICAgICAgKiBpbiB0aGUgaW5wdXQuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gcmVjZWl2ZWQgZGF0YSBhbmQgZXJyb3ItY29ycmVjdGlvbiBjb2Rld29yZHNcbiAgICAgICAgICogQHBhcmFtIHR3b1MgbnVtYmVyIG9mIGVycm9yLWNvcnJlY3Rpb24gY29kZXdvcmRzIGF2YWlsYWJsZVxuICAgICAgICAgKiBAdGhyb3dzIFJlZWRTb2xvbW9uRXhjZXB0aW9uIGlmIGRlY29kaW5nIGZhaWxzIGZvciBhbnkgcmVhc29uXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGUocmVjZWl2ZWQsIHR3b1MgLyppbnQqLykge1xuICAgICAgICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpZWxkO1xuICAgICAgICAgICAgY29uc3QgcG9seSA9IG5ldyBHZW5lcmljR0ZQb2x5KGZpZWxkLCByZWNlaXZlZCk7XG4gICAgICAgICAgICBjb25zdCBzeW5kcm9tZUNvZWZmaWNpZW50cyA9IG5ldyBJbnQzMkFycmF5KHR3b1MpO1xuICAgICAgICAgICAgbGV0IG5vRXJyb3IgPSB0cnVlO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0d29TOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBldmFsUmVzdWx0ID0gcG9seS5ldmFsdWF0ZUF0KGZpZWxkLmV4cChpICsgZmllbGQuZ2V0R2VuZXJhdG9yQmFzZSgpKSk7XG4gICAgICAgICAgICAgICAgc3luZHJvbWVDb2VmZmljaWVudHNbc3luZHJvbWVDb2VmZmljaWVudHMubGVuZ3RoIC0gMSAtIGldID0gZXZhbFJlc3VsdDtcbiAgICAgICAgICAgICAgICBpZiAoZXZhbFJlc3VsdCAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBub0Vycm9yID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG5vRXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBzeW5kcm9tZSA9IG5ldyBHZW5lcmljR0ZQb2x5KGZpZWxkLCBzeW5kcm9tZUNvZWZmaWNpZW50cyk7XG4gICAgICAgICAgICBjb25zdCBzaWdtYU9tZWdhID0gdGhpcy5ydW5FdWNsaWRlYW5BbGdvcml0aG0oZmllbGQuYnVpbGRNb25vbWlhbCh0d29TLCAxKSwgc3luZHJvbWUsIHR3b1MpO1xuICAgICAgICAgICAgY29uc3Qgc2lnbWEgPSBzaWdtYU9tZWdhWzBdO1xuICAgICAgICAgICAgY29uc3Qgb21lZ2EgPSBzaWdtYU9tZWdhWzFdO1xuICAgICAgICAgICAgY29uc3QgZXJyb3JMb2NhdGlvbnMgPSB0aGlzLmZpbmRFcnJvckxvY2F0aW9ucyhzaWdtYSk7XG4gICAgICAgICAgICBjb25zdCBlcnJvck1hZ25pdHVkZXMgPSB0aGlzLmZpbmRFcnJvck1hZ25pdHVkZXMob21lZ2EsIGVycm9yTG9jYXRpb25zKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZXJyb3JMb2NhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwb3NpdGlvbiA9IHJlY2VpdmVkLmxlbmd0aCAtIDEgLSBmaWVsZC5sb2coZXJyb3JMb2NhdGlvbnNbaV0pO1xuICAgICAgICAgICAgICAgIGlmIChwb3NpdGlvbiA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFJlZWRTb2xvbW9uRXhjZXB0aW9uKCdCYWQgZXJyb3IgbG9jYXRpb24nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVjZWl2ZWRbcG9zaXRpb25dID0gR2VuZXJpY0dGLmFkZE9yU3VidHJhY3QocmVjZWl2ZWRbcG9zaXRpb25dLCBlcnJvck1hZ25pdHVkZXNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJ1bkV1Y2xpZGVhbkFsZ29yaXRobShhLCBiLCBSIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIC8vIEFzc3VtZSBhJ3MgZGVncmVlIGlzID49IGInc1xuICAgICAgICAgICAgaWYgKGEuZ2V0RGVncmVlKCkgPCBiLmdldERlZ3JlZSgpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdGVtcCA9IGE7XG4gICAgICAgICAgICAgICAgYSA9IGI7XG4gICAgICAgICAgICAgICAgYiA9IHRlbXA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBmaWVsZCA9IHRoaXMuZmllbGQ7XG4gICAgICAgICAgICBsZXQgckxhc3QgPSBhO1xuICAgICAgICAgICAgbGV0IHIgPSBiO1xuICAgICAgICAgICAgbGV0IHRMYXN0ID0gZmllbGQuZ2V0WmVybygpO1xuICAgICAgICAgICAgbGV0IHQgPSBmaWVsZC5nZXRPbmUoKTtcbiAgICAgICAgICAgIC8vIFJ1biBFdWNsaWRlYW4gYWxnb3JpdGhtIHVudGlsIHIncyBkZWdyZWUgaXMgbGVzcyB0aGFuIFIvMlxuICAgICAgICAgICAgd2hpbGUgKHIuZ2V0RGVncmVlKCkgPj0gKFIgLyAyIHwgMCkpIHtcbiAgICAgICAgICAgICAgICBsZXQgckxhc3RMYXN0ID0gckxhc3Q7XG4gICAgICAgICAgICAgICAgbGV0IHRMYXN0TGFzdCA9IHRMYXN0O1xuICAgICAgICAgICAgICAgIHJMYXN0ID0gcjtcbiAgICAgICAgICAgICAgICB0TGFzdCA9IHQ7XG4gICAgICAgICAgICAgICAgLy8gRGl2aWRlIHJMYXN0TGFzdCBieSByTGFzdCwgd2l0aCBxdW90aWVudCBpbiBxIGFuZCByZW1haW5kZXIgaW4gclxuICAgICAgICAgICAgICAgIGlmIChyTGFzdC5pc1plcm8oKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBPb3BzLCBFdWNsaWRlYW4gYWxnb3JpdGhtIGFscmVhZHkgdGVybWluYXRlZD9cbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFJlZWRTb2xvbW9uRXhjZXB0aW9uKCdyX3tpLTF9IHdhcyB6ZXJvJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHIgPSByTGFzdExhc3Q7XG4gICAgICAgICAgICAgICAgbGV0IHEgPSBmaWVsZC5nZXRaZXJvKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgZGVub21pbmF0b3JMZWFkaW5nVGVybSA9IHJMYXN0LmdldENvZWZmaWNpZW50KHJMYXN0LmdldERlZ3JlZSgpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBkbHRJbnZlcnNlID0gZmllbGQuaW52ZXJzZShkZW5vbWluYXRvckxlYWRpbmdUZXJtKTtcbiAgICAgICAgICAgICAgICB3aGlsZSAoci5nZXREZWdyZWUoKSA+PSByTGFzdC5nZXREZWdyZWUoKSAmJiAhci5pc1plcm8oKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWdyZWVEaWZmID0gci5nZXREZWdyZWUoKSAtIHJMYXN0LmdldERlZ3JlZSgpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzY2FsZSA9IGZpZWxkLm11bHRpcGx5KHIuZ2V0Q29lZmZpY2llbnQoci5nZXREZWdyZWUoKSksIGRsdEludmVyc2UpO1xuICAgICAgICAgICAgICAgICAgICBxID0gcS5hZGRPclN1YnRyYWN0KGZpZWxkLmJ1aWxkTW9ub21pYWwoZGVncmVlRGlmZiwgc2NhbGUpKTtcbiAgICAgICAgICAgICAgICAgICAgciA9IHIuYWRkT3JTdWJ0cmFjdChyTGFzdC5tdWx0aXBseUJ5TW9ub21pYWwoZGVncmVlRGlmZiwgc2NhbGUpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdCA9IHEubXVsdGlwbHkodExhc3QpLmFkZE9yU3VidHJhY3QodExhc3RMYXN0KTtcbiAgICAgICAgICAgICAgICBpZiAoci5nZXREZWdyZWUoKSA+PSByTGFzdC5nZXREZWdyZWUoKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCdEaXZpc2lvbiBhbGdvcml0aG0gZmFpbGVkIHRvIHJlZHVjZSBwb2x5bm9taWFsPycpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHNpZ21hVGlsZGVBdFplcm8gPSB0LmdldENvZWZmaWNpZW50KDApO1xuICAgICAgICAgICAgaWYgKHNpZ21hVGlsZGVBdFplcm8gPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUmVlZFNvbG9tb25FeGNlcHRpb24oJ3NpZ21hVGlsZGUoMCkgd2FzIHplcm8nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGludmVyc2UgPSBmaWVsZC5pbnZlcnNlKHNpZ21hVGlsZGVBdFplcm8pO1xuICAgICAgICAgICAgY29uc3Qgc2lnbWEgPSB0Lm11bHRpcGx5U2NhbGFyKGludmVyc2UpO1xuICAgICAgICAgICAgY29uc3Qgb21lZ2EgPSByLm11bHRpcGx5U2NhbGFyKGludmVyc2UpO1xuICAgICAgICAgICAgcmV0dXJuIFtzaWdtYSwgb21lZ2FdO1xuICAgICAgICB9XG4gICAgICAgIGZpbmRFcnJvckxvY2F0aW9ucyhlcnJvckxvY2F0b3IpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgYSBkaXJlY3QgYXBwbGljYXRpb24gb2YgQ2hpZW4ncyBzZWFyY2hcbiAgICAgICAgICAgIGNvbnN0IG51bUVycm9ycyA9IGVycm9yTG9jYXRvci5nZXREZWdyZWUoKTtcbiAgICAgICAgICAgIGlmIChudW1FcnJvcnMgPT09IDEpIHsgLy8gc2hvcnRjdXRcbiAgICAgICAgICAgICAgICByZXR1cm4gSW50MzJBcnJheS5mcm9tKFtlcnJvckxvY2F0b3IuZ2V0Q29lZmZpY2llbnQoMSldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBJbnQzMkFycmF5KG51bUVycm9ycyk7XG4gICAgICAgICAgICBsZXQgZSA9IDA7XG4gICAgICAgICAgICBjb25zdCBmaWVsZCA9IHRoaXMuZmllbGQ7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IGZpZWxkLmdldFNpemUoKSAmJiBlIDwgbnVtRXJyb3JzOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3JMb2NhdG9yLmV2YWx1YXRlQXQoaSkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2VdID0gZmllbGQuaW52ZXJzZShpKTtcbiAgICAgICAgICAgICAgICAgICAgZSsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChlICE9PSBudW1FcnJvcnMpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUmVlZFNvbG9tb25FeGNlcHRpb24oJ0Vycm9yIGxvY2F0b3IgZGVncmVlIGRvZXMgbm90IG1hdGNoIG51bWJlciBvZiByb290cycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBmaW5kRXJyb3JNYWduaXR1ZGVzKGVycm9yRXZhbHVhdG9yLCBlcnJvckxvY2F0aW9ucykge1xuICAgICAgICAgICAgLy8gVGhpcyBpcyBkaXJlY3RseSBhcHBseWluZyBGb3JuZXkncyBGb3JtdWxhXG4gICAgICAgICAgICBjb25zdCBzID0gZXJyb3JMb2NhdGlvbnMubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IEludDMyQXJyYXkocyk7XG4gICAgICAgICAgICBjb25zdCBmaWVsZCA9IHRoaXMuZmllbGQ7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHM7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHhpSW52ZXJzZSA9IGZpZWxkLmludmVyc2UoZXJyb3JMb2NhdGlvbnNbaV0pO1xuICAgICAgICAgICAgICAgIGxldCBkZW5vbWluYXRvciA9IDE7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBzOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkgIT09IGopIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRlbm9taW5hdG9yID0gZmllbGQubXVsdGlwbHkoZGVub21pbmF0b3IsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICBHZW5lcmljR0YuYWRkT3JTdWJ0cmFjdCgxLCBmaWVsZC5tdWx0aXBseShlcnJvckxvY2F0aW9uc1tqXSwgeGlJbnZlcnNlKSkpXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBYm92ZSBzaG91bGQgd29yayBidXQgZmFpbHMgb24gc29tZSBBcHBsZSBhbmQgTGludXggSkRLcyBkdWUgdG8gYSBIb3RzcG90IGJ1Zy5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJlbG93IGlzIGEgZnVubnktbG9va2luZyB3b3JrYXJvdW5kIGZyb20gU3RldmVuIFBhcmtlc1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGVybSA9IGZpZWxkLm11bHRpcGx5KGVycm9yTG9jYXRpb25zW2pdLCB4aUludmVyc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGVybVBsdXMxID0gKHRlcm0gJiAweDEpID09PSAwID8gdGVybSB8IDEgOiB0ZXJtICYgfjE7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZW5vbWluYXRvciA9IGZpZWxkLm11bHRpcGx5KGRlbm9taW5hdG9yLCB0ZXJtUGx1czEpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc3VsdFtpXSA9IGZpZWxkLm11bHRpcGx5KGVycm9yRXZhbHVhdG9yLmV2YWx1YXRlQXQoeGlJbnZlcnNlKSwgZmllbGQuaW52ZXJzZShkZW5vbWluYXRvcikpO1xuICAgICAgICAgICAgICAgIGlmIChmaWVsZC5nZXRHZW5lcmF0b3JCYXNlKCkgIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2ldID0gZmllbGQubXVsdGlwbHkocmVzdWx0W2ldLCB4aUludmVyc2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDEwIFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8vIGltcG9ydCBqYXZhLnV0aWwuQXJyYXlzO1xuICAgIHZhciBUYWJsZTtcbiAgICAoZnVuY3Rpb24gKFRhYmxlKSB7XG4gICAgICAgIFRhYmxlW1RhYmxlW1wiVVBQRVJcIl0gPSAwXSA9IFwiVVBQRVJcIjtcbiAgICAgICAgVGFibGVbVGFibGVbXCJMT1dFUlwiXSA9IDFdID0gXCJMT1dFUlwiO1xuICAgICAgICBUYWJsZVtUYWJsZVtcIk1JWEVEXCJdID0gMl0gPSBcIk1JWEVEXCI7XG4gICAgICAgIFRhYmxlW1RhYmxlW1wiRElHSVRcIl0gPSAzXSA9IFwiRElHSVRcIjtcbiAgICAgICAgVGFibGVbVGFibGVbXCJQVU5DVFwiXSA9IDRdID0gXCJQVU5DVFwiO1xuICAgICAgICBUYWJsZVtUYWJsZVtcIkJJTkFSWVwiXSA9IDVdID0gXCJCSU5BUllcIjtcbiAgICB9KShUYWJsZSB8fCAoVGFibGUgPSB7fSkpO1xuICAgIC8qKlxuICAgICAqIDxwPlRoZSBtYWluIGNsYXNzIHdoaWNoIGltcGxlbWVudHMgQXp0ZWMgQ29kZSBkZWNvZGluZyAtLSBhcyBvcHBvc2VkIHRvIGxvY2F0aW5nIGFuZCBleHRyYWN0aW5nXG4gICAgICogdGhlIEF6dGVjIENvZGUgZnJvbSBhbiBpbWFnZS48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIERhdmlkIE9saXZpZXJcbiAgICAgKi9cbiAgICBjbGFzcyBEZWNvZGVyIHtcbiAgICAgICAgZGVjb2RlKGRldGVjdG9yUmVzdWx0KSB7XG4gICAgICAgICAgICB0aGlzLmRkYXRhID0gZGV0ZWN0b3JSZXN1bHQ7XG4gICAgICAgICAgICBsZXQgbWF0cml4ID0gZGV0ZWN0b3JSZXN1bHQuZ2V0Qml0cygpO1xuICAgICAgICAgICAgbGV0IHJhd2JpdHMgPSB0aGlzLmV4dHJhY3RCaXRzKG1hdHJpeCk7XG4gICAgICAgICAgICBsZXQgY29ycmVjdGVkQml0cyA9IHRoaXMuY29ycmVjdEJpdHMocmF3Yml0cyk7XG4gICAgICAgICAgICBsZXQgcmF3Qnl0ZXMgPSBEZWNvZGVyLmNvbnZlcnRCb29sQXJyYXlUb0J5dGVBcnJheShjb3JyZWN0ZWRCaXRzKTtcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSBEZWNvZGVyLmdldEVuY29kZWREYXRhKGNvcnJlY3RlZEJpdHMpO1xuICAgICAgICAgICAgbGV0IGRlY29kZXJSZXN1bHQgPSBuZXcgRGVjb2RlclJlc3VsdChyYXdCeXRlcywgcmVzdWx0LCBudWxsLCBudWxsKTtcbiAgICAgICAgICAgIGRlY29kZXJSZXN1bHQuc2V0TnVtQml0cyhjb3JyZWN0ZWRCaXRzLmxlbmd0aCk7XG4gICAgICAgICAgICByZXR1cm4gZGVjb2RlclJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICAvLyBUaGlzIG1ldGhvZCBpcyB1c2VkIGZvciB0ZXN0aW5nIHRoZSBoaWdoLWxldmVsIGVuY29kZXJcbiAgICAgICAgc3RhdGljIGhpZ2hMZXZlbERlY29kZShjb3JyZWN0ZWRCaXRzKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRFbmNvZGVkRGF0YShjb3JyZWN0ZWRCaXRzKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogR2V0cyB0aGUgc3RyaW5nIGVuY29kZWQgaW4gdGhlIGF6dGVjIGNvZGUgYml0c1xuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIHRoZSBkZWNvZGVkIHN0cmluZ1xuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGdldEVuY29kZWREYXRhKGNvcnJlY3RlZEJpdHMpIHtcbiAgICAgICAgICAgIGxldCBlbmRJbmRleCA9IGNvcnJlY3RlZEJpdHMubGVuZ3RoO1xuICAgICAgICAgICAgbGV0IGxhdGNoVGFibGUgPSBUYWJsZS5VUFBFUjsgLy8gdGFibGUgbW9zdCByZWNlbnRseSBsYXRjaGVkIHRvXG4gICAgICAgICAgICBsZXQgc2hpZnRUYWJsZSA9IFRhYmxlLlVQUEVSOyAvLyB0YWJsZSB0byB1c2UgZm9yIHRoZSBuZXh0IHJlYWRcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSAnJztcbiAgICAgICAgICAgIGxldCBpbmRleCA9IDA7XG4gICAgICAgICAgICB3aGlsZSAoaW5kZXggPCBlbmRJbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChzaGlmdFRhYmxlID09PSBUYWJsZS5CSU5BUlkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVuZEluZGV4IC0gaW5kZXggPCA1KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBsZXQgbGVuZ3RoID0gRGVjb2Rlci5yZWFkQ29kZShjb3JyZWN0ZWRCaXRzLCBpbmRleCwgNSk7XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDU7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbmRJbmRleCAtIGluZGV4IDwgMTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aCA9IERlY29kZXIucmVhZENvZGUoY29ycmVjdGVkQml0cywgaW5kZXgsIDExKSArIDMxO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgY2hhckNvdW50ID0gMDsgY2hhckNvdW50IDwgbGVuZ3RoOyBjaGFyQ291bnQrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVuZEluZGV4IC0gaW5kZXggPCA4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggPSBlbmRJbmRleDsgLy8gRm9yY2Ugb3V0ZXIgbG9vcCB0byBleGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb2RlID0gRGVjb2Rlci5yZWFkQ29kZShjb3JyZWN0ZWRCaXRzLCBpbmRleCwgOCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gLyooY2hhcikqLyBTdHJpbmdVdGlscy5jYXN0QXNOb25VdGY4Q2hhcihjb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDg7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gR28gYmFjayB0byB3aGF0ZXZlciBtb2RlIHdlIGhhZCBiZWVuIGluXG4gICAgICAgICAgICAgICAgICAgIHNoaWZ0VGFibGUgPSBsYXRjaFRhYmxlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHNpemUgPSBzaGlmdFRhYmxlID09PSBUYWJsZS5ESUdJVCA/IDQgOiA1O1xuICAgICAgICAgICAgICAgICAgICBpZiAoZW5kSW5kZXggLSBpbmRleCA8IHNpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGxldCBjb2RlID0gRGVjb2Rlci5yZWFkQ29kZShjb3JyZWN0ZWRCaXRzLCBpbmRleCwgc2l6ZSk7XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IHNpemU7XG4gICAgICAgICAgICAgICAgICAgIGxldCBzdHIgPSBEZWNvZGVyLmdldENoYXJhY3RlcihzaGlmdFRhYmxlLCBjb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0ci5zdGFydHNXaXRoKCdDVFJMXycpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUYWJsZSBjaGFuZ2VzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJU08vSUVDIDI0Nzc4OjIwMDggcHJlc2NyaWJlcyBlbmRpbmcgYSBzaGlmdCBzZXF1ZW5jZSBpbiB0aGUgbW9kZSBmcm9tIHdoaWNoIGl0IHdhcyBpbnZva2VkLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhhdCdzIGluY2x1ZGluZyB3aGVuIHRoYXQgbW9kZSBpcyBhIHNoaWZ0LlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3VyIHRlc3QgY2FzZSBkbHVzYnMucG5nIGZvciBpc3N1ZSAjNjQyIGV4ZXJjaXNlcyB0aGF0LlxuICAgICAgICAgICAgICAgICAgICAgICAgbGF0Y2hUYWJsZSA9IHNoaWZ0VGFibGU7IC8vIExhdGNoIHRoZSBjdXJyZW50IG1vZGUsIHNvIGFzIHRvIHJldHVybiB0byBVcHBlciBhZnRlciBVL1MgQi9TXG4gICAgICAgICAgICAgICAgICAgICAgICBzaGlmdFRhYmxlID0gRGVjb2Rlci5nZXRUYWJsZShzdHIuY2hhckF0KDUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdHIuY2hhckF0KDYpID09PSAnTCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXRjaFRhYmxlID0gc2hpZnRUYWJsZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSBzdHI7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBHbyBiYWNrIHRvIHdoYXRldmVyIG1vZGUgd2UgaGFkIGJlZW4gaW5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNoaWZ0VGFibGUgPSBsYXRjaFRhYmxlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogZ2V0cyB0aGUgdGFibGUgY29ycmVzcG9uZGluZyB0byB0aGUgY2hhciBwYXNzZWRcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBnZXRUYWJsZSh0KSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHQpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdMJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFRhYmxlLkxPV0VSO1xuICAgICAgICAgICAgICAgIGNhc2UgJ1AnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gVGFibGUuUFVOQ1Q7XG4gICAgICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBUYWJsZS5NSVhFRDtcbiAgICAgICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFRhYmxlLkRJR0lUO1xuICAgICAgICAgICAgICAgIGNhc2UgJ0InOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gVGFibGUuQklOQVJZO1xuICAgICAgICAgICAgICAgIGNhc2UgJ1UnOlxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBUYWJsZS5VUFBFUjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogR2V0cyB0aGUgY2hhcmFjdGVyIChvciBzdHJpbmcpIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHBhc3NlZCBjb2RlIGluIHRoZSBnaXZlbiB0YWJsZVxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gdGFibGUgdGhlIHRhYmxlIHVzZWRcbiAgICAgICAgICogQHBhcmFtIGNvZGUgdGhlIGNvZGUgb2YgdGhlIGNoYXJhY3RlclxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGdldENoYXJhY3Rlcih0YWJsZSwgY29kZSkge1xuICAgICAgICAgICAgc3dpdGNoICh0YWJsZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgVGFibGUuVVBQRVI6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBEZWNvZGVyLlVQUEVSX1RBQkxFW2NvZGVdO1xuICAgICAgICAgICAgICAgIGNhc2UgVGFibGUuTE9XRVI6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBEZWNvZGVyLkxPV0VSX1RBQkxFW2NvZGVdO1xuICAgICAgICAgICAgICAgIGNhc2UgVGFibGUuTUlYRUQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBEZWNvZGVyLk1JWEVEX1RBQkxFW2NvZGVdO1xuICAgICAgICAgICAgICAgIGNhc2UgVGFibGUuUFVOQ1Q6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBEZWNvZGVyLlBVTkNUX1RBQkxFW2NvZGVdO1xuICAgICAgICAgICAgICAgIGNhc2UgVGFibGUuRElHSVQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBEZWNvZGVyLkRJR0lUX1RBQkxFW2NvZGVdO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIC8vIFNob3VsZCBub3QgcmVhY2ggaGVyZS5cbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbignQmFkIHRhYmxlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPlBlcmZvcm1zIFJTIGVycm9yIGNvcnJlY3Rpb24gb24gYW4gYXJyYXkgb2YgYml0cy48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gdGhlIGNvcnJlY3RlZCBhcnJheVxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvbiBpZiB0aGUgaW5wdXQgY29udGFpbnMgdG9vIG1hbnkgZXJyb3JzXG4gICAgICAgICAqL1xuICAgICAgICBjb3JyZWN0Qml0cyhyYXdiaXRzKSB7XG4gICAgICAgICAgICBsZXQgZ2Y7XG4gICAgICAgICAgICBsZXQgY29kZXdvcmRTaXplO1xuICAgICAgICAgICAgaWYgKHRoaXMuZGRhdGEuZ2V0TmJMYXllcnMoKSA8PSAyKSB7XG4gICAgICAgICAgICAgICAgY29kZXdvcmRTaXplID0gNjtcbiAgICAgICAgICAgICAgICBnZiA9IEdlbmVyaWNHRi5BWlRFQ19EQVRBXzY7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLmRkYXRhLmdldE5iTGF5ZXJzKCkgPD0gOCkge1xuICAgICAgICAgICAgICAgIGNvZGV3b3JkU2l6ZSA9IDg7XG4gICAgICAgICAgICAgICAgZ2YgPSBHZW5lcmljR0YuQVpURUNfREFUQV84O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5kZGF0YS5nZXROYkxheWVycygpIDw9IDIyKSB7XG4gICAgICAgICAgICAgICAgY29kZXdvcmRTaXplID0gMTA7XG4gICAgICAgICAgICAgICAgZ2YgPSBHZW5lcmljR0YuQVpURUNfREFUQV8xMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvZGV3b3JkU2l6ZSA9IDEyO1xuICAgICAgICAgICAgICAgIGdmID0gR2VuZXJpY0dGLkFaVEVDX0RBVEFfMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgbnVtRGF0YUNvZGV3b3JkcyA9IHRoaXMuZGRhdGEuZ2V0TmJEYXRhYmxvY2tzKCk7XG4gICAgICAgICAgICBsZXQgbnVtQ29kZXdvcmRzID0gcmF3Yml0cy5sZW5ndGggLyBjb2Rld29yZFNpemU7XG4gICAgICAgICAgICBpZiAobnVtQ29kZXdvcmRzIDwgbnVtRGF0YUNvZGV3b3Jkcykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBvZmZzZXQgPSByYXdiaXRzLmxlbmd0aCAlIGNvZGV3b3JkU2l6ZTtcbiAgICAgICAgICAgIGxldCBkYXRhV29yZHMgPSBuZXcgSW50MzJBcnJheShudW1Db2Rld29yZHMpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1Db2Rld29yZHM7IGkrKywgb2Zmc2V0ICs9IGNvZGV3b3JkU2l6ZSkge1xuICAgICAgICAgICAgICAgIGRhdGFXb3Jkc1tpXSA9IERlY29kZXIucmVhZENvZGUocmF3Yml0cywgb2Zmc2V0LCBjb2Rld29yZFNpemUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBsZXQgcnNEZWNvZGVyID0gbmV3IFJlZWRTb2xvbW9uRGVjb2RlcihnZik7XG4gICAgICAgICAgICAgICAgcnNEZWNvZGVyLmRlY29kZShkYXRhV29yZHMsIG51bUNvZGV3b3JkcyAtIG51bURhdGFDb2Rld29yZHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbihleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBOb3cgcGVyZm9ybSB0aGUgdW5zdHVmZmluZyBvcGVyYXRpb24uXG4gICAgICAgICAgICAvLyBGaXJzdCwgY291bnQgaG93IG1hbnkgYml0cyBhcmUgZ29pbmcgdG8gYmUgdGhyb3duIG91dCBhcyBzdHVmZmluZ1xuICAgICAgICAgICAgbGV0IG1hc2sgPSAoMSA8PCBjb2Rld29yZFNpemUpIC0gMTtcbiAgICAgICAgICAgIGxldCBzdHVmZmVkQml0cyA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bURhdGFDb2Rld29yZHM7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCBkYXRhV29yZCA9IGRhdGFXb3Jkc1tpXTtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YVdvcmQgPT09IDAgfHwgZGF0YVdvcmQgPT09IG1hc2spIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChkYXRhV29yZCA9PT0gMSB8fCBkYXRhV29yZCA9PT0gbWFzayAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgc3R1ZmZlZEJpdHMrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBOb3csIGFjdHVhbGx5IHVucGFjayB0aGUgYml0cyBhbmQgcmVtb3ZlIHRoZSBzdHVmZmluZ1xuICAgICAgICAgICAgbGV0IGNvcnJlY3RlZEJpdHMgPSBuZXcgQXJyYXkobnVtRGF0YUNvZGV3b3JkcyAqIGNvZGV3b3JkU2l6ZSAtIHN0dWZmZWRCaXRzKTtcbiAgICAgICAgICAgIGxldCBpbmRleCA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bURhdGFDb2Rld29yZHM7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCBkYXRhV29yZCA9IGRhdGFXb3Jkc1tpXTtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YVdvcmQgPT09IDEgfHwgZGF0YVdvcmQgPT09IG1hc2sgLSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIG5leHQgY29kZXdvcmRTaXplLTEgYml0cyBhcmUgYWxsIHplcm9zIG9yIGFsbCBvbmVzXG4gICAgICAgICAgICAgICAgICAgIGNvcnJlY3RlZEJpdHMuZmlsbChkYXRhV29yZCA+IDEsIGluZGV4LCBpbmRleCArIGNvZGV3b3JkU2l6ZSAtIDEpO1xuICAgICAgICAgICAgICAgICAgICAvLyBBcnJheXMuZmlsbChjb3JyZWN0ZWRCaXRzLCBpbmRleCwgaW5kZXggKyBjb2Rld29yZFNpemUgLSAxLCBkYXRhV29yZCA+IDEpO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjb2Rld29yZFNpemUgLSAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgYml0ID0gY29kZXdvcmRTaXplIC0gMTsgYml0ID49IDA7IC0tYml0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWN0ZWRCaXRzW2luZGV4KytdID0gKGRhdGFXb3JkICYgKDEgPDwgYml0KSkgIT09IDA7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY29ycmVjdGVkQml0cztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogR2V0cyB0aGUgYXJyYXkgb2YgYml0cyBmcm9tIGFuIEF6dGVjIENvZGUgbWF0cml4XG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gdGhlIGFycmF5IG9mIGJpdHNcbiAgICAgICAgICovXG4gICAgICAgIGV4dHJhY3RCaXRzKG1hdHJpeCkge1xuICAgICAgICAgICAgbGV0IGNvbXBhY3QgPSB0aGlzLmRkYXRhLmlzQ29tcGFjdCgpO1xuICAgICAgICAgICAgbGV0IGxheWVycyA9IHRoaXMuZGRhdGEuZ2V0TmJMYXllcnMoKTtcbiAgICAgICAgICAgIGxldCBiYXNlTWF0cml4U2l6ZSA9IChjb21wYWN0ID8gMTEgOiAxNCkgKyBsYXllcnMgKiA0OyAvLyBub3QgaW5jbHVkaW5nIGFsaWdubWVudCBsaW5lc1xuICAgICAgICAgICAgbGV0IGFsaWdubWVudE1hcCA9IG5ldyBJbnQzMkFycmF5KGJhc2VNYXRyaXhTaXplKTtcbiAgICAgICAgICAgIGxldCByYXdiaXRzID0gbmV3IEFycmF5KHRoaXMudG90YWxCaXRzSW5MYXllcihsYXllcnMsIGNvbXBhY3QpKTtcbiAgICAgICAgICAgIGlmIChjb21wYWN0KSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhbGlnbm1lbnRNYXAubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgYWxpZ25tZW50TWFwW2ldID0gaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBsZXQgbWF0cml4U2l6ZSA9IGJhc2VNYXRyaXhTaXplICsgMSArIDIgKiBJbnRlZ2VyLnRydW5jRGl2aXNpb24oKEludGVnZXIudHJ1bmNEaXZpc2lvbihiYXNlTWF0cml4U2l6ZSwgMikgLSAxKSwgMTUpO1xuICAgICAgICAgICAgICAgIGxldCBvcmlnQ2VudGVyID0gYmFzZU1hdHJpeFNpemUgLyAyO1xuICAgICAgICAgICAgICAgIGxldCBjZW50ZXIgPSBJbnRlZ2VyLnRydW5jRGl2aXNpb24obWF0cml4U2l6ZSwgMik7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvcmlnQ2VudGVyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG5ld09mZnNldCA9IGkgKyBJbnRlZ2VyLnRydW5jRGl2aXNpb24oaSwgMTUpO1xuICAgICAgICAgICAgICAgICAgICBhbGlnbm1lbnRNYXBbb3JpZ0NlbnRlciAtIGkgLSAxXSA9IGNlbnRlciAtIG5ld09mZnNldCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIGFsaWdubWVudE1hcFtvcmlnQ2VudGVyICsgaV0gPSBjZW50ZXIgKyBuZXdPZmZzZXQgKyAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCByb3dPZmZzZXQgPSAwOyBpIDwgbGF5ZXJzOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgcm93U2l6ZSA9IChsYXllcnMgLSBpKSAqIDQgKyAoY29tcGFjdCA/IDkgOiAxMik7XG4gICAgICAgICAgICAgICAgLy8gVGhlIHRvcC1sZWZ0IG1vc3QgcG9pbnQgb2YgdGhpcyBsYXllciBpcyA8bG93LCBsb3c+IChub3QgaW5jbHVkaW5nIGFsaWdubWVudCBsaW5lcylcbiAgICAgICAgICAgICAgICBsZXQgbG93ID0gaSAqIDI7XG4gICAgICAgICAgICAgICAgLy8gVGhlIGJvdHRvbS1yaWdodCBtb3N0IHBvaW50IG9mIHRoaXMgbGF5ZXIgaXMgPGhpZ2gsIGhpZ2g+IChub3QgaW5jbHVkaW5nIGFsaWdubWVudCBsaW5lcylcbiAgICAgICAgICAgICAgICBsZXQgaGlnaCA9IGJhc2VNYXRyaXhTaXplIC0gMSAtIGxvdztcbiAgICAgICAgICAgICAgICAvLyBXZSBwdWxsIGJpdHMgZnJvbSB0aGUgdHdvIDIgeCByb3dTaXplIGNvbHVtbnMgYW5kIHR3byByb3dTaXplIHggMiByb3dzXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCByb3dTaXplOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNvbHVtbk9mZnNldCA9IGogKiAyO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IDI7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbGVmdCBjb2x1bW5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJhd2JpdHNbcm93T2Zmc2V0ICsgY29sdW1uT2Zmc2V0ICsga10gPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdHJpeC5nZXQoYWxpZ25tZW50TWFwW2xvdyArIGtdLCBhbGlnbm1lbnRNYXBbbG93ICsgal0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYm90dG9tIHJvd1xuICAgICAgICAgICAgICAgICAgICAgICAgcmF3Yml0c1tyb3dPZmZzZXQgKyAyICogcm93U2l6ZSArIGNvbHVtbk9mZnNldCArIGtdID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXguZ2V0KGFsaWdubWVudE1hcFtsb3cgKyBqXSwgYWxpZ25tZW50TWFwW2hpZ2ggLSBrXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyByaWdodCBjb2x1bW5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJhd2JpdHNbcm93T2Zmc2V0ICsgNCAqIHJvd1NpemUgKyBjb2x1bW5PZmZzZXQgKyBrXSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LmdldChhbGlnbm1lbnRNYXBbaGlnaCAtIGtdLCBhbGlnbm1lbnRNYXBbaGlnaCAtIGpdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRvcCByb3dcbiAgICAgICAgICAgICAgICAgICAgICAgIHJhd2JpdHNbcm93T2Zmc2V0ICsgNiAqIHJvd1NpemUgKyBjb2x1bW5PZmZzZXQgKyBrXSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LmdldChhbGlnbm1lbnRNYXBbaGlnaCAtIGpdLCBhbGlnbm1lbnRNYXBbbG93ICsga10pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJvd09mZnNldCArPSByb3dTaXplICogODtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByYXdiaXRzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZWFkcyBhIGNvZGUgb2YgZ2l2ZW4gbGVuZ3RoIGFuZCBhdCBnaXZlbiBpbmRleCBpbiBhbiBhcnJheSBvZiBiaXRzXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgcmVhZENvZGUocmF3Yml0cywgc3RhcnRJbmRleCwgbGVuZ3RoKSB7XG4gICAgICAgICAgICBsZXQgcmVzID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdGFydEluZGV4OyBpIDwgc3RhcnRJbmRleCArIGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcmVzIDw8PSAxO1xuICAgICAgICAgICAgICAgIGlmIChyYXdiaXRzW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcyB8PSAweDAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJlYWRzIGEgY29kZSBvZiBsZW5ndGggOCBpbiBhbiBhcnJheSBvZiBiaXRzLCBwYWRkaW5nIHdpdGggemVyb3NcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyByZWFkQnl0ZShyYXdiaXRzLCBzdGFydEluZGV4KSB7XG4gICAgICAgICAgICBsZXQgbiA9IHJhd2JpdHMubGVuZ3RoIC0gc3RhcnRJbmRleDtcbiAgICAgICAgICAgIGlmIChuID49IDgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRGVjb2Rlci5yZWFkQ29kZShyYXdiaXRzLCBzdGFydEluZGV4LCA4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBEZWNvZGVyLnJlYWRDb2RlKHJhd2JpdHMsIHN0YXJ0SW5kZXgsIG4pIDw8ICg4IC0gbik7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFBhY2tzIGEgYml0IGFycmF5IGludG8gYnl0ZXMsIG1vc3Qgc2lnbmlmaWNhbnQgYml0IGZpcnN0XG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgY29udmVydEJvb2xBcnJheVRvQnl0ZUFycmF5KGJvb2xBcnIpIHtcbiAgICAgICAgICAgIGxldCBieXRlQXJyID0gbmV3IFVpbnQ4QXJyYXkoKGJvb2xBcnIubGVuZ3RoICsgNykgLyA4KTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnl0ZUFyci5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGJ5dGVBcnJbaV0gPSBEZWNvZGVyLnJlYWRCeXRlKGJvb2xBcnIsIDggKiBpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBieXRlQXJyO1xuICAgICAgICB9XG4gICAgICAgIHRvdGFsQml0c0luTGF5ZXIobGF5ZXJzLCBjb21wYWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gKChjb21wYWN0ID8gODggOiAxMTIpICsgMTYgKiBsYXllcnMpICogbGF5ZXJzO1xuICAgICAgICB9XG4gICAgfVxuICAgIERlY29kZXIuVVBQRVJfVEFCTEUgPSBbXG4gICAgICAgICdDVFJMX1BTJywgJyAnLCAnQScsICdCJywgJ0MnLCAnRCcsICdFJywgJ0YnLCAnRycsICdIJywgJ0knLCAnSicsICdLJywgJ0wnLCAnTScsICdOJywgJ08nLCAnUCcsXG4gICAgICAgICdRJywgJ1InLCAnUycsICdUJywgJ1UnLCAnVicsICdXJywgJ1gnLCAnWScsICdaJywgJ0NUUkxfTEwnLCAnQ1RSTF9NTCcsICdDVFJMX0RMJywgJ0NUUkxfQlMnXG4gICAgXTtcbiAgICBEZWNvZGVyLkxPV0VSX1RBQkxFID0gW1xuICAgICAgICAnQ1RSTF9QUycsICcgJywgJ2EnLCAnYicsICdjJywgJ2QnLCAnZScsICdmJywgJ2cnLCAnaCcsICdpJywgJ2onLCAnaycsICdsJywgJ20nLCAnbicsICdvJywgJ3AnLFxuICAgICAgICAncScsICdyJywgJ3MnLCAndCcsICd1JywgJ3YnLCAndycsICd4JywgJ3knLCAneicsICdDVFJMX1VTJywgJ0NUUkxfTUwnLCAnQ1RSTF9ETCcsICdDVFJMX0JTJ1xuICAgIF07XG4gICAgRGVjb2Rlci5NSVhFRF9UQUJMRSA9IFtcbiAgICAgICAgLy8gTW9kdWxlIHBhcnNlIGZhaWxlZDogT2N0YWwgbGl0ZXJhbCBpbiBzdHJpY3QgbW9kZSAoNTA6MjkpXG4gICAgICAgIC8vIHNvIG51bWJlciBzdHJpbmcgd2VyZSBzY2FwZWRcbiAgICAgICAgJ0NUUkxfUFMnLCAnICcsICdcXFxcMScsICdcXFxcMicsICdcXFxcMycsICdcXFxcNCcsICdcXFxcNScsICdcXFxcNicsICdcXFxcNycsICdcXGInLCAnXFx0JywgJ1xcbicsXG4gICAgICAgICdcXFxcMTMnLCAnXFxmJywgJ1xccicsICdcXFxcMzMnLCAnXFxcXDM0JywgJ1xcXFwzNScsICdcXFxcMzYnLCAnXFxcXDM3JywgJ0AnLCAnXFxcXCcsICdeJywgJ18nLFxuICAgICAgICAnYCcsICd8JywgJ34nLCAnXFxcXDE3NycsICdDVFJMX0xMJywgJ0NUUkxfVUwnLCAnQ1RSTF9QTCcsICdDVFJMX0JTJ1xuICAgIF07XG4gICAgRGVjb2Rlci5QVU5DVF9UQUJMRSA9IFtcbiAgICAgICAgJycsICdcXHInLCAnXFxyXFxuJywgJy4gJywgJywgJywgJzogJywgJyEnLCAnXCInLCAnIycsICckJywgJyUnLCAnJicsICdcXCcnLCAnKCcsICcpJyxcbiAgICAgICAgJyonLCAnKycsICcsJywgJy0nLCAnLicsICcvJywgJzonLCAnOycsICc8JywgJz0nLCAnPicsICc/JywgJ1snLCAnXScsICd7JywgJ30nLCAnQ1RSTF9VTCdcbiAgICBdO1xuICAgIERlY29kZXIuRElHSVRfVEFCTEUgPSBbXG4gICAgICAgICdDVFJMX1BTJywgJyAnLCAnMCcsICcxJywgJzInLCAnMycsICc0JywgJzUnLCAnNicsICc3JywgJzgnLCAnOScsICcsJywgJy4nLCAnQ1RSTF9VTCcsICdDVFJMX1VTJ1xuICAgIF07XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDEyIFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qbmFtZXNwYWNlIGNvbS5nb29nbGUuenhpbmcuY29tbW9uLmRldGVjdG9yIHsqL1xuICAgIC8qKlxuICAgICAqIEdlbmVyYWwgbWF0aC1yZWxhdGVkIGFuZCBudW1lcmljIHV0aWxpdHkgZnVuY3Rpb25zLlxuICAgICAqL1xuICAgIGNsYXNzIE1hdGhVdGlscyB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkgeyB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbmRzIHVwIGJlaW5nIGEgYml0IGZhc3RlciB0aGFuIHtAbGluayBNYXRoI3JvdW5kKGZsb2F0KX0uIFRoaXMgbWVyZWx5IHJvdW5kcyBpdHNcbiAgICAgICAgICogYXJndW1lbnQgdG8gdGhlIG5lYXJlc3QgaW50LCB3aGVyZSB4LjUgcm91bmRzIHVwIHRvIHgrMS4gU2VtYW50aWNzIG9mIHRoaXMgc2hvcnRjdXRcbiAgICAgICAgICogZGlmZmVyIHNsaWdodGx5IGZyb20ge0BsaW5rIE1hdGgjcm91bmQoZmxvYXQpfSBpbiB0aGF0IGhhbGYgcm91bmRzIGRvd24gZm9yIG5lZ2F0aXZlXG4gICAgICAgICAqIHZhbHVlcy4gLTIuNSByb3VuZHMgdG8gLTMsIG5vdCAtMi4gRm9yIHB1cnBvc2VzIGhlcmUgaXQgbWFrZXMgbm8gZGlmZmVyZW5jZS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGQgcmVhbCB2YWx1ZSB0byByb3VuZFxuICAgICAgICAgKiBAcmV0dXJuIG5lYXJlc3Qge0Bjb2RlIGludH1cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyByb3VuZChkIC8qZmxvYXQqLykge1xuICAgICAgICAgICAgaWYgKE5hTiA9PT0gZClcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIGlmIChkIDw9IE51bWJlci5NSU5fU0FGRV9JTlRFR0VSKVxuICAgICAgICAgICAgICAgIHJldHVybiBOdW1iZXIuTUlOX1NBRkVfSU5URUdFUjtcbiAgICAgICAgICAgIGlmIChkID49IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSKVxuICAgICAgICAgICAgICAgIHJldHVybiBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUjtcbiAgICAgICAgICAgIHJldHVybiAvKihpbnQpICovIChkICsgKGQgPCAwLjAgPyAtMC41IDogMC41KSkgfCAwO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRZUEVTQ1JJUFRQT1JUOiBtYXliZSByZW1vdmUgcm91bmQgbWV0aG9kIGFuZCBjYWxsIGRpcmVjdGx5IE1hdGgucm91bmQsIGl0IGxvb2tzIGxpa2UgaXQgZG9lc24ndCBtYWtlIHNlbnNlIGZvciBqc1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIGFYIHBvaW50IEEgeCBjb29yZGluYXRlXG4gICAgICAgICAqIEBwYXJhbSBhWSBwb2ludCBBIHkgY29vcmRpbmF0ZVxuICAgICAgICAgKiBAcGFyYW0gYlggcG9pbnQgQiB4IGNvb3JkaW5hdGVcbiAgICAgICAgICogQHBhcmFtIGJZIHBvaW50IEIgeSBjb29yZGluYXRlXG4gICAgICAgICAqIEByZXR1cm4gRXVjbGlkZWFuIGRpc3RhbmNlIGJldHdlZW4gcG9pbnRzIEEgYW5kIEJcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBkaXN0YW5jZShhWCAvKmZsb2F0fGludCovLCBhWSAvKmZsb2F0fGludCovLCBiWCAvKmZsb2F0fGludCovLCBiWSAvKmZsb2F0fGludCovKSB7XG4gICAgICAgICAgICBjb25zdCB4RGlmZiA9IGFYIC0gYlg7XG4gICAgICAgICAgICBjb25zdCB5RGlmZiA9IGFZIC0gYlk7XG4gICAgICAgICAgICByZXR1cm4gLyooZmxvYXQpICovIE1hdGguc3FydCh4RGlmZiAqIHhEaWZmICsgeURpZmYgKiB5RGlmZik7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBhWCBwb2ludCBBIHggY29vcmRpbmF0ZVxuICAgICAgICAgKiBAcGFyYW0gYVkgcG9pbnQgQSB5IGNvb3JkaW5hdGVcbiAgICAgICAgICogQHBhcmFtIGJYIHBvaW50IEIgeCBjb29yZGluYXRlXG4gICAgICAgICAqIEBwYXJhbSBiWSBwb2ludCBCIHkgY29vcmRpbmF0ZVxuICAgICAgICAgKiBAcmV0dXJuIEV1Y2xpZGVhbiBkaXN0YW5jZSBiZXR3ZWVuIHBvaW50cyBBIGFuZCBCXG4gICAgICAgICAqL1xuICAgICAgICAvLyBwdWJsaWMgc3RhdGljIGRpc3RhbmNlKGFYOiBudW1iZXIgLyppbnQqLywgYVk6IG51bWJlciAvKmludCovLCBiWDogbnVtYmVyIC8qaW50Ki8sIGJZOiBudW1iZXIgLyppbnQqLyk6IGZsb2F0IHtcbiAgICAgICAgLy8gICBjb25zdCB4RGlmZiA9IGFYIC0gYlhcbiAgICAgICAgLy8gICBjb25zdCB5RGlmZiA9IGFZIC0gYllcbiAgICAgICAgLy8gICByZXR1cm4gKGZsb2F0KSBNYXRoLnNxcnQoeERpZmYgKiB4RGlmZiArIHlEaWZmICogeURpZmYpO1xuICAgICAgICAvLyB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gYXJyYXkgdmFsdWVzIHRvIHN1bVxuICAgICAgICAgKiBAcmV0dXJuIHN1bSBvZiB2YWx1ZXMgaW4gYXJyYXlcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBzdW0oYXJyYXkpIHtcbiAgICAgICAgICAgIGxldCBjb3VudCA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgbGVuZ3RoID0gYXJyYXkubGVuZ3RoOyBpICE9PSBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGEgPSBhcnJheVtpXTtcbiAgICAgICAgICAgICAgICBjb3VudCArPSBhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGNvdW50O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUG9ueWZpbGwgZm9yIEphdmEncyBGbG9hdCBjbGFzcy5cbiAgICAgKi9cbiAgICBjbGFzcyBGbG9hdCB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTaW5jVFMgaGFzIG5vIGRpZmZlcmVuY2UgYmV0d2VlbiBpbnQgYW5kIGZsb2F0LCB0aGVyZSdzIGFsbCBudW1iZXJzLFxuICAgICAgICAgKiB0aGlzIGlzIHVzZWQgb25seSB0byBwb2x5ZmlsbCBKYXZhIGNvZGUuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZmxvYXRUb0ludEJpdHMoZikge1xuICAgICAgICAgICAgcmV0dXJuIGY7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogVGhlIGZsb2F0IG1heCB2YWx1ZSBpbiBKUyBpcyB0aGUgbnVtYmVyIG1heCB2YWx1ZS5cbiAgICAgKi9cbiAgICBGbG9hdC5NQVhfVkFMVUUgPSBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUjtcblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogPHA+RW5jYXBzdWxhdGVzIGEgcG9pbnQgb2YgaW50ZXJlc3QgaW4gYW4gaW1hZ2UgY29udGFpbmluZyBhIGJhcmNvZGUuIFR5cGljYWxseSwgdGhpc1xuICAgICAqIHdvdWxkIGJlIHRoZSBsb2NhdGlvbiBvZiBhIGZpbmRlciBwYXR0ZXJuIG9yIHRoZSBjb3JuZXIgb2YgdGhlIGJhcmNvZGUsIGZvciBleGFtcGxlLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgUmVzdWx0UG9pbnQge1xuICAgICAgICBjb25zdHJ1Y3Rvcih4LCB5KSB7XG4gICAgICAgICAgICB0aGlzLnggPSB4O1xuICAgICAgICAgICAgdGhpcy55ID0geTtcbiAgICAgICAgfVxuICAgICAgICBnZXRYKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMueDtcbiAgICAgICAgfVxuICAgICAgICBnZXRZKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMueTtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGVxdWFscyhvdGhlcikge1xuICAgICAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgUmVzdWx0UG9pbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBvdGhlclBvaW50ID0gb3RoZXI7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMueCA9PT0gb3RoZXJQb2ludC54ICYmIHRoaXMueSA9PT0gb3RoZXJQb2ludC55O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgaGFzaENvZGUoKSB7XG4gICAgICAgICAgICByZXR1cm4gMzEgKiBGbG9hdC5mbG9hdFRvSW50Qml0cyh0aGlzLngpICsgRmxvYXQuZmxvYXRUb0ludEJpdHModGhpcy55KTtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgcmV0dXJuICcoJyArIHRoaXMueCArICcsJyArIHRoaXMueSArICcpJztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogT3JkZXJzIGFuIGFycmF5IG9mIHRocmVlIFJlc3VsdFBvaW50cyBpbiBhbiBvcmRlciBbQSxCLENdIHN1Y2ggdGhhdCBBQiBpcyBsZXNzIHRoYW4gQUNcbiAgICAgICAgICogYW5kIEJDIGlzIGxlc3MgdGhhbiBBQywgYW5kIHRoZSBhbmdsZSBiZXR3ZWVuIEJDIGFuZCBCQSBpcyBsZXNzIHRoYW4gMTgwIGRlZ3JlZXMuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBwYXR0ZXJucyBhcnJheSBvZiB0aHJlZSB7QGNvZGUgUmVzdWx0UG9pbnR9IHRvIG9yZGVyXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgb3JkZXJCZXN0UGF0dGVybnMocGF0dGVybnMpIHtcbiAgICAgICAgICAgIC8vIEZpbmQgZGlzdGFuY2VzIGJldHdlZW4gcGF0dGVybiBjZW50ZXJzXG4gICAgICAgICAgICBjb25zdCB6ZXJvT25lRGlzdGFuY2UgPSB0aGlzLmRpc3RhbmNlKHBhdHRlcm5zWzBdLCBwYXR0ZXJuc1sxXSk7XG4gICAgICAgICAgICBjb25zdCBvbmVUd29EaXN0YW5jZSA9IHRoaXMuZGlzdGFuY2UocGF0dGVybnNbMV0sIHBhdHRlcm5zWzJdKTtcbiAgICAgICAgICAgIGNvbnN0IHplcm9Ud29EaXN0YW5jZSA9IHRoaXMuZGlzdGFuY2UocGF0dGVybnNbMF0sIHBhdHRlcm5zWzJdKTtcbiAgICAgICAgICAgIGxldCBwb2ludEE7XG4gICAgICAgICAgICBsZXQgcG9pbnRCO1xuICAgICAgICAgICAgbGV0IHBvaW50QztcbiAgICAgICAgICAgIC8vIEFzc3VtZSBvbmUgY2xvc2VzdCB0byBvdGhlciB0d28gaXMgQjsgQSBhbmQgQyB3aWxsIGp1c3QgYmUgZ3Vlc3NlcyBhdCBmaXJzdFxuICAgICAgICAgICAgaWYgKG9uZVR3b0Rpc3RhbmNlID49IHplcm9PbmVEaXN0YW5jZSAmJiBvbmVUd29EaXN0YW5jZSA+PSB6ZXJvVHdvRGlzdGFuY2UpIHtcbiAgICAgICAgICAgICAgICBwb2ludEIgPSBwYXR0ZXJuc1swXTtcbiAgICAgICAgICAgICAgICBwb2ludEEgPSBwYXR0ZXJuc1sxXTtcbiAgICAgICAgICAgICAgICBwb2ludEMgPSBwYXR0ZXJuc1syXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHplcm9Ud29EaXN0YW5jZSA+PSBvbmVUd29EaXN0YW5jZSAmJiB6ZXJvVHdvRGlzdGFuY2UgPj0gemVyb09uZURpc3RhbmNlKSB7XG4gICAgICAgICAgICAgICAgcG9pbnRCID0gcGF0dGVybnNbMV07XG4gICAgICAgICAgICAgICAgcG9pbnRBID0gcGF0dGVybnNbMF07XG4gICAgICAgICAgICAgICAgcG9pbnRDID0gcGF0dGVybnNbMl07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBwb2ludEIgPSBwYXR0ZXJuc1syXTtcbiAgICAgICAgICAgICAgICBwb2ludEEgPSBwYXR0ZXJuc1swXTtcbiAgICAgICAgICAgICAgICBwb2ludEMgPSBwYXR0ZXJuc1sxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFVzZSBjcm9zcyBwcm9kdWN0IHRvIGZpZ3VyZSBvdXQgd2hldGhlciBBIGFuZCBDIGFyZSBjb3JyZWN0IG9yIGZsaXBwZWQuXG4gICAgICAgICAgICAvLyBUaGlzIGFza3Mgd2hldGhlciBCQyB4IEJBIGhhcyBhIHBvc2l0aXZlIHogY29tcG9uZW50LCB3aGljaCBpcyB0aGUgYXJyYW5nZW1lbnRcbiAgICAgICAgICAgIC8vIHdlIHdhbnQgZm9yIEEsIEIsIEMuIElmIGl0J3MgbmVnYXRpdmUsIHRoZW4gd2UndmUgZ290IGl0IGZsaXBwZWQgYXJvdW5kIGFuZFxuICAgICAgICAgICAgLy8gc2hvdWxkIHN3YXAgQSBhbmQgQy5cbiAgICAgICAgICAgIGlmICh0aGlzLmNyb3NzUHJvZHVjdFoocG9pbnRBLCBwb2ludEIsIHBvaW50QykgPCAwLjApIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0ZW1wID0gcG9pbnRBO1xuICAgICAgICAgICAgICAgIHBvaW50QSA9IHBvaW50QztcbiAgICAgICAgICAgICAgICBwb2ludEMgPSB0ZW1wO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGF0dGVybnNbMF0gPSBwb2ludEE7XG4gICAgICAgICAgICBwYXR0ZXJuc1sxXSA9IHBvaW50QjtcbiAgICAgICAgICAgIHBhdHRlcm5zWzJdID0gcG9pbnRDO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gcGF0dGVybjEgZmlyc3QgcGF0dGVyblxuICAgICAgICAgKiBAcGFyYW0gcGF0dGVybjIgc2Vjb25kIHBhdHRlcm5cbiAgICAgICAgICogQHJldHVybiBkaXN0YW5jZSBiZXR3ZWVuIHR3byBwb2ludHNcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBkaXN0YW5jZShwYXR0ZXJuMSwgcGF0dGVybjIpIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoVXRpbHMuZGlzdGFuY2UocGF0dGVybjEueCwgcGF0dGVybjEueSwgcGF0dGVybjIueCwgcGF0dGVybjIueSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldHVybnMgdGhlIHogY29tcG9uZW50IG9mIHRoZSBjcm9zcyBwcm9kdWN0IGJldHdlZW4gdmVjdG9ycyBCQyBhbmQgQkEuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgY3Jvc3NQcm9kdWN0Wihwb2ludEEsIHBvaW50QiwgcG9pbnRDKSB7XG4gICAgICAgICAgICBjb25zdCBiWCA9IHBvaW50Qi54O1xuICAgICAgICAgICAgY29uc3QgYlkgPSBwb2ludEIueTtcbiAgICAgICAgICAgIHJldHVybiAoKHBvaW50Qy54IC0gYlgpICogKHBvaW50QS55IC0gYlkpKSAtICgocG9pbnRDLnkgLSBiWSkgKiAocG9pbnRBLnggLSBiWCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiA8cD5FbmNhcHN1bGF0ZXMgdGhlIHJlc3VsdCBvZiBkZXRlY3RpbmcgYSBiYXJjb2RlIGluIGFuIGltYWdlLiBUaGlzIGluY2x1ZGVzIHRoZSByYXdcbiAgICAgKiBtYXRyaXggb2YgYmxhY2svd2hpdGUgcGl4ZWxzIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGJhcmNvZGUsIGFuZCBwb3NzaWJseSBwb2ludHMgb2YgaW50ZXJlc3RcbiAgICAgKiBpbiB0aGUgaW1hZ2UsIGxpa2UgdGhlIGxvY2F0aW9uIG9mIGZpbmRlciBwYXR0ZXJucyBvciBjb3JuZXJzIG9mIHRoZSBiYXJjb2RlIGluIHRoZSBpbWFnZS48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIERldGVjdG9yUmVzdWx0IHtcbiAgICAgICAgY29uc3RydWN0b3IoYml0cywgcG9pbnRzKSB7XG4gICAgICAgICAgICB0aGlzLmJpdHMgPSBiaXRzO1xuICAgICAgICAgICAgdGhpcy5wb2ludHMgPSBwb2ludHM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Qml0cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJpdHM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0UG9pbnRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucG9pbnRzO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAxMCBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiA8cD5FeHRlbmRzIHtAbGluayBEZXRlY3RvclJlc3VsdH0gd2l0aCBtb3JlIGluZm9ybWF0aW9uIHNwZWNpZmljIHRvIHRoZSBBenRlYyBmb3JtYXQsXG4gICAgICogbGlrZSB0aGUgbnVtYmVyIG9mIGxheWVycyBhbmQgd2hldGhlciBpdCdzIGNvbXBhY3QuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBBenRlY0RldGVjdG9yUmVzdWx0IGV4dGVuZHMgRGV0ZWN0b3JSZXN1bHQge1xuICAgICAgICBjb25zdHJ1Y3RvcihiaXRzLCBwb2ludHMsIGNvbXBhY3QsIG5iRGF0YWJsb2NrcywgbmJMYXllcnMpIHtcbiAgICAgICAgICAgIHN1cGVyKGJpdHMsIHBvaW50cyk7XG4gICAgICAgICAgICB0aGlzLmNvbXBhY3QgPSBjb21wYWN0O1xuICAgICAgICAgICAgdGhpcy5uYkRhdGFibG9ja3MgPSBuYkRhdGFibG9ja3M7XG4gICAgICAgICAgICB0aGlzLm5iTGF5ZXJzID0gbmJMYXllcnM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0TmJMYXllcnMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5uYkxheWVycztcbiAgICAgICAgfVxuICAgICAgICBnZXROYkRhdGFibG9ja3MoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5uYkRhdGFibG9ja3M7XG4gICAgICAgIH1cbiAgICAgICAgaXNDb21wYWN0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29tcGFjdDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMTAgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogPHA+XG4gICAgICogRGV0ZWN0cyBhIGNhbmRpZGF0ZSBiYXJjb2RlLWxpa2UgcmVjdGFuZ3VsYXIgcmVnaW9uIHdpdGhpbiBhbiBpbWFnZS4gSXRcbiAgICAgKiBzdGFydHMgYXJvdW5kIHRoZSBjZW50ZXIgb2YgdGhlIGltYWdlLCBpbmNyZWFzZXMgdGhlIHNpemUgb2YgdGhlIGNhbmRpZGF0ZVxuICAgICAqIHJlZ2lvbiB1bnRpbCBpdCBmaW5kcyBhIHdoaXRlIHJlY3Rhbmd1bGFyIHJlZ2lvbi4gQnkga2VlcGluZyB0cmFjayBvZiB0aGVcbiAgICAgKiBsYXN0IGJsYWNrIHBvaW50cyBpdCBlbmNvdW50ZXJlZCwgaXQgZGV0ZXJtaW5lcyB0aGUgY29ybmVycyBvZiB0aGUgYmFyY29kZS5cbiAgICAgKiA8L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIERhdmlkIE9saXZpZXJcbiAgICAgKi9cbiAgICBjbGFzcyBXaGl0ZVJlY3RhbmdsZURldGVjdG9yIHtcbiAgICAgICAgLy8gcHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgaW1hZ2U6IEJpdE1hdHJpeCkgLyp0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24qLyB7XG4gICAgICAgIC8vICAgdGhpcyhpbWFnZSwgSU5JVF9TSVpFLCBpbWFnZS5nZXRXaWR0aCgpIC8gMiwgaW1hZ2UuZ2V0SGVpZ2h0KCkgLyAyKVxuICAgICAgICAvLyB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gaW1hZ2UgYmFyY29kZSBpbWFnZSB0byBmaW5kIGEgcmVjdGFuZ2xlIGluXG4gICAgICAgICAqIEBwYXJhbSBpbml0U2l6ZSBpbml0aWFsIHNpemUgb2Ygc2VhcmNoIGFyZWEgYXJvdW5kIGNlbnRlclxuICAgICAgICAgKiBAcGFyYW0geCB4IHBvc2l0aW9uIG9mIHNlYXJjaCBjZW50ZXJcbiAgICAgICAgICogQHBhcmFtIHkgeSBwb3NpdGlvbiBvZiBzZWFyY2ggY2VudGVyXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gaWYgaW1hZ2UgaXMgdG9vIHNtYWxsIHRvIGFjY29tbW9kYXRlIHtAY29kZSBpbml0U2l6ZX1cbiAgICAgICAgICovXG4gICAgICAgIGNvbnN0cnVjdG9yKGltYWdlLCBpbml0U2l6ZSAvKmludCovLCB4IC8qaW50Ki8sIHkgLyppbnQqLykge1xuICAgICAgICAgICAgdGhpcy5pbWFnZSA9IGltYWdlO1xuICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSBpbWFnZS5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIHRoaXMud2lkdGggPSBpbWFnZS5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCA9PT0gaW5pdFNpemUgfHwgbnVsbCA9PT0gaW5pdFNpemUpIHtcbiAgICAgICAgICAgICAgICBpbml0U2l6ZSA9IFdoaXRlUmVjdGFuZ2xlRGV0ZWN0b3IuSU5JVF9TSVpFO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCA9PT0geCB8fCBudWxsID09PSB4KSB7XG4gICAgICAgICAgICAgICAgeCA9IGltYWdlLmdldFdpZHRoKCkgLyAyIHwgMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IHkgfHwgbnVsbCA9PT0geSkge1xuICAgICAgICAgICAgICAgIHkgPSBpbWFnZS5nZXRIZWlnaHQoKSAvIDIgfCAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgaGFsZnNpemUgPSBpbml0U2l6ZSAvIDIgfCAwO1xuICAgICAgICAgICAgdGhpcy5sZWZ0SW5pdCA9IHggLSBoYWxmc2l6ZTtcbiAgICAgICAgICAgIHRoaXMucmlnaHRJbml0ID0geCArIGhhbGZzaXplO1xuICAgICAgICAgICAgdGhpcy51cEluaXQgPSB5IC0gaGFsZnNpemU7XG4gICAgICAgICAgICB0aGlzLmRvd25Jbml0ID0geSArIGhhbGZzaXplO1xuICAgICAgICAgICAgaWYgKHRoaXMudXBJbml0IDwgMCB8fCB0aGlzLmxlZnRJbml0IDwgMCB8fCB0aGlzLmRvd25Jbml0ID49IHRoaXMuaGVpZ2h0IHx8IHRoaXMucmlnaHRJbml0ID49IHRoaXMud2lkdGgpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+XG4gICAgICAgICAqIERldGVjdHMgYSBjYW5kaWRhdGUgYmFyY29kZS1saWtlIHJlY3Rhbmd1bGFyIHJlZ2lvbiB3aXRoaW4gYW4gaW1hZ2UuIEl0XG4gICAgICAgICAqIHN0YXJ0cyBhcm91bmQgdGhlIGNlbnRlciBvZiB0aGUgaW1hZ2UsIGluY3JlYXNlcyB0aGUgc2l6ZSBvZiB0aGUgY2FuZGlkYXRlXG4gICAgICAgICAqIHJlZ2lvbiB1bnRpbCBpdCBmaW5kcyBhIHdoaXRlIHJlY3Rhbmd1bGFyIHJlZ2lvbi5cbiAgICAgICAgICogPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIHtAbGluayBSZXN1bHRQb2ludH1bXSBkZXNjcmliaW5nIHRoZSBjb3JuZXJzIG9mIHRoZSByZWN0YW5ndWxhclxuICAgICAgICAgKiAgICAgICAgIHJlZ2lvbi4gVGhlIGZpcnN0IGFuZCBsYXN0IHBvaW50cyBhcmUgb3Bwb3NlZCBvbiB0aGUgZGlhZ29uYWwsIGFzXG4gICAgICAgICAqICAgICAgICAgYXJlIHRoZSBzZWNvbmQgYW5kIHRoaXJkLiBUaGUgZmlyc3QgcG9pbnQgd2lsbCBiZSB0aGUgdG9wbW9zdFxuICAgICAgICAgKiAgICAgICAgIHBvaW50IGFuZCB0aGUgbGFzdCwgdGhlIGJvdHRvbW1vc3QuIFRoZSBzZWNvbmQgcG9pbnQgd2lsbCBiZVxuICAgICAgICAgKiAgICAgICAgIGxlZnRtb3N0IGFuZCB0aGUgdGhpcmQsIHRoZSByaWdodG1vc3RcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBpZiBubyBEYXRhIE1hdHJpeCBDb2RlIGNhbiBiZSBmb3VuZFxuICAgICAgICAgKi9cbiAgICAgICAgZGV0ZWN0KCkge1xuICAgICAgICAgICAgbGV0IGxlZnQgPSB0aGlzLmxlZnRJbml0O1xuICAgICAgICAgICAgbGV0IHJpZ2h0ID0gdGhpcy5yaWdodEluaXQ7XG4gICAgICAgICAgICBsZXQgdXAgPSB0aGlzLnVwSW5pdDtcbiAgICAgICAgICAgIGxldCBkb3duID0gdGhpcy5kb3duSW5pdDtcbiAgICAgICAgICAgIGxldCBzaXplRXhjZWVkZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGxldCBhQmxhY2tQb2ludEZvdW5kT25Cb3JkZXIgPSB0cnVlO1xuICAgICAgICAgICAgbGV0IGF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPbkJvcmRlciA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPblJpZ2h0ID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgYXRMZWFzdE9uZUJsYWNrUG9pbnRGb3VuZE9uQm90dG9tID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgYXRMZWFzdE9uZUJsYWNrUG9pbnRGb3VuZE9uTGVmdCA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPblRvcCA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSB0aGlzLndpZHRoO1xuICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7XG4gICAgICAgICAgICB3aGlsZSAoYUJsYWNrUG9pbnRGb3VuZE9uQm9yZGVyKSB7XG4gICAgICAgICAgICAgICAgYUJsYWNrUG9pbnRGb3VuZE9uQm9yZGVyID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgLy8gLi4uLi5cbiAgICAgICAgICAgICAgICAvLyAuICAgfFxuICAgICAgICAgICAgICAgIC8vIC4uLi4uXG4gICAgICAgICAgICAgICAgbGV0IHJpZ2h0Qm9yZGVyTm90V2hpdGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHdoaWxlICgocmlnaHRCb3JkZXJOb3RXaGl0ZSB8fCAhYXRMZWFzdE9uZUJsYWNrUG9pbnRGb3VuZE9uUmlnaHQpICYmIHJpZ2h0IDwgd2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmlnaHRCb3JkZXJOb3RXaGl0ZSA9IHRoaXMuY29udGFpbnNCbGFja1BvaW50KHVwLCBkb3duLCByaWdodCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHRCb3JkZXJOb3RXaGl0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGFCbGFja1BvaW50Rm91bmRPbkJvcmRlciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBhdExlYXN0T25lQmxhY2tQb2ludEZvdW5kT25SaWdodCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoIWF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPblJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByaWdodCsrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChyaWdodCA+PSB3aWR0aCkge1xuICAgICAgICAgICAgICAgICAgICBzaXplRXhjZWVkZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gLi4uLi5cbiAgICAgICAgICAgICAgICAvLyAuICAgLlxuICAgICAgICAgICAgICAgIC8vIC5fX18uXG4gICAgICAgICAgICAgICAgbGV0IGJvdHRvbUJvcmRlck5vdFdoaXRlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB3aGlsZSAoKGJvdHRvbUJvcmRlck5vdFdoaXRlIHx8ICFhdExlYXN0T25lQmxhY2tQb2ludEZvdW5kT25Cb3R0b20pICYmIGRvd24gPCBoZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgYm90dG9tQm9yZGVyTm90V2hpdGUgPSB0aGlzLmNvbnRhaW5zQmxhY2tQb2ludChsZWZ0LCByaWdodCwgZG93biwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChib3R0b21Cb3JkZXJOb3RXaGl0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG93bisrO1xuICAgICAgICAgICAgICAgICAgICAgICAgYUJsYWNrUG9pbnRGb3VuZE9uQm9yZGVyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPbkJvdHRvbSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoIWF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPbkJvdHRvbSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG93bisrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChkb3duID49IGhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICBzaXplRXhjZWVkZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gLi4uLi5cbiAgICAgICAgICAgICAgICAvLyB8ICAgLlxuICAgICAgICAgICAgICAgIC8vIC4uLi4uXG4gICAgICAgICAgICAgICAgbGV0IGxlZnRCb3JkZXJOb3RXaGl0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgd2hpbGUgKChsZWZ0Qm9yZGVyTm90V2hpdGUgfHwgIWF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPbkxlZnQpICYmIGxlZnQgPj0gMCkge1xuICAgICAgICAgICAgICAgICAgICBsZWZ0Qm9yZGVyTm90V2hpdGUgPSB0aGlzLmNvbnRhaW5zQmxhY2tQb2ludCh1cCwgZG93biwgbGVmdCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobGVmdEJvcmRlck5vdFdoaXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0LS07XG4gICAgICAgICAgICAgICAgICAgICAgICBhQmxhY2tQb2ludEZvdW5kT25Cb3JkZXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXRMZWFzdE9uZUJsYWNrUG9pbnRGb3VuZE9uTGVmdCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoIWF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPbkxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQtLTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobGVmdCA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgc2l6ZUV4Y2VlZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIC5fX18uXG4gICAgICAgICAgICAgICAgLy8gLiAgIC5cbiAgICAgICAgICAgICAgICAvLyAuLi4uLlxuICAgICAgICAgICAgICAgIGxldCB0b3BCb3JkZXJOb3RXaGl0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgd2hpbGUgKCh0b3BCb3JkZXJOb3RXaGl0ZSB8fCAhYXRMZWFzdE9uZUJsYWNrUG9pbnRGb3VuZE9uVG9wKSAmJiB1cCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRvcEJvcmRlck5vdFdoaXRlID0gdGhpcy5jb250YWluc0JsYWNrUG9pbnQobGVmdCwgcmlnaHQsIHVwLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRvcEJvcmRlck5vdFdoaXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1cC0tO1xuICAgICAgICAgICAgICAgICAgICAgICAgYUJsYWNrUG9pbnRGb3VuZE9uQm9yZGVyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPblRvcCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoIWF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPblRvcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdXAtLTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodXAgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpemVFeGNlZWRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYUJsYWNrUG9pbnRGb3VuZE9uQm9yZGVyKSB7XG4gICAgICAgICAgICAgICAgICAgIGF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPbkJvcmRlciA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFzaXplRXhjZWVkZWQgJiYgYXRMZWFzdE9uZUJsYWNrUG9pbnRGb3VuZE9uQm9yZGVyKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbWF4U2l6ZSA9IHJpZ2h0IC0gbGVmdDtcbiAgICAgICAgICAgICAgICBsZXQgeiA9IG51bGw7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDE7IHogPT09IG51bGwgJiYgaSA8IG1heFNpemU7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB6ID0gdGhpcy5nZXRCbGFja1BvaW50T25TZWdtZW50KGxlZnQsIGRvd24gLSBpLCBsZWZ0ICsgaSwgZG93bik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh6ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCB0ID0gbnVsbDtcbiAgICAgICAgICAgICAgICAvLyBnbyBkb3duIHJpZ2h0XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDE7IHQgPT09IG51bGwgJiYgaSA8IG1heFNpemU7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB0ID0gdGhpcy5nZXRCbGFja1BvaW50T25TZWdtZW50KGxlZnQsIHVwICsgaSwgbGVmdCArIGksIHVwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IHggPSBudWxsO1xuICAgICAgICAgICAgICAgIC8vIGdvIGRvd24gbGVmdFxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAxOyB4ID09PSBudWxsICYmIGkgPCBtYXhTaXplOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgeCA9IHRoaXMuZ2V0QmxhY2tQb2ludE9uU2VnbWVudChyaWdodCwgdXAgKyBpLCByaWdodCAtIGksIHVwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHggPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IHkgPSBudWxsO1xuICAgICAgICAgICAgICAgIC8vIGdvIHVwIGxlZnRcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMTsgeSA9PT0gbnVsbCAmJiBpIDwgbWF4U2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHkgPSB0aGlzLmdldEJsYWNrUG9pbnRPblNlZ21lbnQocmlnaHQsIGRvd24gLSBpLCByaWdodCAtIGksIGRvd24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoeSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jZW50ZXJFZGdlcyh5LCB6LCB4LCB0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGdldEJsYWNrUG9pbnRPblNlZ21lbnQoYVggLypmbG9hdCovLCBhWSAvKmZsb2F0Ki8sIGJYIC8qZmxvYXQqLywgYlkgLypmbG9hdCovKSB7XG4gICAgICAgICAgICBjb25zdCBkaXN0ID0gTWF0aFV0aWxzLnJvdW5kKE1hdGhVdGlscy5kaXN0YW5jZShhWCwgYVksIGJYLCBiWSkpO1xuICAgICAgICAgICAgY29uc3QgeFN0ZXAgPSAoYlggLSBhWCkgLyBkaXN0O1xuICAgICAgICAgICAgY29uc3QgeVN0ZXAgPSAoYlkgLSBhWSkgLyBkaXN0O1xuICAgICAgICAgICAgY29uc3QgaW1hZ2UgPSB0aGlzLmltYWdlO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkaXN0OyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCB4ID0gTWF0aFV0aWxzLnJvdW5kKGFYICsgaSAqIHhTdGVwKTtcbiAgICAgICAgICAgICAgICBjb25zdCB5ID0gTWF0aFV0aWxzLnJvdW5kKGFZICsgaSAqIHlTdGVwKTtcbiAgICAgICAgICAgICAgICBpZiAoaW1hZ2UuZ2V0KHgsIHkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUmVzdWx0UG9pbnQoeCwgeSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIHJlY2VudGVycyB0aGUgcG9pbnRzIG9mIGEgY29uc3RhbnQgZGlzdGFuY2UgdG93YXJkcyB0aGUgY2VudGVyXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB5IGJvdHRvbSBtb3N0IHBvaW50XG4gICAgICAgICAqIEBwYXJhbSB6IGxlZnQgbW9zdCBwb2ludFxuICAgICAgICAgKiBAcGFyYW0geCByaWdodCBtb3N0IHBvaW50XG4gICAgICAgICAqIEBwYXJhbSB0IHRvcCBtb3N0IHBvaW50XG4gICAgICAgICAqIEByZXR1cm4ge0BsaW5rIFJlc3VsdFBvaW50fVtdIGRlc2NyaWJpbmcgdGhlIGNvcm5lcnMgb2YgdGhlIHJlY3Rhbmd1bGFyXG4gICAgICAgICAqICAgICAgICAgcmVnaW9uLiBUaGUgZmlyc3QgYW5kIGxhc3QgcG9pbnRzIGFyZSBvcHBvc2VkIG9uIHRoZSBkaWFnb25hbCwgYXNcbiAgICAgICAgICogICAgICAgICBhcmUgdGhlIHNlY29uZCBhbmQgdGhpcmQuIFRoZSBmaXJzdCBwb2ludCB3aWxsIGJlIHRoZSB0b3Btb3N0XG4gICAgICAgICAqICAgICAgICAgcG9pbnQgYW5kIHRoZSBsYXN0LCB0aGUgYm90dG9tbW9zdC4gVGhlIHNlY29uZCBwb2ludCB3aWxsIGJlXG4gICAgICAgICAqICAgICAgICAgbGVmdG1vc3QgYW5kIHRoZSB0aGlyZCwgdGhlIHJpZ2h0bW9zdFxuICAgICAgICAgKi9cbiAgICAgICAgY2VudGVyRWRnZXMoeSwgeiwgeCwgdCkge1xuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vICAgICAgIHQgICAgICAgICAgICB0XG4gICAgICAgICAgICAvLyAgeiAgICAgICAgICAgICAgICAgICAgICB4XG4gICAgICAgICAgICAvLyAgICAgICAgeCAgICBPUiAgICB6XG4gICAgICAgICAgICAvLyAgIHkgICAgICAgICAgICAgICAgICAgIHlcbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICBjb25zdCB5aSA9IHkuZ2V0WCgpO1xuICAgICAgICAgICAgY29uc3QgeWogPSB5LmdldFkoKTtcbiAgICAgICAgICAgIGNvbnN0IHppID0gei5nZXRYKCk7XG4gICAgICAgICAgICBjb25zdCB6aiA9IHouZ2V0WSgpO1xuICAgICAgICAgICAgY29uc3QgeGkgPSB4LmdldFgoKTtcbiAgICAgICAgICAgIGNvbnN0IHhqID0geC5nZXRZKCk7XG4gICAgICAgICAgICBjb25zdCB0aSA9IHQuZ2V0WCgpO1xuICAgICAgICAgICAgY29uc3QgdGogPSB0LmdldFkoKTtcbiAgICAgICAgICAgIGNvbnN0IENPUlIgPSBXaGl0ZVJlY3RhbmdsZURldGVjdG9yLkNPUlI7XG4gICAgICAgICAgICBpZiAoeWkgPCB0aGlzLndpZHRoIC8gMi4wKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICAgICAgbmV3IFJlc3VsdFBvaW50KHRpIC0gQ09SUiwgdGogKyBDT1JSKSxcbiAgICAgICAgICAgICAgICAgICAgbmV3IFJlc3VsdFBvaW50KHppICsgQ09SUiwgemogKyBDT1JSKSxcbiAgICAgICAgICAgICAgICAgICAgbmV3IFJlc3VsdFBvaW50KHhpIC0gQ09SUiwgeGogLSBDT1JSKSxcbiAgICAgICAgICAgICAgICAgICAgbmV3IFJlc3VsdFBvaW50KHlpICsgQ09SUiwgeWogLSBDT1JSKVxuICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgICAgICBuZXcgUmVzdWx0UG9pbnQodGkgKyBDT1JSLCB0aiArIENPUlIpLFxuICAgICAgICAgICAgICAgICAgICBuZXcgUmVzdWx0UG9pbnQoemkgKyBDT1JSLCB6aiAtIENPUlIpLFxuICAgICAgICAgICAgICAgICAgICBuZXcgUmVzdWx0UG9pbnQoeGkgLSBDT1JSLCB4aiArIENPUlIpLFxuICAgICAgICAgICAgICAgICAgICBuZXcgUmVzdWx0UG9pbnQoeWkgLSBDT1JSLCB5aiAtIENPUlIpXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGV0ZXJtaW5lcyB3aGV0aGVyIGEgc2VnbWVudCBjb250YWlucyBhIGJsYWNrIHBvaW50XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBhICAgICAgICAgIG1pbiB2YWx1ZSBvZiB0aGUgc2Nhbm5lZCBjb29yZGluYXRlXG4gICAgICAgICAqIEBwYXJhbSBiICAgICAgICAgIG1heCB2YWx1ZSBvZiB0aGUgc2Nhbm5lZCBjb29yZGluYXRlXG4gICAgICAgICAqIEBwYXJhbSBmaXhlZCAgICAgIHZhbHVlIG9mIGZpeGVkIGNvb3JkaW5hdGVcbiAgICAgICAgICogQHBhcmFtIGhvcml6b250YWwgc2V0IHRvIHRydWUgaWYgc2NhbiBtdXN0IGJlIGhvcml6b250YWwsIGZhbHNlIGlmIHZlcnRpY2FsXG4gICAgICAgICAqIEByZXR1cm4gdHJ1ZSBpZiBhIGJsYWNrIHBvaW50IGhhcyBiZWVuIGZvdW5kLCBlbHNlIGZhbHNlLlxuICAgICAgICAgKi9cbiAgICAgICAgY29udGFpbnNCbGFja1BvaW50KGEgLyppbnQqLywgYiAvKmludCovLCBmaXhlZCAvKmludCovLCBob3Jpem9udGFsKSB7XG4gICAgICAgICAgICBjb25zdCBpbWFnZSA9IHRoaXMuaW1hZ2U7XG4gICAgICAgICAgICBpZiAoaG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSBhOyB4IDw9IGI7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW1hZ2UuZ2V0KHgsIGZpeGVkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB5ID0gYTsgeSA8PSBiOyB5KyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGltYWdlLmdldChmaXhlZCwgeSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIFdoaXRlUmVjdGFuZ2xlRGV0ZWN0b3IuSU5JVF9TSVpFID0gMTA7XG4gICAgV2hpdGVSZWN0YW5nbGVEZXRlY3Rvci5DT1JSID0gMTtcblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogSW1wbGVtZW50YXRpb25zIG9mIHRoaXMgY2xhc3MgY2FuLCBnaXZlbiBsb2NhdGlvbnMgb2YgZmluZGVyIHBhdHRlcm5zIGZvciBhIFFSIGNvZGUgaW4gYW5cbiAgICAgKiBpbWFnZSwgc2FtcGxlIHRoZSByaWdodCBwb2ludHMgaW4gdGhlIGltYWdlIHRvIHJlY29uc3RydWN0IHRoZSBRUiBjb2RlLCBhY2NvdW50aW5nIGZvclxuICAgICAqIHBlcnNwZWN0aXZlIGRpc3RvcnRpb24uIEl0IGlzIGFic3RyYWN0ZWQgc2luY2UgaXQgaXMgcmVsYXRpdmVseSBleHBlbnNpdmUgYW5kIHNob3VsZCBiZSBhbGxvd2VkXG4gICAgICogdG8gdGFrZSBhZHZhbnRhZ2Ugb2YgcGxhdGZvcm0tc3BlY2lmaWMgb3B0aW1pemVkIGltcGxlbWVudGF0aW9ucywgbGlrZSBTdW4ncyBKYXZhIEFkdmFuY2VkXG4gICAgICogSW1hZ2luZyBsaWJyYXJ5LCBidXQgd2hpY2ggbWF5IG5vdCBiZSBhdmFpbGFibGUgaW4gb3RoZXIgZW52aXJvbm1lbnRzIHN1Y2ggYXMgSjJNRSwgYW5kIHZpY2VcbiAgICAgKiB2ZXJzYS5cbiAgICAgKlxuICAgICAqIFRoZSBpbXBsZW1lbnRhdGlvbiB1c2VkIGNhbiBiZSBjb250cm9sbGVkIGJ5IGNhbGxpbmcge0BsaW5rICNzZXRHcmlkU2FtcGxlcihHcmlkU2FtcGxlcil9XG4gICAgICogd2l0aCBhbiBpbnN0YW5jZSBvZiBhIGNsYXNzIHdoaWNoIGltcGxlbWVudHMgdGhpcyBpbnRlcmZhY2UuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIEdyaWRTYW1wbGVyIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkNoZWNrcyBhIHNldCBvZiBwb2ludHMgdGhhdCBoYXZlIGJlZW4gdHJhbnNmb3JtZWQgdG8gc2FtcGxlIHBvaW50cyBvbiBhbiBpbWFnZSBhZ2FpbnN0XG4gICAgICAgICAqIHRoZSBpbWFnZSdzIGRpbWVuc2lvbnMgdG8gc2VlIGlmIHRoZSBwb2ludCBhcmUgZXZlbiB3aXRoaW4gdGhlIGltYWdlLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogPHA+VGhpcyBtZXRob2Qgd2lsbCBhY3R1YWxseSBcIm51ZGdlXCIgdGhlIGVuZHBvaW50cyBiYWNrIG9udG8gdGhlIGltYWdlIGlmIHRoZXkgYXJlIGZvdW5kIHRvIGJlXG4gICAgICAgICAqIGJhcmVseSAobGVzcyB0aGFuIDEgcGl4ZWwpIG9mZiB0aGUgaW1hZ2UuIFRoaXMgYWNjb3VudHMgZm9yIGltcGVyZmVjdCBkZXRlY3Rpb24gb2YgZmluZGVyXG4gICAgICAgICAqIHBhdHRlcm5zIGluIGFuIGltYWdlIHdoZXJlIHRoZSBRUiBDb2RlIHJ1bnMgYWxsIHRoZSB3YXkgdG8gdGhlIGltYWdlIGJvcmRlci48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIDxwPkZvciBlZmZpY2llbmN5LCB0aGUgbWV0aG9kIHdpbGwgY2hlY2sgcG9pbnRzIGZyb20gZWl0aGVyIGVuZCBvZiB0aGUgbGluZSB1bnRpbCBvbmUgaXMgZm91bmRcbiAgICAgICAgICogdG8gYmUgd2l0aGluIHRoZSBpbWFnZS4gQmVjYXVzZSB0aGUgc2V0IG9mIHBvaW50cyBhcmUgYXNzdW1lZCB0byBiZSBsaW5lYXIsIHRoaXMgaXMgdmFsaWQuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gaW1hZ2UgaW1hZ2UgaW50byB3aGljaCB0aGUgcG9pbnRzIHNob3VsZCBtYXBcbiAgICAgICAgICogQHBhcmFtIHBvaW50cyBhY3R1YWwgcG9pbnRzIGluIHgxLHkxLC4uLix4bix5biBmb3JtXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gaWYgYW4gZW5kcG9pbnQgaXMgbGllcyBvdXRzaWRlIHRoZSBpbWFnZSBib3VuZGFyaWVzXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgY2hlY2tBbmROdWRnZVBvaW50cyhpbWFnZSwgcG9pbnRzKSB7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IGltYWdlLmdldFdpZHRoKCk7XG4gICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBpbWFnZS5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIC8vIENoZWNrIGFuZCBudWRnZSBwb2ludHMgZnJvbSBzdGFydCB1bnRpbCB3ZSBzZWUgc29tZSB0aGF0IGFyZSBPSzpcbiAgICAgICAgICAgIGxldCBudWRnZWQgPSB0cnVlO1xuICAgICAgICAgICAgZm9yIChsZXQgb2Zmc2V0ID0gMDsgb2Zmc2V0IDwgcG9pbnRzLmxlbmd0aCAmJiBudWRnZWQ7IG9mZnNldCArPSAyKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgeCA9IE1hdGguZmxvb3IocG9pbnRzW29mZnNldF0pO1xuICAgICAgICAgICAgICAgIGNvbnN0IHkgPSBNYXRoLmZsb29yKHBvaW50c1tvZmZzZXQgKyAxXSk7XG4gICAgICAgICAgICAgICAgaWYgKHggPCAtMSB8fCB4ID4gd2lkdGggfHwgeSA8IC0xIHx8IHkgPiBoZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG51ZGdlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGlmICh4ID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBwb2ludHNbb2Zmc2V0XSA9IDAuMDtcbiAgICAgICAgICAgICAgICAgICAgbnVkZ2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoeCA9PT0gd2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcG9pbnRzW29mZnNldF0gPSB3aWR0aCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIG51ZGdlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh5ID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBwb2ludHNbb2Zmc2V0ICsgMV0gPSAwLjA7XG4gICAgICAgICAgICAgICAgICAgIG51ZGdlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHkgPT09IGhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICBwb2ludHNbb2Zmc2V0ICsgMV0gPSBoZWlnaHQgLSAxO1xuICAgICAgICAgICAgICAgICAgICBudWRnZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIENoZWNrIGFuZCBudWRnZSBwb2ludHMgZnJvbSBlbmQ6XG4gICAgICAgICAgICBudWRnZWQgPSB0cnVlO1xuICAgICAgICAgICAgZm9yIChsZXQgb2Zmc2V0ID0gcG9pbnRzLmxlbmd0aCAtIDI7IG9mZnNldCA+PSAwICYmIG51ZGdlZDsgb2Zmc2V0IC09IDIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB4ID0gTWF0aC5mbG9vcihwb2ludHNbb2Zmc2V0XSk7XG4gICAgICAgICAgICAgICAgY29uc3QgeSA9IE1hdGguZmxvb3IocG9pbnRzW29mZnNldCArIDFdKTtcbiAgICAgICAgICAgICAgICBpZiAoeCA8IC0xIHx8IHggPiB3aWR0aCB8fCB5IDwgLTEgfHwgeSA+IGhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbnVkZ2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgaWYgKHggPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvaW50c1tvZmZzZXRdID0gMC4wO1xuICAgICAgICAgICAgICAgICAgICBudWRnZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh4ID09PSB3aWR0aCkge1xuICAgICAgICAgICAgICAgICAgICBwb2ludHNbb2Zmc2V0XSA9IHdpZHRoIC0gMTtcbiAgICAgICAgICAgICAgICAgICAgbnVkZ2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvaW50c1tvZmZzZXQgKyAxXSA9IDAuMDtcbiAgICAgICAgICAgICAgICAgICAgbnVkZ2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoeSA9PT0gaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIHBvaW50c1tvZmZzZXQgKyAxXSA9IGhlaWdodCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIG51ZGdlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKm5hbWVzcGFjZSBjb20uZ29vZ2xlLnp4aW5nLmNvbW1vbiB7Ki9cbiAgICAvKipcbiAgICAgKiA8cD5UaGlzIGNsYXNzIGltcGxlbWVudHMgYSBwZXJzcGVjdGl2ZSB0cmFuc2Zvcm0gaW4gdHdvIGRpbWVuc2lvbnMuIEdpdmVuIGZvdXIgc291cmNlIGFuZCBmb3VyXG4gICAgICogZGVzdGluYXRpb24gcG9pbnRzLCBpdCB3aWxsIGNvbXB1dGUgdGhlIHRyYW5zZm9ybWF0aW9uIGltcGxpZWQgYmV0d2VlbiB0aGVtLiBUaGUgY29kZSBpcyBiYXNlZFxuICAgICAqIGRpcmVjdGx5IHVwb24gc2VjdGlvbiAzLjQuMiBvZiBHZW9yZ2UgV29sYmVyZydzIFwiRGlnaXRhbCBJbWFnZSBXYXJwaW5nXCI7IHNlZSBwYWdlcyA1NC01Ni48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIFBlcnNwZWN0aXZlVHJhbnNmb3JtIHtcbiAgICAgICAgY29uc3RydWN0b3IoYTExIC8qZmxvYXQqLywgYTIxIC8qZmxvYXQqLywgYTMxIC8qZmxvYXQqLywgYTEyIC8qZmxvYXQqLywgYTIyIC8qZmxvYXQqLywgYTMyIC8qZmxvYXQqLywgYTEzIC8qZmxvYXQqLywgYTIzIC8qZmxvYXQqLywgYTMzIC8qZmxvYXQqLykge1xuICAgICAgICAgICAgdGhpcy5hMTEgPSBhMTE7XG4gICAgICAgICAgICB0aGlzLmEyMSA9IGEyMTtcbiAgICAgICAgICAgIHRoaXMuYTMxID0gYTMxO1xuICAgICAgICAgICAgdGhpcy5hMTIgPSBhMTI7XG4gICAgICAgICAgICB0aGlzLmEyMiA9IGEyMjtcbiAgICAgICAgICAgIHRoaXMuYTMyID0gYTMyO1xuICAgICAgICAgICAgdGhpcy5hMTMgPSBhMTM7XG4gICAgICAgICAgICB0aGlzLmEyMyA9IGEyMztcbiAgICAgICAgICAgIHRoaXMuYTMzID0gYTMzO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBxdWFkcmlsYXRlcmFsVG9RdWFkcmlsYXRlcmFsKHgwIC8qZmxvYXQqLywgeTAgLypmbG9hdCovLCB4MSAvKmZsb2F0Ki8sIHkxIC8qZmxvYXQqLywgeDIgLypmbG9hdCovLCB5MiAvKmZsb2F0Ki8sIHgzIC8qZmxvYXQqLywgeTMgLypmbG9hdCovLCB4MHAgLypmbG9hdCovLCB5MHAgLypmbG9hdCovLCB4MXAgLypmbG9hdCovLCB5MXAgLypmbG9hdCovLCB4MnAgLypmbG9hdCovLCB5MnAgLypmbG9hdCovLCB4M3AgLypmbG9hdCovLCB5M3AgLypmbG9hdCovKSB7XG4gICAgICAgICAgICBjb25zdCBxVG9TID0gUGVyc3BlY3RpdmVUcmFuc2Zvcm0ucXVhZHJpbGF0ZXJhbFRvU3F1YXJlKHgwLCB5MCwgeDEsIHkxLCB4MiwgeTIsIHgzLCB5Myk7XG4gICAgICAgICAgICBjb25zdCBzVG9RID0gUGVyc3BlY3RpdmVUcmFuc2Zvcm0uc3F1YXJlVG9RdWFkcmlsYXRlcmFsKHgwcCwgeTBwLCB4MXAsIHkxcCwgeDJwLCB5MnAsIHgzcCwgeTNwKTtcbiAgICAgICAgICAgIHJldHVybiBzVG9RLnRpbWVzKHFUb1MpO1xuICAgICAgICB9XG4gICAgICAgIHRyYW5zZm9ybVBvaW50cyhwb2ludHMpIHtcbiAgICAgICAgICAgIGNvbnN0IG1heCA9IHBvaW50cy5sZW5ndGg7XG4gICAgICAgICAgICBjb25zdCBhMTEgPSB0aGlzLmExMTtcbiAgICAgICAgICAgIGNvbnN0IGExMiA9IHRoaXMuYTEyO1xuICAgICAgICAgICAgY29uc3QgYTEzID0gdGhpcy5hMTM7XG4gICAgICAgICAgICBjb25zdCBhMjEgPSB0aGlzLmEyMTtcbiAgICAgICAgICAgIGNvbnN0IGEyMiA9IHRoaXMuYTIyO1xuICAgICAgICAgICAgY29uc3QgYTIzID0gdGhpcy5hMjM7XG4gICAgICAgICAgICBjb25zdCBhMzEgPSB0aGlzLmEzMTtcbiAgICAgICAgICAgIGNvbnN0IGEzMiA9IHRoaXMuYTMyO1xuICAgICAgICAgICAgY29uc3QgYTMzID0gdGhpcy5hMzM7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1heDsgaSArPSAyKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgeCA9IHBvaW50c1tpXTtcbiAgICAgICAgICAgICAgICBjb25zdCB5ID0gcG9pbnRzW2kgKyAxXTtcbiAgICAgICAgICAgICAgICBjb25zdCBkZW5vbWluYXRvciA9IGExMyAqIHggKyBhMjMgKiB5ICsgYTMzO1xuICAgICAgICAgICAgICAgIHBvaW50c1tpXSA9IChhMTEgKiB4ICsgYTIxICogeSArIGEzMSkgLyBkZW5vbWluYXRvcjtcbiAgICAgICAgICAgICAgICBwb2ludHNbaSArIDFdID0gKGExMiAqIHggKyBhMjIgKiB5ICsgYTMyKSAvIGRlbm9taW5hdG9yO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRyYW5zZm9ybVBvaW50c1dpdGhWYWx1ZXMoeFZhbHVlcywgeVZhbHVlcykge1xuICAgICAgICAgICAgY29uc3QgYTExID0gdGhpcy5hMTE7XG4gICAgICAgICAgICBjb25zdCBhMTIgPSB0aGlzLmExMjtcbiAgICAgICAgICAgIGNvbnN0IGExMyA9IHRoaXMuYTEzO1xuICAgICAgICAgICAgY29uc3QgYTIxID0gdGhpcy5hMjE7XG4gICAgICAgICAgICBjb25zdCBhMjIgPSB0aGlzLmEyMjtcbiAgICAgICAgICAgIGNvbnN0IGEyMyA9IHRoaXMuYTIzO1xuICAgICAgICAgICAgY29uc3QgYTMxID0gdGhpcy5hMzE7XG4gICAgICAgICAgICBjb25zdCBhMzIgPSB0aGlzLmEzMjtcbiAgICAgICAgICAgIGNvbnN0IGEzMyA9IHRoaXMuYTMzO1xuICAgICAgICAgICAgY29uc3QgbiA9IHhWYWx1ZXMubGVuZ3RoO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCB4ID0geFZhbHVlc1tpXTtcbiAgICAgICAgICAgICAgICBjb25zdCB5ID0geVZhbHVlc1tpXTtcbiAgICAgICAgICAgICAgICBjb25zdCBkZW5vbWluYXRvciA9IGExMyAqIHggKyBhMjMgKiB5ICsgYTMzO1xuICAgICAgICAgICAgICAgIHhWYWx1ZXNbaV0gPSAoYTExICogeCArIGEyMSAqIHkgKyBhMzEpIC8gZGVub21pbmF0b3I7XG4gICAgICAgICAgICAgICAgeVZhbHVlc1tpXSA9IChhMTIgKiB4ICsgYTIyICogeSArIGEzMikgLyBkZW5vbWluYXRvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgc3F1YXJlVG9RdWFkcmlsYXRlcmFsKHgwIC8qZmxvYXQqLywgeTAgLypmbG9hdCovLCB4MSAvKmZsb2F0Ki8sIHkxIC8qZmxvYXQqLywgeDIgLypmbG9hdCovLCB5MiAvKmZsb2F0Ki8sIHgzIC8qZmxvYXQqLywgeTMgLypmbG9hdCovKSB7XG4gICAgICAgICAgICBjb25zdCBkeDMgPSB4MCAtIHgxICsgeDIgLSB4MztcbiAgICAgICAgICAgIGNvbnN0IGR5MyA9IHkwIC0geTEgKyB5MiAtIHkzO1xuICAgICAgICAgICAgaWYgKGR4MyA9PT0gMC4wICYmIGR5MyA9PT0gMC4wKSB7XG4gICAgICAgICAgICAgICAgLy8gQWZmaW5lXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBQZXJzcGVjdGl2ZVRyYW5zZm9ybSh4MSAtIHgwLCB4MiAtIHgxLCB4MCwgeTEgLSB5MCwgeTIgLSB5MSwgeTAsIDAuMCwgMC4wLCAxLjApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZHgxID0geDEgLSB4MjtcbiAgICAgICAgICAgICAgICBjb25zdCBkeDIgPSB4MyAtIHgyO1xuICAgICAgICAgICAgICAgIGNvbnN0IGR5MSA9IHkxIC0geTI7XG4gICAgICAgICAgICAgICAgY29uc3QgZHkyID0geTMgLSB5MjtcbiAgICAgICAgICAgICAgICBjb25zdCBkZW5vbWluYXRvciA9IGR4MSAqIGR5MiAtIGR4MiAqIGR5MTtcbiAgICAgICAgICAgICAgICBjb25zdCBhMTMgPSAoZHgzICogZHkyIC0gZHgyICogZHkzKSAvIGRlbm9taW5hdG9yO1xuICAgICAgICAgICAgICAgIGNvbnN0IGEyMyA9IChkeDEgKiBkeTMgLSBkeDMgKiBkeTEpIC8gZGVub21pbmF0b3I7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBQZXJzcGVjdGl2ZVRyYW5zZm9ybSh4MSAtIHgwICsgYTEzICogeDEsIHgzIC0geDAgKyBhMjMgKiB4MywgeDAsIHkxIC0geTAgKyBhMTMgKiB5MSwgeTMgLSB5MCArIGEyMyAqIHkzLCB5MCwgYTEzLCBhMjMsIDEuMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHF1YWRyaWxhdGVyYWxUb1NxdWFyZSh4MCAvKmZsb2F0Ki8sIHkwIC8qZmxvYXQqLywgeDEgLypmbG9hdCovLCB5MSAvKmZsb2F0Ki8sIHgyIC8qZmxvYXQqLywgeTIgLypmbG9hdCovLCB4MyAvKmZsb2F0Ki8sIHkzIC8qZmxvYXQqLykge1xuICAgICAgICAgICAgLy8gSGVyZSwgdGhlIGFkam9pbnQgc2VydmVzIGFzIHRoZSBpbnZlcnNlOlxuICAgICAgICAgICAgcmV0dXJuIFBlcnNwZWN0aXZlVHJhbnNmb3JtLnNxdWFyZVRvUXVhZHJpbGF0ZXJhbCh4MCwgeTAsIHgxLCB5MSwgeDIsIHkyLCB4MywgeTMpLmJ1aWxkQWRqb2ludCgpO1xuICAgICAgICB9XG4gICAgICAgIGJ1aWxkQWRqb2ludCgpIHtcbiAgICAgICAgICAgIC8vIEFkam9pbnQgaXMgdGhlIHRyYW5zcG9zZSBvZiB0aGUgY29mYWN0b3IgbWF0cml4OlxuICAgICAgICAgICAgcmV0dXJuIG5ldyBQZXJzcGVjdGl2ZVRyYW5zZm9ybSh0aGlzLmEyMiAqIHRoaXMuYTMzIC0gdGhpcy5hMjMgKiB0aGlzLmEzMiwgdGhpcy5hMjMgKiB0aGlzLmEzMSAtIHRoaXMuYTIxICogdGhpcy5hMzMsIHRoaXMuYTIxICogdGhpcy5hMzIgLSB0aGlzLmEyMiAqIHRoaXMuYTMxLCB0aGlzLmExMyAqIHRoaXMuYTMyIC0gdGhpcy5hMTIgKiB0aGlzLmEzMywgdGhpcy5hMTEgKiB0aGlzLmEzMyAtIHRoaXMuYTEzICogdGhpcy5hMzEsIHRoaXMuYTEyICogdGhpcy5hMzEgLSB0aGlzLmExMSAqIHRoaXMuYTMyLCB0aGlzLmExMiAqIHRoaXMuYTIzIC0gdGhpcy5hMTMgKiB0aGlzLmEyMiwgdGhpcy5hMTMgKiB0aGlzLmEyMSAtIHRoaXMuYTExICogdGhpcy5hMjMsIHRoaXMuYTExICogdGhpcy5hMjIgLSB0aGlzLmExMiAqIHRoaXMuYTIxKTtcbiAgICAgICAgfVxuICAgICAgICB0aW1lcyhvdGhlcikge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQZXJzcGVjdGl2ZVRyYW5zZm9ybSh0aGlzLmExMSAqIG90aGVyLmExMSArIHRoaXMuYTIxICogb3RoZXIuYTEyICsgdGhpcy5hMzEgKiBvdGhlci5hMTMsIHRoaXMuYTExICogb3RoZXIuYTIxICsgdGhpcy5hMjEgKiBvdGhlci5hMjIgKyB0aGlzLmEzMSAqIG90aGVyLmEyMywgdGhpcy5hMTEgKiBvdGhlci5hMzEgKyB0aGlzLmEyMSAqIG90aGVyLmEzMiArIHRoaXMuYTMxICogb3RoZXIuYTMzLCB0aGlzLmExMiAqIG90aGVyLmExMSArIHRoaXMuYTIyICogb3RoZXIuYTEyICsgdGhpcy5hMzIgKiBvdGhlci5hMTMsIHRoaXMuYTEyICogb3RoZXIuYTIxICsgdGhpcy5hMjIgKiBvdGhlci5hMjIgKyB0aGlzLmEzMiAqIG90aGVyLmEyMywgdGhpcy5hMTIgKiBvdGhlci5hMzEgKyB0aGlzLmEyMiAqIG90aGVyLmEzMiArIHRoaXMuYTMyICogb3RoZXIuYTMzLCB0aGlzLmExMyAqIG90aGVyLmExMSArIHRoaXMuYTIzICogb3RoZXIuYTEyICsgdGhpcy5hMzMgKiBvdGhlci5hMTMsIHRoaXMuYTEzICogb3RoZXIuYTIxICsgdGhpcy5hMjMgKiBvdGhlci5hMjIgKyB0aGlzLmEzMyAqIG90aGVyLmEyMywgdGhpcy5hMTMgKiBvdGhlci5hMzEgKyB0aGlzLmEyMyAqIG90aGVyLmEzMiArIHRoaXMuYTMzICogb3RoZXIuYTMzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBEZWZhdWx0R3JpZFNhbXBsZXIgZXh0ZW5kcyBHcmlkU2FtcGxlciB7XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgc2FtcGxlR3JpZChpbWFnZSwgZGltZW5zaW9uWCAvKmludCovLCBkaW1lbnNpb25ZIC8qaW50Ki8sIHAxVG9YIC8qZmxvYXQqLywgcDFUb1kgLypmbG9hdCovLCBwMlRvWCAvKmZsb2F0Ki8sIHAyVG9ZIC8qZmxvYXQqLywgcDNUb1ggLypmbG9hdCovLCBwM1RvWSAvKmZsb2F0Ki8sIHA0VG9YIC8qZmxvYXQqLywgcDRUb1kgLypmbG9hdCovLCBwMUZyb21YIC8qZmxvYXQqLywgcDFGcm9tWSAvKmZsb2F0Ki8sIHAyRnJvbVggLypmbG9hdCovLCBwMkZyb21ZIC8qZmxvYXQqLywgcDNGcm9tWCAvKmZsb2F0Ki8sIHAzRnJvbVkgLypmbG9hdCovLCBwNEZyb21YIC8qZmxvYXQqLywgcDRGcm9tWSAvKmZsb2F0Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zZm9ybSA9IFBlcnNwZWN0aXZlVHJhbnNmb3JtLnF1YWRyaWxhdGVyYWxUb1F1YWRyaWxhdGVyYWwocDFUb1gsIHAxVG9ZLCBwMlRvWCwgcDJUb1ksIHAzVG9YLCBwM1RvWSwgcDRUb1gsIHA0VG9ZLCBwMUZyb21YLCBwMUZyb21ZLCBwMkZyb21YLCBwMkZyb21ZLCBwM0Zyb21YLCBwM0Zyb21ZLCBwNEZyb21YLCBwNEZyb21ZKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNhbXBsZUdyaWRXaXRoVHJhbnNmb3JtKGltYWdlLCBkaW1lbnNpb25YLCBkaW1lbnNpb25ZLCB0cmFuc2Zvcm0pO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgc2FtcGxlR3JpZFdpdGhUcmFuc2Zvcm0oaW1hZ2UsIGRpbWVuc2lvblggLyppbnQqLywgZGltZW5zaW9uWSAvKmludCovLCB0cmFuc2Zvcm0pIHtcbiAgICAgICAgICAgIGlmIChkaW1lbnNpb25YIDw9IDAgfHwgZGltZW5zaW9uWSA8PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBiaXRzID0gbmV3IEJpdE1hdHJpeChkaW1lbnNpb25YLCBkaW1lbnNpb25ZKTtcbiAgICAgICAgICAgIGNvbnN0IHBvaW50cyA9IG5ldyBGbG9hdDMyQXJyYXkoMiAqIGRpbWVuc2lvblgpO1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCBkaW1lbnNpb25ZOyB5KyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBtYXggPSBwb2ludHMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGNvbnN0IGlWYWx1ZSA9IHkgKyAwLjU7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCBtYXg7IHggKz0gMikge1xuICAgICAgICAgICAgICAgICAgICBwb2ludHNbeF0gPSAoeCAvIDIpICsgMC41O1xuICAgICAgICAgICAgICAgICAgICBwb2ludHNbeCArIDFdID0gaVZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm0udHJhbnNmb3JtUG9pbnRzKHBvaW50cyk7XG4gICAgICAgICAgICAgICAgLy8gUXVpY2sgY2hlY2sgdG8gc2VlIGlmIHBvaW50cyB0cmFuc2Zvcm1lZCB0byBzb21ldGhpbmcgaW5zaWRlIHRoZSBpbWFnZVxuICAgICAgICAgICAgICAgIC8vIHN1ZmZpY2llbnQgdG8gY2hlY2sgdGhlIGVuZHBvaW50c1xuICAgICAgICAgICAgICAgIEdyaWRTYW1wbGVyLmNoZWNrQW5kTnVkZ2VQb2ludHMoaW1hZ2UsIHBvaW50cyk7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCBtYXg7IHggKz0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGltYWdlLmdldChNYXRoLmZsb29yKHBvaW50c1t4XSksIE1hdGguZmxvb3IocG9pbnRzW3ggKyAxXSkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQmxhY2soLWlzaCkgcGl4ZWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaXRzLnNldCh4IC8gMiwgeSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKGFpb29iZSAvKjogQXJyYXlJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uKi8pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBmZWVscyB3cm9uZywgYnV0LCBzb21ldGltZXMgaWYgdGhlIGZpbmRlciBwYXR0ZXJucyBhcmUgbWlzaWRlbnRpZmllZCwgdGhlIHJlc3VsdGluZ1xuICAgICAgICAgICAgICAgICAgICAvLyB0cmFuc2Zvcm0gZ2V0cyBcInR3aXN0ZWRcIiBzdWNoIHRoYXQgaXQgbWFwcyBhIHN0cmFpZ2h0IGxpbmUgb2YgcG9pbnRzIHRvIGEgc2V0IG9mIHBvaW50c1xuICAgICAgICAgICAgICAgICAgICAvLyB3aG9zZSBlbmRwb2ludHMgYXJlIGluIGJvdW5kcywgYnV0IG90aGVycyBhcmUgbm90LiBUaGVyZSBpcyBwcm9iYWJseSBzb21lIG1hdGhlbWF0aWNhbFxuICAgICAgICAgICAgICAgICAgICAvLyB3YXkgdG8gZGV0ZWN0IHRoaXMgYWJvdXQgdGhlIHRyYW5zZm9ybWF0aW9uIHRoYXQgSSBkb24ndCBrbm93IHlldC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyByZXN1bHRzIGluIGFuIHVnbHkgcnVudGltZSBleGNlcHRpb24gZGVzcGl0ZSBvdXIgY2xldmVyIGNoZWNrcyBhYm92ZSAtLSBjYW4ndCBoYXZlXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoYXQuIFdlIGNvdWxkIGNoZWNrIGVhY2ggcG9pbnQncyBjb29yZGluYXRlcyBidXQgdGhhdCBmZWVscyBkdXBsaWNhdGl2ZS4gV2Ugc2V0dGxlIGZvclxuICAgICAgICAgICAgICAgICAgICAvLyBjYXRjaGluZyBhbmQgd3JhcHBpbmcgQXJyYXlJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uLlxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYml0cztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNsYXNzIEdyaWRTYW1wbGVySW5zdGFuY2Uge1xuICAgICAgICAvKipcbiAgICAgICAgICogU2V0cyB0aGUgaW1wbGVtZW50YXRpb24gb2YgR3JpZFNhbXBsZXIgdXNlZCBieSB0aGUgbGlicmFyeS4gT25lIGdsb2JhbFxuICAgICAgICAgKiBpbnN0YW5jZSBpcyBzdG9yZWQsIHdoaWNoIG1heSBzb3VuZCBwcm9ibGVtYXRpYy4gQnV0LCB0aGUgaW1wbGVtZW50YXRpb24gcHJvdmlkZWRcbiAgICAgICAgICogb3VnaHQgdG8gYmUgYXBwcm9wcmlhdGUgZm9yIHRoZSBlbnRpcmUgcGxhdGZvcm0sIGFuZCBhbGwgdXNlcyBvZiB0aGlzIGxpYnJhcnlcbiAgICAgICAgICogaW4gdGhlIHdob2xlIGxpZmV0aW1lIG9mIHRoZSBKVk0uIEZvciBpbnN0YW5jZSwgYW4gQW5kcm9pZCBhY3Rpdml0eSBjYW4gc3dhcCBpblxuICAgICAgICAgKiBhbiBpbXBsZW1lbnRhdGlvbiB0aGF0IHRha2VzIGFkdmFudGFnZSBvZiBuYXRpdmUgcGxhdGZvcm0gbGlicmFyaWVzLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gbmV3R3JpZFNhbXBsZXIgVGhlIHBsYXRmb3JtLXNwZWNpZmljIG9iamVjdCB0byBpbnN0YWxsLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIHNldEdyaWRTYW1wbGVyKG5ld0dyaWRTYW1wbGVyKSB7XG4gICAgICAgICAgICBHcmlkU2FtcGxlckluc3RhbmNlLmdyaWRTYW1wbGVyID0gbmV3R3JpZFNhbXBsZXI7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gdGhlIGN1cnJlbnQgaW1wbGVtZW50YXRpb24gb2YgR3JpZFNhbXBsZXJcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBnZXRJbnN0YW5jZSgpIHtcbiAgICAgICAgICAgIHJldHVybiBHcmlkU2FtcGxlckluc3RhbmNlLmdyaWRTYW1wbGVyO1xuICAgICAgICB9XG4gICAgfVxuICAgIEdyaWRTYW1wbGVySW5zdGFuY2UuZ3JpZFNhbXBsZXIgPSBuZXcgRGVmYXVsdEdyaWRTYW1wbGVyKCk7XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDEwIFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIGNsYXNzIFBvaW50IHtcbiAgICAgICAgY29uc3RydWN0b3IoeCwgeSkge1xuICAgICAgICAgICAgdGhpcy54ID0geDtcbiAgICAgICAgICAgIHRoaXMueSA9IHk7XG4gICAgICAgIH1cbiAgICAgICAgdG9SZXN1bHRQb2ludCgpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUmVzdWx0UG9pbnQodGhpcy5nZXRYKCksIHRoaXMuZ2V0WSgpKTtcbiAgICAgICAgfVxuICAgICAgICBnZXRYKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMueDtcbiAgICAgICAgfVxuICAgICAgICBnZXRZKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMueTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBFbmNhcHN1bGF0ZXMgbG9naWMgdGhhdCBjYW4gZGV0ZWN0IGFuIEF6dGVjIENvZGUgaW4gYW4gaW1hZ2UsIGV2ZW4gaWYgdGhlIEF6dGVjIENvZGVcbiAgICAgKiBpcyByb3RhdGVkIG9yIHNrZXdlZCwgb3IgcGFydGlhbGx5IG9ic2N1cmVkLlxuICAgICAqXG4gICAgICogQGF1dGhvciBEYXZpZCBPbGl2aWVyXG4gICAgICogQGF1dGhvciBGcmFuayBZZWxsaW5cbiAgICAgKi9cbiAgICBjbGFzcyBEZXRlY3RvciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGltYWdlKSB7XG4gICAgICAgICAgICB0aGlzLkVYUEVDVEVEX0NPUk5FUl9CSVRTID0gbmV3IEludDMyQXJyYXkoW1xuICAgICAgICAgICAgICAgIDB4ZWUwLFxuICAgICAgICAgICAgICAgIDB4MWRjLFxuICAgICAgICAgICAgICAgIDB4ODNiLFxuICAgICAgICAgICAgICAgIDB4NzA3LFxuICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICB0aGlzLmltYWdlID0gaW1hZ2U7XG4gICAgICAgIH1cbiAgICAgICAgZGV0ZWN0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGV0ZWN0TWlycm9yKGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGV0ZWN0cyBhbiBBenRlYyBDb2RlIGluIGFuIGltYWdlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gaXNNaXJyb3IgaWYgdHJ1ZSwgaW1hZ2UgaXMgYSBtaXJyb3ItaW1hZ2Ugb2Ygb3JpZ2luYWxcbiAgICAgICAgICogQHJldHVybiB7QGxpbmsgQXp0ZWNEZXRlY3RvclJlc3VsdH0gZW5jYXBzdWxhdGluZyByZXN1bHRzIG9mIGRldGVjdGluZyBhbiBBenRlYyBDb2RlXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gaWYgbm8gQXp0ZWMgQ29kZSBjYW4gYmUgZm91bmRcbiAgICAgICAgICovXG4gICAgICAgIGRldGVjdE1pcnJvcihpc01pcnJvcikge1xuICAgICAgICAgICAgLy8gMS4gR2V0IHRoZSBjZW50ZXIgb2YgdGhlIGF6dGVjIG1hdHJpeFxuICAgICAgICAgICAgbGV0IHBDZW50ZXIgPSB0aGlzLmdldE1hdHJpeENlbnRlcigpO1xuICAgICAgICAgICAgLy8gMi4gR2V0IHRoZSBjZW50ZXIgcG9pbnRzIG9mIHRoZSBmb3VyIGRpYWdvbmFsIHBvaW50cyBqdXN0IG91dHNpZGUgdGhlIGJ1bGwncyBleWVcbiAgICAgICAgICAgIC8vICBbdG9wUmlnaHQsIGJvdHRvbVJpZ2h0LCBib3R0b21MZWZ0LCB0b3BMZWZ0XVxuICAgICAgICAgICAgbGV0IGJ1bGxzRXllQ29ybmVycyA9IHRoaXMuZ2V0QnVsbHNFeWVDb3JuZXJzKHBDZW50ZXIpO1xuICAgICAgICAgICAgaWYgKGlzTWlycm9yKSB7XG4gICAgICAgICAgICAgICAgbGV0IHRlbXAgPSBidWxsc0V5ZUNvcm5lcnNbMF07XG4gICAgICAgICAgICAgICAgYnVsbHNFeWVDb3JuZXJzWzBdID0gYnVsbHNFeWVDb3JuZXJzWzJdO1xuICAgICAgICAgICAgICAgIGJ1bGxzRXllQ29ybmVyc1syXSA9IHRlbXA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyAzLiBHZXQgdGhlIHNpemUgb2YgdGhlIG1hdHJpeCBhbmQgb3RoZXIgcGFyYW1ldGVycyBmcm9tIHRoZSBidWxsJ3MgZXllXG4gICAgICAgICAgICB0aGlzLmV4dHJhY3RQYXJhbWV0ZXJzKGJ1bGxzRXllQ29ybmVycyk7XG4gICAgICAgICAgICAvLyA0LiBTYW1wbGUgdGhlIGdyaWRcbiAgICAgICAgICAgIGxldCBiaXRzID0gdGhpcy5zYW1wbGVHcmlkKHRoaXMuaW1hZ2UsIGJ1bGxzRXllQ29ybmVyc1t0aGlzLnNoaWZ0ICUgNF0sIGJ1bGxzRXllQ29ybmVyc1sodGhpcy5zaGlmdCArIDEpICUgNF0sIGJ1bGxzRXllQ29ybmVyc1sodGhpcy5zaGlmdCArIDIpICUgNF0sIGJ1bGxzRXllQ29ybmVyc1sodGhpcy5zaGlmdCArIDMpICUgNF0pO1xuICAgICAgICAgICAgLy8gNS4gR2V0IHRoZSBjb3JuZXJzIG9mIHRoZSBtYXRyaXguXG4gICAgICAgICAgICBsZXQgY29ybmVycyA9IHRoaXMuZ2V0TWF0cml4Q29ybmVyUG9pbnRzKGJ1bGxzRXllQ29ybmVycyk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEF6dGVjRGV0ZWN0b3JSZXN1bHQoYml0cywgY29ybmVycywgdGhpcy5jb21wYWN0LCB0aGlzLm5iRGF0YUJsb2NrcywgdGhpcy5uYkxheWVycyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEV4dHJhY3RzIHRoZSBudW1iZXIgb2YgZGF0YSBsYXllcnMgYW5kIGRhdGEgYmxvY2tzIGZyb20gdGhlIGxheWVyIGFyb3VuZCB0aGUgYnVsbCdzIGV5ZS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGJ1bGxzRXllQ29ybmVycyB0aGUgYXJyYXkgb2YgYnVsbCdzIGV5ZSBjb3JuZXJzXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gaW4gY2FzZSBvZiB0b28gbWFueSBlcnJvcnMgb3IgaW52YWxpZCBwYXJhbWV0ZXJzXG4gICAgICAgICAqL1xuICAgICAgICBleHRyYWN0UGFyYW1ldGVycyhidWxsc0V5ZUNvcm5lcnMpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5pc1ZhbGlkUG9pbnQoYnVsbHNFeWVDb3JuZXJzWzBdKSB8fCAhdGhpcy5pc1ZhbGlkUG9pbnQoYnVsbHNFeWVDb3JuZXJzWzFdKSB8fFxuICAgICAgICAgICAgICAgICF0aGlzLmlzVmFsaWRQb2ludChidWxsc0V5ZUNvcm5lcnNbMl0pIHx8ICF0aGlzLmlzVmFsaWRQb2ludChidWxsc0V5ZUNvcm5lcnNbM10pKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgbGVuZ3RoID0gMiAqIHRoaXMubmJDZW50ZXJMYXllcnM7XG4gICAgICAgICAgICAvLyBHZXQgdGhlIGJpdHMgYXJvdW5kIHRoZSBidWxsJ3MgZXllXG4gICAgICAgICAgICBsZXQgc2lkZXMgPSBuZXcgSW50MzJBcnJheShbXG4gICAgICAgICAgICAgICAgdGhpcy5zYW1wbGVMaW5lKGJ1bGxzRXllQ29ybmVyc1swXSwgYnVsbHNFeWVDb3JuZXJzWzFdLCBsZW5ndGgpLFxuICAgICAgICAgICAgICAgIHRoaXMuc2FtcGxlTGluZShidWxsc0V5ZUNvcm5lcnNbMV0sIGJ1bGxzRXllQ29ybmVyc1syXSwgbGVuZ3RoKSxcbiAgICAgICAgICAgICAgICB0aGlzLnNhbXBsZUxpbmUoYnVsbHNFeWVDb3JuZXJzWzJdLCBidWxsc0V5ZUNvcm5lcnNbM10sIGxlbmd0aCksXG4gICAgICAgICAgICAgICAgdGhpcy5zYW1wbGVMaW5lKGJ1bGxzRXllQ29ybmVyc1szXSwgYnVsbHNFeWVDb3JuZXJzWzBdLCBsZW5ndGgpIC8vIFRvcFxuICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAvLyBidWxsc0V5ZUNvcm5lcnNbc2hpZnRdIGlzIHRoZSBjb3JuZXIgb2YgdGhlIGJ1bGxzJ2V5ZSB0aGF0IGhhcyB0aHJlZVxuICAgICAgICAgICAgLy8gb3JpZW50YXRpb24gbWFya3MuXG4gICAgICAgICAgICAvLyBzaWRlc1tzaGlmdF0gaXMgdGhlIHJvdy9jb2x1bW4gdGhhdCBnb2VzIGZyb20gdGhlIGNvcm5lciB3aXRoIHRocmVlXG4gICAgICAgICAgICAvLyBvcmllbnRhdGlvbiBtYXJrcyB0byB0aGUgY29ybmVyIHdpdGggdHdvLlxuICAgICAgICAgICAgdGhpcy5zaGlmdCA9IHRoaXMuZ2V0Um90YXRpb24oc2lkZXMsIGxlbmd0aCk7XG4gICAgICAgICAgICAvLyBGbGF0dGVuIHRoZSBwYXJhbWV0ZXIgYml0cyBpbnRvIGEgc2luZ2xlIDI4LSBvciA0MC1iaXQgbG9uZ1xuICAgICAgICAgICAgbGV0IHBhcmFtZXRlckRhdGEgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCA0OyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgc2lkZSA9IHNpZGVzWyh0aGlzLnNoaWZ0ICsgaSkgJSA0XTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb21wYWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEVhY2ggc2lkZSBvZiB0aGUgZm9ybSAuLlhYWFhYWFguIHdoZXJlIFhzIGFyZSBwYXJhbWV0ZXIgZGF0YVxuICAgICAgICAgICAgICAgICAgICBwYXJhbWV0ZXJEYXRhIDw8PSA3O1xuICAgICAgICAgICAgICAgICAgICBwYXJhbWV0ZXJEYXRhICs9IChzaWRlID4+IDEpICYgMHg3RjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEVhY2ggc2lkZSBvZiB0aGUgZm9ybSAuLlhYWFhYLlhYWFhYLiB3aGVyZSBYcyBhcmUgcGFyYW1ldGVyIGRhdGFcbiAgICAgICAgICAgICAgICAgICAgcGFyYW1ldGVyRGF0YSA8PD0gMTA7XG4gICAgICAgICAgICAgICAgICAgIHBhcmFtZXRlckRhdGEgKz0gKChzaWRlID4+IDIpICYgKDB4MWYgPDwgNSkpICsgKChzaWRlID4+IDEpICYgMHgxRik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQ29ycmVjdHMgcGFyYW1ldGVyIGRhdGEgdXNpbmcgUlMuICBSZXR1cm5zIGp1c3QgdGhlIGRhdGEgcG9ydGlvblxuICAgICAgICAgICAgLy8gd2l0aG91dCB0aGUgZXJyb3IgY29ycmVjdGlvbi5cbiAgICAgICAgICAgIGxldCBjb3JyZWN0ZWREYXRhID0gdGhpcy5nZXRDb3JyZWN0ZWRQYXJhbWV0ZXJEYXRhKHBhcmFtZXRlckRhdGEsIHRoaXMuY29tcGFjdCk7XG4gICAgICAgICAgICBpZiAodGhpcy5jb21wYWN0KSB7XG4gICAgICAgICAgICAgICAgLy8gOCBiaXRzOiAgMiBiaXRzIGxheWVycyBhbmQgNiBiaXRzIGRhdGEgYmxvY2tzXG4gICAgICAgICAgICAgICAgdGhpcy5uYkxheWVycyA9IChjb3JyZWN0ZWREYXRhID4+IDYpICsgMTtcbiAgICAgICAgICAgICAgICB0aGlzLm5iRGF0YUJsb2NrcyA9IChjb3JyZWN0ZWREYXRhICYgMHgzRikgKyAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gMTYgYml0czogIDUgYml0cyBsYXllcnMgYW5kIDExIGJpdHMgZGF0YSBibG9ja3NcbiAgICAgICAgICAgICAgICB0aGlzLm5iTGF5ZXJzID0gKGNvcnJlY3RlZERhdGEgPj4gMTEpICsgMTtcbiAgICAgICAgICAgICAgICB0aGlzLm5iRGF0YUJsb2NrcyA9IChjb3JyZWN0ZWREYXRhICYgMHg3RkYpICsgMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBnZXRSb3RhdGlvbihzaWRlcywgbGVuZ3RoKSB7XG4gICAgICAgICAgICAvLyBJbiBhIG5vcm1hbCBwYXR0ZXJuLCB3ZSBleHBlY3QgdG8gU2VlXG4gICAgICAgICAgICAvLyAgICoqICAgIC4qICAgICAgICAgICAgIEQgICAgICAgQVxuICAgICAgICAgICAgLy8gICAqICAgICAgKlxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vICAgLiAgICAgICpcbiAgICAgICAgICAgIC8vICAgLi4gICAgLi4gICAgICAgICAgICAgQyAgICAgICBCXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gR3JhYiB0aGUgMyBiaXRzIGZyb20gZWFjaCBvZiB0aGUgc2lkZXMgdGhlIGZvcm0gdGhlIGxvY2F0b3IgcGF0dGVybiBhbmQgY29uY2F0ZW5hdGVcbiAgICAgICAgICAgIC8vIGludG8gYSAxMi1iaXQgaW50ZWdlci4gIFN0YXJ0IHdpdGggdGhlIGJpdCBhdCBBXG4gICAgICAgICAgICBsZXQgY29ybmVyQml0cyA9IDA7XG4gICAgICAgICAgICBzaWRlcy5mb3JFYWNoKChzaWRlLCBpZHgsIGFycikgPT4ge1xuICAgICAgICAgICAgICAgIC8vIFhYLi4uLi4uWCB3aGVyZSBYJ3MgYXJlIG9yaWVudGF0aW9uIG1hcmtzXG4gICAgICAgICAgICAgICAgbGV0IHQgPSAoKHNpZGUgPj4gKGxlbmd0aCAtIDIpKSA8PCAxKSArIChzaWRlICYgMSk7XG4gICAgICAgICAgICAgICAgY29ybmVyQml0cyA9IChjb3JuZXJCaXRzIDw8IDMpICsgdDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgLy8gZm9yICh2YXIgc2lkZSBpbiBzaWRlcykge1xuICAgICAgICAgICAgLy8gICAgIC8vIFhYLi4uLi4uWCB3aGVyZSBYJ3MgYXJlIG9yaWVudGF0aW9uIG1hcmtzXG4gICAgICAgICAgICAvLyAgICAgdmFyIHQgPSAoKHNpZGUgPj4gKGxlbmd0aCAtIDIpKSA8PCAxKSArIChzaWRlICYgMSk7XG4gICAgICAgICAgICAvLyAgICAgY29ybmVyQml0cyA9IChjb3JuZXJCaXRzIDw8IDMpICsgdDtcbiAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgIC8vIE1vdiB0aGUgYm90dG9tIGJpdCB0byB0aGUgdG9wLCBzbyB0aGF0IHRoZSB0aHJlZSBiaXRzIG9mIHRoZSBsb2NhdG9yIHBhdHRlcm4gYXQgQSBhcmVcbiAgICAgICAgICAgIC8vIHRvZ2V0aGVyLiAgY29ybmVyQml0cyBpcyBub3c6XG4gICAgICAgICAgICAvLyAgMyBvcmllbnRhdGlvbiBiaXRzIGF0IEEgfHwgMyBvcmllbnRhdGlvbiBiaXRzIGF0IEIgfHwgLi4uIHx8IDMgb3JpZW50YXRpb24gYml0cyBhdCBEXG4gICAgICAgICAgICBjb3JuZXJCaXRzID0gKChjb3JuZXJCaXRzICYgMSkgPDwgMTEpICsgKGNvcm5lckJpdHMgPj4gMSk7XG4gICAgICAgICAgICAvLyBUaGUgcmVzdWx0IHNoaWZ0IGluZGljYXRlcyB3aGljaCBlbGVtZW50IG9mIEJ1bGxzRXllQ29ybmVyc1tdIGdvZXMgaW50byB0aGUgdG9wLWxlZnRcbiAgICAgICAgICAgIC8vIGNvcm5lci4gU2luY2UgdGhlIGZvdXIgcm90YXRpb24gdmFsdWVzIGhhdmUgYSBIYW1taW5nIGRpc3RhbmNlIG9mIDgsIHdlXG4gICAgICAgICAgICAvLyBjYW4gZWFzaWx5IHRvbGVyYXRlIHR3byBlcnJvcnMuXG4gICAgICAgICAgICBmb3IgKGxldCBzaGlmdCA9IDA7IHNoaWZ0IDwgNDsgc2hpZnQrKykge1xuICAgICAgICAgICAgICAgIGlmIChJbnRlZ2VyLmJpdENvdW50KGNvcm5lckJpdHMgXiB0aGlzLkVYUEVDVEVEX0NPUk5FUl9CSVRTW3NoaWZ0XSkgPD0gMikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2hpZnQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvcnJlY3RzIHRoZSBwYXJhbWV0ZXIgYml0cyB1c2luZyBSZWVkLVNvbG9tb24gYWxnb3JpdGhtLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gcGFyYW1ldGVyRGF0YSBwYXJhbWV0ZXIgYml0c1xuICAgICAgICAgKiBAcGFyYW0gY29tcGFjdCB0cnVlIGlmIHRoaXMgaXMgYSBjb21wYWN0IEF6dGVjIGNvZGVcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBpZiB0aGUgYXJyYXkgY29udGFpbnMgdG9vIG1hbnkgZXJyb3JzXG4gICAgICAgICAqL1xuICAgICAgICBnZXRDb3JyZWN0ZWRQYXJhbWV0ZXJEYXRhKHBhcmFtZXRlckRhdGEsIGNvbXBhY3QpIHtcbiAgICAgICAgICAgIGxldCBudW1Db2Rld29yZHM7XG4gICAgICAgICAgICBsZXQgbnVtRGF0YUNvZGV3b3JkcztcbiAgICAgICAgICAgIGlmIChjb21wYWN0KSB7XG4gICAgICAgICAgICAgICAgbnVtQ29kZXdvcmRzID0gNztcbiAgICAgICAgICAgICAgICBudW1EYXRhQ29kZXdvcmRzID0gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG51bUNvZGV3b3JkcyA9IDEwO1xuICAgICAgICAgICAgICAgIG51bURhdGFDb2Rld29yZHMgPSA0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IG51bUVDQ29kZXdvcmRzID0gbnVtQ29kZXdvcmRzIC0gbnVtRGF0YUNvZGV3b3JkcztcbiAgICAgICAgICAgIGxldCBwYXJhbWV0ZXJXb3JkcyA9IG5ldyBJbnQzMkFycmF5KG51bUNvZGV3b3Jkcyk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gbnVtQ29kZXdvcmRzIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgICAgICAgICBwYXJhbWV0ZXJXb3Jkc1tpXSA9IHBhcmFtZXRlckRhdGEgJiAweEY7XG4gICAgICAgICAgICAgICAgcGFyYW1ldGVyRGF0YSA+Pj0gNDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbGV0IHJzRGVjb2RlciA9IG5ldyBSZWVkU29sb21vbkRlY29kZXIoR2VuZXJpY0dGLkFaVEVDX1BBUkFNKTtcbiAgICAgICAgICAgICAgICByc0RlY29kZXIuZGVjb2RlKHBhcmFtZXRlcldvcmRzLCBudW1FQ0NvZGV3b3Jkcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoaWdub3JlZCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gVG9zcyB0aGUgZXJyb3IgY29ycmVjdGlvbi4gIEp1c3QgcmV0dXJuIHRoZSBkYXRhIGFzIGFuIGludGVnZXJcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1EYXRhQ29kZXdvcmRzOyBpKyspIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSAocmVzdWx0IDw8IDQpICsgcGFyYW1ldGVyV29yZHNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBGaW5kcyB0aGUgY29ybmVycyBvZiBhIGJ1bGwtZXllIGNlbnRlcmVkIG9uIHRoZSBwYXNzZWQgcG9pbnQuXG4gICAgICAgICAqIFRoaXMgcmV0dXJucyB0aGUgY2VudGVycyBvZiB0aGUgZGlhZ29uYWwgcG9pbnRzIGp1c3Qgb3V0c2lkZSB0aGUgYnVsbCdzIGV5ZVxuICAgICAgICAgKiBSZXR1cm5zIFt0b3BSaWdodCwgYm90dG9tUmlnaHQsIGJvdHRvbUxlZnQsIHRvcExlZnRdXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBwQ2VudGVyIENlbnRlciBwb2ludFxuICAgICAgICAgKiBAcmV0dXJuIFRoZSBjb3JuZXJzIG9mIHRoZSBidWxsLWV5ZVxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIElmIG5vIHZhbGlkIGJ1bGwtZXllIGNhbiBiZSBmb3VuZFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0QnVsbHNFeWVDb3JuZXJzKHBDZW50ZXIpIHtcbiAgICAgICAgICAgIGxldCBwaW5hID0gcENlbnRlcjtcbiAgICAgICAgICAgIGxldCBwaW5iID0gcENlbnRlcjtcbiAgICAgICAgICAgIGxldCBwaW5jID0gcENlbnRlcjtcbiAgICAgICAgICAgIGxldCBwaW5kID0gcENlbnRlcjtcbiAgICAgICAgICAgIGxldCBjb2xvciA9IHRydWU7XG4gICAgICAgICAgICBmb3IgKHRoaXMubmJDZW50ZXJMYXllcnMgPSAxOyB0aGlzLm5iQ2VudGVyTGF5ZXJzIDwgOTsgdGhpcy5uYkNlbnRlckxheWVycysrKSB7XG4gICAgICAgICAgICAgICAgbGV0IHBvdXRhID0gdGhpcy5nZXRGaXJzdERpZmZlcmVudChwaW5hLCBjb2xvciwgMSwgLTEpO1xuICAgICAgICAgICAgICAgIGxldCBwb3V0YiA9IHRoaXMuZ2V0Rmlyc3REaWZmZXJlbnQocGluYiwgY29sb3IsIDEsIDEpO1xuICAgICAgICAgICAgICAgIGxldCBwb3V0YyA9IHRoaXMuZ2V0Rmlyc3REaWZmZXJlbnQocGluYywgY29sb3IsIC0xLCAxKTtcbiAgICAgICAgICAgICAgICBsZXQgcG91dGQgPSB0aGlzLmdldEZpcnN0RGlmZmVyZW50KHBpbmQsIGNvbG9yLCAtMSwgLTEpO1xuICAgICAgICAgICAgICAgIC8vIGQgICAgICBhXG4gICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAvLyBjICAgICAgYlxuICAgICAgICAgICAgICAgIGlmICh0aGlzLm5iQ2VudGVyTGF5ZXJzID4gMikge1xuICAgICAgICAgICAgICAgICAgICBsZXQgcSA9ICh0aGlzLmRpc3RhbmNlUG9pbnQocG91dGQsIHBvdXRhKSAqIHRoaXMubmJDZW50ZXJMYXllcnMpIC8gKHRoaXMuZGlzdGFuY2VQb2ludChwaW5kLCBwaW5hKSAqICh0aGlzLm5iQ2VudGVyTGF5ZXJzICsgMikpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocSA8IDAuNzUgfHwgcSA+IDEuMjUgfHwgIXRoaXMuaXNXaGl0ZU9yQmxhY2tSZWN0YW5nbGUocG91dGEsIHBvdXRiLCBwb3V0YywgcG91dGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwaW5hID0gcG91dGE7XG4gICAgICAgICAgICAgICAgcGluYiA9IHBvdXRiO1xuICAgICAgICAgICAgICAgIHBpbmMgPSBwb3V0YztcbiAgICAgICAgICAgICAgICBwaW5kID0gcG91dGQ7XG4gICAgICAgICAgICAgICAgY29sb3IgPSAhY29sb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5uYkNlbnRlckxheWVycyAhPT0gNSAmJiB0aGlzLm5iQ2VudGVyTGF5ZXJzICE9PSA3KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmNvbXBhY3QgPSB0aGlzLm5iQ2VudGVyTGF5ZXJzID09PSA1O1xuICAgICAgICAgICAgLy8gRXhwYW5kIHRoZSBzcXVhcmUgYnkgLjUgcGl4ZWwgaW4gZWFjaCBkaXJlY3Rpb24gc28gdGhhdCB3ZSdyZSBvbiB0aGUgYm9yZGVyXG4gICAgICAgICAgICAvLyBiZXR3ZWVuIHRoZSB3aGl0ZSBzcXVhcmUgYW5kIHRoZSBibGFjayBzcXVhcmVcbiAgICAgICAgICAgIGxldCBwaW5heCA9IG5ldyBSZXN1bHRQb2ludChwaW5hLmdldFgoKSArIDAuNSwgcGluYS5nZXRZKCkgLSAwLjUpO1xuICAgICAgICAgICAgbGV0IHBpbmJ4ID0gbmV3IFJlc3VsdFBvaW50KHBpbmIuZ2V0WCgpICsgMC41LCBwaW5iLmdldFkoKSArIDAuNSk7XG4gICAgICAgICAgICBsZXQgcGluY3ggPSBuZXcgUmVzdWx0UG9pbnQocGluYy5nZXRYKCkgLSAwLjUsIHBpbmMuZ2V0WSgpICsgMC41KTtcbiAgICAgICAgICAgIGxldCBwaW5keCA9IG5ldyBSZXN1bHRQb2ludChwaW5kLmdldFgoKSAtIDAuNSwgcGluZC5nZXRZKCkgLSAwLjUpO1xuICAgICAgICAgICAgLy8gRXhwYW5kIHRoZSBzcXVhcmUgc28gdGhhdCBpdHMgY29ybmVycyBhcmUgdGhlIGNlbnRlcnMgb2YgdGhlIHBvaW50c1xuICAgICAgICAgICAgLy8ganVzdCBvdXRzaWRlIHRoZSBidWxsJ3MgZXllLlxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXhwYW5kU3F1YXJlKFtwaW5heCwgcGluYngsIHBpbmN4LCBwaW5keF0sIDIgKiB0aGlzLm5iQ2VudGVyTGF5ZXJzIC0gMywgMiAqIHRoaXMubmJDZW50ZXJMYXllcnMpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBGaW5kcyBhIGNhbmRpZGF0ZSBjZW50ZXIgcG9pbnQgb2YgYW4gQXp0ZWMgY29kZSBmcm9tIGFuIGltYWdlXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gdGhlIGNlbnRlciBwb2ludFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0TWF0cml4Q2VudGVyKCkge1xuICAgICAgICAgICAgbGV0IHBvaW50QTtcbiAgICAgICAgICAgIGxldCBwb2ludEI7XG4gICAgICAgICAgICBsZXQgcG9pbnRDO1xuICAgICAgICAgICAgbGV0IHBvaW50RDtcbiAgICAgICAgICAgIC8vIEdldCBhIHdoaXRlIHJlY3RhbmdsZSB0aGF0IGNhbiBiZSB0aGUgYm9yZGVyIG9mIHRoZSBtYXRyaXggaW4gY2VudGVyIGJ1bGwncyBleWUgb3JcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbGV0IGNvcm5lclBvaW50cyA9IG5ldyBXaGl0ZVJlY3RhbmdsZURldGVjdG9yKHRoaXMuaW1hZ2UpLmRldGVjdCgpO1xuICAgICAgICAgICAgICAgIHBvaW50QSA9IGNvcm5lclBvaW50c1swXTtcbiAgICAgICAgICAgICAgICBwb2ludEIgPSBjb3JuZXJQb2ludHNbMV07XG4gICAgICAgICAgICAgICAgcG9pbnRDID0gY29ybmVyUG9pbnRzWzJdO1xuICAgICAgICAgICAgICAgIHBvaW50RCA9IGNvcm5lclBvaW50c1szXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBleGNlcHRpb24gY2FuIGJlIGluIGNhc2UgdGhlIGluaXRpYWwgcmVjdGFuZ2xlIGlzIHdoaXRlXG4gICAgICAgICAgICAgICAgLy8gSW4gdGhhdCBjYXNlLCBzdXJlbHkgaW4gdGhlIGJ1bGwncyBleWUsIHdlIHRyeSB0byBleHBhbmQgdGhlIHJlY3RhbmdsZS5cbiAgICAgICAgICAgICAgICBsZXQgY3ggPSB0aGlzLmltYWdlLmdldFdpZHRoKCkgLyAyO1xuICAgICAgICAgICAgICAgIGxldCBjeSA9IHRoaXMuaW1hZ2UuZ2V0SGVpZ2h0KCkgLyAyO1xuICAgICAgICAgICAgICAgIHBvaW50QSA9IHRoaXMuZ2V0Rmlyc3REaWZmZXJlbnQobmV3IFBvaW50KGN4ICsgNywgY3kgLSA3KSwgZmFsc2UsIDEsIC0xKS50b1Jlc3VsdFBvaW50KCk7XG4gICAgICAgICAgICAgICAgcG9pbnRCID0gdGhpcy5nZXRGaXJzdERpZmZlcmVudChuZXcgUG9pbnQoY3ggKyA3LCBjeSArIDcpLCBmYWxzZSwgMSwgMSkudG9SZXN1bHRQb2ludCgpO1xuICAgICAgICAgICAgICAgIHBvaW50QyA9IHRoaXMuZ2V0Rmlyc3REaWZmZXJlbnQobmV3IFBvaW50KGN4IC0gNywgY3kgKyA3KSwgZmFsc2UsIC0xLCAxKS50b1Jlc3VsdFBvaW50KCk7XG4gICAgICAgICAgICAgICAgcG9pbnREID0gdGhpcy5nZXRGaXJzdERpZmZlcmVudChuZXcgUG9pbnQoY3ggLSA3LCBjeSAtIDcpLCBmYWxzZSwgLTEsIC0xKS50b1Jlc3VsdFBvaW50KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBDb21wdXRlIHRoZSBjZW50ZXIgb2YgdGhlIHJlY3RhbmdsZVxuICAgICAgICAgICAgbGV0IGN4ID0gTWF0aFV0aWxzLnJvdW5kKChwb2ludEEuZ2V0WCgpICsgcG9pbnRELmdldFgoKSArIHBvaW50Qi5nZXRYKCkgKyBwb2ludEMuZ2V0WCgpKSAvIDQuMCk7XG4gICAgICAgICAgICBsZXQgY3kgPSBNYXRoVXRpbHMucm91bmQoKHBvaW50QS5nZXRZKCkgKyBwb2ludEQuZ2V0WSgpICsgcG9pbnRCLmdldFkoKSArIHBvaW50Qy5nZXRZKCkpIC8gNC4wKTtcbiAgICAgICAgICAgIC8vIFJlZGV0ZXJtaW5lIHRoZSB3aGl0ZSByZWN0YW5nbGUgc3RhcnRpbmcgZnJvbSBwcmV2aW91c2x5IGNvbXB1dGVkIGNlbnRlci5cbiAgICAgICAgICAgIC8vIFRoaXMgd2lsbCBlbnN1cmUgdGhhdCB3ZSBlbmQgdXAgd2l0aCBhIHdoaXRlIHJlY3RhbmdsZSBpbiBjZW50ZXIgYnVsbCdzIGV5ZVxuICAgICAgICAgICAgLy8gaW4gb3JkZXIgdG8gY29tcHV0ZSBhIG1vcmUgYWNjdXJhdGUgY2VudGVyLlxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBsZXQgY29ybmVyUG9pbnRzID0gbmV3IFdoaXRlUmVjdGFuZ2xlRGV0ZWN0b3IodGhpcy5pbWFnZSwgMTUsIGN4LCBjeSkuZGV0ZWN0KCk7XG4gICAgICAgICAgICAgICAgcG9pbnRBID0gY29ybmVyUG9pbnRzWzBdO1xuICAgICAgICAgICAgICAgIHBvaW50QiA9IGNvcm5lclBvaW50c1sxXTtcbiAgICAgICAgICAgICAgICBwb2ludEMgPSBjb3JuZXJQb2ludHNbMl07XG4gICAgICAgICAgICAgICAgcG9pbnREID0gY29ybmVyUG9pbnRzWzNdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGV4Y2VwdGlvbiBjYW4gYmUgaW4gY2FzZSB0aGUgaW5pdGlhbCByZWN0YW5nbGUgaXMgd2hpdGVcbiAgICAgICAgICAgICAgICAvLyBJbiB0aGF0IGNhc2Ugd2UgdHJ5IHRvIGV4cGFuZCB0aGUgcmVjdGFuZ2xlLlxuICAgICAgICAgICAgICAgIHBvaW50QSA9IHRoaXMuZ2V0Rmlyc3REaWZmZXJlbnQobmV3IFBvaW50KGN4ICsgNywgY3kgLSA3KSwgZmFsc2UsIDEsIC0xKS50b1Jlc3VsdFBvaW50KCk7XG4gICAgICAgICAgICAgICAgcG9pbnRCID0gdGhpcy5nZXRGaXJzdERpZmZlcmVudChuZXcgUG9pbnQoY3ggKyA3LCBjeSArIDcpLCBmYWxzZSwgMSwgMSkudG9SZXN1bHRQb2ludCgpO1xuICAgICAgICAgICAgICAgIHBvaW50QyA9IHRoaXMuZ2V0Rmlyc3REaWZmZXJlbnQobmV3IFBvaW50KGN4IC0gNywgY3kgKyA3KSwgZmFsc2UsIC0xLCAxKS50b1Jlc3VsdFBvaW50KCk7XG4gICAgICAgICAgICAgICAgcG9pbnREID0gdGhpcy5nZXRGaXJzdERpZmZlcmVudChuZXcgUG9pbnQoY3ggLSA3LCBjeSAtIDcpLCBmYWxzZSwgLTEsIC0xKS50b1Jlc3VsdFBvaW50KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBSZWNvbXB1dGUgdGhlIGNlbnRlciBvZiB0aGUgcmVjdGFuZ2xlXG4gICAgICAgICAgICBjeCA9IE1hdGhVdGlscy5yb3VuZCgocG9pbnRBLmdldFgoKSArIHBvaW50RC5nZXRYKCkgKyBwb2ludEIuZ2V0WCgpICsgcG9pbnRDLmdldFgoKSkgLyA0LjApO1xuICAgICAgICAgICAgY3kgPSBNYXRoVXRpbHMucm91bmQoKHBvaW50QS5nZXRZKCkgKyBwb2ludEQuZ2V0WSgpICsgcG9pbnRCLmdldFkoKSArIHBvaW50Qy5nZXRZKCkpIC8gNC4wKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUG9pbnQoY3gsIGN5KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogR2V0cyB0aGUgQXp0ZWMgY29kZSBjb3JuZXJzIGZyb20gdGhlIGJ1bGwncyBleWUgY29ybmVycyBhbmQgdGhlIHBhcmFtZXRlcnMuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBidWxsc0V5ZUNvcm5lcnMgdGhlIGFycmF5IG9mIGJ1bGwncyBleWUgY29ybmVyc1xuICAgICAgICAgKiBAcmV0dXJuIHRoZSBhcnJheSBvZiBhenRlYyBjb2RlIGNvcm5lcnNcbiAgICAgICAgICovXG4gICAgICAgIGdldE1hdHJpeENvcm5lclBvaW50cyhidWxsc0V5ZUNvcm5lcnMpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmV4cGFuZFNxdWFyZShidWxsc0V5ZUNvcm5lcnMsIDIgKiB0aGlzLm5iQ2VudGVyTGF5ZXJzLCB0aGlzLmdldERpbWVuc2lvbigpKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIEJpdE1hdHJpeCBieSBzYW1wbGluZyB0aGUgcHJvdmlkZWQgaW1hZ2UuXG4gICAgICAgICAqIHRvcExlZnQsIHRvcFJpZ2h0LCBib3R0b21SaWdodCwgYW5kIGJvdHRvbUxlZnQgYXJlIHRoZSBjZW50ZXJzIG9mIHRoZSBzcXVhcmVzIG9uIHRoZVxuICAgICAgICAgKiBkaWFnb25hbCBqdXN0IG91dHNpZGUgdGhlIGJ1bGwncyBleWUuXG4gICAgICAgICAqL1xuICAgICAgICBzYW1wbGVHcmlkKGltYWdlLCB0b3BMZWZ0LCB0b3BSaWdodCwgYm90dG9tUmlnaHQsIGJvdHRvbUxlZnQpIHtcbiAgICAgICAgICAgIGxldCBzYW1wbGVyID0gR3JpZFNhbXBsZXJJbnN0YW5jZS5nZXRJbnN0YW5jZSgpO1xuICAgICAgICAgICAgbGV0IGRpbWVuc2lvbiA9IHRoaXMuZ2V0RGltZW5zaW9uKCk7XG4gICAgICAgICAgICBsZXQgbG93ID0gZGltZW5zaW9uIC8gMiAtIHRoaXMubmJDZW50ZXJMYXllcnM7XG4gICAgICAgICAgICBsZXQgaGlnaCA9IGRpbWVuc2lvbiAvIDIgKyB0aGlzLm5iQ2VudGVyTGF5ZXJzO1xuICAgICAgICAgICAgcmV0dXJuIHNhbXBsZXIuc2FtcGxlR3JpZChpbWFnZSwgZGltZW5zaW9uLCBkaW1lbnNpb24sIGxvdywgbG93LCAvLyB0b3BsZWZ0XG4gICAgICAgICAgICBoaWdoLCBsb3csIC8vIHRvcHJpZ2h0XG4gICAgICAgICAgICBoaWdoLCBoaWdoLCAvLyBib3R0b21yaWdodFxuICAgICAgICAgICAgbG93LCBoaWdoLCAvLyBib3R0b21sZWZ0XG4gICAgICAgICAgICB0b3BMZWZ0LmdldFgoKSwgdG9wTGVmdC5nZXRZKCksIHRvcFJpZ2h0LmdldFgoKSwgdG9wUmlnaHQuZ2V0WSgpLCBib3R0b21SaWdodC5nZXRYKCksIGJvdHRvbVJpZ2h0LmdldFkoKSwgYm90dG9tTGVmdC5nZXRYKCksIGJvdHRvbUxlZnQuZ2V0WSgpKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogU2FtcGxlcyBhIGxpbmUuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBwMSAgIHN0YXJ0IHBvaW50IChpbmNsdXNpdmUpXG4gICAgICAgICAqIEBwYXJhbSBwMiAgIGVuZCBwb2ludCAoZXhjbHVzaXZlKVxuICAgICAgICAgKiBAcGFyYW0gc2l6ZSBudW1iZXIgb2YgYml0c1xuICAgICAgICAgKiBAcmV0dXJuIHRoZSBhcnJheSBvZiBiaXRzIGFzIGFuIGludCAoZmlyc3QgYml0IGlzIGhpZ2gtb3JkZXIgYml0IG9mIHJlc3VsdClcbiAgICAgICAgICovXG4gICAgICAgIHNhbXBsZUxpbmUocDEsIHAyLCBzaXplKSB7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gMDtcbiAgICAgICAgICAgIGxldCBkID0gdGhpcy5kaXN0YW5jZVJlc3VsdFBvaW50KHAxLCBwMik7XG4gICAgICAgICAgICBsZXQgbW9kdWxlU2l6ZSA9IGQgLyBzaXplO1xuICAgICAgICAgICAgbGV0IHB4ID0gcDEuZ2V0WCgpO1xuICAgICAgICAgICAgbGV0IHB5ID0gcDEuZ2V0WSgpO1xuICAgICAgICAgICAgbGV0IGR4ID0gbW9kdWxlU2l6ZSAqIChwMi5nZXRYKCkgLSBwMS5nZXRYKCkpIC8gZDtcbiAgICAgICAgICAgIGxldCBkeSA9IG1vZHVsZVNpemUgKiAocDIuZ2V0WSgpIC0gcDEuZ2V0WSgpKSAvIGQ7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmltYWdlLmdldChNYXRoVXRpbHMucm91bmQocHggKyBpICogZHgpLCBNYXRoVXRpbHMucm91bmQocHkgKyBpICogZHkpKSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgfD0gMSA8PCAoc2l6ZSAtIGkgLSAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHRydWUgaWYgdGhlIGJvcmRlciBvZiB0aGUgcmVjdGFuZ2xlIHBhc3NlZCBpbiBwYXJhbWV0ZXIgaXMgY29tcG91bmQgb2Ygd2hpdGUgcG9pbnRzIG9ubHlcbiAgICAgICAgICogICAgICAgICBvciBibGFjayBwb2ludHMgb25seVxuICAgICAgICAgKi9cbiAgICAgICAgaXNXaGl0ZU9yQmxhY2tSZWN0YW5nbGUocDEsIHAyLCBwMywgcDQpIHtcbiAgICAgICAgICAgIGxldCBjb3JyID0gMztcbiAgICAgICAgICAgIHAxID0gbmV3IFBvaW50KHAxLmdldFgoKSAtIGNvcnIsIHAxLmdldFkoKSArIGNvcnIpO1xuICAgICAgICAgICAgcDIgPSBuZXcgUG9pbnQocDIuZ2V0WCgpIC0gY29yciwgcDIuZ2V0WSgpIC0gY29ycik7XG4gICAgICAgICAgICBwMyA9IG5ldyBQb2ludChwMy5nZXRYKCkgKyBjb3JyLCBwMy5nZXRZKCkgLSBjb3JyKTtcbiAgICAgICAgICAgIHA0ID0gbmV3IFBvaW50KHA0LmdldFgoKSArIGNvcnIsIHA0LmdldFkoKSArIGNvcnIpO1xuICAgICAgICAgICAgbGV0IGNJbml0ID0gdGhpcy5nZXRDb2xvcihwNCwgcDEpO1xuICAgICAgICAgICAgaWYgKGNJbml0ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGMgPSB0aGlzLmdldENvbG9yKHAxLCBwMik7XG4gICAgICAgICAgICBpZiAoYyAhPT0gY0luaXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjID0gdGhpcy5nZXRDb2xvcihwMiwgcDMpO1xuICAgICAgICAgICAgaWYgKGMgIT09IGNJbml0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYyA9IHRoaXMuZ2V0Q29sb3IocDMsIHA0KTtcbiAgICAgICAgICAgIHJldHVybiBjID09PSBjSW5pdDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogR2V0cyB0aGUgY29sb3Igb2YgYSBzZWdtZW50XG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gMSBpZiBzZWdtZW50IG1vcmUgdGhhbiA5MCUgYmxhY2ssIC0xIGlmIHNlZ21lbnQgaXMgbW9yZSB0aGFuIDkwJSB3aGl0ZSwgMCBlbHNlXG4gICAgICAgICAqL1xuICAgICAgICBnZXRDb2xvcihwMSwgcDIpIHtcbiAgICAgICAgICAgIGxldCBkID0gdGhpcy5kaXN0YW5jZVBvaW50KHAxLCBwMik7XG4gICAgICAgICAgICBsZXQgZHggPSAocDIuZ2V0WCgpIC0gcDEuZ2V0WCgpKSAvIGQ7XG4gICAgICAgICAgICBsZXQgZHkgPSAocDIuZ2V0WSgpIC0gcDEuZ2V0WSgpKSAvIGQ7XG4gICAgICAgICAgICBsZXQgZXJyb3IgPSAwO1xuICAgICAgICAgICAgbGV0IHB4ID0gcDEuZ2V0WCgpO1xuICAgICAgICAgICAgbGV0IHB5ID0gcDEuZ2V0WSgpO1xuICAgICAgICAgICAgbGV0IGNvbG9yTW9kZWwgPSB0aGlzLmltYWdlLmdldChwMS5nZXRYKCksIHAxLmdldFkoKSk7XG4gICAgICAgICAgICBsZXQgaU1heCA9IE1hdGguY2VpbChkKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaU1heDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcHggKz0gZHg7XG4gICAgICAgICAgICAgICAgcHkgKz0gZHk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaW1hZ2UuZ2V0KE1hdGhVdGlscy5yb3VuZChweCksIE1hdGhVdGlscy5yb3VuZChweSkpICE9PSBjb2xvck1vZGVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGVyclJhdGlvID0gZXJyb3IgLyBkO1xuICAgICAgICAgICAgaWYgKGVyclJhdGlvID4gMC4xICYmIGVyclJhdGlvIDwgMC45KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gKGVyclJhdGlvIDw9IDAuMSkgPT09IGNvbG9yTW9kZWwgPyAxIDogLTE7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdldHMgdGhlIGNvb3JkaW5hdGUgb2YgdGhlIGZpcnN0IHBvaW50IHdpdGggYSBkaWZmZXJlbnQgY29sb3IgaW4gdGhlIGdpdmVuIGRpcmVjdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0Rmlyc3REaWZmZXJlbnQoaW5pdCwgY29sb3IsIGR4LCBkeSkge1xuICAgICAgICAgICAgbGV0IHggPSBpbml0LmdldFgoKSArIGR4O1xuICAgICAgICAgICAgbGV0IHkgPSBpbml0LmdldFkoKSArIGR5O1xuICAgICAgICAgICAgd2hpbGUgKHRoaXMuaXNWYWxpZCh4LCB5KSAmJiB0aGlzLmltYWdlLmdldCh4LCB5KSA9PT0gY29sb3IpIHtcbiAgICAgICAgICAgICAgICB4ICs9IGR4O1xuICAgICAgICAgICAgICAgIHkgKz0gZHk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB4IC09IGR4O1xuICAgICAgICAgICAgeSAtPSBkeTtcbiAgICAgICAgICAgIHdoaWxlICh0aGlzLmlzVmFsaWQoeCwgeSkgJiYgdGhpcy5pbWFnZS5nZXQoeCwgeSkgPT09IGNvbG9yKSB7XG4gICAgICAgICAgICAgICAgeCArPSBkeDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHggLT0gZHg7XG4gICAgICAgICAgICB3aGlsZSAodGhpcy5pc1ZhbGlkKHgsIHkpICYmIHRoaXMuaW1hZ2UuZ2V0KHgsIHkpID09PSBjb2xvcikge1xuICAgICAgICAgICAgICAgIHkgKz0gZHk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB5IC09IGR5O1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQb2ludCh4LCB5KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRXhwYW5kIHRoZSBzcXVhcmUgcmVwcmVzZW50ZWQgYnkgdGhlIGNvcm5lciBwb2ludHMgYnkgcHVzaGluZyBvdXQgZXF1YWxseSBpbiBhbGwgZGlyZWN0aW9uc1xuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gY29ybmVyUG9pbnRzIHRoZSBjb3JuZXJzIG9mIHRoZSBzcXVhcmUsIHdoaWNoIGhhcyB0aGUgYnVsbCdzIGV5ZSBhdCBpdHMgY2VudGVyXG4gICAgICAgICAqIEBwYXJhbSBvbGRTaWRlIHRoZSBvcmlnaW5hbCBsZW5ndGggb2YgdGhlIHNpZGUgb2YgdGhlIHNxdWFyZSBpbiB0aGUgdGFyZ2V0IGJpdCBtYXRyaXhcbiAgICAgICAgICogQHBhcmFtIG5ld1NpZGUgdGhlIG5ldyBsZW5ndGggb2YgdGhlIHNpemUgb2YgdGhlIHNxdWFyZSBpbiB0aGUgdGFyZ2V0IGJpdCBtYXRyaXhcbiAgICAgICAgICogQHJldHVybiB0aGUgY29ybmVycyBvZiB0aGUgZXhwYW5kZWQgc3F1YXJlXG4gICAgICAgICAqL1xuICAgICAgICBleHBhbmRTcXVhcmUoY29ybmVyUG9pbnRzLCBvbGRTaWRlLCBuZXdTaWRlKSB7XG4gICAgICAgICAgICBsZXQgcmF0aW8gPSBuZXdTaWRlIC8gKDIuMCAqIG9sZFNpZGUpO1xuICAgICAgICAgICAgbGV0IGR4ID0gY29ybmVyUG9pbnRzWzBdLmdldFgoKSAtIGNvcm5lclBvaW50c1syXS5nZXRYKCk7XG4gICAgICAgICAgICBsZXQgZHkgPSBjb3JuZXJQb2ludHNbMF0uZ2V0WSgpIC0gY29ybmVyUG9pbnRzWzJdLmdldFkoKTtcbiAgICAgICAgICAgIGxldCBjZW50ZXJ4ID0gKGNvcm5lclBvaW50c1swXS5nZXRYKCkgKyBjb3JuZXJQb2ludHNbMl0uZ2V0WCgpKSAvIDIuMDtcbiAgICAgICAgICAgIGxldCBjZW50ZXJ5ID0gKGNvcm5lclBvaW50c1swXS5nZXRZKCkgKyBjb3JuZXJQb2ludHNbMl0uZ2V0WSgpKSAvIDIuMDtcbiAgICAgICAgICAgIGxldCByZXN1bHQwID0gbmV3IFJlc3VsdFBvaW50KGNlbnRlcnggKyByYXRpbyAqIGR4LCBjZW50ZXJ5ICsgcmF0aW8gKiBkeSk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0MiA9IG5ldyBSZXN1bHRQb2ludChjZW50ZXJ4IC0gcmF0aW8gKiBkeCwgY2VudGVyeSAtIHJhdGlvICogZHkpO1xuICAgICAgICAgICAgZHggPSBjb3JuZXJQb2ludHNbMV0uZ2V0WCgpIC0gY29ybmVyUG9pbnRzWzNdLmdldFgoKTtcbiAgICAgICAgICAgIGR5ID0gY29ybmVyUG9pbnRzWzFdLmdldFkoKSAtIGNvcm5lclBvaW50c1szXS5nZXRZKCk7XG4gICAgICAgICAgICBjZW50ZXJ4ID0gKGNvcm5lclBvaW50c1sxXS5nZXRYKCkgKyBjb3JuZXJQb2ludHNbM10uZ2V0WCgpKSAvIDIuMDtcbiAgICAgICAgICAgIGNlbnRlcnkgPSAoY29ybmVyUG9pbnRzWzFdLmdldFkoKSArIGNvcm5lclBvaW50c1szXS5nZXRZKCkpIC8gMi4wO1xuICAgICAgICAgICAgbGV0IHJlc3VsdDEgPSBuZXcgUmVzdWx0UG9pbnQoY2VudGVyeCArIHJhdGlvICogZHgsIGNlbnRlcnkgKyByYXRpbyAqIGR5KTtcbiAgICAgICAgICAgIGxldCByZXN1bHQzID0gbmV3IFJlc3VsdFBvaW50KGNlbnRlcnggLSByYXRpbyAqIGR4LCBjZW50ZXJ5IC0gcmF0aW8gKiBkeSk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0cyA9IFtyZXN1bHQwLCByZXN1bHQxLCByZXN1bHQyLCByZXN1bHQzXTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHRzO1xuICAgICAgICB9XG4gICAgICAgIGlzVmFsaWQoeCwgeSkge1xuICAgICAgICAgICAgcmV0dXJuIHggPj0gMCAmJiB4IDwgdGhpcy5pbWFnZS5nZXRXaWR0aCgpICYmIHkgPiAwICYmIHkgPCB0aGlzLmltYWdlLmdldEhlaWdodCgpO1xuICAgICAgICB9XG4gICAgICAgIGlzVmFsaWRQb2ludChwb2ludCkge1xuICAgICAgICAgICAgbGV0IHggPSBNYXRoVXRpbHMucm91bmQocG9pbnQuZ2V0WCgpKTtcbiAgICAgICAgICAgIGxldCB5ID0gTWF0aFV0aWxzLnJvdW5kKHBvaW50LmdldFkoKSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5pc1ZhbGlkKHgsIHkpO1xuICAgICAgICB9XG4gICAgICAgIGRpc3RhbmNlUG9pbnQoYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGhVdGlscy5kaXN0YW5jZShhLmdldFgoKSwgYS5nZXRZKCksIGIuZ2V0WCgpLCBiLmdldFkoKSk7XG4gICAgICAgIH1cbiAgICAgICAgZGlzdGFuY2VSZXN1bHRQb2ludChhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aFV0aWxzLmRpc3RhbmNlKGEuZ2V0WCgpLCBhLmdldFkoKSwgYi5nZXRYKCksIGIuZ2V0WSgpKTtcbiAgICAgICAgfVxuICAgICAgICBnZXREaW1lbnNpb24oKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5jb21wYWN0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDQgKiB0aGlzLm5iTGF5ZXJzICsgMTE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5uYkxheWVycyA8PSA0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDQgKiB0aGlzLm5iTGF5ZXJzICsgMTU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gNCAqIHRoaXMubmJMYXllcnMgKyAyICogKEludGVnZXIudHJ1bmNEaXZpc2lvbigodGhpcy5uYkxheWVycyAtIDQpLCA4KSArIDEpICsgMTU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDEwIFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8vIGltcG9ydCBqYXZhLnV0aWwuTGlzdDtcbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLk1hcDtcbiAgICAvKipcbiAgICAgKiBUaGlzIGltcGxlbWVudGF0aW9uIGNhbiBkZXRlY3QgYW5kIGRlY29kZSBBenRlYyBjb2RlcyBpbiBhbiBpbWFnZS5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgRGF2aWQgT2xpdmllclxuICAgICAqL1xuICAgIGNsYXNzIEF6dGVjUmVhZGVyIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIExvY2F0ZXMgYW5kIGRlY29kZXMgYSBEYXRhIE1hdHJpeCBjb2RlIGluIGFuIGltYWdlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIGEgU3RyaW5nIHJlcHJlc2VudGluZyB0aGUgY29udGVudCBlbmNvZGVkIGJ5IHRoZSBEYXRhIE1hdHJpeCBjb2RlXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gaWYgYSBEYXRhIE1hdHJpeCBjb2RlIGNhbm5vdCBiZSBmb3VuZFxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvbiBpZiBhIERhdGEgTWF0cml4IGNvZGUgY2Fubm90IGJlIGRlY29kZWRcbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZShpbWFnZSwgaGludHMgPSBudWxsKSB7XG4gICAgICAgICAgICBsZXQgZXhjZXB0aW9uID0gbnVsbDtcbiAgICAgICAgICAgIGxldCBkZXRlY3RvciA9IG5ldyBEZXRlY3RvcihpbWFnZS5nZXRCbGFja01hdHJpeCgpKTtcbiAgICAgICAgICAgIGxldCBwb2ludHMgPSBudWxsO1xuICAgICAgICAgICAgbGV0IGRlY29kZXJSZXN1bHQgPSBudWxsO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBsZXQgZGV0ZWN0b3JSZXN1bHQgPSBkZXRlY3Rvci5kZXRlY3RNaXJyb3IoZmFsc2UpO1xuICAgICAgICAgICAgICAgIHBvaW50cyA9IGRldGVjdG9yUmVzdWx0LmdldFBvaW50cygpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVwb3J0Rm91bmRSZXN1bHRQb2ludHMoaGludHMsIHBvaW50cyk7XG4gICAgICAgICAgICAgICAgZGVjb2RlclJlc3VsdCA9IG5ldyBEZWNvZGVyKCkuZGVjb2RlKGRldGVjdG9yUmVzdWx0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgZXhjZXB0aW9uID0gZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChkZWNvZGVyUmVzdWx0ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgZGV0ZWN0b3JSZXN1bHQgPSBkZXRlY3Rvci5kZXRlY3RNaXJyb3IodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHBvaW50cyA9IGRldGVjdG9yUmVzdWx0LmdldFBvaW50cygpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlcG9ydEZvdW5kUmVzdWx0UG9pbnRzKGhpbnRzLCBwb2ludHMpO1xuICAgICAgICAgICAgICAgICAgICBkZWNvZGVyUmVzdWx0ID0gbmV3IERlY29kZXIoKS5kZWNvZGUoZGV0ZWN0b3JSZXN1bHQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXhjZXB0aW9uICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGV4Y2VwdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCByZXN1bHQgPSBuZXcgUmVzdWx0KGRlY29kZXJSZXN1bHQuZ2V0VGV4dCgpLCBkZWNvZGVyUmVzdWx0LmdldFJhd0J5dGVzKCksIGRlY29kZXJSZXN1bHQuZ2V0TnVtQml0cygpLCBwb2ludHMsIEJhcmNvZGVGb3JtYXQkMS5BWlRFQywgU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCkpO1xuICAgICAgICAgICAgbGV0IGJ5dGVTZWdtZW50cyA9IGRlY29kZXJSZXN1bHQuZ2V0Qnl0ZVNlZ21lbnRzKCk7XG4gICAgICAgICAgICBpZiAoYnl0ZVNlZ21lbnRzICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQucHV0TWV0YWRhdGEoUmVzdWx0TWV0YWRhdGFUeXBlJDEuQllURV9TRUdNRU5UUywgYnl0ZVNlZ21lbnRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBlY0xldmVsID0gZGVjb2RlclJlc3VsdC5nZXRFQ0xldmVsKCk7XG4gICAgICAgICAgICBpZiAoZWNMZXZlbCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1dE1ldGFkYXRhKFJlc3VsdE1ldGFkYXRhVHlwZSQxLkVSUk9SX0NPUlJFQ1RJT05fTEVWRUwsIGVjTGV2ZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICByZXBvcnRGb3VuZFJlc3VsdFBvaW50cyhoaW50cywgcG9pbnRzKSB7XG4gICAgICAgICAgICBpZiAoaGludHMgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGxldCBycGNiID0gaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuTkVFRF9SRVNVTFRfUE9JTlRfQ0FMTEJBQ0spO1xuICAgICAgICAgICAgICAgIGlmIChycGNiICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcG9pbnRzLmZvckVhY2goKHBvaW50LCBpZHgsIGFycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcnBjYi5mb3VuZFBvc3NpYmxlUmVzdWx0UG9pbnQocG9pbnQpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIHJlc2V0KCkge1xuICAgICAgICAgICAgLy8gZG8gbm90aGluZ1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXp0ZWMgQ29kZSByZWFkZXIgdG8gdXNlIGZyb20gYnJvd3Nlci5cbiAgICAgKlxuICAgICAqIEBjbGFzcyBCcm93c2VyQXp0ZWNDb2RlUmVhZGVyXG4gICAgICogQGV4dGVuZHMge0Jyb3dzZXJDb2RlUmVhZGVyfVxuICAgICAqL1xuICAgIGNsYXNzIEJyb3dzZXJBenRlY0NvZGVSZWFkZXIgZXh0ZW5kcyBCcm93c2VyQ29kZVJlYWRlciB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIEJyb3dzZXJBenRlY0NvZGVSZWFkZXIuXG4gICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbdGltZUJldHdlZW5TY2Fuc01pbGxpcz01MDBdIHRoZSB0aW1lIGRlbGF5IGJldHdlZW4gc3Vic2VxdWVudCBkZWNvZGUgdHJpZXNcbiAgICAgICAgICpcbiAgICAgICAgICogQG1lbWJlck9mIEJyb3dzZXJBenRlY0NvZGVSZWFkZXJcbiAgICAgICAgICovXG4gICAgICAgIGNvbnN0cnVjdG9yKHRpbWVCZXR3ZWVuU2NhbnNNaWxsaXMgPSA1MDApIHtcbiAgICAgICAgICAgIHN1cGVyKG5ldyBBenRlY1JlYWRlcigpLCB0aW1lQmV0d2VlblNjYW5zTWlsbGlzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVuY2Fwc3VsYXRlcyBmdW5jdGlvbmFsaXR5IGFuZCBpbXBsZW1lbnRhdGlvbiB0aGF0IGlzIGNvbW1vbiB0byBhbGwgZmFtaWxpZXNcbiAgICAgKiBvZiBvbmUtZGltZW5zaW9uYWwgYmFyY29kZXMuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIGRzd2l0a2luQGdvb2dsZS5jb20gKERhbmllbCBTd2l0a2luKVxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgT25lRFJlYWRlciB7XG4gICAgICAgIC8qXG4gICAgICAgIEBPdmVycmlkZVxuICAgICAgICBwdWJsaWMgUmVzdWx0IGRlY29kZShCaW5hcnlCaXRtYXAgaW1hZ2UpIHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiwgRm9ybWF0RXhjZXB0aW9uIHtcbiAgICAgICAgICByZXR1cm4gZGVjb2RlKGltYWdlLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgICAqL1xuICAgICAgICAvLyBOb3RlIHRoYXQgd2UgZG9uJ3QgdHJ5IHJvdGF0aW9uIHdpdGhvdXQgdGhlIHRyeSBoYXJkZXIgZmxhZywgZXZlbiBpZiByb3RhdGlvbiB3YXMgc3VwcG9ydGVkLlxuICAgICAgICAvLyBAT3ZlcnJpZGVcbiAgICAgICAgZGVjb2RlKGltYWdlLCBoaW50cykge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5kb0RlY29kZShpbWFnZSwgaGludHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKG5mZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHRyeUhhcmRlciA9IGhpbnRzICYmIChoaW50cy5nZXQoRGVjb2RlSGludFR5cGUkMS5UUllfSEFSREVSKSA9PT0gdHJ1ZSk7XG4gICAgICAgICAgICAgICAgaWYgKHRyeUhhcmRlciAmJiBpbWFnZS5pc1JvdGF0ZVN1cHBvcnRlZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJvdGF0ZWRJbWFnZSA9IGltYWdlLnJvdGF0ZUNvdW50ZXJDbG9ja3dpc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5kb0RlY29kZShyb3RhdGVkSW1hZ2UsIGhpbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVjb3JkIHRoYXQgd2UgZm91bmQgaXQgcm90YXRlZCA5MCBkZWdyZWVzIENDVyAvIDI3MCBkZWdyZWVzIENXXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldGFkYXRhID0gcmVzdWx0LmdldFJlc3VsdE1ldGFkYXRhKCk7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvcmllbnRhdGlvbiA9IDI3MDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1ldGFkYXRhICE9PSBudWxsICYmIChtZXRhZGF0YS5nZXQoUmVzdWx0TWV0YWRhdGFUeXBlJDEuT1JJRU5UQVRJT04pID09PSB0cnVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQnV0IGlmIHdlIGZvdW5kIGl0IHJldmVyc2VkIGluIGRvRGVjb2RlKCksIGFkZCBpbiB0aGF0IHJlc3VsdCBoZXJlOlxuICAgICAgICAgICAgICAgICAgICAgICAgb3JpZW50YXRpb24gPSAob3JpZW50YXRpb24gKyBtZXRhZGF0YS5nZXQoUmVzdWx0TWV0YWRhdGFUeXBlJDEuT1JJRU5UQVRJT04pICUgMzYwKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHV0TWV0YWRhdGEoUmVzdWx0TWV0YWRhdGFUeXBlJDEuT1JJRU5UQVRJT04sIG9yaWVudGF0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gVXBkYXRlIHJlc3VsdCBwb2ludHNcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9pbnRzID0gcmVzdWx0LmdldFJlc3VsdFBvaW50cygpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocG9pbnRzICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWlnaHQgPSByb3RhdGVkSW1hZ2UuZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBvaW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50c1tpXSA9IG5ldyBSZXN1bHRQb2ludChoZWlnaHQgLSBwb2ludHNbaV0uZ2V0WSgpIC0gMSwgcG9pbnRzW2ldLmdldFgoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBAT3ZlcnJpZGVcbiAgICAgICAgcmVzZXQoKSB7XG4gICAgICAgICAgICAvLyBkbyBub3RoaW5nXG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdlJ3JlIGdvaW5nIHRvIGV4YW1pbmUgcm93cyBmcm9tIHRoZSBtaWRkbGUgb3V0d2FyZCwgc2VhcmNoaW5nIGFsdGVybmF0ZWx5IGFib3ZlIGFuZCBiZWxvdyB0aGVcbiAgICAgICAgICogbWlkZGxlLCBhbmQgZmFydGhlciBvdXQgZWFjaCB0aW1lLiByb3dTdGVwIGlzIHRoZSBudW1iZXIgb2Ygcm93cyBiZXR3ZWVuIGVhY2ggc3VjY2Vzc2l2ZVxuICAgICAgICAgKiBhdHRlbXB0IGFib3ZlIGFuZCBiZWxvdyB0aGUgbWlkZGxlLiBTbyB3ZSdkIHNjYW4gcm93IG1pZGRsZSwgdGhlbiBtaWRkbGUgLSByb3dTdGVwLCB0aGVuXG4gICAgICAgICAqIG1pZGRsZSArIHJvd1N0ZXAsIHRoZW4gbWlkZGxlIC0gKDIgKiByb3dTdGVwKSwgZXRjLlxuICAgICAgICAgKiByb3dTdGVwIGlzIGJpZ2dlciBhcyB0aGUgaW1hZ2UgaXMgdGFsbGVyLCBidXQgaXMgYWx3YXlzIGF0IGxlYXN0IDEuIFdlJ3ZlIHNvbWV3aGF0IGFyYml0cmFyaWx5XG4gICAgICAgICAqIGRlY2lkZWQgdGhhdCBtb3ZpbmcgdXAgYW5kIGRvd24gYnkgYWJvdXQgMS8xNiBvZiB0aGUgaW1hZ2UgaXMgcHJldHR5IGdvb2Q7IHdlIHRyeSBtb3JlIG9mIHRoZVxuICAgICAgICAgKiBpbWFnZSBpZiBcInRyeWluZyBoYXJkZXJcIi5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGltYWdlIFRoZSBpbWFnZSB0byBkZWNvZGVcbiAgICAgICAgICogQHBhcmFtIGhpbnRzIEFueSBoaW50cyB0aGF0IHdlcmUgcmVxdWVzdGVkXG4gICAgICAgICAqIEByZXR1cm4gVGhlIGNvbnRlbnRzIG9mIHRoZSBkZWNvZGVkIGJhcmNvZGVcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBBbnkgc3BvbnRhbmVvdXMgZXJyb3JzIHdoaWNoIG9jY3VyXG4gICAgICAgICAqL1xuICAgICAgICBkb0RlY29kZShpbWFnZSwgaGludHMpIHtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gaW1hZ2UuZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IGltYWdlLmdldEhlaWdodCgpO1xuICAgICAgICAgICAgbGV0IHJvdyA9IG5ldyBCaXRBcnJheSh3aWR0aCk7XG4gICAgICAgICAgICBjb25zdCB0cnlIYXJkZXIgPSBoaW50cyAmJiAoaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuVFJZX0hBUkRFUikgPT09IHRydWUpO1xuICAgICAgICAgICAgY29uc3Qgcm93U3RlcCA9IE1hdGgubWF4KDEsIGhlaWdodCA+PiAodHJ5SGFyZGVyID8gOCA6IDUpKTtcbiAgICAgICAgICAgIGxldCBtYXhMaW5lcztcbiAgICAgICAgICAgIGlmICh0cnlIYXJkZXIpIHtcbiAgICAgICAgICAgICAgICBtYXhMaW5lcyA9IGhlaWdodDsgLy8gTG9vayBhdCB0aGUgd2hvbGUgaW1hZ2UsIG5vdCBqdXN0IHRoZSBjZW50ZXJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG1heExpbmVzID0gMTU7IC8vIDE1IHJvd3Mgc3BhY2VkIDEvMzIgYXBhcnQgaXMgcm91Z2hseSB0aGUgbWlkZGxlIGhhbGYgb2YgdGhlIGltYWdlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBtaWRkbGUgPSBNYXRoLnRydW5jKGhlaWdodCAvIDIpO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCBtYXhMaW5lczsgeCsrKSB7XG4gICAgICAgICAgICAgICAgLy8gU2Nhbm5pbmcgZnJvbSB0aGUgbWlkZGxlIG91dC4gRGV0ZXJtaW5lIHdoaWNoIHJvdyB3ZSdyZSBsb29raW5nIGF0IG5leHQ6XG4gICAgICAgICAgICAgICAgY29uc3Qgcm93U3RlcHNBYm92ZU9yQmVsb3cgPSBNYXRoLnRydW5jKCh4ICsgMSkgLyAyKTtcbiAgICAgICAgICAgICAgICBjb25zdCBpc0Fib3ZlID0gKHggJiAweDAxKSA9PT0gMDsgLy8gaS5lLiBpcyB4IGV2ZW4/XG4gICAgICAgICAgICAgICAgY29uc3Qgcm93TnVtYmVyID0gbWlkZGxlICsgcm93U3RlcCAqIChpc0Fib3ZlID8gcm93U3RlcHNBYm92ZU9yQmVsb3cgOiAtcm93U3RlcHNBYm92ZU9yQmVsb3cpO1xuICAgICAgICAgICAgICAgIGlmIChyb3dOdW1iZXIgPCAwIHx8IHJvd051bWJlciA+PSBoZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gT29wcywgaWYgd2UgcnVuIG9mZiB0aGUgdG9wIG9yIGJvdHRvbSwgc3RvcFxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gRXN0aW1hdGUgYmxhY2sgcG9pbnQgZm9yIHRoaXMgcm93IGFuZCBsb2FkIGl0OlxuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJvdyA9IGltYWdlLmdldEJsYWNrUm93KHJvd051bWJlciwgcm93KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKGlnbm9yZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIFdoaWxlIHdlIGhhdmUgdGhlIGltYWdlIGRhdGEgaW4gYSBCaXRBcnJheSwgaXQncyBmYWlybHkgY2hlYXAgdG8gcmV2ZXJzZSBpdCBpbiBwbGFjZSB0b1xuICAgICAgICAgICAgICAgIC8vIGhhbmRsZSBkZWNvZGluZyB1cHNpZGUgZG93biBiYXJjb2Rlcy5cbiAgICAgICAgICAgICAgICBmb3IgKGxldCBhdHRlbXB0ID0gMDsgYXR0ZW1wdCA8IDI7IGF0dGVtcHQrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoYXR0ZW1wdCA9PT0gMSkgeyAvLyB0cnlpbmcgYWdhaW4/XG4gICAgICAgICAgICAgICAgICAgICAgICByb3cucmV2ZXJzZSgpOyAvLyByZXZlcnNlIHRoZSByb3cgYW5kIGNvbnRpbnVlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIG1lYW5zIHdlIHdpbGwgb25seSBldmVyIGRyYXcgcmVzdWx0IHBvaW50cyAqb25jZSogaW4gdGhlIGxpZmUgb2YgdGhpcyBtZXRob2RcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNpbmNlIHdlIHdhbnQgdG8gYXZvaWQgZHJhd2luZyB0aGUgd3JvbmcgcG9pbnRzIGFmdGVyIGZsaXBwaW5nIHRoZSByb3csIGFuZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRvbid0IHdhbnQgdG8gY2x1dHRlciB3aXRoIG5vaXNlIGZyb20gZXZlcnkgc2luZ2xlIHJvdyBzY2FuIC0tIGp1c3QgdGhlIHNjYW5zXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGF0IHN0YXJ0IG9uIHRoZSBjZW50ZXIgbGluZS5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChoaW50cyAmJiAoaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuTkVFRF9SRVNVTFRfUE9JTlRfQ0FMTEJBQ0spID09PSB0cnVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld0hpbnRzID0gbmV3IE1hcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpbnRzLmZvckVhY2goKGhpbnQsIGtleSkgPT4gbmV3SGludHMuc2V0KGtleSwgaGludCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0hpbnRzLmRlbGV0ZShEZWNvZGVIaW50VHlwZSQxLk5FRURfUkVTVUxUX1BPSU5UX0NBTExCQUNLKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaW50cyA9IG5ld0hpbnRzO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBMb29rIGZvciBhIGJhcmNvZGVcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuZGVjb2RlUm93KHJvd051bWJlciwgcm93LCBoaW50cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBmb3VuZCBvdXIgYmFyY29kZVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dGVtcHQgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBCdXQgaXQgd2FzIHVwc2lkZSBkb3duLCBzbyBub3RlIHRoYXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHV0TWV0YWRhdGEoUmVzdWx0TWV0YWRhdGFUeXBlJDEuT1JJRU5UQVRJT04sIDE4MCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQW5kIHJlbWVtYmVyIHRvIGZsaXAgdGhlIHJlc3VsdCBwb2ludHMgaG9yaXpvbnRhbGx5LlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvaW50cyA9IHJlc3VsdC5nZXRSZXN1bHRQb2ludHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocG9pbnRzICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50c1swXSA9IG5ldyBSZXN1bHRQb2ludCh3aWR0aCAtIHBvaW50c1swXS5nZXRYKCkgLSAxLCBwb2ludHNbMF0uZ2V0WSgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRzWzFdID0gbmV3IFJlc3VsdFBvaW50KHdpZHRoIC0gcG9pbnRzWzFdLmdldFgoKSAtIDEsIHBvaW50c1sxXS5nZXRZKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY2F0Y2ggKHJlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb250aW51ZSAtLSBqdXN0IGNvdWxkbid0IGRlY29kZSB0aGlzIHJvd1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJlY29yZHMgdGhlIHNpemUgb2Ygc3VjY2Vzc2l2ZSBydW5zIG9mIHdoaXRlIGFuZCBibGFjayBwaXhlbHMgaW4gYSByb3csIHN0YXJ0aW5nIGF0IGEgZ2l2ZW4gcG9pbnQuXG4gICAgICAgICAqIFRoZSB2YWx1ZXMgYXJlIHJlY29yZGVkIGluIHRoZSBnaXZlbiBhcnJheSwgYW5kIHRoZSBudW1iZXIgb2YgcnVucyByZWNvcmRlZCBpcyBlcXVhbCB0byB0aGUgc2l6ZVxuICAgICAgICAgKiBvZiB0aGUgYXJyYXkuIElmIHRoZSByb3cgc3RhcnRzIG9uIGEgd2hpdGUgcGl4ZWwgYXQgdGhlIGdpdmVuIHN0YXJ0IHBvaW50LCB0aGVuIHRoZSBmaXJzdCBjb3VudFxuICAgICAgICAgKiByZWNvcmRlZCBpcyB0aGUgcnVuIG9mIHdoaXRlIHBpeGVscyBzdGFydGluZyBmcm9tIHRoYXQgcG9pbnQ7IGxpa2V3aXNlIGl0IGlzIHRoZSBjb3VudCBvZiBhIHJ1blxuICAgICAgICAgKiBvZiBibGFjayBwaXhlbHMgaWYgdGhlIHJvdyBiZWdpbiBvbiBhIGJsYWNrIHBpeGVscyBhdCB0aGF0IHBvaW50LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gcm93IHJvdyB0byBjb3VudCBmcm9tXG4gICAgICAgICAqIEBwYXJhbSBzdGFydCBvZmZzZXQgaW50byByb3cgdG8gc3RhcnQgYXRcbiAgICAgICAgICogQHBhcmFtIGNvdW50ZXJzIGFycmF5IGludG8gd2hpY2ggdG8gcmVjb3JkIGNvdW50c1xuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIGNvdW50ZXJzIGNhbm5vdCBiZSBmaWxsZWQgZW50aXJlbHkgZnJvbSByb3cgYmVmb3JlIHJ1bm5pbmcgb3V0XG4gICAgICAgICAqICBvZiBwaXhlbHNcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyByZWNvcmRQYXR0ZXJuKHJvdywgc3RhcnQsIGNvdW50ZXJzKSB7XG4gICAgICAgICAgICBjb25zdCBudW1Db3VudGVycyA9IGNvdW50ZXJzLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBudW1Db3VudGVyczsgaW5kZXgrKylcbiAgICAgICAgICAgICAgICBjb3VudGVyc1tpbmRleF0gPSAwO1xuICAgICAgICAgICAgY29uc3QgZW5kID0gcm93LmdldFNpemUoKTtcbiAgICAgICAgICAgIGlmIChzdGFydCA+PSBlbmQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBpc1doaXRlID0gIXJvdy5nZXQoc3RhcnQpO1xuICAgICAgICAgICAgbGV0IGNvdW50ZXJQb3NpdGlvbiA9IDA7XG4gICAgICAgICAgICBsZXQgaSA9IHN0YXJ0O1xuICAgICAgICAgICAgd2hpbGUgKGkgPCBlbmQpIHtcbiAgICAgICAgICAgICAgICBpZiAocm93LmdldChpKSAhPT0gaXNXaGl0ZSkge1xuICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb25dKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoKytjb3VudGVyUG9zaXRpb24gPT09IG51bUNvdW50ZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbl0gPSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNXaGl0ZSA9ICFpc1doaXRlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIElmIHdlIHJlYWQgZnVsbHkgdGhlIGxhc3Qgc2VjdGlvbiBvZiBwaXhlbHMgYW5kIGZpbGxlZCB1cCBvdXIgY291bnRlcnMgLS0gb3IgZmlsbGVkXG4gICAgICAgICAgICAvLyB0aGUgbGFzdCBjb3VudGVyIGJ1dCByYW4gb2ZmIHRoZSBzaWRlIG9mIHRoZSBpbWFnZSwgT0suIE90aGVyd2lzZSwgYSBwcm9ibGVtLlxuICAgICAgICAgICAgaWYgKCEoY291bnRlclBvc2l0aW9uID09PSBudW1Db3VudGVycyB8fCAoY291bnRlclBvc2l0aW9uID09PSBudW1Db3VudGVycyAtIDEgJiYgaSA9PT0gZW5kKSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgcmVjb3JkUGF0dGVybkluUmV2ZXJzZShyb3csIHN0YXJ0LCBjb3VudGVycykge1xuICAgICAgICAgICAgLy8gVGhpcyBjb3VsZCBiZSBtb3JlIGVmZmljaWVudCBJIGd1ZXNzXG4gICAgICAgICAgICBsZXQgbnVtVHJhbnNpdGlvbnNMZWZ0ID0gY291bnRlcnMubGVuZ3RoO1xuICAgICAgICAgICAgbGV0IGxhc3QgPSByb3cuZ2V0KHN0YXJ0KTtcbiAgICAgICAgICAgIHdoaWxlIChzdGFydCA+IDAgJiYgbnVtVHJhbnNpdGlvbnNMZWZ0ID49IDApIHtcbiAgICAgICAgICAgICAgICBpZiAocm93LmdldCgtLXN0YXJ0KSAhPT0gbGFzdCkge1xuICAgICAgICAgICAgICAgICAgICBudW1UcmFuc2l0aW9uc0xlZnQtLTtcbiAgICAgICAgICAgICAgICAgICAgbGFzdCA9ICFsYXN0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChudW1UcmFuc2l0aW9uc0xlZnQgPj0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgT25lRFJlYWRlci5yZWNvcmRQYXR0ZXJuKHJvdywgc3RhcnQgKyAxLCBjb3VudGVycyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERldGVybWluZXMgaG93IGNsb3NlbHkgYSBzZXQgb2Ygb2JzZXJ2ZWQgY291bnRzIG9mIHJ1bnMgb2YgYmxhY2svd2hpdGUgdmFsdWVzIG1hdGNoZXMgYSBnaXZlblxuICAgICAgICAgKiB0YXJnZXQgcGF0dGVybi4gVGhpcyBpcyByZXBvcnRlZCBhcyB0aGUgcmF0aW8gb2YgdGhlIHRvdGFsIHZhcmlhbmNlIGZyb20gdGhlIGV4cGVjdGVkIHBhdHRlcm5cbiAgICAgICAgICogcHJvcG9ydGlvbnMgYWNyb3NzIGFsbCBwYXR0ZXJuIGVsZW1lbnRzLCB0byB0aGUgbGVuZ3RoIG9mIHRoZSBwYXR0ZXJuLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gY291bnRlcnMgb2JzZXJ2ZWQgY291bnRlcnNcbiAgICAgICAgICogQHBhcmFtIHBhdHRlcm4gZXhwZWN0ZWQgcGF0dGVyblxuICAgICAgICAgKiBAcGFyYW0gbWF4SW5kaXZpZHVhbFZhcmlhbmNlIFRoZSBtb3N0IGFueSBjb3VudGVyIGNhbiBkaWZmZXIgYmVmb3JlIHdlIGdpdmUgdXBcbiAgICAgICAgICogQHJldHVybiByYXRpbyBvZiB0b3RhbCB2YXJpYW5jZSBiZXR3ZWVuIGNvdW50ZXJzIGFuZCBwYXR0ZXJuIGNvbXBhcmVkIHRvIHRvdGFsIHBhdHRlcm4gc2l6ZVxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIHBhdHRlcm5NYXRjaFZhcmlhbmNlKGNvdW50ZXJzLCBwYXR0ZXJuLCBtYXhJbmRpdmlkdWFsVmFyaWFuY2UpIHtcbiAgICAgICAgICAgIGNvbnN0IG51bUNvdW50ZXJzID0gY291bnRlcnMubGVuZ3RoO1xuICAgICAgICAgICAgbGV0IHRvdGFsID0gMDtcbiAgICAgICAgICAgIGxldCBwYXR0ZXJuTGVuZ3RoID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtQ291bnRlcnM7IGkrKykge1xuICAgICAgICAgICAgICAgIHRvdGFsICs9IGNvdW50ZXJzW2ldO1xuICAgICAgICAgICAgICAgIHBhdHRlcm5MZW5ndGggKz0gcGF0dGVybltpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0b3RhbCA8IHBhdHRlcm5MZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB3ZSBkb24ndCBldmVuIGhhdmUgb25lIHBpeGVsIHBlciB1bml0IG9mIGJhciB3aWR0aCwgYXNzdW1lIHRoaXMgaXMgdG9vIHNtYWxsXG4gICAgICAgICAgICAgICAgLy8gdG8gcmVsaWFibHkgbWF0Y2gsIHNvIGZhaWw6XG4gICAgICAgICAgICAgICAgcmV0dXJuIE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHVuaXRCYXJXaWR0aCA9IHRvdGFsIC8gcGF0dGVybkxlbmd0aDtcbiAgICAgICAgICAgIG1heEluZGl2aWR1YWxWYXJpYW5jZSAqPSB1bml0QmFyV2lkdGg7XG4gICAgICAgICAgICBsZXQgdG90YWxWYXJpYW5jZSA9IDAuMDtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgbnVtQ291bnRlcnM7IHgrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvdW50ZXIgPSBjb3VudGVyc1t4XTtcbiAgICAgICAgICAgICAgICBjb25zdCBzY2FsZWRQYXR0ZXJuID0gcGF0dGVyblt4XSAqIHVuaXRCYXJXaWR0aDtcbiAgICAgICAgICAgICAgICBjb25zdCB2YXJpYW5jZSA9IGNvdW50ZXIgPiBzY2FsZWRQYXR0ZXJuID8gY291bnRlciAtIHNjYWxlZFBhdHRlcm4gOiBzY2FsZWRQYXR0ZXJuIC0gY291bnRlcjtcbiAgICAgICAgICAgICAgICBpZiAodmFyaWFuY2UgPiBtYXhJbmRpdmlkdWFsVmFyaWFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdG90YWxWYXJpYW5jZSArPSB2YXJpYW5jZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0b3RhbFZhcmlhbmNlIC8gdG90YWw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiA8cD5EZWNvZGVzIENvZGUgMTI4IGJhcmNvZGVzLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgQ29kZTEyOFJlYWRlciBleHRlbmRzIE9uZURSZWFkZXIge1xuICAgICAgICBzdGF0aWMgZmluZFN0YXJ0UGF0dGVybihyb3cpIHtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gcm93LmdldFNpemUoKTtcbiAgICAgICAgICAgIGNvbnN0IHJvd09mZnNldCA9IHJvdy5nZXROZXh0U2V0KDApO1xuICAgICAgICAgICAgbGV0IGNvdW50ZXJQb3NpdGlvbiA9IDA7XG4gICAgICAgICAgICBsZXQgY291bnRlcnMgPSBJbnQzMkFycmF5LmZyb20oWzAsIDAsIDAsIDAsIDAsIDBdKTtcbiAgICAgICAgICAgIGxldCBwYXR0ZXJuU3RhcnQgPSByb3dPZmZzZXQ7XG4gICAgICAgICAgICBsZXQgaXNXaGl0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3QgcGF0dGVybkxlbmd0aCA9IDY7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gcm93T2Zmc2V0OyBpIDwgd2lkdGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChyb3cuZ2V0KGkpICE9PSBpc1doaXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbl0rKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb3VudGVyUG9zaXRpb24gPT09IChwYXR0ZXJuTGVuZ3RoIC0gMSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBiZXN0VmFyaWFuY2UgPSBDb2RlMTI4UmVhZGVyLk1BWF9BVkdfVkFSSUFOQ0U7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgYmVzdE1hdGNoID0gLTE7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBzdGFydENvZGUgPSBDb2RlMTI4UmVhZGVyLkNPREVfU1RBUlRfQTsgc3RhcnRDb2RlIDw9IENvZGUxMjhSZWFkZXIuQ09ERV9TVEFSVF9DOyBzdGFydENvZGUrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhcmlhbmNlID0gT25lRFJlYWRlci5wYXR0ZXJuTWF0Y2hWYXJpYW5jZShjb3VudGVycywgQ29kZTEyOFJlYWRlci5DT0RFX1BBVFRFUk5TW3N0YXJ0Q29kZV0sIENvZGUxMjhSZWFkZXIuTUFYX0lORElWSURVQUxfVkFSSUFOQ0UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YXJpYW5jZSA8IGJlc3RWYXJpYW5jZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZXN0VmFyaWFuY2UgPSB2YXJpYW5jZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVzdE1hdGNoID0gc3RhcnRDb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIExvb2sgZm9yIHdoaXRlc3BhY2UgYmVmb3JlIHN0YXJ0IHBhdHRlcm4sID49IDUwJSBvZiB3aWR0aCBvZiBzdGFydCBwYXR0ZXJuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYmVzdE1hdGNoID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cuaXNSYW5nZShNYXRoLm1heCgwLCBwYXR0ZXJuU3RhcnQgLSAoaSAtIHBhdHRlcm5TdGFydCkgLyAyKSwgcGF0dGVyblN0YXJ0LCBmYWxzZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gSW50MzJBcnJheS5mcm9tKFtwYXR0ZXJuU3RhcnQsIGksIGJlc3RNYXRjaF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVyblN0YXJ0ICs9IGNvdW50ZXJzWzBdICsgY291bnRlcnNbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVycyA9IGNvdW50ZXJzLnNsaWNlKDIsIGNvdW50ZXJzLmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbY291bnRlclBvc2l0aW9uIC0gMV0gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbY291bnRlclBvc2l0aW9uXSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyUG9zaXRpb24tLTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJQb3NpdGlvbisrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbl0gPSAxO1xuICAgICAgICAgICAgICAgICAgICBpc1doaXRlID0gIWlzV2hpdGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGRlY29kZUNvZGUocm93LCBjb3VudGVycywgcm93T2Zmc2V0KSB7XG4gICAgICAgICAgICBPbmVEUmVhZGVyLnJlY29yZFBhdHRlcm4ocm93LCByb3dPZmZzZXQsIGNvdW50ZXJzKTtcbiAgICAgICAgICAgIGxldCBiZXN0VmFyaWFuY2UgPSBDb2RlMTI4UmVhZGVyLk1BWF9BVkdfVkFSSUFOQ0U7IC8vIHdvcnN0IHZhcmlhbmNlIHdlJ2xsIGFjY2VwdFxuICAgICAgICAgICAgbGV0IGJlc3RNYXRjaCA9IC0xO1xuICAgICAgICAgICAgZm9yIChsZXQgZCA9IDA7IGQgPCBDb2RlMTI4UmVhZGVyLkNPREVfUEFUVEVSTlMubGVuZ3RoOyBkKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXR0ZXJuID0gQ29kZTEyOFJlYWRlci5DT0RFX1BBVFRFUk5TW2RdO1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhcmlhbmNlID0gdGhpcy5wYXR0ZXJuTWF0Y2hWYXJpYW5jZShjb3VudGVycywgcGF0dGVybiwgQ29kZTEyOFJlYWRlci5NQVhfSU5ESVZJRFVBTF9WQVJJQU5DRSk7XG4gICAgICAgICAgICAgICAgaWYgKHZhcmlhbmNlIDwgYmVzdFZhcmlhbmNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RWYXJpYW5jZSA9IHZhcmlhbmNlO1xuICAgICAgICAgICAgICAgICAgICBiZXN0TWF0Y2ggPSBkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFRPRE8gV2UncmUgb3Zlcmxvb2tpbmcgdGhlIGZhY3QgdGhhdCB0aGUgU1RPUCBwYXR0ZXJuIGhhcyA3IHZhbHVlcywgbm90IDYuXG4gICAgICAgICAgICBpZiAoYmVzdE1hdGNoID49IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYmVzdE1hdGNoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZGVjb2RlUm93KHJvd051bWJlciwgcm93LCBoaW50cykge1xuICAgICAgICAgICAgY29uc3QgY29udmVydEZOQzEgPSBoaW50cyAmJiAoaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuQVNTVU1FX0dTMSkgPT09IHRydWUpO1xuICAgICAgICAgICAgY29uc3Qgc3RhcnRQYXR0ZXJuSW5mbyA9IENvZGUxMjhSZWFkZXIuZmluZFN0YXJ0UGF0dGVybihyb3cpO1xuICAgICAgICAgICAgY29uc3Qgc3RhcnRDb2RlID0gc3RhcnRQYXR0ZXJuSW5mb1syXTtcbiAgICAgICAgICAgIGxldCBjdXJyZW50UmF3Q29kZXNJbmRleCA9IDA7XG4gICAgICAgICAgICBjb25zdCByYXdDb2RlcyA9IG5ldyBVaW50OEFycmF5KDIwKTtcbiAgICAgICAgICAgIHJhd0NvZGVzW2N1cnJlbnRSYXdDb2Rlc0luZGV4KytdID0gc3RhcnRDb2RlO1xuICAgICAgICAgICAgbGV0IGNvZGVTZXQ7XG4gICAgICAgICAgICBzd2l0Y2ggKHN0YXJ0Q29kZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX1NUQVJUX0E6XG4gICAgICAgICAgICAgICAgICAgIGNvZGVTZXQgPSBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9BO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9TVEFSVF9COlxuICAgICAgICAgICAgICAgICAgICBjb2RlU2V0ID0gQ29kZTEyOFJlYWRlci5DT0RFX0NPREVfQjtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfU1RBUlRfQzpcbiAgICAgICAgICAgICAgICAgICAgY29kZVNldCA9IENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0M7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBkb25lID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgaXNOZXh0U2hpZnRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9ICcnO1xuICAgICAgICAgICAgbGV0IGxhc3RTdGFydCA9IHN0YXJ0UGF0dGVybkluZm9bMF07XG4gICAgICAgICAgICBsZXQgbmV4dFN0YXJ0ID0gc3RhcnRQYXR0ZXJuSW5mb1sxXTtcbiAgICAgICAgICAgIGNvbnN0IGNvdW50ZXJzID0gSW50MzJBcnJheS5mcm9tKFswLCAwLCAwLCAwLCAwLCAwXSk7XG4gICAgICAgICAgICBsZXQgbGFzdENvZGUgPSAwO1xuICAgICAgICAgICAgbGV0IGNvZGUgPSAwO1xuICAgICAgICAgICAgbGV0IGNoZWNrc3VtVG90YWwgPSBzdGFydENvZGU7XG4gICAgICAgICAgICBsZXQgbXVsdGlwbGllciA9IDA7XG4gICAgICAgICAgICBsZXQgbGFzdENoYXJhY3Rlcldhc1ByaW50YWJsZSA9IHRydWU7XG4gICAgICAgICAgICBsZXQgdXBwZXJNb2RlID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgc2hpZnRVcHBlck1vZGUgPSBmYWxzZTtcbiAgICAgICAgICAgIHdoaWxlICghZG9uZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHVuc2hpZnQgPSBpc05leHRTaGlmdGVkO1xuICAgICAgICAgICAgICAgIGlzTmV4dFNoaWZ0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAvLyBTYXZlIG9mZiBsYXN0IGNvZGVcbiAgICAgICAgICAgICAgICBsYXN0Q29kZSA9IGNvZGU7XG4gICAgICAgICAgICAgICAgLy8gRGVjb2RlIGFub3RoZXIgY29kZSBmcm9tIGltYWdlXG4gICAgICAgICAgICAgICAgY29kZSA9IENvZGUxMjhSZWFkZXIuZGVjb2RlQ29kZShyb3csIGNvdW50ZXJzLCBuZXh0U3RhcnQpO1xuICAgICAgICAgICAgICAgIHJhd0NvZGVzW2N1cnJlbnRSYXdDb2Rlc0luZGV4KytdID0gY29kZTtcbiAgICAgICAgICAgICAgICAvLyBSZW1lbWJlciB3aGV0aGVyIHRoZSBsYXN0IGNvZGUgd2FzIHByaW50YWJsZSBvciBub3QgKGV4Y2x1ZGluZyBDT0RFX1NUT1ApXG4gICAgICAgICAgICAgICAgaWYgKGNvZGUgIT09IENvZGUxMjhSZWFkZXIuQ09ERV9TVE9QKSB7XG4gICAgICAgICAgICAgICAgICAgIGxhc3RDaGFyYWN0ZXJXYXNQcmludGFibGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBBZGQgdG8gY2hlY2tzdW0gY29tcHV0YXRpb24gKGlmIG5vdCBDT0RFX1NUT1Agb2YgY291cnNlKVxuICAgICAgICAgICAgICAgIGlmIChjb2RlICE9PSBDb2RlMTI4UmVhZGVyLkNPREVfU1RPUCkge1xuICAgICAgICAgICAgICAgICAgICBtdWx0aXBsaWVyKys7XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrc3VtVG90YWwgKz0gbXVsdGlwbGllciAqIGNvZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIEFkdmFuY2UgdG8gd2hlcmUgdGhlIG5leHQgY29kZSB3aWxsIHRvIHN0YXJ0XG4gICAgICAgICAgICAgICAgbGFzdFN0YXJ0ID0gbmV4dFN0YXJ0O1xuICAgICAgICAgICAgICAgIG5leHRTdGFydCArPSBjb3VudGVycy5yZWR1Y2UoKHByZXZpb3VzLCBjdXJyZW50KSA9PiBwcmV2aW91cyArIGN1cnJlbnQsIDApO1xuICAgICAgICAgICAgICAgIC8vIFRha2UgY2FyZSBvZiBpbGxlZ2FsIHN0YXJ0IGNvZGVzXG4gICAgICAgICAgICAgICAgc3dpdGNoIChjb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX1NUQVJUX0E6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX1NUQVJUX0I6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX1NUQVJUX0M6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN3aXRjaCAoY29kZVNldCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0E6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29kZSA8IDY0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNoaWZ0VXBwZXJNb2RlID09PSB1cHBlck1vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKCcgJy5jaGFyQ29kZUF0KDApICsgY29kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKCcgJy5jaGFyQ29kZUF0KDApICsgY29kZSArIDEyOCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaGlmdFVwcGVyTW9kZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoY29kZSA8IDk2KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNoaWZ0VXBwZXJNb2RlID09PSB1cHBlck1vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKGNvZGUgLSA2NCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKGNvZGUgKyA2NCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaGlmdFVwcGVyTW9kZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9uJ3QgbGV0IENPREVfU1RPUCwgd2hpY2ggYWx3YXlzIGFwcGVhcnMsIGFmZmVjdCB3aGV0aGVyIHdoZXRoZXIgd2UgdGhpbmsgdGhlIGxhc3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjb2RlIHdhcyBwcmludGFibGUgb3Igbm90LlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb2RlICE9PSBDb2RlMTI4UmVhZGVyLkNPREVfU1RPUCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0Q2hhcmFjdGVyV2FzUHJpbnRhYmxlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoY29kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9GTkNfMTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb252ZXJ0Rk5DMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdTMSBzcGVjaWZpY2F0aW9uIDUuNC4zLjcuIGFuZCA1LjQuNi40LiBJZiB0aGUgZmlyc3QgY2hhciBhZnRlciB0aGUgc3RhcnQgY29kZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpcyBGTkMxIHRoZW4gdGhpcyBpcyBHUzEtMTI4LiBXZSBhZGQgdGhlIHN5bWJvbG9neSBpZGVudGlmaWVyLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ11DMSc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHUzEgc3BlY2lmaWNhdGlvbiA1LjQuNy41LiBFdmVyeSBzdWJzZXF1ZW50IEZOQzEgaXMgcmV0dXJuZWQgYXMgQVNDSUkgMjkgKEdTKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgyOSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX0ZOQ18yOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9GTkNfMzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRvIG5vdGhpbmc/XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfRk5DXzRfQTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdXBwZXJNb2RlICYmIHNoaWZ0VXBwZXJNb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBwZXJNb2RlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaGlmdFVwcGVyTW9kZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodXBwZXJNb2RlICYmIHNoaWZ0VXBwZXJNb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBwZXJNb2RlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hpZnRVcHBlck1vZGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoaWZ0VXBwZXJNb2RlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9TSElGVDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzTmV4dFNoaWZ0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZVNldCA9IENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9COlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZVNldCA9IENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9DOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZVNldCA9IENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0M7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfU1RPUDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX0NPREVfQjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb2RlIDwgOTYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2hpZnRVcHBlck1vZGUgPT09IHVwcGVyTW9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgoJyAnLmNoYXJDb2RlQXQoMCkgKyBjb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgoJyAnLmNoYXJDb2RlQXQoMCkgKyBjb2RlICsgMTI4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoaWZ0VXBwZXJNb2RlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29kZSAhPT0gQ29kZTEyOFJlYWRlci5DT0RFX1NUT1ApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdENoYXJhY3Rlcldhc1ByaW50YWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGNvZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfRk5DXzE6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29udmVydEZOQzEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHUzEgc3BlY2lmaWNhdGlvbiA1LjQuMy43LiBhbmQgNS40LjYuNC4gSWYgdGhlIGZpcnN0IGNoYXIgYWZ0ZXIgdGhlIHN0YXJ0IGNvZGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXMgRk5DMSB0aGVuIHRoaXMgaXMgR1MxLTEyOC4gV2UgYWRkIHRoZSBzeW1ib2xvZ3kgaWRlbnRpZmllci5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICddQzEnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR1MxIHNwZWNpZmljYXRpb24gNS40LjcuNS4gRXZlcnkgc3Vic2VxdWVudCBGTkMxIGlzIHJldHVybmVkIGFzIEFTQ0lJIDI5IChHUylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMjkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9GTkNfMjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfRk5DXzM6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBkbyBub3RoaW5nP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX0ZOQ180X0I6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXVwcGVyTW9kZSAmJiBzaGlmdFVwcGVyTW9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwcGVyTW9kZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hpZnRVcHBlck1vZGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHVwcGVyTW9kZSAmJiBzaGlmdFVwcGVyTW9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwcGVyTW9kZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoaWZ0VXBwZXJNb2RlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaGlmdFVwcGVyTW9kZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfU0hJRlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc05leHRTaGlmdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVTZXQgPSBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9BO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX0NPREVfQTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVTZXQgPSBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9BO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX0NPREVfQzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVTZXQgPSBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9DO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX1NUT1A6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0M6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29kZSA8IDEwMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb2RlIDwgMTApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICcwJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IGNvZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29kZSAhPT0gQ29kZTEyOFJlYWRlci5DT0RFX1NUT1ApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdENoYXJhY3Rlcldhc1ByaW50YWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGNvZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfRk5DXzE6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29udmVydEZOQzEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHUzEgc3BlY2lmaWNhdGlvbiA1LjQuMy43LiBhbmQgNS40LjYuNC4gSWYgdGhlIGZpcnN0IGNoYXIgYWZ0ZXIgdGhlIHN0YXJ0IGNvZGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXMgRk5DMSB0aGVuIHRoaXMgaXMgR1MxLTEyOC4gV2UgYWRkIHRoZSBzeW1ib2xvZ3kgaWRlbnRpZmllci5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICddQzEnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR1MxIHNwZWNpZmljYXRpb24gNS40LjcuNS4gRXZlcnkgc3Vic2VxdWVudCBGTkMxIGlzIHJldHVybmVkIGFzIEFTQ0lJIDI5IChHUylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMjkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0E6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2RlU2V0ID0gQ29kZTEyOFJlYWRlci5DT0RFX0NPREVfQTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0I6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2RlU2V0ID0gQ29kZTEyOFJlYWRlci5DT0RFX0NPREVfQjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9TVE9QOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gVW5zaGlmdCBiYWNrIHRvIGFub3RoZXIgY29kZSBzZXQgaWYgd2Ugd2VyZSBzaGlmdGVkXG4gICAgICAgICAgICAgICAgaWYgKHVuc2hpZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29kZVNldCA9IGNvZGVTZXQgPT09IENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0EgPyBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9CIDogQ29kZTEyOFJlYWRlci5DT0RFX0NPREVfQTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBsYXN0UGF0dGVyblNpemUgPSBuZXh0U3RhcnQgLSBsYXN0U3RhcnQ7XG4gICAgICAgICAgICAvLyBDaGVjayBmb3IgYW1wbGUgd2hpdGVzcGFjZSBmb2xsb3dpbmcgcGF0dGVybiwgYnV0LCB0byBkbyB0aGlzIHdlIGZpcnN0IG5lZWQgdG8gcmVtZW1iZXIgdGhhdFxuICAgICAgICAgICAgLy8gd2UgZnVkZ2VkIGRlY29kaW5nIENPREVfU1RPUCBzaW5jZSBpdCBhY3R1YWxseSBoYXMgNyBiYXJzLCBub3QgNi4gVGhlcmUgaXMgYSBibGFjayBiYXIgbGVmdFxuICAgICAgICAgICAgLy8gdG8gcmVhZCBvZmYuIFdvdWxkIGJlIHNsaWdodGx5IGJldHRlciB0byBwcm9wZXJseSByZWFkLiBIZXJlIHdlIGp1c3Qgc2tpcCBpdDpcbiAgICAgICAgICAgIG5leHRTdGFydCA9IHJvdy5nZXROZXh0VW5zZXQobmV4dFN0YXJ0KTtcbiAgICAgICAgICAgIGlmICghcm93LmlzUmFuZ2UobmV4dFN0YXJ0LCBNYXRoLm1pbihyb3cuZ2V0U2l6ZSgpLCBuZXh0U3RhcnQgKyAobmV4dFN0YXJ0IC0gbGFzdFN0YXJ0KSAvIDIpLCBmYWxzZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFB1bGwgb3V0IGZyb20gc3VtIHRoZSB2YWx1ZSBvZiB0aGUgcGVudWx0aW1hdGUgY2hlY2sgY29kZVxuICAgICAgICAgICAgY2hlY2tzdW1Ub3RhbCAtPSBtdWx0aXBsaWVyICogbGFzdENvZGU7XG4gICAgICAgICAgICAvLyBsYXN0Q29kZSBpcyB0aGUgY2hlY2tzdW0gdGhlbjpcbiAgICAgICAgICAgIGlmIChjaGVja3N1bVRvdGFsICUgMTAzICE9PSBsYXN0Q29kZSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBDaGVja3N1bUV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gTmVlZCB0byBwdWxsIG91dCB0aGUgY2hlY2sgZGlnaXRzIGZyb20gc3RyaW5nXG4gICAgICAgICAgICBjb25zdCByZXN1bHRMZW5ndGggPSByZXN1bHQubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKHJlc3VsdExlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIC8vIGZhbHNlIHBvc2l0aXZlXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBPbmx5IGJvdGhlciBpZiB0aGUgcmVzdWx0IGhhZCBhdCBsZWFzdCBvbmUgY2hhcmFjdGVyLCBhbmQgaWYgdGhlIGNoZWNrc3VtIGRpZ2l0IGhhcHBlbmVkIHRvXG4gICAgICAgICAgICAvLyBiZSBhIHByaW50YWJsZSBjaGFyYWN0ZXIuIElmIGl0IHdhcyBqdXN0IGludGVycHJldGVkIGFzIGEgY29udHJvbCBjb2RlLCBub3RoaW5nIHRvIHJlbW92ZS5cbiAgICAgICAgICAgIGlmIChyZXN1bHRMZW5ndGggPiAwICYmIGxhc3RDaGFyYWN0ZXJXYXNQcmludGFibGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoY29kZVNldCA9PT0gQ29kZTEyOFJlYWRlci5DT0RFX0NPREVfQykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSByZXN1bHQuc3Vic3RyaW5nKDAsIHJlc3VsdExlbmd0aCAtIDIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LnN1YnN0cmluZygwLCByZXN1bHRMZW5ndGggLSAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBsZWZ0ID0gKHN0YXJ0UGF0dGVybkluZm9bMV0gKyBzdGFydFBhdHRlcm5JbmZvWzBdKSAvIDIuMDtcbiAgICAgICAgICAgIGNvbnN0IHJpZ2h0ID0gbGFzdFN0YXJ0ICsgbGFzdFBhdHRlcm5TaXplIC8gMi4wO1xuICAgICAgICAgICAgY29uc3QgcmF3Q29kZXNTaXplID0gcmF3Q29kZXMubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3QgcmF3Qnl0ZXMgPSBuZXcgVWludDhBcnJheShyYXdDb2Rlc1NpemUpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCByYXdDb2Rlc1NpemU7IGkrKykge1xuICAgICAgICAgICAgICAgIHJhd0J5dGVzW2ldID0gcmF3Q29kZXNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBwb2ludHMgPSBbbmV3IFJlc3VsdFBvaW50KGxlZnQsIHJvd051bWJlciksIG5ldyBSZXN1bHRQb2ludChyaWdodCwgcm93TnVtYmVyKV07XG4gICAgICAgICAgICByZXR1cm4gbmV3IFJlc3VsdChyZXN1bHQsIHJhd0J5dGVzLCAwLCBwb2ludHMsIEJhcmNvZGVGb3JtYXQkMS5DT0RFXzEyOCwgbmV3IERhdGUoKS5nZXRUaW1lKCkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIENvZGUxMjhSZWFkZXIuQ09ERV9QQVRURVJOUyA9IFtcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAxLCAyLCAyLCAyLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMiwgMiwgMSwgMiwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDIsIDIsIDIsIDIsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAyLCAxLCAyLCAyLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMiwgMSwgMywgMiwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDMsIDEsIDIsIDIsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAyLCAyLCAyLCAxLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMiwgMiwgMywgMSwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDMsIDIsIDIsIDEsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAyLCAxLCAyLCAxLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMiwgMSwgMywgMSwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDMsIDEsIDIsIDEsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAyLCAyLCAzLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMiwgMiwgMSwgMywgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDIsIDIsIDIsIDMsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAzLCAyLCAyLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMiwgMywgMSwgMiwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDIsIDMsIDIsIDIsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAyLCAzLCAyLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMiwgMSwgMSwgMywgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDIsIDEsIDIsIDMsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAxLCAzLCAyLCAxLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMiwgMywgMSwgMSwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDEsIDIsIDEsIDMsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAxLCAxLCAyLCAyLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgMiwgMSwgMSwgMiwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDIsIDEsIDIsIDIsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAxLCAyLCAyLCAxLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgMiwgMiwgMSwgMSwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDIsIDIsIDIsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAxLCAyLCAxLCAyLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMSwgMiwgMywgMiwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDMsIDIsIDEsIDIsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAxLCAzLCAyLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMywgMSwgMSwgMiwgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDMsIDEsIDMsIDIsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAyLCAzLCAxLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMywgMiwgMSwgMSwgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDMsIDIsIDMsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAxLCAxLCAzLCAxLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMywgMSwgMSwgMSwgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDMsIDEsIDMsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAyLCAxLCAzLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMiwgMywgMywgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDMsIDIsIDEsIDMsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAzLCAxLCAyLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMywgMywgMiwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDMsIDMsIDEsIDIsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAxLCAzLCAxLCAyLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMSwgMSwgMywgMywgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDMsIDEsIDEsIDMsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAxLCAzLCAxLCAxLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMSwgMywgMywgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDEsIDMsIDEsIDMsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAxLCAxLCAxLCAyLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgMSwgMSwgMywgMiwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDMsIDEsIDEsIDIsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAxLCAyLCAxLCAxLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgMSwgMiwgMywgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDMsIDIsIDEsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAxLCA0LCAxLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMiwgMSwgNCwgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzQsIDMsIDEsIDEsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAxLCAyLCAyLCA0XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMSwgNCwgMiwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDIsIDEsIDEsIDIsIDRdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAyLCAxLCA0LCAyLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgNCwgMSwgMSwgMiwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDQsIDEsIDIsIDIsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAyLCAyLCAxLCA0XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMiwgNCwgMSwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDIsIDIsIDEsIDEsIDRdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAyLCAyLCA0LCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgNCwgMiwgMSwgMSwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDQsIDIsIDIsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCA0LCAxLCAyLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMiwgMSwgMSwgMSwgNF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzQsIDEsIDMsIDEsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCA0LCAxLCAxLCAxLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMywgNCwgMSwgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDEsIDIsIDQsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAyLCAxLCAxLCA0LCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMiwgMSwgMiwgNCwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDQsIDIsIDEsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAyLCA0LCAxLCAxLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMiwgNCwgMiwgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzQsIDEsIDEsIDIsIDEsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs0LCAyLCAxLCAxLCAxLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNCwgMiwgMSwgMiwgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDEsIDIsIDEsIDQsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAxLCA0LCAxLCAyLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNCwgMSwgMiwgMSwgMiwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDEsIDEsIDQsIDNdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAxLCAzLCA0LCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMywgMSwgMSwgNCwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDQsIDEsIDEsIDNdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCA0LCAzLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNCwgMSwgMSwgMSwgMSwgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzQsIDEsIDEsIDMsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAzLCAxLCA0LCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgNCwgMSwgMywgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDEsIDEsIDEsIDQsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs0LCAxLCAxLCAxLCAzLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMSwgMSwgNCwgMSwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDEsIDEsIDIsIDEsIDRdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAxLCAxLCAyLCAzLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMywgMywgMSwgMSwgMSwgMl0pLFxuICAgIF07XG4gICAgQ29kZTEyOFJlYWRlci5NQVhfQVZHX1ZBUklBTkNFID0gMC4yNTtcbiAgICBDb2RlMTI4UmVhZGVyLk1BWF9JTkRJVklEVUFMX1ZBUklBTkNFID0gMC43O1xuICAgIENvZGUxMjhSZWFkZXIuQ09ERV9TSElGVCA9IDk4O1xuICAgIENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0MgPSA5OTtcbiAgICBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9CID0gMTAwO1xuICAgIENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0EgPSAxMDE7XG4gICAgQ29kZTEyOFJlYWRlci5DT0RFX0ZOQ18xID0gMTAyO1xuICAgIENvZGUxMjhSZWFkZXIuQ09ERV9GTkNfMiA9IDk3O1xuICAgIENvZGUxMjhSZWFkZXIuQ09ERV9GTkNfMyA9IDk2O1xuICAgIENvZGUxMjhSZWFkZXIuQ09ERV9GTkNfNF9BID0gMTAxO1xuICAgIENvZGUxMjhSZWFkZXIuQ09ERV9GTkNfNF9CID0gMTAwO1xuICAgIENvZGUxMjhSZWFkZXIuQ09ERV9TVEFSVF9BID0gMTAzO1xuICAgIENvZGUxMjhSZWFkZXIuQ09ERV9TVEFSVF9CID0gMTA0O1xuICAgIENvZGUxMjhSZWFkZXIuQ09ERV9TVEFSVF9DID0gMTA1O1xuICAgIENvZGUxMjhSZWFkZXIuQ09ERV9TVE9QID0gMTA2O1xuXG4gICAgLyoqXG4gICAgICogPHA+RGVjb2RlcyBDb2RlIDM5IGJhcmNvZGVzLiBTdXBwb3J0cyBcIkZ1bGwgQVNDSUkgQ29kZSAzOVwiIGlmIFVTRV9DT0RFXzM5X0VYVEVOREVEX01PREUgaXMgc2V0LjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICogQHNlZSBDb2RlOTNSZWFkZXJcbiAgICAgKi9cbiAgICBjbGFzcyBDb2RlMzlSZWFkZXIgZXh0ZW5kcyBPbmVEUmVhZGVyIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSByZWFkZXIgdGhhdCBhc3N1bWVzIGFsbCBlbmNvZGVkIGRhdGEgaXMgZGF0YSwgYW5kIGRvZXMgbm90IHRyZWF0IHRoZSBmaW5hbFxuICAgICAgICAgKiBjaGFyYWN0ZXIgYXMgYSBjaGVjayBkaWdpdC4gSXQgd2lsbCBub3QgZGVjb2RlZCBcImV4dGVuZGVkIENvZGUgMzlcIiBzZXF1ZW5jZXMuXG4gICAgICAgICAqL1xuICAgICAgICAvLyBwdWJsaWMgQ29kZTM5UmVhZGVyKCkge1xuICAgICAgICAvLyAgIHRoaXMoZmFsc2UpO1xuICAgICAgICAvLyB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgcmVhZGVyIHRoYXQgY2FuIGJlIGNvbmZpZ3VyZWQgdG8gY2hlY2sgdGhlIGxhc3QgY2hhcmFjdGVyIGFzIGEgY2hlY2sgZGlnaXQuXG4gICAgICAgICAqIEl0IHdpbGwgbm90IGRlY29kZWQgXCJleHRlbmRlZCBDb2RlIDM5XCIgc2VxdWVuY2VzLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gdXNpbmdDaGVja0RpZ2l0IGlmIHRydWUsIHRyZWF0IHRoZSBsYXN0IGRhdGEgY2hhcmFjdGVyIGFzIGEgY2hlY2sgZGlnaXQsIG5vdFxuICAgICAgICAgKiBkYXRhLCBhbmQgdmVyaWZ5IHRoYXQgdGhlIGNoZWNrc3VtIHBhc3Nlcy5cbiAgICAgICAgICovXG4gICAgICAgIC8vIHB1YmxpYyBDb2RlMzlSZWFkZXIoYm9vbGVhbiB1c2luZ0NoZWNrRGlnaXQpIHtcbiAgICAgICAgLy8gICB0aGlzKHVzaW5nQ2hlY2tEaWdpdCwgZmFsc2UpO1xuICAgICAgICAvLyB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgcmVhZGVyIHRoYXQgY2FuIGJlIGNvbmZpZ3VyZWQgdG8gY2hlY2sgdGhlIGxhc3QgY2hhcmFjdGVyIGFzIGEgY2hlY2sgZGlnaXQsXG4gICAgICAgICAqIG9yIG9wdGlvbmFsbHkgYXR0ZW1wdCB0byBkZWNvZGUgXCJleHRlbmRlZCBDb2RlIDM5XCIgc2VxdWVuY2VzIHRoYXQgYXJlIHVzZWQgdG8gZW5jb2RlXG4gICAgICAgICAqIHRoZSBmdWxsIEFTQ0lJIGNoYXJhY3RlciBzZXQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB1c2luZ0NoZWNrRGlnaXQgaWYgdHJ1ZSwgdHJlYXQgdGhlIGxhc3QgZGF0YSBjaGFyYWN0ZXIgYXMgYSBjaGVjayBkaWdpdCwgbm90XG4gICAgICAgICAqIGRhdGEsIGFuZCB2ZXJpZnkgdGhhdCB0aGUgY2hlY2tzdW0gcGFzc2VzLlxuICAgICAgICAgKiBAcGFyYW0gZXh0ZW5kZWRNb2RlIGlmIHRydWUsIHdpbGwgYXR0ZW1wdCB0byBkZWNvZGUgZXh0ZW5kZWQgQ29kZSAzOSBzZXF1ZW5jZXMgaW4gdGhlXG4gICAgICAgICAqIHRleHQuXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3Rvcih1c2luZ0NoZWNrRGlnaXQgPSBmYWxzZSwgZXh0ZW5kZWRNb2RlID0gZmFsc2UpIHtcbiAgICAgICAgICAgIHN1cGVyKCk7XG4gICAgICAgICAgICB0aGlzLnVzaW5nQ2hlY2tEaWdpdCA9IHVzaW5nQ2hlY2tEaWdpdDtcbiAgICAgICAgICAgIHRoaXMuZXh0ZW5kZWRNb2RlID0gZXh0ZW5kZWRNb2RlO1xuICAgICAgICAgICAgdGhpcy5kZWNvZGVSb3dSZXN1bHQgPSAnJztcbiAgICAgICAgICAgIHRoaXMuY291bnRlcnMgPSBuZXcgSW50MzJBcnJheSg5KTtcbiAgICAgICAgfVxuICAgICAgICBkZWNvZGVSb3cocm93TnVtYmVyLCByb3csIGhpbnRzKSB7XG4gICAgICAgICAgICBsZXQgdGhlQ291bnRlcnMgPSB0aGlzLmNvdW50ZXJzO1xuICAgICAgICAgICAgdGhlQ291bnRlcnMuZmlsbCgwKTtcbiAgICAgICAgICAgIHRoaXMuZGVjb2RlUm93UmVzdWx0ID0gJyc7XG4gICAgICAgICAgICBsZXQgc3RhcnQgPSBDb2RlMzlSZWFkZXIuZmluZEFzdGVyaXNrUGF0dGVybihyb3csIHRoZUNvdW50ZXJzKTtcbiAgICAgICAgICAgIC8vIFJlYWQgb2ZmIHdoaXRlIHNwYWNlXG4gICAgICAgICAgICBsZXQgbmV4dFN0YXJ0ID0gcm93LmdldE5leHRTZXQoc3RhcnRbMV0pO1xuICAgICAgICAgICAgbGV0IGVuZCA9IHJvdy5nZXRTaXplKCk7XG4gICAgICAgICAgICBsZXQgZGVjb2RlZENoYXI7XG4gICAgICAgICAgICBsZXQgbGFzdFN0YXJ0O1xuICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgIENvZGUzOVJlYWRlci5yZWNvcmRQYXR0ZXJuKHJvdywgbmV4dFN0YXJ0LCB0aGVDb3VudGVycyk7XG4gICAgICAgICAgICAgICAgbGV0IHBhdHRlcm4gPSBDb2RlMzlSZWFkZXIudG9OYXJyb3dXaWRlUGF0dGVybih0aGVDb3VudGVycyk7XG4gICAgICAgICAgICAgICAgaWYgKHBhdHRlcm4gPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZWNvZGVkQ2hhciA9IENvZGUzOVJlYWRlci5wYXR0ZXJuVG9DaGFyKHBhdHRlcm4pO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVjb2RlUm93UmVzdWx0ICs9IGRlY29kZWRDaGFyO1xuICAgICAgICAgICAgICAgIGxhc3RTdGFydCA9IG5leHRTdGFydDtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBjb3VudGVyIG9mIHRoZUNvdW50ZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIG5leHRTdGFydCArPSBjb3VudGVyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBSZWFkIG9mZiB3aGl0ZSBzcGFjZVxuICAgICAgICAgICAgICAgIG5leHRTdGFydCA9IHJvdy5nZXROZXh0U2V0KG5leHRTdGFydCk7XG4gICAgICAgICAgICB9IHdoaWxlIChkZWNvZGVkQ2hhciAhPT0gJyonKTtcbiAgICAgICAgICAgIHRoaXMuZGVjb2RlUm93UmVzdWx0ID0gdGhpcy5kZWNvZGVSb3dSZXN1bHQuc3Vic3RyaW5nKDAsIHRoaXMuZGVjb2RlUm93UmVzdWx0Lmxlbmd0aCAtIDEpOyAvLyByZW1vdmUgYXN0ZXJpc2tcbiAgICAgICAgICAgIC8vIExvb2sgZm9yIHdoaXRlc3BhY2UgYWZ0ZXIgcGF0dGVybjpcbiAgICAgICAgICAgIGxldCBsYXN0UGF0dGVyblNpemUgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgY291bnRlciBvZiB0aGVDb3VudGVycykge1xuICAgICAgICAgICAgICAgIGxhc3RQYXR0ZXJuU2l6ZSArPSBjb3VudGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHdoaXRlU3BhY2VBZnRlckVuZCA9IG5leHRTdGFydCAtIGxhc3RTdGFydCAtIGxhc3RQYXR0ZXJuU2l6ZTtcbiAgICAgICAgICAgIC8vIElmIDUwJSBvZiBsYXN0IHBhdHRlcm4gc2l6ZSwgZm9sbG93aW5nIGxhc3QgcGF0dGVybiwgaXMgbm90IHdoaXRlc3BhY2UsIGZhaWxcbiAgICAgICAgICAgIC8vIChidXQgaWYgaXQncyB3aGl0ZXNwYWNlIHRvIHRoZSB2ZXJ5IGVuZCBvZiB0aGUgaW1hZ2UsIHRoYXQncyBPSylcbiAgICAgICAgICAgIGlmIChuZXh0U3RhcnQgIT09IGVuZCAmJiAod2hpdGVTcGFjZUFmdGVyRW5kICogMikgPCBsYXN0UGF0dGVyblNpemUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLnVzaW5nQ2hlY2tEaWdpdCkge1xuICAgICAgICAgICAgICAgIGxldCBtYXggPSB0aGlzLmRlY29kZVJvd1Jlc3VsdC5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIGxldCB0b3RhbCA9IDA7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB0b3RhbCArPSBDb2RlMzlSZWFkZXIuQUxQSEFCRVRfU1RSSU5HLmluZGV4T2YodGhpcy5kZWNvZGVSb3dSZXN1bHQuY2hhckF0KGkpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZGVjb2RlUm93UmVzdWx0LmNoYXJBdChtYXgpICE9PSBDb2RlMzlSZWFkZXIuQUxQSEFCRVRfU1RSSU5HLmNoYXJBdCh0b3RhbCAlIDQzKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQ2hlY2tzdW1FeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5kZWNvZGVSb3dSZXN1bHQgPSB0aGlzLmRlY29kZVJvd1Jlc3VsdC5zdWJzdHJpbmcoMCwgbWF4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmRlY29kZVJvd1Jlc3VsdC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyBmYWxzZSBwb3NpdGl2ZVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHJlc3VsdFN0cmluZztcbiAgICAgICAgICAgIGlmICh0aGlzLmV4dGVuZGVkTW9kZSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdFN0cmluZyA9IENvZGUzOVJlYWRlci5kZWNvZGVFeHRlbmRlZCh0aGlzLmRlY29kZVJvd1Jlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHRTdHJpbmcgPSB0aGlzLmRlY29kZVJvd1Jlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBsZWZ0ID0gKHN0YXJ0WzFdICsgc3RhcnRbMF0pIC8gMi4wO1xuICAgICAgICAgICAgbGV0IHJpZ2h0ID0gbGFzdFN0YXJ0ICsgbGFzdFBhdHRlcm5TaXplIC8gMi4wO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBSZXN1bHQocmVzdWx0U3RyaW5nLCBudWxsLCAwLCBbbmV3IFJlc3VsdFBvaW50KGxlZnQsIHJvd051bWJlciksIG5ldyBSZXN1bHRQb2ludChyaWdodCwgcm93TnVtYmVyKV0sIEJhcmNvZGVGb3JtYXQkMS5DT0RFXzM5LCBuZXcgRGF0ZSgpLmdldFRpbWUoKSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGZpbmRBc3Rlcmlza1BhdHRlcm4ocm93LCBjb3VudGVycykge1xuICAgICAgICAgICAgbGV0IHdpZHRoID0gcm93LmdldFNpemUoKTtcbiAgICAgICAgICAgIGxldCByb3dPZmZzZXQgPSByb3cuZ2V0TmV4dFNldCgwKTtcbiAgICAgICAgICAgIGxldCBjb3VudGVyUG9zaXRpb24gPSAwO1xuICAgICAgICAgICAgbGV0IHBhdHRlcm5TdGFydCA9IHJvd09mZnNldDtcbiAgICAgICAgICAgIGxldCBpc1doaXRlID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgcGF0dGVybkxlbmd0aCA9IGNvdW50ZXJzLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSByb3dPZmZzZXQ7IGkgPCB3aWR0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJvdy5nZXQoaSkgIT09IGlzV2hpdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbY291bnRlclBvc2l0aW9uXSsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvdW50ZXJQb3NpdGlvbiA9PT0gcGF0dGVybkxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIExvb2sgZm9yIHdoaXRlc3BhY2UgYmVmb3JlIHN0YXJ0IHBhdHRlcm4sID49IDUwJSBvZiB3aWR0aCBvZiBzdGFydCBwYXR0ZXJuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy50b05hcnJvd1dpZGVQYXR0ZXJuKGNvdW50ZXJzKSA9PT0gQ29kZTM5UmVhZGVyLkFTVEVSSVNLX0VOQ09ESU5HICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93LmlzUmFuZ2UoTWF0aC5tYXgoMCwgcGF0dGVyblN0YXJ0IC0gTWF0aC5mbG9vcigoaSAtIHBhdHRlcm5TdGFydCkgLyAyKSksIHBhdHRlcm5TdGFydCwgZmFsc2UpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtwYXR0ZXJuU3RhcnQsIGldO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVyblN0YXJ0ICs9IGNvdW50ZXJzWzBdICsgY291bnRlcnNbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVycy5jb3B5V2l0aGluKDAsIDIsIDIgKyBjb3VudGVyUG9zaXRpb24gLSAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbiAtIDFdID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbl0gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlclBvc2l0aW9uLS07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyUG9zaXRpb24rKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb25dID0gMTtcbiAgICAgICAgICAgICAgICAgICAgaXNXaGl0ZSA9ICFpc1doaXRlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEZvciBlZmZpY2llbmN5LCByZXR1cm5zIC0xIG9uIGZhaWx1cmUuIE5vdCB0aHJvd2luZyBoZXJlIHNhdmVkIGFzIG1hbnkgYXMgNzAwIGV4Y2VwdGlvbnNcbiAgICAgICAgLy8gcGVyIGltYWdlIHdoZW4gdXNpbmcgc29tZSBvZiBvdXIgYmxhY2tib3ggaW1hZ2VzLlxuICAgICAgICBzdGF0aWMgdG9OYXJyb3dXaWRlUGF0dGVybihjb3VudGVycykge1xuICAgICAgICAgICAgbGV0IG51bUNvdW50ZXJzID0gY291bnRlcnMubGVuZ3RoO1xuICAgICAgICAgICAgbGV0IG1heE5hcnJvd0NvdW50ZXIgPSAwO1xuICAgICAgICAgICAgbGV0IHdpZGVDb3VudGVycztcbiAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICBsZXQgbWluQ291bnRlciA9IDB4N2ZmZmZmZmY7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgY291bnRlciBvZiBjb3VudGVycykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY291bnRlciA8IG1pbkNvdW50ZXIgJiYgY291bnRlciA+IG1heE5hcnJvd0NvdW50ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkNvdW50ZXIgPSBjb3VudGVyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1heE5hcnJvd0NvdW50ZXIgPSBtaW5Db3VudGVyO1xuICAgICAgICAgICAgICAgIHdpZGVDb3VudGVycyA9IDA7XG4gICAgICAgICAgICAgICAgbGV0IHRvdGFsV2lkZUNvdW50ZXJzV2lkdGggPSAwO1xuICAgICAgICAgICAgICAgIGxldCBwYXR0ZXJuID0gMDtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUNvdW50ZXJzOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNvdW50ZXIgPSBjb3VudGVyc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvdW50ZXIgPiBtYXhOYXJyb3dDb3VudGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuIHw9IDEgPDwgKG51bUNvdW50ZXJzIC0gMSAtIGkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgd2lkZUNvdW50ZXJzKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB0b3RhbFdpZGVDb3VudGVyc1dpZHRoICs9IGNvdW50ZXI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHdpZGVDb3VudGVycyA9PT0gMykge1xuICAgICAgICAgICAgICAgICAgICAvLyBGb3VuZCAzIHdpZGUgY291bnRlcnMsIGJ1dCBhcmUgdGhleSBjbG9zZSBlbm91Z2ggaW4gd2lkdGg/XG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIGNhbiBwZXJmb3JtIGEgY2hlYXAsIGNvbnNlcnZhdGl2ZSBjaGVjayB0byBzZWUgaWYgYW55IGluZGl2aWR1YWxcbiAgICAgICAgICAgICAgICAgICAgLy8gY291bnRlciBpcyBtb3JlIHRoYW4gMS41IHRpbWVzIHRoZSBhdmVyYWdlOlxuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUNvdW50ZXJzICYmIHdpZGVDb3VudGVycyA+IDA7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNvdW50ZXIgPSBjb3VudGVyc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb3VudGVyID4gbWF4TmFycm93Q291bnRlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZGVDb3VudGVycy0tO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRvdGFsV2lkZUNvdW50ZXJzV2lkdGggPSAzICogYXZlcmFnZSwgc28gdGhpcyBjaGVja3MgaWYgY291bnRlciA+PSAzLzIgKiBhdmVyYWdlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChjb3VudGVyICogMikgPj0gdG90YWxXaWRlQ291bnRlcnNXaWR0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXR0ZXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gd2hpbGUgKHdpZGVDb3VudGVycyA+IDMpO1xuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBwYXR0ZXJuVG9DaGFyKHBhdHRlcm4pIHtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgQ29kZTM5UmVhZGVyLkNIQVJBQ1RFUl9FTkNPRElOR1MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoQ29kZTM5UmVhZGVyLkNIQVJBQ1RFUl9FTkNPRElOR1NbaV0gPT09IHBhdHRlcm4pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIENvZGUzOVJlYWRlci5BTFBIQUJFVF9TVFJJTkcuY2hhckF0KGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChwYXR0ZXJuID09PSBDb2RlMzlSZWFkZXIuQVNURVJJU0tfRU5DT0RJTkcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJyonO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGRlY29kZUV4dGVuZGVkKGVuY29kZWQpIHtcbiAgICAgICAgICAgIGxldCBsZW5ndGggPSBlbmNvZGVkLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBkZWNvZGVkID0gJyc7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IGMgPSBlbmNvZGVkLmNoYXJBdChpKTtcbiAgICAgICAgICAgICAgICBpZiAoYyA9PT0gJysnIHx8IGMgPT09ICckJyB8fCBjID09PSAnJScgfHwgYyA9PT0gJy8nKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBuZXh0ID0gZW5jb2RlZC5jaGFyQXQoaSArIDEpO1xuICAgICAgICAgICAgICAgICAgICBsZXQgZGVjb2RlZENoYXIgPSAnXFwwJztcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChjKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICcrJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyArQSB0byArWiBtYXAgdG8gYSB0byB6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5leHQgPj0gJ0EnICYmIG5leHQgPD0gJ1onKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY29kZWRDaGFyID0gU3RyaW5nLmZyb21DaGFyQ29kZShuZXh0LmNoYXJDb2RlQXQoMCkgKyAzMik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnJCc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gJEEgdG8gJFogbWFwIHRvIGNvbnRyb2wgY29kZXMgU0ggdG8gU0JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobmV4dCA+PSAnQScgJiYgbmV4dCA8PSAnWicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjb2RlZENoYXIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKG5leHQuY2hhckNvZGVBdCgwKSAtIDY0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICclJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAlQSB0byAlRSBtYXAgdG8gY29udHJvbCBjb2RlcyBFU0MgdG8gVVNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobmV4dCA+PSAnQScgJiYgbmV4dCA8PSAnRScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjb2RlZENoYXIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKG5leHQuY2hhckNvZGVBdCgwKSAtIDM4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobmV4dCA+PSAnRicgJiYgbmV4dCA8PSAnSicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjb2RlZENoYXIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKG5leHQuY2hhckNvZGVBdCgwKSAtIDExKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobmV4dCA+PSAnSycgJiYgbmV4dCA8PSAnTycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjb2RlZENoYXIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKG5leHQuY2hhckNvZGVBdCgwKSArIDE2KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobmV4dCA+PSAnUCcgJiYgbmV4dCA8PSAnVCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjb2RlZENoYXIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKG5leHQuY2hhckNvZGVBdCgwKSArIDQzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobmV4dCA9PT0gJ1UnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY29kZWRDaGFyID0gJ1xcMCc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKG5leHQgPT09ICdWJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNvZGVkQ2hhciA9ICdAJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobmV4dCA9PT0gJ1cnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY29kZWRDaGFyID0gJ2AnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChuZXh0ID09PSAnWCcgfHwgbmV4dCA9PT0gJ1knIHx8IG5leHQgPT09ICdaJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNvZGVkQ2hhciA9ICdcXHg3Zic7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnLyc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gL0EgdG8gL08gbWFwIHRvICEgdG8gLCBhbmQgL1ogbWFwcyB0byA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5leHQgPj0gJ0EnICYmIG5leHQgPD0gJ08nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY29kZWRDaGFyID0gU3RyaW5nLmZyb21DaGFyQ29kZShuZXh0LmNoYXJDb2RlQXQoMCkgLSAzMik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKG5leHQgPT09ICdaJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNvZGVkQ2hhciA9ICc6JztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZGVjb2RlZCArPSBkZWNvZGVkQ2hhcjtcbiAgICAgICAgICAgICAgICAgICAgLy8gYnVtcCB1cCBpIGFnYWluIHNpbmNlIHdlIHJlYWQgdHdvIGNoYXJhY3RlcnNcbiAgICAgICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZGVjb2RlZCArPSBjO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBkZWNvZGVkO1xuICAgICAgICB9XG4gICAgfVxuICAgIENvZGUzOVJlYWRlci5BTFBIQUJFVF9TVFJJTkcgPSAnMDEyMzQ1Njc4OUFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaLS4gJC8rJSc7XG4gICAgLyoqXG4gICAgICogVGhlc2UgcmVwcmVzZW50IHRoZSBlbmNvZGluZ3Mgb2YgY2hhcmFjdGVycywgYXMgcGF0dGVybnMgb2Ygd2lkZSBhbmQgbmFycm93IGJhcnMuXG4gICAgICogVGhlIDkgbGVhc3Qtc2lnbmlmaWNhbnQgYml0cyBvZiBlYWNoIGludCBjb3JyZXNwb25kIHRvIHRoZSBwYXR0ZXJuIG9mIHdpZGUgYW5kIG5hcnJvdyxcbiAgICAgKiB3aXRoIDFzIHJlcHJlc2VudGluZyBcIndpZGVcIiBhbmQgMHMgcmVwcmVzZW50aW5nIG5hcnJvdy5cbiAgICAgKi9cbiAgICBDb2RlMzlSZWFkZXIuQ0hBUkFDVEVSX0VOQ09ESU5HUyA9IFtcbiAgICAgICAgMHgwMzQsIDB4MTIxLCAweDA2MSwgMHgxNjAsIDB4MDMxLCAweDEzMCwgMHgwNzAsIDB4MDI1LCAweDEyNCwgMHgwNjQsXG4gICAgICAgIDB4MTA5LCAweDA0OSwgMHgxNDgsIDB4MDE5LCAweDExOCwgMHgwNTgsIDB4MDBELCAweDEwQywgMHgwNEMsIDB4MDFDLFxuICAgICAgICAweDEwMywgMHgwNDMsIDB4MTQyLCAweDAxMywgMHgxMTIsIDB4MDUyLCAweDAwNywgMHgxMDYsIDB4MDQ2LCAweDAxNixcbiAgICAgICAgMHgxODEsIDB4MEMxLCAweDFDMCwgMHgwOTEsIDB4MTkwLCAweDBEMCwgMHgwODUsIDB4MTg0LCAweDBDNCwgMHgwQTgsXG4gICAgICAgIDB4MEEyLCAweDA4QSwgMHgwMkEgLy8gLy0lXG4gICAgXTtcbiAgICBDb2RlMzlSZWFkZXIuQVNURVJJU0tfRU5DT0RJTkcgPSAweDA5NDtcblxuICAgIC8qKlxuICAgICAqIDxwPkRlY29kZXMgSVRGIGJhcmNvZGVzLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgVGppZWNvXG4gICAgICovXG4gICAgY2xhc3MgSVRGUmVhZGVyIGV4dGVuZHMgT25lRFJlYWRlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgLy8gcHJpdmF0ZSBzdGF0aWMgVyA9IDM7IC8vIFBpeGVsIHdpZHRoIG9mIGEgM3ggd2lkZSBsaW5lXG4gICAgICAgICAgICAvLyBwcml2YXRlIHN0YXRpYyB3ID0gMjsgLy8gUGl4ZWwgd2lkdGggb2YgYSAyeCB3aWRlIGxpbmVcbiAgICAgICAgICAgIC8vIHByaXZhdGUgc3RhdGljIE4gPSAxOyAvLyBQaXhlZCB3aWR0aCBvZiBhIG5hcnJvdyBsaW5lXG4gICAgICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICAgICAgLy8gU3RvcmVzIHRoZSBhY3R1YWwgbmFycm93IGxpbmUgd2lkdGggb2YgdGhlIGltYWdlIGJlaW5nIGRlY29kZWQuXG4gICAgICAgICAgICB0aGlzLm5hcnJvd0xpbmVXaWR0aCA9IC0xO1xuICAgICAgICB9XG4gICAgICAgIC8vIFNlZSBJVEZXcml0ZXIuUEFUVEVSTlNcbiAgICAgICAgLypcbiAgICAgIFxuICAgICAgICAvISoqXG4gICAgICAgICAqIFBhdHRlcm5zIG9mIFdpZGUgLyBOYXJyb3cgbGluZXMgdG8gaW5kaWNhdGUgZWFjaCBkaWdpdFxuICAgICAgICAgKiEvXG4gICAgICAgICovXG4gICAgICAgIGRlY29kZVJvdyhyb3dOdW1iZXIsIHJvdywgaGludHMpIHtcbiAgICAgICAgICAgIC8vIEZpbmQgb3V0IHdoZXJlIHRoZSBNaWRkbGUgc2VjdGlvbiAocGF5bG9hZCkgc3RhcnRzICYgZW5kc1xuICAgICAgICAgICAgbGV0IHN0YXJ0UmFuZ2UgPSB0aGlzLmRlY29kZVN0YXJ0KHJvdyk7XG4gICAgICAgICAgICBsZXQgZW5kUmFuZ2UgPSB0aGlzLmRlY29kZUVuZChyb3cpO1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICBJVEZSZWFkZXIuZGVjb2RlTWlkZGxlKHJvdywgc3RhcnRSYW5nZVsxXSwgZW5kUmFuZ2VbMF0sIHJlc3VsdCk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0U3RyaW5nID0gcmVzdWx0LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICBsZXQgYWxsb3dlZExlbmd0aHMgPSBudWxsO1xuICAgICAgICAgICAgaWYgKGhpbnRzICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBhbGxvd2VkTGVuZ3RocyA9IGhpbnRzLmdldChEZWNvZGVIaW50VHlwZSQxLkFMTE9XRURfTEVOR1RIUyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYWxsb3dlZExlbmd0aHMgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGFsbG93ZWRMZW5ndGhzID0gSVRGUmVhZGVyLkRFRkFVTFRfQUxMT1dFRF9MRU5HVEhTO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gVG8gYXZvaWQgZmFsc2UgcG9zaXRpdmVzIHdpdGggMkQgYmFyY29kZXMgKGFuZCBvdGhlciBwYXR0ZXJucyksIG1ha2VcbiAgICAgICAgICAgIC8vIGFuIGFzc3VtcHRpb24gdGhhdCB0aGUgZGVjb2RlZCBzdHJpbmcgbXVzdCBiZSBhICdzdGFuZGFyZCcgbGVuZ3RoIGlmIGl0J3Mgc2hvcnRcbiAgICAgICAgICAgIGxldCBsZW5ndGggPSByZXN1bHRTdHJpbmcubGVuZ3RoO1xuICAgICAgICAgICAgbGV0IGxlbmd0aE9LID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgbWF4QWxsb3dlZExlbmd0aCA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCB2YWx1ZSBvZiBhbGxvd2VkTGVuZ3Rocykge1xuICAgICAgICAgICAgICAgIGlmIChsZW5ndGggPT09IHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGxlbmd0aE9LID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA+IG1heEFsbG93ZWRMZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgbWF4QWxsb3dlZExlbmd0aCA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghbGVuZ3RoT0sgJiYgbGVuZ3RoID4gbWF4QWxsb3dlZExlbmd0aCkge1xuICAgICAgICAgICAgICAgIGxlbmd0aE9LID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghbGVuZ3RoT0spIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBwb2ludHMgPSBbbmV3IFJlc3VsdFBvaW50KHN0YXJ0UmFuZ2VbMV0sIHJvd051bWJlciksIG5ldyBSZXN1bHRQb2ludChlbmRSYW5nZVswXSwgcm93TnVtYmVyKV07XG4gICAgICAgICAgICBsZXQgcmVzdWx0UmV0dXJuID0gbmV3IFJlc3VsdChyZXN1bHRTdHJpbmcsIG51bGwsIC8vIG5vIG5hdHVyYWwgYnl0ZSByZXByZXNlbnRhdGlvbiBmb3IgdGhlc2UgYmFyY29kZXNcbiAgICAgICAgICAgIDAsIHBvaW50cywgQmFyY29kZUZvcm1hdCQxLklURiwgbmV3IERhdGUoKS5nZXRUaW1lKCkpO1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdFJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvKlxuICAgICAgICAvISoqXG4gICAgICAgICAqIEBwYXJhbSByb3cgICAgICAgICAgcm93IG9mIGJsYWNrL3doaXRlIHZhbHVlcyB0byBzZWFyY2hcbiAgICAgICAgICogQHBhcmFtIHBheWxvYWRTdGFydCBvZmZzZXQgb2Ygc3RhcnQgcGF0dGVyblxuICAgICAgICAgKiBAcGFyYW0gcmVzdWx0U3RyaW5nIHtAbGluayBTdHJpbmdCdWlsZGVyfSB0byBhcHBlbmQgZGVjb2RlZCBjaGFycyB0b1xuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIGRlY29kaW5nIGNvdWxkIG5vdCBjb21wbGV0ZSBzdWNjZXNzZnVsbHlcbiAgICAgICAgICohLyovXG4gICAgICAgIHN0YXRpYyBkZWNvZGVNaWRkbGUocm93LCBwYXlsb2FkU3RhcnQsIHBheWxvYWRFbmQsIHJlc3VsdFN0cmluZykge1xuICAgICAgICAgICAgLy8gRGlnaXRzIGFyZSBpbnRlcmxlYXZlZCBpbiBwYWlycyAtIDUgYmxhY2sgbGluZXMgZm9yIG9uZSBkaWdpdCwgYW5kIHRoZVxuICAgICAgICAgICAgLy8gNVxuICAgICAgICAgICAgLy8gaW50ZXJsZWF2ZWQgd2hpdGUgbGluZXMgZm9yIHRoZSBzZWNvbmQgZGlnaXQuXG4gICAgICAgICAgICAvLyBUaGVyZWZvcmUsIG5lZWQgdG8gc2NhbiAxMCBsaW5lcyBhbmQgdGhlblxuICAgICAgICAgICAgLy8gc3BsaXQgdGhlc2UgaW50byB0d28gYXJyYXlzXG4gICAgICAgICAgICBsZXQgY291bnRlckRpZ2l0UGFpciA9IG5ldyBJbnQzMkFycmF5KDEwKTsgLy8gMTBcbiAgICAgICAgICAgIGxldCBjb3VudGVyQmxhY2sgPSBuZXcgSW50MzJBcnJheSg1KTsgLy8gNVxuICAgICAgICAgICAgbGV0IGNvdW50ZXJXaGl0ZSA9IG5ldyBJbnQzMkFycmF5KDUpOyAvLyA1XG4gICAgICAgICAgICBjb3VudGVyRGlnaXRQYWlyLmZpbGwoMCk7XG4gICAgICAgICAgICBjb3VudGVyQmxhY2suZmlsbCgwKTtcbiAgICAgICAgICAgIGNvdW50ZXJXaGl0ZS5maWxsKDApO1xuICAgICAgICAgICAgd2hpbGUgKHBheWxvYWRTdGFydCA8IHBheWxvYWRFbmQpIHtcbiAgICAgICAgICAgICAgICAvLyBHZXQgMTAgcnVucyBvZiBibGFjay93aGl0ZS5cbiAgICAgICAgICAgICAgICBPbmVEUmVhZGVyLnJlY29yZFBhdHRlcm4ocm93LCBwYXlsb2FkU3RhcnQsIGNvdW50ZXJEaWdpdFBhaXIpO1xuICAgICAgICAgICAgICAgIC8vIFNwbGl0IHRoZW0gaW50byBlYWNoIGFycmF5XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCA1OyBrKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHR3b0sgPSAyICogaztcbiAgICAgICAgICAgICAgICAgICAgY291bnRlckJsYWNrW2tdID0gY291bnRlckRpZ2l0UGFpclt0d29LXTtcbiAgICAgICAgICAgICAgICAgICAgY291bnRlcldoaXRlW2tdID0gY291bnRlckRpZ2l0UGFpclt0d29LICsgMV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCBiZXN0TWF0Y2ggPSBJVEZSZWFkZXIuZGVjb2RlRGlnaXQoY291bnRlckJsYWNrKTtcbiAgICAgICAgICAgICAgICByZXN1bHRTdHJpbmcuYXBwZW5kKGJlc3RNYXRjaC50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICBiZXN0TWF0Y2ggPSB0aGlzLmRlY29kZURpZ2l0KGNvdW50ZXJXaGl0ZSk7XG4gICAgICAgICAgICAgICAgcmVzdWx0U3RyaW5nLmFwcGVuZChiZXN0TWF0Y2gudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgY291bnRlckRpZ2l0UGFpci5mb3JFYWNoKGZ1bmN0aW9uIChjb3VudGVyRGlnaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF5bG9hZFN0YXJ0ICs9IGNvdW50ZXJEaWdpdDtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKi8hKipcbiAgICAgICAgICogSWRlbnRpZnkgd2hlcmUgdGhlIHN0YXJ0IG9mIHRoZSBtaWRkbGUgLyBwYXlsb2FkIHNlY3Rpb24gc3RhcnRzLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gcm93IHJvdyBvZiBibGFjay93aGl0ZSB2YWx1ZXMgdG8gc2VhcmNoXG4gICAgICAgICAqIEByZXR1cm4gQXJyYXksIGNvbnRhaW5pbmcgaW5kZXggb2Ygc3RhcnQgb2YgJ3N0YXJ0IGJsb2NrJyBhbmQgZW5kIG9mXG4gICAgICAgICAqICAgICAgICAgJ3N0YXJ0IGJsb2NrJ1xuICAgICAgICAgKiEvKi9cbiAgICAgICAgZGVjb2RlU3RhcnQocm93KSB7XG4gICAgICAgICAgICBsZXQgZW5kU3RhcnQgPSBJVEZSZWFkZXIuc2tpcFdoaXRlU3BhY2Uocm93KTtcbiAgICAgICAgICAgIGxldCBzdGFydFBhdHRlcm4gPSBJVEZSZWFkZXIuZmluZEd1YXJkUGF0dGVybihyb3csIGVuZFN0YXJ0LCBJVEZSZWFkZXIuU1RBUlRfUEFUVEVSTik7XG4gICAgICAgICAgICAvLyBEZXRlcm1pbmUgdGhlIHdpZHRoIG9mIGEgbmFycm93IGxpbmUgaW4gcGl4ZWxzLiBXZSBjYW4gZG8gdGhpcyBieVxuICAgICAgICAgICAgLy8gZ2V0dGluZyB0aGUgd2lkdGggb2YgdGhlIHN0YXJ0IHBhdHRlcm4gYW5kIGRpdmlkaW5nIGJ5IDQgYmVjYXVzZSBpdHNcbiAgICAgICAgICAgIC8vIG1hZGUgdXAgb2YgNCBuYXJyb3cgbGluZXMuXG4gICAgICAgICAgICB0aGlzLm5hcnJvd0xpbmVXaWR0aCA9IChzdGFydFBhdHRlcm5bMV0gLSBzdGFydFBhdHRlcm5bMF0pIC8gNDtcbiAgICAgICAgICAgIHRoaXMudmFsaWRhdGVRdWlldFpvbmUocm93LCBzdGFydFBhdHRlcm5bMF0pO1xuICAgICAgICAgICAgcmV0dXJuIHN0YXJ0UGF0dGVybjtcbiAgICAgICAgfVxuICAgICAgICAvKi8hKipcbiAgICAgICAgICogVGhlIHN0YXJ0ICYgZW5kIHBhdHRlcm5zIG11c3QgYmUgcHJlL3Bvc3QgZml4ZWQgYnkgYSBxdWlldCB6b25lLiBUaGlzXG4gICAgICAgICAqIHpvbmUgbXVzdCBiZSBhdCBsZWFzdCAxMCB0aW1lcyB0aGUgd2lkdGggb2YgYSBuYXJyb3cgbGluZS4gIFNjYW4gYmFjayB1bnRpbFxuICAgICAgICAgKiB3ZSBlaXRoZXIgZ2V0IHRvIHRoZSBzdGFydCBvZiB0aGUgYmFyY29kZSBvciBtYXRjaCB0aGUgbmVjZXNzYXJ5IG51bWJlciBvZlxuICAgICAgICAgKiBxdWlldCB6b25lIHBpeGVscy5cbiAgICAgICAgICpcbiAgICAgICAgICogTm90ZTogSXRzIGFzc3VtZWQgdGhlIHJvdyBpcyByZXZlcnNlZCB3aGVuIHVzaW5nIHRoaXMgbWV0aG9kIHRvIGZpbmRcbiAgICAgICAgICogcXVpZXQgem9uZSBhZnRlciB0aGUgZW5kIHBhdHRlcm4uXG4gICAgICAgICAqXG4gICAgICAgICAqIHJlZjogaHR0cDovL3d3dy5iYXJjb2RlLTEubmV0L2kyNWNvZGUuaHRtbFxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gcm93IGJpdCBhcnJheSByZXByZXNlbnRpbmcgdGhlIHNjYW5uZWQgYmFyY29kZS5cbiAgICAgICAgICogQHBhcmFtIHN0YXJ0UGF0dGVybiBpbmRleCBpbnRvIHJvdyBvZiB0aGUgc3RhcnQgb3IgZW5kIHBhdHRlcm4uXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gaWYgdGhlIHF1aWV0IHpvbmUgY2Fubm90IGJlIGZvdW5kXG4gICAgICAgICAqIS8qL1xuICAgICAgICB2YWxpZGF0ZVF1aWV0Wm9uZShyb3csIHN0YXJ0UGF0dGVybikge1xuICAgICAgICAgICAgbGV0IHF1aWV0Q291bnQgPSB0aGlzLm5hcnJvd0xpbmVXaWR0aCAqIDEwOyAvLyBleHBlY3QgdG8gZmluZCB0aGlzIG1hbnkgcGl4ZWxzIG9mIHF1aWV0IHpvbmVcbiAgICAgICAgICAgIC8vIGlmIHRoZXJlIGFyZSBub3Qgc28gbWFueSBwaXhlbCBhdCBhbGwgbGV0J3MgdHJ5IGFzIG1hbnkgYXMgcG9zc2libGVcbiAgICAgICAgICAgIHF1aWV0Q291bnQgPSBxdWlldENvdW50IDwgc3RhcnRQYXR0ZXJuID8gcXVpZXRDb3VudCA6IHN0YXJ0UGF0dGVybjtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdGFydFBhdHRlcm4gLSAxOyBxdWlldENvdW50ID4gMCAmJiBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgICAgIGlmIChyb3cuZ2V0KGkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBxdWlldENvdW50LS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocXVpZXRDb3VudCAhPT0gMCkge1xuICAgICAgICAgICAgICAgIC8vIFVuYWJsZSB0byBmaW5kIHRoZSBuZWNlc3NhcnkgbnVtYmVyIG9mIHF1aWV0IHpvbmUgcGl4ZWxzLlxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qXG4gICAgICAgIC8hKipcbiAgICAgICAgICogU2tpcCBhbGwgd2hpdGVzcGFjZSB1bnRpbCB3ZSBnZXQgdG8gdGhlIGZpcnN0IGJsYWNrIGxpbmUuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSByb3cgcm93IG9mIGJsYWNrL3doaXRlIHZhbHVlcyB0byBzZWFyY2hcbiAgICAgICAgICogQHJldHVybiBpbmRleCBvZiB0aGUgZmlyc3QgYmxhY2sgbGluZS5cbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBUaHJvd3MgZXhjZXB0aW9uIGlmIG5vIGJsYWNrIGxpbmVzIGFyZSBmb3VuZCBpbiB0aGUgcm93XG4gICAgICAgICAqIS8qL1xuICAgICAgICBzdGF0aWMgc2tpcFdoaXRlU3BhY2Uocm93KSB7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IHJvdy5nZXRTaXplKCk7XG4gICAgICAgICAgICBjb25zdCBlbmRTdGFydCA9IHJvdy5nZXROZXh0U2V0KDApO1xuICAgICAgICAgICAgaWYgKGVuZFN0YXJ0ID09PSB3aWR0aCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGVuZFN0YXJ0O1xuICAgICAgICB9XG4gICAgICAgIC8qLyEqKlxuICAgICAgICAgKiBJZGVudGlmeSB3aGVyZSB0aGUgZW5kIG9mIHRoZSBtaWRkbGUgLyBwYXlsb2FkIHNlY3Rpb24gZW5kcy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHJvdyByb3cgb2YgYmxhY2svd2hpdGUgdmFsdWVzIHRvIHNlYXJjaFxuICAgICAgICAgKiBAcmV0dXJuIEFycmF5LCBjb250YWluaW5nIGluZGV4IG9mIHN0YXJ0IG9mICdlbmQgYmxvY2snIGFuZCBlbmQgb2YgJ2VuZFxuICAgICAgICAgKiAgICAgICAgIGJsb2NrJ1xuICAgICAgICAgKiEvKi9cbiAgICAgICAgZGVjb2RlRW5kKHJvdykge1xuICAgICAgICAgICAgLy8gRm9yIGNvbnZlbmllbmNlLCByZXZlcnNlIHRoZSByb3cgYW5kIHRoZW5cbiAgICAgICAgICAgIC8vIHNlYXJjaCBmcm9tICd0aGUgc3RhcnQnIGZvciB0aGUgZW5kIGJsb2NrXG4gICAgICAgICAgICByb3cucmV2ZXJzZSgpO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBsZXQgZW5kU3RhcnQgPSBJVEZSZWFkZXIuc2tpcFdoaXRlU3BhY2Uocm93KTtcbiAgICAgICAgICAgICAgICBsZXQgZW5kUGF0dGVybjtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBlbmRQYXR0ZXJuID0gSVRGUmVhZGVyLmZpbmRHdWFyZFBhdHRlcm4ocm93LCBlbmRTdGFydCwgSVRGUmVhZGVyLkVORF9QQVRURVJOX1JFVkVSU0VEWzBdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIE5vdEZvdW5kRXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbmRQYXR0ZXJuID0gSVRGUmVhZGVyLmZpbmRHdWFyZFBhdHRlcm4ocm93LCBlbmRTdGFydCwgSVRGUmVhZGVyLkVORF9QQVRURVJOX1JFVkVSU0VEWzFdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBUaGUgc3RhcnQgJiBlbmQgcGF0dGVybnMgbXVzdCBiZSBwcmUvcG9zdCBmaXhlZCBieSBhIHF1aWV0IHpvbmUuIFRoaXNcbiAgICAgICAgICAgICAgICAvLyB6b25lIG11c3QgYmUgYXQgbGVhc3QgMTAgdGltZXMgdGhlIHdpZHRoIG9mIGEgbmFycm93IGxpbmUuXG4gICAgICAgICAgICAgICAgLy8gcmVmOiBodHRwOi8vd3d3LmJhcmNvZGUtMS5uZXQvaTI1Y29kZS5odG1sXG4gICAgICAgICAgICAgICAgdGhpcy52YWxpZGF0ZVF1aWV0Wm9uZShyb3csIGVuZFBhdHRlcm5bMF0pO1xuICAgICAgICAgICAgICAgIC8vIE5vdyByZWNhbGN1bGF0ZSB0aGUgaW5kaWNlcyBvZiB3aGVyZSB0aGUgJ2VuZGJsb2NrJyBzdGFydHMgJiBzdG9wcyB0b1xuICAgICAgICAgICAgICAgIC8vIGFjY29tbW9kYXRlXG4gICAgICAgICAgICAgICAgLy8gdGhlIHJldmVyc2VkIG5hdHVyZSBvZiB0aGUgc2VhcmNoXG4gICAgICAgICAgICAgICAgbGV0IHRlbXAgPSBlbmRQYXR0ZXJuWzBdO1xuICAgICAgICAgICAgICAgIGVuZFBhdHRlcm5bMF0gPSByb3cuZ2V0U2l6ZSgpIC0gZW5kUGF0dGVyblsxXTtcbiAgICAgICAgICAgICAgICBlbmRQYXR0ZXJuWzFdID0gcm93LmdldFNpemUoKSAtIHRlbXA7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVuZFBhdHRlcm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAvLyBQdXQgdGhlIHJvdyBiYWNrIHRoZSByaWdodCB3YXkuXG4gICAgICAgICAgICAgICAgcm93LnJldmVyc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKlxuICAgICAgICAvISoqXG4gICAgICAgICAqIEBwYXJhbSByb3cgICAgICAgcm93IG9mIGJsYWNrL3doaXRlIHZhbHVlcyB0byBzZWFyY2hcbiAgICAgICAgICogQHBhcmFtIHJvd09mZnNldCBwb3NpdGlvbiB0byBzdGFydCBzZWFyY2hcbiAgICAgICAgICogQHBhcmFtIHBhdHRlcm4gICBwYXR0ZXJuIG9mIGNvdW50cyBvZiBudW1iZXIgb2YgYmxhY2sgYW5kIHdoaXRlIHBpeGVscyB0aGF0IGFyZVxuICAgICAgICAgKiAgICAgICAgICAgICAgICAgIGJlaW5nIHNlYXJjaGVkIGZvciBhcyBhIHBhdHRlcm5cbiAgICAgICAgICogQHJldHVybiBzdGFydC9lbmQgaG9yaXpvbnRhbCBvZmZzZXQgb2YgZ3VhcmQgcGF0dGVybiwgYXMgYW4gYXJyYXkgb2YgdHdvXG4gICAgICAgICAqICAgICAgICAgaW50c1xuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIHBhdHRlcm4gaXMgbm90IGZvdW5kXG4gICAgICAgICAqIS8qL1xuICAgICAgICBzdGF0aWMgZmluZEd1YXJkUGF0dGVybihyb3csIHJvd09mZnNldCwgcGF0dGVybikge1xuICAgICAgICAgICAgbGV0IHBhdHRlcm5MZW5ndGggPSBwYXR0ZXJuLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBjb3VudGVycyA9IG5ldyBJbnQzMkFycmF5KHBhdHRlcm5MZW5ndGgpO1xuICAgICAgICAgICAgbGV0IHdpZHRoID0gcm93LmdldFNpemUoKTtcbiAgICAgICAgICAgIGxldCBpc1doaXRlID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgY291bnRlclBvc2l0aW9uID0gMDtcbiAgICAgICAgICAgIGxldCBwYXR0ZXJuU3RhcnQgPSByb3dPZmZzZXQ7XG4gICAgICAgICAgICBjb3VudGVycy5maWxsKDApO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IHJvd09mZnNldDsgeCA8IHdpZHRoOyB4KyspIHtcbiAgICAgICAgICAgICAgICBpZiAocm93LmdldCh4KSAhPT0gaXNXaGl0ZSkge1xuICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb25dKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY291bnRlclBvc2l0aW9uID09PSBwYXR0ZXJuTGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKE9uZURSZWFkZXIucGF0dGVybk1hdGNoVmFyaWFuY2UoY291bnRlcnMsIHBhdHRlcm4sIElURlJlYWRlci5NQVhfSU5ESVZJRFVBTF9WQVJJQU5DRSkgPCBJVEZSZWFkZXIuTUFYX0FWR19WQVJJQU5DRSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbcGF0dGVyblN0YXJ0LCB4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm5TdGFydCArPSBjb3VudGVyc1swXSArIGNvdW50ZXJzWzFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weShjb3VudGVycywgMiwgY291bnRlcnMsIDAsIGNvdW50ZXJQb3NpdGlvbiAtIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbY291bnRlclBvc2l0aW9uIC0gMV0gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbY291bnRlclBvc2l0aW9uXSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyUG9zaXRpb24tLTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJQb3NpdGlvbisrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbl0gPSAxO1xuICAgICAgICAgICAgICAgICAgICBpc1doaXRlID0gIWlzV2hpdGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgLyovISoqXG4gICAgICAgICAqIEF0dGVtcHRzIHRvIGRlY29kZSBhIHNlcXVlbmNlIG9mIElURiBibGFjay93aGl0ZSBsaW5lcyBpbnRvIHNpbmdsZVxuICAgICAgICAgKiBkaWdpdC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGNvdW50ZXJzIHRoZSBjb3VudHMgb2YgcnVucyBvZiBvYnNlcnZlZCBibGFjay93aGl0ZS9ibGFjay8uLi4gdmFsdWVzXG4gICAgICAgICAqIEByZXR1cm4gVGhlIGRlY29kZWQgZGlnaXRcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBpZiBkaWdpdCBjYW5ub3QgYmUgZGVjb2RlZFxuICAgICAgICAgKiEvKi9cbiAgICAgICAgc3RhdGljIGRlY29kZURpZ2l0KGNvdW50ZXJzKSB7XG4gICAgICAgICAgICBsZXQgYmVzdFZhcmlhbmNlID0gSVRGUmVhZGVyLk1BWF9BVkdfVkFSSUFOQ0U7IC8vIHdvcnN0IHZhcmlhbmNlIHdlJ2xsIGFjY2VwdFxuICAgICAgICAgICAgbGV0IGJlc3RNYXRjaCA9IC0xO1xuICAgICAgICAgICAgbGV0IG1heCA9IElURlJlYWRlci5QQVRURVJOUy5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1heDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IHBhdHRlcm4gPSBJVEZSZWFkZXIuUEFUVEVSTlNbaV07XG4gICAgICAgICAgICAgICAgbGV0IHZhcmlhbmNlID0gT25lRFJlYWRlci5wYXR0ZXJuTWF0Y2hWYXJpYW5jZShjb3VudGVycywgcGF0dGVybiwgSVRGUmVhZGVyLk1BWF9JTkRJVklEVUFMX1ZBUklBTkNFKTtcbiAgICAgICAgICAgICAgICBpZiAodmFyaWFuY2UgPCBiZXN0VmFyaWFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgYmVzdFZhcmlhbmNlID0gdmFyaWFuY2U7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RNYXRjaCA9IGk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHZhcmlhbmNlID09PSBiZXN0VmFyaWFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgZmluZCBhIHNlY29uZCAnYmVzdCBtYXRjaCcgd2l0aCB0aGUgc2FtZSB2YXJpYW5jZSwgd2UgY2FuIG5vdCByZWxpYWJseSByZXBvcnQgdG8gaGF2ZSBhIHN1aXRhYmxlIG1hdGNoXG4gICAgICAgICAgICAgICAgICAgIGJlc3RNYXRjaCA9IC0xO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChiZXN0TWF0Y2ggPj0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBiZXN0TWF0Y2ggJSAxMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIElURlJlYWRlci5QQVRURVJOUyA9IFtcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAyLCAyLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMSwgMSwgMSwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDIsIDEsIDEsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAyLCAxLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMiwgMSwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDEsIDIsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAyLCAyLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMSwgMiwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDEsIDEsIDIsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAyLCAxLCAyLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMywgMywgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDEsIDEsIDEsIDNdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAzLCAxLCAxLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgMywgMSwgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDMsIDEsIDNdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAxLCAzLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMywgMywgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDEsIDMsIDNdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAxLCAxLCAzLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMywgMSwgMywgMV0pIC8vIDlcbiAgICBdO1xuICAgIElURlJlYWRlci5NQVhfQVZHX1ZBUklBTkNFID0gMC4zODtcbiAgICBJVEZSZWFkZXIuTUFYX0lORElWSURVQUxfVkFSSUFOQ0UgPSAwLjU7XG4gICAgLyogLyEqKiBWYWxpZCBJVEYgbGVuZ3Rocy4gQW55dGhpbmcgbG9uZ2VyIHRoYW4gdGhlIGxhcmdlc3QgdmFsdWUgaXMgYWxzbyBhbGxvd2VkLiAqIS8qL1xuICAgIElURlJlYWRlci5ERUZBVUxUX0FMTE9XRURfTEVOR1RIUyA9IFs2LCA4LCAxMCwgMTIsIDE0XTtcbiAgICAvKi8hKipcbiAgICAgKiBTdGFydC9lbmQgZ3VhcmQgcGF0dGVybi5cbiAgICAgKlxuICAgICAqIE5vdGU6IFRoZSBlbmQgcGF0dGVybiBpcyByZXZlcnNlZCBiZWNhdXNlIHRoZSByb3cgaXMgcmV2ZXJzZWQgYmVmb3JlXG4gICAgICogc2VhcmNoaW5nIGZvciB0aGUgRU5EX1BBVFRFUk5cbiAgICAgKiEvKi9cbiAgICBJVEZSZWFkZXIuU1RBUlRfUEFUVEVSTiA9IEludDMyQXJyYXkuZnJvbShbMSwgMSwgMSwgMV0pO1xuICAgIElURlJlYWRlci5FTkRfUEFUVEVSTl9SRVZFUlNFRCA9IFtcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgM10pIC8vIDN4XG4gICAgXTtcblxuICAgIC8qKlxuICAgICAqIDxwPkVuY2Fwc3VsYXRlcyBmdW5jdGlvbmFsaXR5IGFuZCBpbXBsZW1lbnRhdGlvbiB0aGF0IGlzIGNvbW1vbiB0byBVUEMgYW5kIEVBTiBmYW1pbGllc1xuICAgICAqIG9mIG9uZS1kaW1lbnNpb25hbCBiYXJjb2Rlcy48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIGRzd2l0a2luQGdvb2dsZS5jb20gKERhbmllbCBTd2l0a2luKVxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICogQGF1dGhvciBhbGFzZGFpckBnb29nbGUuY29tIChBbGFzZGFpciBNYWNraW50b3NoKVxuICAgICAqL1xuICAgIGNsYXNzIEFic3RyYWN0VVBDRUFOUmVhZGVyIGV4dGVuZHMgT25lRFJlYWRlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgICAgIHRoaXMuZGVjb2RlUm93U3RyaW5nQnVmZmVyID0gJyc7XG4gICAgICAgIH1cblxuICAgICAgICBzdGF0aWMgZmluZFN0YXJ0R3VhcmRQYXR0ZXJuKHJvdykge1xuICAgICAgICAgICAgbGV0IGZvdW5kU3RhcnQgPSBmYWxzZTtcbiAgICAgICAgICAgIGxldCBzdGFydFJhbmdlO1xuICAgICAgICAgICAgbGV0IG5leHRTdGFydCA9IDA7XG4gICAgICAgICAgICBsZXQgY291bnRlcnMgPSBJbnQzMkFycmF5LmZyb20oWzAsIDAsIDBdKTtcbiAgICAgICAgICAgIHdoaWxlICghZm91bmRTdGFydCkge1xuICAgICAgICAgICAgICAgIGNvdW50ZXJzID0gSW50MzJBcnJheS5mcm9tKFswLCAwLCAwXSk7XG4gICAgICAgICAgICAgICAgc3RhcnRSYW5nZSA9IEFic3RyYWN0VVBDRUFOUmVhZGVyLmZpbmRHdWFyZFBhdHRlcm4ocm93LCBuZXh0U3RhcnQsIGZhbHNlLCB0aGlzLlNUQVJUX0VORF9QQVRURVJOLCBjb3VudGVycyk7XG4gICAgICAgICAgICAgICAgbGV0IHN0YXJ0ID0gc3RhcnRSYW5nZVswXTtcbiAgICAgICAgICAgICAgICBuZXh0U3RhcnQgPSBzdGFydFJhbmdlWzFdO1xuICAgICAgICAgICAgICAgIGxldCBxdWlldFN0YXJ0ID0gc3RhcnQgLSAobmV4dFN0YXJ0IC0gc3RhcnQpO1xuICAgICAgICAgICAgICAgIGlmIChxdWlldFN0YXJ0ID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgZm91bmRTdGFydCA9IHJvdy5pc1JhbmdlKHF1aWV0U3RhcnQsIHN0YXJ0LCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN0YXJ0UmFuZ2U7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGNoZWNrQ2hlY2tzdW0ocykge1xuICAgICAgICAgICAgcmV0dXJuIEFic3RyYWN0VVBDRUFOUmVhZGVyLmNoZWNrU3RhbmRhcmRVUENFQU5DaGVja3N1bShzKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgY2hlY2tTdGFuZGFyZFVQQ0VBTkNoZWNrc3VtKHMpIHtcbiAgICAgICAgICAgIGxldCBsZW5ndGggPSBzLmxlbmd0aDtcbiAgICAgICAgICAgIGlmIChsZW5ndGggPT09IDApXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgbGV0IGNoZWNrID0gcGFyc2VJbnQocy5jaGFyQXQobGVuZ3RoIC0gMSksIDEwKTtcbiAgICAgICAgICAgIHJldHVybiBBYnN0cmFjdFVQQ0VBTlJlYWRlci5nZXRTdGFuZGFyZFVQQ0VBTkNoZWNrc3VtKHMuc3Vic3RyaW5nKDAsIGxlbmd0aCAtIDEpKSA9PT0gY2hlY2s7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdldFN0YW5kYXJkVVBDRUFOQ2hlY2tzdW0ocykge1xuICAgICAgICAgICAgbGV0IGxlbmd0aCA9IHMubGVuZ3RoO1xuICAgICAgICAgICAgbGV0IHN1bSA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gbGVuZ3RoIC0gMTsgaSA+PSAwOyBpIC09IDIpIHtcbiAgICAgICAgICAgICAgICBsZXQgZGlnaXQgPSBzLmNoYXJBdChpKS5jaGFyQ29kZUF0KDApIC0gJzAnLmNoYXJDb2RlQXQoMCk7XG4gICAgICAgICAgICAgICAgaWYgKGRpZ2l0IDwgMCB8fCBkaWdpdCA+IDkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzdW0gKz0gZGlnaXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdW0gKj0gMztcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBsZW5ndGggLSAyOyBpID49IDA7IGkgLT0gMikge1xuICAgICAgICAgICAgICAgIGxldCBkaWdpdCA9IHMuY2hhckF0KGkpLmNoYXJDb2RlQXQoMCkgLSAnMCcuY2hhckNvZGVBdCgwKTtcbiAgICAgICAgICAgICAgICBpZiAoZGlnaXQgPCAwIHx8IGRpZ2l0ID4gOSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN1bSArPSBkaWdpdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAoMTAwMCAtIHN1bSkgJSAxMDtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZGVjb2RlRW5kKHJvdywgZW5kU3RhcnQpIHtcbiAgICAgICAgICAgIHJldHVybiBBYnN0cmFjdFVQQ0VBTlJlYWRlci5maW5kR3VhcmRQYXR0ZXJuKHJvdywgZW5kU3RhcnQsIGZhbHNlLCBBYnN0cmFjdFVQQ0VBTlJlYWRlci5TVEFSVF9FTkRfUEFUVEVSTiwgbmV3IEludDMyQXJyYXkoQWJzdHJhY3RVUENFQU5SZWFkZXIuU1RBUlRfRU5EX1BBVFRFUk4ubGVuZ3RoKS5maWxsKDApKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGZpbmRHdWFyZFBhdHRlcm5XaXRob3V0Q291bnRlcnMocm93LCByb3dPZmZzZXQsIHdoaXRlRmlyc3QsIHBhdHRlcm4pIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbmRHdWFyZFBhdHRlcm4ocm93LCByb3dPZmZzZXQsIHdoaXRlRmlyc3QsIHBhdHRlcm4sIG5ldyBJbnQzMkFycmF5KHBhdHRlcm4ubGVuZ3RoKSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSByb3cgcm93IG9mIGJsYWNrL3doaXRlIHZhbHVlcyB0byBzZWFyY2hcbiAgICAgICAgICogQHBhcmFtIHJvd09mZnNldCBwb3NpdGlvbiB0byBzdGFydCBzZWFyY2hcbiAgICAgICAgICogQHBhcmFtIHdoaXRlRmlyc3QgaWYgdHJ1ZSwgaW5kaWNhdGVzIHRoYXQgdGhlIHBhdHRlcm4gc3BlY2lmaWVzIHdoaXRlL2JsYWNrL3doaXRlLy4uLlxuICAgICAgICAgKiBwaXhlbCBjb3VudHMsIG90aGVyd2lzZSwgaXQgaXMgaW50ZXJwcmV0ZWQgYXMgYmxhY2svd2hpdGUvYmxhY2svLi4uXG4gICAgICAgICAqIEBwYXJhbSBwYXR0ZXJuIHBhdHRlcm4gb2YgY291bnRzIG9mIG51bWJlciBvZiBibGFjayBhbmQgd2hpdGUgcGl4ZWxzIHRoYXQgYXJlIGJlaW5nXG4gICAgICAgICAqIHNlYXJjaGVkIGZvciBhcyBhIHBhdHRlcm5cbiAgICAgICAgICogQHBhcmFtIGNvdW50ZXJzIGFycmF5IG9mIGNvdW50ZXJzLCBhcyBsb25nIGFzIHBhdHRlcm4sIHRvIHJlLXVzZVxuICAgICAgICAgKiBAcmV0dXJuIHN0YXJ0L2VuZCBob3Jpem9udGFsIG9mZnNldCBvZiBndWFyZCBwYXR0ZXJuLCBhcyBhbiBhcnJheSBvZiB0d28gaW50c1xuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIHBhdHRlcm4gaXMgbm90IGZvdW5kXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZmluZEd1YXJkUGF0dGVybihyb3csIHJvd09mZnNldCwgd2hpdGVGaXJzdCwgcGF0dGVybiwgY291bnRlcnMpIHtcbiAgICAgICAgICAgIGxldCB3aWR0aCA9IHJvdy5nZXRTaXplKCk7XG4gICAgICAgICAgICByb3dPZmZzZXQgPSB3aGl0ZUZpcnN0ID8gcm93LmdldE5leHRVbnNldChyb3dPZmZzZXQpIDogcm93LmdldE5leHRTZXQocm93T2Zmc2V0KTtcbiAgICAgICAgICAgIGxldCBjb3VudGVyUG9zaXRpb24gPSAwO1xuICAgICAgICAgICAgbGV0IHBhdHRlcm5TdGFydCA9IHJvd09mZnNldDtcbiAgICAgICAgICAgIGxldCBwYXR0ZXJuTGVuZ3RoID0gcGF0dGVybi5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgaXNXaGl0ZSA9IHdoaXRlRmlyc3Q7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gcm93T2Zmc2V0OyB4IDwgd2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgIGlmIChyb3cuZ2V0KHgpICE9PSBpc1doaXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbl0rKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb3VudGVyUG9zaXRpb24gPT09IHBhdHRlcm5MZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoT25lRFJlYWRlci5wYXR0ZXJuTWF0Y2hWYXJpYW5jZShjb3VudGVycywgcGF0dGVybiwgQWJzdHJhY3RVUENFQU5SZWFkZXIuTUFYX0lORElWSURVQUxfVkFSSUFOQ0UpIDwgQWJzdHJhY3RVUENFQU5SZWFkZXIuTUFYX0FWR19WQVJJQU5DRSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBJbnQzMkFycmF5LmZyb20oW3BhdHRlcm5TdGFydCwgeF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVyblN0YXJ0ICs9IGNvdW50ZXJzWzBdICsgY291bnRlcnNbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc2xpY2UgPSBjb3VudGVycy5zbGljZSgyLCBjb3VudGVycy5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnRlclBvc2l0aW9uIC0gMTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbaV0gPSBzbGljZVtpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbiAtIDFdID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbl0gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlclBvc2l0aW9uLS07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyUG9zaXRpb24rKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb25dID0gMTtcbiAgICAgICAgICAgICAgICAgICAgaXNXaGl0ZSA9ICFpc1doaXRlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBkZWNvZGVEaWdpdChyb3csIGNvdW50ZXJzLCByb3dPZmZzZXQsIHBhdHRlcm5zKSB7XG4gICAgICAgICAgICB0aGlzLnJlY29yZFBhdHRlcm4ocm93LCByb3dPZmZzZXQsIGNvdW50ZXJzKTtcbiAgICAgICAgICAgIGxldCBiZXN0VmFyaWFuY2UgPSB0aGlzLk1BWF9BVkdfVkFSSUFOQ0U7XG4gICAgICAgICAgICBsZXQgYmVzdE1hdGNoID0gLTE7XG4gICAgICAgICAgICBsZXQgbWF4ID0gcGF0dGVybnMubGVuZ3RoO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXg7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCBwYXR0ZXJuID0gcGF0dGVybnNbaV07XG4gICAgICAgICAgICAgICAgbGV0IHZhcmlhbmNlID0gT25lRFJlYWRlci5wYXR0ZXJuTWF0Y2hWYXJpYW5jZShjb3VudGVycywgcGF0dGVybiwgQWJzdHJhY3RVUENFQU5SZWFkZXIuTUFYX0lORElWSURVQUxfVkFSSUFOQ0UpO1xuICAgICAgICAgICAgICAgIGlmICh2YXJpYW5jZSA8IGJlc3RWYXJpYW5jZSkge1xuICAgICAgICAgICAgICAgICAgICBiZXN0VmFyaWFuY2UgPSB2YXJpYW5jZTtcbiAgICAgICAgICAgICAgICAgICAgYmVzdE1hdGNoID0gaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYmVzdE1hdGNoID49IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYmVzdE1hdGNoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gVGhlc2UgdHdvIHZhbHVlcyBhcmUgY3JpdGljYWwgZm9yIGRldGVybWluaW5nIGhvdyBwZXJtaXNzaXZlIHRoZSBkZWNvZGluZyB3aWxsIGJlLlxuICAgIC8vIFdlJ3ZlIGFycml2ZWQgYXQgdGhlc2UgdmFsdWVzIHRocm91Z2ggYSBsb3Qgb2YgdHJpYWwgYW5kIGVycm9yLiBTZXR0aW5nIHRoZW0gYW55IGhpZ2hlclxuICAgIC8vIGxldHMgZmFsc2UgcG9zaXRpdmVzIGNyZWVwIGluIHF1aWNrbHkuXG4gICAgQWJzdHJhY3RVUENFQU5SZWFkZXIuTUFYX0FWR19WQVJJQU5DRSA9IDAuNDg7XG4gICAgQWJzdHJhY3RVUENFQU5SZWFkZXIuTUFYX0lORElWSURVQUxfVkFSSUFOQ0UgPSAwLjc7XG4gICAgLyoqXG4gICAgICogU3RhcnQvZW5kIGd1YXJkIHBhdHRlcm4uXG4gICAgICovXG4gICAgQWJzdHJhY3RVUENFQU5SZWFkZXIuU1RBUlRfRU5EX1BBVFRFUk4gPSBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDFdKTtcbiAgICAvKipcbiAgICAgKiBQYXR0ZXJuIG1hcmtpbmcgdGhlIG1pZGRsZSBvZiBhIFVQQy9FQU4gcGF0dGVybiwgc2VwYXJhdGluZyB0aGUgdHdvIGhhbHZlcy5cbiAgICAgKi9cbiAgICBBYnN0cmFjdFVQQ0VBTlJlYWRlci5NSURETEVfUEFUVEVSTiA9IEludDMyQXJyYXkuZnJvbShbMSwgMSwgMSwgMSwgMV0pO1xuICAgIC8qKlxuICAgICAqIGVuZCBndWFyZCBwYXR0ZXJuLlxuICAgICAqL1xuICAgIEFic3RyYWN0VVBDRUFOUmVhZGVyLkVORF9QQVRURVJOID0gSW50MzJBcnJheS5mcm9tKFsxLCAxLCAxLCAxLCAxLCAxXSk7XG4gICAgLyoqXG4gICAgICogXCJPZGRcIiwgb3IgXCJMXCIgcGF0dGVybnMgdXNlZCB0byBlbmNvZGUgVVBDL0VBTiBkaWdpdHMuXG4gICAgICovXG4gICAgQWJzdHJhY3RVUENFQU5SZWFkZXIuTF9QQVRURVJOUyA9IFtcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAyLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMiwgMiwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDEsIDIsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCA0LCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMywgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDIsIDMsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAxLCA0XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMywgMSwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDIsIDEsIDNdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAxLCAxLCAyXSksXG4gICAgXTtcblxuICAgIC8qKlxuICAgICAqIEBzZWUgVVBDRUFORXh0ZW5zaW9uMlN1cHBvcnRcbiAgICAgKi9cbiAgICBjbGFzcyBVUENFQU5FeHRlbnNpb241U3VwcG9ydCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgdGhpcy5DSEVDS19ESUdJVF9FTkNPRElOR1MgPSBbMHgxOCwgMHgxNCwgMHgxMiwgMHgxMSwgMHgwQywgMHgwNiwgMHgwMywgMHgwQSwgMHgwOSwgMHgwNV07XG4gICAgICAgICAgICB0aGlzLmRlY29kZU1pZGRsZUNvdW50ZXJzID0gSW50MzJBcnJheS5mcm9tKFswLCAwLCAwLCAwXSk7XG4gICAgICAgICAgICB0aGlzLmRlY29kZVJvd1N0cmluZ0J1ZmZlciA9ICcnO1xuICAgICAgICB9XG4gICAgICAgIGRlY29kZVJvdyhyb3dOdW1iZXIsIHJvdywgZXh0ZW5zaW9uU3RhcnRSYW5nZSkge1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IHRoaXMuZGVjb2RlUm93U3RyaW5nQnVmZmVyO1xuICAgICAgICAgICAgbGV0IGVuZCA9IHRoaXMuZGVjb2RlTWlkZGxlKHJvdywgZXh0ZW5zaW9uU3RhcnRSYW5nZSwgcmVzdWx0KTtcbiAgICAgICAgICAgIGxldCByZXN1bHRTdHJpbmcgPSByZXN1bHQudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGxldCBleHRlbnNpb25EYXRhID0gVVBDRUFORXh0ZW5zaW9uNVN1cHBvcnQucGFyc2VFeHRlbnNpb25TdHJpbmcocmVzdWx0U3RyaW5nKTtcbiAgICAgICAgICAgIGxldCByZXN1bHRQb2ludHMgPSBbXG4gICAgICAgICAgICAgICAgbmV3IFJlc3VsdFBvaW50KChleHRlbnNpb25TdGFydFJhbmdlWzBdICsgZXh0ZW5zaW9uU3RhcnRSYW5nZVsxXSkgLyAyLjAsIHJvd051bWJlciksXG4gICAgICAgICAgICAgICAgbmV3IFJlc3VsdFBvaW50KGVuZCwgcm93TnVtYmVyKVxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIGxldCBleHRlbnNpb25SZXN1bHQgPSBuZXcgUmVzdWx0KHJlc3VsdFN0cmluZywgbnVsbCwgMCwgcmVzdWx0UG9pbnRzLCBCYXJjb2RlRm9ybWF0JDEuVVBDX0VBTl9FWFRFTlNJT04sIG5ldyBEYXRlKCkuZ2V0VGltZSgpKTtcbiAgICAgICAgICAgIGlmIChleHRlbnNpb25EYXRhICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBleHRlbnNpb25SZXN1bHQucHV0QWxsTWV0YWRhdGEoZXh0ZW5zaW9uRGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZXh0ZW5zaW9uUmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIGRlY29kZU1pZGRsZShyb3csIHN0YXJ0UmFuZ2UsIHJlc3VsdFN0cmluZykge1xuICAgICAgICAgICAgbGV0IGNvdW50ZXJzID0gdGhpcy5kZWNvZGVNaWRkbGVDb3VudGVycztcbiAgICAgICAgICAgIGNvdW50ZXJzWzBdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzFdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzJdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzNdID0gMDtcbiAgICAgICAgICAgIGxldCBlbmQgPSByb3cuZ2V0U2l6ZSgpO1xuICAgICAgICAgICAgbGV0IHJvd09mZnNldCA9IHN0YXJ0UmFuZ2VbMV07XG4gICAgICAgICAgICBsZXQgbGdQYXR0ZXJuRm91bmQgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCA1ICYmIHJvd09mZnNldCA8IGVuZDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IGJlc3RNYXRjaCA9IEFic3RyYWN0VVBDRUFOUmVhZGVyLmRlY29kZURpZ2l0KFxuICAgICAgICAgICAgICAgICAgICByb3csXG4gICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzLFxuICAgICAgICAgICAgICAgICAgICByb3dPZmZzZXQsXG4gICAgICAgICAgICAgICAgICAgIEFic3RyYWN0VVBDRUFOUmVhZGVyLkxfQU5EX0dfUEFUVEVSTlMpO1xuICAgICAgICAgICAgICAgIHJlc3VsdFN0cmluZyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKCgnMCcuY2hhckNvZGVBdCgwKSArIGJlc3RNYXRjaCAlIDEwKSk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgY291bnRlciBvZiBjb3VudGVycykge1xuICAgICAgICAgICAgICAgICAgICByb3dPZmZzZXQgKz0gY291bnRlcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGJlc3RNYXRjaCA+PSAxMCkge1xuICAgICAgICAgICAgICAgICAgICBsZ1BhdHRlcm5Gb3VuZCB8PSAxIDw8ICg0IC0geCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh4ICE9PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlYWQgb2ZmIHNlcGFyYXRvciBpZiBub3QgbGFzdFxuICAgICAgICAgICAgICAgICAgICByb3dPZmZzZXQgPSByb3cuZ2V0TmV4dFNldChyb3dPZmZzZXQpO1xuICAgICAgICAgICAgICAgICAgICByb3dPZmZzZXQgPSByb3cuZ2V0TmV4dFVuc2V0KHJvd09mZnNldCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJlc3VsdFN0cmluZy5sZW5ndGggIT09IDUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBjaGVja0RpZ2l0ID0gdGhpcy5kZXRlcm1pbmVDaGVja0RpZ2l0KGxnUGF0dGVybkZvdW5kKTtcbiAgICAgICAgICAgIGlmIChVUENFQU5FeHRlbnNpb241U3VwcG9ydC5leHRlbnNpb25DaGVja3N1bShyZXN1bHRTdHJpbmcudG9TdHJpbmcoKSkgIT09IGNoZWNrRGlnaXQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByb3dPZmZzZXQ7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGV4dGVuc2lvbkNoZWNrc3VtKHMpIHtcbiAgICAgICAgICAgIGxldCBsZW5ndGggPSBzLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBzdW0gPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGxlbmd0aCAtIDI7IGkgPj0gMDsgaSAtPSAyKSB7XG4gICAgICAgICAgICAgICAgc3VtICs9IHMuY2hhckF0KGkpLmNoYXJDb2RlQXQoMCkgLSAnMCcuY2hhckNvZGVBdCgwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN1bSAqPSAzO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGxlbmd0aCAtIDE7IGkgPj0gMDsgaSAtPSAyKSB7XG4gICAgICAgICAgICAgICAgc3VtICs9IHMuY2hhckF0KGkpLmNoYXJDb2RlQXQoMCkgLSAnMCcuY2hhckNvZGVBdCgwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN1bSAqPSAzO1xuICAgICAgICAgICAgcmV0dXJuIHN1bSAlIDEwO1xuICAgICAgICB9XG4gICAgICAgIGRldGVybWluZUNoZWNrRGlnaXQobGdQYXR0ZXJuRm91bmQpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGQgPSAwOyBkIDwgMTA7IGQrKykge1xuICAgICAgICAgICAgICAgIGlmIChsZ1BhdHRlcm5Gb3VuZCA9PT0gdGhpcy5DSEVDS19ESUdJVF9FTkNPRElOR1NbZF0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHBhcnNlRXh0ZW5zaW9uU3RyaW5nKHJhdykge1xuICAgICAgICAgICAgaWYgKHJhdy5sZW5ndGggIT09IDUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCB2YWx1ZSA9IFVQQ0VBTkV4dGVuc2lvbjVTdXBwb3J0LnBhcnNlRXh0ZW5zaW9uNVN0cmluZyhyYXcpO1xuICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgTWFwKFtbUmVzdWx0TWV0YWRhdGFUeXBlJDEuU1VHR0VTVEVEX1BSSUNFLCB2YWx1ZV1dKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgcGFyc2VFeHRlbnNpb241U3RyaW5nKHJhdykge1xuICAgICAgICAgICAgbGV0IGN1cnJlbmN5O1xuICAgICAgICAgICAgc3dpdGNoIChyYXcuY2hhckF0KDApKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnMCc6XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gJ8KjJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnNSc6XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gJyQnO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICc5JzpcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVmZXJlbmNlOiBodHRwOi8vd3d3LmpvbGx5dGVjaC5jb21cbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChyYXcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJzkwMDAwJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBObyBzdWdnZXN0ZWQgcmV0YWlsIHByaWNlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICc5OTk5MSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ29tcGxlbWVudGFyeVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnMC4wMCc7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICc5OTk5MCc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdVc2VkJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UuLi4gdW5rbm93biBjdXJyZW5jeT9cbiAgICAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcmF3QW1vdW50ID0gcGFyc2VJbnQocmF3LnN1YnN0cmluZygxKSk7XG4gICAgICAgICAgICBsZXQgdW5pdHNTdHJpbmcgPSAocmF3QW1vdW50IC8gMTAwKS50b1N0cmluZygpO1xuICAgICAgICAgICAgbGV0IGh1bmRyZWR0aHMgPSByYXdBbW91bnQgJSAxMDA7XG4gICAgICAgICAgICBsZXQgaHVuZHJlZHRoc1N0cmluZyA9IGh1bmRyZWR0aHMgPCAxMCA/ICcwJyArIGh1bmRyZWR0aHMgOiBodW5kcmVkdGhzLnRvU3RyaW5nKCk7IC8vIGZpeG1lXG4gICAgICAgICAgICByZXR1cm4gY3VycmVuY3kgKyB1bml0c1N0cmluZyArICcuJyArIGh1bmRyZWR0aHNTdHJpbmc7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAc2VlIFVQQ0VBTkV4dGVuc2lvbjVTdXBwb3J0XG4gICAgICovXG4gICAgY2xhc3MgVVBDRUFORXh0ZW5zaW9uMlN1cHBvcnQge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICAgIHRoaXMuZGVjb2RlTWlkZGxlQ291bnRlcnMgPSBJbnQzMkFycmF5LmZyb20oWzAsIDAsIDAsIDBdKTtcbiAgICAgICAgICAgIHRoaXMuZGVjb2RlUm93U3RyaW5nQnVmZmVyID0gJyc7XG4gICAgICAgIH1cbiAgICAgICAgZGVjb2RlUm93KHJvd051bWJlciwgcm93LCBleHRlbnNpb25TdGFydFJhbmdlKSB7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gdGhpcy5kZWNvZGVSb3dTdHJpbmdCdWZmZXI7XG4gICAgICAgICAgICBsZXQgZW5kID0gdGhpcy5kZWNvZGVNaWRkbGUocm93LCBleHRlbnNpb25TdGFydFJhbmdlLCByZXN1bHQpO1xuICAgICAgICAgICAgbGV0IHJlc3VsdFN0cmluZyA9IHJlc3VsdC50b1N0cmluZygpO1xuICAgICAgICAgICAgbGV0IGV4dGVuc2lvbkRhdGEgPSBVUENFQU5FeHRlbnNpb24yU3VwcG9ydC5wYXJzZUV4dGVuc2lvblN0cmluZyhyZXN1bHRTdHJpbmcpO1xuICAgICAgICAgICAgbGV0IHJlc3VsdFBvaW50cyA9IFtcbiAgICAgICAgICAgICAgICBuZXcgUmVzdWx0UG9pbnQoKGV4dGVuc2lvblN0YXJ0UmFuZ2VbMF0gKyBleHRlbnNpb25TdGFydFJhbmdlWzFdKSAvIDIuMCwgcm93TnVtYmVyKSxcbiAgICAgICAgICAgICAgICBuZXcgUmVzdWx0UG9pbnQoZW5kLCByb3dOdW1iZXIpXG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgbGV0IGV4dGVuc2lvblJlc3VsdCA9IG5ldyBSZXN1bHQocmVzdWx0U3RyaW5nLCBudWxsLCAwLCByZXN1bHRQb2ludHMsIEJhcmNvZGVGb3JtYXQkMS5VUENfRUFOX0VYVEVOU0lPTiwgbmV3IERhdGUoKS5nZXRUaW1lKCkpO1xuICAgICAgICAgICAgaWYgKGV4dGVuc2lvbkRhdGEgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGV4dGVuc2lvblJlc3VsdC5wdXRBbGxNZXRhZGF0YShleHRlbnNpb25EYXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBleHRlbnNpb25SZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgZGVjb2RlTWlkZGxlKHJvdywgc3RhcnRSYW5nZSwgcmVzdWx0U3RyaW5nKSB7XG4gICAgICAgICAgICBsZXQgY291bnRlcnMgPSB0aGlzLmRlY29kZU1pZGRsZUNvdW50ZXJzO1xuICAgICAgICAgICAgY291bnRlcnNbMF0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbMV0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbMl0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbM10gPSAwO1xuICAgICAgICAgICAgbGV0IGVuZCA9IHJvdy5nZXRTaXplKCk7XG4gICAgICAgICAgICBsZXQgcm93T2Zmc2V0ID0gc3RhcnRSYW5nZVsxXTtcbiAgICAgICAgICAgIGxldCBjaGVja1Bhcml0eSA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IDIgJiYgcm93T2Zmc2V0IDwgZW5kOyB4KyspIHtcbiAgICAgICAgICAgICAgICBsZXQgYmVzdE1hdGNoID0gQWJzdHJhY3RVUENFQU5SZWFkZXIuZGVjb2RlRGlnaXQocm93LCBjb3VudGVycywgcm93T2Zmc2V0LCBBYnN0cmFjdFVQQ0VBTlJlYWRlci5MX0FORF9HX1BBVFRFUk5TKTtcbiAgICAgICAgICAgICAgICByZXN1bHRTdHJpbmcgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgoJzAnLmNoYXJDb2RlQXQoMCkgKyBiZXN0TWF0Y2ggJSAxMCkpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGNvdW50ZXIgb2YgY291bnRlcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgcm93T2Zmc2V0ICs9IGNvdW50ZXI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChiZXN0TWF0Y2ggPj0gMTApIHtcbiAgICAgICAgICAgICAgICAgICAgY2hlY2tQYXJpdHkgfD0gMSA8PCAoMSAtIHgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoeCAhPT0gMSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZWFkIG9mZiBzZXBhcmF0b3IgaWYgbm90IGxhc3RcbiAgICAgICAgICAgICAgICAgICAgcm93T2Zmc2V0ID0gcm93LmdldE5leHRTZXQocm93T2Zmc2V0KTtcbiAgICAgICAgICAgICAgICAgICAgcm93T2Zmc2V0ID0gcm93LmdldE5leHRVbnNldChyb3dPZmZzZXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyZXN1bHRTdHJpbmcubGVuZ3RoICE9PSAyKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocGFyc2VJbnQocmVzdWx0U3RyaW5nLnRvU3RyaW5nKCkpICUgNCAhPT0gY2hlY2tQYXJpdHkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByb3dPZmZzZXQ7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHBhcnNlRXh0ZW5zaW9uU3RyaW5nKHJhdykge1xuICAgICAgICAgICAgaWYgKHJhdy5sZW5ndGggIT09IDIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgTWFwKFtbUmVzdWx0TWV0YWRhdGFUeXBlJDEuSVNTVUVfTlVNQkVSLCBwYXJzZUludChyYXcpXV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xhc3MgVVBDRUFORXh0ZW5zaW9uU3VwcG9ydCB7XG4gICAgICAgIHN0YXRpYyBkZWNvZGVSb3cocm93TnVtYmVyLCByb3csIHJvd09mZnNldCkge1xuICAgICAgICAgICAgbGV0IGV4dGVuc2lvblN0YXJ0UmFuZ2UgPSBBYnN0cmFjdFVQQ0VBTlJlYWRlci5maW5kR3VhcmRQYXR0ZXJuKFxuICAgICAgICAgICAgICAgIHJvdyxcbiAgICAgICAgICAgICAgICByb3dPZmZzZXQsXG4gICAgICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgICAgICAgdGhpcy5FWFRFTlNJT05fU1RBUlRfUEFUVEVSTixcbiAgICAgICAgICAgICAgICBuZXcgSW50MzJBcnJheSh0aGlzLkVYVEVOU0lPTl9TVEFSVF9QQVRURVJOLmxlbmd0aCkuZmlsbCgwKSk7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIC8vIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIGxldCBmaXZlU3VwcG9ydCA9IG5ldyBVUENFQU5FeHRlbnNpb241U3VwcG9ydCgpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmaXZlU3VwcG9ydC5kZWNvZGVSb3cocm93TnVtYmVyLCByb3csIGV4dGVuc2lvblN0YXJ0UmFuZ2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIC8vIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIGxldCB0d29TdXBwb3J0ID0gbmV3IFVQQ0VBTkV4dGVuc2lvbjJTdXBwb3J0KCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR3b1N1cHBvcnQuZGVjb2RlUm93KHJvd051bWJlciwgcm93LCBleHRlbnNpb25TdGFydFJhbmdlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBVUENFQU5FeHRlbnNpb25TdXBwb3J0LkVYVEVOU0lPTl9TVEFSVF9QQVRURVJOID0gSW50MzJBcnJheS5mcm9tKFsxLCAxLCAyXSk7XG5cbiAgICAvKipcbiAgICAgKiA8cD5FbmNhcHN1bGF0ZXMgZnVuY3Rpb25hbGl0eSBhbmQgaW1wbGVtZW50YXRpb24gdGhhdCBpcyBjb21tb24gdG8gVVBDIGFuZCBFQU4gZmFtaWxpZXNcbiAgICAgKiBvZiBvbmUtZGltZW5zaW9uYWwgYmFyY29kZXMuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBkc3dpdGtpbkBnb29nbGUuY29tIChEYW5pZWwgU3dpdGtpbilcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqIEBhdXRob3IgYWxhc2RhaXJAZ29vZ2xlLmNvbSAoQWxhc2RhaXIgTWFja2ludG9zaClcbiAgICAgKi9cbiAgICBjbGFzcyBVUENFQU5SZWFkZXIgZXh0ZW5kcyBBYnN0cmFjdFVQQ0VBTlJlYWRlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgICAgIHRoaXMuZGVjb2RlUm93U3RyaW5nQnVmZmVyID0gJyc7XG4gICAgICAgICAgICBVUENFQU5SZWFkZXIuTF9BTkRfR19QQVRURVJOUyA9IFVQQ0VBTlJlYWRlci5MX1BBVFRFUk5TLm1hcChhcnIgPT4gSW50MzJBcnJheS5mcm9tKGFycikpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDEwOyBpIDwgMjA7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCB3aWR0aHMgPSBVUENFQU5SZWFkZXIuTF9QQVRURVJOU1tpIC0gMTBdO1xuICAgICAgICAgICAgICAgIGxldCByZXZlcnNlZFdpZHRocyA9IG5ldyBJbnQzMkFycmF5KHdpZHRocy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgd2lkdGhzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldmVyc2VkV2lkdGhzW2pdID0gd2lkdGhzW3dpZHRocy5sZW5ndGggLSBqIC0gMV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIFVQQ0VBTlJlYWRlci5MX0FORF9HX1BBVFRFUk5TW2ldID0gcmV2ZXJzZWRXaWR0aHM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZGVjb2RlUm93KHJvd051bWJlciwgcm93LCBoaW50cykge1xuICAgICAgICAgICAgbGV0IHN0YXJ0R3VhcmRSYW5nZSA9IFVQQ0VBTlJlYWRlci5maW5kU3RhcnRHdWFyZFBhdHRlcm4ocm93KTtcbiAgICAgICAgICAgIGxldCByZXN1bHRQb2ludENhbGxiYWNrID0gaGludHMgPT0gbnVsbCA/IG51bGwgOiBoaW50cy5nZXQoRGVjb2RlSGludFR5cGUkMS5ORUVEX1JFU1VMVF9QT0lOVF9DQUxMQkFDSyk7XG4gICAgICAgICAgICBpZiAocmVzdWx0UG9pbnRDYWxsYmFjayAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0UG9pbnQgPSBuZXcgUmVzdWx0UG9pbnQoKHN0YXJ0R3VhcmRSYW5nZVswXSArIHN0YXJ0R3VhcmRSYW5nZVsxXSkgLyAyLjAsIHJvd051bWJlcik7XG4gICAgICAgICAgICAgICAgcmVzdWx0UG9pbnRDYWxsYmFjay5mb3VuZFBvc3NpYmxlUmVzdWx0UG9pbnQocmVzdWx0UG9pbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGJ1ZGVsbG8gPSB0aGlzLmRlY29kZU1pZGRsZShyb3csIHN0YXJ0R3VhcmRSYW5nZSwgdGhpcy5kZWNvZGVSb3dTdHJpbmdCdWZmZXIpO1xuICAgICAgICAgICAgbGV0IGVuZFN0YXJ0ID0gYnVkZWxsby5yb3dPZmZzZXQ7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gYnVkZWxsby5yZXN1bHRTdHJpbmc7XG4gICAgICAgICAgICBpZiAocmVzdWx0UG9pbnRDYWxsYmFjayAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0UG9pbnQgPSBuZXcgUmVzdWx0UG9pbnQoZW5kU3RhcnQsIHJvd051bWJlcik7XG4gICAgICAgICAgICAgICAgcmVzdWx0UG9pbnRDYWxsYmFjay5mb3VuZFBvc3NpYmxlUmVzdWx0UG9pbnQocmVzdWx0UG9pbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGVuZFJhbmdlID0gdGhpcy5kZWNvZGVFbmQocm93LCBlbmRTdGFydCk7XG4gICAgICAgICAgICBpZiAocmVzdWx0UG9pbnRDYWxsYmFjayAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0UG9pbnQgPSBuZXcgUmVzdWx0UG9pbnQoKGVuZFJhbmdlWzBdICsgZW5kUmFuZ2VbMV0pIC8gMi4wLCByb3dOdW1iZXIpO1xuICAgICAgICAgICAgICAgIHJlc3VsdFBvaW50Q2FsbGJhY2suZm91bmRQb3NzaWJsZVJlc3VsdFBvaW50KHJlc3VsdFBvaW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSB0aGVyZSBpcyBhIHF1aWV0IHpvbmUgYXQgbGVhc3QgYXMgYmlnIGFzIHRoZSBlbmQgcGF0dGVybiBhZnRlciB0aGUgYmFyY29kZS4gVGhlXG4gICAgICAgICAgICAvLyBzcGVjIG1pZ2h0IHdhbnQgbW9yZSB3aGl0ZXNwYWNlLCBidXQgaW4gcHJhY3RpY2UgdGhpcyBpcyB0aGUgbWF4aW11bSB3ZSBjYW4gY291bnQgb24uXG4gICAgICAgICAgICBsZXQgZW5kID0gZW5kUmFuZ2VbMV07XG4gICAgICAgICAgICBsZXQgcXVpZXRFbmQgPSBlbmQgKyAoZW5kIC0gZW5kUmFuZ2VbMF0pO1xuICAgICAgICAgICAgaWYgKHF1aWV0RW5kID49IHJvdy5nZXRTaXplKCkgfHwgIXJvdy5pc1JhbmdlKGVuZCwgcXVpZXRFbmQsIGZhbHNlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHJlc3VsdFN0cmluZyA9IHJlc3VsdC50b1N0cmluZygpO1xuICAgICAgICAgICAgLy8gVVBDL0VBTiBzaG91bGQgbmV2ZXIgYmUgbGVzcyB0aGFuIDggY2hhcnMgYW55d2F5XG4gICAgICAgICAgICBpZiAocmVzdWx0U3RyaW5nLmxlbmd0aCA8IDgpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIVVQQ0VBTlJlYWRlci5jaGVja0NoZWNrc3VtKHJlc3VsdFN0cmluZykpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQ2hlY2tzdW1FeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBsZWZ0ID0gKHN0YXJ0R3VhcmRSYW5nZVsxXSArIHN0YXJ0R3VhcmRSYW5nZVswXSkgLyAyLjA7XG4gICAgICAgICAgICBsZXQgcmlnaHQgPSAoZW5kUmFuZ2VbMV0gKyBlbmRSYW5nZVswXSkgLyAyLjA7XG4gICAgICAgICAgICBsZXQgZm9ybWF0ID0gdGhpcy5nZXRCYXJjb2RlRm9ybWF0KCk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0UG9pbnQgPSBbbmV3IFJlc3VsdFBvaW50KGxlZnQsIHJvd051bWJlciksIG5ldyBSZXN1bHRQb2ludChyaWdodCwgcm93TnVtYmVyKV07XG4gICAgICAgICAgICBsZXQgZGVjb2RlUmVzdWx0ID0gbmV3IFJlc3VsdChyZXN1bHRTdHJpbmcsIG51bGwsIDAsIHJlc3VsdFBvaW50LCBmb3JtYXQsIG5ldyBEYXRlKCkuZ2V0VGltZSgpKTtcbiAgICAgICAgICAgIGxldCBleHRlbnNpb25MZW5ndGggPSAwO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBsZXQgZXh0ZW5zaW9uUmVzdWx0ID0gVVBDRUFORXh0ZW5zaW9uU3VwcG9ydC5kZWNvZGVSb3cocm93TnVtYmVyLCByb3csIGVuZFJhbmdlWzFdKTtcbiAgICAgICAgICAgICAgICBkZWNvZGVSZXN1bHQucHV0TWV0YWRhdGEoUmVzdWx0TWV0YWRhdGFUeXBlJDEuVVBDX0VBTl9FWFRFTlNJT04sIGV4dGVuc2lvblJlc3VsdC5nZXRUZXh0KCkpO1xuICAgICAgICAgICAgICAgIGRlY29kZVJlc3VsdC5wdXRBbGxNZXRhZGF0YShleHRlbnNpb25SZXN1bHQuZ2V0UmVzdWx0TWV0YWRhdGEoKSk7XG4gICAgICAgICAgICAgICAgZGVjb2RlUmVzdWx0LmFkZFJlc3VsdFBvaW50cyhleHRlbnNpb25SZXN1bHQuZ2V0UmVzdWx0UG9pbnRzKCkpO1xuICAgICAgICAgICAgICAgIGV4dGVuc2lvbkxlbmd0aCA9IGV4dGVuc2lvblJlc3VsdC5nZXRUZXh0KCkubGVuZ3RoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGlnbm9yZUVycm9yKSB7fVxuICAgICAgICAgICAgbGV0IGFsbG93ZWRFeHRlbnNpb25zID0gaGludHMgPT0gbnVsbCA/IG51bGwgOiBoaW50cy5nZXQoRGVjb2RlSGludFR5cGUkMS5BTExPV0VEX0VBTl9FWFRFTlNJT05TKTtcbiAgICAgICAgICAgIGlmIChhbGxvd2VkRXh0ZW5zaW9ucyAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgbGV0IHZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgbGVuZ3RoIGluIGFsbG93ZWRFeHRlbnNpb25zKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChleHRlbnNpb25MZW5ndGgudG9TdHJpbmcoKSA9PT0gbGVuZ3RoKSB7IC8vIGNoZWNrIG1lXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIXZhbGlkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBkZWNvZGVSZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgZGVjb2RlRW5kKHJvdywgZW5kU3RhcnQpIHtcbiAgICAgICAgICAgIHJldHVybiBVUENFQU5SZWFkZXIuZmluZEd1YXJkUGF0dGVybihcbiAgICAgICAgICAgICAgICByb3csIGVuZFN0YXJ0LCBmYWxzZSwgVVBDRUFOUmVhZGVyLlNUQVJUX0VORF9QQVRURVJOLFxuICAgICAgICAgICAgICAgIG5ldyBJbnQzMkFycmF5KFVQQ0VBTlJlYWRlci5TVEFSVF9FTkRfUEFUVEVSTi5sZW5ndGgpLmZpbGwoMCkpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBjaGVja0NoZWNrc3VtKHMpIHtcbiAgICAgICAgICAgIHJldHVybiBVUENFQU5SZWFkZXIuY2hlY2tTdGFuZGFyZFVQQ0VBTkNoZWNrc3VtKHMpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBjaGVja1N0YW5kYXJkVVBDRUFOQ2hlY2tzdW0ocykge1xuICAgICAgICAgICAgbGV0IGxlbmd0aCA9IHMubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKGxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICBsZXQgY2hlY2sgPSBwYXJzZUludChzLmNoYXJBdChsZW5ndGggLSAxKSwgMTApO1xuICAgICAgICAgICAgcmV0dXJuIFVQQ0VBTlJlYWRlci5nZXRTdGFuZGFyZFVQQ0VBTkNoZWNrc3VtKHMuc3Vic3RyaW5nKDAsIGxlbmd0aCAtIDEpKSA9PT0gY2hlY2s7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdldFN0YW5kYXJkVVBDRUFOQ2hlY2tzdW0ocykge1xuICAgICAgICAgICAgbGV0IGxlbmd0aCA9IHMubGVuZ3RoO1xuICAgICAgICAgICAgbGV0IHN1bSA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gbGVuZ3RoIC0gMTsgaSA+PSAwOyBpIC09IDIpIHtcbiAgICAgICAgICAgICAgICBsZXQgZGlnaXQgPSBzLmNoYXJBdChpKS5jaGFyQ29kZUF0KDApIC0gJzAnLmNoYXJDb2RlQXQoMCk7XG4gICAgICAgICAgICAgICAgaWYgKGRpZ2l0IDwgMCB8fCBkaWdpdCA+IDkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzdW0gKz0gZGlnaXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdW0gKj0gMztcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBsZW5ndGggLSAyOyBpID49IDA7IGkgLT0gMikge1xuICAgICAgICAgICAgICAgIGxldCBkaWdpdCA9IHMuY2hhckF0KGkpLmNoYXJDb2RlQXQoMCkgLSAnMCcuY2hhckNvZGVBdCgwKTtcbiAgICAgICAgICAgICAgICBpZiAoZGlnaXQgPCAwIHx8IGRpZ2l0ID4gOSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN1bSArPSBkaWdpdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAoMTAwMCAtIHN1bSkgJSAxMDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDxwPkltcGxlbWVudHMgZGVjb2Rpbmcgb2YgdGhlIEVBTi0xMyBmb3JtYXQuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBkc3dpdGtpbkBnb29nbGUuY29tIChEYW5pZWwgU3dpdGtpbilcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqIEBhdXRob3IgYWxhc2RhaXJAZ29vZ2xlLmNvbSAoQWxhc2RhaXIgTWFja2ludG9zaClcbiAgICAgKi9cbiAgICBjbGFzcyBFQU4xM1JlYWRlciBleHRlbmRzIFVQQ0VBTlJlYWRlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgICAgIHRoaXMuZGVjb2RlTWlkZGxlQ291bnRlcnMgPSBJbnQzMkFycmF5LmZyb20oWzAsIDAsIDAsIDBdKTtcbiAgICAgICAgfVxuICAgICAgICBkZWNvZGVNaWRkbGUocm93LCBzdGFydFJhbmdlLCByZXN1bHRTdHJpbmcpIHtcbiAgICAgICAgICAgIGxldCBjb3VudGVycyA9IHRoaXMuZGVjb2RlTWlkZGxlQ291bnRlcnM7XG4gICAgICAgICAgICBjb3VudGVyc1swXSA9IDA7XG4gICAgICAgICAgICBjb3VudGVyc1sxXSA9IDA7XG4gICAgICAgICAgICBjb3VudGVyc1syXSA9IDA7XG4gICAgICAgICAgICBjb3VudGVyc1szXSA9IDA7XG4gICAgICAgICAgICBsZXQgZW5kID0gcm93LmdldFNpemUoKTtcbiAgICAgICAgICAgIGxldCByb3dPZmZzZXQgPSBzdGFydFJhbmdlWzFdO1xuICAgICAgICAgICAgbGV0IGxnUGF0dGVybkZvdW5kID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgNiAmJiByb3dPZmZzZXQgPCBlbmQ7IHgrKykge1xuICAgICAgICAgICAgICAgIGxldCBiZXN0TWF0Y2ggPSBVUENFQU5SZWFkZXIuZGVjb2RlRGlnaXQocm93LCBjb3VudGVycywgcm93T2Zmc2V0LCBVUENFQU5SZWFkZXIuTF9BTkRfR19QQVRURVJOUyk7XG4gICAgICAgICAgICAgICAgcmVzdWx0U3RyaW5nICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKCcwJy5jaGFyQ29kZUF0KDApICsgYmVzdE1hdGNoICUgMTApKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBjb3VudGVyIG9mIGNvdW50ZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJvd09mZnNldCArPSBjb3VudGVyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYmVzdE1hdGNoID49IDEwKSB7XG4gICAgICAgICAgICAgICAgICAgIGxnUGF0dGVybkZvdW5kIHw9IDEgPDwgKDUgLSB4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXN1bHRTdHJpbmcgPSBFQU4xM1JlYWRlci5kZXRlcm1pbmVGaXJzdERpZ2l0KHJlc3VsdFN0cmluZywgbGdQYXR0ZXJuRm91bmQpO1xuICAgICAgICAgICAgbGV0IG1pZGRsZVJhbmdlID0gVVBDRUFOUmVhZGVyLmZpbmRHdWFyZFBhdHRlcm4oXG4gICAgICAgICAgICAgICAgcm93LFxuICAgICAgICAgICAgICAgIHJvd09mZnNldCxcbiAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICAgICAgICAgIFVQQ0VBTlJlYWRlci5NSURETEVfUEFUVEVSTixcbiAgICAgICAgICAgICAgICBuZXcgSW50MzJBcnJheShVUENFQU5SZWFkZXIuTUlERExFX1BBVFRFUk4ubGVuZ3RoKS5maWxsKDApKTtcbiAgICAgICAgICAgIHJvd09mZnNldCA9IG1pZGRsZVJhbmdlWzFdO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCA2ICYmIHJvd09mZnNldCA8IGVuZDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IGJlc3RNYXRjaCA9IFVQQ0VBTlJlYWRlci5kZWNvZGVEaWdpdChyb3csIGNvdW50ZXJzLCByb3dPZmZzZXQsIFVQQ0VBTlJlYWRlci5MX1BBVFRFUk5TKTtcbiAgICAgICAgICAgICAgICByZXN1bHRTdHJpbmcgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgoJzAnLmNoYXJDb2RlQXQoMCkgKyBiZXN0TWF0Y2gpKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBjb3VudGVyIG9mIGNvdW50ZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJvd09mZnNldCArPSBjb3VudGVyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB7IHJvd09mZnNldCwgcmVzdWx0U3RyaW5nIH07XG4gICAgICAgIH1cbiAgICAgICAgZ2V0QmFyY29kZUZvcm1hdCgpIHtcbiAgICAgICAgICAgIHJldHVybiBCYXJjb2RlRm9ybWF0JDEuRUFOXzEzO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBkZXRlcm1pbmVGaXJzdERpZ2l0KHJlc3VsdFN0cmluZywgbGdQYXR0ZXJuRm91bmQpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGQgPSAwOyBkIDwgMTA7IGQrKykge1xuICAgICAgICAgICAgICAgIGlmIChsZ1BhdHRlcm5Gb3VuZCA9PT0gdGhpcy5GSVJTVF9ESUdJVF9FTkNPRElOR1NbZF0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0U3RyaW5nID0gU3RyaW5nLmZyb21DaGFyQ29kZSgoJzAnLmNoYXJDb2RlQXQoMCkgKyBkKSkgKyByZXN1bHRTdHJpbmc7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHRTdHJpbmc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgRUFOMTNSZWFkZXIuRklSU1RfRElHSVRfRU5DT0RJTkdTID0gWzB4MDAsIDB4MEIsIDB4MEQsIDB4RSwgMHgxMywgMHgxOSwgMHgxQywgMHgxNSwgMHgxNiwgMHgxQV07XG5cbiAgICAvKipcbiAgICAgKiA8cD5JbXBsZW1lbnRzIGRlY29kaW5nIG9mIHRoZSBFQU4tOCBmb3JtYXQuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBFQU44UmVhZGVyIGV4dGVuZHMgVVBDRUFOUmVhZGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgICAgICBzdXBlcigpO1xuICAgICAgICAgICAgdGhpcy5kZWNvZGVNaWRkbGVDb3VudGVycyA9IEludDMyQXJyYXkuZnJvbShbMCwgMCwgMCwgMF0pO1xuICAgICAgICB9XG4gICAgICAgIGRlY29kZU1pZGRsZShyb3csIHN0YXJ0UmFuZ2UsIHJlc3VsdFN0cmluZykge1xuICAgICAgICAgICAgY29uc3QgY291bnRlcnMgPSB0aGlzLmRlY29kZU1pZGRsZUNvdW50ZXJzO1xuICAgICAgICAgICAgY291bnRlcnNbMF0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbMV0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbMl0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbM10gPSAwO1xuICAgICAgICAgICAgbGV0IGVuZCA9IHJvdy5nZXRTaXplKCk7XG4gICAgICAgICAgICBsZXQgcm93T2Zmc2V0ID0gc3RhcnRSYW5nZVsxXTtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgNCAmJiByb3dPZmZzZXQgPCBlbmQ7IHgrKykge1xuICAgICAgICAgICAgICAgIGxldCBiZXN0TWF0Y2ggPSBVUENFQU5SZWFkZXIuZGVjb2RlRGlnaXQocm93LCBjb3VudGVycywgcm93T2Zmc2V0LCBVUENFQU5SZWFkZXIuTF9QQVRURVJOUyk7XG4gICAgICAgICAgICAgICAgcmVzdWx0U3RyaW5nICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKCcwJy5jaGFyQ29kZUF0KDApICsgYmVzdE1hdGNoKSk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgY291bnRlciBvZiBjb3VudGVycykge1xuICAgICAgICAgICAgICAgICAgICByb3dPZmZzZXQgKz0gY291bnRlcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgbWlkZGxlUmFuZ2UgPSBVUENFQU5SZWFkZXIuZmluZEd1YXJkUGF0dGVybihyb3csIHJvd09mZnNldCwgdHJ1ZSwgVVBDRUFOUmVhZGVyLk1JRERMRV9QQVRURVJOLCBuZXcgSW50MzJBcnJheShVUENFQU5SZWFkZXIuTUlERExFX1BBVFRFUk4ubGVuZ3RoKS5maWxsKDApKTtcbiAgICAgICAgICAgIHJvd09mZnNldCA9IG1pZGRsZVJhbmdlWzFdO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCA0ICYmIHJvd09mZnNldCA8IGVuZDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IGJlc3RNYXRjaCA9IFVQQ0VBTlJlYWRlci5kZWNvZGVEaWdpdChyb3csIGNvdW50ZXJzLCByb3dPZmZzZXQsIFVQQ0VBTlJlYWRlci5MX1BBVFRFUk5TKTtcbiAgICAgICAgICAgICAgICByZXN1bHRTdHJpbmcgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgoJzAnLmNoYXJDb2RlQXQoMCkgKyBiZXN0TWF0Y2gpKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBjb3VudGVyIG9mIGNvdW50ZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJvd09mZnNldCArPSBjb3VudGVyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB7IHJvd09mZnNldCwgcmVzdWx0U3RyaW5nIH07XG4gICAgICAgIH1cbiAgICAgICAgZ2V0QmFyY29kZUZvcm1hdCgpIHtcbiAgICAgICAgICAgIHJldHVybiBCYXJjb2RlRm9ybWF0JDEuRUFOXzg7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFbmNhcHN1bGF0ZXMgZnVuY3Rpb25hbGl0eSBhbmQgaW1wbGVtZW50YXRpb24gdGhhdCBpcyBjb21tb24gdG8gYWxsIGZhbWlsaWVzXG4gICAgICogb2Ygb25lLWRpbWVuc2lvbmFsIGJhcmNvZGVzLlxuICAgICAqXG4gICAgICogQGF1dGhvciBkc3dpdGtpbkBnb29nbGUuY29tIChEYW5pZWwgU3dpdGtpbilcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqIEBhdXRob3Igc2FtMjMzMiAoU2FtIFJ1ZGxvZmYpXG4gICAgICpcbiAgICAgKiBAc291cmNlIGh0dHBzOi8vZ2l0aHViLmNvbS96eGluZy96eGluZy9ibG9iLzNjOTY5MjMyNzZkZDU3ODVkNThlYjk3MGI2YmEzZjgwZDM2YTk1MDUvY29yZS9zcmMvbWFpbi9qYXZhL2NvbS9nb29nbGUvenhpbmcvb25lZC9VUENBUmVhZGVyLmphdmFcbiAgICAgKlxuICAgICAqIEBleHBlcmltZW50YWxcbiAgICAgKi9cbiAgICBjbGFzcyBVUENBUmVhZGVyIGV4dGVuZHMgVVBDRUFOUmVhZGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICAgICAgdGhpcy5lYW4xM1JlYWRlciA9IG5ldyBFQU4xM1JlYWRlcigpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEBPdmVycmlkZVxuICAgICAgICBnZXRCYXJjb2RlRm9ybWF0KCkge1xuICAgICAgICAgICAgcmV0dXJuIEJhcmNvZGVGb3JtYXQkMS5VUENfQTtcbiAgICAgICAgfVxuICAgICAgICAvLyBOb3RlIHRoYXQgd2UgZG9uJ3QgdHJ5IHJvdGF0aW9uIHdpdGhvdXQgdGhlIHRyeSBoYXJkZXIgZmxhZywgZXZlbiBpZiByb3RhdGlvbiB3YXMgc3VwcG9ydGVkLlxuICAgICAgICAvLyBAT3ZlcnJpZGVcbiAgICAgICAgZGVjb2RlKGltYWdlLCBoaW50cykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubWF5YmVSZXR1cm5SZXN1bHQodGhpcy5lYW4xM1JlYWRlci5kZWNvZGUoaW1hZ2UpKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBAT3ZlcnJpZGVcbiAgICAgICAgZGVjb2RlUm93KHJvd051bWJlciwgcm93LCBoaW50cykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubWF5YmVSZXR1cm5SZXN1bHQodGhpcy5lYW4xM1JlYWRlci5kZWNvZGVSb3cocm93TnVtYmVyLCByb3csIGhpbnRzKSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIGRlY29kZU1pZGRsZShyb3csIHN0YXJ0UmFuZ2UsIHJlc3VsdFN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWFuMTNSZWFkZXIuZGVjb2RlTWlkZGxlKHJvdywgc3RhcnRSYW5nZSwgcmVzdWx0U3RyaW5nKTtcbiAgICAgICAgfVxuICAgICAgICBtYXliZVJldHVyblJlc3VsdChyZXN1bHQpIHtcbiAgICAgICAgICAgIGxldCB0ZXh0ID0gcmVzdWx0LmdldFRleHQoKTtcbiAgICAgICAgICAgIGlmICh0ZXh0LmNoYXJBdCgwKSA9PT0gJzAnKSB7XG4gICAgICAgICAgICAgICAgbGV0IHVwY2FSZXN1bHQgPSBuZXcgUmVzdWx0KHRleHQuc3Vic3RyaW5nKDEpLCBudWxsLCBudWxsLCByZXN1bHQuZ2V0UmVzdWx0UG9pbnRzKCksIEJhcmNvZGVGb3JtYXQkMS5VUENfQSk7XG4gICAgICAgICAgICAgICAgaWYgKHJlc3VsdC5nZXRSZXN1bHRNZXRhZGF0YSgpICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgdXBjYVJlc3VsdC5wdXRBbGxNZXRhZGF0YShyZXN1bHQuZ2V0UmVzdWx0TWV0YWRhdGEoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB1cGNhUmVzdWx0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmVzZXQoKSB7XG4gICAgICAgICAgICB0aGlzLmVhbjEzUmVhZGVyLnJlc2V0KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiA8cD5JbXBsZW1lbnRzIGRlY29kaW5nIG9mIHRoZSBVUEMtRSBmb3JtYXQuPC9wPlxuICAgICAqIDxwPjxhIGhyZWY9XCJodHRwOi8vd3d3LmJhcmNvZGVpc2xhbmQuY29tL3VwY2UucGh0bWxcIj5UaGlzPC9hPiBpcyBhIGdyZWF0IHJlZmVyZW5jZSBmb3JcbiAgICAgKiBVUEMtRSBpbmZvcm1hdGlvbi48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqXG4gICAgICogQHNvdXJjZSBodHRwczovL2dpdGh1Yi5jb20venhpbmcvenhpbmcvYmxvYi8zYzk2OTIzMjc2ZGQ1Nzg1ZDU4ZWI5NzBiNmJhM2Y4MGQzNmE5NTA1L2NvcmUvc3JjL21haW4vamF2YS9jb20vZ29vZ2xlL3p4aW5nL29uZWQvVVBDRVJlYWRlci5qYXZhXG4gICAgICpcbiAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICovXG4gICAgLyogZmluYWwgKi8gY2xhc3MgVVBDRVJlYWRlciBleHRlbmRzIFVQQ0VBTlJlYWRlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgICAgIHRoaXMuZGVjb2RlTWlkZGxlQ291bnRlcnMgPSBuZXcgSW50MzJBcnJheSg0KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIGRlY29kZU1pZGRsZShyb3csIHN0YXJ0UmFuZ2UsIHJlc3VsdCkge1xuICAgICAgICAgICAgY29uc3QgY291bnRlcnMgPSB0aGlzLmRlY29kZU1pZGRsZUNvdW50ZXJzLm1hcCh4ID0+IHgpO1xuICAgICAgICAgICAgY291bnRlcnNbMF0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbMV0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbMl0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbM10gPSAwO1xuICAgICAgICAgICAgY29uc3QgZW5kID0gcm93LmdldFNpemUoKTtcbiAgICAgICAgICAgIGxldCByb3dPZmZzZXQgPSBzdGFydFJhbmdlWzFdO1xuICAgICAgICAgICAgbGV0IGxnUGF0dGVybkZvdW5kID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgNiAmJiByb3dPZmZzZXQgPCBlbmQ7IHgrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGJlc3RNYXRjaCA9IFVQQ0VSZWFkZXIuZGVjb2RlRGlnaXQoXG4gICAgICAgICAgICAgICAgICAgIHJvdywgY291bnRlcnMsIHJvd09mZnNldCwgVVBDRVJlYWRlci5MX0FORF9HX1BBVFRFUk5TKTtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgoJzAnLmNoYXJDb2RlQXQoMCkgKyAoYmVzdE1hdGNoICUgMTApKSk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgY291bnRlciBvZiBjb3VudGVycykge1xuICAgICAgICAgICAgICAgICAgICByb3dPZmZzZXQgKz0gY291bnRlcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGJlc3RNYXRjaCA+PSAxMCkge1xuICAgICAgICAgICAgICAgICAgICBsZ1BhdHRlcm5Gb3VuZCB8PSAoMSA8PCAoNSAtIHgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcmVzdWx0U3RyaW5nID0gVVBDRVJlYWRlci5kZXRlcm1pbmVOdW1TeXNBbmRDaGVja0RpZ2l0KFxuICAgICAgICAgICAgICAgIHJlc3VsdCwgbGdQYXR0ZXJuRm91bmQpO1xuICAgICAgICAgICAgcmV0dXJuIHtyb3dPZmZzZXQsIHJlc3VsdFN0cmluZ307XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIC8vIEBPdmVycmlkZVxuICAgICAgICBkZWNvZGVFbmQocm93LCBlbmRTdGFydCkge1xuICAgICAgICAgICAgcmV0dXJuIFVQQ0VSZWFkZXIuZmluZEd1YXJkUGF0dGVybldpdGhvdXRDb3VudGVycyhcbiAgICAgICAgICAgICAgICByb3csIGVuZFN0YXJ0LCB0cnVlLCBVUENFUmVhZGVyLk1JRERMRV9FTkRfUEFUVEVSTik7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uXG4gICAgICAgICAqL1xuICAgICAgICAvLyBAT3ZlcnJpZGVcbiAgICAgICAgY2hlY2tDaGVja3N1bShzKSB7XG4gICAgICAgICAgICByZXR1cm4gVVBDRUFOUmVhZGVyLmNoZWNrQ2hlY2tzdW0oVVBDRVJlYWRlci5jb252ZXJ0VVBDRXRvVVBDQShzKSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBkZXRlcm1pbmVOdW1TeXNBbmRDaGVja0RpZ2l0KHJlc3VsdFN0cmluZywgbGdQYXR0ZXJuRm91bmQpIHtcbiAgICAgICAgICAgIGZvciAobGV0IG51bVN5cyA9IDA7IG51bVN5cyA8PSAxOyBudW1TeXMrKykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGQgPSAwOyBkIDwgMTA7IGQrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAobGdQYXR0ZXJuRm91bmQgPT09IHRoaXMuTlVNU1lTX0FORF9DSEVDS19ESUdJVF9QQVRURVJOU1tudW1TeXNdW2RdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgcHJlZml4ID0gU3RyaW5nLmZyb21DaGFyQ29kZSgnMCcuY2hhckNvZGVBdCgwKSArIG51bVN5cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3VmZml4ID0gU3RyaW5nLmZyb21DaGFyQ29kZSgnMCcuY2hhckNvZGVBdCgwKSArIGQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByZWZpeCArIHJlc3VsdFN0cmluZyArIHN1ZmZpeDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IE5vdEZvdW5kRXhjZXB0aW9uLmdldE5vdEZvdW5kSW5zdGFuY2UoKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBAT3ZlcnJpZGVcbiAgICAgICAgZ2V0QmFyY29kZUZvcm1hdCgpIHtcbiAgICAgICAgICAgIHJldHVybiBCYXJjb2RlRm9ybWF0JDEuVVBDX0U7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEV4cGFuZHMgYSBVUEMtRSB2YWx1ZSBiYWNrIGludG8gaXRzIGZ1bGwsIGVxdWl2YWxlbnQgVVBDLUEgY29kZSB2YWx1ZS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHVwY2UgVVBDLUUgY29kZSBhcyBzdHJpbmcgb2YgZGlnaXRzXG4gICAgICAgICAqIEByZXR1cm4gZXF1aXZhbGVudCBVUEMtQSBjb2RlIGFzIHN0cmluZyBvZiBkaWdpdHNcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBjb252ZXJ0VVBDRXRvVVBDQSh1cGNlKSB7XG4gICAgICAgICAgICAvLyB0aGUgZm9sbG93aW5nIGxpbmUgaXMgZXF1aXZhbGVudCB0byB1cGNlLmdldENoYXJzKDEsIDcsIHVwY2VDaGFycywgMCk7XG4gICAgICAgICAgICBjb25zdCB1cGNlQ2hhcnMgPSB1cGNlLnNsaWNlKDEsIDcpLnNwbGl0KCcnKS5tYXAoeCA9PiB4LmNoYXJDb2RlQXQoMCkpO1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IFN0cmluZ0J1aWxkZXIoIC8qMTIqLyk7XG4gICAgICAgICAgICByZXN1bHQuYXBwZW5kKHVwY2UuY2hhckF0KDApKTtcbiAgICAgICAgICAgIGxldCBsYXN0Q2hhciA9IHVwY2VDaGFyc1s1XTtcbiAgICAgICAgICAgIHN3aXRjaCAobGFzdENoYXIpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZENoYXJzKHVwY2VDaGFycywgMCwgMik7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQobGFzdENoYXIpO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCcwMDAwJyk7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmRDaGFycyh1cGNlQ2hhcnMsIDIsIDMpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmRDaGFycyh1cGNlQ2hhcnMsIDAsIDMpO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCcwMDAwMCcpO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kQ2hhcnModXBjZUNoYXJzLCAzLCAyKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kQ2hhcnModXBjZUNoYXJzLCAwLCA0KTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnMDAwMDAnKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCh1cGNlQ2hhcnNbNF0pO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kQ2hhcnModXBjZUNoYXJzLCAwLCA1KTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnMDAwMCcpO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKGxhc3RDaGFyKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBPbmx5IGFwcGVuZCBjaGVjayBkaWdpdCBpbiBjb252ZXJzaW9uIGlmIHN1cHBsaWVkXG4gICAgICAgICAgICBpZiAodXBjZS5sZW5ndGggPj0gOCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQodXBjZS5jaGFyQXQoNykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC50b1N0cmluZygpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoZSBwYXR0ZXJuIHRoYXQgbWFya3MgdGhlIG1pZGRsZSwgYW5kIGVuZCwgb2YgYSBVUEMtRSBwYXR0ZXJuLlxuICAgICAqIFRoZXJlIGlzIG5vIFwic2Vjb25kIGhhbGZcIiB0byBhIFVQQy1FIGJhcmNvZGUuXG4gICAgICovXG4gICAgVVBDRVJlYWRlci5NSURETEVfRU5EX1BBVFRFUk4gPSBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDEsIDEsIDEsIDFdKTtcbiAgICAvLyBGb3IgYW4gVVBDLUUgYmFyY29kZSwgdGhlIGZpbmFsIGRpZ2l0IGlzIHJlcHJlc2VudGVkIGJ5IHRoZSBwYXJpdGllcyB1c2VkXG4gICAgLy8gdG8gZW5jb2RlIHRoZSBtaWRkbGUgc2l4IGRpZ2l0cywgYWNjb3JkaW5nIHRvIHRoZSB0YWJsZSBiZWxvdy5cbiAgICAvL1xuICAgIC8vICAgICAgICAgICAgICAgIFBhcml0eSBvZiBuZXh0IDYgZGlnaXRzXG4gICAgLy8gICAgRGlnaXQgICAwICAgICAxICAgICAyICAgICAzICAgICA0ICAgICA1XG4gICAgLy8gICAgICAgMCAgICBFdmVuICAgRXZlbiAgRXZlbiBPZGQgIE9kZCAgIE9kZFxuICAgIC8vICAgICAgIDEgICAgRXZlbiAgIEV2ZW4gIE9kZCAgRXZlbiBPZGQgICBPZGRcbiAgICAvLyAgICAgICAyICAgIEV2ZW4gICBFdmVuICBPZGQgIE9kZCAgRXZlbiAgT2RkXG4gICAgLy8gICAgICAgMyAgICBFdmVuICAgRXZlbiAgT2RkICBPZGQgIE9kZCAgIEV2ZW5cbiAgICAvLyAgICAgICA0ICAgIEV2ZW4gICBPZGQgICBFdmVuIEV2ZW4gT2RkICAgT2RkXG4gICAgLy8gICAgICAgNSAgICBFdmVuICAgT2RkICAgT2RkICBFdmVuIEV2ZW4gIE9kZFxuICAgIC8vICAgICAgIDYgICAgRXZlbiAgIE9kZCAgIE9kZCAgT2RkICBFdmVuICBFdmVuXG4gICAgLy8gICAgICAgNyAgICBFdmVuICAgT2RkICAgRXZlbiBPZGQgIEV2ZW4gIE9kZFxuICAgIC8vICAgICAgIDggICAgRXZlbiAgIE9kZCAgIEV2ZW4gT2RkICBPZGQgICBFdmVuXG4gICAgLy8gICAgICAgOSAgICBFdmVuICAgT2RkICAgT2RkICBFdmVuIE9kZCAgIEV2ZW5cbiAgICAvL1xuICAgIC8vIFRoZSBlbmNvZGluZyBpcyByZXByZXNlbnRlZCBieSB0aGUgZm9sbG93aW5nIGFycmF5LCB3aGljaCBpcyBhIGJpdCBwYXR0ZXJuXG4gICAgLy8gdXNpbmcgT2RkID0gMCBhbmQgRXZlbiA9IDEuIEZvciBleGFtcGxlLCA1IGlzIHJlcHJlc2VudGVkIGJ5OlxuICAgIC8vXG4gICAgLy8gICAgICAgICAgICAgIE9kZCBFdmVuIEV2ZW4gT2RkIE9kZCBFdmVuXG4gICAgLy8gaW4gYmluYXJ5OlxuICAgIC8vICAgICAgICAgICAgICAgIDAgICAgMSAgICAxICAgMCAgIDAgICAgMSAgID09IDB4MTlcbiAgICAvL1xuICAgIC8qKlxuICAgICAqIFNlZSB7QGxpbmsgI0xfQU5EX0dfUEFUVEVSTlN9OyB0aGVzZSB2YWx1ZXMgc2ltaWxhcmx5IHJlcHJlc2VudCBwYXR0ZXJucyBvZlxuICAgICAqIGV2ZW4tb2RkIHBhcml0eSBlbmNvZGluZ3Mgb2YgZGlnaXRzIHRoYXQgaW1wbHkgYm90aCB0aGUgbnVtYmVyIHN5c3RlbSAoMCBvciAxKVxuICAgICAqIHVzZWQsIGFuZCB0aGUgY2hlY2sgZGlnaXQuXG4gICAgICovXG4gICAgVVBDRVJlYWRlci5OVU1TWVNfQU5EX0NIRUNLX0RJR0lUX1BBVFRFUk5TID0gW1xuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4MzgsIDB4MzQsIDB4MzIsIDB4MzEsIDB4MkMsIDB4MjYsIDB4MjMsIDB4MkEsIDB4MjksIDB4MjVdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsweDA3LCAweDBCLCAweDBELCAweDBFLCAweDEzLCAweDE5LCAweDFDLCAweDE1LCAweDE2LCAweDFBXSksXG4gICAgXTtcblxuICAgIC8qKlxuICAgICAqIDxwPkEgcmVhZGVyIHRoYXQgY2FuIHJlYWQgYWxsIGF2YWlsYWJsZSBVUEMvRUFOIGZvcm1hdHMuIElmIGEgY2FsbGVyIHdhbnRzIHRvIHRyeSB0b1xuICAgICAqIHJlYWQgYWxsIHN1Y2ggZm9ybWF0cywgaXQgaXMgbW9zdCBlZmZpY2llbnQgdG8gdXNlIHRoaXMgaW1wbGVtZW50YXRpb24gcmF0aGVyIHRoYW4gaW52b2tlXG4gICAgICogaW5kaXZpZHVhbCByZWFkZXJzLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgTXVsdGlGb3JtYXRVUENFQU5SZWFkZXIgZXh0ZW5kcyBPbmVEUmVhZGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IoaGludHMpIHtcbiAgICAgICAgICAgIHN1cGVyKCk7XG4gICAgICAgICAgICBsZXQgcG9zc2libGVGb3JtYXRzID0gaGludHMgPT0gbnVsbCA/IG51bGwgOiBoaW50cy5nZXQoRGVjb2RlSGludFR5cGUkMS5QT1NTSUJMRV9GT1JNQVRTKTtcbiAgICAgICAgICAgIGxldCByZWFkZXJzID0gW107XG4gICAgICAgICAgICBpZiAoIWlzTnVsbE9yVW5kZWZpbmVkKHBvc3NpYmxlRm9ybWF0cykpIHtcbiAgICAgICAgICAgICAgICBpZiAocG9zc2libGVGb3JtYXRzLmluZGV4T2YoQmFyY29kZUZvcm1hdCQxLkVBTl8xMykgPiAtMSkge1xuICAgICAgICAgICAgICAgICAgICByZWFkZXJzLnB1c2gobmV3IEVBTjEzUmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocG9zc2libGVGb3JtYXRzLmluZGV4T2YoQmFyY29kZUZvcm1hdCQxLlVQQ19BKSA+IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlcnMucHVzaChuZXcgVVBDQVJlYWRlcigpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHBvc3NpYmxlRm9ybWF0cy5pbmRleE9mKEJhcmNvZGVGb3JtYXQkMS5FQU5fOCkgPiAtMSkge1xuICAgICAgICAgICAgICAgICAgICByZWFkZXJzLnB1c2gobmV3IEVBTjhSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChwb3NzaWJsZUZvcm1hdHMuaW5kZXhPZihCYXJjb2RlRm9ybWF0JDEuVVBDX0UpID4gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVycy5wdXNoKG5ldyBVUENFUmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gTm8gaGludHMgcHJvdmlkZWQuXG4gICAgICAgICAgICAgICAgcmVhZGVycy5wdXNoKG5ldyBFQU4xM1JlYWRlcigpKTtcbiAgICAgICAgICAgICAgICByZWFkZXJzLnB1c2gobmV3IFVQQ0FSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgcmVhZGVycy5wdXNoKG5ldyBFQU44UmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIHJlYWRlcnMucHVzaChuZXcgVVBDRVJlYWRlcigpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucmVhZGVycyA9IHJlYWRlcnM7XG4gICAgICAgIH1cbiAgICAgICAgZGVjb2RlUm93KHJvd051bWJlciwgcm93LCBoaW50cykge1xuICAgICAgICAgICAgZm9yIChsZXQgcmVhZGVyIG9mIHRoaXMucmVhZGVycykge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGNvbnN0IHJlc3VsdDogUmVzdWx0ID0gcmVhZGVyLmRlY29kZVJvdyhyb3dOdW1iZXIsIHJvdywgc3RhcnRHdWFyZFBhdHRlcm4sIGhpbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gcmVhZGVyLmRlY29kZVJvdyhyb3dOdW1iZXIsIHJvdywgaGludHMpO1xuICAgICAgICAgICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2U6IGEgMTItZGlnaXQgY29kZSBlbmNvZGVkIGluIFVQQy1BIGlzIGlkZW50aWNhbCB0byBhIFwiMFwiXG4gICAgICAgICAgICAgICAgICAgIC8vIGZvbGxvd2VkIGJ5IHRob3NlIDEyIGRpZ2l0cyBlbmNvZGVkIGFzIEVBTi0xMy4gRWFjaCB3aWxsIHJlY29nbml6ZSBzdWNoIGEgY29kZSxcbiAgICAgICAgICAgICAgICAgICAgLy8gVVBDLUEgYXMgYSAxMi1kaWdpdCBzdHJpbmcgYW5kIEVBTi0xMyBhcyBhIDEzLWRpZ2l0IHN0cmluZyBzdGFydGluZyB3aXRoIFwiMFwiLlxuICAgICAgICAgICAgICAgICAgICAvLyBJbmRpdmlkdWFsbHkgdGhlc2UgYXJlIGNvcnJlY3QgYW5kIHRoZWlyIHJlYWRlcnMgd2lsbCBib3RoIHJlYWQgc3VjaCBhIGNvZGVcbiAgICAgICAgICAgICAgICAgICAgLy8gYW5kIGNvcnJlY3RseSBjYWxsIGl0IEVBTi0xMywgb3IgVVBDLUEsIHJlc3BlY3RpdmVseS5cbiAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgLy8gSW4gdGhpcyBjYXNlLCBpZiB3ZSd2ZSBiZWVuIGxvb2tpbmcgZm9yIGJvdGggdHlwZXMsIHdlJ2QgbGlrZSB0byBjYWxsIGl0XG4gICAgICAgICAgICAgICAgICAgIC8vIGEgVVBDLUEgY29kZS4gQnV0IGZvciBlZmZpY2llbmN5IHdlIG9ubHkgcnVuIHRoZSBFQU4tMTMgZGVjb2RlciB0byBhbHNvIHJlYWRcbiAgICAgICAgICAgICAgICAgICAgLy8gVVBDLUEuIFNvIHdlIHNwZWNpYWwgY2FzZSBpdCBoZXJlLCBhbmQgY29udmVydCBhbiBFQU4tMTMgcmVzdWx0IHRvIGEgVVBDLUFcbiAgICAgICAgICAgICAgICAgICAgLy8gcmVzdWx0IGlmIGFwcHJvcHJpYXRlLlxuICAgICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgICAvLyBCdXQsIGRvbid0IHJldHVybiBVUEMtQSBpZiBVUEMtQSB3YXMgbm90IGEgcmVxdWVzdGVkIGZvcm1hdCFcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZWFuMTNNYXlCZVVQQ0EgPSByZXN1bHQuZ2V0QmFyY29kZUZvcm1hdCgpID09PSBCYXJjb2RlRm9ybWF0JDEuRUFOXzEzICYmXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuZ2V0VGV4dCgpLmNoYXJBdCgwKSA9PT0gJzAnO1xuICAgICAgICAgICAgICAgICAgICAvLyBAU3VwcHJlc3NXYXJuaW5ncyhcInVuY2hlY2tlZFwiKVxuICAgICAgICAgICAgICAgICAgICBjb25zdCBwb3NzaWJsZUZvcm1hdHMgPSBoaW50cyA9PSBudWxsID8gbnVsbCA6IGhpbnRzLmdldChEZWNvZGVIaW50VHlwZSQxLlBPU1NJQkxFX0ZPUk1BVFMpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW5SZXR1cm5VUENBID0gcG9zc2libGVGb3JtYXRzID09IG51bGwgfHwgcG9zc2libGVGb3JtYXRzLmluY2x1ZGVzKEJhcmNvZGVGb3JtYXQkMS5VUENfQSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlYW4xM01heUJlVVBDQSAmJiBjYW5SZXR1cm5VUENBKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByYXdCeXRlcyA9IHJlc3VsdC5nZXRSYXdCeXRlcygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVHJhbnNmZXIgdGhlIG1ldGFkYXRhIGFjcm9zc1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0VVBDQSA9IG5ldyBSZXN1bHQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmdldFRleHQoKS5zdWJzdHJpbmcoMSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3Qnl0ZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHJhd0J5dGVzID8gcmF3Qnl0ZXMubGVuZ3RoIDogbnVsbCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmdldFJlc3VsdFBvaW50cygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJhcmNvZGVGb3JtYXQkMS5VUENfQSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRVUENBLnB1dEFsbE1ldGFkYXRhKHJlc3VsdC5nZXRSZXN1bHRNZXRhZGF0YSgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHRVUENBO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmVzZXQoKSB7XG4gICAgICAgICAgICBmb3IgKGxldCByZWFkZXIgb2YgdGhpcy5yZWFkZXJzKSB7XG4gICAgICAgICAgICAgICAgcmVhZGVyLnJlc2V0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBpbXBvcnQgSW50ZWdlciBmcm9tICcuLi8uLi91dGlsL0ludGVnZXInO1xuICAgIC8vIGltcG9ydCBGbG9hdCBmcm9tICcuLi8uLi91dGlsL0Zsb2F0JztcbiAgICBjbGFzcyBBYnN0cmFjdFJTU1JlYWRlciBleHRlbmRzIE9uZURSZWFkZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICAgIHN1cGVyKCk7XG4gICAgICAgICAgICB0aGlzLmRlY29kZUZpbmRlckNvdW50ZXJzID0gbmV3IEludDMyQXJyYXkoNCk7XG4gICAgICAgICAgICB0aGlzLmRhdGFDaGFyYWN0ZXJDb3VudGVycyA9IG5ldyBJbnQzMkFycmF5KDgpO1xuICAgICAgICAgICAgdGhpcy5vZGRSb3VuZGluZ0Vycm9ycyA9IG5ldyBBcnJheSg0KTtcbiAgICAgICAgICAgIHRoaXMuZXZlblJvdW5kaW5nRXJyb3JzID0gbmV3IEFycmF5KDQpO1xuICAgICAgICAgICAgdGhpcy5vZGRDb3VudHMgPSBuZXcgQXJyYXkodGhpcy5kYXRhQ2hhcmFjdGVyQ291bnRlcnMubGVuZ3RoIC8gMik7XG4gICAgICAgICAgICB0aGlzLmV2ZW5Db3VudHMgPSBuZXcgQXJyYXkodGhpcy5kYXRhQ2hhcmFjdGVyQ291bnRlcnMubGVuZ3RoIC8gMik7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RGVjb2RlRmluZGVyQ291bnRlcnMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGVGaW5kZXJDb3VudGVycztcbiAgICAgICAgfVxuICAgICAgICBnZXREYXRhQ2hhcmFjdGVyQ291bnRlcnMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRhQ2hhcmFjdGVyQ291bnRlcnM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0T2RkUm91bmRpbmdFcnJvcnMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vZGRSb3VuZGluZ0Vycm9ycztcbiAgICAgICAgfVxuICAgICAgICBnZXRFdmVuUm91bmRpbmdFcnJvcnMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ldmVuUm91bmRpbmdFcnJvcnM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0T2RkQ291bnRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMub2RkQ291bnRzO1xuICAgICAgICB9XG4gICAgICAgIGdldEV2ZW5Db3VudHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ldmVuQ291bnRzO1xuICAgICAgICB9XG4gICAgICAgIHBhcnNlRmluZGVyVmFsdWUoY291bnRlcnMsIGZpbmRlclBhdHRlcm5zKSB7XG4gICAgICAgICAgICBmb3IgKGxldCB2YWx1ZSA9IDA7IHZhbHVlIDwgZmluZGVyUGF0dGVybnMubGVuZ3RoOyB2YWx1ZSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9uZURSZWFkZXIucGF0dGVybk1hdGNoVmFyaWFuY2UoY291bnRlcnMsIGZpbmRlclBhdHRlcm5zW3ZhbHVlXSwgQWJzdHJhY3RSU1NSZWFkZXIuTUFYX0lORElWSURVQUxfVkFSSUFOQ0UpIDwgQWJzdHJhY3RSU1NSZWFkZXIuTUFYX0FWR19WQVJJQU5DRSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBhcnJheSB2YWx1ZXMgdG8gc3VtXG4gICAgICAgICAqIEByZXR1cm4gc3VtIG9mIHZhbHVlc1xuICAgICAgICAgKiBAZGVwcmVjYXRlZCBjYWxsIHtAbGluayBNYXRoVXRpbHMjc3VtKGludFtdKX1cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBjb3VudChhcnJheSkge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGhVdGlscy5zdW0obmV3IEludDMyQXJyYXkoYXJyYXkpKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgaW5jcmVtZW50KGFycmF5LCBlcnJvcnMpIHtcbiAgICAgICAgICAgIGxldCBpbmRleCA9IDA7XG4gICAgICAgICAgICBsZXQgYmlnZ2VzdEVycm9yID0gZXJyb3JzWzBdO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcnNbaV0gPiBiaWdnZXN0RXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgYmlnZ2VzdEVycm9yID0gZXJyb3JzW2ldO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCA9IGk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXJyYXlbaW5kZXhdKys7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGRlY3JlbWVudChhcnJheSwgZXJyb3JzKSB7XG4gICAgICAgICAgICBsZXQgaW5kZXggPSAwO1xuICAgICAgICAgICAgbGV0IGJpZ2dlc3RFcnJvciA9IGVycm9yc1swXTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3JzW2ldIDwgYmlnZ2VzdEVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGJpZ2dlc3RFcnJvciA9IGVycm9yc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggPSBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFycmF5W2luZGV4XS0tO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBpc0ZpbmRlclBhdHRlcm4oY291bnRlcnMpIHtcbiAgICAgICAgICAgIGxldCBmaXJzdFR3b1N1bSA9IGNvdW50ZXJzWzBdICsgY291bnRlcnNbMV07XG4gICAgICAgICAgICBsZXQgc3VtID0gZmlyc3RUd29TdW0gKyBjb3VudGVyc1syXSArIGNvdW50ZXJzWzNdO1xuICAgICAgICAgICAgbGV0IHJhdGlvID0gZmlyc3RUd29TdW0gLyBzdW07XG4gICAgICAgICAgICBpZiAocmF0aW8gPj0gQWJzdHJhY3RSU1NSZWFkZXIuTUlOX0ZJTkRFUl9QQVRURVJOX1JBVElPICYmIHJhdGlvIDw9IEFic3RyYWN0UlNTUmVhZGVyLk1BWF9GSU5ERVJfUEFUVEVSTl9SQVRJTykge1xuICAgICAgICAgICAgICAgIC8vIHBhc3NlcyByYXRpbyB0ZXN0IGluIHNwZWMsIGJ1dCBzZWUgaWYgdGhlIGNvdW50cyBhcmUgdW5yZWFzb25hYmxlXG4gICAgICAgICAgICAgICAgbGV0IG1pbkNvdW50ZXIgPSBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUjtcbiAgICAgICAgICAgICAgICBsZXQgbWF4Q291bnRlciA9IE51bWJlci5NSU5fU0FGRV9JTlRFR0VSO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGNvdW50ZXIgb2YgY291bnRlcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvdW50ZXIgPiBtYXhDb3VudGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhDb3VudGVyID0gY291bnRlcjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoY291bnRlciA8IG1pbkNvdW50ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkNvdW50ZXIgPSBjb3VudGVyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBtYXhDb3VudGVyIDwgMTAgKiBtaW5Db3VudGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIEFic3RyYWN0UlNTUmVhZGVyLk1BWF9BVkdfVkFSSUFOQ0UgPSAwLjI7XG4gICAgQWJzdHJhY3RSU1NSZWFkZXIuTUFYX0lORElWSURVQUxfVkFSSUFOQ0UgPSAwLjQ1O1xuICAgIEFic3RyYWN0UlNTUmVhZGVyLk1JTl9GSU5ERVJfUEFUVEVSTl9SQVRJTyA9IDkuNSAvIDEyLjA7XG4gICAgQWJzdHJhY3RSU1NSZWFkZXIuTUFYX0ZJTkRFUl9QQVRURVJOX1JBVElPID0gMTIuNSAvIDE0LjA7XG5cbiAgICBjbGFzcyBEYXRhQ2hhcmFjdGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IodmFsdWUsIGNoZWNrc3VtUG9ydGlvbikge1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgdGhpcy5jaGVja3N1bVBvcnRpb24gPSBjaGVja3N1bVBvcnRpb247XG4gICAgICAgIH1cbiAgICAgICAgZ2V0VmFsdWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRDaGVja3N1bVBvcnRpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jaGVja3N1bVBvcnRpb247XG4gICAgICAgIH1cbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZSArICcoJyArIHRoaXMuY2hlY2tzdW1Qb3J0aW9uICsgJyknO1xuICAgICAgICB9XG4gICAgICAgIGVxdWFscyhvKSB7XG4gICAgICAgICAgICBpZiAoIShvIGluc3RhbmNlb2YgRGF0YUNoYXJhY3RlcikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCB0aGF0ID0gbztcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlID09PSB0aGF0LnZhbHVlICYmIHRoaXMuY2hlY2tzdW1Qb3J0aW9uID09PSB0aGF0LmNoZWNrc3VtUG9ydGlvbjtcbiAgICAgICAgfVxuICAgICAgICBoYXNoQ29kZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlIF4gdGhpcy5jaGVja3N1bVBvcnRpb247XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjbGFzcyBGaW5kZXJQYXR0ZXJuIHtcbiAgICAgICAgY29uc3RydWN0b3IodmFsdWUsIHN0YXJ0RW5kLCBzdGFydCwgZW5kLCByb3dOdW1iZXIpIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIHRoaXMuc3RhcnRFbmQgPSBzdGFydEVuZDtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIHRoaXMuc3RhcnRFbmQgPSBzdGFydEVuZDtcbiAgICAgICAgICAgIHRoaXMucmVzdWx0UG9pbnRzID0gbmV3IEFycmF5KCk7XG4gICAgICAgICAgICB0aGlzLnJlc3VsdFBvaW50cy5wdXNoKG5ldyBSZXN1bHRQb2ludChzdGFydCwgcm93TnVtYmVyKSk7XG4gICAgICAgICAgICB0aGlzLnJlc3VsdFBvaW50cy5wdXNoKG5ldyBSZXN1bHRQb2ludChlbmQsIHJvd051bWJlcikpO1xuICAgICAgICB9XG4gICAgICAgIGdldFZhbHVlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0U3RhcnRFbmQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zdGFydEVuZDtcbiAgICAgICAgfVxuICAgICAgICBnZXRSZXN1bHRQb2ludHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZXN1bHRQb2ludHM7XG4gICAgICAgIH1cbiAgICAgICAgZXF1YWxzKG8pIHtcbiAgICAgICAgICAgIGlmICghKG8gaW5zdGFuY2VvZiBGaW5kZXJQYXR0ZXJuKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHRoYXQgPSBvO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWUgPT09IHRoYXQudmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaGFzaENvZGUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJTUyB1dGlsIGZ1bmN0aW9ucy5cbiAgICAgKi9cbiAgICBjbGFzcyBSU1NVdGlscyB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkgeyB9XG4gICAgICAgIHN0YXRpYyBnZXRSU1N2YWx1ZSh3aWR0aHMsIG1heFdpZHRoLCBub05hcnJvdykge1xuICAgICAgICAgICAgbGV0IG4gPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgd2lkdGggb2Ygd2lkdGhzKSB7XG4gICAgICAgICAgICAgICAgbiArPSB3aWR0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCB2YWwgPSAwO1xuICAgICAgICAgICAgbGV0IG5hcnJvd01hc2sgPSAwO1xuICAgICAgICAgICAgbGV0IGVsZW1lbnRzID0gd2lkdGhzLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAobGV0IGJhciA9IDA7IGJhciA8IGVsZW1lbnRzIC0gMTsgYmFyKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgZWxtV2lkdGg7XG4gICAgICAgICAgICAgICAgZm9yIChlbG1XaWR0aCA9IDEsIG5hcnJvd01hc2sgfD0gMSA8PCBiYXI7IGVsbVdpZHRoIDwgd2lkdGhzW2Jhcl07IGVsbVdpZHRoKyssIG5hcnJvd01hc2sgJj0gfigxIDw8IGJhcikpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHN1YlZhbCA9IFJTU1V0aWxzLmNvbWJpbnMobiAtIGVsbVdpZHRoIC0gMSwgZWxlbWVudHMgLSBiYXIgLSAyKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5vTmFycm93ICYmIChuYXJyb3dNYXNrID09PSAwKSAmJiAobiAtIGVsbVdpZHRoIC0gKGVsZW1lbnRzIC0gYmFyIC0gMSkgPj0gZWxlbWVudHMgLSBiYXIgLSAxKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3ViVmFsIC09IFJTU1V0aWxzLmNvbWJpbnMobiAtIGVsbVdpZHRoIC0gKGVsZW1lbnRzIC0gYmFyKSwgZWxlbWVudHMgLSBiYXIgLSAyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudHMgLSBiYXIgLSAxID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGxlc3NWYWwgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgbXh3RWxlbWVudCA9IG4gLSBlbG1XaWR0aCAtIChlbGVtZW50cyAtIGJhciAtIDIpOyBteHdFbGVtZW50ID4gbWF4V2lkdGg7IG14d0VsZW1lbnQtLSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlc3NWYWwgKz0gUlNTVXRpbHMuY29tYmlucyhuIC0gZWxtV2lkdGggLSBteHdFbGVtZW50IC0gMSwgZWxlbWVudHMgLSBiYXIgLSAzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHN1YlZhbCAtPSBsZXNzVmFsICogKGVsZW1lbnRzIC0gMSAtIGJhcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobiAtIGVsbVdpZHRoID4gbWF4V2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1YlZhbC0tO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhbCArPSBzdWJWYWw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG4gLT0gZWxtV2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdmFsO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBjb21iaW5zKG4sIHIpIHtcbiAgICAgICAgICAgIGxldCBtYXhEZW5vbTtcbiAgICAgICAgICAgIGxldCBtaW5EZW5vbTtcbiAgICAgICAgICAgIGlmIChuIC0gciA+IHIpIHtcbiAgICAgICAgICAgICAgICBtaW5EZW5vbSA9IHI7XG4gICAgICAgICAgICAgICAgbWF4RGVub20gPSBuIC0gcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG1pbkRlbm9tID0gbiAtIHI7XG4gICAgICAgICAgICAgICAgbWF4RGVub20gPSByO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHZhbCA9IDE7XG4gICAgICAgICAgICBsZXQgaiA9IDE7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gbjsgaSA+IG1heERlbm9tOyBpLS0pIHtcbiAgICAgICAgICAgICAgICB2YWwgKj0gaTtcbiAgICAgICAgICAgICAgICBpZiAoaiA8PSBtaW5EZW5vbSkge1xuICAgICAgICAgICAgICAgICAgICB2YWwgLz0gajtcbiAgICAgICAgICAgICAgICAgICAgaisrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdoaWxlICgoaiA8PSBtaW5EZW5vbSkpIHtcbiAgICAgICAgICAgICAgICB2YWwgLz0gajtcbiAgICAgICAgICAgICAgICBqKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdmFsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xhc3MgQml0QXJyYXlCdWlsZGVyIHtcbiAgICAgICAgc3RhdGljIGJ1aWxkQml0QXJyYXkocGFpcnMpIHtcbiAgICAgICAgICAgIGxldCBjaGFyTnVtYmVyID0gKHBhaXJzLmxlbmd0aCAqIDIpIC0gMTtcbiAgICAgICAgICAgIGlmIChwYWlyc1twYWlycy5sZW5ndGggLSAxXS5nZXRSaWdodENoYXIoKSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgY2hhck51bWJlciAtPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHNpemUgPSAxMiAqIGNoYXJOdW1iZXI7XG4gICAgICAgICAgICBsZXQgYmluYXJ5ID0gbmV3IEJpdEFycmF5KHNpemUpO1xuICAgICAgICAgICAgbGV0IGFjY1BvcyA9IDA7XG4gICAgICAgICAgICBsZXQgZmlyc3RQYWlyID0gcGFpcnNbMF07XG4gICAgICAgICAgICBsZXQgZmlyc3RWYWx1ZSA9IGZpcnN0UGFpci5nZXRSaWdodENoYXIoKS5nZXRWYWx1ZSgpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDExOyBpID49IDA7IC0taSkge1xuICAgICAgICAgICAgICAgIGlmICgoZmlyc3RWYWx1ZSAmICgxIDw8IGkpKSAhPSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGJpbmFyeS5zZXQoYWNjUG9zKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYWNjUG9zKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHBhaXJzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgbGV0IGN1cnJlbnRQYWlyID0gcGFpcnNbaV07XG4gICAgICAgICAgICAgICAgbGV0IGxlZnRWYWx1ZSA9IGN1cnJlbnRQYWlyLmdldExlZnRDaGFyKCkuZ2V0VmFsdWUoKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMTE7IGogPj0gMDsgLS1qKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICgobGVmdFZhbHVlICYgKDEgPDwgaikpICE9IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJpbmFyeS5zZXQoYWNjUG9zKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBhY2NQb3MrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRQYWlyLmdldFJpZ2h0Q2hhcigpICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHJpZ2h0VmFsdWUgPSBjdXJyZW50UGFpci5nZXRSaWdodENoYXIoKS5nZXRWYWx1ZSgpO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMTE7IGogPj0gMDsgLS1qKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoKHJpZ2h0VmFsdWUgJiAoMSA8PCBqKSkgIT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpbmFyeS5zZXQoYWNjUG9zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGFjY1BvcysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGJpbmFyeTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNsYXNzIEJsb2NrUGFyc2VkUmVzdWx0IHtcbiAgICAgICAgY29uc3RydWN0b3IoZmluaXNoZWQsIGRlY29kZWRJbmZvcm1hdGlvbikge1xuICAgICAgICAgICAgaWYgKGRlY29kZWRJbmZvcm1hdGlvbikge1xuICAgICAgICAgICAgICAgIHRoaXMuZGVjb2RlZEluZm9ybWF0aW9uID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuZmluaXNoZWQgPSBmaW5pc2hlZDtcbiAgICAgICAgICAgICAgICB0aGlzLmRlY29kZWRJbmZvcm1hdGlvbiA9IGRlY29kZWRJbmZvcm1hdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBnZXREZWNvZGVkSW5mb3JtYXRpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGVkSW5mb3JtYXRpb247XG4gICAgICAgIH1cbiAgICAgICAgaXNGaW5pc2hlZCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbmlzaGVkO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xhc3MgRGVjb2RlZE9iamVjdCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKG5ld1Bvc2l0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLm5ld1Bvc2l0aW9uID0gbmV3UG9zaXRpb247XG4gICAgICAgIH1cbiAgICAgICAgZ2V0TmV3UG9zaXRpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5uZXdQb3NpdGlvbjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNsYXNzIERlY29kZWRDaGFyIGV4dGVuZHMgRGVjb2RlZE9iamVjdCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKG5ld1Bvc2l0aW9uLCB2YWx1ZSkge1xuICAgICAgICAgICAgc3VwZXIobmV3UG9zaXRpb24pO1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGdldFZhbHVlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaXNGTkMxKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWUgPT09IERlY29kZWRDaGFyLkZOQzE7XG4gICAgICAgIH1cbiAgICB9XG4gICAgRGVjb2RlZENoYXIuRk5DMSA9ICckJztcblxuICAgIGNsYXNzIERlY29kZWRJbmZvcm1hdGlvbiBleHRlbmRzIERlY29kZWRPYmplY3Qge1xuICAgICAgICBjb25zdHJ1Y3RvcihuZXdQb3NpdGlvbiwgbmV3U3RyaW5nLCByZW1haW5pbmdWYWx1ZSkge1xuICAgICAgICAgICAgc3VwZXIobmV3UG9zaXRpb24pO1xuICAgICAgICAgICAgaWYgKHJlbWFpbmluZ1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1haW5pbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMucmVtYWluaW5nVmFsdWUgPSB0aGlzLnJlbWFpbmluZ1ZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1haW5pbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbWFpbmluZ1ZhbHVlID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMubmV3U3RyaW5nID0gbmV3U3RyaW5nO1xuICAgICAgICB9XG4gICAgICAgIGdldE5ld1N0cmluZygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm5ld1N0cmluZztcbiAgICAgICAgfVxuICAgICAgICBpc1JlbWFpbmluZygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlbWFpbmluZztcbiAgICAgICAgfVxuICAgICAgICBnZXRSZW1haW5pbmdWYWx1ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlbWFpbmluZ1ZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xhc3MgRGVjb2RlZE51bWVyaWMgZXh0ZW5kcyBEZWNvZGVkT2JqZWN0IHtcbiAgICAgICAgY29uc3RydWN0b3IobmV3UG9zaXRpb24sIGZpcnN0RGlnaXQsIHNlY29uZERpZ2l0KSB7XG4gICAgICAgICAgICBzdXBlcihuZXdQb3NpdGlvbik7XG4gICAgICAgICAgICBpZiAoZmlyc3REaWdpdCA8IDAgfHwgZmlyc3REaWdpdCA+IDEwIHx8IHNlY29uZERpZ2l0IDwgMCB8fCBzZWNvbmREaWdpdCA+IDEwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5maXJzdERpZ2l0ID0gZmlyc3REaWdpdDtcbiAgICAgICAgICAgIHRoaXMuc2Vjb25kRGlnaXQgPSBzZWNvbmREaWdpdDtcbiAgICAgICAgfVxuICAgICAgICBnZXRGaXJzdERpZ2l0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmlyc3REaWdpdDtcbiAgICAgICAgfVxuICAgICAgICBnZXRTZWNvbmREaWdpdCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNlY29uZERpZ2l0O1xuICAgICAgICB9XG4gICAgICAgIGdldFZhbHVlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmlyc3REaWdpdCAqIDEwICsgdGhpcy5zZWNvbmREaWdpdDtcbiAgICAgICAgfVxuICAgICAgICBpc0ZpcnN0RGlnaXRGTkMxKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmlyc3REaWdpdCA9PT0gRGVjb2RlZE51bWVyaWMuRk5DMTtcbiAgICAgICAgfVxuICAgICAgICBpc1NlY29uZERpZ2l0Rk5DMSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNlY29uZERpZ2l0ID09PSBEZWNvZGVkTnVtZXJpYy5GTkMxO1xuICAgICAgICB9XG4gICAgICAgIGlzQW55Rk5DMSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZpcnN0RGlnaXQgPT09IERlY29kZWROdW1lcmljLkZOQzEgfHwgdGhpcy5zZWNvbmREaWdpdCA9PT0gRGVjb2RlZE51bWVyaWMuRk5DMTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBEZWNvZGVkTnVtZXJpYy5GTkMxID0gMTA7XG5cbiAgICBjbGFzcyBGaWVsZFBhcnNlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBwYXJzZUZpZWxkc0luR2VuZXJhbFB1cnBvc2UocmF3SW5mb3JtYXRpb24pIHtcbiAgICAgICAgICAgIGlmICghcmF3SW5mb3JtYXRpb24pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFByb2Nlc3NpbmcgMi1kaWdpdCBBSXNcbiAgICAgICAgICAgIGlmIChyYXdJbmZvcm1hdGlvbi5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZmlyc3RUd29EaWdpdHMgPSByYXdJbmZvcm1hdGlvbi5zdWJzdHJpbmcoMCwgMik7XG4gICAgICAgICAgICBmb3IgKGxldCBkYXRhTGVuZ3RoIG9mIEZpZWxkUGFyc2VyLlRXT19ESUdJVF9EQVRBX0xFTkdUSCkge1xuICAgICAgICAgICAgICAgIGlmIChkYXRhTGVuZ3RoWzBdID09PSBmaXJzdFR3b0RpZ2l0cykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YUxlbmd0aFsxXSA9PT0gRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RIKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gRmllbGRQYXJzZXIucHJvY2Vzc1ZhcmlhYmxlQUkoMiwgZGF0YUxlbmd0aFsyXSwgcmF3SW5mb3JtYXRpb24pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBGaWVsZFBhcnNlci5wcm9jZXNzRml4ZWRBSSgyLCBkYXRhTGVuZ3RoWzFdLCByYXdJbmZvcm1hdGlvbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJhd0luZm9ybWF0aW9uLmxlbmd0aCA8IDMpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBmaXJzdFRocmVlRGlnaXRzID0gcmF3SW5mb3JtYXRpb24uc3Vic3RyaW5nKDAsIDMpO1xuICAgICAgICAgICAgZm9yIChsZXQgZGF0YUxlbmd0aCBvZiBGaWVsZFBhcnNlci5USFJFRV9ESUdJVF9EQVRBX0xFTkdUSCkge1xuICAgICAgICAgICAgICAgIGlmIChkYXRhTGVuZ3RoWzBdID09PSBmaXJzdFRocmVlRGlnaXRzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChkYXRhTGVuZ3RoWzFdID09PSBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBGaWVsZFBhcnNlci5wcm9jZXNzVmFyaWFibGVBSSgzLCBkYXRhTGVuZ3RoWzJdLCByYXdJbmZvcm1hdGlvbik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEZpZWxkUGFyc2VyLnByb2Nlc3NGaXhlZEFJKDMsIGRhdGFMZW5ndGhbMV0sIHJhd0luZm9ybWF0aW9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBkYXRhTGVuZ3RoIG9mIEZpZWxkUGFyc2VyLlRIUkVFX0RJR0lUX1BMVVNfRElHSVRfREFUQV9MRU5HVEgpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YUxlbmd0aFswXSA9PT0gZmlyc3RUaHJlZURpZ2l0cykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YUxlbmd0aFsxXSA9PT0gRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RIKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gRmllbGRQYXJzZXIucHJvY2Vzc1ZhcmlhYmxlQUkoNCwgZGF0YUxlbmd0aFsyXSwgcmF3SW5mb3JtYXRpb24pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBGaWVsZFBhcnNlci5wcm9jZXNzRml4ZWRBSSg0LCBkYXRhTGVuZ3RoWzFdLCByYXdJbmZvcm1hdGlvbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJhd0luZm9ybWF0aW9uLmxlbmd0aCA8IDQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBmaXJzdEZvdXJEaWdpdHMgPSByYXdJbmZvcm1hdGlvbi5zdWJzdHJpbmcoMCwgNCk7XG4gICAgICAgICAgICBmb3IgKGxldCBkYXRhTGVuZ3RoIG9mIEZpZWxkUGFyc2VyLkZPVVJfRElHSVRfREFUQV9MRU5HVEgpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YUxlbmd0aFswXSA9PT0gZmlyc3RGb3VyRGlnaXRzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChkYXRhTGVuZ3RoWzFdID09PSBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBGaWVsZFBhcnNlci5wcm9jZXNzVmFyaWFibGVBSSg0LCBkYXRhTGVuZ3RoWzJdLCByYXdJbmZvcm1hdGlvbik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEZpZWxkUGFyc2VyLnByb2Nlc3NGaXhlZEFJKDQsIGRhdGFMZW5ndGhbMV0sIHJhd0luZm9ybWF0aW9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgcHJvY2Vzc0ZpeGVkQUkoYWlTaXplLCBmaWVsZFNpemUsIHJhd0luZm9ybWF0aW9uKSB7XG4gICAgICAgICAgICBpZiAocmF3SW5mb3JtYXRpb24ubGVuZ3RoIDwgYWlTaXplKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgYWkgPSByYXdJbmZvcm1hdGlvbi5zdWJzdHJpbmcoMCwgYWlTaXplKTtcbiAgICAgICAgICAgIGlmIChyYXdJbmZvcm1hdGlvbi5sZW5ndGggPCBhaVNpemUgKyBmaWVsZFNpemUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBmaWVsZCA9IHJhd0luZm9ybWF0aW9uLnN1YnN0cmluZyhhaVNpemUsIGFpU2l6ZSArIGZpZWxkU2l6ZSk7XG4gICAgICAgICAgICBsZXQgcmVtYWluaW5nID0gcmF3SW5mb3JtYXRpb24uc3Vic3RyaW5nKGFpU2l6ZSArIGZpZWxkU2l6ZSk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gJygnICsgYWkgKyAnKScgKyBmaWVsZDtcbiAgICAgICAgICAgIGxldCBwYXJzZWRBSSA9IEZpZWxkUGFyc2VyLnBhcnNlRmllbGRzSW5HZW5lcmFsUHVycG9zZShyZW1haW5pbmcpO1xuICAgICAgICAgICAgcmV0dXJuIHBhcnNlZEFJID09IG51bGwgPyByZXN1bHQgOiByZXN1bHQgKyBwYXJzZWRBSTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgcHJvY2Vzc1ZhcmlhYmxlQUkoYWlTaXplLCB2YXJpYWJsZUZpZWxkU2l6ZSwgcmF3SW5mb3JtYXRpb24pIHtcbiAgICAgICAgICAgIGxldCBhaSA9IHJhd0luZm9ybWF0aW9uLnN1YnN0cmluZygwLCBhaVNpemUpO1xuICAgICAgICAgICAgbGV0IG1heFNpemU7XG4gICAgICAgICAgICBpZiAocmF3SW5mb3JtYXRpb24ubGVuZ3RoIDwgYWlTaXplICsgdmFyaWFibGVGaWVsZFNpemUpIHtcbiAgICAgICAgICAgICAgICBtYXhTaXplID0gcmF3SW5mb3JtYXRpb24ubGVuZ3RoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbWF4U2l6ZSA9IGFpU2l6ZSArIHZhcmlhYmxlRmllbGRTaXplO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGZpZWxkID0gcmF3SW5mb3JtYXRpb24uc3Vic3RyaW5nKGFpU2l6ZSwgbWF4U2l6ZSk7XG4gICAgICAgICAgICBsZXQgcmVtYWluaW5nID0gcmF3SW5mb3JtYXRpb24uc3Vic3RyaW5nKG1heFNpemUpO1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9ICcoJyArIGFpICsgJyknICsgZmllbGQ7XG4gICAgICAgICAgICBsZXQgcGFyc2VkQUkgPSBGaWVsZFBhcnNlci5wYXJzZUZpZWxkc0luR2VuZXJhbFB1cnBvc2UocmVtYWluaW5nKTtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZWRBSSA9PSBudWxsID8gcmVzdWx0IDogcmVzdWx0ICsgcGFyc2VkQUk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RIID0gW107XG4gICAgRmllbGRQYXJzZXIuVFdPX0RJR0lUX0RBVEFfTEVOR1RIID0gW1xuICAgICAgICBbJzAwJywgMThdLFxuICAgICAgICBbJzAxJywgMTRdLFxuICAgICAgICBbJzAyJywgMTRdLFxuICAgICAgICBbJzEwJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAyMF0sXG4gICAgICAgIFsnMTEnLCA2XSxcbiAgICAgICAgWycxMicsIDZdLFxuICAgICAgICBbJzEzJywgNl0sXG4gICAgICAgIFsnMTUnLCA2XSxcbiAgICAgICAgWycxNycsIDZdLFxuICAgICAgICBbJzIwJywgMl0sXG4gICAgICAgIFsnMjEnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDIwXSxcbiAgICAgICAgWycyMicsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMjldLFxuICAgICAgICBbJzMwJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCA4XSxcbiAgICAgICAgWyczNycsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgOF0sXG4gICAgICAgIC8vIGludGVybmFsIGNvbXBhbnkgY29kZXNcbiAgICAgICAgWyc5MCcsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMzBdLFxuICAgICAgICBbJzkxJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAzMF0sXG4gICAgICAgIFsnOTInLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDMwXSxcbiAgICAgICAgWyc5MycsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMzBdLFxuICAgICAgICBbJzk0JywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAzMF0sXG4gICAgICAgIFsnOTUnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDMwXSxcbiAgICAgICAgWyc5NicsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMzBdLFxuICAgICAgICBbJzk3JywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAzXSxcbiAgICAgICAgWyc5OCcsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMzBdLFxuICAgICAgICBbJzk5JywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAzMF0sXG4gICAgXTtcbiAgICBGaWVsZFBhcnNlci5USFJFRV9ESUdJVF9EQVRBX0xFTkdUSCA9IFtcbiAgICAgICAgLy8gU2FtZSBmb3JtYXQgYXMgYWJvdmVcbiAgICAgICAgWycyNDAnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDMwXSxcbiAgICAgICAgWycyNDEnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDMwXSxcbiAgICAgICAgWycyNDInLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDZdLFxuICAgICAgICBbJzI1MCcsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMzBdLFxuICAgICAgICBbJzI1MScsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMzBdLFxuICAgICAgICBbJzI1MycsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMTddLFxuICAgICAgICBbJzI1NCcsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMjBdLFxuICAgICAgICBbJzQwMCcsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMzBdLFxuICAgICAgICBbJzQwMScsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMzBdLFxuICAgICAgICBbJzQwMicsIDE3XSxcbiAgICAgICAgWyc0MDMnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDMwXSxcbiAgICAgICAgWyc0MTAnLCAxM10sXG4gICAgICAgIFsnNDExJywgMTNdLFxuICAgICAgICBbJzQxMicsIDEzXSxcbiAgICAgICAgWyc0MTMnLCAxM10sXG4gICAgICAgIFsnNDE0JywgMTNdLFxuICAgICAgICBbJzQyMCcsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMjBdLFxuICAgICAgICBbJzQyMScsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMTVdLFxuICAgICAgICBbJzQyMicsIDNdLFxuICAgICAgICBbJzQyMycsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMTVdLFxuICAgICAgICBbJzQyNCcsIDNdLFxuICAgICAgICBbJzQyNScsIDNdLFxuICAgICAgICBbJzQyNicsIDNdLFxuICAgIF07XG4gICAgRmllbGRQYXJzZXIuVEhSRUVfRElHSVRfUExVU19ESUdJVF9EQVRBX0xFTkdUSCA9IFtcbiAgICAgICAgLy8gU2FtZSBmb3JtYXQgYXMgYWJvdmVcbiAgICAgICAgWyczMTAnLCA2XSxcbiAgICAgICAgWyczMTEnLCA2XSxcbiAgICAgICAgWyczMTInLCA2XSxcbiAgICAgICAgWyczMTMnLCA2XSxcbiAgICAgICAgWyczMTQnLCA2XSxcbiAgICAgICAgWyczMTUnLCA2XSxcbiAgICAgICAgWyczMTYnLCA2XSxcbiAgICAgICAgWyczMjAnLCA2XSxcbiAgICAgICAgWyczMjEnLCA2XSxcbiAgICAgICAgWyczMjInLCA2XSxcbiAgICAgICAgWyczMjMnLCA2XSxcbiAgICAgICAgWyczMjQnLCA2XSxcbiAgICAgICAgWyczMjUnLCA2XSxcbiAgICAgICAgWyczMjYnLCA2XSxcbiAgICAgICAgWyczMjcnLCA2XSxcbiAgICAgICAgWyczMjgnLCA2XSxcbiAgICAgICAgWyczMjknLCA2XSxcbiAgICAgICAgWyczMzAnLCA2XSxcbiAgICAgICAgWyczMzEnLCA2XSxcbiAgICAgICAgWyczMzInLCA2XSxcbiAgICAgICAgWyczMzMnLCA2XSxcbiAgICAgICAgWyczMzQnLCA2XSxcbiAgICAgICAgWyczMzUnLCA2XSxcbiAgICAgICAgWyczMzYnLCA2XSxcbiAgICAgICAgWyczNDAnLCA2XSxcbiAgICAgICAgWyczNDEnLCA2XSxcbiAgICAgICAgWyczNDInLCA2XSxcbiAgICAgICAgWyczNDMnLCA2XSxcbiAgICAgICAgWyczNDQnLCA2XSxcbiAgICAgICAgWyczNDUnLCA2XSxcbiAgICAgICAgWyczNDYnLCA2XSxcbiAgICAgICAgWyczNDcnLCA2XSxcbiAgICAgICAgWyczNDgnLCA2XSxcbiAgICAgICAgWyczNDknLCA2XSxcbiAgICAgICAgWyczNTAnLCA2XSxcbiAgICAgICAgWyczNTEnLCA2XSxcbiAgICAgICAgWyczNTInLCA2XSxcbiAgICAgICAgWyczNTMnLCA2XSxcbiAgICAgICAgWyczNTQnLCA2XSxcbiAgICAgICAgWyczNTUnLCA2XSxcbiAgICAgICAgWyczNTYnLCA2XSxcbiAgICAgICAgWyczNTcnLCA2XSxcbiAgICAgICAgWyczNjAnLCA2XSxcbiAgICAgICAgWyczNjEnLCA2XSxcbiAgICAgICAgWyczNjInLCA2XSxcbiAgICAgICAgWyczNjMnLCA2XSxcbiAgICAgICAgWyczNjQnLCA2XSxcbiAgICAgICAgWyczNjUnLCA2XSxcbiAgICAgICAgWyczNjYnLCA2XSxcbiAgICAgICAgWyczNjcnLCA2XSxcbiAgICAgICAgWyczNjgnLCA2XSxcbiAgICAgICAgWyczNjknLCA2XSxcbiAgICAgICAgWyczOTAnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDE1XSxcbiAgICAgICAgWyczOTEnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDE4XSxcbiAgICAgICAgWyczOTInLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDE1XSxcbiAgICAgICAgWyczOTMnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDE4XSxcbiAgICAgICAgWyc3MDMnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDMwXSxcbiAgICBdO1xuICAgIEZpZWxkUGFyc2VyLkZPVVJfRElHSVRfREFUQV9MRU5HVEggPSBbXG4gICAgICAgIC8vIFNhbWUgZm9ybWF0IGFzIGFib3ZlXG4gICAgICAgIFsnNzAwMScsIDEzXSxcbiAgICAgICAgWyc3MDAyJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAzMF0sXG4gICAgICAgIFsnNzAwMycsIDEwXSxcbiAgICAgICAgWyc4MDAxJywgMTRdLFxuICAgICAgICBbJzgwMDInLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDIwXSxcbiAgICAgICAgWyc4MDAzJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAzMF0sXG4gICAgICAgIFsnODAwNCcsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMzBdLFxuICAgICAgICBbJzgwMDUnLCA2XSxcbiAgICAgICAgWyc4MDA2JywgMThdLFxuICAgICAgICBbJzgwMDcnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDMwXSxcbiAgICAgICAgWyc4MDA4JywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAxMl0sXG4gICAgICAgIFsnODAxOCcsIDE4XSxcbiAgICAgICAgWyc4MDIwJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAyNV0sXG4gICAgICAgIFsnODEwMCcsIDZdLFxuICAgICAgICBbJzgxMDEnLCAxMF0sXG4gICAgICAgIFsnODEwMicsIDJdLFxuICAgICAgICBbJzgxMTAnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDcwXSxcbiAgICAgICAgWyc4MjAwJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCA3MF0sXG4gICAgXTtcblxuICAgIGNsYXNzIEdlbmVyYWxBcHBJZERlY29kZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcihpbmZvcm1hdGlvbikge1xuICAgICAgICAgICAgdGhpcy5idWZmZXIgPSBuZXcgU3RyaW5nQnVpbGRlcigpO1xuICAgICAgICAgICAgdGhpcy5pbmZvcm1hdGlvbiA9IGluZm9ybWF0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGRlY29kZUFsbENvZGVzKGJ1ZmYsIGluaXRpYWxQb3NpdGlvbikge1xuICAgICAgICAgICAgbGV0IGN1cnJlbnRQb3NpdGlvbiA9IGluaXRpYWxQb3NpdGlvbjtcbiAgICAgICAgICAgIGxldCByZW1haW5pbmcgPSBudWxsO1xuICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgIGxldCBpbmZvID0gdGhpcy5kZWNvZGVHZW5lcmFsUHVycG9zZUZpZWxkKGN1cnJlbnRQb3NpdGlvbiwgcmVtYWluaW5nKTtcbiAgICAgICAgICAgICAgICBsZXQgcGFyc2VkRmllbGRzID0gRmllbGRQYXJzZXIucGFyc2VGaWVsZHNJbkdlbmVyYWxQdXJwb3NlKGluZm8uZ2V0TmV3U3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgIGlmIChwYXJzZWRGaWVsZHMgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBidWZmLmFwcGVuZChwYXJzZWRGaWVsZHMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoaW5mby5pc1JlbWFpbmluZygpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbWFpbmluZyA9ICcnICsgaW5mby5nZXRSZW1haW5pbmdWYWx1ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtYWluaW5nID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRQb3NpdGlvbiA9PT0gaW5mby5nZXROZXdQb3NpdGlvbigpKSB7IC8vIE5vIHN0ZXAgZm9yd2FyZCFcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGN1cnJlbnRQb3NpdGlvbiA9IGluZm8uZ2V0TmV3UG9zaXRpb24oKTtcbiAgICAgICAgICAgIH0gd2hpbGUgKHRydWUpO1xuICAgICAgICAgICAgcmV0dXJuIGJ1ZmYudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgICAgICBpc1N0aWxsTnVtZXJpYyhwb3MpIHtcbiAgICAgICAgICAgIC8vIEl0J3MgbnVtZXJpYyBpZiBpdCBzdGlsbCBoYXMgNyBwb3NpdGlvbnNcbiAgICAgICAgICAgIC8vIGFuZCBvbmUgb2YgdGhlIGZpcnN0IDQgYml0cyBpcyBcIjFcIi5cbiAgICAgICAgICAgIGlmIChwb3MgKyA3ID4gdGhpcy5pbmZvcm1hdGlvbi5nZXRTaXplKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcG9zICsgNCA8PSB0aGlzLmluZm9ybWF0aW9uLmdldFNpemUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBwb3M7IGkgPCBwb3MgKyAzOyArK2kpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pbmZvcm1hdGlvbi5nZXQoaSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5mb3JtYXRpb24uZ2V0KHBvcyArIDMpO1xuICAgICAgICB9XG4gICAgICAgIGRlY29kZU51bWVyaWMocG9zKSB7XG4gICAgICAgICAgICBpZiAocG9zICsgNyA+IHRoaXMuaW5mb3JtYXRpb24uZ2V0U2l6ZSgpKSB7XG4gICAgICAgICAgICAgICAgbGV0IG51bWVyaWMgPSB0aGlzLmV4dHJhY3ROdW1lcmljVmFsdWVGcm9tQml0QXJyYXkocG9zLCA0KTtcbiAgICAgICAgICAgICAgICBpZiAobnVtZXJpYyA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERlY29kZWROdW1lcmljKHRoaXMuaW5mb3JtYXRpb24uZ2V0U2l6ZSgpLCBEZWNvZGVkTnVtZXJpYy5GTkMxLCBEZWNvZGVkTnVtZXJpYy5GTkMxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBEZWNvZGVkTnVtZXJpYyh0aGlzLmluZm9ybWF0aW9uLmdldFNpemUoKSwgbnVtZXJpYyAtIDEsIERlY29kZWROdW1lcmljLkZOQzEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IG51bWVyaWMgPSB0aGlzLmV4dHJhY3ROdW1lcmljVmFsdWVGcm9tQml0QXJyYXkocG9zLCA3KTtcbiAgICAgICAgICAgIGxldCBkaWdpdDEgPSAobnVtZXJpYyAtIDgpIC8gMTE7XG4gICAgICAgICAgICBsZXQgZGlnaXQyID0gKG51bWVyaWMgLSA4KSAlIDExO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBEZWNvZGVkTnVtZXJpYyhwb3MgKyA3LCBkaWdpdDEsIGRpZ2l0Mik7XG4gICAgICAgIH1cbiAgICAgICAgZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShwb3MsIGJpdHMpIHtcbiAgICAgICAgICAgIHJldHVybiBHZW5lcmFsQXBwSWREZWNvZGVyLmV4dHJhY3ROdW1lcmljVmFsdWVGcm9tQml0QXJyYXkodGhpcy5pbmZvcm1hdGlvbiwgcG9zLCBiaXRzKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShpbmZvcm1hdGlvbiwgcG9zLCBiaXRzKSB7XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBiaXRzOyArK2kpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5mb3JtYXRpb24uZ2V0KHBvcyArIGkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlIHw9IDEgPDwgKGJpdHMgLSBpIC0gMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGRlY29kZUdlbmVyYWxQdXJwb3NlRmllbGQocG9zLCByZW1haW5pbmcpIHtcbiAgICAgICAgICAgIC8vIHRoaXMuYnVmZmVyLnNldExlbmd0aCgwKTtcbiAgICAgICAgICAgIHRoaXMuYnVmZmVyLnNldExlbmd0aFRvWmVybygpO1xuICAgICAgICAgICAgaWYgKHJlbWFpbmluZyAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5idWZmZXIuYXBwZW5kKHJlbWFpbmluZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnQuc2V0UG9zaXRpb24ocG9zKTtcbiAgICAgICAgICAgIGxldCBsYXN0RGVjb2RlZCA9IHRoaXMucGFyc2VCbG9ja3MoKTtcbiAgICAgICAgICAgIGlmIChsYXN0RGVjb2RlZCAhPSBudWxsICYmIGxhc3REZWNvZGVkLmlzUmVtYWluaW5nKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERlY29kZWRJbmZvcm1hdGlvbih0aGlzLmN1cnJlbnQuZ2V0UG9zaXRpb24oKSwgdGhpcy5idWZmZXIudG9TdHJpbmcoKSwgbGFzdERlY29kZWQuZ2V0UmVtYWluaW5nVmFsdWUoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IERlY29kZWRJbmZvcm1hdGlvbih0aGlzLmN1cnJlbnQuZ2V0UG9zaXRpb24oKSwgdGhpcy5idWZmZXIudG9TdHJpbmcoKSk7XG4gICAgICAgIH1cbiAgICAgICAgcGFyc2VCbG9ja3MoKSB7XG4gICAgICAgICAgICBsZXQgaXNGaW5pc2hlZDtcbiAgICAgICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgbGV0IGluaXRpYWxQb3NpdGlvbiA9IHRoaXMuY3VycmVudC5nZXRQb3NpdGlvbigpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnQuaXNBbHBoYSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMucGFyc2VBbHBoYUJsb2NrKCk7XG4gICAgICAgICAgICAgICAgICAgIGlzRmluaXNoZWQgPSByZXN1bHQuaXNGaW5pc2hlZCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0aGlzLmN1cnJlbnQuaXNJc29JZWM2NDYoKSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLnBhcnNlSXNvSWVjNjQ2QmxvY2soKTtcbiAgICAgICAgICAgICAgICAgICAgaXNGaW5pc2hlZCA9IHJlc3VsdC5pc0ZpbmlzaGVkKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgeyAvLyBpdCBtdXN0IGJlIG51bWVyaWNcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy5wYXJzZU51bWVyaWNCbG9jaygpO1xuICAgICAgICAgICAgICAgICAgICBpc0ZpbmlzaGVkID0gcmVzdWx0LmlzRmluaXNoZWQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IHBvc2l0aW9uQ2hhbmdlZCA9IGluaXRpYWxQb3NpdGlvbiAhPT0gdGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCk7XG4gICAgICAgICAgICAgICAgaWYgKCFwb3NpdGlvbkNoYW5nZWQgJiYgIWlzRmluaXNoZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSB3aGlsZSAoIWlzRmluaXNoZWQpO1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC5nZXREZWNvZGVkSW5mb3JtYXRpb24oKTtcbiAgICAgICAgfVxuICAgICAgICBwYXJzZU51bWVyaWNCbG9jaygpIHtcbiAgICAgICAgICAgIHdoaWxlICh0aGlzLmlzU3RpbGxOdW1lcmljKHRoaXMuY3VycmVudC5nZXRQb3NpdGlvbigpKSkge1xuICAgICAgICAgICAgICAgIGxldCBudW1lcmljID0gdGhpcy5kZWNvZGVOdW1lcmljKHRoaXMuY3VycmVudC5nZXRQb3NpdGlvbigpKTtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQuc2V0UG9zaXRpb24obnVtZXJpYy5nZXROZXdQb3NpdGlvbigpKTtcbiAgICAgICAgICAgICAgICBpZiAobnVtZXJpYy5pc0ZpcnN0RGlnaXRGTkMxKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGluZm9ybWF0aW9uO1xuICAgICAgICAgICAgICAgICAgICBpZiAobnVtZXJpYy5pc1NlY29uZERpZ2l0Rk5DMSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmZvcm1hdGlvbiA9IG5ldyBEZWNvZGVkSW5mb3JtYXRpb24odGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCksIHRoaXMuYnVmZmVyLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5mb3JtYXRpb24gPSBuZXcgRGVjb2RlZEluZm9ybWF0aW9uKHRoaXMuY3VycmVudC5nZXRQb3NpdGlvbigpLCB0aGlzLmJ1ZmZlci50b1N0cmluZygpLCBudW1lcmljLmdldFNlY29uZERpZ2l0KCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQmxvY2tQYXJzZWRSZXN1bHQodHJ1ZSwgaW5mb3JtYXRpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZlci5hcHBlbmQobnVtZXJpYy5nZXRGaXJzdERpZ2l0KCkpO1xuICAgICAgICAgICAgICAgIGlmIChudW1lcmljLmlzU2Vjb25kRGlnaXRGTkMxKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGluZm9ybWF0aW9uID0gbmV3IERlY29kZWRJbmZvcm1hdGlvbih0aGlzLmN1cnJlbnQuZ2V0UG9zaXRpb24oKSwgdGhpcy5idWZmZXIudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQmxvY2tQYXJzZWRSZXN1bHQodHJ1ZSwgaW5mb3JtYXRpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZlci5hcHBlbmQobnVtZXJpYy5nZXRTZWNvbmREaWdpdCgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmlzTnVtZXJpY1RvQWxwaGFOdW1lcmljTGF0Y2godGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCkpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnNldEFscGhhKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LmluY3JlbWVudFBvc2l0aW9uKDQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBCbG9ja1BhcnNlZFJlc3VsdChmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgcGFyc2VJc29JZWM2NDZCbG9jaygpIHtcbiAgICAgICAgICAgIHdoaWxlICh0aGlzLmlzU3RpbGxJc29JZWM2NDYodGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCkpKSB7XG4gICAgICAgICAgICAgICAgbGV0IGlzbyA9IHRoaXMuZGVjb2RlSXNvSWVjNjQ2KHRoaXMuY3VycmVudC5nZXRQb3NpdGlvbigpKTtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQuc2V0UG9zaXRpb24oaXNvLmdldE5ld1Bvc2l0aW9uKCkpO1xuICAgICAgICAgICAgICAgIGlmIChpc28uaXNGTkMxKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGluZm9ybWF0aW9uID0gbmV3IERlY29kZWRJbmZvcm1hdGlvbih0aGlzLmN1cnJlbnQuZ2V0UG9zaXRpb24oKSwgdGhpcy5idWZmZXIudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQmxvY2tQYXJzZWRSZXN1bHQodHJ1ZSwgaW5mb3JtYXRpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZlci5hcHBlbmQoaXNvLmdldFZhbHVlKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaXNBbHBoYU9yNjQ2VG9OdW1lcmljTGF0Y2godGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCkpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LmluY3JlbWVudFBvc2l0aW9uKDMpO1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5zZXROdW1lcmljKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLmlzQWxwaGFUbzY0NlRvQWxwaGFMYXRjaCh0aGlzLmN1cnJlbnQuZ2V0UG9zaXRpb24oKSkpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCkgKyA1IDwgdGhpcy5pbmZvcm1hdGlvbi5nZXRTaXplKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LmluY3JlbWVudFBvc2l0aW9uKDUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnNldFBvc2l0aW9uKHRoaXMuaW5mb3JtYXRpb24uZ2V0U2l6ZSgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnNldEFscGhhKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IEJsb2NrUGFyc2VkUmVzdWx0KGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICBwYXJzZUFscGhhQmxvY2soKSB7XG4gICAgICAgICAgICB3aGlsZSAodGhpcy5pc1N0aWxsQWxwaGEodGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCkpKSB7XG4gICAgICAgICAgICAgICAgbGV0IGFscGhhID0gdGhpcy5kZWNvZGVBbHBoYW51bWVyaWModGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCkpO1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5zZXRQb3NpdGlvbihhbHBoYS5nZXROZXdQb3NpdGlvbigpKTtcbiAgICAgICAgICAgICAgICBpZiAoYWxwaGEuaXNGTkMxKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGluZm9ybWF0aW9uID0gbmV3IERlY29kZWRJbmZvcm1hdGlvbih0aGlzLmN1cnJlbnQuZ2V0UG9zaXRpb24oKSwgdGhpcy5idWZmZXIudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQmxvY2tQYXJzZWRSZXN1bHQodHJ1ZSwgaW5mb3JtYXRpb24pOyAvLyBlbmQgb2YgdGhlIGNoYXIgYmxvY2tcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5idWZmZXIuYXBwZW5kKGFscGhhLmdldFZhbHVlKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaXNBbHBoYU9yNjQ2VG9OdW1lcmljTGF0Y2godGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCkpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LmluY3JlbWVudFBvc2l0aW9uKDMpO1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5zZXROdW1lcmljKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLmlzQWxwaGFUbzY0NlRvQWxwaGFMYXRjaCh0aGlzLmN1cnJlbnQuZ2V0UG9zaXRpb24oKSkpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCkgKyA1IDwgdGhpcy5pbmZvcm1hdGlvbi5nZXRTaXplKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LmluY3JlbWVudFBvc2l0aW9uKDUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnNldFBvc2l0aW9uKHRoaXMuaW5mb3JtYXRpb24uZ2V0U2l6ZSgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnNldElzb0llYzY0NigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBCbG9ja1BhcnNlZFJlc3VsdChmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgaXNTdGlsbElzb0llYzY0Nihwb3MpIHtcbiAgICAgICAgICAgIGlmIChwb3MgKyA1ID4gdGhpcy5pbmZvcm1hdGlvbi5nZXRTaXplKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZml2ZUJpdFZhbHVlID0gdGhpcy5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KHBvcywgNSk7XG4gICAgICAgICAgICBpZiAoZml2ZUJpdFZhbHVlID49IDUgJiYgZml2ZUJpdFZhbHVlIDwgMTYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChwb3MgKyA3ID4gdGhpcy5pbmZvcm1hdGlvbi5nZXRTaXplKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc2V2ZW5CaXRWYWx1ZSA9IHRoaXMuZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShwb3MsIDcpO1xuICAgICAgICAgICAgaWYgKHNldmVuQml0VmFsdWUgPj0gNjQgJiYgc2V2ZW5CaXRWYWx1ZSA8IDExNikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBvcyArIDggPiB0aGlzLmluZm9ybWF0aW9uLmdldFNpemUoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBlaWdodEJpdFZhbHVlID0gdGhpcy5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KHBvcywgOCk7XG4gICAgICAgICAgICByZXR1cm4gZWlnaHRCaXRWYWx1ZSA+PSAyMzIgJiYgZWlnaHRCaXRWYWx1ZSA8IDI1MztcbiAgICAgICAgfVxuICAgICAgICBkZWNvZGVJc29JZWM2NDYocG9zKSB7XG4gICAgICAgICAgICBsZXQgZml2ZUJpdFZhbHVlID0gdGhpcy5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KHBvcywgNSk7XG4gICAgICAgICAgICBpZiAoZml2ZUJpdFZhbHVlID09PSAxNSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRGVjb2RlZENoYXIocG9zICsgNSwgRGVjb2RlZENoYXIuRk5DMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZml2ZUJpdFZhbHVlID49IDUgJiYgZml2ZUJpdFZhbHVlIDwgMTUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERlY29kZWRDaGFyKHBvcyArIDUsICgnMCcgKyAoZml2ZUJpdFZhbHVlIC0gNSkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBzZXZlbkJpdFZhbHVlID0gdGhpcy5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KHBvcywgNyk7XG4gICAgICAgICAgICBpZiAoc2V2ZW5CaXRWYWx1ZSA+PSA2NCAmJiBzZXZlbkJpdFZhbHVlIDwgOTApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERlY29kZWRDaGFyKHBvcyArIDcsICgnJyArIChzZXZlbkJpdFZhbHVlICsgMSkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZXZlbkJpdFZhbHVlID49IDkwICYmIHNldmVuQml0VmFsdWUgPCAxMTYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERlY29kZWRDaGFyKHBvcyArIDcsICgnJyArIChzZXZlbkJpdFZhbHVlICsgNykpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBlaWdodEJpdFZhbHVlID0gdGhpcy5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KHBvcywgOCk7XG4gICAgICAgICAgICBsZXQgYztcbiAgICAgICAgICAgIHN3aXRjaCAoZWlnaHRCaXRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMjMyOlxuICAgICAgICAgICAgICAgICAgICBjID0gJyEnO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDIzMzpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICdcIic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjM0OlxuICAgICAgICAgICAgICAgICAgICBjID0gJyUnO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDIzNTpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICcmJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyMzY6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnXFwnJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyMzc6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnKCc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjM4OlxuICAgICAgICAgICAgICAgICAgICBjID0gJyknO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDIzOTpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICcqJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyNDA6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnKyc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjQxOlxuICAgICAgICAgICAgICAgICAgICBjID0gJywnO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDI0MjpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICctJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyNDM6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnLic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjQ0OlxuICAgICAgICAgICAgICAgICAgICBjID0gJy8nO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDI0NTpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICc6JztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyNDY6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnOyc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjQ3OlxuICAgICAgICAgICAgICAgICAgICBjID0gJzwnO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDI0ODpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICc9JztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyNDk6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnPic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjUwOlxuICAgICAgICAgICAgICAgICAgICBjID0gJz8nO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDI1MTpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICdfJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyNTI6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnICc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgRGVjb2RlZENoYXIocG9zICsgOCwgYyk7XG4gICAgICAgIH1cbiAgICAgICAgaXNTdGlsbEFscGhhKHBvcykge1xuICAgICAgICAgICAgaWYgKHBvcyArIDUgPiB0aGlzLmluZm9ybWF0aW9uLmdldFNpemUoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFdlIG5vdyBjaGVjayBpZiBpdCdzIGEgdmFsaWQgNS1iaXQgdmFsdWUgKDAuLjkgYW5kIEZOQzEpXG4gICAgICAgICAgICBsZXQgZml2ZUJpdFZhbHVlID0gdGhpcy5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KHBvcywgNSk7XG4gICAgICAgICAgICBpZiAoZml2ZUJpdFZhbHVlID49IDUgJiYgZml2ZUJpdFZhbHVlIDwgMTYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChwb3MgKyA2ID4gdGhpcy5pbmZvcm1hdGlvbi5nZXRTaXplKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc2l4Qml0VmFsdWUgPSB0aGlzLmV4dHJhY3ROdW1lcmljVmFsdWVGcm9tQml0QXJyYXkocG9zLCA2KTtcbiAgICAgICAgICAgIHJldHVybiBzaXhCaXRWYWx1ZSA+PSAxNiAmJiBzaXhCaXRWYWx1ZSA8IDYzOyAvLyA2MyBub3QgaW5jbHVkZWRcbiAgICAgICAgfVxuICAgICAgICBkZWNvZGVBbHBoYW51bWVyaWMocG9zKSB7XG4gICAgICAgICAgICBsZXQgZml2ZUJpdFZhbHVlID0gdGhpcy5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KHBvcywgNSk7XG4gICAgICAgICAgICBpZiAoZml2ZUJpdFZhbHVlID09PSAxNSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRGVjb2RlZENoYXIocG9zICsgNSwgRGVjb2RlZENoYXIuRk5DMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZml2ZUJpdFZhbHVlID49IDUgJiYgZml2ZUJpdFZhbHVlIDwgMTUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERlY29kZWRDaGFyKHBvcyArIDUsICgnMCcgKyAoZml2ZUJpdFZhbHVlIC0gNSkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBzaXhCaXRWYWx1ZSA9IHRoaXMuZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShwb3MsIDYpO1xuICAgICAgICAgICAgaWYgKHNpeEJpdFZhbHVlID49IDMyICYmIHNpeEJpdFZhbHVlIDwgNTgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERlY29kZWRDaGFyKHBvcyArIDYsICgnJyArIChzaXhCaXRWYWx1ZSArIDMzKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGM7XG4gICAgICAgICAgICBzd2l0Y2ggKHNpeEJpdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSA1ODpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICcqJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA1OTpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICcsJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA2MDpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICctJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA2MTpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICcuJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA2MjpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICcvJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbignRGVjb2RpbmcgaW52YWxpZCBhbHBoYW51bWVyaWMgdmFsdWU6ICcgKyBzaXhCaXRWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IERlY29kZWRDaGFyKHBvcyArIDYsIGMpO1xuICAgICAgICB9XG4gICAgICAgIGlzQWxwaGFUbzY0NlRvQWxwaGFMYXRjaChwb3MpIHtcbiAgICAgICAgICAgIGlmIChwb3MgKyAxID4gdGhpcy5pbmZvcm1hdGlvbi5nZXRTaXplKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDUgJiYgaSArIHBvcyA8IHRoaXMuaW5mb3JtYXRpb24uZ2V0U2l6ZSgpOyArK2kpIHtcbiAgICAgICAgICAgICAgICBpZiAoaSA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaW5mb3JtYXRpb24uZ2V0KHBvcyArIDIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5pbmZvcm1hdGlvbi5nZXQocG9zICsgaSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlzQWxwaGFPcjY0NlRvTnVtZXJpY0xhdGNoKHBvcykge1xuICAgICAgICAgICAgLy8gTmV4dCBpcyBhbHBoYW51bWVyaWMgaWYgdGhlcmUgYXJlIDMgcG9zaXRpb25zIGFuZCB0aGV5IGFyZSBhbGwgemVyb3NcbiAgICAgICAgICAgIGlmIChwb3MgKyAzID4gdGhpcy5pbmZvcm1hdGlvbi5nZXRTaXplKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gcG9zOyBpIDwgcG9zICsgMzsgKytpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5mb3JtYXRpb24uZ2V0KGkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpc051bWVyaWNUb0FscGhhTnVtZXJpY0xhdGNoKHBvcykge1xuICAgICAgICAgICAgLy8gTmV4dCBpcyBhbHBoYW51bWVyaWMgaWYgdGhlcmUgYXJlIDQgcG9zaXRpb25zIGFuZCB0aGV5IGFyZSBhbGwgemVyb3MsIG9yXG4gICAgICAgICAgICAvLyBpZiB0aGVyZSBpcyBhIHN1YnNldCBvZiB0aGlzIGp1c3QgYmVmb3JlIHRoZSBlbmQgb2YgdGhlIHN5bWJvbFxuICAgICAgICAgICAgaWYgKHBvcyArIDEgPiB0aGlzLmluZm9ybWF0aW9uLmdldFNpemUoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNCAmJiBpICsgcG9zIDwgdGhpcy5pbmZvcm1hdGlvbi5nZXRTaXplKCk7ICsraSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmluZm9ybWF0aW9uLmdldChwb3MgKyBpKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjbGFzcyBBYnN0cmFjdEV4cGFuZGVkRGVjb2RlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGluZm9ybWF0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmluZm9ybWF0aW9uID0gaW5mb3JtYXRpb247XG4gICAgICAgICAgICB0aGlzLmdlbmVyYWxEZWNvZGVyID0gbmV3IEdlbmVyYWxBcHBJZERlY29kZXIoaW5mb3JtYXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIGdldEluZm9ybWF0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5mb3JtYXRpb247XG4gICAgICAgIH1cbiAgICAgICAgZ2V0R2VuZXJhbERlY29kZXIoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZW5lcmFsRGVjb2RlcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNsYXNzIEFJMDFkZWNvZGVyIGV4dGVuZHMgQWJzdHJhY3RFeHBhbmRlZERlY29kZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcihpbmZvcm1hdGlvbikge1xuICAgICAgICAgICAgc3VwZXIoaW5mb3JtYXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIGVuY29kZUNvbXByZXNzZWRHdGluKGJ1ZiwgY3VycmVudFBvcykge1xuICAgICAgICAgICAgYnVmLmFwcGVuZCgnKDAxKScpO1xuICAgICAgICAgICAgbGV0IGluaXRpYWxQb3NpdGlvbiA9IGJ1Zi5sZW5ndGgoKTtcbiAgICAgICAgICAgIGJ1Zi5hcHBlbmQoJzknKTtcbiAgICAgICAgICAgIHRoaXMuZW5jb2RlQ29tcHJlc3NlZEd0aW5XaXRob3V0QUkoYnVmLCBjdXJyZW50UG9zLCBpbml0aWFsUG9zaXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIGVuY29kZUNvbXByZXNzZWRHdGluV2l0aG91dEFJKGJ1ZiwgY3VycmVudFBvcywgaW5pdGlhbEJ1ZmZlclBvc2l0aW9uKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDQ7ICsraSkge1xuICAgICAgICAgICAgICAgIGxldCBjdXJyZW50QmxvY2sgPSB0aGlzLmdldEdlbmVyYWxEZWNvZGVyKCkuZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShjdXJyZW50UG9zICsgMTAgKiBpLCAxMCk7XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRCbG9jayAvIDEwMCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBidWYuYXBwZW5kKCcwJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50QmxvY2sgLyAxMCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBidWYuYXBwZW5kKCcwJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJ1Zi5hcHBlbmQoY3VycmVudEJsb2NrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIEFJMDFkZWNvZGVyLmFwcGVuZENoZWNrRGlnaXQoYnVmLCBpbml0aWFsQnVmZmVyUG9zaXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBhcHBlbmRDaGVja0RpZ2l0KGJ1ZiwgY3VycmVudFBvcykge1xuICAgICAgICAgICAgbGV0IGNoZWNrRGlnaXQgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAxMzsgaSsrKSB7XG4gICAgICAgICAgICAgICAgLy8gbGV0IGRpZ2l0ID0gYnVmLmNoYXJBdChpICsgY3VycmVudFBvcykgLSAnMCc7XG4gICAgICAgICAgICAgICAgLy8gVG8gYmUgY2hlY2tlZFxuICAgICAgICAgICAgICAgIGxldCBkaWdpdCA9IGJ1Zi5jaGFyQXQoaSArIGN1cnJlbnRQb3MpLmNoYXJDb2RlQXQoMCkgLSAnMCcuY2hhckNvZGVBdCgwKTtcbiAgICAgICAgICAgICAgICBjaGVja0RpZ2l0ICs9IChpICYgMHgwMSkgPT09IDAgPyAzICogZGlnaXQgOiBkaWdpdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNoZWNrRGlnaXQgPSAxMCAtIChjaGVja0RpZ2l0ICUgMTApO1xuICAgICAgICAgICAgaWYgKGNoZWNrRGlnaXQgPT09IDEwKSB7XG4gICAgICAgICAgICAgICAgY2hlY2tEaWdpdCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBidWYuYXBwZW5kKGNoZWNrRGlnaXQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIEFJMDFkZWNvZGVyLkdUSU5fU0laRSA9IDQwO1xuXG4gICAgY2xhc3MgQUkwMUFuZE90aGVyQUlzIGV4dGVuZHMgQUkwMWRlY29kZXIge1xuICAgICAgICAvLyB0aGUgc2Vjb25kIG9uZSBpcyB0aGUgZW5jb2RhdGlvbiBtZXRob2QsIGFuZCB0aGUgb3RoZXIgdHdvIGFyZSBmb3IgdGhlIHZhcmlhYmxlIGxlbmd0aFxuICAgICAgICBjb25zdHJ1Y3RvcihpbmZvcm1hdGlvbikge1xuICAgICAgICAgICAgc3VwZXIoaW5mb3JtYXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIHBhcnNlSW5mb3JtYXRpb24oKSB7XG4gICAgICAgICAgICBsZXQgYnVmZiA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICBidWZmLmFwcGVuZCgnKDAxKScpO1xuICAgICAgICAgICAgbGV0IGluaXRpYWxHdGluUG9zaXRpb24gPSBidWZmLmxlbmd0aCgpO1xuICAgICAgICAgICAgbGV0IGZpcnN0R3RpbkRpZ2l0ID0gdGhpcy5nZXRHZW5lcmFsRGVjb2RlcigpLmV4dHJhY3ROdW1lcmljVmFsdWVGcm9tQml0QXJyYXkoQUkwMUFuZE90aGVyQUlzLkhFQURFUl9TSVpFLCA0KTtcbiAgICAgICAgICAgIGJ1ZmYuYXBwZW5kKGZpcnN0R3RpbkRpZ2l0KTtcbiAgICAgICAgICAgIHRoaXMuZW5jb2RlQ29tcHJlc3NlZEd0aW5XaXRob3V0QUkoYnVmZiwgQUkwMUFuZE90aGVyQUlzLkhFQURFUl9TSVpFICsgNCwgaW5pdGlhbEd0aW5Qb3NpdGlvbik7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRHZW5lcmFsRGVjb2RlcigpLmRlY29kZUFsbENvZGVzKGJ1ZmYsIEFJMDFBbmRPdGhlckFJcy5IRUFERVJfU0laRSArIDQ0KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBBSTAxQW5kT3RoZXJBSXMuSEVBREVSX1NJWkUgPSAxICsgMSArIDI7IC8vIGZpcnN0IGJpdCBlbmNvZGVzIHRoZSBsaW5rYWdlIGZsYWcsXG5cbiAgICBjbGFzcyBBbnlBSURlY29kZXIgZXh0ZW5kcyBBYnN0cmFjdEV4cGFuZGVkRGVjb2RlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGluZm9ybWF0aW9uKSB7XG4gICAgICAgICAgICBzdXBlcihpbmZvcm1hdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgcGFyc2VJbmZvcm1hdGlvbigpIHtcbiAgICAgICAgICAgIGxldCBidWYgPSBuZXcgU3RyaW5nQnVpbGRlcigpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0R2VuZXJhbERlY29kZXIoKS5kZWNvZGVBbGxDb2RlcyhidWYsIEFueUFJRGVjb2Rlci5IRUFERVJfU0laRSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgQW55QUlEZWNvZGVyLkhFQURFUl9TSVpFID0gMiArIDEgKyAyO1xuXG4gICAgY2xhc3MgQUkwMXdlaWdodERlY29kZXIgZXh0ZW5kcyBBSTAxZGVjb2RlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGluZm9ybWF0aW9uKSB7XG4gICAgICAgICAgICBzdXBlcihpbmZvcm1hdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgZW5jb2RlQ29tcHJlc3NlZFdlaWdodChidWYsIGN1cnJlbnRQb3MsIHdlaWdodFNpemUpIHtcbiAgICAgICAgICAgIGxldCBvcmlnaW5hbFdlaWdodE51bWVyaWMgPSB0aGlzLmdldEdlbmVyYWxEZWNvZGVyKCkuZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShjdXJyZW50UG9zLCB3ZWlnaHRTaXplKTtcbiAgICAgICAgICAgIHRoaXMuYWRkV2VpZ2h0Q29kZShidWYsIG9yaWdpbmFsV2VpZ2h0TnVtZXJpYyk7XG4gICAgICAgICAgICBsZXQgd2VpZ2h0TnVtZXJpYyA9IHRoaXMuY2hlY2tXZWlnaHQob3JpZ2luYWxXZWlnaHROdW1lcmljKTtcbiAgICAgICAgICAgIGxldCBjdXJyZW50RGl2aXNvciA9IDEwMDAwMDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNTsgKytpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHdlaWdodE51bWVyaWMgLyBjdXJyZW50RGl2aXNvciA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBidWYuYXBwZW5kKCcwJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGN1cnJlbnREaXZpc29yIC89IDEwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnVmLmFwcGVuZCh3ZWlnaHROdW1lcmljKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNsYXNzIEFJMDEzeDB4RGVjb2RlciBleHRlbmRzIEFJMDF3ZWlnaHREZWNvZGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IoaW5mb3JtYXRpb24pIHtcbiAgICAgICAgICAgIHN1cGVyKGluZm9ybWF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBwYXJzZUluZm9ybWF0aW9uKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZ2V0SW5mb3JtYXRpb24oKS5nZXRTaXplKCkgIT0gQUkwMTN4MHhEZWNvZGVyLkhFQURFUl9TSVpFICsgQUkwMXdlaWdodERlY29kZXIuR1RJTl9TSVpFICsgQUkwMTN4MHhEZWNvZGVyLldFSUdIVF9TSVpFKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgYnVmID0gbmV3IFN0cmluZ0J1aWxkZXIoKTtcbiAgICAgICAgICAgIHRoaXMuZW5jb2RlQ29tcHJlc3NlZEd0aW4oYnVmLCBBSTAxM3gweERlY29kZXIuSEVBREVSX1NJWkUpO1xuICAgICAgICAgICAgdGhpcy5lbmNvZGVDb21wcmVzc2VkV2VpZ2h0KGJ1ZiwgQUkwMTN4MHhEZWNvZGVyLkhFQURFUl9TSVpFICsgQUkwMXdlaWdodERlY29kZXIuR1RJTl9TSVpFLCBBSTAxM3gweERlY29kZXIuV0VJR0hUX1NJWkUpO1xuICAgICAgICAgICAgcmV0dXJuIGJ1Zi50b1N0cmluZygpO1xuICAgICAgICB9XG4gICAgfVxuICAgIEFJMDEzeDB4RGVjb2Rlci5IRUFERVJfU0laRSA9IDQgKyAxO1xuICAgIEFJMDEzeDB4RGVjb2Rlci5XRUlHSFRfU0laRSA9IDE1O1xuXG4gICAgY2xhc3MgQUkwMTMxMDNkZWNvZGVyIGV4dGVuZHMgQUkwMTN4MHhEZWNvZGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IoaW5mb3JtYXRpb24pIHtcbiAgICAgICAgICAgIHN1cGVyKGluZm9ybWF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBhZGRXZWlnaHRDb2RlKGJ1Ziwgd2VpZ2h0KSB7XG4gICAgICAgICAgICBidWYuYXBwZW5kKCcoMzEwMyknKTtcbiAgICAgICAgfVxuICAgICAgICBjaGVja1dlaWdodCh3ZWlnaHQpIHtcbiAgICAgICAgICAgIHJldHVybiB3ZWlnaHQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjbGFzcyBBSTAxMzIweERlY29kZXIgZXh0ZW5kcyBBSTAxM3gweERlY29kZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcihpbmZvcm1hdGlvbikge1xuICAgICAgICAgICAgc3VwZXIoaW5mb3JtYXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIGFkZFdlaWdodENvZGUoYnVmLCB3ZWlnaHQpIHtcbiAgICAgICAgICAgIGlmICh3ZWlnaHQgPCAxMDAwMCkge1xuICAgICAgICAgICAgICAgIGJ1Zi5hcHBlbmQoJygzMjAyKScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgYnVmLmFwcGVuZCgnKDMyMDMpJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY2hlY2tXZWlnaHQod2VpZ2h0KSB7XG4gICAgICAgICAgICBpZiAod2VpZ2h0IDwgMTAwMDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gd2VpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHdlaWdodCAtIDEwMDAwO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xhc3MgQUkwMTM5MnhEZWNvZGVyIGV4dGVuZHMgQUkwMWRlY29kZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcihpbmZvcm1hdGlvbikge1xuICAgICAgICAgICAgc3VwZXIoaW5mb3JtYXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIHBhcnNlSW5mb3JtYXRpb24oKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5nZXRJbmZvcm1hdGlvbigpLmdldFNpemUoKSA8IEFJMDEzOTJ4RGVjb2Rlci5IRUFERVJfU0laRSArIEFJMDFkZWNvZGVyLkdUSU5fU0laRSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGJ1ZiA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICB0aGlzLmVuY29kZUNvbXByZXNzZWRHdGluKGJ1ZiwgQUkwMTM5MnhEZWNvZGVyLkhFQURFUl9TSVpFKTtcbiAgICAgICAgICAgIGxldCBsYXN0QUlkaWdpdCA9IHRoaXMuZ2V0R2VuZXJhbERlY29kZXIoKS5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KEFJMDEzOTJ4RGVjb2Rlci5IRUFERVJfU0laRSArIEFJMDFkZWNvZGVyLkdUSU5fU0laRSwgQUkwMTM5MnhEZWNvZGVyLkxBU1RfRElHSVRfU0laRSk7XG4gICAgICAgICAgICBidWYuYXBwZW5kKCcoMzkyJyk7XG4gICAgICAgICAgICBidWYuYXBwZW5kKGxhc3RBSWRpZ2l0KTtcbiAgICAgICAgICAgIGJ1Zi5hcHBlbmQoJyknKTtcbiAgICAgICAgICAgIGxldCBkZWNvZGVkSW5mb3JtYXRpb24gPSB0aGlzLmdldEdlbmVyYWxEZWNvZGVyKCkuZGVjb2RlR2VuZXJhbFB1cnBvc2VGaWVsZChBSTAxMzkyeERlY29kZXIuSEVBREVSX1NJWkUgKyBBSTAxZGVjb2Rlci5HVElOX1NJWkUgKyBBSTAxMzkyeERlY29kZXIuTEFTVF9ESUdJVF9TSVpFLCBudWxsKTtcbiAgICAgICAgICAgIGJ1Zi5hcHBlbmQoZGVjb2RlZEluZm9ybWF0aW9uLmdldE5ld1N0cmluZygpKTtcbiAgICAgICAgICAgIHJldHVybiBidWYudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBBSTAxMzkyeERlY29kZXIuSEVBREVSX1NJWkUgPSA1ICsgMSArIDI7XG4gICAgQUkwMTM5MnhEZWNvZGVyLkxBU1RfRElHSVRfU0laRSA9IDI7XG5cbiAgICBjbGFzcyBBSTAxMzkzeERlY29kZXIgZXh0ZW5kcyBBSTAxZGVjb2RlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGluZm9ybWF0aW9uKSB7XG4gICAgICAgICAgICBzdXBlcihpbmZvcm1hdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgcGFyc2VJbmZvcm1hdGlvbigpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmdldEluZm9ybWF0aW9uKCkuZ2V0U2l6ZSgpIDwgQUkwMTM5M3hEZWNvZGVyLkhFQURFUl9TSVpFICsgQUkwMWRlY29kZXIuR1RJTl9TSVpFKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgYnVmID0gbmV3IFN0cmluZ0J1aWxkZXIoKTtcbiAgICAgICAgICAgIHRoaXMuZW5jb2RlQ29tcHJlc3NlZEd0aW4oYnVmLCBBSTAxMzkzeERlY29kZXIuSEVBREVSX1NJWkUpO1xuICAgICAgICAgICAgbGV0IGxhc3RBSWRpZ2l0ID0gdGhpcy5nZXRHZW5lcmFsRGVjb2RlcigpLmV4dHJhY3ROdW1lcmljVmFsdWVGcm9tQml0QXJyYXkoQUkwMTM5M3hEZWNvZGVyLkhFQURFUl9TSVpFICsgQUkwMWRlY29kZXIuR1RJTl9TSVpFLCBBSTAxMzkzeERlY29kZXIuTEFTVF9ESUdJVF9TSVpFKTtcbiAgICAgICAgICAgIGJ1Zi5hcHBlbmQoJygzOTMnKTtcbiAgICAgICAgICAgIGJ1Zi5hcHBlbmQobGFzdEFJZGlnaXQpO1xuICAgICAgICAgICAgYnVmLmFwcGVuZCgnKScpO1xuICAgICAgICAgICAgbGV0IGZpcnN0VGhyZWVEaWdpdHMgPSB0aGlzLmdldEdlbmVyYWxEZWNvZGVyKCkuZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShBSTAxMzkzeERlY29kZXIuSEVBREVSX1NJWkUgKyBBSTAxZGVjb2Rlci5HVElOX1NJWkUgKyBBSTAxMzkzeERlY29kZXIuTEFTVF9ESUdJVF9TSVpFLCBBSTAxMzkzeERlY29kZXIuRklSU1RfVEhSRUVfRElHSVRTX1NJWkUpO1xuICAgICAgICAgICAgaWYgKGZpcnN0VGhyZWVEaWdpdHMgLyAxMDAgPT0gMCkge1xuICAgICAgICAgICAgICAgIGJ1Zi5hcHBlbmQoJzAnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmaXJzdFRocmVlRGlnaXRzIC8gMTAgPT0gMCkge1xuICAgICAgICAgICAgICAgIGJ1Zi5hcHBlbmQoJzAnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJ1Zi5hcHBlbmQoZmlyc3RUaHJlZURpZ2l0cyk7XG4gICAgICAgICAgICBsZXQgZ2VuZXJhbEluZm9ybWF0aW9uID0gdGhpcy5nZXRHZW5lcmFsRGVjb2RlcigpLmRlY29kZUdlbmVyYWxQdXJwb3NlRmllbGQoQUkwMTM5M3hEZWNvZGVyLkhFQURFUl9TSVpFICsgQUkwMWRlY29kZXIuR1RJTl9TSVpFICsgQUkwMTM5M3hEZWNvZGVyLkxBU1RfRElHSVRfU0laRSArIEFJMDEzOTN4RGVjb2Rlci5GSVJTVF9USFJFRV9ESUdJVFNfU0laRSwgbnVsbCk7XG4gICAgICAgICAgICBidWYuYXBwZW5kKGdlbmVyYWxJbmZvcm1hdGlvbi5nZXROZXdTdHJpbmcoKSk7XG4gICAgICAgICAgICByZXR1cm4gYnVmLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgQUkwMTM5M3hEZWNvZGVyLkhFQURFUl9TSVpFID0gNSArIDEgKyAyO1xuICAgIEFJMDEzOTN4RGVjb2Rlci5MQVNUX0RJR0lUX1NJWkUgPSAyO1xuICAgIEFJMDEzOTN4RGVjb2Rlci5GSVJTVF9USFJFRV9ESUdJVFNfU0laRSA9IDEwO1xuXG4gICAgY2xhc3MgQUkwMTN4MHgxeERlY29kZXIgZXh0ZW5kcyBBSTAxd2VpZ2h0RGVjb2RlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGluZm9ybWF0aW9uLCBmaXJzdEFJZGlnaXRzLCBkYXRlQ29kZSkge1xuICAgICAgICAgICAgc3VwZXIoaW5mb3JtYXRpb24pO1xuICAgICAgICAgICAgdGhpcy5kYXRlQ29kZSA9IGRhdGVDb2RlO1xuICAgICAgICAgICAgdGhpcy5maXJzdEFJZGlnaXRzID0gZmlyc3RBSWRpZ2l0cztcbiAgICAgICAgfVxuICAgICAgICBwYXJzZUluZm9ybWF0aW9uKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZ2V0SW5mb3JtYXRpb24oKS5nZXRTaXplKCkgIT0gQUkwMTN4MHgxeERlY29kZXIuSEVBREVSX1NJWkUgKyBBSTAxM3gweDF4RGVjb2Rlci5HVElOX1NJWkUgKyBBSTAxM3gweDF4RGVjb2Rlci5XRUlHSFRfU0laRSArIEFJMDEzeDB4MXhEZWNvZGVyLkRBVEVfU0laRSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGJ1ZiA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICB0aGlzLmVuY29kZUNvbXByZXNzZWRHdGluKGJ1ZiwgQUkwMTN4MHgxeERlY29kZXIuSEVBREVSX1NJWkUpO1xuICAgICAgICAgICAgdGhpcy5lbmNvZGVDb21wcmVzc2VkV2VpZ2h0KGJ1ZiwgQUkwMTN4MHgxeERlY29kZXIuSEVBREVSX1NJWkUgKyBBSTAxM3gweDF4RGVjb2Rlci5HVElOX1NJWkUsIEFJMDEzeDB4MXhEZWNvZGVyLldFSUdIVF9TSVpFKTtcbiAgICAgICAgICAgIHRoaXMuZW5jb2RlQ29tcHJlc3NlZERhdGUoYnVmLCBBSTAxM3gweDF4RGVjb2Rlci5IRUFERVJfU0laRSArIEFJMDEzeDB4MXhEZWNvZGVyLkdUSU5fU0laRSArIEFJMDEzeDB4MXhEZWNvZGVyLldFSUdIVF9TSVpFKTtcbiAgICAgICAgICAgIHJldHVybiBidWYudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgICAgICBlbmNvZGVDb21wcmVzc2VkRGF0ZShidWYsIGN1cnJlbnRQb3MpIHtcbiAgICAgICAgICAgIGxldCBudW1lcmljRGF0ZSA9IHRoaXMuZ2V0R2VuZXJhbERlY29kZXIoKS5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KGN1cnJlbnRQb3MsIEFJMDEzeDB4MXhEZWNvZGVyLkRBVEVfU0laRSk7XG4gICAgICAgICAgICBpZiAobnVtZXJpY0RhdGUgPT0gMzg0MDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBidWYuYXBwZW5kKCcoJyk7XG4gICAgICAgICAgICBidWYuYXBwZW5kKHRoaXMuZGF0ZUNvZGUpO1xuICAgICAgICAgICAgYnVmLmFwcGVuZCgnKScpO1xuICAgICAgICAgICAgbGV0IGRheSA9IG51bWVyaWNEYXRlICUgMzI7XG4gICAgICAgICAgICBudW1lcmljRGF0ZSAvPSAzMjtcbiAgICAgICAgICAgIGxldCBtb250aCA9IG51bWVyaWNEYXRlICUgMTIgKyAxO1xuICAgICAgICAgICAgbnVtZXJpY0RhdGUgLz0gMTI7XG4gICAgICAgICAgICBsZXQgeWVhciA9IG51bWVyaWNEYXRlO1xuICAgICAgICAgICAgaWYgKHllYXIgLyAxMCA9PSAwKSB7XG4gICAgICAgICAgICAgICAgYnVmLmFwcGVuZCgnMCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnVmLmFwcGVuZCh5ZWFyKTtcbiAgICAgICAgICAgIGlmIChtb250aCAvIDEwID09IDApIHtcbiAgICAgICAgICAgICAgICBidWYuYXBwZW5kKCcwJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBidWYuYXBwZW5kKG1vbnRoKTtcbiAgICAgICAgICAgIGlmIChkYXkgLyAxMCA9PSAwKSB7XG4gICAgICAgICAgICAgICAgYnVmLmFwcGVuZCgnMCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnVmLmFwcGVuZChkYXkpO1xuICAgICAgICB9XG4gICAgICAgIGFkZFdlaWdodENvZGUoYnVmLCB3ZWlnaHQpIHtcbiAgICAgICAgICAgIGJ1Zi5hcHBlbmQoJygnKTtcbiAgICAgICAgICAgIGJ1Zi5hcHBlbmQodGhpcy5maXJzdEFJZGlnaXRzKTtcbiAgICAgICAgICAgIGJ1Zi5hcHBlbmQod2VpZ2h0IC8gMTAwMDAwKTtcbiAgICAgICAgICAgIGJ1Zi5hcHBlbmQoJyknKTtcbiAgICAgICAgfVxuICAgICAgICBjaGVja1dlaWdodCh3ZWlnaHQpIHtcbiAgICAgICAgICAgIHJldHVybiB3ZWlnaHQgJSAxMDAwMDA7XG4gICAgICAgIH1cbiAgICB9XG4gICAgQUkwMTN4MHgxeERlY29kZXIuSEVBREVSX1NJWkUgPSA3ICsgMTtcbiAgICBBSTAxM3gweDF4RGVjb2Rlci5XRUlHSFRfU0laRSA9IDIwO1xuICAgIEFJMDEzeDB4MXhEZWNvZGVyLkRBVEVfU0laRSA9IDE2O1xuXG4gICAgZnVuY3Rpb24gY3JlYXRlRGVjb2RlcihpbmZvcm1hdGlvbikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKGluZm9ybWF0aW9uLmdldCgxKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQUkwMUFuZE90aGVyQUlzKGluZm9ybWF0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghaW5mb3JtYXRpb24uZ2V0KDIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBBbnlBSURlY29kZXIoaW5mb3JtYXRpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGZvdXJCaXRFbmNvZGF0aW9uTWV0aG9kID0gR2VuZXJhbEFwcElkRGVjb2Rlci5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KGluZm9ybWF0aW9uLCAxLCA0KTtcbiAgICAgICAgICAgIHN3aXRjaCAoZm91ckJpdEVuY29kYXRpb25NZXRob2QpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IHJldHVybiBuZXcgQUkwMTMxMDNkZWNvZGVyKGluZm9ybWF0aW9uKTtcbiAgICAgICAgICAgICAgICBjYXNlIDU6IHJldHVybiBuZXcgQUkwMTMyMHhEZWNvZGVyKGluZm9ybWF0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBmaXZlQml0RW5jb2RhdGlvbk1ldGhvZCA9IEdlbmVyYWxBcHBJZERlY29kZXIuZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShpbmZvcm1hdGlvbiwgMSwgNSk7XG4gICAgICAgICAgICBzd2l0Y2ggKGZpdmVCaXRFbmNvZGF0aW9uTWV0aG9kKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAxMjogcmV0dXJuIG5ldyBBSTAxMzkyeERlY29kZXIoaW5mb3JtYXRpb24pO1xuICAgICAgICAgICAgICAgIGNhc2UgMTM6IHJldHVybiBuZXcgQUkwMTM5M3hEZWNvZGVyKGluZm9ybWF0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBzZXZlbkJpdEVuY29kYXRpb25NZXRob2QgPSBHZW5lcmFsQXBwSWREZWNvZGVyLmV4dHJhY3ROdW1lcmljVmFsdWVGcm9tQml0QXJyYXkoaW5mb3JtYXRpb24sIDEsIDcpO1xuICAgICAgICAgICAgc3dpdGNoIChzZXZlbkJpdEVuY29kYXRpb25NZXRob2QpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDU2OiByZXR1cm4gbmV3IEFJMDEzeDB4MXhEZWNvZGVyKGluZm9ybWF0aW9uLCAnMzEwJywgJzExJyk7XG4gICAgICAgICAgICAgICAgY2FzZSA1NzogcmV0dXJuIG5ldyBBSTAxM3gweDF4RGVjb2RlcihpbmZvcm1hdGlvbiwgJzMyMCcsICcxMScpO1xuICAgICAgICAgICAgICAgIGNhc2UgNTg6IHJldHVybiBuZXcgQUkwMTN4MHgxeERlY29kZXIoaW5mb3JtYXRpb24sICczMTAnLCAnMTMnKTtcbiAgICAgICAgICAgICAgICBjYXNlIDU5OiByZXR1cm4gbmV3IEFJMDEzeDB4MXhEZWNvZGVyKGluZm9ybWF0aW9uLCAnMzIwJywgJzEzJyk7XG4gICAgICAgICAgICAgICAgY2FzZSA2MDogcmV0dXJuIG5ldyBBSTAxM3gweDF4RGVjb2RlcihpbmZvcm1hdGlvbiwgJzMxMCcsICcxNScpO1xuICAgICAgICAgICAgICAgIGNhc2UgNjE6IHJldHVybiBuZXcgQUkwMTN4MHgxeERlY29kZXIoaW5mb3JtYXRpb24sICczMjAnLCAnMTUnKTtcbiAgICAgICAgICAgICAgICBjYXNlIDYyOiByZXR1cm4gbmV3IEFJMDEzeDB4MXhEZWNvZGVyKGluZm9ybWF0aW9uLCAnMzEwJywgJzE3Jyk7XG4gICAgICAgICAgICAgICAgY2FzZSA2MzogcmV0dXJuIG5ldyBBSTAxM3gweDF4RGVjb2RlcihpbmZvcm1hdGlvbiwgJzMyMCcsICcxNycpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhlKTtcbiAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oJ3Vua25vd24gZGVjb2RlcjogJyArIGluZm9ybWF0aW9uKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNsYXNzIEV4cGFuZGVkUGFpciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGxlZnRDaGFyLCByaWdodENoYXIsIGZpbmRlclBhdHRlciwgbWF5QmVMYXN0KSB7XG4gICAgICAgICAgICB0aGlzLmxlZnRjaGFyID0gbGVmdENoYXI7XG4gICAgICAgICAgICB0aGlzLnJpZ2h0Y2hhciA9IHJpZ2h0Q2hhcjtcbiAgICAgICAgICAgIHRoaXMuZmluZGVycGF0dGVybiA9IGZpbmRlclBhdHRlcjtcbiAgICAgICAgICAgIHRoaXMubWF5YmVMYXN0ID0gbWF5QmVMYXN0O1xuICAgICAgICB9XG4gICAgICAgIG1heUJlTGFzdCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1heWJlTGFzdDtcbiAgICAgICAgfVxuICAgICAgICBnZXRMZWZ0Q2hhcigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxlZnRjaGFyO1xuICAgICAgICB9XG4gICAgICAgIGdldFJpZ2h0Q2hhcigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJpZ2h0Y2hhcjtcbiAgICAgICAgfVxuICAgICAgICBnZXRGaW5kZXJQYXR0ZXJuKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmluZGVycGF0dGVybjtcbiAgICAgICAgfVxuICAgICAgICBtdXN0QmVMYXN0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucmlnaHRjaGFyID09IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1sgJyArIHRoaXMubGVmdGNoYXIgKyAnLCAnICsgdGhpcy5yaWdodGNoYXIgKyAnIDogJyArICh0aGlzLmZpbmRlcnBhdHRlcm4gPT0gbnVsbCA/ICdudWxsJyA6IHRoaXMuZmluZGVycGF0dGVybi5nZXRWYWx1ZSgpKSArICcgXSc7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGVxdWFscyhvMSwgbzIpIHtcbiAgICAgICAgICAgIGlmICghKG8xIGluc3RhbmNlb2YgRXhwYW5kZWRQYWlyKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBFeHBhbmRlZFBhaXIuZXF1YWxzT3JOdWxsKG8xLmxlZnRjaGFyLCBvMi5sZWZ0Y2hhcikgJiZcbiAgICAgICAgICAgICAgICBFeHBhbmRlZFBhaXIuZXF1YWxzT3JOdWxsKG8xLnJpZ2h0Y2hhciwgbzIucmlnaHRjaGFyKSAmJlxuICAgICAgICAgICAgICAgIEV4cGFuZGVkUGFpci5lcXVhbHNPck51bGwobzEuZmluZGVycGF0dGVybiwgbzIuZmluZGVycGF0dGVybik7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGVxdWFsc09yTnVsbChvMSwgbzIpIHtcbiAgICAgICAgICAgIHJldHVybiBvMSA9PT0gbnVsbCA/IG8yID09PSBudWxsIDogRXhwYW5kZWRQYWlyLmVxdWFscyhvMSwgbzIpO1xuICAgICAgICB9XG4gICAgICAgIGhhc2hDb2RlKCkge1xuICAgICAgICAgICAgLy8gcmV0dXJuIEV4cGFuZGVkUGFpci5oYXNoTm90TnVsbChsZWZ0Q2hhcikgXiBoYXNoTm90TnVsbChyaWdodENoYXIpIF4gaGFzaE5vdE51bGwoZmluZGVyUGF0dGVybik7XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSB0aGlzLmxlZnRjaGFyLmdldFZhbHVlKCkgXiB0aGlzLnJpZ2h0Y2hhci5nZXRWYWx1ZSgpIF4gdGhpcy5maW5kZXJwYXR0ZXJuLmdldFZhbHVlKCk7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjbGFzcyBFeHBhbmRlZFJvdyB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHBhaXJzLCByb3dOdW1iZXIsIHdhc1JldmVyc2VkKSB7XG4gICAgICAgICAgICB0aGlzLnBhaXJzID0gcGFpcnM7XG4gICAgICAgICAgICB0aGlzLnJvd051bWJlciA9IHJvd051bWJlcjtcbiAgICAgICAgICAgIHRoaXMud2FzUmV2ZXJzZWQgPSB3YXNSZXZlcnNlZDtcbiAgICAgICAgfVxuICAgICAgICBnZXRQYWlycygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhaXJzO1xuICAgICAgICB9XG4gICAgICAgIGdldFJvd051bWJlcigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJvd051bWJlcjtcbiAgICAgICAgfVxuICAgICAgICBpc1JldmVyc2VkKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2FzUmV2ZXJzZWQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gY2hlY2sgaW1wbGVtZW50YXRpb25cbiAgICAgICAgaXNFcXVpdmFsZW50KG90aGVyUGFpcnMpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNoZWNrRXF1YWxpdGl0eSh0aGlzLCBvdGhlclBhaXJzKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBAT3ZlcnJpZGVcbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ3sgJyArIHRoaXMucGFpcnMgKyAnIH0nO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUd28gcm93cyBhcmUgZXF1YWwgaWYgdGhleSBjb250YWluIHRoZSBzYW1lIHBhaXJzIGluIHRoZSBzYW1lIG9yZGVyLlxuICAgICAgICAgKi9cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIC8vIGNoZWNrIGltcGxlbWVudGF0aW9uXG4gICAgICAgIGVxdWFscyhvMSwgbzIpIHtcbiAgICAgICAgICAgIGlmICghKG8xIGluc3RhbmNlb2YgRXhwYW5kZWRSb3cpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2hlY2tFcXVhbGl0aXR5KG8xLCBvMikgJiYgbzEud2FzUmV2ZXJzZWQgPT09IG8yLndhc1JldmVyc2VkO1xuICAgICAgICB9XG4gICAgICAgIGNoZWNrRXF1YWxpdGl0eShwYWlyMSwgcGFpcjIpIHtcbiAgICAgICAgICAgIGlmICghcGFpcjEgfHwgIXBhaXIyKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgICAgICBwYWlyMS5mb3JFYWNoKChlMSwgaSkgPT4ge1xuICAgICAgICAgICAgICAgIHBhaXIyLmZvckVhY2goZTIgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZTEuZ2V0TGVmdENoYXIoKS5nZXRWYWx1ZSgpID09PSBlMi5nZXRMZWZ0Q2hhcigpLmdldFZhbHVlKCkgJiYgZTEuZ2V0UmlnaHRDaGFyKCkuZ2V0VmFsdWUoKSA9PT0gZTIuZ2V0UmlnaHRDaGFyKCkuZ2V0VmFsdWUoKSAmJiBlMS5nZXRGaW5kZXJQYXR0ZXIoKS5nZXRWYWx1ZSgpID09PSBlMi5nZXRGaW5kZXJQYXR0ZXIoKS5nZXRWYWx1ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLkFycmF5TGlzdDtcbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLkl0ZXJhdG9yO1xuICAgIC8vIGltcG9ydCBqYXZhLnV0aWwuTGlzdDtcbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLk1hcDtcbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLkNvbGxlY3Rpb25zO1xuICAgIGNsYXNzIFJTU0V4cGFuZGVkUmVhZGVyIGV4dGVuZHMgQWJzdHJhY3RSU1NSZWFkZXIge1xuICAgICAgICBjb25zdHJ1Y3Rvcih2ZXJib3NlKSB7XG4gICAgICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICAgICAgdGhpcy5wYWlycyA9IG5ldyBBcnJheShSU1NFeHBhbmRlZFJlYWRlci5NQVhfUEFJUlMpO1xuICAgICAgICAgICAgdGhpcy5yb3dzID0gbmV3IEFycmF5KCk7XG4gICAgICAgICAgICB0aGlzLnN0YXJ0RW5kID0gWzJdO1xuICAgICAgICAgICAgdGhpcy52ZXJib3NlID0gKHZlcmJvc2UgPT09IHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIGRlY29kZVJvdyhyb3dOdW1iZXIsIHJvdywgaGludHMpIHtcbiAgICAgICAgICAgIC8vIFJvd3MgY2FuIHN0YXJ0IHdpdGggZXZlbiBwYXR0ZXJuIGluIGNhc2UgaW4gcHJldiByb3dzIHRoZXJlIHdoZXJlIG9kZCBudW1iZXIgb2YgcGF0dGVycy5cbiAgICAgICAgICAgIC8vIFNvIGxldHMgdHJ5IHR3aWNlXG4gICAgICAgICAgICAvLyB0aGlzLnBhaXJzLmNsZWFyKCk7XG4gICAgICAgICAgICB0aGlzLnBhaXJzLmxlbmd0aCA9IDA7XG4gICAgICAgICAgICB0aGlzLnN0YXJ0RnJvbUV2ZW4gPSBmYWxzZTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFJTU0V4cGFuZGVkUmVhZGVyLmNvbnN0cnVjdFJlc3VsdCh0aGlzLmRlY29kZVJvdzJwYWlycyhyb3dOdW1iZXIsIHJvdykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAvLyBPS1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnZlcmJvc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5wYWlycy5sZW5ndGggPSAwO1xuICAgICAgICAgICAgdGhpcy5zdGFydEZyb21FdmVuID0gdHJ1ZTtcbiAgICAgICAgICAgIHJldHVybiBSU1NFeHBhbmRlZFJlYWRlci5jb25zdHJ1Y3RSZXN1bHQodGhpcy5kZWNvZGVSb3cycGFpcnMocm93TnVtYmVyLCByb3cpKTtcbiAgICAgICAgfVxuICAgICAgICByZXNldCgpIHtcbiAgICAgICAgICAgIHRoaXMucGFpcnMubGVuZ3RoID0gMDtcbiAgICAgICAgICAgIHRoaXMucm93cy5sZW5ndGggPSAwO1xuICAgICAgICB9XG4gICAgICAgIC8vIE5vdCBwcml2YXRlIGZvciB0ZXN0aW5nXG4gICAgICAgIGRlY29kZVJvdzJwYWlycyhyb3dOdW1iZXIsIHJvdykge1xuICAgICAgICAgICAgbGV0IGRvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgIHdoaWxlICghZG9uZSkge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGFpcnMucHVzaCh0aGlzLnJldHJpZXZlTmV4dFBhaXIocm93LCB0aGlzLnBhaXJzLCByb3dOdW1iZXIpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIE5vdEZvdW5kRXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMucGFpcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBleGl0IHRoaXMgbG9vcCB3aGVuIHJldHJpZXZlTmV4dFBhaXIoKSBmYWlscyBhbmQgdGhyb3dzXG4gICAgICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFRPRE86IHZlcmlmeSBzZXF1ZW5jZSBvZiBmaW5kZXIgcGF0dGVybnMgYXMgaW4gY2hlY2tQYWlyU2VxdWVuY2UoKVxuICAgICAgICAgICAgaWYgKHRoaXMuY2hlY2tDaGVja3N1bSgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFpcnM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgdHJ5U3RhY2tlZERlY29kZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJvd3MubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdHJ5U3RhY2tlZERlY29kZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0cnlTdGFja2VkRGVjb2RlID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBsZXQgdHJ5U3RhY2tlZERlY29kZSA9ICF0aGlzLnJvd3MuaXNFbXB0eSgpO1xuICAgICAgICAgICAgdGhpcy5zdG9yZVJvdyhyb3dOdW1iZXIsIGZhbHNlKTsgLy8gVE9ETzogZGVhbCB3aXRoIHJldmVyc2VkIHJvd3NcbiAgICAgICAgICAgIGlmICh0cnlTdGFja2VkRGVjb2RlKSB7XG4gICAgICAgICAgICAgICAgLy8gV2hlbiB0aGUgaW1hZ2UgaXMgMTgwLXJvdGF0ZWQsIHRoZW4gcm93cyBhcmUgc29ydGVkIGluIHdyb25nIGRpcmVjdGlvbi5cbiAgICAgICAgICAgICAgICAvLyBUcnkgdHdpY2Ugd2l0aCBib3RoIHRoZSBkaXJlY3Rpb25zLlxuICAgICAgICAgICAgICAgIGxldCBwcyA9IHRoaXMuY2hlY2tSb3dzQm9vbGVhbihmYWxzZSk7XG4gICAgICAgICAgICAgICAgaWYgKHBzICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwcyA9IHRoaXMuY2hlY2tSb3dzQm9vbGVhbih0cnVlKTtcbiAgICAgICAgICAgICAgICBpZiAocHMgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTmVlZCB0byBWZXJpZnlcbiAgICAgICAgY2hlY2tSb3dzQm9vbGVhbihyZXZlcnNlKSB7XG4gICAgICAgICAgICAvLyBMaW1pdCBudW1iZXIgb2Ygcm93cyB3ZSBhcmUgY2hlY2tpbmdcbiAgICAgICAgICAgIC8vIFdlIHVzZSByZWN1cnNpdmUgYWxnb3JpdGhtIHdpdGggcHVyZSBjb21wbGV4aXR5IGFuZCBkb24ndCB3YW50IGl0IHRvIHRha2UgZm9yZXZlclxuICAgICAgICAgICAgLy8gU3RhY2tlZCBiYXJjb2RlIGNhbiBoYXZlIHVwIHRvIDExIHJvd3MsIHNvIDI1IHNlZW1zIHJlYXNvbmFibGUgZW5vdWdoXG4gICAgICAgICAgICBpZiAodGhpcy5yb3dzLmxlbmd0aCA+IDI1KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yb3dzLmxlbmd0aCA9IDA7IC8vIFdlIHdpbGwgbmV2ZXIgaGF2ZSBhIGNoYW5jZSB0byBnZXQgcmVzdWx0LCBzbyBjbGVhciBpdFxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5wYWlycy5sZW5ndGggPSAwO1xuICAgICAgICAgICAgaWYgKHJldmVyc2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJvd3MgPSB0aGlzLnJvd3MucmV2ZXJzZSgpO1xuICAgICAgICAgICAgICAgIC8vIENvbGxlY3Rpb25zLnJldmVyc2UodGhpcy5yb3dzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBwcyA9IG51bGw7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHBzID0gdGhpcy5jaGVja1Jvd3MobmV3IEFycmF5KCksIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAvLyBPS1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnZlcmJvc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJldmVyc2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJvd3MgPSB0aGlzLnJvd3MucmV2ZXJzZSgpO1xuICAgICAgICAgICAgICAgIC8vIENvbGxlY3Rpb25zLnJldmVyc2UodGhpcy5yb3dzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBwcztcbiAgICAgICAgfVxuICAgICAgICAvLyBUcnkgdG8gY29uc3RydWN0IGEgdmFsaWQgcm93cyBzZXF1ZW5jZVxuICAgICAgICAvLyBSZWN1cnNpb24gaXMgdXNlZCB0byBpbXBsZW1lbnQgYmFja3RyYWNraW5nXG4gICAgICAgIGNoZWNrUm93cyhjb2xsZWN0ZWRSb3dzLCBjdXJyZW50Um93KSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gY3VycmVudFJvdzsgaSA8IHRoaXMucm93cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCByb3cgPSB0aGlzLnJvd3NbaV07XG4gICAgICAgICAgICAgICAgdGhpcy5wYWlycy5sZW5ndGggPSAwO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGNvbGxlY3RlZFJvdyBvZiBjb2xsZWN0ZWRSb3dzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGFpcnMucHVzaChjb2xsZWN0ZWRSb3cuZ2V0UGFpcnMoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMucGFpcnMucHVzaChyb3cuZ2V0UGFpcnMoKSk7XG4gICAgICAgICAgICAgICAgaWYgKCFSU1NFeHBhbmRlZFJlYWRlci5pc1ZhbGlkU2VxdWVuY2UodGhpcy5wYWlycykpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNoZWNrQ2hlY2tzdW0oKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wYWlycztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IHJzID0gbmV3IEFycmF5KGNvbGxlY3RlZFJvd3MpO1xuICAgICAgICAgICAgICAgIHJzLnB1c2gocm93KTtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZWN1cnNpb246IHRyeSB0byBhZGQgbW9yZSByb3dzXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNoZWNrUm93cyhycywgaSArIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBXZSBmYWlsZWQsIHRyeSB0aGUgbmV4dCBjYW5kaWRhdGVcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMudmVyYm9zZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBXaGV0aGVyIHRoZSBwYWlycyBmb3JtIGEgdmFsaWQgZmluZCBwYXR0ZXJuIHNlcXVlbmNlLFxuICAgICAgICAvLyBlaXRoZXIgY29tcGxldGUgb3IgYSBwcmVmaXhcbiAgICAgICAgc3RhdGljIGlzVmFsaWRTZXF1ZW5jZShwYWlycykge1xuICAgICAgICAgICAgZm9yIChsZXQgc2VxdWVuY2Ugb2YgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVFRFUk5fU0VRVUVOQ0VTKSB7XG4gICAgICAgICAgICAgICAgaWYgKHBhaXJzLmxlbmd0aCA+IHNlcXVlbmNlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IHN0b3AgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgcGFpcnMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhaXJzW2pdLmdldEZpbmRlclBhdHRlcm4oKS5nZXRWYWx1ZSgpICE9IHNlcXVlbmNlW2pdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdG9wID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoc3RvcCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgc3RvcmVSb3cocm93TnVtYmVyLCB3YXNSZXZlcnNlZCkge1xuICAgICAgICAgICAgLy8gRGlzY2FyZCBpZiBkdXBsaWNhdGUgYWJvdmUgb3IgYmVsb3c7IG90aGVyd2lzZSBpbnNlcnQgaW4gb3JkZXIgYnkgcm93IG51bWJlci5cbiAgICAgICAgICAgIGxldCBpbnNlcnRQb3MgPSAwO1xuICAgICAgICAgICAgbGV0IHByZXZJc1NhbWUgPSBmYWxzZTtcbiAgICAgICAgICAgIGxldCBuZXh0SXNTYW1lID0gZmFsc2U7XG4gICAgICAgICAgICB3aGlsZSAoaW5zZXJ0UG9zIDwgdGhpcy5yb3dzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGxldCBlcm93ID0gdGhpcy5yb3dzW2luc2VydFBvc107XG4gICAgICAgICAgICAgICAgaWYgKGVyb3cuZ2V0Um93TnVtYmVyKCkgPiByb3dOdW1iZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV4dElzU2FtZSA9IGVyb3cuaXNFcXVpdmFsZW50KHRoaXMucGFpcnMpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcHJldklzU2FtZSA9IGVyb3cuaXNFcXVpdmFsZW50KHRoaXMucGFpcnMpO1xuICAgICAgICAgICAgICAgIGluc2VydFBvcysrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG5leHRJc1NhbWUgfHwgcHJldklzU2FtZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFdoZW4gdGhlIHJvdyB3YXMgcGFydGlhbGx5IGRlY29kZWQgKGUuZy4gMiBwYWlycyBmb3VuZCBpbnN0ZWFkIG9mIDMpLFxuICAgICAgICAgICAgLy8gaXQgd2lsbCBwcmV2ZW50IHVzIGZyb20gZGV0ZWN0aW5nIHRoZSBiYXJjb2RlLlxuICAgICAgICAgICAgLy8gVHJ5IHRvIG1lcmdlIHBhcnRpYWwgcm93c1xuICAgICAgICAgICAgLy8gQ2hlY2sgd2hldGhlciB0aGUgcm93IGlzIHBhcnQgb2YgYW4gYWxscmVhZHkgZGV0ZWN0ZWQgcm93XG4gICAgICAgICAgICBpZiAoUlNTRXhwYW5kZWRSZWFkZXIuaXNQYXJ0aWFsUm93KHRoaXMucGFpcnMsIHRoaXMucm93cykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnJvd3MucHVzaChpbnNlcnRQb3MsIG5ldyBFeHBhbmRlZFJvdyh0aGlzLnBhaXJzLCByb3dOdW1iZXIsIHdhc1JldmVyc2VkKSk7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZVBhcnRpYWxSb3dzKHRoaXMucGFpcnMsIHRoaXMucm93cyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmVtb3ZlIGFsbCB0aGUgcm93cyB0aGF0IGNvbnRhaW5zIG9ubHkgc3BlY2lmaWVkIHBhaXJzXG4gICAgICAgIHJlbW92ZVBhcnRpYWxSb3dzKHBhaXJzLCByb3dzKSB7XG4gICAgICAgICAgICAvLyBmb3IgKEl0ZXJhdG9yPEV4cGFuZGVkUm93PiBpdGVyYXRvciA9IHJvd3MuaXRlcmF0b3IoKTsgaXRlcmF0b3IuaGFzTmV4dCgpOykge1xuICAgICAgICAgICAgLy8gICBFeHBhbmRlZFJvdyByID0gaXRlcmF0b3IubmV4dCgpO1xuICAgICAgICAgICAgLy8gICBpZiAoci5nZXRQYWlycygpLnNpemUoKSA9PSBwYWlycy5zaXplKCkpIHtcbiAgICAgICAgICAgIC8vICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIC8vICAgfVxuICAgICAgICAgICAgLy8gICBib29sZWFuIGFsbEZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIC8vICAgZm9yIChFeHBhbmRlZFBhaXIgcCA6IHIuZ2V0UGFpcnMoKSkge1xuICAgICAgICAgICAgLy8gICAgIGJvb2xlYW4gZm91bmQgPSBmYWxzZTtcbiAgICAgICAgICAgIC8vICAgICBmb3IgKEV4cGFuZGVkUGFpciBwcCA6IHBhaXJzKSB7XG4gICAgICAgICAgICAvLyAgICAgICBpZiAocC5lcXVhbHMocHApKSB7XG4gICAgICAgICAgICAvLyAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIC8vICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAvLyAgICAgICB9XG4gICAgICAgICAgICAvLyAgICAgfVxuICAgICAgICAgICAgLy8gICAgIGlmICghZm91bmQpIHtcbiAgICAgICAgICAgIC8vICAgICAgIGFsbEZvdW5kID0gZmFsc2U7XG4gICAgICAgICAgICAvLyAgICAgICBicmVhaztcbiAgICAgICAgICAgIC8vICAgICB9XG4gICAgICAgICAgICAvLyAgIH1cbiAgICAgICAgICAgIC8vICAgaWYgKGFsbEZvdW5kKSB7XG4gICAgICAgICAgICAvLyAgICAgLy8gJ3BhaXJzJyBjb250YWlucyBhbGwgdGhlIHBhaXJzIGZyb20gdGhlIHJvdyAncidcbiAgICAgICAgICAgIC8vICAgICBpdGVyYXRvci5yZW1vdmUoKTtcbiAgICAgICAgICAgIC8vICAgfVxuICAgICAgICAgICAgLy8gfVxuICAgICAgICAgICAgZm9yIChsZXQgcm93IG9mIHJvd3MpIHtcbiAgICAgICAgICAgICAgICBpZiAocm93LmdldFBhaXJzKCkubGVuZ3RoID09PSBwYWlycy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAobGV0IHAgb2Ygcm93LmdldFBhaXJzKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgcHAgb2YgcGFpcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChFeHBhbmRlZFBhaXIuZXF1YWxzKHAsIHBwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIFJldHVybnMgdHJ1ZSB3aGVuIG9uZSBvZiB0aGUgcm93cyBhbHJlYWR5IGNvbnRhaW5zIGFsbCB0aGUgcGFpcnNcbiAgICAgICAgc3RhdGljIGlzUGFydGlhbFJvdyhwYWlycywgcm93cykge1xuICAgICAgICAgICAgZm9yIChsZXQgciBvZiByb3dzKSB7XG4gICAgICAgICAgICAgICAgbGV0IGFsbEZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBwIG9mIHBhaXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBwcCBvZiByLmdldFBhaXJzKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwLmVxdWFscyhwcCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFmb3VuZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWxsRm91bmQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChhbGxGb3VuZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgcm93ICdyJyBjb250YWluIGFsbCB0aGUgcGFpcnMgZnJvbSAncGFpcnMnXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBPbmx5IHVzZWQgZm9yIHVuaXQgdGVzdGluZ1xuICAgICAgICBnZXRSb3dzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucm93cztcbiAgICAgICAgfVxuICAgICAgICAvLyBOb3QgcHJpdmF0ZSBmb3IgdW5pdCB0ZXN0aW5nXG4gICAgICAgIHN0YXRpYyBjb25zdHJ1Y3RSZXN1bHQocGFpcnMpIHtcbiAgICAgICAgICAgIGxldCBiaW5hcnkgPSBCaXRBcnJheUJ1aWxkZXIuYnVpbGRCaXRBcnJheShwYWlycyk7XG4gICAgICAgICAgICBsZXQgZGVjb2RlciA9IGNyZWF0ZURlY29kZXIoYmluYXJ5KTtcbiAgICAgICAgICAgIGxldCByZXN1bHRpbmdTdHJpbmcgPSBkZWNvZGVyLnBhcnNlSW5mb3JtYXRpb24oKTtcbiAgICAgICAgICAgIGxldCBmaXJzdFBvaW50cyA9IHBhaXJzWzBdLmdldEZpbmRlclBhdHRlcm4oKS5nZXRSZXN1bHRQb2ludHMoKTtcbiAgICAgICAgICAgIGxldCBsYXN0UG9pbnRzID0gcGFpcnNbcGFpcnMubGVuZ3RoIC0gMV0uZ2V0RmluZGVyUGF0dGVybigpLmdldFJlc3VsdFBvaW50cygpO1xuICAgICAgICAgICAgbGV0IHBvaW50cyA9IFtmaXJzdFBvaW50c1swXSwgZmlyc3RQb2ludHNbMV0sIGxhc3RQb2ludHNbMF0sIGxhc3RQb2ludHNbMV1dO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBSZXN1bHQocmVzdWx0aW5nU3RyaW5nLCBudWxsLCBudWxsLCBwb2ludHMsIEJhcmNvZGVGb3JtYXQkMS5SU1NfRVhQQU5ERUQsIG51bGwpO1xuICAgICAgICB9XG4gICAgICAgIGNoZWNrQ2hlY2tzdW0oKSB7XG4gICAgICAgICAgICBsZXQgZmlyc3RQYWlyID0gdGhpcy5wYWlycy5nZXQoMCk7XG4gICAgICAgICAgICBsZXQgY2hlY2tDaGFyYWN0ZXIgPSBmaXJzdFBhaXIuZ2V0TGVmdENoYXIoKTtcbiAgICAgICAgICAgIGxldCBmaXJzdENoYXJhY3RlciA9IGZpcnN0UGFpci5nZXRSaWdodENoYXIoKTtcbiAgICAgICAgICAgIGlmIChmaXJzdENoYXJhY3RlciA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGNoZWNrc3VtID0gZmlyc3RDaGFyYWN0ZXIuZ2V0Q2hlY2tzdW1Qb3J0aW9uKCk7XG4gICAgICAgICAgICBsZXQgcyA9IDI7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHRoaXMucGFpcnMuc2l6ZSgpOyArK2kpIHtcbiAgICAgICAgICAgICAgICBsZXQgY3VycmVudFBhaXIgPSB0aGlzLnBhaXJzLmdldChpKTtcbiAgICAgICAgICAgICAgICBjaGVja3N1bSArPSBjdXJyZW50UGFpci5nZXRMZWZ0Q2hhcigpLmdldENoZWNrc3VtUG9ydGlvbigpO1xuICAgICAgICAgICAgICAgIHMrKztcbiAgICAgICAgICAgICAgICBsZXQgY3VycmVudFJpZ2h0Q2hhciA9IGN1cnJlbnRQYWlyLmdldFJpZ2h0Q2hhcigpO1xuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50UmlnaHRDaGFyICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hlY2tzdW0gKz0gY3VycmVudFJpZ2h0Q2hhci5nZXRDaGVja3N1bVBvcnRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgcysrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNoZWNrc3VtICU9IDIxMTtcbiAgICAgICAgICAgIGxldCBjaGVja0NoYXJhY3RlclZhbHVlID0gMjExICogKHMgLSA0KSArIGNoZWNrc3VtO1xuICAgICAgICAgICAgcmV0dXJuIGNoZWNrQ2hhcmFjdGVyVmFsdWUgPT0gY2hlY2tDaGFyYWN0ZXIuZ2V0VmFsdWUoKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZ2V0TmV4dFNlY29uZEJhcihyb3csIGluaXRpYWxQb3MpIHtcbiAgICAgICAgICAgIGxldCBjdXJyZW50UG9zO1xuICAgICAgICAgICAgaWYgKHJvdy5nZXQoaW5pdGlhbFBvcykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50UG9zID0gcm93LmdldE5leHRVbnNldChpbml0aWFsUG9zKTtcbiAgICAgICAgICAgICAgICBjdXJyZW50UG9zID0gcm93LmdldE5leHRTZXQoY3VycmVudFBvcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50UG9zID0gcm93LmdldE5leHRTZXQoaW5pdGlhbFBvcyk7XG4gICAgICAgICAgICAgICAgY3VycmVudFBvcyA9IHJvdy5nZXROZXh0VW5zZXQoY3VycmVudFBvcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY3VycmVudFBvcztcbiAgICAgICAgfVxuICAgICAgICAvLyBub3QgcHJpdmF0ZSBmb3IgdGVzdGluZ1xuICAgICAgICByZXRyaWV2ZU5leHRQYWlyKHJvdywgcHJldmlvdXNQYWlycywgcm93TnVtYmVyKSB7XG4gICAgICAgICAgICBsZXQgaXNPZGRQYXR0ZXJuID0gcHJldmlvdXNQYWlycy5sZW5ndGggJSAyID09IDA7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGFydEZyb21FdmVuKSB7XG4gICAgICAgICAgICAgICAgaXNPZGRQYXR0ZXJuID0gIWlzT2RkUGF0dGVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBwYXR0ZXJuO1xuICAgICAgICAgICAgbGV0IGtlZXBGaW5kaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIGxldCBmb3JjZWRPZmZzZXQgPSAtMTtcbiAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpbmROZXh0UGFpcihyb3csIHByZXZpb3VzUGFpcnMsIGZvcmNlZE9mZnNldCk7XG4gICAgICAgICAgICAgICAgcGF0dGVybiA9IHRoaXMucGFyc2VGb3VuZEZpbmRlclBhdHRlcm4ocm93LCByb3dOdW1iZXIsIGlzT2RkUGF0dGVybik7XG4gICAgICAgICAgICAgICAgaWYgKHBhdHRlcm4gPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBmb3JjZWRPZmZzZXQgPSBSU1NFeHBhbmRlZFJlYWRlci5nZXROZXh0U2Vjb25kQmFyKHJvdywgdGhpcy5zdGFydEVuZFswXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBrZWVwRmluZGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gd2hpbGUgKGtlZXBGaW5kaW5nKTtcbiAgICAgICAgICAgIC8vIFdoZW4gc3RhY2tlZCBzeW1ib2wgaXMgc3BsaXQgb3ZlciBtdWx0aXBsZSByb3dzLCB0aGVyZSdzIG5vIHdheSB0byBndWVzcyBpZiB0aGlzIHBhaXIgY2FuIGJlIGxhc3Qgb3Igbm90LlxuICAgICAgICAgICAgLy8gYm9vbGVhbiBtYXlCZUxhc3QgPSBjaGVja1BhaXJTZXF1ZW5jZShwcmV2aW91c1BhaXJzLCBwYXR0ZXJuKTtcbiAgICAgICAgICAgIGxldCBsZWZ0Q2hhciA9IHRoaXMuZGVjb2RlRGF0YUNoYXJhY3Rlcihyb3csIHBhdHRlcm4sIGlzT2RkUGF0dGVybiwgdHJ1ZSk7XG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNFbXB0eVBhaXIocHJldmlvdXNQYWlycykgJiYgcHJldmlvdXNQYWlyc1twcmV2aW91c1BhaXJzLmxlbmd0aCAtIDFdLm11c3RCZUxhc3QoKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHJpZ2h0Q2hhcjtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmlnaHRDaGFyID0gdGhpcy5kZWNvZGVEYXRhQ2hhcmFjdGVyKHJvdywgcGF0dGVybiwgaXNPZGRQYXR0ZXJuLCBmYWxzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHJpZ2h0Q2hhciA9IG51bGw7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMudmVyYm9zZSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IEV4cGFuZGVkUGFpcihsZWZ0Q2hhciwgcmlnaHRDaGFyLCBwYXR0ZXJuLCB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICBpc0VtcHR5UGFpcihwYWlycykge1xuICAgICAgICAgICAgaWYgKHBhaXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGZpbmROZXh0UGFpcihyb3csIHByZXZpb3VzUGFpcnMsIGZvcmNlZE9mZnNldCkge1xuICAgICAgICAgICAgbGV0IGNvdW50ZXJzID0gdGhpcy5nZXREZWNvZGVGaW5kZXJDb3VudGVycygpO1xuICAgICAgICAgICAgY291bnRlcnNbMF0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbMV0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbMl0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbM10gPSAwO1xuICAgICAgICAgICAgbGV0IHdpZHRoID0gcm93LmdldFNpemUoKTtcbiAgICAgICAgICAgIGxldCByb3dPZmZzZXQ7XG4gICAgICAgICAgICBpZiAoZm9yY2VkT2Zmc2V0ID49IDApIHtcbiAgICAgICAgICAgICAgICByb3dPZmZzZXQgPSBmb3JjZWRPZmZzZXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLmlzRW1wdHlQYWlyKHByZXZpb3VzUGFpcnMpKSB7XG4gICAgICAgICAgICAgICAgcm93T2Zmc2V0ID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGxldCBsYXN0UGFpciA9IHByZXZpb3VzUGFpcnNbcHJldmlvdXNQYWlycy5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgICAgICByb3dPZmZzZXQgPSBsYXN0UGFpci5nZXRGaW5kZXJQYXR0ZXJuKCkuZ2V0U3RhcnRFbmQoKVsxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBzZWFyY2hpbmdFdmVuUGFpciA9IHByZXZpb3VzUGFpcnMubGVuZ3RoICUgMiAhPSAwO1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhcnRGcm9tRXZlbikge1xuICAgICAgICAgICAgICAgIHNlYXJjaGluZ0V2ZW5QYWlyID0gIXNlYXJjaGluZ0V2ZW5QYWlyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGlzV2hpdGUgPSBmYWxzZTtcbiAgICAgICAgICAgIHdoaWxlIChyb3dPZmZzZXQgPCB3aWR0aCkge1xuICAgICAgICAgICAgICAgIGlzV2hpdGUgPSAhcm93LmdldChyb3dPZmZzZXQpO1xuICAgICAgICAgICAgICAgIGlmICghaXNXaGl0ZSkge1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcm93T2Zmc2V0Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgY291bnRlclBvc2l0aW9uID0gMDtcbiAgICAgICAgICAgIGxldCBwYXR0ZXJuU3RhcnQgPSByb3dPZmZzZXQ7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gcm93T2Zmc2V0OyB4IDwgd2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgIGlmIChyb3cuZ2V0KHgpICE9IGlzV2hpdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbY291bnRlclBvc2l0aW9uXSsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvdW50ZXJQb3NpdGlvbiA9PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VhcmNoaW5nRXZlblBhaXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBSU1NFeHBhbmRlZFJlYWRlci5yZXZlcnNlQ291bnRlcnMoY291bnRlcnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFJTU0V4cGFuZGVkUmVhZGVyLmlzRmluZGVyUGF0dGVybihjb3VudGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0RW5kWzBdID0gcGF0dGVyblN0YXJ0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhcnRFbmRbMV0gPSB4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZWFyY2hpbmdFdmVuUGFpcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJTU0V4cGFuZGVkUmVhZGVyLnJldmVyc2VDb3VudGVycyhjb3VudGVycyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuU3RhcnQgKz0gY291bnRlcnNbMF0gKyBjb3VudGVyc1sxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzWzBdID0gY291bnRlcnNbMl07XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1sxXSA9IGNvdW50ZXJzWzNdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbMl0gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbM10gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlclBvc2l0aW9uLS07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyUG9zaXRpb24rKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb25dID0gMTtcbiAgICAgICAgICAgICAgICAgICAgaXNXaGl0ZSA9ICFpc1doaXRlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyByZXZlcnNlQ291bnRlcnMoY291bnRlcnMpIHtcbiAgICAgICAgICAgIGxldCBsZW5ndGggPSBjb3VudGVycy5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aCAvIDI7ICsraSkge1xuICAgICAgICAgICAgICAgIGxldCB0bXAgPSBjb3VudGVyc1tpXTtcbiAgICAgICAgICAgICAgICBjb3VudGVyc1tpXSA9IGNvdW50ZXJzW2xlbmd0aCAtIGkgLSAxXTtcbiAgICAgICAgICAgICAgICBjb3VudGVyc1tsZW5ndGggLSBpIC0gMV0gPSB0bXA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcGFyc2VGb3VuZEZpbmRlclBhdHRlcm4ocm93LCByb3dOdW1iZXIsIG9kZFBhdHRlcm4pIHtcbiAgICAgICAgICAgIC8vIEFjdHVhbGx5IHdlIGZvdW5kIGVsZW1lbnRzIDItNS5cbiAgICAgICAgICAgIGxldCBmaXJzdENvdW50ZXI7XG4gICAgICAgICAgICBsZXQgc3RhcnQ7XG4gICAgICAgICAgICBsZXQgZW5kO1xuICAgICAgICAgICAgaWYgKG9kZFBhdHRlcm4pIHtcbiAgICAgICAgICAgICAgICAvLyBJZiBwYXR0ZXJuIG51bWJlciBpcyBvZGQsIHdlIG5lZWQgdG8gbG9jYXRlIGVsZW1lbnQgMSAqYmVmb3JlKiB0aGUgY3VycmVudCBibG9jay5cbiAgICAgICAgICAgICAgICBsZXQgZmlyc3RFbGVtZW50U3RhcnQgPSB0aGlzLnN0YXJ0RW5kWzBdIC0gMTtcbiAgICAgICAgICAgICAgICAvLyBMb2NhdGUgZWxlbWVudCAxXG4gICAgICAgICAgICAgICAgd2hpbGUgKGZpcnN0RWxlbWVudFN0YXJ0ID49IDAgJiYgIXJvdy5nZXQoZmlyc3RFbGVtZW50U3RhcnQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpcnN0RWxlbWVudFN0YXJ0LS07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZpcnN0RWxlbWVudFN0YXJ0Kys7XG4gICAgICAgICAgICAgICAgZmlyc3RDb3VudGVyID0gdGhpcy5zdGFydEVuZFswXSAtIGZpcnN0RWxlbWVudFN0YXJ0O1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gZmlyc3RFbGVtZW50U3RhcnQ7XG4gICAgICAgICAgICAgICAgZW5kID0gdGhpcy5zdGFydEVuZFsxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIElmIHBhdHRlcm4gbnVtYmVyIGlzIGV2ZW4sIHRoZSBwYXR0ZXJuIGlzIHJldmVyc2VkLCBzbyB3ZSBuZWVkIHRvIGxvY2F0ZSBlbGVtZW50IDEgKmFmdGVyKiB0aGUgY3VycmVudCBibG9jay5cbiAgICAgICAgICAgICAgICBzdGFydCA9IHRoaXMuc3RhcnRFbmRbMF07XG4gICAgICAgICAgICAgICAgZW5kID0gcm93LmdldE5leHRVbnNldCh0aGlzLnN0YXJ0RW5kWzFdICsgMSk7XG4gICAgICAgICAgICAgICAgZmlyc3RDb3VudGVyID0gZW5kIC0gdGhpcy5zdGFydEVuZFsxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE1ha2UgJ2NvdW50ZXJzJyBob2xkIDEtNFxuICAgICAgICAgICAgbGV0IGNvdW50ZXJzID0gdGhpcy5nZXREZWNvZGVGaW5kZXJDb3VudGVycygpO1xuICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weShjb3VudGVycywgMCwgY291bnRlcnMsIDEsIGNvdW50ZXJzLmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgY291bnRlcnNbMF0gPSBmaXJzdENvdW50ZXI7XG4gICAgICAgICAgICBsZXQgdmFsdWU7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5wYXJzZUZpbmRlclZhbHVlKGNvdW50ZXJzLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUVEVSTlMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHJldHVybiBuZXcgRmluZGVyUGF0dGVybih2YWx1ZSwgbmV3IGludFtdIHsgc3RhcnQsIGVuZCB9LCBzdGFydCwgZW5kLCByb3dOdW1iZXJ9KTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRmluZGVyUGF0dGVybih2YWx1ZSwgW3N0YXJ0LCBlbmRdLCBzdGFydCwgZW5kLCByb3dOdW1iZXIpO1xuICAgICAgICB9XG4gICAgICAgIGRlY29kZURhdGFDaGFyYWN0ZXIocm93LCBwYXR0ZXJuLCBpc09kZFBhdHRlcm4sIGxlZnRDaGFyKSB7XG4gICAgICAgICAgICBsZXQgY291bnRlcnMgPSB0aGlzLmdldERhdGFDaGFyYWN0ZXJDb3VudGVycygpO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCBjb3VudGVycy5sZW5ndGg7IHgrKykge1xuICAgICAgICAgICAgICAgIGNvdW50ZXJzW3hdID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChsZWZ0Q2hhcikge1xuICAgICAgICAgICAgICAgIFJTU0V4cGFuZGVkUmVhZGVyLnJlY29yZFBhdHRlcm5JblJldmVyc2Uocm93LCBwYXR0ZXJuLmdldFN0YXJ0RW5kKClbMF0sIGNvdW50ZXJzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIFJTU0V4cGFuZGVkUmVhZGVyLnJlY29yZFBhdHRlcm4ocm93LCBwYXR0ZXJuLmdldFN0YXJ0RW5kKClbMV0sIGNvdW50ZXJzKTtcbiAgICAgICAgICAgICAgICAvLyByZXZlcnNlIGl0XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGogPSBjb3VudGVycy5sZW5ndGggLSAxOyBpIDwgajsgaSsrLCBqLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHRlbXAgPSBjb3VudGVyc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbaV0gPSBjb3VudGVyc1tqXTtcbiAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbal0gPSB0ZW1wO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gLy8gY291bnRlcnNbXSBoYXMgdGhlIHBpeGVscyBvZiB0aGUgbW9kdWxlXG4gICAgICAgICAgICBsZXQgbnVtTW9kdWxlcyA9IDE3OyAvLyBsZWZ0IGFuZCByaWdodCBkYXRhIGNoYXJhY3RlcnMgaGF2ZSBhbGwgdGhlIHNhbWUgbGVuZ3RoXG4gICAgICAgICAgICBsZXQgZWxlbWVudFdpZHRoID0gTWF0aFV0aWxzLnN1bShuZXcgSW50MzJBcnJheShjb3VudGVycykpIC8gbnVtTW9kdWxlcztcbiAgICAgICAgICAgIC8vIFNhbml0eSBjaGVjazogZWxlbWVudCB3aWR0aCBmb3IgcGF0dGVybiBhbmQgdGhlIGNoYXJhY3RlciBzaG91bGQgbWF0Y2hcbiAgICAgICAgICAgIGxldCBleHBlY3RlZEVsZW1lbnRXaWR0aCA9IChwYXR0ZXJuLmdldFN0YXJ0RW5kKClbMV0gLSBwYXR0ZXJuLmdldFN0YXJ0RW5kKClbMF0pIC8gMTUuMDtcbiAgICAgICAgICAgIGlmIChNYXRoLmFicyhlbGVtZW50V2lkdGggLSBleHBlY3RlZEVsZW1lbnRXaWR0aCkgLyBleHBlY3RlZEVsZW1lbnRXaWR0aCA+IDAuMykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IG9kZENvdW50cyA9IHRoaXMuZ2V0T2RkQ291bnRzKCk7XG4gICAgICAgICAgICBsZXQgZXZlbkNvdW50cyA9IHRoaXMuZ2V0RXZlbkNvdW50cygpO1xuICAgICAgICAgICAgbGV0IG9kZFJvdW5kaW5nRXJyb3JzID0gdGhpcy5nZXRPZGRSb3VuZGluZ0Vycm9ycygpO1xuICAgICAgICAgICAgbGV0IGV2ZW5Sb3VuZGluZ0Vycm9ycyA9IHRoaXMuZ2V0RXZlblJvdW5kaW5nRXJyb3JzKCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IHZhbHVlID0gMS4wICogY291bnRlcnNbaV0gLyBlbGVtZW50V2lkdGg7XG4gICAgICAgICAgICAgICAgbGV0IGNvdW50ID0gdmFsdWUgKyAwLjU7IC8vIFJvdW5kXG4gICAgICAgICAgICAgICAgaWYgKGNvdW50IDwgMSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUgPCAwLjMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ID0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoY291bnQgPiA4KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA+IDguNykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY291bnQgPSA4O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgb2Zmc2V0ID0gaSAvIDI7XG4gICAgICAgICAgICAgICAgaWYgKChpICYgMHgwMSkgPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBvZGRDb3VudHNbb2Zmc2V0XSA9IGNvdW50O1xuICAgICAgICAgICAgICAgICAgICBvZGRSb3VuZGluZ0Vycm9yc1tvZmZzZXRdID0gdmFsdWUgLSBjb3VudDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW5Db3VudHNbb2Zmc2V0XSA9IGNvdW50O1xuICAgICAgICAgICAgICAgICAgICBldmVuUm91bmRpbmdFcnJvcnNbb2Zmc2V0XSA9IHZhbHVlIC0gY291bnQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5hZGp1c3RPZGRFdmVuQ291bnRzKG51bU1vZHVsZXMpO1xuICAgICAgICAgICAgbGV0IHdlaWdodFJvd051bWJlciA9IDQgKiBwYXR0ZXJuLmdldFZhbHVlKCkgKyAoaXNPZGRQYXR0ZXJuID8gMCA6IDIpICsgKGxlZnRDaGFyID8gMCA6IDEpIC0gMTtcbiAgICAgICAgICAgIGxldCBvZGRTdW0gPSAwO1xuICAgICAgICAgICAgbGV0IG9kZENoZWNrc3VtUG9ydGlvbiA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gb2RkQ291bnRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICAgICAgaWYgKFJTU0V4cGFuZGVkUmVhZGVyLmlzTm90QTFsZWZ0KHBhdHRlcm4sIGlzT2RkUGF0dGVybiwgbGVmdENoYXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCB3ZWlnaHQgPSBSU1NFeHBhbmRlZFJlYWRlci5XRUlHSFRTW3dlaWdodFJvd051bWJlcl1bMiAqIGldO1xuICAgICAgICAgICAgICAgICAgICBvZGRDaGVja3N1bVBvcnRpb24gKz0gb2RkQ291bnRzW2ldICogd2VpZ2h0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvZGRTdW0gKz0gb2RkQ291bnRzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGV2ZW5DaGVja3N1bVBvcnRpb24gPSAwO1xuICAgICAgICAgICAgLy8gaW50IGV2ZW5TdW0gPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGV2ZW5Db3VudHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgICAgICBpZiAoUlNTRXhwYW5kZWRSZWFkZXIuaXNOb3RBMWxlZnQocGF0dGVybiwgaXNPZGRQYXR0ZXJuLCBsZWZ0Q2hhcikpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHdlaWdodCA9IFJTU0V4cGFuZGVkUmVhZGVyLldFSUdIVFNbd2VpZ2h0Um93TnVtYmVyXVsyICogaSArIDFdO1xuICAgICAgICAgICAgICAgICAgICBldmVuQ2hlY2tzdW1Qb3J0aW9uICs9IGV2ZW5Db3VudHNbaV0gKiB3ZWlnaHQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGV2ZW5TdW0gKz0gZXZlbkNvdW50c1tpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBjaGVja3N1bVBvcnRpb24gPSBvZGRDaGVja3N1bVBvcnRpb24gKyBldmVuQ2hlY2tzdW1Qb3J0aW9uO1xuICAgICAgICAgICAgaWYgKChvZGRTdW0gJiAweDAxKSAhPSAwIHx8IG9kZFN1bSA+IDEzIHx8IG9kZFN1bSA8IDQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBncm91cCA9ICgxMyAtIG9kZFN1bSkgLyAyO1xuICAgICAgICAgICAgbGV0IG9kZFdpZGVzdCA9IFJTU0V4cGFuZGVkUmVhZGVyLlNZTUJPTF9XSURFU1RbZ3JvdXBdO1xuICAgICAgICAgICAgbGV0IGV2ZW5XaWRlc3QgPSA5IC0gb2RkV2lkZXN0O1xuICAgICAgICAgICAgbGV0IHZPZGQgPSBSU1NVdGlscy5nZXRSU1N2YWx1ZShvZGRDb3VudHMsIG9kZFdpZGVzdCwgdHJ1ZSk7XG4gICAgICAgICAgICBsZXQgdkV2ZW4gPSBSU1NVdGlscy5nZXRSU1N2YWx1ZShldmVuQ291bnRzLCBldmVuV2lkZXN0LCBmYWxzZSk7XG4gICAgICAgICAgICBsZXQgdEV2ZW4gPSBSU1NFeHBhbmRlZFJlYWRlci5FVkVOX1RPVEFMX1NVQlNFVFtncm91cF07XG4gICAgICAgICAgICBsZXQgZ1N1bSA9IFJTU0V4cGFuZGVkUmVhZGVyLkdTVU1bZ3JvdXBdO1xuICAgICAgICAgICAgbGV0IHZhbHVlID0gdk9kZCAqIHRFdmVuICsgdkV2ZW4gKyBnU3VtO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBEYXRhQ2hhcmFjdGVyKHZhbHVlLCBjaGVja3N1bVBvcnRpb24pO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBpc05vdEExbGVmdChwYXR0ZXJuLCBpc09kZFBhdHRlcm4sIGxlZnRDaGFyKSB7XG4gICAgICAgICAgICAvLyBBMTogcGF0dGVybi5nZXRWYWx1ZSBpcyAwIChBKSwgYW5kIGl0J3MgYW4gb2RkUGF0dGVybiwgYW5kIGl0IGlzIGEgbGVmdCBjaGFyXG4gICAgICAgICAgICByZXR1cm4gIShwYXR0ZXJuLmdldFZhbHVlKCkgPT0gMCAmJiBpc09kZFBhdHRlcm4gJiYgbGVmdENoYXIpO1xuICAgICAgICB9XG4gICAgICAgIGFkanVzdE9kZEV2ZW5Db3VudHMobnVtTW9kdWxlcykge1xuICAgICAgICAgICAgbGV0IG9kZFN1bSA9IE1hdGhVdGlscy5zdW0obmV3IEludDMyQXJyYXkodGhpcy5nZXRPZGRDb3VudHMoKSkpO1xuICAgICAgICAgICAgbGV0IGV2ZW5TdW0gPSBNYXRoVXRpbHMuc3VtKG5ldyBJbnQzMkFycmF5KHRoaXMuZ2V0RXZlbkNvdW50cygpKSk7XG4gICAgICAgICAgICBsZXQgaW5jcmVtZW50T2RkID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgZGVjcmVtZW50T2RkID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAob2RkU3VtID4gMTMpIHtcbiAgICAgICAgICAgICAgICBkZWNyZW1lbnRPZGQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAob2RkU3VtIDwgNCkge1xuICAgICAgICAgICAgICAgIGluY3JlbWVudE9kZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgaW5jcmVtZW50RXZlbiA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGRlY3JlbWVudEV2ZW4gPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChldmVuU3VtID4gMTMpIHtcbiAgICAgICAgICAgICAgICBkZWNyZW1lbnRFdmVuID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGV2ZW5TdW0gPCA0KSB7XG4gICAgICAgICAgICAgICAgaW5jcmVtZW50RXZlbiA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgbWlzbWF0Y2ggPSBvZGRTdW0gKyBldmVuU3VtIC0gbnVtTW9kdWxlcztcbiAgICAgICAgICAgIGxldCBvZGRQYXJpdHlCYWQgPSAob2RkU3VtICYgMHgwMSkgPT0gMTtcbiAgICAgICAgICAgIGxldCBldmVuUGFyaXR5QmFkID0gKGV2ZW5TdW0gJiAweDAxKSA9PSAwO1xuICAgICAgICAgICAgaWYgKG1pc21hdGNoID09IDEpIHtcbiAgICAgICAgICAgICAgICBpZiAob2RkUGFyaXR5QmFkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChldmVuUGFyaXR5QmFkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkZWNyZW1lbnRPZGQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFldmVuUGFyaXR5QmFkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkZWNyZW1lbnRFdmVuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChtaXNtYXRjaCA9PSAtMSkge1xuICAgICAgICAgICAgICAgIGlmIChvZGRQYXJpdHlCYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW5QYXJpdHlCYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGluY3JlbWVudE9kZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWV2ZW5QYXJpdHlCYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGluY3JlbWVudEV2ZW4gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKG1pc21hdGNoID09IDApIHtcbiAgICAgICAgICAgICAgICBpZiAob2RkUGFyaXR5QmFkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZXZlblBhcml0eUJhZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gQm90aCBiYWRcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9kZFN1bSA8IGV2ZW5TdW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluY3JlbWVudE9kZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWNyZW1lbnRFdmVuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlY3JlbWVudE9kZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmNyZW1lbnRFdmVuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW5QYXJpdHlCYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIE5vdGhpbmcgdG8gZG8hXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaW5jcmVtZW50T2RkKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRlY3JlbWVudE9kZCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgUlNTRXhwYW5kZWRSZWFkZXIuaW5jcmVtZW50KHRoaXMuZ2V0T2RkQ291bnRzKCksIHRoaXMuZ2V0T2RkUm91bmRpbmdFcnJvcnMoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZGVjcmVtZW50T2RkKSB7XG4gICAgICAgICAgICAgICAgUlNTRXhwYW5kZWRSZWFkZXIuZGVjcmVtZW50KHRoaXMuZ2V0T2RkQ291bnRzKCksIHRoaXMuZ2V0T2RkUm91bmRpbmdFcnJvcnMoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaW5jcmVtZW50RXZlbikge1xuICAgICAgICAgICAgICAgIGlmIChkZWNyZW1lbnRFdmVuKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBSU1NFeHBhbmRlZFJlYWRlci5pbmNyZW1lbnQodGhpcy5nZXRFdmVuQ291bnRzKCksIHRoaXMuZ2V0T2RkUm91bmRpbmdFcnJvcnMoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZGVjcmVtZW50RXZlbikge1xuICAgICAgICAgICAgICAgIFJTU0V4cGFuZGVkUmVhZGVyLmRlY3JlbWVudCh0aGlzLmdldEV2ZW5Db3VudHMoKSwgdGhpcy5nZXRFdmVuUm91bmRpbmdFcnJvcnMoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgUlNTRXhwYW5kZWRSZWFkZXIuU1lNQk9MX1dJREVTVCA9IFs3LCA1LCA0LCAzLCAxXTtcbiAgICBSU1NFeHBhbmRlZFJlYWRlci5FVkVOX1RPVEFMX1NVQlNFVCA9IFs0LCAyMCwgNTIsIDEwNCwgMjA0XTtcbiAgICBSU1NFeHBhbmRlZFJlYWRlci5HU1VNID0gWzAsIDM0OCwgMTM4OCwgMjk0OCwgMzk4OF07XG4gICAgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVFRFUk5TID0gW1xuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDgsIDQsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCA2LCA0LCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgNCwgNiwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDIsIDgsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCA2LCA1LCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMiwgOSwgMV0pIC8vIEZcbiAgICBdO1xuICAgIFJTU0V4cGFuZGVkUmVhZGVyLldFSUdIVFMgPSBbXG4gICAgICAgIFsxLCAzLCA5LCAyNywgODEsIDMyLCA5NiwgNzddLFxuICAgICAgICBbMjAsIDYwLCAxODAsIDExOCwgMTQzLCA3LCAyMSwgNjNdLFxuICAgICAgICBbMTg5LCAxNDUsIDEzLCAzOSwgMTE3LCAxNDAsIDIwOSwgMjA1XSxcbiAgICAgICAgWzE5MywgMTU3LCA0OSwgMTQ3LCAxOSwgNTcsIDE3MSwgOTFdLFxuICAgICAgICBbNjIsIDE4NiwgMTM2LCAxOTcsIDE2OSwgODUsIDQ0LCAxMzJdLFxuICAgICAgICBbMTg1LCAxMzMsIDE4OCwgMTQyLCA0LCAxMiwgMzYsIDEwOF0sXG4gICAgICAgIFsxMTMsIDEyOCwgMTczLCA5NywgODAsIDI5LCA4NywgNTBdLFxuICAgICAgICBbMTUwLCAyOCwgODQsIDQxLCAxMjMsIDE1OCwgNTIsIDE1Nl0sXG4gICAgICAgIFs0NiwgMTM4LCAyMDMsIDE4NywgMTM5LCAyMDYsIDE5NiwgMTY2XSxcbiAgICAgICAgWzc2LCAxNywgNTEsIDE1MywgMzcsIDExMSwgMTIyLCAxNTVdLFxuICAgICAgICBbNDMsIDEyOSwgMTc2LCAxMDYsIDEwNywgMTEwLCAxMTksIDE0Nl0sXG4gICAgICAgIFsxNiwgNDgsIDE0NCwgMTAsIDMwLCA5MCwgNTksIDE3N10sXG4gICAgICAgIFsxMDksIDExNiwgMTM3LCAyMDAsIDE3OCwgMTEyLCAxMjUsIDE2NF0sXG4gICAgICAgIFs3MCwgMjEwLCAyMDgsIDIwMiwgMTg0LCAxMzAsIDE3OSwgMTE1XSxcbiAgICAgICAgWzEzNCwgMTkxLCAxNTEsIDMxLCA5MywgNjgsIDIwNCwgMTkwXSxcbiAgICAgICAgWzE0OCwgMjIsIDY2LCAxOTgsIDE3MiwgOTQsIDcxLCAyXSxcbiAgICAgICAgWzYsIDE4LCA1NCwgMTYyLCA2NCwgMTkyLCAxNTQsIDQwXSxcbiAgICAgICAgWzEyMCwgMTQ5LCAyNSwgNzUsIDE0LCA0MiwgMTI2LCAxNjddLFxuICAgICAgICBbNzksIDI2LCA3OCwgMjMsIDY5LCAyMDcsIDE5OSwgMTc1XSxcbiAgICAgICAgWzEwMywgOTgsIDgzLCAzOCwgMTE0LCAxMzEsIDE4MiwgMTI0XSxcbiAgICAgICAgWzE2MSwgNjEsIDE4MywgMTI3LCAxNzAsIDg4LCA1MywgMTU5XSxcbiAgICAgICAgWzU1LCAxNjUsIDczLCA4LCAyNCwgNzIsIDUsIDE1XSxcbiAgICAgICAgWzQ1LCAxMzUsIDE5NCwgMTYwLCA1OCwgMTc0LCAxMDAsIDg5XVxuICAgIF07XG4gICAgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9BID0gMDtcbiAgICBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0IgPSAxO1xuICAgIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQyA9IDI7XG4gICAgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9EID0gMztcbiAgICBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0UgPSA0O1xuICAgIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRiA9IDU7XG4gICAgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVFRFUk5fU0VRVUVOQ0VTID0gW1xuICAgICAgICBbUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9BLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0FdLFxuICAgICAgICBbUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9BLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0IsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQl0sXG4gICAgICAgIFtSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0EsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQywgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9CLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0RdLFxuICAgICAgICBbUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9BLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0UsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQiwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9ELCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0NdLFxuICAgICAgICBbUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9BLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0UsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQiwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9ELCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0QsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRl0sXG4gICAgICAgIFtSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0EsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRSwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9CLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0QsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRSwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9GLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0ZdLFxuICAgICAgICBbUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9BLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0EsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQiwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9CLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0MsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQywgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9ELCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0RdLFxuICAgICAgICBbUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9BLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0EsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQiwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9CLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0MsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQywgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9ELCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0UsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRV0sXG4gICAgICAgIFtSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0EsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQSwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9CLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0IsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQywgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9DLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0QsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRSwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9GLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0ZdLFxuICAgICAgICBbUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9BLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0EsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQiwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9CLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0MsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRCwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9ELCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0UsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRSwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9GLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0ZdLFxuICAgIF07XG4gICAgUlNTRXhwYW5kZWRSZWFkZXIuTUFYX1BBSVJTID0gMTE7XG5cbiAgICBjbGFzcyBQYWlyIGV4dGVuZHMgRGF0YUNoYXJhY3RlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHZhbHVlLCBjaGVja3N1bVBvcnRpb24sIGZpbmRlclBhdHRlcm4pIHtcbiAgICAgICAgICAgIHN1cGVyKHZhbHVlLCBjaGVja3N1bVBvcnRpb24pO1xuICAgICAgICAgICAgdGhpcy5jb3VudCA9IDA7XG4gICAgICAgICAgICB0aGlzLmZpbmRlclBhdHRlcm4gPSBmaW5kZXJQYXR0ZXJuO1xuICAgICAgICB9XG4gICAgICAgIGdldEZpbmRlclBhdHRlcm4oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5maW5kZXJQYXR0ZXJuO1xuICAgICAgICB9XG4gICAgICAgIGdldENvdW50KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY291bnQ7XG4gICAgICAgIH1cbiAgICAgICAgaW5jcmVtZW50Q291bnQoKSB7XG4gICAgICAgICAgICB0aGlzLmNvdW50Kys7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjbGFzcyBSU1MxNFJlYWRlciBleHRlbmRzIEFic3RyYWN0UlNTUmVhZGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICAgICAgdGhpcy5wb3NzaWJsZUxlZnRQYWlycyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5wb3NzaWJsZVJpZ2h0UGFpcnMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICBkZWNvZGVSb3cocm93TnVtYmVyLCByb3csIGhpbnRzKSB7XG4gICAgICAgICAgICBjb25zdCBsZWZ0UGFpciA9IHRoaXMuZGVjb2RlUGFpcihyb3csIGZhbHNlLCByb3dOdW1iZXIsIGhpbnRzKTtcbiAgICAgICAgICAgIFJTUzE0UmVhZGVyLmFkZE9yVGFsbHkodGhpcy5wb3NzaWJsZUxlZnRQYWlycywgbGVmdFBhaXIpO1xuICAgICAgICAgICAgcm93LnJldmVyc2UoKTtcbiAgICAgICAgICAgIGxldCByaWdodFBhaXIgPSB0aGlzLmRlY29kZVBhaXIocm93LCB0cnVlLCByb3dOdW1iZXIsIGhpbnRzKTtcbiAgICAgICAgICAgIFJTUzE0UmVhZGVyLmFkZE9yVGFsbHkodGhpcy5wb3NzaWJsZVJpZ2h0UGFpcnMsIHJpZ2h0UGFpcik7XG4gICAgICAgICAgICByb3cucmV2ZXJzZSgpO1xuICAgICAgICAgICAgZm9yIChsZXQgbGVmdCBvZiB0aGlzLnBvc3NpYmxlTGVmdFBhaXJzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGxlZnQuZ2V0Q291bnQoKSA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgcmlnaHQgb2YgdGhpcy5wb3NzaWJsZVJpZ2h0UGFpcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyaWdodC5nZXRDb3VudCgpID4gMSAmJiBSU1MxNFJlYWRlci5jaGVja0NoZWNrc3VtKGxlZnQsIHJpZ2h0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBSU1MxNFJlYWRlci5jb25zdHJ1Y3RSZXN1bHQobGVmdCwgcmlnaHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGFkZE9yVGFsbHkocG9zc2libGVQYWlycywgcGFpcikge1xuICAgICAgICAgICAgaWYgKHBhaXIgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgICAgICAgICAgZm9yIChsZXQgb3RoZXIgb2YgcG9zc2libGVQYWlycykge1xuICAgICAgICAgICAgICAgIGlmIChvdGhlci5nZXRWYWx1ZSgpID09PSBwYWlyLmdldFZhbHVlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgb3RoZXIuaW5jcmVtZW50Q291bnQoKTtcbiAgICAgICAgICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWZvdW5kKSB7XG4gICAgICAgICAgICAgICAgcG9zc2libGVQYWlycy5wdXNoKHBhaXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJlc2V0KCkge1xuICAgICAgICAgICAgdGhpcy5wb3NzaWJsZUxlZnRQYWlycy5sZW5ndGggPSAwO1xuICAgICAgICAgICAgdGhpcy5wb3NzaWJsZVJpZ2h0UGFpcnMubGVuZ3RoID0gMDtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgY29uc3RydWN0UmVzdWx0KGxlZnRQYWlyLCByaWdodFBhaXIpIHtcbiAgICAgICAgICAgIGxldCBzeW1ib2xWYWx1ZSA9IDQ1MzcwNzcgKiBsZWZ0UGFpci5nZXRWYWx1ZSgpICsgcmlnaHRQYWlyLmdldFZhbHVlKCk7XG4gICAgICAgICAgICBsZXQgdGV4dCA9IG5ldyBTdHJpbmcoc3ltYm9sVmFsdWUpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICBsZXQgYnVmZmVyID0gbmV3IFN0cmluZ0J1aWxkZXIoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAxMyAtIHRleHQubGVuZ3RoOyBpID4gMDsgaS0tKSB7XG4gICAgICAgICAgICAgICAgYnVmZmVyLmFwcGVuZCgnMCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnVmZmVyLmFwcGVuZCh0ZXh0KTtcbiAgICAgICAgICAgIGxldCBjaGVja0RpZ2l0ID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMTM7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCBkaWdpdCA9IGJ1ZmZlci5jaGFyQXQoaSkuY2hhckNvZGVBdCgwKSAtICcwJy5jaGFyQ29kZUF0KDApO1xuICAgICAgICAgICAgICAgIGNoZWNrRGlnaXQgKz0gKChpICYgMHgwMSkgPT09IDApID8gMyAqIGRpZ2l0IDogZGlnaXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjaGVja0RpZ2l0ID0gMTAgLSAoY2hlY2tEaWdpdCAlIDEwKTtcbiAgICAgICAgICAgIGlmIChjaGVja0RpZ2l0ID09PSAxMCkge1xuICAgICAgICAgICAgICAgIGNoZWNrRGlnaXQgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnVmZmVyLmFwcGVuZChjaGVja0RpZ2l0LnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgbGV0IGxlZnRQb2ludHMgPSBsZWZ0UGFpci5nZXRGaW5kZXJQYXR0ZXJuKCkuZ2V0UmVzdWx0UG9pbnRzKCk7XG4gICAgICAgICAgICBsZXQgcmlnaHRQb2ludHMgPSByaWdodFBhaXIuZ2V0RmluZGVyUGF0dGVybigpLmdldFJlc3VsdFBvaW50cygpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBSZXN1bHQoYnVmZmVyLnRvU3RyaW5nKCksIG51bGwsIDAsIFtsZWZ0UG9pbnRzWzBdLCBsZWZ0UG9pbnRzWzFdLCByaWdodFBvaW50c1swXSwgcmlnaHRQb2ludHNbMV1dLCBCYXJjb2RlRm9ybWF0JDEuUlNTXzE0LCBuZXcgRGF0ZSgpLmdldFRpbWUoKSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGNoZWNrQ2hlY2tzdW0obGVmdFBhaXIsIHJpZ2h0UGFpcikge1xuICAgICAgICAgICAgbGV0IGNoZWNrVmFsdWUgPSAobGVmdFBhaXIuZ2V0Q2hlY2tzdW1Qb3J0aW9uKCkgKyAxNiAqIHJpZ2h0UGFpci5nZXRDaGVja3N1bVBvcnRpb24oKSkgJSA3OTtcbiAgICAgICAgICAgIGxldCB0YXJnZXRDaGVja1ZhbHVlID0gOSAqIGxlZnRQYWlyLmdldEZpbmRlclBhdHRlcm4oKS5nZXRWYWx1ZSgpICsgcmlnaHRQYWlyLmdldEZpbmRlclBhdHRlcm4oKS5nZXRWYWx1ZSgpO1xuICAgICAgICAgICAgaWYgKHRhcmdldENoZWNrVmFsdWUgPiA3Mikge1xuICAgICAgICAgICAgICAgIHRhcmdldENoZWNrVmFsdWUtLTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0YXJnZXRDaGVja1ZhbHVlID4gOCkge1xuICAgICAgICAgICAgICAgIHRhcmdldENoZWNrVmFsdWUtLTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBjaGVja1ZhbHVlID09PSB0YXJnZXRDaGVja1ZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGRlY29kZVBhaXIocm93LCByaWdodCwgcm93TnVtYmVyLCBoaW50cykge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBsZXQgc3RhcnRFbmQgPSB0aGlzLmZpbmRGaW5kZXJQYXR0ZXJuKHJvdywgcmlnaHQpO1xuICAgICAgICAgICAgICAgIGxldCBwYXR0ZXJuID0gdGhpcy5wYXJzZUZvdW5kRmluZGVyUGF0dGVybihyb3csIHJvd051bWJlciwgcmlnaHQsIHN0YXJ0RW5kKTtcbiAgICAgICAgICAgICAgICBsZXQgcmVzdWx0UG9pbnRDYWxsYmFjayA9IGhpbnRzID09IG51bGwgPyBudWxsIDogaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuTkVFRF9SRVNVTFRfUE9JTlRfQ0FMTEJBQ0spO1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHRQb2ludENhbGxiYWNrICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNlbnRlciA9IChzdGFydEVuZFswXSArIHN0YXJ0RW5kWzFdKSAvIDIuMDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyByb3cgaXMgYWN0dWFsbHkgcmV2ZXJzZWRcbiAgICAgICAgICAgICAgICAgICAgICAgIGNlbnRlciA9IHJvdy5nZXRTaXplKCkgLSAxIC0gY2VudGVyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFBvaW50Q2FsbGJhY2suZm91bmRQb3NzaWJsZVJlc3VsdFBvaW50KG5ldyBSZXN1bHRQb2ludChjZW50ZXIsIHJvd051bWJlcikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgb3V0c2lkZSA9IHRoaXMuZGVjb2RlRGF0YUNoYXJhY3Rlcihyb3csIHBhdHRlcm4sIHRydWUpO1xuICAgICAgICAgICAgICAgIGxldCBpbnNpZGUgPSB0aGlzLmRlY29kZURhdGFDaGFyYWN0ZXIocm93LCBwYXR0ZXJuLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBQYWlyKDE1OTcgKiBvdXRzaWRlLmdldFZhbHVlKCkgKyBpbnNpZGUuZ2V0VmFsdWUoKSwgb3V0c2lkZS5nZXRDaGVja3N1bVBvcnRpb24oKSArIDQgKiBpbnNpZGUuZ2V0Q2hlY2tzdW1Qb3J0aW9uKCksIHBhdHRlcm4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGRlY29kZURhdGFDaGFyYWN0ZXIocm93LCBwYXR0ZXJuLCBvdXRzaWRlQ2hhcikge1xuICAgICAgICAgICAgbGV0IGNvdW50ZXJzID0gdGhpcy5nZXREYXRhQ2hhcmFjdGVyQ291bnRlcnMoKTtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgY291bnRlcnMubGVuZ3RoOyB4KyspIHtcbiAgICAgICAgICAgICAgICBjb3VudGVyc1t4XSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob3V0c2lkZUNoYXIpIHtcbiAgICAgICAgICAgICAgICBPbmVEUmVhZGVyLnJlY29yZFBhdHRlcm5JblJldmVyc2Uocm93LCBwYXR0ZXJuLmdldFN0YXJ0RW5kKClbMF0sIGNvdW50ZXJzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIE9uZURSZWFkZXIucmVjb3JkUGF0dGVybihyb3csIHBhdHRlcm4uZ2V0U3RhcnRFbmQoKVsxXSArIDEsIGNvdW50ZXJzKTtcbiAgICAgICAgICAgICAgICAvLyByZXZlcnNlIGl0XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGogPSBjb3VudGVycy5sZW5ndGggLSAxOyBpIDwgajsgaSsrLCBqLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHRlbXAgPSBjb3VudGVyc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbaV0gPSBjb3VudGVyc1tqXTtcbiAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbal0gPSB0ZW1wO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBudW1Nb2R1bGVzID0gb3V0c2lkZUNoYXIgPyAxNiA6IDE1O1xuICAgICAgICAgICAgbGV0IGVsZW1lbnRXaWR0aCA9IE1hdGhVdGlscy5zdW0obmV3IEludDMyQXJyYXkoY291bnRlcnMpKSAvIG51bU1vZHVsZXM7XG4gICAgICAgICAgICBsZXQgb2RkQ291bnRzID0gdGhpcy5nZXRPZGRDb3VudHMoKTtcbiAgICAgICAgICAgIGxldCBldmVuQ291bnRzID0gdGhpcy5nZXRFdmVuQ291bnRzKCk7XG4gICAgICAgICAgICBsZXQgb2RkUm91bmRpbmdFcnJvcnMgPSB0aGlzLmdldE9kZFJvdW5kaW5nRXJyb3JzKCk7XG4gICAgICAgICAgICBsZXQgZXZlblJvdW5kaW5nRXJyb3JzID0gdGhpcy5nZXRFdmVuUm91bmRpbmdFcnJvcnMoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnRlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgdmFsdWUgPSBjb3VudGVyc1tpXSAvIGVsZW1lbnRXaWR0aDtcbiAgICAgICAgICAgICAgICBsZXQgY291bnQgPSBNYXRoLmZsb29yKHZhbHVlICsgMC41KTtcbiAgICAgICAgICAgICAgICBpZiAoY291bnQgPCAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ID0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoY291bnQgPiA4KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ID0gODtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IG9mZnNldCA9IE1hdGguZmxvb3IoaSAvIDIpO1xuICAgICAgICAgICAgICAgIGlmICgoaSAmIDB4MDEpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG9kZENvdW50c1tvZmZzZXRdID0gY291bnQ7XG4gICAgICAgICAgICAgICAgICAgIG9kZFJvdW5kaW5nRXJyb3JzW29mZnNldF0gPSB2YWx1ZSAtIGNvdW50O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbkNvdW50c1tvZmZzZXRdID0gY291bnQ7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW5Sb3VuZGluZ0Vycm9yc1tvZmZzZXRdID0gdmFsdWUgLSBjb3VudDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmFkanVzdE9kZEV2ZW5Db3VudHMob3V0c2lkZUNoYXIsIG51bU1vZHVsZXMpO1xuICAgICAgICAgICAgbGV0IG9kZFN1bSA9IDA7XG4gICAgICAgICAgICBsZXQgb2RkQ2hlY2tzdW1Qb3J0aW9uID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBvZGRDb3VudHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgICAgICBvZGRDaGVja3N1bVBvcnRpb24gKj0gOTtcbiAgICAgICAgICAgICAgICBvZGRDaGVja3N1bVBvcnRpb24gKz0gb2RkQ291bnRzW2ldO1xuICAgICAgICAgICAgICAgIG9kZFN1bSArPSBvZGRDb3VudHNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZXZlbkNoZWNrc3VtUG9ydGlvbiA9IDA7XG4gICAgICAgICAgICBsZXQgZXZlblN1bSA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gZXZlbkNvdW50cy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgICAgIGV2ZW5DaGVja3N1bVBvcnRpb24gKj0gOTtcbiAgICAgICAgICAgICAgICBldmVuQ2hlY2tzdW1Qb3J0aW9uICs9IGV2ZW5Db3VudHNbaV07XG4gICAgICAgICAgICAgICAgZXZlblN1bSArPSBldmVuQ291bnRzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGNoZWNrc3VtUG9ydGlvbiA9IG9kZENoZWNrc3VtUG9ydGlvbiArIDMgKiBldmVuQ2hlY2tzdW1Qb3J0aW9uO1xuICAgICAgICAgICAgaWYgKG91dHNpZGVDaGFyKSB7XG4gICAgICAgICAgICAgICAgaWYgKChvZGRTdW0gJiAweDAxKSAhPT0gMCB8fCBvZGRTdW0gPiAxMiB8fCBvZGRTdW0gPCA0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgZ3JvdXAgPSAoMTIgLSBvZGRTdW0pIC8gMjtcbiAgICAgICAgICAgICAgICBsZXQgb2RkV2lkZXN0ID0gUlNTMTRSZWFkZXIuT1VUU0lERV9PRERfV0lERVNUW2dyb3VwXTtcbiAgICAgICAgICAgICAgICBsZXQgZXZlbldpZGVzdCA9IDkgLSBvZGRXaWRlc3Q7XG4gICAgICAgICAgICAgICAgbGV0IHZPZGQgPSBSU1NVdGlscy5nZXRSU1N2YWx1ZShvZGRDb3VudHMsIG9kZFdpZGVzdCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIGxldCB2RXZlbiA9IFJTU1V0aWxzLmdldFJTU3ZhbHVlKGV2ZW5Db3VudHMsIGV2ZW5XaWRlc3QsIHRydWUpO1xuICAgICAgICAgICAgICAgIGxldCB0RXZlbiA9IFJTUzE0UmVhZGVyLk9VVFNJREVfRVZFTl9UT1RBTF9TVUJTRVRbZ3JvdXBdO1xuICAgICAgICAgICAgICAgIGxldCBnU3VtID0gUlNTMTRSZWFkZXIuT1VUU0lERV9HU1VNW2dyb3VwXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERhdGFDaGFyYWN0ZXIodk9kZCAqIHRFdmVuICsgdkV2ZW4gKyBnU3VtLCBjaGVja3N1bVBvcnRpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKChldmVuU3VtICYgMHgwMSkgIT09IDAgfHwgZXZlblN1bSA+IDEwIHx8IGV2ZW5TdW0gPCA0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgZ3JvdXAgPSAoMTAgLSBldmVuU3VtKSAvIDI7XG4gICAgICAgICAgICAgICAgbGV0IG9kZFdpZGVzdCA9IFJTUzE0UmVhZGVyLklOU0lERV9PRERfV0lERVNUW2dyb3VwXTtcbiAgICAgICAgICAgICAgICBsZXQgZXZlbldpZGVzdCA9IDkgLSBvZGRXaWRlc3Q7XG4gICAgICAgICAgICAgICAgbGV0IHZPZGQgPSBSU1NVdGlscy5nZXRSU1N2YWx1ZShvZGRDb3VudHMsIG9kZFdpZGVzdCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgbGV0IHZFdmVuID0gUlNTVXRpbHMuZ2V0UlNTdmFsdWUoZXZlbkNvdW50cywgZXZlbldpZGVzdCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIGxldCB0T2RkID0gUlNTMTRSZWFkZXIuSU5TSURFX09ERF9UT1RBTF9TVUJTRVRbZ3JvdXBdO1xuICAgICAgICAgICAgICAgIGxldCBnU3VtID0gUlNTMTRSZWFkZXIuSU5TSURFX0dTVU1bZ3JvdXBdO1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRGF0YUNoYXJhY3Rlcih2RXZlbiAqIHRPZGQgKyB2T2RkICsgZ1N1bSwgY2hlY2tzdW1Qb3J0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmaW5kRmluZGVyUGF0dGVybihyb3csIHJpZ2h0RmluZGVyUGF0dGVybikge1xuICAgICAgICAgICAgbGV0IGNvdW50ZXJzID0gdGhpcy5nZXREZWNvZGVGaW5kZXJDb3VudGVycygpO1xuICAgICAgICAgICAgY291bnRlcnNbMF0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbMV0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbMl0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbM10gPSAwO1xuICAgICAgICAgICAgbGV0IHdpZHRoID0gcm93LmdldFNpemUoKTtcbiAgICAgICAgICAgIGxldCBpc1doaXRlID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgcm93T2Zmc2V0ID0gMDtcbiAgICAgICAgICAgIHdoaWxlIChyb3dPZmZzZXQgPCB3aWR0aCkge1xuICAgICAgICAgICAgICAgIGlzV2hpdGUgPSAhcm93LmdldChyb3dPZmZzZXQpO1xuICAgICAgICAgICAgICAgIGlmIChyaWdodEZpbmRlclBhdHRlcm4gPT09IGlzV2hpdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gV2lsbCBlbmNvdW50ZXIgd2hpdGUgZmlyc3Qgd2hlbiBzZWFyY2hpbmcgZm9yIHJpZ2h0IGZpbmRlciBwYXR0ZXJuXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByb3dPZmZzZXQrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBjb3VudGVyUG9zaXRpb24gPSAwO1xuICAgICAgICAgICAgbGV0IHBhdHRlcm5TdGFydCA9IHJvd09mZnNldDtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSByb3dPZmZzZXQ7IHggPCB3aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJvdy5nZXQoeCkgIT09IGlzV2hpdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbY291bnRlclBvc2l0aW9uXSsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvdW50ZXJQb3NpdGlvbiA9PT0gMykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEFic3RyYWN0UlNTUmVhZGVyLmlzRmluZGVyUGF0dGVybihjb3VudGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gW3BhdHRlcm5TdGFydCwgeF07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuU3RhcnQgKz0gY291bnRlcnNbMF0gKyBjb3VudGVyc1sxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzWzBdID0gY291bnRlcnNbMl07XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1sxXSA9IGNvdW50ZXJzWzNdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbMl0gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbM10gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlclBvc2l0aW9uLS07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyUG9zaXRpb24rKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb25dID0gMTtcbiAgICAgICAgICAgICAgICAgICAgaXNXaGl0ZSA9ICFpc1doaXRlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIHBhcnNlRm91bmRGaW5kZXJQYXR0ZXJuKHJvdywgcm93TnVtYmVyLCByaWdodCwgc3RhcnRFbmQpIHtcbiAgICAgICAgICAgIC8vIEFjdHVhbGx5IHdlIGZvdW5kIGVsZW1lbnRzIDItNVxuICAgICAgICAgICAgbGV0IGZpcnN0SXNCbGFjayA9IHJvdy5nZXQoc3RhcnRFbmRbMF0pO1xuICAgICAgICAgICAgbGV0IGZpcnN0RWxlbWVudFN0YXJ0ID0gc3RhcnRFbmRbMF0gLSAxO1xuICAgICAgICAgICAgLy8gTG9jYXRlIGVsZW1lbnQgMVxuICAgICAgICAgICAgd2hpbGUgKGZpcnN0RWxlbWVudFN0YXJ0ID49IDAgJiYgZmlyc3RJc0JsYWNrICE9PSByb3cuZ2V0KGZpcnN0RWxlbWVudFN0YXJ0KSkge1xuICAgICAgICAgICAgICAgIGZpcnN0RWxlbWVudFN0YXJ0LS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmaXJzdEVsZW1lbnRTdGFydCsrO1xuICAgICAgICAgICAgY29uc3QgZmlyc3RDb3VudGVyID0gc3RhcnRFbmRbMF0gLSBmaXJzdEVsZW1lbnRTdGFydDtcbiAgICAgICAgICAgIC8vIE1ha2UgJ2NvdW50ZXJzJyBob2xkIDEtNFxuICAgICAgICAgICAgY29uc3QgY291bnRlcnMgPSB0aGlzLmdldERlY29kZUZpbmRlckNvdW50ZXJzKCk7XG4gICAgICAgICAgICBjb25zdCBjb3B5ID0gbmV3IEludDMyQXJyYXkoY291bnRlcnMubGVuZ3RoKTtcbiAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkoY291bnRlcnMsIDAsIGNvcHksIDEsIGNvdW50ZXJzLmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgY29weVswXSA9IGZpcnN0Q291bnRlcjtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5wYXJzZUZpbmRlclZhbHVlKGNvcHksIFJTUzE0UmVhZGVyLkZJTkRFUl9QQVRURVJOUyk7XG4gICAgICAgICAgICBsZXQgc3RhcnQgPSBmaXJzdEVsZW1lbnRTdGFydDtcbiAgICAgICAgICAgIGxldCBlbmQgPSBzdGFydEVuZFsxXTtcbiAgICAgICAgICAgIGlmIChyaWdodCkge1xuICAgICAgICAgICAgICAgIC8vIHJvdyBpcyBhY3R1YWxseSByZXZlcnNlZFxuICAgICAgICAgICAgICAgIHN0YXJ0ID0gcm93LmdldFNpemUoKSAtIDEgLSBzdGFydDtcbiAgICAgICAgICAgICAgICBlbmQgPSByb3cuZ2V0U2l6ZSgpIC0gMSAtIGVuZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgRmluZGVyUGF0dGVybih2YWx1ZSwgW2ZpcnN0RWxlbWVudFN0YXJ0LCBzdGFydEVuZFsxXV0sIHN0YXJ0LCBlbmQsIHJvd051bWJlcik7XG4gICAgICAgIH1cbiAgICAgICAgYWRqdXN0T2RkRXZlbkNvdW50cyhvdXRzaWRlQ2hhciwgbnVtTW9kdWxlcykge1xuICAgICAgICAgICAgbGV0IG9kZFN1bSA9IE1hdGhVdGlscy5zdW0obmV3IEludDMyQXJyYXkodGhpcy5nZXRPZGRDb3VudHMoKSkpO1xuICAgICAgICAgICAgbGV0IGV2ZW5TdW0gPSBNYXRoVXRpbHMuc3VtKG5ldyBJbnQzMkFycmF5KHRoaXMuZ2V0RXZlbkNvdW50cygpKSk7XG4gICAgICAgICAgICBsZXQgaW5jcmVtZW50T2RkID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgZGVjcmVtZW50T2RkID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgaW5jcmVtZW50RXZlbiA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGRlY3JlbWVudEV2ZW4gPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChvdXRzaWRlQ2hhcikge1xuICAgICAgICAgICAgICAgIGlmIChvZGRTdW0gPiAxMikge1xuICAgICAgICAgICAgICAgICAgICBkZWNyZW1lbnRPZGQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChvZGRTdW0gPCA0KSB7XG4gICAgICAgICAgICAgICAgICAgIGluY3JlbWVudE9kZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChldmVuU3VtID4gMTIpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVjcmVtZW50RXZlbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGV2ZW5TdW0gPCA0KSB7XG4gICAgICAgICAgICAgICAgICAgIGluY3JlbWVudEV2ZW4gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChvZGRTdW0gPiAxMSkge1xuICAgICAgICAgICAgICAgICAgICBkZWNyZW1lbnRPZGQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChvZGRTdW0gPCA1KSB7XG4gICAgICAgICAgICAgICAgICAgIGluY3JlbWVudE9kZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChldmVuU3VtID4gMTApIHtcbiAgICAgICAgICAgICAgICAgICAgZGVjcmVtZW50RXZlbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGV2ZW5TdW0gPCA0KSB7XG4gICAgICAgICAgICAgICAgICAgIGluY3JlbWVudEV2ZW4gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBtaXNtYXRjaCA9IG9kZFN1bSArIGV2ZW5TdW0gLSBudW1Nb2R1bGVzO1xuICAgICAgICAgICAgbGV0IG9kZFBhcml0eUJhZCA9IChvZGRTdW0gJiAweDAxKSA9PT0gKG91dHNpZGVDaGFyID8gMSA6IDApO1xuICAgICAgICAgICAgbGV0IGV2ZW5QYXJpdHlCYWQgPSAoZXZlblN1bSAmIDB4MDEpID09PSAxO1xuICAgICAgICAgICAgaWYgKG1pc21hdGNoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9kZFBhcml0eUJhZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXZlblBhcml0eUJhZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZGVjcmVtZW50T2RkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZXZlblBhcml0eUJhZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZGVjcmVtZW50RXZlbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAobWlzbWF0Y2ggPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9kZFBhcml0eUJhZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXZlblBhcml0eUJhZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaW5jcmVtZW50T2RkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZXZlblBhcml0eUJhZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaW5jcmVtZW50RXZlbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAobWlzbWF0Y2ggPT09IDApIHtcbiAgICAgICAgICAgICAgICBpZiAob2RkUGFyaXR5QmFkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZXZlblBhcml0eUJhZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gQm90aCBiYWRcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9kZFN1bSA8IGV2ZW5TdW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluY3JlbWVudE9kZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWNyZW1lbnRFdmVuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlY3JlbWVudE9kZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmNyZW1lbnRFdmVuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW5QYXJpdHlCYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIE5vdGhpbmcgdG8gZG8hXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaW5jcmVtZW50T2RkKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRlY3JlbWVudE9kZCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgQWJzdHJhY3RSU1NSZWFkZXIuaW5jcmVtZW50KHRoaXMuZ2V0T2RkQ291bnRzKCksIHRoaXMuZ2V0T2RkUm91bmRpbmdFcnJvcnMoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZGVjcmVtZW50T2RkKSB7XG4gICAgICAgICAgICAgICAgQWJzdHJhY3RSU1NSZWFkZXIuZGVjcmVtZW50KHRoaXMuZ2V0T2RkQ291bnRzKCksIHRoaXMuZ2V0T2RkUm91bmRpbmdFcnJvcnMoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaW5jcmVtZW50RXZlbikge1xuICAgICAgICAgICAgICAgIGlmIChkZWNyZW1lbnRFdmVuKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBBYnN0cmFjdFJTU1JlYWRlci5pbmNyZW1lbnQodGhpcy5nZXRFdmVuQ291bnRzKCksIHRoaXMuZ2V0T2RkUm91bmRpbmdFcnJvcnMoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZGVjcmVtZW50RXZlbikge1xuICAgICAgICAgICAgICAgIEFic3RyYWN0UlNTUmVhZGVyLmRlY3JlbWVudCh0aGlzLmdldEV2ZW5Db3VudHMoKSwgdGhpcy5nZXRFdmVuUm91bmRpbmdFcnJvcnMoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgUlNTMTRSZWFkZXIuT1VUU0lERV9FVkVOX1RPVEFMX1NVQlNFVCA9IFsxLCAxMCwgMzQsIDcwLCAxMjZdO1xuICAgIFJTUzE0UmVhZGVyLklOU0lERV9PRERfVE9UQUxfU1VCU0VUID0gWzQsIDIwLCA0OCwgODFdO1xuICAgIFJTUzE0UmVhZGVyLk9VVFNJREVfR1NVTSA9IFswLCAxNjEsIDk2MSwgMjAxNSwgMjcxNV07XG4gICAgUlNTMTRSZWFkZXIuSU5TSURFX0dTVU0gPSBbMCwgMzM2LCAxMDM2LCAxNTE2XTtcbiAgICBSU1MxNFJlYWRlci5PVVRTSURFX09ERF9XSURFU1QgPSBbOCwgNiwgNCwgMywgMV07XG4gICAgUlNTMTRSZWFkZXIuSU5TSURFX09ERF9XSURFU1QgPSBbMiwgNCwgNiwgOF07XG4gICAgUlNTMTRSZWFkZXIuRklOREVSX1BBVFRFUk5TID0gW1xuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDgsIDIsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCA1LCA1LCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgMywgNywgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDEsIDksIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCA3LCA0LCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgNSwgNiwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDMsIDgsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCA1LCA3LCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMywgOSwgMV0pLFxuICAgIF07XG5cbiAgICAvKipcbiAgICAgKiBAYXV0aG9yIERhbmllbCBTd2l0a2luIDxkc3dpdGtpbkBnb29nbGUuY29tPlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgTXVsdGlGb3JtYXRPbmVEUmVhZGVyIGV4dGVuZHMgT25lRFJlYWRlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGhpbnRzLCB2ZXJib3NlKSB7XG4gICAgICAgICAgICBzdXBlcigpO1xuICAgICAgICAgICAgdGhpcy5yZWFkZXJzID0gW107XG4gICAgICAgICAgICB0aGlzLnZlcmJvc2UgPSAodmVyYm9zZSA9PT0gdHJ1ZSk7XG4gICAgICAgICAgICBjb25zdCBwb3NzaWJsZUZvcm1hdHMgPSAhaGludHMgPyBudWxsIDogaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuUE9TU0lCTEVfRk9STUFUUyk7XG4gICAgICAgICAgICBjb25zdCB1c2VDb2RlMzlDaGVja0RpZ2l0ID0gaGludHMgJiYgaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuQVNTVU1FX0NPREVfMzlfQ0hFQ0tfRElHSVQpICE9PSB1bmRlZmluZWQ7XG4gICAgICAgICAgICBpZiAocG9zc2libGVGb3JtYXRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHBvc3NpYmxlRm9ybWF0cy5pbmNsdWRlcyhCYXJjb2RlRm9ybWF0JDEuRUFOXzEzKSB8fFxuICAgICAgICAgICAgICAgICAgICBwb3NzaWJsZUZvcm1hdHMuaW5jbHVkZXMoQmFyY29kZUZvcm1hdCQxLlVQQ19BKSB8fFxuICAgICAgICAgICAgICAgICAgICBwb3NzaWJsZUZvcm1hdHMuaW5jbHVkZXMoQmFyY29kZUZvcm1hdCQxLkVBTl84KSB8fFxuICAgICAgICAgICAgICAgICAgICBwb3NzaWJsZUZvcm1hdHMuaW5jbHVkZXMoQmFyY29kZUZvcm1hdCQxLlVQQ19FKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlYWRlcnMucHVzaChuZXcgTXVsdGlGb3JtYXRVUENFQU5SZWFkZXIoaGludHMpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHBvc3NpYmxlRm9ybWF0cy5pbmNsdWRlcyhCYXJjb2RlRm9ybWF0JDEuQ09ERV8zOSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWFkZXJzLnB1c2gobmV3IENvZGUzOVJlYWRlcih1c2VDb2RlMzlDaGVja0RpZ2l0KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGlmIChwb3NzaWJsZUZvcm1hdHMuaW5jbHVkZXMoQmFyY29kZUZvcm1hdC5DT0RFXzkzKSkge1xuICAgICAgICAgICAgICAgIC8vICAgIHRoaXMucmVhZGVycy5wdXNoKG5ldyBDb2RlOTNSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgLy8gfVxuICAgICAgICAgICAgICAgIGlmIChwb3NzaWJsZUZvcm1hdHMuaW5jbHVkZXMoQmFyY29kZUZvcm1hdCQxLkNPREVfMTI4KSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlYWRlcnMucHVzaChuZXcgQ29kZTEyOFJlYWRlcigpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHBvc3NpYmxlRm9ybWF0cy5pbmNsdWRlcyhCYXJjb2RlRm9ybWF0JDEuSVRGKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlYWRlcnMucHVzaChuZXcgSVRGUmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBpZiAocG9zc2libGVGb3JtYXRzLmluY2x1ZGVzKEJhcmNvZGVGb3JtYXQuQ09EQUJBUikpIHtcbiAgICAgICAgICAgICAgICAvLyAgICB0aGlzLnJlYWRlcnMucHVzaChuZXcgQ29kYUJhclJlYWRlcigpKTtcbiAgICAgICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICAgICAgaWYgKHBvc3NpYmxlRm9ybWF0cy5pbmNsdWRlcyhCYXJjb2RlRm9ybWF0JDEuUlNTXzE0KSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlYWRlcnMucHVzaChuZXcgUlNTMTRSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChwb3NzaWJsZUZvcm1hdHMuaW5jbHVkZXMoQmFyY29kZUZvcm1hdCQxLlJTU19FWFBBTkRFRCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWFkZXJzLnB1c2gobmV3IFJTU0V4cGFuZGVkUmVhZGVyKHRoaXMudmVyYm9zZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gQ2FzZSB3aGVuIG5vIGhpbnRzIHdlcmUgcHJvdmlkZWQgLT4gYWRkIGFsbC5cbiAgICAgICAgICAgICAgICB0aGlzLnJlYWRlcnMucHVzaChuZXcgTXVsdGlGb3JtYXRVUENFQU5SZWFkZXIoaGludHMpKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlYWRlcnMucHVzaChuZXcgQ29kZTM5UmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIC8vIHRoaXMucmVhZGVycy5wdXNoKG5ldyBDb2RhQmFyUmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIC8vIHRoaXMucmVhZGVycy5wdXNoKG5ldyBDb2RlOTNSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFkZXJzLnB1c2gobmV3IE11bHRpRm9ybWF0VVBDRUFOUmVhZGVyKGhpbnRzKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFkZXJzLnB1c2gobmV3IENvZGUxMjhSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFkZXJzLnB1c2gobmV3IElURlJlYWRlcigpKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlYWRlcnMucHVzaChuZXcgUlNTMTRSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFkZXJzLnB1c2gobmV3IFJTU0V4cGFuZGVkUmVhZGVyKHRoaXMudmVyYm9zZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIEBPdmVycmlkZVxuICAgICAgICBkZWNvZGVSb3cocm93TnVtYmVyLCByb3csIGhpbnRzKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMucmVhZGVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJlYWRlcnNbaV0uZGVjb2RlUm93KHJvd051bWJlciwgcm93LCBoaW50cyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChyZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBjb250aW51ZVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEBPdmVycmlkZVxuICAgICAgICByZXNldCgpIHtcbiAgICAgICAgICAgIHRoaXMucmVhZGVycy5mb3JFYWNoKHJlYWRlciA9PiByZWFkZXIucmVzZXQoKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAZGVwcmVjYXRlZCBNb3ZpbmcgdG8gQHp4aW5nL2Jyb3dzZXJcbiAgICAgKlxuICAgICAqIEJhcmNvZGUgcmVhZGVyIHJlYWRlciB0byB1c2UgZnJvbSBicm93c2VyLlxuICAgICAqL1xuICAgIGNsYXNzIEJyb3dzZXJCYXJjb2RlUmVhZGVyIGV4dGVuZHMgQnJvd3NlckNvZGVSZWFkZXIge1xuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBCcm93c2VyQmFyY29kZVJlYWRlci5cbiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IFt0aW1lQmV0d2VlblNjYW5zTWlsbGlzPTUwMF0gdGhlIHRpbWUgZGVsYXkgYmV0d2VlbiBzdWJzZXF1ZW50IGRlY29kZSB0cmllc1xuICAgICAgICAgKiBAcGFyYW0ge01hcDxEZWNvZGVIaW50VHlwZSwgYW55Pn0gaGludHNcbiAgICAgICAgICovXG4gICAgICAgIGNvbnN0cnVjdG9yKHRpbWVCZXR3ZWVuU2NhbnNNaWxsaXMgPSA1MDAsIGhpbnRzKSB7XG4gICAgICAgICAgICBzdXBlcihuZXcgTXVsdGlGb3JtYXRPbmVEUmVhZGVyKGhpbnRzKSwgdGltZUJldHdlZW5TY2Fuc01pbGxpcywgaGludHMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiA8cD5FbmNhcHN1bGF0ZXMgYSBzZXQgb2YgZXJyb3ItY29ycmVjdGlvbiBibG9ja3MgaW4gb25lIHN5bWJvbCB2ZXJzaW9uLiBNb3N0IHZlcnNpb25zIHdpbGxcbiAgICAgKiB1c2UgYmxvY2tzIG9mIGRpZmZlcmluZyBzaXplcyB3aXRoaW4gb25lIHZlcnNpb24sIHNvLCB0aGlzIGVuY2Fwc3VsYXRlcyB0aGUgcGFyYW1ldGVycyBmb3JcbiAgICAgKiBlYWNoIHNldCBvZiBibG9ja3MuIEl0IGFsc28gaG9sZHMgdGhlIG51bWJlciBvZiBlcnJvci1jb3JyZWN0aW9uIGNvZGV3b3JkcyBwZXIgYmxvY2sgc2luY2UgaXRcbiAgICAgKiB3aWxsIGJlIHRoZSBzYW1lIGFjcm9zcyBhbGwgYmxvY2tzIHdpdGhpbiBvbmUgdmVyc2lvbi48L3A+XG4gICAgICovXG4gICAgY2xhc3MgRUNCbG9ja3Mge1xuICAgICAgICBjb25zdHJ1Y3RvcihlY0NvZGV3b3JkcywgZWNCbG9ja3MxLCBlY0Jsb2NrczIpIHtcbiAgICAgICAgICAgIHRoaXMuZWNDb2Rld29yZHMgPSBlY0NvZGV3b3JkcztcbiAgICAgICAgICAgIHRoaXMuZWNCbG9ja3MgPSBbZWNCbG9ja3MxXTtcbiAgICAgICAgICAgIGVjQmxvY2tzMiAmJiB0aGlzLmVjQmxvY2tzLnB1c2goZWNCbG9ja3MyKTtcbiAgICAgICAgfVxuICAgICAgICBnZXRFQ0NvZGV3b3JkcygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVjQ29kZXdvcmRzO1xuICAgICAgICB9XG4gICAgICAgIGdldEVDQmxvY2tzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWNCbG9ja3M7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogPHA+RW5jYXBzdWxhdGVzIHRoZSBwYXJhbWV0ZXJzIGZvciBvbmUgZXJyb3ItY29ycmVjdGlvbiBibG9jayBpbiBvbmUgc3ltYm9sIHZlcnNpb24uXG4gICAgICogVGhpcyBpbmNsdWRlcyB0aGUgbnVtYmVyIG9mIGRhdGEgY29kZXdvcmRzLCBhbmQgdGhlIG51bWJlciBvZiB0aW1lcyBhIGJsb2NrIHdpdGggdGhlc2VcbiAgICAgKiBwYXJhbWV0ZXJzIGlzIHVzZWQgY29uc2VjdXRpdmVseSBpbiB0aGUgRGF0YSBNYXRyaXggY29kZSB2ZXJzaW9uJ3MgZm9ybWF0LjwvcD5cbiAgICAgKi9cbiAgICBjbGFzcyBFQ0Ige1xuICAgICAgICBjb25zdHJ1Y3Rvcihjb3VudCwgZGF0YUNvZGV3b3Jkcykge1xuICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50O1xuICAgICAgICAgICAgdGhpcy5kYXRhQ29kZXdvcmRzID0gZGF0YUNvZGV3b3JkcztcbiAgICAgICAgfVxuICAgICAgICBnZXRDb3VudCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvdW50O1xuICAgICAgICB9XG4gICAgICAgIGdldERhdGFDb2Rld29yZHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRhQ29kZXdvcmRzO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoZSBWZXJzaW9uIG9iamVjdCBlbmNhcHN1bGF0ZXMgYXR0cmlidXRlcyBhYm91dCBhIHBhcnRpY3VsYXJcbiAgICAgKiBzaXplIERhdGEgTWF0cml4IENvZGUuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIGJicm93bkBnb29nbGUuY29tIChCcmlhbiBCcm93bilcbiAgICAgKi9cbiAgICBjbGFzcyBWZXJzaW9uIHtcbiAgICAgICAgY29uc3RydWN0b3IodmVyc2lvbk51bWJlciwgc3ltYm9sU2l6ZVJvd3MsIHN5bWJvbFNpemVDb2x1bW5zLCBkYXRhUmVnaW9uU2l6ZVJvd3MsIGRhdGFSZWdpb25TaXplQ29sdW1ucywgZWNCbG9ja3MpIHtcbiAgICAgICAgICAgIHRoaXMudmVyc2lvbk51bWJlciA9IHZlcnNpb25OdW1iZXI7XG4gICAgICAgICAgICB0aGlzLnN5bWJvbFNpemVSb3dzID0gc3ltYm9sU2l6ZVJvd3M7XG4gICAgICAgICAgICB0aGlzLnN5bWJvbFNpemVDb2x1bW5zID0gc3ltYm9sU2l6ZUNvbHVtbnM7XG4gICAgICAgICAgICB0aGlzLmRhdGFSZWdpb25TaXplUm93cyA9IGRhdGFSZWdpb25TaXplUm93cztcbiAgICAgICAgICAgIHRoaXMuZGF0YVJlZ2lvblNpemVDb2x1bW5zID0gZGF0YVJlZ2lvblNpemVDb2x1bW5zO1xuICAgICAgICAgICAgdGhpcy5lY0Jsb2NrcyA9IGVjQmxvY2tzO1xuICAgICAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSB0b3RhbCBudW1iZXIgb2YgY29kZXdvcmRzXG4gICAgICAgICAgICBsZXQgdG90YWwgPSAwO1xuICAgICAgICAgICAgY29uc3QgZWNDb2Rld29yZHMgPSBlY0Jsb2Nrcy5nZXRFQ0NvZGV3b3JkcygpO1xuICAgICAgICAgICAgY29uc3QgZWNiQXJyYXkgPSBlY0Jsb2Nrcy5nZXRFQ0Jsb2NrcygpO1xuICAgICAgICAgICAgZm9yIChsZXQgZWNCbG9jayBvZiBlY2JBcnJheSkge1xuICAgICAgICAgICAgICAgIHRvdGFsICs9IGVjQmxvY2suZ2V0Q291bnQoKSAqIChlY0Jsb2NrLmdldERhdGFDb2Rld29yZHMoKSArIGVjQ29kZXdvcmRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudG90YWxDb2Rld29yZHMgPSB0b3RhbDtcbiAgICAgICAgfVxuICAgICAgICBnZXRWZXJzaW9uTnVtYmVyKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmVyc2lvbk51bWJlcjtcbiAgICAgICAgfVxuICAgICAgICBnZXRTeW1ib2xTaXplUm93cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN5bWJvbFNpemVSb3dzO1xuICAgICAgICB9XG4gICAgICAgIGdldFN5bWJvbFNpemVDb2x1bW5zKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3ltYm9sU2l6ZUNvbHVtbnM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RGF0YVJlZ2lvblNpemVSb3dzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0YVJlZ2lvblNpemVSb3dzO1xuICAgICAgICB9XG4gICAgICAgIGdldERhdGFSZWdpb25TaXplQ29sdW1ucygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGFSZWdpb25TaXplQ29sdW1ucztcbiAgICAgICAgfVxuICAgICAgICBnZXRUb3RhbENvZGV3b3JkcygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRvdGFsQ29kZXdvcmRzO1xuICAgICAgICB9XG4gICAgICAgIGdldEVDQmxvY2tzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWNCbG9ja3M7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkRlZHVjZXMgdmVyc2lvbiBpbmZvcm1hdGlvbiBmcm9tIERhdGEgTWF0cml4IGRpbWVuc2lvbnMuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gbnVtUm93cyBOdW1iZXIgb2Ygcm93cyBpbiBtb2R1bGVzXG4gICAgICAgICAqIEBwYXJhbSBudW1Db2x1bW5zIE51bWJlciBvZiBjb2x1bW5zIGluIG1vZHVsZXNcbiAgICAgICAgICogQHJldHVybiBWZXJzaW9uIGZvciBhIERhdGEgTWF0cml4IENvZGUgb2YgdGhvc2UgZGltZW5zaW9uc1xuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvbiBpZiBkaW1lbnNpb25zIGRvIGNvcnJlc3BvbmQgdG8gYSB2YWxpZCBEYXRhIE1hdHJpeCBzaXplXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZ2V0VmVyc2lvbkZvckRpbWVuc2lvbnMobnVtUm93cywgbnVtQ29sdW1ucykge1xuICAgICAgICAgICAgaWYgKChudW1Sb3dzICYgMHgwMSkgIT09IDAgfHwgKG51bUNvbHVtbnMgJiAweDAxKSAhPT0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAobGV0IHZlcnNpb24gb2YgVmVyc2lvbi5WRVJTSU9OUykge1xuICAgICAgICAgICAgICAgIGlmICh2ZXJzaW9uLnN5bWJvbFNpemVSb3dzID09PSBudW1Sb3dzICYmIHZlcnNpb24uc3ltYm9sU2l6ZUNvbHVtbnMgPT09IG51bUNvbHVtbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZlcnNpb247XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIC8vICBAT3ZlcnJpZGVcbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICByZXR1cm4gJycgKyB0aGlzLnZlcnNpb25OdW1iZXI7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNlZSBJU08gMTYwMjI6MjAwNiA1LjUuMSBUYWJsZSA3XG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgYnVpbGRWZXJzaW9ucygpIHtcbiAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oMSwgMTAsIDEwLCA4LCA4LCBuZXcgRUNCbG9ja3MoNSwgbmV3IEVDQigxLCAzKSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDIsIDEyLCAxMiwgMTAsIDEwLCBuZXcgRUNCbG9ja3MoNywgbmV3IEVDQigxLCA1KSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDMsIDE0LCAxNCwgMTIsIDEyLCBuZXcgRUNCbG9ja3MoMTAsIG5ldyBFQ0IoMSwgOCkpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbig0LCAxNiwgMTYsIDE0LCAxNCwgbmV3IEVDQmxvY2tzKDEyLCBuZXcgRUNCKDEsIDEyKSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDUsIDE4LCAxOCwgMTYsIDE2LCBuZXcgRUNCbG9ja3MoMTQsIG5ldyBFQ0IoMSwgMTgpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oNiwgMjAsIDIwLCAxOCwgMTgsIG5ldyBFQ0Jsb2NrcygxOCwgbmV3IEVDQigxLCAyMikpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbig3LCAyMiwgMjIsIDIwLCAyMCwgbmV3IEVDQmxvY2tzKDIwLCBuZXcgRUNCKDEsIDMwKSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDgsIDI0LCAyNCwgMjIsIDIyLCBuZXcgRUNCbG9ja3MoMjQsIG5ldyBFQ0IoMSwgMzYpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oOSwgMjYsIDI2LCAyNCwgMjQsIG5ldyBFQ0Jsb2NrcygyOCwgbmV3IEVDQigxLCA0NCkpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbigxMCwgMzIsIDMyLCAxNCwgMTQsIG5ldyBFQ0Jsb2NrcygzNiwgbmV3IEVDQigxLCA2MikpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbigxMSwgMzYsIDM2LCAxNiwgMTYsIG5ldyBFQ0Jsb2Nrcyg0MiwgbmV3IEVDQigxLCA4NikpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbigxMiwgNDAsIDQwLCAxOCwgMTgsIG5ldyBFQ0Jsb2Nrcyg0OCwgbmV3IEVDQigxLCAxMTQpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oMTMsIDQ0LCA0NCwgMjAsIDIwLCBuZXcgRUNCbG9ja3MoNTYsIG5ldyBFQ0IoMSwgMTQ0KSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDE0LCA0OCwgNDgsIDIyLCAyMiwgbmV3IEVDQmxvY2tzKDY4LCBuZXcgRUNCKDEsIDE3NCkpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbigxNSwgNTIsIDUyLCAyNCwgMjQsIG5ldyBFQ0Jsb2Nrcyg0MiwgbmV3IEVDQigyLCAxMDIpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oMTYsIDY0LCA2NCwgMTQsIDE0LCBuZXcgRUNCbG9ja3MoNTYsIG5ldyBFQ0IoMiwgMTQwKSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDE3LCA3MiwgNzIsIDE2LCAxNiwgbmV3IEVDQmxvY2tzKDM2LCBuZXcgRUNCKDQsIDkyKSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDE4LCA4MCwgODAsIDE4LCAxOCwgbmV3IEVDQmxvY2tzKDQ4LCBuZXcgRUNCKDQsIDExNCkpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbigxOSwgODgsIDg4LCAyMCwgMjAsIG5ldyBFQ0Jsb2Nrcyg1NiwgbmV3IEVDQig0LCAxNDQpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oMjAsIDk2LCA5NiwgMjIsIDIyLCBuZXcgRUNCbG9ja3MoNjgsIG5ldyBFQ0IoNCwgMTc0KSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDIxLCAxMDQsIDEwNCwgMjQsIDI0LCBuZXcgRUNCbG9ja3MoNTYsIG5ldyBFQ0IoNiwgMTM2KSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDIyLCAxMjAsIDEyMCwgMTgsIDE4LCBuZXcgRUNCbG9ja3MoNjgsIG5ldyBFQ0IoNiwgMTc1KSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDIzLCAxMzIsIDEzMiwgMjAsIDIwLCBuZXcgRUNCbG9ja3MoNjIsIG5ldyBFQ0IoOCwgMTYzKSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDI0LCAxNDQsIDE0NCwgMjIsIDIyLCBuZXcgRUNCbG9ja3MoNjIsIG5ldyBFQ0IoOCwgMTU2KSwgbmV3IEVDQigyLCAxNTUpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oMjUsIDgsIDE4LCA2LCAxNiwgbmV3IEVDQmxvY2tzKDcsIG5ldyBFQ0IoMSwgNSkpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbigyNiwgOCwgMzIsIDYsIDE0LCBuZXcgRUNCbG9ja3MoMTEsIG5ldyBFQ0IoMSwgMTApKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oMjcsIDEyLCAyNiwgMTAsIDI0LCBuZXcgRUNCbG9ja3MoMTQsIG5ldyBFQ0IoMSwgMTYpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oMjgsIDEyLCAzNiwgMTAsIDE2LCBuZXcgRUNCbG9ja3MoMTgsIG5ldyBFQ0IoMSwgMjIpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oMjksIDE2LCAzNiwgMTQsIDE2LCBuZXcgRUNCbG9ja3MoMjQsIG5ldyBFQ0IoMSwgMzIpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oMzAsIDE2LCA0OCwgMTQsIDIyLCBuZXcgRUNCbG9ja3MoMjgsIG5ldyBFQ0IoMSwgNDkpKSlcbiAgICAgICAgICAgIF07XG4gICAgICAgIH1cbiAgICB9XG4gICAgVmVyc2lvbi5WRVJTSU9OUyA9IFZlcnNpb24uYnVpbGRWZXJzaW9ucygpO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiBAYXV0aG9yIGJicm93bkBnb29nbGUuY29tIChCcmlhbiBCcm93bilcbiAgICAgKi9cbiAgICBjbGFzcyBCaXRNYXRyaXhQYXJzZXIge1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIGJpdE1hdHJpeCB7QGxpbmsgQml0TWF0cml4fSB0byBwYXJzZVxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvbiBpZiBkaW1lbnNpb24gaXMgPCA4IG9yID4gMTQ0IG9yIG5vdCAwIG1vZCAyXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3RvcihiaXRNYXRyaXgpIHtcbiAgICAgICAgICAgIGNvbnN0IGRpbWVuc2lvbiA9IGJpdE1hdHJpeC5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGlmIChkaW1lbnNpb24gPCA4IHx8IGRpbWVuc2lvbiA+IDE0NCB8fCAoZGltZW5zaW9uICYgMHgwMSkgIT09IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnZlcnNpb24gPSBCaXRNYXRyaXhQYXJzZXIucmVhZFZlcnNpb24oYml0TWF0cml4KTtcbiAgICAgICAgICAgIHRoaXMubWFwcGluZ0JpdE1hdHJpeCA9IHRoaXMuZXh0cmFjdERhdGFSZWdpb24oYml0TWF0cml4KTtcbiAgICAgICAgICAgIHRoaXMucmVhZE1hcHBpbmdNYXRyaXggPSBuZXcgQml0TWF0cml4KHRoaXMubWFwcGluZ0JpdE1hdHJpeC5nZXRXaWR0aCgpLCB0aGlzLm1hcHBpbmdCaXRNYXRyaXguZ2V0SGVpZ2h0KCkpO1xuICAgICAgICB9XG4gICAgICAgIGdldFZlcnNpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52ZXJzaW9uO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5DcmVhdGVzIHRoZSB2ZXJzaW9uIG9iamVjdCBiYXNlZCBvbiB0aGUgZGltZW5zaW9uIG9mIHRoZSBvcmlnaW5hbCBiaXQgbWF0cml4IGZyb21cbiAgICAgICAgICogdGhlIGRhdGFtYXRyaXggY29kZS48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIDxwPlNlZSBJU08gMTYwMjI6MjAwNiBUYWJsZSA3IC0gRUNDIDIwMCBzeW1ib2wgYXR0cmlidXRlczwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGJpdE1hdHJpeCBPcmlnaW5hbCB7QGxpbmsgQml0TWF0cml4fSBpbmNsdWRpbmcgYWxpZ25tZW50IHBhdHRlcm5zXG4gICAgICAgICAqIEByZXR1cm4ge0BsaW5rIFZlcnNpb259IGVuY2Fwc3VsYXRpbmcgdGhlIERhdGEgTWF0cml4IENvZGUncyBcInZlcnNpb25cIlxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvbiBpZiB0aGUgZGltZW5zaW9ucyBvZiB0aGUgbWFwcGluZyBtYXRyaXggYXJlIG5vdCB2YWxpZFxuICAgICAgICAgKiBEYXRhIE1hdHJpeCBkaW1lbnNpb25zLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIHJlYWRWZXJzaW9uKGJpdE1hdHJpeCkge1xuICAgICAgICAgICAgY29uc3QgbnVtUm93cyA9IGJpdE1hdHJpeC5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IG51bUNvbHVtbnMgPSBiaXRNYXRyaXguZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIHJldHVybiBWZXJzaW9uLmdldFZlcnNpb25Gb3JEaW1lbnNpb25zKG51bVJvd3MsIG51bUNvbHVtbnMpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5SZWFkcyB0aGUgYml0cyBpbiB0aGUge0BsaW5rIEJpdE1hdHJpeH0gcmVwcmVzZW50aW5nIHRoZSBtYXBwaW5nIG1hdHJpeCAoTm8gYWxpZ25tZW50IHBhdHRlcm5zKVxuICAgICAgICAgKiBpbiB0aGUgY29ycmVjdCBvcmRlciBpbiBvcmRlciB0byByZWNvbnN0aXR1dGUgdGhlIGNvZGV3b3JkcyBieXRlcyBjb250YWluZWQgd2l0aGluIHRoZVxuICAgICAgICAgKiBEYXRhIE1hdHJpeCBDb2RlLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiBieXRlcyBlbmNvZGVkIHdpdGhpbiB0aGUgRGF0YSBNYXRyaXggQ29kZVxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvbiBpZiB0aGUgZXhhY3QgbnVtYmVyIG9mIGJ5dGVzIGV4cGVjdGVkIGlzIG5vdCByZWFkXG4gICAgICAgICAqL1xuICAgICAgICByZWFkQ29kZXdvcmRzKCkge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IEludDhBcnJheSh0aGlzLnZlcnNpb24uZ2V0VG90YWxDb2Rld29yZHMoKSk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0T2Zmc2V0ID0gMDtcbiAgICAgICAgICAgIGxldCByb3cgPSA0O1xuICAgICAgICAgICAgbGV0IGNvbHVtbiA9IDA7XG4gICAgICAgICAgICBjb25zdCBudW1Sb3dzID0gdGhpcy5tYXBwaW5nQml0TWF0cml4LmdldEhlaWdodCgpO1xuICAgICAgICAgICAgY29uc3QgbnVtQ29sdW1ucyA9IHRoaXMubWFwcGluZ0JpdE1hdHJpeC5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgbGV0IGNvcm5lcjFSZWFkID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgY29ybmVyMlJlYWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGxldCBjb3JuZXIzUmVhZCA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGNvcm5lcjRSZWFkID0gZmFsc2U7XG4gICAgICAgICAgICAvLyBSZWFkIGFsbCBvZiB0aGUgY29kZXdvcmRzXG4gICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgdGhlIGZvdXIgY29ybmVyIGNhc2VzXG4gICAgICAgICAgICAgICAgaWYgKChyb3cgPT09IG51bVJvd3MpICYmIChjb2x1bW4gPT09IDApICYmICFjb3JuZXIxUmVhZCkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRbcmVzdWx0T2Zmc2V0KytdID0gdGhpcy5yZWFkQ29ybmVyMShudW1Sb3dzLCBudW1Db2x1bW5zKSAmIDB4ZmY7XG4gICAgICAgICAgICAgICAgICAgIHJvdyAtPSAyO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW4gKz0gMjtcbiAgICAgICAgICAgICAgICAgICAgY29ybmVyMVJlYWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICgocm93ID09PSBudW1Sb3dzIC0gMikgJiYgKGNvbHVtbiA9PT0gMCkgJiYgKChudW1Db2x1bW5zICYgMHgwMykgIT09IDApICYmICFjb3JuZXIyUmVhZCkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRbcmVzdWx0T2Zmc2V0KytdID0gdGhpcy5yZWFkQ29ybmVyMihudW1Sb3dzLCBudW1Db2x1bW5zKSAmIDB4ZmY7XG4gICAgICAgICAgICAgICAgICAgIHJvdyAtPSAyO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW4gKz0gMjtcbiAgICAgICAgICAgICAgICAgICAgY29ybmVyMlJlYWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICgocm93ID09PSBudW1Sb3dzICsgNCkgJiYgKGNvbHVtbiA9PT0gMikgJiYgKChudW1Db2x1bW5zICYgMHgwNykgPT09IDApICYmICFjb3JuZXIzUmVhZCkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRbcmVzdWx0T2Zmc2V0KytdID0gdGhpcy5yZWFkQ29ybmVyMyhudW1Sb3dzLCBudW1Db2x1bW5zKSAmIDB4ZmY7XG4gICAgICAgICAgICAgICAgICAgIHJvdyAtPSAyO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW4gKz0gMjtcbiAgICAgICAgICAgICAgICAgICAgY29ybmVyM1JlYWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICgocm93ID09PSBudW1Sb3dzIC0gMikgJiYgKGNvbHVtbiA9PT0gMCkgJiYgKChudW1Db2x1bW5zICYgMHgwNykgPT09IDQpICYmICFjb3JuZXI0UmVhZCkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRbcmVzdWx0T2Zmc2V0KytdID0gdGhpcy5yZWFkQ29ybmVyNChudW1Sb3dzLCBudW1Db2x1bW5zKSAmIDB4ZmY7XG4gICAgICAgICAgICAgICAgICAgIHJvdyAtPSAyO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW4gKz0gMjtcbiAgICAgICAgICAgICAgICAgICAgY29ybmVyNFJlYWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gU3dlZXAgdXB3YXJkIGRpYWdvbmFsbHkgdG8gdGhlIHJpZ2h0XG4gICAgICAgICAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgocm93IDwgbnVtUm93cykgJiYgKGNvbHVtbiA+PSAwKSAmJiAhdGhpcy5yZWFkTWFwcGluZ01hdHJpeC5nZXQoY29sdW1uLCByb3cpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0W3Jlc3VsdE9mZnNldCsrXSA9IHRoaXMucmVhZFV0YWgocm93LCBjb2x1bW4sIG51bVJvd3MsIG51bUNvbHVtbnMpICYgMHhmZjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJvdyAtPSAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uICs9IDI7XG4gICAgICAgICAgICAgICAgICAgIH0gd2hpbGUgKChyb3cgPj0gMCkgJiYgKGNvbHVtbiA8IG51bUNvbHVtbnMpKTtcbiAgICAgICAgICAgICAgICAgICAgcm93ICs9IDE7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbiArPSAzO1xuICAgICAgICAgICAgICAgICAgICAvLyBTd2VlcCBkb3dud2FyZCBkaWFnb25hbGx5IHRvIHRoZSBsZWZ0XG4gICAgICAgICAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgocm93ID49IDApICYmIChjb2x1bW4gPCBudW1Db2x1bW5zKSAmJiAhdGhpcy5yZWFkTWFwcGluZ01hdHJpeC5nZXQoY29sdW1uLCByb3cpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0W3Jlc3VsdE9mZnNldCsrXSA9IHRoaXMucmVhZFV0YWgocm93LCBjb2x1bW4sIG51bVJvd3MsIG51bUNvbHVtbnMpICYgMHhmZjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJvdyArPSAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uIC09IDI7XG4gICAgICAgICAgICAgICAgICAgIH0gd2hpbGUgKChyb3cgPCBudW1Sb3dzKSAmJiAoY29sdW1uID49IDApKTtcbiAgICAgICAgICAgICAgICAgICAgcm93ICs9IDM7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbiArPSAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gd2hpbGUgKChyb3cgPCBudW1Sb3dzKSB8fCAoY29sdW1uIDwgbnVtQ29sdW1ucykpO1xuICAgICAgICAgICAgaWYgKHJlc3VsdE9mZnNldCAhPT0gdGhpcy52ZXJzaW9uLmdldFRvdGFsQ29kZXdvcmRzKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5SZWFkcyBhIGJpdCBvZiB0aGUgbWFwcGluZyBtYXRyaXggYWNjb3VudGluZyBmb3IgYm91bmRhcnkgd3JhcHBpbmcuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gcm93IFJvdyB0byByZWFkIGluIHRoZSBtYXBwaW5nIG1hdHJpeFxuICAgICAgICAgKiBAcGFyYW0gY29sdW1uIENvbHVtbiB0byByZWFkIGluIHRoZSBtYXBwaW5nIG1hdHJpeFxuICAgICAgICAgKiBAcGFyYW0gbnVtUm93cyBOdW1iZXIgb2Ygcm93cyBpbiB0aGUgbWFwcGluZyBtYXRyaXhcbiAgICAgICAgICogQHBhcmFtIG51bUNvbHVtbnMgTnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhlIG1hcHBpbmcgbWF0cml4XG4gICAgICAgICAqIEByZXR1cm4gdmFsdWUgb2YgdGhlIGdpdmVuIGJpdCBpbiB0aGUgbWFwcGluZyBtYXRyaXhcbiAgICAgICAgICovXG4gICAgICAgIHJlYWRNb2R1bGUocm93LCBjb2x1bW4sIG51bVJvd3MsIG51bUNvbHVtbnMpIHtcbiAgICAgICAgICAgIC8vIEFkanVzdCB0aGUgcm93IGFuZCBjb2x1bW4gaW5kaWNlcyBiYXNlZCBvbiBib3VuZGFyeSB3cmFwcGluZ1xuICAgICAgICAgICAgaWYgKHJvdyA8IDApIHtcbiAgICAgICAgICAgICAgICByb3cgKz0gbnVtUm93cztcbiAgICAgICAgICAgICAgICBjb2x1bW4gKz0gNCAtICgobnVtUm93cyArIDQpICYgMHgwNyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29sdW1uIDwgMCkge1xuICAgICAgICAgICAgICAgIGNvbHVtbiArPSBudW1Db2x1bW5zO1xuICAgICAgICAgICAgICAgIHJvdyArPSA0IC0gKChudW1Db2x1bW5zICsgNCkgJiAweDA3KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucmVhZE1hcHBpbmdNYXRyaXguc2V0KGNvbHVtbiwgcm93KTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1hcHBpbmdCaXRNYXRyaXguZ2V0KGNvbHVtbiwgcm93KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+UmVhZHMgdGhlIDggYml0cyBvZiB0aGUgc3RhbmRhcmQgVXRhaC1zaGFwZWQgcGF0dGVybi48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIDxwPlNlZSBJU08gMTYwMjI6MjAwNiwgNS44LjEgRmlndXJlIDY8L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSByb3cgQ3VycmVudCByb3cgaW4gdGhlIG1hcHBpbmcgbWF0cml4LCBhbmNob3JlZCBhdCB0aGUgOHRoIGJpdCAoTFNCKSBvZiB0aGUgcGF0dGVyblxuICAgICAgICAgKiBAcGFyYW0gY29sdW1uIEN1cnJlbnQgY29sdW1uIGluIHRoZSBtYXBwaW5nIG1hdHJpeCwgYW5jaG9yZWQgYXQgdGhlIDh0aCBiaXQgKExTQikgb2YgdGhlIHBhdHRlcm5cbiAgICAgICAgICogQHBhcmFtIG51bVJvd3MgTnVtYmVyIG9mIHJvd3MgaW4gdGhlIG1hcHBpbmcgbWF0cml4XG4gICAgICAgICAqIEBwYXJhbSBudW1Db2x1bW5zIE51bWJlciBvZiBjb2x1bW5zIGluIHRoZSBtYXBwaW5nIG1hdHJpeFxuICAgICAgICAgKiBAcmV0dXJuIGJ5dGUgZnJvbSB0aGUgdXRhaCBzaGFwZVxuICAgICAgICAgKi9cbiAgICAgICAgcmVhZFV0YWgocm93LCBjb2x1bW4sIG51bVJvd3MsIG51bUNvbHVtbnMpIHtcbiAgICAgICAgICAgIGxldCBjdXJyZW50Qnl0ZSA9IDA7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKHJvdyAtIDIsIGNvbHVtbiAtIDIsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZShyb3cgLSAyLCBjb2x1bW4gLSAxLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUocm93IC0gMSwgY29sdW1uIC0gMiwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKHJvdyAtIDEsIGNvbHVtbiAtIDEsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZShyb3cgLSAxLCBjb2x1bW4sIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZShyb3csIGNvbHVtbiAtIDIsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZShyb3csIGNvbHVtbiAtIDEsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZShyb3csIGNvbHVtbiwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRCeXRlO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5SZWFkcyB0aGUgOCBiaXRzIG9mIHRoZSBzcGVjaWFsIGNvcm5lciBjb25kaXRpb24gMS48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIDxwPlNlZSBJU08gMTYwMjI6MjAwNiwgRmlndXJlIEYuMzwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIG51bVJvd3MgTnVtYmVyIG9mIHJvd3MgaW4gdGhlIG1hcHBpbmcgbWF0cml4XG4gICAgICAgICAqIEBwYXJhbSBudW1Db2x1bW5zIE51bWJlciBvZiBjb2x1bW5zIGluIHRoZSBtYXBwaW5nIG1hdHJpeFxuICAgICAgICAgKiBAcmV0dXJuIGJ5dGUgZnJvbSB0aGUgQ29ybmVyIGNvbmRpdGlvbiAxXG4gICAgICAgICAqL1xuICAgICAgICByZWFkQ29ybmVyMShudW1Sb3dzLCBudW1Db2x1bW5zKSB7XG4gICAgICAgICAgICBsZXQgY3VycmVudEJ5dGUgPSAwO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZShudW1Sb3dzIC0gMSwgMCwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKG51bVJvd3MgLSAxLCAxLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUobnVtUm93cyAtIDEsIDIsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZSgwLCBudW1Db2x1bW5zIC0gMiwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKDAsIG51bUNvbHVtbnMgLSAxLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUoMSwgbnVtQ29sdW1ucyAtIDEsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZSgyLCBudW1Db2x1bW5zIC0gMSwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKDMsIG51bUNvbHVtbnMgLSAxLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY3VycmVudEJ5dGU7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPlJlYWRzIHRoZSA4IGJpdHMgb2YgdGhlIHNwZWNpYWwgY29ybmVyIGNvbmRpdGlvbiAyLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogPHA+U2VlIElTTyAxNjAyMjoyMDA2LCBGaWd1cmUgRi40PC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gbnVtUm93cyBOdW1iZXIgb2Ygcm93cyBpbiB0aGUgbWFwcGluZyBtYXRyaXhcbiAgICAgICAgICogQHBhcmFtIG51bUNvbHVtbnMgTnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhlIG1hcHBpbmcgbWF0cml4XG4gICAgICAgICAqIEByZXR1cm4gYnl0ZSBmcm9tIHRoZSBDb3JuZXIgY29uZGl0aW9uIDJcbiAgICAgICAgICovXG4gICAgICAgIHJlYWRDb3JuZXIyKG51bVJvd3MsIG51bUNvbHVtbnMpIHtcbiAgICAgICAgICAgIGxldCBjdXJyZW50Qnl0ZSA9IDA7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKG51bVJvd3MgLSAzLCAwLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUobnVtUm93cyAtIDIsIDAsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZShudW1Sb3dzIC0gMSwgMCwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKDAsIG51bUNvbHVtbnMgLSA0LCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUoMCwgbnVtQ29sdW1ucyAtIDMsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZSgwLCBudW1Db2x1bW5zIC0gMiwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKDAsIG51bUNvbHVtbnMgLSAxLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUoMSwgbnVtQ29sdW1ucyAtIDEsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50Qnl0ZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+UmVhZHMgdGhlIDggYml0cyBvZiB0aGUgc3BlY2lhbCBjb3JuZXIgY29uZGl0aW9uIDMuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiA8cD5TZWUgSVNPIDE2MDIyOjIwMDYsIEZpZ3VyZSBGLjU8L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBudW1Sb3dzIE51bWJlciBvZiByb3dzIGluIHRoZSBtYXBwaW5nIG1hdHJpeFxuICAgICAgICAgKiBAcGFyYW0gbnVtQ29sdW1ucyBOdW1iZXIgb2YgY29sdW1ucyBpbiB0aGUgbWFwcGluZyBtYXRyaXhcbiAgICAgICAgICogQHJldHVybiBieXRlIGZyb20gdGhlIENvcm5lciBjb25kaXRpb24gM1xuICAgICAgICAgKi9cbiAgICAgICAgcmVhZENvcm5lcjMobnVtUm93cywgbnVtQ29sdW1ucykge1xuICAgICAgICAgICAgbGV0IGN1cnJlbnRCeXRlID0gMDtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUobnVtUm93cyAtIDEsIDAsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZShudW1Sb3dzIC0gMSwgbnVtQ29sdW1ucyAtIDEsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZSgwLCBudW1Db2x1bW5zIC0gMywgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKDAsIG51bUNvbHVtbnMgLSAyLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUoMCwgbnVtQ29sdW1ucyAtIDEsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZSgxLCBudW1Db2x1bW5zIC0gMywgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKDEsIG51bUNvbHVtbnMgLSAyLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUoMSwgbnVtQ29sdW1ucyAtIDEsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50Qnl0ZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+UmVhZHMgdGhlIDggYml0cyBvZiB0aGUgc3BlY2lhbCBjb3JuZXIgY29uZGl0aW9uIDQuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiA8cD5TZWUgSVNPIDE2MDIyOjIwMDYsIEZpZ3VyZSBGLjY8L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBudW1Sb3dzIE51bWJlciBvZiByb3dzIGluIHRoZSBtYXBwaW5nIG1hdHJpeFxuICAgICAgICAgKiBAcGFyYW0gbnVtQ29sdW1ucyBOdW1iZXIgb2YgY29sdW1ucyBpbiB0aGUgbWFwcGluZyBtYXRyaXhcbiAgICAgICAgICogQHJldHVybiBieXRlIGZyb20gdGhlIENvcm5lciBjb25kaXRpb24gNFxuICAgICAgICAgKi9cbiAgICAgICAgcmVhZENvcm5lcjQobnVtUm93cywgbnVtQ29sdW1ucykge1xuICAgICAgICAgICAgbGV0IGN1cnJlbnRCeXRlID0gMDtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUobnVtUm93cyAtIDMsIDAsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZShudW1Sb3dzIC0gMiwgMCwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKG51bVJvd3MgLSAxLCAwLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUoMCwgbnVtQ29sdW1ucyAtIDIsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZSgwLCBudW1Db2x1bW5zIC0gMSwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKDEsIG51bUNvbHVtbnMgLSAxLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUoMiwgbnVtQ29sdW1ucyAtIDEsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZSgzLCBudW1Db2x1bW5zIC0gMSwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRCeXRlO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5FeHRyYWN0cyB0aGUgZGF0YSByZWdpb24gZnJvbSBhIHtAbGluayBCaXRNYXRyaXh9IHRoYXQgY29udGFpbnNcbiAgICAgICAgICogYWxpZ25tZW50IHBhdHRlcm5zLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGJpdE1hdHJpeCBPcmlnaW5hbCB7QGxpbmsgQml0TWF0cml4fSB3aXRoIGFsaWdubWVudCBwYXR0ZXJuc1xuICAgICAgICAgKiBAcmV0dXJuIEJpdE1hdHJpeCB0aGF0IGhhcyB0aGUgYWxpZ25tZW50IHBhdHRlcm5zIHJlbW92ZWRcbiAgICAgICAgICovXG4gICAgICAgIGV4dHJhY3REYXRhUmVnaW9uKGJpdE1hdHJpeCkge1xuICAgICAgICAgICAgY29uc3Qgc3ltYm9sU2l6ZVJvd3MgPSB0aGlzLnZlcnNpb24uZ2V0U3ltYm9sU2l6ZVJvd3MoKTtcbiAgICAgICAgICAgIGNvbnN0IHN5bWJvbFNpemVDb2x1bW5zID0gdGhpcy52ZXJzaW9uLmdldFN5bWJvbFNpemVDb2x1bW5zKCk7XG4gICAgICAgICAgICBpZiAoYml0TWF0cml4LmdldEhlaWdodCgpICE9PSBzeW1ib2xTaXplUm93cykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ0RpbWVuc2lvbiBvZiBiaXRNYXRyaXggbXVzdCBtYXRjaCB0aGUgdmVyc2lvbiBzaXplJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBkYXRhUmVnaW9uU2l6ZVJvd3MgPSB0aGlzLnZlcnNpb24uZ2V0RGF0YVJlZ2lvblNpemVSb3dzKCk7XG4gICAgICAgICAgICBjb25zdCBkYXRhUmVnaW9uU2l6ZUNvbHVtbnMgPSB0aGlzLnZlcnNpb24uZ2V0RGF0YVJlZ2lvblNpemVDb2x1bW5zKCk7XG4gICAgICAgICAgICBjb25zdCBudW1EYXRhUmVnaW9uc1JvdyA9IHN5bWJvbFNpemVSb3dzIC8gZGF0YVJlZ2lvblNpemVSb3dzIHwgMDtcbiAgICAgICAgICAgIGNvbnN0IG51bURhdGFSZWdpb25zQ29sdW1uID0gc3ltYm9sU2l6ZUNvbHVtbnMgLyBkYXRhUmVnaW9uU2l6ZUNvbHVtbnMgfCAwO1xuICAgICAgICAgICAgY29uc3Qgc2l6ZURhdGFSZWdpb25Sb3cgPSBudW1EYXRhUmVnaW9uc1JvdyAqIGRhdGFSZWdpb25TaXplUm93cztcbiAgICAgICAgICAgIGNvbnN0IHNpemVEYXRhUmVnaW9uQ29sdW1uID0gbnVtRGF0YVJlZ2lvbnNDb2x1bW4gKiBkYXRhUmVnaW9uU2l6ZUNvbHVtbnM7XG4gICAgICAgICAgICBjb25zdCBiaXRNYXRyaXhXaXRob3V0QWxpZ25tZW50ID0gbmV3IEJpdE1hdHJpeChzaXplRGF0YVJlZ2lvbkNvbHVtbiwgc2l6ZURhdGFSZWdpb25Sb3cpO1xuICAgICAgICAgICAgZm9yIChsZXQgZGF0YVJlZ2lvblJvdyA9IDA7IGRhdGFSZWdpb25Sb3cgPCBudW1EYXRhUmVnaW9uc1JvdzsgKytkYXRhUmVnaW9uUm93KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0YVJlZ2lvblJvd09mZnNldCA9IGRhdGFSZWdpb25Sb3cgKiBkYXRhUmVnaW9uU2l6ZVJvd3M7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgZGF0YVJlZ2lvbkNvbHVtbiA9IDA7IGRhdGFSZWdpb25Db2x1bW4gPCBudW1EYXRhUmVnaW9uc0NvbHVtbjsgKytkYXRhUmVnaW9uQ29sdW1uKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGFSZWdpb25Db2x1bW5PZmZzZXQgPSBkYXRhUmVnaW9uQ29sdW1uICogZGF0YVJlZ2lvblNpemVDb2x1bW5zO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRhdGFSZWdpb25TaXplUm93czsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZWFkUm93T2Zmc2V0ID0gZGF0YVJlZ2lvblJvdyAqIChkYXRhUmVnaW9uU2l6ZVJvd3MgKyAyKSArIDEgKyBpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgd3JpdGVSb3dPZmZzZXQgPSBkYXRhUmVnaW9uUm93T2Zmc2V0ICsgaTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgZGF0YVJlZ2lvblNpemVDb2x1bW5zOyArK2opIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZWFkQ29sdW1uT2Zmc2V0ID0gZGF0YVJlZ2lvbkNvbHVtbiAqIChkYXRhUmVnaW9uU2l6ZUNvbHVtbnMgKyAyKSArIDEgKyBqO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiaXRNYXRyaXguZ2V0KHJlYWRDb2x1bW5PZmZzZXQsIHJlYWRSb3dPZmZzZXQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdyaXRlQ29sdW1uT2Zmc2V0ID0gZGF0YVJlZ2lvbkNvbHVtbk9mZnNldCArIGo7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpdE1hdHJpeFdpdGhvdXRBbGlnbm1lbnQuc2V0KHdyaXRlQ29sdW1uT2Zmc2V0LCB3cml0ZVJvd09mZnNldCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGJpdE1hdHJpeFdpdGhvdXRBbGlnbm1lbnQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiA8cD5FbmNhcHN1bGF0ZXMgYSBibG9jayBvZiBkYXRhIHdpdGhpbiBhIERhdGEgTWF0cml4IENvZGUuIERhdGEgTWF0cml4IENvZGVzIG1heSBzcGxpdCB0aGVpciBkYXRhIGludG9cbiAgICAgKiBtdWx0aXBsZSBibG9ja3MsIGVhY2ggb2Ygd2hpY2ggaXMgYSB1bml0IG9mIGRhdGEgYW5kIGVycm9yLWNvcnJlY3Rpb24gY29kZXdvcmRzLiBFYWNoXG4gICAgICogaXMgcmVwcmVzZW50ZWQgYnkgYW4gaW5zdGFuY2Ugb2YgdGhpcyBjbGFzcy48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIGJicm93bkBnb29nbGUuY29tIChCcmlhbiBCcm93bilcbiAgICAgKi9cbiAgICBjbGFzcyBEYXRhQmxvY2sge1xuICAgICAgICBjb25zdHJ1Y3RvcihudW1EYXRhQ29kZXdvcmRzLCBjb2Rld29yZHMpIHtcbiAgICAgICAgICAgIHRoaXMubnVtRGF0YUNvZGV3b3JkcyA9IG51bURhdGFDb2Rld29yZHM7XG4gICAgICAgICAgICB0aGlzLmNvZGV3b3JkcyA9IGNvZGV3b3JkcztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+V2hlbiBEYXRhIE1hdHJpeCBDb2RlcyB1c2UgbXVsdGlwbGUgZGF0YSBibG9ja3MsIHRoZXkgYWN0dWFsbHkgaW50ZXJsZWF2ZSB0aGUgYnl0ZXMgb2YgZWFjaCBvZiB0aGVtLlxuICAgICAgICAgKiBUaGF0IGlzLCB0aGUgZmlyc3QgYnl0ZSBvZiBkYXRhIGJsb2NrIDEgdG8gbiBpcyB3cml0dGVuLCB0aGVuIHRoZSBzZWNvbmQgYnl0ZXMsIGFuZCBzbyBvbi4gVGhpc1xuICAgICAgICAgKiBtZXRob2Qgd2lsbCBzZXBhcmF0ZSB0aGUgZGF0YSBpbnRvIG9yaWdpbmFsIGJsb2Nrcy48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSByYXdDb2Rld29yZHMgYnl0ZXMgYXMgcmVhZCBkaXJlY3RseSBmcm9tIHRoZSBEYXRhIE1hdHJpeCBDb2RlXG4gICAgICAgICAqIEBwYXJhbSB2ZXJzaW9uIHZlcnNpb24gb2YgdGhlIERhdGEgTWF0cml4IENvZGVcbiAgICAgICAgICogQHJldHVybiBEYXRhQmxvY2tzIGNvbnRhaW5pbmcgb3JpZ2luYWwgYnl0ZXMsIFwiZGUtaW50ZXJsZWF2ZWRcIiBmcm9tIHJlcHJlc2VudGF0aW9uIGluIHRoZVxuICAgICAgICAgKiAgICAgICAgIERhdGEgTWF0cml4IENvZGVcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBnZXREYXRhQmxvY2tzKHJhd0NvZGV3b3JkcywgdmVyc2lvbikge1xuICAgICAgICAgICAgLy8gRmlndXJlIG91dCB0aGUgbnVtYmVyIGFuZCBzaXplIG9mIGRhdGEgYmxvY2tzIHVzZWQgYnkgdGhpcyB2ZXJzaW9uXG4gICAgICAgICAgICBjb25zdCBlY0Jsb2NrcyA9IHZlcnNpb24uZ2V0RUNCbG9ja3MoKTtcbiAgICAgICAgICAgIC8vIEZpcnN0IGNvdW50IHRoZSB0b3RhbCBudW1iZXIgb2YgZGF0YSBibG9ja3NcbiAgICAgICAgICAgIGxldCB0b3RhbEJsb2NrcyA9IDA7XG4gICAgICAgICAgICBjb25zdCBlY0Jsb2NrQXJyYXkgPSBlY0Jsb2Nrcy5nZXRFQ0Jsb2NrcygpO1xuICAgICAgICAgICAgZm9yIChsZXQgZWNCbG9jayBvZiBlY0Jsb2NrQXJyYXkpIHtcbiAgICAgICAgICAgICAgICB0b3RhbEJsb2NrcyArPSBlY0Jsb2NrLmdldENvdW50KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBOb3cgZXN0YWJsaXNoIERhdGFCbG9ja3Mgb2YgdGhlIGFwcHJvcHJpYXRlIHNpemUgYW5kIG51bWJlciBvZiBkYXRhIGNvZGV3b3Jkc1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IEFycmF5KHRvdGFsQmxvY2tzKTtcbiAgICAgICAgICAgIGxldCBudW1SZXN1bHRCbG9ja3MgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgZWNCbG9jayBvZiBlY0Jsb2NrQXJyYXkpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVjQmxvY2suZ2V0Q291bnQoKTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG51bURhdGFDb2Rld29yZHMgPSBlY0Jsb2NrLmdldERhdGFDb2Rld29yZHMoKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbnVtQmxvY2tDb2Rld29yZHMgPSBlY0Jsb2Nrcy5nZXRFQ0NvZGV3b3JkcygpICsgbnVtRGF0YUNvZGV3b3JkcztcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W251bVJlc3VsdEJsb2NrcysrXSA9IG5ldyBEYXRhQmxvY2sobnVtRGF0YUNvZGV3b3JkcywgbmV3IFVpbnQ4QXJyYXkobnVtQmxvY2tDb2Rld29yZHMpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBBbGwgYmxvY2tzIGhhdmUgdGhlIHNhbWUgYW1vdW50IG9mIGRhdGEsIGV4Y2VwdCB0aGF0IHRoZSBsYXN0IG5cbiAgICAgICAgICAgIC8vICh3aGVyZSBuIG1heSBiZSAwKSBoYXZlIDEgbGVzcyBieXRlLiBGaWd1cmUgb3V0IHdoZXJlIHRoZXNlIHN0YXJ0LlxuICAgICAgICAgICAgLy8gVE9ETyhiYnJvd24pOiBUaGVyZSBpcyBvbmx5IG9uZSBjYXNlIHdoZXJlIHRoZXJlIGlzIGEgZGlmZmVyZW5jZSBmb3IgRGF0YSBNYXRyaXggZm9yIHNpemUgMTQ0XG4gICAgICAgICAgICBjb25zdCBsb25nZXJCbG9ja3NUb3RhbENvZGV3b3JkcyA9IHJlc3VsdFswXS5jb2Rld29yZHMubGVuZ3RoO1xuICAgICAgICAgICAgLy8gaW50IHNob3J0ZXJCbG9ja3NUb3RhbENvZGV3b3JkcyA9IGxvbmdlckJsb2Nrc1RvdGFsQ29kZXdvcmRzIC0gMTtcbiAgICAgICAgICAgIGNvbnN0IGxvbmdlckJsb2Nrc051bURhdGFDb2Rld29yZHMgPSBsb25nZXJCbG9ja3NUb3RhbENvZGV3b3JkcyAtIGVjQmxvY2tzLmdldEVDQ29kZXdvcmRzKCk7XG4gICAgICAgICAgICBjb25zdCBzaG9ydGVyQmxvY2tzTnVtRGF0YUNvZGV3b3JkcyA9IGxvbmdlckJsb2Nrc051bURhdGFDb2Rld29yZHMgLSAxO1xuICAgICAgICAgICAgLy8gVGhlIGxhc3QgZWxlbWVudHMgb2YgcmVzdWx0IG1heSBiZSAxIGVsZW1lbnQgc2hvcnRlciBmb3IgMTQ0IG1hdHJpeFxuICAgICAgICAgICAgLy8gZmlyc3QgZmlsbCBvdXQgYXMgbWFueSBlbGVtZW50cyBhcyBhbGwgb2YgdGhlbSBoYXZlIG1pbnVzIDFcbiAgICAgICAgICAgIGxldCByYXdDb2Rld29yZHNPZmZzZXQgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaG9ydGVyQmxvY2tzTnVtRGF0YUNvZGV3b3JkczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBudW1SZXN1bHRCbG9ja3M7IGorKykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRbal0uY29kZXdvcmRzW2ldID0gcmF3Q29kZXdvcmRzW3Jhd0NvZGV3b3Jkc09mZnNldCsrXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBGaWxsIG91dCB0aGUgbGFzdCBkYXRhIGJsb2NrIGluIHRoZSBsb25nZXIgb25lc1xuICAgICAgICAgICAgY29uc3Qgc3BlY2lhbFZlcnNpb24gPSB2ZXJzaW9uLmdldFZlcnNpb25OdW1iZXIoKSA9PT0gMjQ7XG4gICAgICAgICAgICBjb25zdCBudW1Mb25nZXJCbG9ja3MgPSBzcGVjaWFsVmVyc2lvbiA/IDggOiBudW1SZXN1bHRCbG9ja3M7XG4gICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IG51bUxvbmdlckJsb2NrczsgaisrKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0W2pdLmNvZGV3b3Jkc1tsb25nZXJCbG9ja3NOdW1EYXRhQ29kZXdvcmRzIC0gMV0gPSByYXdDb2Rld29yZHNbcmF3Q29kZXdvcmRzT2Zmc2V0KytdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gTm93IGFkZCBpbiBlcnJvciBjb3JyZWN0aW9uIGJsb2Nrc1xuICAgICAgICAgICAgY29uc3QgbWF4ID0gcmVzdWx0WzBdLmNvZGV3b3Jkcy5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gbG9uZ2VyQmxvY2tzTnVtRGF0YUNvZGV3b3JkczsgaSA8IG1heDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBudW1SZXN1bHRCbG9ja3M7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBqT2Zmc2V0ID0gc3BlY2lhbFZlcnNpb24gPyAoaiArIDgpICUgbnVtUmVzdWx0QmxvY2tzIDogajtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaU9mZnNldCA9IHNwZWNpYWxWZXJzaW9uICYmIGpPZmZzZXQgPiA3ID8gaSAtIDEgOiBpO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRbak9mZnNldF0uY29kZXdvcmRzW2lPZmZzZXRdID0gcmF3Q29kZXdvcmRzW3Jhd0NvZGV3b3Jkc09mZnNldCsrXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmF3Q29kZXdvcmRzT2Zmc2V0ICE9PSByYXdDb2Rld29yZHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBnZXROdW1EYXRhQ29kZXdvcmRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubnVtRGF0YUNvZGV3b3JkcztcbiAgICAgICAgfVxuICAgICAgICBnZXRDb2Rld29yZHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2Rld29yZHM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIDxwPlRoaXMgcHJvdmlkZXMgYW4gZWFzeSBhYnN0cmFjdGlvbiB0byByZWFkIGJpdHMgYXQgYSB0aW1lIGZyb20gYSBzZXF1ZW5jZSBvZiBieXRlcywgd2hlcmUgdGhlXG4gICAgICogbnVtYmVyIG9mIGJpdHMgcmVhZCBpcyBub3Qgb2Z0ZW4gYSBtdWx0aXBsZSBvZiA4LjwvcD5cbiAgICAgKlxuICAgICAqIDxwPlRoaXMgY2xhc3MgaXMgdGhyZWFkLXNhZmUgYnV0IG5vdCByZWVudHJhbnQgLS0gdW5sZXNzIHRoZSBjYWxsZXIgbW9kaWZpZXMgdGhlIGJ5dGVzIGFycmF5XG4gICAgICogaXQgcGFzc2VkIGluLCBpbiB3aGljaCBjYXNlIGFsbCBiZXRzIGFyZSBvZmYuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBCaXRTb3VyY2Uge1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIGJ5dGVzIGJ5dGVzIGZyb20gd2hpY2ggdGhpcyB3aWxsIHJlYWQgYml0cy4gQml0cyB3aWxsIGJlIHJlYWQgZnJvbSB0aGUgZmlyc3QgYnl0ZSBmaXJzdC5cbiAgICAgICAgICogQml0cyBhcmUgcmVhZCB3aXRoaW4gYSBieXRlIGZyb20gbW9zdC1zaWduaWZpY2FudCB0byBsZWFzdC1zaWduaWZpY2FudCBiaXQuXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3RvcihieXRlcykge1xuICAgICAgICAgICAgdGhpcy5ieXRlcyA9IGJ5dGVzO1xuICAgICAgICAgICAgdGhpcy5ieXRlT2Zmc2V0ID0gMDtcbiAgICAgICAgICAgIHRoaXMuYml0T2Zmc2V0ID0gMDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBpbmRleCBvZiBuZXh0IGJpdCBpbiBjdXJyZW50IGJ5dGUgd2hpY2ggd291bGQgYmUgcmVhZCBieSB0aGUgbmV4dCBjYWxsIHRvIHtAbGluayAjcmVhZEJpdHMoaW50KX0uXG4gICAgICAgICAqL1xuICAgICAgICBnZXRCaXRPZmZzZXQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5iaXRPZmZzZXQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gaW5kZXggb2YgbmV4dCBieXRlIGluIGlucHV0IGJ5dGUgYXJyYXkgd2hpY2ggd291bGQgYmUgcmVhZCBieSB0aGUgbmV4dCBjYWxsIHRvIHtAbGluayAjcmVhZEJpdHMoaW50KX0uXG4gICAgICAgICAqL1xuICAgICAgICBnZXRCeXRlT2Zmc2V0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYnl0ZU9mZnNldDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIG51bUJpdHMgbnVtYmVyIG9mIGJpdHMgdG8gcmVhZFxuICAgICAgICAgKiBAcmV0dXJuIGludCByZXByZXNlbnRpbmcgdGhlIGJpdHMgcmVhZC4gVGhlIGJpdHMgd2lsbCBhcHBlYXIgYXMgdGhlIGxlYXN0LXNpZ25pZmljYW50XG4gICAgICAgICAqICAgICAgICAgYml0cyBvZiB0aGUgaW50XG4gICAgICAgICAqIEB0aHJvd3MgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uIGlmIG51bUJpdHMgaXNuJ3QgaW4gWzEsMzJdIG9yIG1vcmUgdGhhbiBpcyBhdmFpbGFibGVcbiAgICAgICAgICovXG4gICAgICAgIHJlYWRCaXRzKG51bUJpdHMgLyppbnQqLykge1xuICAgICAgICAgICAgaWYgKG51bUJpdHMgPCAxIHx8IG51bUJpdHMgPiAzMiB8fCBudW1CaXRzID4gdGhpcy5hdmFpbGFibGUoKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJycgKyBudW1CaXRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCByZXN1bHQgPSAwO1xuICAgICAgICAgICAgbGV0IGJpdE9mZnNldCA9IHRoaXMuYml0T2Zmc2V0O1xuICAgICAgICAgICAgbGV0IGJ5dGVPZmZzZXQgPSB0aGlzLmJ5dGVPZmZzZXQ7XG4gICAgICAgICAgICBjb25zdCBieXRlcyA9IHRoaXMuYnl0ZXM7XG4gICAgICAgICAgICAvLyBGaXJzdCwgcmVhZCByZW1haW5kZXIgZnJvbSBjdXJyZW50IGJ5dGVcbiAgICAgICAgICAgIGlmIChiaXRPZmZzZXQgPiAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYml0c0xlZnQgPSA4IC0gYml0T2Zmc2V0O1xuICAgICAgICAgICAgICAgIGNvbnN0IHRvUmVhZCA9IG51bUJpdHMgPCBiaXRzTGVmdCA/IG51bUJpdHMgOiBiaXRzTGVmdDtcbiAgICAgICAgICAgICAgICBjb25zdCBiaXRzVG9Ob3RSZWFkID0gYml0c0xlZnQgLSB0b1JlYWQ7XG4gICAgICAgICAgICAgICAgY29uc3QgbWFzayA9ICgweEZGID4+ICg4IC0gdG9SZWFkKSkgPDwgYml0c1RvTm90UmVhZDtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSAoYnl0ZXNbYnl0ZU9mZnNldF0gJiBtYXNrKSA+PiBiaXRzVG9Ob3RSZWFkO1xuICAgICAgICAgICAgICAgIG51bUJpdHMgLT0gdG9SZWFkO1xuICAgICAgICAgICAgICAgIGJpdE9mZnNldCArPSB0b1JlYWQ7XG4gICAgICAgICAgICAgICAgaWYgKGJpdE9mZnNldCA9PT0gOCkge1xuICAgICAgICAgICAgICAgICAgICBiaXRPZmZzZXQgPSAwO1xuICAgICAgICAgICAgICAgICAgICBieXRlT2Zmc2V0Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gTmV4dCByZWFkIHdob2xlIGJ5dGVzXG4gICAgICAgICAgICBpZiAobnVtQml0cyA+IDApIHtcbiAgICAgICAgICAgICAgICB3aGlsZSAobnVtQml0cyA+PSA4KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IChyZXN1bHQgPDwgOCkgfCAoYnl0ZXNbYnl0ZU9mZnNldF0gJiAweEZGKTtcbiAgICAgICAgICAgICAgICAgICAgYnl0ZU9mZnNldCsrO1xuICAgICAgICAgICAgICAgICAgICBudW1CaXRzIC09IDg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIEZpbmFsbHkgcmVhZCBhIHBhcnRpYWwgYnl0ZVxuICAgICAgICAgICAgICAgIGlmIChudW1CaXRzID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBiaXRzVG9Ob3RSZWFkID0gOCAtIG51bUJpdHM7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG1hc2sgPSAoMHhGRiA+PiBiaXRzVG9Ob3RSZWFkKSA8PCBiaXRzVG9Ob3RSZWFkO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSAocmVzdWx0IDw8IG51bUJpdHMpIHwgKChieXRlc1tieXRlT2Zmc2V0XSAmIG1hc2spID4+IGJpdHNUb05vdFJlYWQpO1xuICAgICAgICAgICAgICAgICAgICBiaXRPZmZzZXQgKz0gbnVtQml0cztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmJpdE9mZnNldCA9IGJpdE9mZnNldDtcbiAgICAgICAgICAgIHRoaXMuYnl0ZU9mZnNldCA9IGJ5dGVPZmZzZXQ7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIG51bWJlciBvZiBiaXRzIHRoYXQgY2FuIGJlIHJlYWQgc3VjY2Vzc2Z1bGx5XG4gICAgICAgICAqL1xuICAgICAgICBhdmFpbGFibGUoKSB7XG4gICAgICAgICAgICByZXR1cm4gOCAqICh0aGlzLmJ5dGVzLmxlbmd0aCAtIHRoaXMuYnl0ZU9mZnNldCkgLSB0aGlzLmJpdE9mZnNldDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBNb2RlO1xuICAgIChmdW5jdGlvbiAoTW9kZSkge1xuICAgICAgICBNb2RlW01vZGVbXCJQQURfRU5DT0RFXCJdID0gMF0gPSBcIlBBRF9FTkNPREVcIjtcbiAgICAgICAgTW9kZVtNb2RlW1wiQVNDSUlfRU5DT0RFXCJdID0gMV0gPSBcIkFTQ0lJX0VOQ09ERVwiO1xuICAgICAgICBNb2RlW01vZGVbXCJDNDBfRU5DT0RFXCJdID0gMl0gPSBcIkM0MF9FTkNPREVcIjtcbiAgICAgICAgTW9kZVtNb2RlW1wiVEVYVF9FTkNPREVcIl0gPSAzXSA9IFwiVEVYVF9FTkNPREVcIjtcbiAgICAgICAgTW9kZVtNb2RlW1wiQU5TSVgxMl9FTkNPREVcIl0gPSA0XSA9IFwiQU5TSVgxMl9FTkNPREVcIjtcbiAgICAgICAgTW9kZVtNb2RlW1wiRURJRkFDVF9FTkNPREVcIl0gPSA1XSA9IFwiRURJRkFDVF9FTkNPREVcIjtcbiAgICAgICAgTW9kZVtNb2RlW1wiQkFTRTI1Nl9FTkNPREVcIl0gPSA2XSA9IFwiQkFTRTI1Nl9FTkNPREVcIjtcbiAgICB9KShNb2RlIHx8IChNb2RlID0ge30pKTtcbiAgICAvKipcbiAgICAgKiA8cD5EYXRhIE1hdHJpeCBDb2RlcyBjYW4gZW5jb2RlIHRleHQgYXMgYml0cyBpbiBvbmUgb2Ygc2V2ZXJhbCBtb2RlcywgYW5kIGNhbiB1c2UgbXVsdGlwbGUgbW9kZXNcbiAgICAgKiBpbiBvbmUgRGF0YSBNYXRyaXggQ29kZS4gVGhpcyBjbGFzcyBkZWNvZGVzIHRoZSBiaXRzIGJhY2sgaW50byB0ZXh0LjwvcD5cbiAgICAgKlxuICAgICAqIDxwPlNlZSBJU08gMTYwMjI6MjAwNiwgNS4yLjEgLSA1LjIuOS4yPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBiYnJvd25AZ29vZ2xlLmNvbSAoQnJpYW4gQnJvd24pXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBEZWNvZGVkQml0U3RyZWFtUGFyc2VyIHtcbiAgICAgICAgc3RhdGljIGRlY29kZShieXRlcykge1xuICAgICAgICAgICAgY29uc3QgYml0cyA9IG5ldyBCaXRTb3VyY2UoYnl0ZXMpO1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IFN0cmluZ0J1aWxkZXIoKTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdFRyYWlsZXIgPSBuZXcgU3RyaW5nQnVpbGRlcigpO1xuICAgICAgICAgICAgY29uc3QgYnl0ZVNlZ21lbnRzID0gbmV3IEFycmF5KCk7XG4gICAgICAgICAgICBsZXQgbW9kZSA9IE1vZGUuQVNDSUlfRU5DT0RFO1xuICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgIGlmIChtb2RlID09PSBNb2RlLkFTQ0lJX0VOQ09ERSkge1xuICAgICAgICAgICAgICAgICAgICBtb2RlID0gdGhpcy5kZWNvZGVBc2NpaVNlZ21lbnQoYml0cywgcmVzdWx0LCByZXN1bHRUcmFpbGVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAobW9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBNb2RlLkM0MF9FTkNPREU6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWNvZGVDNDBTZWdtZW50KGJpdHMsIHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIE1vZGUuVEVYVF9FTkNPREU6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWNvZGVUZXh0U2VnbWVudChiaXRzLCByZXN1bHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBNb2RlLkFOU0lYMTJfRU5DT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVjb2RlQW5zaVgxMlNlZ21lbnQoYml0cywgcmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgTW9kZS5FRElGQUNUX0VOQ09ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlY29kZUVkaWZhY3RTZWdtZW50KGJpdHMsIHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIE1vZGUuQkFTRTI1Nl9FTkNPREU6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWNvZGVCYXNlMjU2U2VnbWVudChiaXRzLCByZXN1bHQsIGJ5dGVTZWdtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBtb2RlID0gTW9kZS5BU0NJSV9FTkNPREU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSB3aGlsZSAobW9kZSAhPT0gTW9kZS5QQURfRU5DT0RFICYmIGJpdHMuYXZhaWxhYmxlKCkgPiAwKTtcbiAgICAgICAgICAgIGlmIChyZXN1bHRUcmFpbGVyLmxlbmd0aCgpID4gMCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQocmVzdWx0VHJhaWxlci50b1N0cmluZygpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgRGVjb2RlclJlc3VsdChieXRlcywgcmVzdWx0LnRvU3RyaW5nKCksIGJ5dGVTZWdtZW50cy5sZW5ndGggPT09IDAgPyBudWxsIDogYnl0ZVNlZ21lbnRzLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogU2VlIElTTyAxNjAyMjoyMDA2LCA1LjIuMyBhbmQgQW5uZXggQywgVGFibGUgQy4yXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGVjb2RlQXNjaWlTZWdtZW50KGJpdHMsIHJlc3VsdCwgcmVzdWx0VHJhaWxlcikge1xuICAgICAgICAgICAgbGV0IHVwcGVyU2hpZnQgPSBmYWxzZTtcbiAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICBsZXQgb25lQnl0ZSA9IGJpdHMucmVhZEJpdHMoOCk7XG4gICAgICAgICAgICAgICAgaWYgKG9uZUJ5dGUgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChvbmVCeXRlIDw9IDEyOCkgeyAvLyBBU0NJSSBkYXRhIChBU0NJSSB2YWx1ZSArIDEpXG4gICAgICAgICAgICAgICAgICAgIGlmICh1cHBlclNoaWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvbmVCeXRlICs9IDEyODtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHVwcGVyU2hpZnQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKFN0cmluZy5mcm9tQ2hhckNvZGUob25lQnl0ZSAtIDEpKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE1vZGUuQVNDSUlfRU5DT0RFO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChvbmVCeXRlID09PSAxMjkpIHsgLy8gUGFkXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBNb2RlLlBBRF9FTkNPREU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKG9uZUJ5dGUgPD0gMjI5KSB7IC8vIDItZGlnaXQgZGF0YSAwMC05OSAoTnVtZXJpYyBWYWx1ZSArIDEzMClcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBvbmVCeXRlIC0gMTMwO1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUgPCAxMCkgeyAvLyBwYWQgd2l0aCAnMCcgZm9yIHNpbmdsZSBkaWdpdCB2YWx1ZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoJzAnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCcnICsgdmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChvbmVCeXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDIzMDogLy8gTGF0Y2ggdG8gQzQwIGVuY29kYXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gTW9kZS5DNDBfRU5DT0RFO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyMzE6IC8vIExhdGNoIHRvIEJhc2UgMjU2IGVuY29kYXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gTW9kZS5CQVNFMjU2X0VOQ09ERTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjMyOiAvLyBGTkMxXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChTdHJpbmcuZnJvbUNoYXJDb2RlKDI5KSk7IC8vIHRyYW5zbGF0ZSBhcyBBU0NJSSAyOVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyMzM6IC8vIFN0cnVjdHVyZWQgQXBwZW5kXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDIzNDogLy8gUmVhZGVyIFByb2dyYW1taW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWdub3JlIHRoZXNlIHN5bWJvbHMgZm9yIG5vd1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRocm93IFJlYWRlckV4Y2VwdGlvbi5nZXRJbnN0YW5jZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyMzU6IC8vIFVwcGVyIFNoaWZ0IChzaGlmdCB0byBFeHRlbmRlZCBBU0NJSSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cHBlclNoaWZ0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjM2OiAvLyAwNSBNYWNyb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoJ1spPlxcdTAwMUUwNVxcdTAwMUQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRUcmFpbGVyLmluc2VydCgwLCAnXFx1MDAxRVxcdTAwMDQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjM3OiAvLyAwNiBNYWNyb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoJ1spPlxcdTAwMUUwNlxcdTAwMUQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRUcmFpbGVyLmluc2VydCgwLCAnXFx1MDAxRVxcdTAwMDQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjM4OiAvLyBMYXRjaCB0byBBTlNJIFgxMiBlbmNvZGF0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE1vZGUuQU5TSVgxMl9FTkNPREU7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDIzOTogLy8gTGF0Y2ggdG8gVGV4dCBlbmNvZGF0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE1vZGUuVEVYVF9FTkNPREU7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDI0MDogLy8gTGF0Y2ggdG8gRURJRkFDVCBlbmNvZGF0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE1vZGUuRURJRkFDVF9FTkNPREU7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDI0MTogLy8gRUNJIENoYXJhY3RlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE8oYmJyb3duKTogSSB0aGluayB3ZSBuZWVkIHRvIHN1cHBvcnQgRUNJXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhyb3cgUmVhZGVyRXhjZXB0aW9uLmdldEluc3RhbmNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWdub3JlIHRoaXMgc3ltYm9sIGZvciBub3dcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm90IHRvIGJlIHVzZWQgaW4gQVNDSUkgZW5jb2RhdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJ1dCB3b3JrIGFyb3VuZCBlbmNvZGVycyB0aGF0IGVuZCB3aXRoIDI1NCwgbGF0Y2ggYmFjayB0byBBU0NJSVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvbmVCeXRlICE9PSAyNTQgfHwgYml0cy5hdmFpbGFibGUoKSAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSB3aGlsZSAoYml0cy5hdmFpbGFibGUoKSA+IDApO1xuICAgICAgICAgICAgcmV0dXJuIE1vZGUuQVNDSUlfRU5DT0RFO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZWUgSVNPIDE2MDIyOjIwMDYsIDUuMi41IGFuZCBBbm5leCBDLCBUYWJsZSBDLjFcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBkZWNvZGVDNDBTZWdtZW50KGJpdHMsIHJlc3VsdCkge1xuICAgICAgICAgICAgLy8gVGhyZWUgQzQwIHZhbHVlcyBhcmUgZW5jb2RlZCBpbiBhIDE2LWJpdCB2YWx1ZSBhc1xuICAgICAgICAgICAgLy8gKDE2MDAgKiBDMSkgKyAoNDAgKiBDMikgKyBDMyArIDFcbiAgICAgICAgICAgIC8vIFRPRE8oYmJyb3duKTogVGhlIFVwcGVyIFNoaWZ0IHdpdGggQzQwIGRvZXNuJ3Qgd29yayBpbiB0aGUgNCB2YWx1ZSBzY2VuYXJpbyBhbGwgdGhlIHRpbWVcbiAgICAgICAgICAgIGxldCB1cHBlclNoaWZ0ID0gZmFsc2U7XG4gICAgICAgICAgICBjb25zdCBjVmFsdWVzID0gW107XG4gICAgICAgICAgICBsZXQgc2hpZnQgPSAwO1xuICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZXJlIGlzIG9ubHkgb25lIGJ5dGUgbGVmdCB0aGVuIGl0IHdpbGwgYmUgZW5jb2RlZCBhcyBBU0NJSVxuICAgICAgICAgICAgICAgIGlmIChiaXRzLmF2YWlsYWJsZSgpID09PSA4KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgZmlyc3RCeXRlID0gYml0cy5yZWFkQml0cyg4KTtcbiAgICAgICAgICAgICAgICBpZiAoZmlyc3RCeXRlID09PSAyNTQpIHsgLy8gVW5sYXRjaCBjb2Rld29yZFxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMucGFyc2VUd29CeXRlcyhmaXJzdEJ5dGUsIGJpdHMucmVhZEJpdHMoOCksIGNWYWx1ZXMpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMzsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNWYWx1ZSA9IGNWYWx1ZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoc2hpZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY1ZhbHVlIDwgMykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaGlmdCA9IGNWYWx1ZSArIDE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGNWYWx1ZSA8IHRoaXMuQzQwX0JBU0lDX1NFVF9DSEFSUy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYzQwY2hhciA9IHRoaXMuQzQwX0JBU0lDX1NFVF9DSEFSU1tjVmFsdWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodXBwZXJTaGlmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChTdHJpbmcuZnJvbUNoYXJDb2RlKGM0MGNoYXIuY2hhckNvZGVBdCgwKSArIDEyOCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBwZXJTaGlmdCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChjNDBjaGFyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodXBwZXJTaGlmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKFN0cmluZy5mcm9tQ2hhckNvZGUoY1ZhbHVlICsgMTI4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwcGVyU2hpZnQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoU3RyaW5nLmZyb21DaGFyQ29kZShjVmFsdWUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hpZnQgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjVmFsdWUgPCB0aGlzLkM0MF9TSElGVDJfU0VUX0NIQVJTLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjNDBjaGFyID0gdGhpcy5DNDBfU0hJRlQyX1NFVF9DSEFSU1tjVmFsdWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodXBwZXJTaGlmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChTdHJpbmcuZnJvbUNoYXJDb2RlKGM0MGNoYXIuY2hhckNvZGVBdCgwKSArIDEyOCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBwZXJTaGlmdCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChjNDBjaGFyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChjVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjc6IC8vIEZOQzFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKFN0cmluZy5mcm9tQ2hhckNvZGUoMjkpKTsgLy8gdHJhbnNsYXRlIGFzIEFTQ0lJIDI5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDMwOiAvLyBVcHBlciBTaGlmdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwcGVyU2hpZnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hpZnQgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh1cHBlclNoaWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoU3RyaW5nLmZyb21DaGFyQ29kZShjVmFsdWUgKyAyMjQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBwZXJTaGlmdCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChTdHJpbmcuZnJvbUNoYXJDb2RlKGNWYWx1ZSArIDk2KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoaWZ0ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSB3aGlsZSAoYml0cy5hdmFpbGFibGUoKSA+IDApO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZWUgSVNPIDE2MDIyOjIwMDYsIDUuMi42IGFuZCBBbm5leCBDLCBUYWJsZSBDLjJcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBkZWNvZGVUZXh0U2VnbWVudChiaXRzLCByZXN1bHQpIHtcbiAgICAgICAgICAgIC8vIFRocmVlIFRleHQgdmFsdWVzIGFyZSBlbmNvZGVkIGluIGEgMTYtYml0IHZhbHVlIGFzXG4gICAgICAgICAgICAvLyAoMTYwMCAqIEMxKSArICg0MCAqIEMyKSArIEMzICsgMVxuICAgICAgICAgICAgLy8gVE9ETyhiYnJvd24pOiBUaGUgVXBwZXIgU2hpZnQgd2l0aCBUZXh0IGRvZXNuJ3Qgd29yayBpbiB0aGUgNCB2YWx1ZSBzY2VuYXJpbyBhbGwgdGhlIHRpbWVcbiAgICAgICAgICAgIGxldCB1cHBlclNoaWZ0ID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgY1ZhbHVlcyA9IFtdO1xuICAgICAgICAgICAgbGV0IHNoaWZ0ID0gMDtcbiAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGVyZSBpcyBvbmx5IG9uZSBieXRlIGxlZnQgdGhlbiBpdCB3aWxsIGJlIGVuY29kZWQgYXMgQVNDSUlcbiAgICAgICAgICAgICAgICBpZiAoYml0cy5hdmFpbGFibGUoKSA9PT0gOCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGZpcnN0Qnl0ZSA9IGJpdHMucmVhZEJpdHMoOCk7XG4gICAgICAgICAgICAgICAgaWYgKGZpcnN0Qnl0ZSA9PT0gMjU0KSB7IC8vIFVubGF0Y2ggY29kZXdvcmRcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnBhcnNlVHdvQnl0ZXMoZmlyc3RCeXRlLCBiaXRzLnJlYWRCaXRzKDgpLCBjVmFsdWVzKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDM7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjVmFsdWUgPSBjVmFsdWVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHNoaWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNWYWx1ZSA8IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hpZnQgPSBjVmFsdWUgKyAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChjVmFsdWUgPCB0aGlzLlRFWFRfQkFTSUNfU0VUX0NIQVJTLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZXh0Q2hhciA9IHRoaXMuVEVYVF9CQVNJQ19TRVRfQ0hBUlNbY1ZhbHVlXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHVwcGVyU2hpZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoU3RyaW5nLmZyb21DaGFyQ29kZSh0ZXh0Q2hhci5jaGFyQ29kZUF0KDApICsgMTI4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cHBlclNoaWZ0ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKHRleHRDaGFyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodXBwZXJTaGlmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKFN0cmluZy5mcm9tQ2hhckNvZGUoY1ZhbHVlICsgMTI4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwcGVyU2hpZnQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoU3RyaW5nLmZyb21DaGFyQ29kZShjVmFsdWUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hpZnQgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNoaWZ0IDIgZm9yIFRleHQgaXMgdGhlIHNhbWUgZW5jb2RpbmcgYXMgQzQwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNWYWx1ZSA8IHRoaXMuVEVYVF9TSElGVDJfU0VUX0NIQVJTLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZXh0Q2hhciA9IHRoaXMuVEVYVF9TSElGVDJfU0VUX0NIQVJTW2NWYWx1ZV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh1cHBlclNoaWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKFN0cmluZy5mcm9tQ2hhckNvZGUodGV4dENoYXIuY2hhckNvZGVBdCgwKSArIDEyOCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBwZXJTaGlmdCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCh0ZXh0Q2hhcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoY1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDI3OiAvLyBGTkMxXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChTdHJpbmcuZnJvbUNoYXJDb2RlKDI5KSk7IC8vIHRyYW5zbGF0ZSBhcyBBU0NJSSAyOVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAzMDogLy8gVXBwZXIgU2hpZnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cHBlclNoaWZ0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoaWZ0ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY1ZhbHVlIDwgdGhpcy5URVhUX1NISUZUM19TRVRfQ0hBUlMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRleHRDaGFyID0gdGhpcy5URVhUX1NISUZUM19TRVRfQ0hBUlNbY1ZhbHVlXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHVwcGVyU2hpZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoU3RyaW5nLmZyb21DaGFyQ29kZSh0ZXh0Q2hhci5jaGFyQ29kZUF0KDApICsgMTI4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cHBlclNoaWZ0ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKHRleHRDaGFyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaGlmdCA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IHdoaWxlIChiaXRzLmF2YWlsYWJsZSgpID4gMCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNlZSBJU08gMTYwMjI6MjAwNiwgNS4yLjdcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBkZWNvZGVBbnNpWDEyU2VnbWVudChiaXRzLCByZXN1bHQpIHtcbiAgICAgICAgICAgIC8vIFRocmVlIEFOU0kgWDEyIHZhbHVlcyBhcmUgZW5jb2RlZCBpbiBhIDE2LWJpdCB2YWx1ZSBhc1xuICAgICAgICAgICAgLy8gKDE2MDAgKiBDMSkgKyAoNDAgKiBDMikgKyBDMyArIDFcbiAgICAgICAgICAgIGNvbnN0IGNWYWx1ZXMgPSBbXTtcbiAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGVyZSBpcyBvbmx5IG9uZSBieXRlIGxlZnQgdGhlbiBpdCB3aWxsIGJlIGVuY29kZWQgYXMgQVNDSUlcbiAgICAgICAgICAgICAgICBpZiAoYml0cy5hdmFpbGFibGUoKSA9PT0gOCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGZpcnN0Qnl0ZSA9IGJpdHMucmVhZEJpdHMoOCk7XG4gICAgICAgICAgICAgICAgaWYgKGZpcnN0Qnl0ZSA9PT0gMjU0KSB7IC8vIFVubGF0Y2ggY29kZXdvcmRcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnBhcnNlVHdvQnl0ZXMoZmlyc3RCeXRlLCBiaXRzLnJlYWRCaXRzKDgpLCBjVmFsdWVzKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDM7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjVmFsdWUgPSBjVmFsdWVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAwOiAvLyBYMTIgc2VnbWVudCB0ZXJtaW5hdG9yIDxDUj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCdcXHInKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMTogLy8gWDEyIHNlZ21lbnQgc2VwYXJhdG9yICpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCcqJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDI6IC8vIFgxMiBzdWItZWxlbWVudCBzZXBhcmF0b3IgPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoJz4nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMzogLy8gc3BhY2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCcgJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjVmFsdWUgPCAxNCkgeyAvLyAwIC0gOVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKFN0cmluZy5mcm9tQ2hhckNvZGUoY1ZhbHVlICsgNDQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoY1ZhbHVlIDwgNDApIHsgLy8gQSAtIFpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChTdHJpbmcuZnJvbUNoYXJDb2RlKGNWYWx1ZSArIDUxKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSB3aGlsZSAoYml0cy5hdmFpbGFibGUoKSA+IDApO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBwYXJzZVR3b0J5dGVzKGZpcnN0Qnl0ZSwgc2Vjb25kQnl0ZSwgcmVzdWx0KSB7XG4gICAgICAgICAgICBsZXQgZnVsbEJpdFZhbHVlID0gKGZpcnN0Qnl0ZSA8PCA4KSArIHNlY29uZEJ5dGUgLSAxO1xuICAgICAgICAgICAgbGV0IHRlbXAgPSBNYXRoLmZsb29yKGZ1bGxCaXRWYWx1ZSAvIDE2MDApO1xuICAgICAgICAgICAgcmVzdWx0WzBdID0gdGVtcDtcbiAgICAgICAgICAgIGZ1bGxCaXRWYWx1ZSAtPSB0ZW1wICogMTYwMDtcbiAgICAgICAgICAgIHRlbXAgPSBNYXRoLmZsb29yKGZ1bGxCaXRWYWx1ZSAvIDQwKTtcbiAgICAgICAgICAgIHJlc3VsdFsxXSA9IHRlbXA7XG4gICAgICAgICAgICByZXN1bHRbMl0gPSBmdWxsQml0VmFsdWUgLSB0ZW1wICogNDA7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNlZSBJU08gMTYwMjI6MjAwNiwgNS4yLjggYW5kIEFubmV4IEMgVGFibGUgQy4zXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGVjb2RlRWRpZmFjdFNlZ21lbnQoYml0cywgcmVzdWx0KSB7XG4gICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlcmUgaXMgb25seSB0d28gb3IgbGVzcyBieXRlcyBsZWZ0IHRoZW4gaXQgd2lsbCBiZSBlbmNvZGVkIGFzIEFTQ0lJXG4gICAgICAgICAgICAgICAgaWYgKGJpdHMuYXZhaWxhYmxlKCkgPD0gMTYpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgZWRpZmFjdFZhbHVlID0gYml0cy5yZWFkQml0cyg2KTtcbiAgICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgZm9yIHRoZSB1bmxhdGNoIGNoYXJhY3RlclxuICAgICAgICAgICAgICAgICAgICBpZiAoZWRpZmFjdFZhbHVlID09PSAweDFGKSB7IC8vIDAxMTExMVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVhZCByZXN0IG9mIGJ5dGUsIHdoaWNoIHNob3VsZCBiZSAwLCBhbmQgc3RvcFxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYml0c0xlZnQgPSA4IC0gYml0cy5nZXRCaXRPZmZzZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiaXRzTGVmdCAhPT0gOCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpdHMucmVhZEJpdHMoYml0c0xlZnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICgoZWRpZmFjdFZhbHVlICYgMHgyMCkgPT09IDApIHsgLy8gbm8gMSBpbiB0aGUgbGVhZGluZyAoNnRoKSBiaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIGVkaWZhY3RWYWx1ZSB8PSAweDQwOyAvLyBBZGQgYSBsZWFkaW5nIDAxIHRvIHRoZSA2IGJpdCBiaW5hcnkgdmFsdWVcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKFN0cmluZy5mcm9tQ2hhckNvZGUoZWRpZmFjdFZhbHVlKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSB3aGlsZSAoYml0cy5hdmFpbGFibGUoKSA+IDApO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZWUgSVNPIDE2MDIyOjIwMDYsIDUuMi45IGFuZCBBbm5leCBCLCBCLjJcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBkZWNvZGVCYXNlMjU2U2VnbWVudChiaXRzLCByZXN1bHQsIGJ5dGVTZWdtZW50cykge1xuICAgICAgICAgICAgLy8gRmlndXJlIG91dCBob3cgbG9uZyB0aGUgQmFzZSAyNTYgU2VnbWVudCBpcy5cbiAgICAgICAgICAgIGxldCBjb2Rld29yZFBvc2l0aW9uID0gMSArIGJpdHMuZ2V0Qnl0ZU9mZnNldCgpOyAvLyBwb3NpdGlvbiBpcyAxLWluZGV4ZWRcbiAgICAgICAgICAgIGNvbnN0IGQxID0gdGhpcy51bnJhbmRvbWl6ZTI1NVN0YXRlKGJpdHMucmVhZEJpdHMoOCksIGNvZGV3b3JkUG9zaXRpb24rKyk7XG4gICAgICAgICAgICBsZXQgY291bnQ7XG4gICAgICAgICAgICBpZiAoZDEgPT09IDApIHsgLy8gUmVhZCB0aGUgcmVtYWluZGVyIG9mIHRoZSBzeW1ib2xcbiAgICAgICAgICAgICAgICBjb3VudCA9IGJpdHMuYXZhaWxhYmxlKCkgLyA4IHwgMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGQxIDwgMjUwKSB7XG4gICAgICAgICAgICAgICAgY291bnQgPSBkMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvdW50ID0gMjUwICogKGQxIC0gMjQ5KSArIHRoaXMudW5yYW5kb21pemUyNTVTdGF0ZShiaXRzLnJlYWRCaXRzKDgpLCBjb2Rld29yZFBvc2l0aW9uKyspO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gV2UncmUgc2VlaW5nIE5lZ2F0aXZlQXJyYXlTaXplRXhjZXB0aW9uIGVycm9ycyBmcm9tIHVzZXJzLlxuICAgICAgICAgICAgaWYgKGNvdW50IDwgMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoY291bnQpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgLy8gSGF2ZSBzZWVuIHRoaXMgcGFydGljdWxhciBlcnJvciBpbiB0aGUgd2lsZCwgc3VjaCBhcyBhdFxuICAgICAgICAgICAgICAgIC8vIGh0dHA6Ly93d3cuYmNnZW4uY29tL2RlbW8vSURBdXRvbWF0aW9uU3RyZWFtaW5nRGF0YU1hdHJpeC5hc3B4P01PREU9MyZEPUZyZWQmUEZNVD0zJlBUPUYmWD0wLjMmTz0wJkxNPTAuMlxuICAgICAgICAgICAgICAgIGlmIChiaXRzLmF2YWlsYWJsZSgpIDwgOCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJ5dGVzW2ldID0gdGhpcy51bnJhbmRvbWl6ZTI1NVN0YXRlKGJpdHMucmVhZEJpdHMoOCksIGNvZGV3b3JkUG9zaXRpb24rKyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBieXRlU2VnbWVudHMucHVzaChieXRlcyk7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoU3RyaW5nRW5jb2RpbmcuZGVjb2RlKGJ5dGVzLCBTdHJpbmdVdGlscy5JU084ODU5MSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKHVlZSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oJ1BsYXRmb3JtIGRvZXMgbm90IHN1cHBvcnQgcmVxdWlyZWQgZW5jb2Rpbmc6ICcgKyB1ZWUubWVzc2FnZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNlZSBJU08gMTYwMjI6MjAwNiwgQW5uZXggQiwgQi4yXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgdW5yYW5kb21pemUyNTVTdGF0ZShyYW5kb21pemVkQmFzZTI1NkNvZGV3b3JkLCBiYXNlMjU2Q29kZXdvcmRQb3NpdGlvbikge1xuICAgICAgICAgICAgY29uc3QgcHNldWRvUmFuZG9tTnVtYmVyID0gKCgxNDkgKiBiYXNlMjU2Q29kZXdvcmRQb3NpdGlvbikgJSAyNTUpICsgMTtcbiAgICAgICAgICAgIGNvbnN0IHRlbXBWYXJpYWJsZSA9IHJhbmRvbWl6ZWRCYXNlMjU2Q29kZXdvcmQgLSBwc2V1ZG9SYW5kb21OdW1iZXI7XG4gICAgICAgICAgICByZXR1cm4gdGVtcFZhcmlhYmxlID49IDAgPyB0ZW1wVmFyaWFibGUgOiB0ZW1wVmFyaWFibGUgKyAyNTY7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogU2VlIElTTyAxNjAyMjoyMDA2LCBBbm5leCBDIFRhYmxlIEMuMVxuICAgICAqIFRoZSBDNDAgQmFzaWMgQ2hhcmFjdGVyIFNldCAoKidzIHVzZWQgZm9yIHBsYWNlaG9sZGVycyBmb3IgdGhlIHNoaWZ0IHZhbHVlcylcbiAgICAgKi9cbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyLkM0MF9CQVNJQ19TRVRfQ0hBUlMgPSBbXG4gICAgICAgICcqJywgJyonLCAnKicsICcgJywgJzAnLCAnMScsICcyJywgJzMnLCAnNCcsICc1JywgJzYnLCAnNycsICc4JywgJzknLFxuICAgICAgICAnQScsICdCJywgJ0MnLCAnRCcsICdFJywgJ0YnLCAnRycsICdIJywgJ0knLCAnSicsICdLJywgJ0wnLCAnTScsICdOJyxcbiAgICAgICAgJ08nLCAnUCcsICdRJywgJ1InLCAnUycsICdUJywgJ1UnLCAnVicsICdXJywgJ1gnLCAnWScsICdaJ1xuICAgIF07XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlci5DNDBfU0hJRlQyX1NFVF9DSEFSUyA9IFtcbiAgICAgICAgJyEnLCAnXCInLCAnIycsICckJywgJyUnLCAnJicsICdcXCcnLCAnKCcsICcpJywgJyonLCAnKycsICcsJywgJy0nLCAnLicsXG4gICAgICAgICcvJywgJzonLCAnOycsICc8JywgJz0nLCAnPicsICc/JywgJ0AnLCAnWycsICdcXFxcJywgJ10nLCAnXicsICdfJ1xuICAgIF07XG4gICAgLyoqXG4gICAgICogU2VlIElTTyAxNjAyMjoyMDA2LCBBbm5leCBDIFRhYmxlIEMuMlxuICAgICAqIFRoZSBUZXh0IEJhc2ljIENoYXJhY3RlciBTZXQgKConcyB1c2VkIGZvciBwbGFjZWhvbGRlcnMgZm9yIHRoZSBzaGlmdCB2YWx1ZXMpXG4gICAgICovXG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlci5URVhUX0JBU0lDX1NFVF9DSEFSUyA9IFtcbiAgICAgICAgJyonLCAnKicsICcqJywgJyAnLCAnMCcsICcxJywgJzInLCAnMycsICc0JywgJzUnLCAnNicsICc3JywgJzgnLCAnOScsXG4gICAgICAgICdhJywgJ2InLCAnYycsICdkJywgJ2UnLCAnZicsICdnJywgJ2gnLCAnaScsICdqJywgJ2snLCAnbCcsICdtJywgJ24nLFxuICAgICAgICAnbycsICdwJywgJ3EnLCAncicsICdzJywgJ3QnLCAndScsICd2JywgJ3cnLCAneCcsICd5JywgJ3onXG4gICAgXTtcbiAgICAvLyBTaGlmdCAyIGZvciBUZXh0IGlzIHRoZSBzYW1lIGVuY29kaW5nIGFzIEM0MFxuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIuVEVYVF9TSElGVDJfU0VUX0NIQVJTID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlci5DNDBfU0hJRlQyX1NFVF9DSEFSUztcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyLlRFWFRfU0hJRlQzX1NFVF9DSEFSUyA9IFtcbiAgICAgICAgJ2AnLCAnQScsICdCJywgJ0MnLCAnRCcsICdFJywgJ0YnLCAnRycsICdIJywgJ0knLCAnSicsICdLJywgJ0wnLCAnTScsICdOJyxcbiAgICAgICAgJ08nLCAnUCcsICdRJywgJ1InLCAnUycsICdUJywgJ1UnLCAnVicsICdXJywgJ1gnLCAnWScsICdaJywgJ3snLCAnfCcsICd9JywgJ34nLCBTdHJpbmcuZnJvbUNoYXJDb2RlKDEyNylcbiAgICBdO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiA8cD5UaGUgbWFpbiBjbGFzcyB3aGljaCBpbXBsZW1lbnRzIERhdGEgTWF0cml4IENvZGUgZGVjb2RpbmcgLS0gYXMgb3Bwb3NlZCB0byBsb2NhdGluZyBhbmQgZXh0cmFjdGluZ1xuICAgICAqIHRoZSBEYXRhIE1hdHJpeCBDb2RlIGZyb20gYW4gaW1hZ2UuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBiYnJvd25AZ29vZ2xlLmNvbSAoQnJpYW4gQnJvd24pXG4gICAgICovXG4gICAgY2xhc3MgRGVjb2RlciQxIHtcbiAgICAgICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgICAgICB0aGlzLnJzRGVjb2RlciA9IG5ldyBSZWVkU29sb21vbkRlY29kZXIoR2VuZXJpY0dGLkRBVEFfTUFUUklYX0ZJRUxEXzI1Nik7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkRlY29kZXMgYSBEYXRhIE1hdHJpeCBDb2RlIHJlcHJlc2VudGVkIGFzIGEge0BsaW5rIEJpdE1hdHJpeH0uIEEgMSBvciBcInRydWVcIiBpcyB0YWtlblxuICAgICAgICAgKiB0byBtZWFuIGEgYmxhY2sgbW9kdWxlLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGJpdHMgYm9vbGVhbnMgcmVwcmVzZW50aW5nIHdoaXRlL2JsYWNrIERhdGEgTWF0cml4IENvZGUgbW9kdWxlc1xuICAgICAgICAgKiBAcmV0dXJuIHRleHQgYW5kIGJ5dGVzIGVuY29kZWQgd2l0aGluIHRoZSBEYXRhIE1hdHJpeCBDb2RlXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uIGlmIHRoZSBEYXRhIE1hdHJpeCBDb2RlIGNhbm5vdCBiZSBkZWNvZGVkXG4gICAgICAgICAqIEB0aHJvd3MgQ2hlY2tzdW1FeGNlcHRpb24gaWYgZXJyb3IgY29ycmVjdGlvbiBmYWlsc1xuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlKGJpdHMpIHtcbiAgICAgICAgICAgIC8vIENvbnN0cnVjdCBhIHBhcnNlciBhbmQgcmVhZCB2ZXJzaW9uLCBlcnJvci1jb3JyZWN0aW9uIGxldmVsXG4gICAgICAgICAgICBjb25zdCBwYXJzZXIgPSBuZXcgQml0TWF0cml4UGFyc2VyKGJpdHMpO1xuICAgICAgICAgICAgY29uc3QgdmVyc2lvbiA9IHBhcnNlci5nZXRWZXJzaW9uKCk7XG4gICAgICAgICAgICAvLyBSZWFkIGNvZGV3b3Jkc1xuICAgICAgICAgICAgY29uc3QgY29kZXdvcmRzID0gcGFyc2VyLnJlYWRDb2Rld29yZHMoKTtcbiAgICAgICAgICAgIC8vIFNlcGFyYXRlIGludG8gZGF0YSBibG9ja3NcbiAgICAgICAgICAgIGNvbnN0IGRhdGFCbG9ja3MgPSBEYXRhQmxvY2suZ2V0RGF0YUJsb2Nrcyhjb2Rld29yZHMsIHZlcnNpb24pO1xuICAgICAgICAgICAgLy8gQ291bnQgdG90YWwgbnVtYmVyIG9mIGRhdGEgYnl0ZXNcbiAgICAgICAgICAgIGxldCB0b3RhbEJ5dGVzID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGRiIG9mIGRhdGFCbG9ja3MpIHtcbiAgICAgICAgICAgICAgICB0b3RhbEJ5dGVzICs9IGRiLmdldE51bURhdGFDb2Rld29yZHMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdEJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkodG90YWxCeXRlcyk7XG4gICAgICAgICAgICBjb25zdCBkYXRhQmxvY2tzQ291bnQgPSBkYXRhQmxvY2tzLmxlbmd0aDtcbiAgICAgICAgICAgIC8vIEVycm9yLWNvcnJlY3QgYW5kIGNvcHkgZGF0YSBibG9ja3MgdG9nZXRoZXIgaW50byBhIHN0cmVhbSBvZiBieXRlc1xuICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBkYXRhQmxvY2tzQ291bnQ7IGorKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGFCbG9jayA9IGRhdGFCbG9ja3Nbal07XG4gICAgICAgICAgICAgICAgY29uc3QgY29kZXdvcmRCeXRlcyA9IGRhdGFCbG9jay5nZXRDb2Rld29yZHMoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBudW1EYXRhQ29kZXdvcmRzID0gZGF0YUJsb2NrLmdldE51bURhdGFDb2Rld29yZHMoKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvcnJlY3RFcnJvcnMoY29kZXdvcmRCeXRlcywgbnVtRGF0YUNvZGV3b3Jkcyk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1EYXRhQ29kZXdvcmRzOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRGUtaW50ZXJsYWNlIGRhdGEgYmxvY2tzLlxuICAgICAgICAgICAgICAgICAgICByZXN1bHRCeXRlc1tpICogZGF0YUJsb2Nrc0NvdW50ICsgal0gPSBjb2Rld29yZEJ5dGVzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIERlY29kZSB0aGUgY29udGVudHMgb2YgdGhhdCBzdHJlYW0gb2YgYnl0ZXNcbiAgICAgICAgICAgIHJldHVybiBEZWNvZGVkQml0U3RyZWFtUGFyc2VyLmRlY29kZShyZXN1bHRCeXRlcyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkdpdmVuIGRhdGEgYW5kIGVycm9yLWNvcnJlY3Rpb24gY29kZXdvcmRzIHJlY2VpdmVkLCBwb3NzaWJseSBjb3JydXB0ZWQgYnkgZXJyb3JzLCBhdHRlbXB0cyB0b1xuICAgICAgICAgKiBjb3JyZWN0IHRoZSBlcnJvcnMgaW4tcGxhY2UgdXNpbmcgUmVlZC1Tb2xvbW9uIGVycm9yIGNvcnJlY3Rpb24uPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gY29kZXdvcmRCeXRlcyBkYXRhIGFuZCBlcnJvciBjb3JyZWN0aW9uIGNvZGV3b3Jkc1xuICAgICAgICAgKiBAcGFyYW0gbnVtRGF0YUNvZGV3b3JkcyBudW1iZXIgb2YgY29kZXdvcmRzIHRoYXQgYXJlIGRhdGEgYnl0ZXNcbiAgICAgICAgICogQHRocm93cyBDaGVja3N1bUV4Y2VwdGlvbiBpZiBlcnJvciBjb3JyZWN0aW9uIGZhaWxzXG4gICAgICAgICAqL1xuICAgICAgICBjb3JyZWN0RXJyb3JzKGNvZGV3b3JkQnl0ZXMsIG51bURhdGFDb2Rld29yZHMpIHtcbiAgICAgICAgICAgIC8vIGNvbnN0IG51bUNvZGV3b3JkcyA9IGNvZGV3b3JkQnl0ZXMubGVuZ3RoO1xuICAgICAgICAgICAgLy8gRmlyc3QgcmVhZCBpbnRvIGFuIGFycmF5IG9mIGludHNcbiAgICAgICAgICAgIGNvbnN0IGNvZGV3b3Jkc0ludHMgPSBuZXcgSW50MzJBcnJheShjb2Rld29yZEJ5dGVzKTtcbiAgICAgICAgICAgIC8vIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtQ29kZXdvcmRzOyBpKyspIHtcbiAgICAgICAgICAgIC8vICAgY29kZXdvcmRzSW50c1tpXSA9IGNvZGV3b3JkQnl0ZXNbaV0gJiAweEZGO1xuICAgICAgICAgICAgLy8gfVxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB0aGlzLnJzRGVjb2Rlci5kZWNvZGUoY29kZXdvcmRzSW50cywgY29kZXdvcmRCeXRlcy5sZW5ndGggLSBudW1EYXRhQ29kZXdvcmRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChpZ25vcmVkIC8qIFJlZWRTb2xvbW9uRXhjZXB0aW9uICovKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IENoZWNrc3VtRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBDb3B5IGJhY2sgaW50byBhcnJheSBvZiBieXRlcyAtLSBvbmx5IG5lZWQgdG8gd29ycnkgYWJvdXQgdGhlIGJ5dGVzIHRoYXQgd2VyZSBkYXRhXG4gICAgICAgICAgICAvLyBXZSBkb24ndCBjYXJlIGFib3V0IGVycm9ycyBpbiB0aGUgZXJyb3ItY29ycmVjdGlvbiBjb2Rld29yZHNcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtRGF0YUNvZGV3b3JkczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29kZXdvcmRCeXRlc1tpXSA9IGNvZGV3b3Jkc0ludHNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiA8cD5FbmNhcHN1bGF0ZXMgbG9naWMgdGhhdCBjYW4gZGV0ZWN0IGEgRGF0YSBNYXRyaXggQ29kZSBpbiBhbiBpbWFnZSwgZXZlbiBpZiB0aGUgRGF0YSBNYXRyaXggQ29kZVxuICAgICAqIGlzIHJvdGF0ZWQgb3Igc2tld2VkLCBvciBwYXJ0aWFsbHkgb2JzY3VyZWQuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBEZXRlY3RvciQxIHtcbiAgICAgICAgY29uc3RydWN0b3IoaW1hZ2UpIHtcbiAgICAgICAgICAgIHRoaXMuaW1hZ2UgPSBpbWFnZTtcbiAgICAgICAgICAgIHRoaXMucmVjdGFuZ2xlRGV0ZWN0b3IgPSBuZXcgV2hpdGVSZWN0YW5nbGVEZXRlY3Rvcih0aGlzLmltYWdlKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+RGV0ZWN0cyBhIERhdGEgTWF0cml4IENvZGUgaW4gYW4gaW1hZ2UuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIHtAbGluayBEZXRlY3RvclJlc3VsdH0gZW5jYXBzdWxhdGluZyByZXN1bHRzIG9mIGRldGVjdGluZyBhIERhdGEgTWF0cml4IENvZGVcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBpZiBubyBEYXRhIE1hdHJpeCBDb2RlIGNhbiBiZSBmb3VuZFxuICAgICAgICAgKi9cbiAgICAgICAgZGV0ZWN0KCkge1xuICAgICAgICAgICAgY29uc3QgY29ybmVyUG9pbnRzID0gdGhpcy5yZWN0YW5nbGVEZXRlY3Rvci5kZXRlY3QoKTtcbiAgICAgICAgICAgIGxldCBwb2ludHMgPSB0aGlzLmRldGVjdFNvbGlkMShjb3JuZXJQb2ludHMpO1xuICAgICAgICAgICAgcG9pbnRzID0gdGhpcy5kZXRlY3RTb2xpZDIocG9pbnRzKTtcbiAgICAgICAgICAgIHBvaW50c1szXSA9IHRoaXMuY29ycmVjdFRvcFJpZ2h0KHBvaW50cyk7XG4gICAgICAgICAgICBpZiAoIXBvaW50c1szXSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcG9pbnRzID0gdGhpcy5zaGlmdFRvTW9kdWxlQ2VudGVyKHBvaW50cyk7XG4gICAgICAgICAgICBjb25zdCB0b3BMZWZ0ID0gcG9pbnRzWzBdO1xuICAgICAgICAgICAgY29uc3QgYm90dG9tTGVmdCA9IHBvaW50c1sxXTtcbiAgICAgICAgICAgIGNvbnN0IGJvdHRvbVJpZ2h0ID0gcG9pbnRzWzJdO1xuICAgICAgICAgICAgY29uc3QgdG9wUmlnaHQgPSBwb2ludHNbM107XG4gICAgICAgICAgICBsZXQgZGltZW5zaW9uVG9wID0gdGhpcy50cmFuc2l0aW9uc0JldHdlZW4odG9wTGVmdCwgdG9wUmlnaHQpICsgMTtcbiAgICAgICAgICAgIGxldCBkaW1lbnNpb25SaWdodCA9IHRoaXMudHJhbnNpdGlvbnNCZXR3ZWVuKGJvdHRvbVJpZ2h0LCB0b3BSaWdodCkgKyAxO1xuICAgICAgICAgICAgaWYgKChkaW1lbnNpb25Ub3AgJiAweDAxKSA9PT0gMSkge1xuICAgICAgICAgICAgICAgIGRpbWVuc2lvblRvcCArPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKChkaW1lbnNpb25SaWdodCAmIDB4MDEpID09PSAxKSB7XG4gICAgICAgICAgICAgICAgZGltZW5zaW9uUmlnaHQgKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICg0ICogZGltZW5zaW9uVG9wIDwgNyAqIGRpbWVuc2lvblJpZ2h0ICYmIDQgKiBkaW1lbnNpb25SaWdodCA8IDcgKiBkaW1lbnNpb25Ub3ApIHtcbiAgICAgICAgICAgICAgICAvLyBUaGUgbWF0cml4IGlzIHNxdWFyZVxuICAgICAgICAgICAgICAgIGRpbWVuc2lvblRvcCA9IGRpbWVuc2lvblJpZ2h0ID0gTWF0aC5tYXgoZGltZW5zaW9uVG9wLCBkaW1lbnNpb25SaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgYml0cyA9IERldGVjdG9yJDEuc2FtcGxlR3JpZCh0aGlzLmltYWdlLCB0b3BMZWZ0LCBib3R0b21MZWZ0LCBib3R0b21SaWdodCwgdG9wUmlnaHQsIGRpbWVuc2lvblRvcCwgZGltZW5zaW9uUmlnaHQpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBEZXRlY3RvclJlc3VsdChiaXRzLCBbdG9wTGVmdCwgYm90dG9tTGVmdCwgYm90dG9tUmlnaHQsIHRvcFJpZ2h0XSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHNoaWZ0UG9pbnQocG9pbnQsIHRvLCBkaXYpIHtcbiAgICAgICAgICAgIGxldCB4ID0gKHRvLmdldFgoKSAtIHBvaW50LmdldFgoKSkgLyAoZGl2ICsgMSk7XG4gICAgICAgICAgICBsZXQgeSA9ICh0by5nZXRZKCkgLSBwb2ludC5nZXRZKCkpIC8gKGRpdiArIDEpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBSZXN1bHRQb2ludChwb2ludC5nZXRYKCkgKyB4LCBwb2ludC5nZXRZKCkgKyB5KTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgbW92ZUF3YXkocG9pbnQsIGZyb21YLCBmcm9tWSkge1xuICAgICAgICAgICAgbGV0IHggPSBwb2ludC5nZXRYKCk7XG4gICAgICAgICAgICBsZXQgeSA9IHBvaW50LmdldFkoKTtcbiAgICAgICAgICAgIGlmICh4IDwgZnJvbVgpIHtcbiAgICAgICAgICAgICAgICB4IC09IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB4ICs9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoeSA8IGZyb21ZKSB7XG4gICAgICAgICAgICAgICAgeSAtPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgeSArPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBSZXN1bHRQb2ludCh4LCB5KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGV0ZWN0IGEgc29saWQgc2lkZSB3aGljaCBoYXMgbWluaW11bSB0cmFuc2l0aW9uLlxuICAgICAgICAgKi9cbiAgICAgICAgZGV0ZWN0U29saWQxKGNvcm5lclBvaW50cykge1xuICAgICAgICAgICAgLy8gMCAgMlxuICAgICAgICAgICAgLy8gMSAgM1xuICAgICAgICAgICAgbGV0IHBvaW50QSA9IGNvcm5lclBvaW50c1swXTtcbiAgICAgICAgICAgIGxldCBwb2ludEIgPSBjb3JuZXJQb2ludHNbMV07XG4gICAgICAgICAgICBsZXQgcG9pbnRDID0gY29ybmVyUG9pbnRzWzNdO1xuICAgICAgICAgICAgbGV0IHBvaW50RCA9IGNvcm5lclBvaW50c1syXTtcbiAgICAgICAgICAgIGxldCB0ckFCID0gdGhpcy50cmFuc2l0aW9uc0JldHdlZW4ocG9pbnRBLCBwb2ludEIpO1xuICAgICAgICAgICAgbGV0IHRyQkMgPSB0aGlzLnRyYW5zaXRpb25zQmV0d2Vlbihwb2ludEIsIHBvaW50Qyk7XG4gICAgICAgICAgICBsZXQgdHJDRCA9IHRoaXMudHJhbnNpdGlvbnNCZXR3ZWVuKHBvaW50QywgcG9pbnREKTtcbiAgICAgICAgICAgIGxldCB0ckRBID0gdGhpcy50cmFuc2l0aW9uc0JldHdlZW4ocG9pbnRELCBwb2ludEEpO1xuICAgICAgICAgICAgLy8gMC4uM1xuICAgICAgICAgICAgLy8gOiAgOlxuICAgICAgICAgICAgLy8gMS0tMlxuICAgICAgICAgICAgbGV0IG1pbiA9IHRyQUI7XG4gICAgICAgICAgICBsZXQgcG9pbnRzID0gW3BvaW50RCwgcG9pbnRBLCBwb2ludEIsIHBvaW50Q107XG4gICAgICAgICAgICBpZiAobWluID4gdHJCQykge1xuICAgICAgICAgICAgICAgIG1pbiA9IHRyQkM7XG4gICAgICAgICAgICAgICAgcG9pbnRzWzBdID0gcG9pbnRBO1xuICAgICAgICAgICAgICAgIHBvaW50c1sxXSA9IHBvaW50QjtcbiAgICAgICAgICAgICAgICBwb2ludHNbMl0gPSBwb2ludEM7XG4gICAgICAgICAgICAgICAgcG9pbnRzWzNdID0gcG9pbnREO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1pbiA+IHRyQ0QpIHtcbiAgICAgICAgICAgICAgICBtaW4gPSB0ckNEO1xuICAgICAgICAgICAgICAgIHBvaW50c1swXSA9IHBvaW50QjtcbiAgICAgICAgICAgICAgICBwb2ludHNbMV0gPSBwb2ludEM7XG4gICAgICAgICAgICAgICAgcG9pbnRzWzJdID0gcG9pbnREO1xuICAgICAgICAgICAgICAgIHBvaW50c1szXSA9IHBvaW50QTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtaW4gPiB0ckRBKSB7XG4gICAgICAgICAgICAgICAgcG9pbnRzWzBdID0gcG9pbnRDO1xuICAgICAgICAgICAgICAgIHBvaW50c1sxXSA9IHBvaW50RDtcbiAgICAgICAgICAgICAgICBwb2ludHNbMl0gPSBwb2ludEE7XG4gICAgICAgICAgICAgICAgcG9pbnRzWzNdID0gcG9pbnRCO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHBvaW50cztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGV0ZWN0IGEgc2Vjb25kIHNvbGlkIHNpZGUgbmV4dCB0byBmaXJzdCBzb2xpZCBzaWRlLlxuICAgICAgICAgKi9cbiAgICAgICAgZGV0ZWN0U29saWQyKHBvaW50cykge1xuICAgICAgICAgICAgLy8gQS4uRFxuICAgICAgICAgICAgLy8gOiAgOlxuICAgICAgICAgICAgLy8gQi0tQ1xuICAgICAgICAgICAgbGV0IHBvaW50QSA9IHBvaW50c1swXTtcbiAgICAgICAgICAgIGxldCBwb2ludEIgPSBwb2ludHNbMV07XG4gICAgICAgICAgICBsZXQgcG9pbnRDID0gcG9pbnRzWzJdO1xuICAgICAgICAgICAgbGV0IHBvaW50RCA9IHBvaW50c1szXTtcbiAgICAgICAgICAgIC8vIFRyYW5zaXRpb24gZGV0ZWN0aW9uIG9uIHRoZSBlZGdlIGlzIG5vdCBzdGFibGUuXG4gICAgICAgICAgICAvLyBUbyBzYWZlbHkgZGV0ZWN0LCBzaGlmdCB0aGUgcG9pbnRzIHRvIHRoZSBtb2R1bGUgY2VudGVyLlxuICAgICAgICAgICAgbGV0IHRyID0gdGhpcy50cmFuc2l0aW9uc0JldHdlZW4ocG9pbnRBLCBwb2ludEQpO1xuICAgICAgICAgICAgbGV0IHBvaW50QnMgPSBEZXRlY3RvciQxLnNoaWZ0UG9pbnQocG9pbnRCLCBwb2ludEMsICh0ciArIDEpICogNCk7XG4gICAgICAgICAgICBsZXQgcG9pbnRDcyA9IERldGVjdG9yJDEuc2hpZnRQb2ludChwb2ludEMsIHBvaW50QiwgKHRyICsgMSkgKiA0KTtcbiAgICAgICAgICAgIGxldCB0ckJBID0gdGhpcy50cmFuc2l0aW9uc0JldHdlZW4ocG9pbnRCcywgcG9pbnRBKTtcbiAgICAgICAgICAgIGxldCB0ckNEID0gdGhpcy50cmFuc2l0aW9uc0JldHdlZW4ocG9pbnRDcywgcG9pbnREKTtcbiAgICAgICAgICAgIC8vIDAuLjNcbiAgICAgICAgICAgIC8vIHwgIDpcbiAgICAgICAgICAgIC8vIDEtLTJcbiAgICAgICAgICAgIGlmICh0ckJBIDwgdHJDRCkge1xuICAgICAgICAgICAgICAgIC8vIHNvbGlkIHNpZGVzOiBBLUItQ1xuICAgICAgICAgICAgICAgIHBvaW50c1swXSA9IHBvaW50QTtcbiAgICAgICAgICAgICAgICBwb2ludHNbMV0gPSBwb2ludEI7XG4gICAgICAgICAgICAgICAgcG9pbnRzWzJdID0gcG9pbnRDO1xuICAgICAgICAgICAgICAgIHBvaW50c1szXSA9IHBvaW50RDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIHNvbGlkIHNpZGVzOiBCLUMtRFxuICAgICAgICAgICAgICAgIHBvaW50c1swXSA9IHBvaW50QjtcbiAgICAgICAgICAgICAgICBwb2ludHNbMV0gPSBwb2ludEM7XG4gICAgICAgICAgICAgICAgcG9pbnRzWzJdID0gcG9pbnREO1xuICAgICAgICAgICAgICAgIHBvaW50c1szXSA9IHBvaW50QTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBwb2ludHM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENhbGN1bGF0ZXMgdGhlIGNvcm5lciBwb3NpdGlvbiBvZiB0aGUgd2hpdGUgdG9wIHJpZ2h0IG1vZHVsZS5cbiAgICAgICAgICovXG4gICAgICAgIGNvcnJlY3RUb3BSaWdodChwb2ludHMpIHtcbiAgICAgICAgICAgIC8vIEEuLkRcbiAgICAgICAgICAgIC8vIHwgIDpcbiAgICAgICAgICAgIC8vIEItLUNcbiAgICAgICAgICAgIGxldCBwb2ludEEgPSBwb2ludHNbMF07XG4gICAgICAgICAgICBsZXQgcG9pbnRCID0gcG9pbnRzWzFdO1xuICAgICAgICAgICAgbGV0IHBvaW50QyA9IHBvaW50c1syXTtcbiAgICAgICAgICAgIGxldCBwb2ludEQgPSBwb2ludHNbM107XG4gICAgICAgICAgICAvLyBzaGlmdCBwb2ludHMgZm9yIHNhZmUgdHJhbnNpdGlvbiBkZXRlY3Rpb24uXG4gICAgICAgICAgICBsZXQgdHJUb3AgPSB0aGlzLnRyYW5zaXRpb25zQmV0d2Vlbihwb2ludEEsIHBvaW50RCk7XG4gICAgICAgICAgICBsZXQgdHJSaWdodCA9IHRoaXMudHJhbnNpdGlvbnNCZXR3ZWVuKHBvaW50QiwgcG9pbnREKTtcbiAgICAgICAgICAgIGxldCBwb2ludEFzID0gRGV0ZWN0b3IkMS5zaGlmdFBvaW50KHBvaW50QSwgcG9pbnRCLCAodHJSaWdodCArIDEpICogNCk7XG4gICAgICAgICAgICBsZXQgcG9pbnRDcyA9IERldGVjdG9yJDEuc2hpZnRQb2ludChwb2ludEMsIHBvaW50QiwgKHRyVG9wICsgMSkgKiA0KTtcbiAgICAgICAgICAgIHRyVG9wID0gdGhpcy50cmFuc2l0aW9uc0JldHdlZW4ocG9pbnRBcywgcG9pbnREKTtcbiAgICAgICAgICAgIHRyUmlnaHQgPSB0aGlzLnRyYW5zaXRpb25zQmV0d2Vlbihwb2ludENzLCBwb2ludEQpO1xuICAgICAgICAgICAgbGV0IGNhbmRpZGF0ZTEgPSBuZXcgUmVzdWx0UG9pbnQocG9pbnRELmdldFgoKSArIChwb2ludEMuZ2V0WCgpIC0gcG9pbnRCLmdldFgoKSkgLyAodHJUb3AgKyAxKSwgcG9pbnRELmdldFkoKSArIChwb2ludEMuZ2V0WSgpIC0gcG9pbnRCLmdldFkoKSkgLyAodHJUb3AgKyAxKSk7XG4gICAgICAgICAgICBsZXQgY2FuZGlkYXRlMiA9IG5ldyBSZXN1bHRQb2ludChwb2ludEQuZ2V0WCgpICsgKHBvaW50QS5nZXRYKCkgLSBwb2ludEIuZ2V0WCgpKSAvICh0clJpZ2h0ICsgMSksIHBvaW50RC5nZXRZKCkgKyAocG9pbnRBLmdldFkoKSAtIHBvaW50Qi5nZXRZKCkpIC8gKHRyUmlnaHQgKyAxKSk7XG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNWYWxpZChjYW5kaWRhdGUxKSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzVmFsaWQoY2FuZGlkYXRlMikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNhbmRpZGF0ZTI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoY2FuZGlkYXRlMikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2FuZGlkYXRlMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBzdW1jMSA9IHRoaXMudHJhbnNpdGlvbnNCZXR3ZWVuKHBvaW50QXMsIGNhbmRpZGF0ZTEpICsgdGhpcy50cmFuc2l0aW9uc0JldHdlZW4ocG9pbnRDcywgY2FuZGlkYXRlMSk7XG4gICAgICAgICAgICBsZXQgc3VtYzIgPSB0aGlzLnRyYW5zaXRpb25zQmV0d2Vlbihwb2ludEFzLCBjYW5kaWRhdGUyKSArIHRoaXMudHJhbnNpdGlvbnNCZXR3ZWVuKHBvaW50Q3MsIGNhbmRpZGF0ZTIpO1xuICAgICAgICAgICAgaWYgKHN1bWMxID4gc3VtYzIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2FuZGlkYXRlMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBjYW5kaWRhdGUyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTaGlmdCB0aGUgZWRnZSBwb2ludHMgdG8gdGhlIG1vZHVsZSBjZW50ZXIuXG4gICAgICAgICAqL1xuICAgICAgICBzaGlmdFRvTW9kdWxlQ2VudGVyKHBvaW50cykge1xuICAgICAgICAgICAgLy8gQS4uRFxuICAgICAgICAgICAgLy8gfCAgOlxuICAgICAgICAgICAgLy8gQi0tQ1xuICAgICAgICAgICAgbGV0IHBvaW50QSA9IHBvaW50c1swXTtcbiAgICAgICAgICAgIGxldCBwb2ludEIgPSBwb2ludHNbMV07XG4gICAgICAgICAgICBsZXQgcG9pbnRDID0gcG9pbnRzWzJdO1xuICAgICAgICAgICAgbGV0IHBvaW50RCA9IHBvaW50c1szXTtcbiAgICAgICAgICAgIC8vIGNhbGN1bGF0ZSBwc2V1ZG8gZGltZW5zaW9uc1xuICAgICAgICAgICAgbGV0IGRpbUggPSB0aGlzLnRyYW5zaXRpb25zQmV0d2Vlbihwb2ludEEsIHBvaW50RCkgKyAxO1xuICAgICAgICAgICAgbGV0IGRpbVYgPSB0aGlzLnRyYW5zaXRpb25zQmV0d2Vlbihwb2ludEMsIHBvaW50RCkgKyAxO1xuICAgICAgICAgICAgLy8gc2hpZnQgcG9pbnRzIGZvciBzYWZlIGRpbWVuc2lvbiBkZXRlY3Rpb25cbiAgICAgICAgICAgIGxldCBwb2ludEFzID0gRGV0ZWN0b3IkMS5zaGlmdFBvaW50KHBvaW50QSwgcG9pbnRCLCBkaW1WICogNCk7XG4gICAgICAgICAgICBsZXQgcG9pbnRDcyA9IERldGVjdG9yJDEuc2hpZnRQb2ludChwb2ludEMsIHBvaW50QiwgZGltSCAqIDQpO1xuICAgICAgICAgICAgLy8gIGNhbGN1bGF0ZSBtb3JlIHByZWNpc2UgZGltZW5zaW9uc1xuICAgICAgICAgICAgZGltSCA9IHRoaXMudHJhbnNpdGlvbnNCZXR3ZWVuKHBvaW50QXMsIHBvaW50RCkgKyAxO1xuICAgICAgICAgICAgZGltViA9IHRoaXMudHJhbnNpdGlvbnNCZXR3ZWVuKHBvaW50Q3MsIHBvaW50RCkgKyAxO1xuICAgICAgICAgICAgaWYgKChkaW1IICYgMHgwMSkgPT09IDEpIHtcbiAgICAgICAgICAgICAgICBkaW1IICs9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoKGRpbVYgJiAweDAxKSA9PT0gMSkge1xuICAgICAgICAgICAgICAgIGRpbVYgKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFdoaXRlUmVjdGFuZ2xlRGV0ZWN0b3IgcmV0dXJucyBwb2ludHMgaW5zaWRlIG9mIHRoZSByZWN0YW5nbGUuXG4gICAgICAgICAgICAvLyBJIHdhbnQgcG9pbnRzIG9uIHRoZSBlZGdlcy5cbiAgICAgICAgICAgIGxldCBjZW50ZXJYID0gKHBvaW50QS5nZXRYKCkgKyBwb2ludEIuZ2V0WCgpICsgcG9pbnRDLmdldFgoKSArIHBvaW50RC5nZXRYKCkpIC8gNDtcbiAgICAgICAgICAgIGxldCBjZW50ZXJZID0gKHBvaW50QS5nZXRZKCkgKyBwb2ludEIuZ2V0WSgpICsgcG9pbnRDLmdldFkoKSArIHBvaW50RC5nZXRZKCkpIC8gNDtcbiAgICAgICAgICAgIHBvaW50QSA9IERldGVjdG9yJDEubW92ZUF3YXkocG9pbnRBLCBjZW50ZXJYLCBjZW50ZXJZKTtcbiAgICAgICAgICAgIHBvaW50QiA9IERldGVjdG9yJDEubW92ZUF3YXkocG9pbnRCLCBjZW50ZXJYLCBjZW50ZXJZKTtcbiAgICAgICAgICAgIHBvaW50QyA9IERldGVjdG9yJDEubW92ZUF3YXkocG9pbnRDLCBjZW50ZXJYLCBjZW50ZXJZKTtcbiAgICAgICAgICAgIHBvaW50RCA9IERldGVjdG9yJDEubW92ZUF3YXkocG9pbnRELCBjZW50ZXJYLCBjZW50ZXJZKTtcbiAgICAgICAgICAgIGxldCBwb2ludEJzO1xuICAgICAgICAgICAgbGV0IHBvaW50RHM7XG4gICAgICAgICAgICAvLyBzaGlmdCBwb2ludHMgdG8gdGhlIGNlbnRlciBvZiBlYWNoIG1vZHVsZXNcbiAgICAgICAgICAgIHBvaW50QXMgPSBEZXRlY3RvciQxLnNoaWZ0UG9pbnQocG9pbnRBLCBwb2ludEIsIGRpbVYgKiA0KTtcbiAgICAgICAgICAgIHBvaW50QXMgPSBEZXRlY3RvciQxLnNoaWZ0UG9pbnQocG9pbnRBcywgcG9pbnRELCBkaW1IICogNCk7XG4gICAgICAgICAgICBwb2ludEJzID0gRGV0ZWN0b3IkMS5zaGlmdFBvaW50KHBvaW50QiwgcG9pbnRBLCBkaW1WICogNCk7XG4gICAgICAgICAgICBwb2ludEJzID0gRGV0ZWN0b3IkMS5zaGlmdFBvaW50KHBvaW50QnMsIHBvaW50QywgZGltSCAqIDQpO1xuICAgICAgICAgICAgcG9pbnRDcyA9IERldGVjdG9yJDEuc2hpZnRQb2ludChwb2ludEMsIHBvaW50RCwgZGltViAqIDQpO1xuICAgICAgICAgICAgcG9pbnRDcyA9IERldGVjdG9yJDEuc2hpZnRQb2ludChwb2ludENzLCBwb2ludEIsIGRpbUggKiA0KTtcbiAgICAgICAgICAgIHBvaW50RHMgPSBEZXRlY3RvciQxLnNoaWZ0UG9pbnQocG9pbnRELCBwb2ludEMsIGRpbVYgKiA0KTtcbiAgICAgICAgICAgIHBvaW50RHMgPSBEZXRlY3RvciQxLnNoaWZ0UG9pbnQocG9pbnREcywgcG9pbnRBLCBkaW1IICogNCk7XG4gICAgICAgICAgICByZXR1cm4gW3BvaW50QXMsIHBvaW50QnMsIHBvaW50Q3MsIHBvaW50RHNdO1xuICAgICAgICB9XG4gICAgICAgIGlzVmFsaWQocCkge1xuICAgICAgICAgICAgcmV0dXJuIHAuZ2V0WCgpID49IDAgJiYgcC5nZXRYKCkgPCB0aGlzLmltYWdlLmdldFdpZHRoKCkgJiYgcC5nZXRZKCkgPiAwICYmIHAuZ2V0WSgpIDwgdGhpcy5pbWFnZS5nZXRIZWlnaHQoKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgc2FtcGxlR3JpZChpbWFnZSwgdG9wTGVmdCwgYm90dG9tTGVmdCwgYm90dG9tUmlnaHQsIHRvcFJpZ2h0LCBkaW1lbnNpb25YLCBkaW1lbnNpb25ZKSB7XG4gICAgICAgICAgICBjb25zdCBzYW1wbGVyID0gR3JpZFNhbXBsZXJJbnN0YW5jZS5nZXRJbnN0YW5jZSgpO1xuICAgICAgICAgICAgcmV0dXJuIHNhbXBsZXIuc2FtcGxlR3JpZChpbWFnZSwgZGltZW5zaW9uWCwgZGltZW5zaW9uWSwgMC41LCAwLjUsIGRpbWVuc2lvblggLSAwLjUsIDAuNSwgZGltZW5zaW9uWCAtIDAuNSwgZGltZW5zaW9uWSAtIDAuNSwgMC41LCBkaW1lbnNpb25ZIC0gMC41LCB0b3BMZWZ0LmdldFgoKSwgdG9wTGVmdC5nZXRZKCksIHRvcFJpZ2h0LmdldFgoKSwgdG9wUmlnaHQuZ2V0WSgpLCBib3R0b21SaWdodC5nZXRYKCksIGJvdHRvbVJpZ2h0LmdldFkoKSwgYm90dG9tTGVmdC5nZXRYKCksIGJvdHRvbUxlZnQuZ2V0WSgpKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ291bnRzIHRoZSBudW1iZXIgb2YgYmxhY2svd2hpdGUgdHJhbnNpdGlvbnMgYmV0d2VlbiB0d28gcG9pbnRzLCB1c2luZyBzb21ldGhpbmcgbGlrZSBCcmVzZW5oYW0ncyBhbGdvcml0aG0uXG4gICAgICAgICAqL1xuICAgICAgICB0cmFuc2l0aW9uc0JldHdlZW4oZnJvbSwgdG8pIHtcbiAgICAgICAgICAgIC8vIFNlZSBRUiBDb2RlIERldGVjdG9yLCBzaXplT2ZCbGFja1doaXRlQmxhY2tSdW4oKVxuICAgICAgICAgICAgbGV0IGZyb21YID0gTWF0aC50cnVuYyhmcm9tLmdldFgoKSk7XG4gICAgICAgICAgICBsZXQgZnJvbVkgPSBNYXRoLnRydW5jKGZyb20uZ2V0WSgpKTtcbiAgICAgICAgICAgIGxldCB0b1ggPSBNYXRoLnRydW5jKHRvLmdldFgoKSk7XG4gICAgICAgICAgICBsZXQgdG9ZID0gTWF0aC50cnVuYyh0by5nZXRZKCkpO1xuICAgICAgICAgICAgbGV0IHN0ZWVwID0gTWF0aC5hYnModG9ZIC0gZnJvbVkpID4gTWF0aC5hYnModG9YIC0gZnJvbVgpO1xuICAgICAgICAgICAgaWYgKHN0ZWVwKSB7XG4gICAgICAgICAgICAgICAgbGV0IHRlbXAgPSBmcm9tWDtcbiAgICAgICAgICAgICAgICBmcm9tWCA9IGZyb21ZO1xuICAgICAgICAgICAgICAgIGZyb21ZID0gdGVtcDtcbiAgICAgICAgICAgICAgICB0ZW1wID0gdG9YO1xuICAgICAgICAgICAgICAgIHRvWCA9IHRvWTtcbiAgICAgICAgICAgICAgICB0b1kgPSB0ZW1wO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGR4ID0gTWF0aC5hYnModG9YIC0gZnJvbVgpO1xuICAgICAgICAgICAgbGV0IGR5ID0gTWF0aC5hYnModG9ZIC0gZnJvbVkpO1xuICAgICAgICAgICAgbGV0IGVycm9yID0gLWR4IC8gMjtcbiAgICAgICAgICAgIGxldCB5c3RlcCA9IGZyb21ZIDwgdG9ZID8gMSA6IC0xO1xuICAgICAgICAgICAgbGV0IHhzdGVwID0gZnJvbVggPCB0b1ggPyAxIDogLTE7XG4gICAgICAgICAgICBsZXQgdHJhbnNpdGlvbnMgPSAwO1xuICAgICAgICAgICAgbGV0IGluQmxhY2sgPSB0aGlzLmltYWdlLmdldChzdGVlcCA/IGZyb21ZIDogZnJvbVgsIHN0ZWVwID8gZnJvbVggOiBmcm9tWSk7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gZnJvbVgsIHkgPSBmcm9tWTsgeCAhPT0gdG9YOyB4ICs9IHhzdGVwKSB7XG4gICAgICAgICAgICAgICAgbGV0IGlzQmxhY2sgPSB0aGlzLmltYWdlLmdldChzdGVlcCA/IHkgOiB4LCBzdGVlcCA/IHggOiB5KTtcbiAgICAgICAgICAgICAgICBpZiAoaXNCbGFjayAhPT0gaW5CbGFjaykge1xuICAgICAgICAgICAgICAgICAgICB0cmFuc2l0aW9ucysrO1xuICAgICAgICAgICAgICAgICAgICBpbkJsYWNrID0gaXNCbGFjaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZXJyb3IgKz0gZHk7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoeSA9PT0gdG9ZKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB5ICs9IHlzdGVwO1xuICAgICAgICAgICAgICAgICAgICBlcnJvciAtPSBkeDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJhbnNpdGlvbnM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIFRoaXMgaW1wbGVtZW50YXRpb24gY2FuIGRldGVjdCBhbmQgZGVjb2RlIERhdGEgTWF0cml4IGNvZGVzIGluIGFuIGltYWdlLlxuICAgICAqXG4gICAgICogQGF1dGhvciBiYnJvd25AZ29vZ2xlLmNvbSAoQnJpYW4gQnJvd24pXG4gICAgICovXG4gICAgY2xhc3MgRGF0YU1hdHJpeFJlYWRlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgdGhpcy5kZWNvZGVyID0gbmV3IERlY29kZXIkMSgpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBMb2NhdGVzIGFuZCBkZWNvZGVzIGEgRGF0YSBNYXRyaXggY29kZSBpbiBhbiBpbWFnZS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiBhIFN0cmluZyByZXByZXNlbnRpbmcgdGhlIGNvbnRlbnQgZW5jb2RlZCBieSB0aGUgRGF0YSBNYXRyaXggY29kZVxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIGEgRGF0YSBNYXRyaXggY29kZSBjYW5ub3QgYmUgZm91bmRcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb24gaWYgYSBEYXRhIE1hdHJpeCBjb2RlIGNhbm5vdCBiZSBkZWNvZGVkXG4gICAgICAgICAqIEB0aHJvd3MgQ2hlY2tzdW1FeGNlcHRpb24gaWYgZXJyb3IgY29ycmVjdGlvbiBmYWlsc1xuICAgICAgICAgKi9cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIC8vIHB1YmxpYyBSZXN1bHQgZGVjb2RlKEJpbmFyeUJpdG1hcCBpbWFnZSkgdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uLCBDaGVja3N1bUV4Y2VwdGlvbiwgRm9ybWF0RXhjZXB0aW9uIHtcbiAgICAgICAgLy8gICByZXR1cm4gZGVjb2RlKGltYWdlLCBudWxsKTtcbiAgICAgICAgLy8gfVxuICAgICAgICAvLyBAT3ZlcnJpZGVcbiAgICAgICAgZGVjb2RlKGltYWdlLCBoaW50cyA9IG51bGwpIHtcbiAgICAgICAgICAgIGxldCBkZWNvZGVyUmVzdWx0O1xuICAgICAgICAgICAgbGV0IHBvaW50cztcbiAgICAgICAgICAgIGlmIChoaW50cyAhPSBudWxsICYmIGhpbnRzLmhhcyhEZWNvZGVIaW50VHlwZSQxLlBVUkVfQkFSQ09ERSkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBiaXRzID0gRGF0YU1hdHJpeFJlYWRlci5leHRyYWN0UHVyZUJpdHMoaW1hZ2UuZ2V0QmxhY2tNYXRyaXgoKSk7XG4gICAgICAgICAgICAgICAgZGVjb2RlclJlc3VsdCA9IHRoaXMuZGVjb2Rlci5kZWNvZGUoYml0cyk7XG4gICAgICAgICAgICAgICAgcG9pbnRzID0gRGF0YU1hdHJpeFJlYWRlci5OT19QT0lOVFM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkZXRlY3RvclJlc3VsdCA9IG5ldyBEZXRlY3RvciQxKGltYWdlLmdldEJsYWNrTWF0cml4KCkpLmRldGVjdCgpO1xuICAgICAgICAgICAgICAgIGRlY29kZXJSZXN1bHQgPSB0aGlzLmRlY29kZXIuZGVjb2RlKGRldGVjdG9yUmVzdWx0LmdldEJpdHMoKSk7XG4gICAgICAgICAgICAgICAgcG9pbnRzID0gZGV0ZWN0b3JSZXN1bHQuZ2V0UG9pbnRzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByYXdCeXRlcyA9IGRlY29kZXJSZXN1bHQuZ2V0UmF3Qnl0ZXMoKTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBSZXN1bHQoZGVjb2RlclJlc3VsdC5nZXRUZXh0KCksIHJhd0J5dGVzLCA4ICogcmF3Qnl0ZXMubGVuZ3RoLCBwb2ludHMsIEJhcmNvZGVGb3JtYXQkMS5EQVRBX01BVFJJWCwgU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCkpO1xuICAgICAgICAgICAgY29uc3QgYnl0ZVNlZ21lbnRzID0gZGVjb2RlclJlc3VsdC5nZXRCeXRlU2VnbWVudHMoKTtcbiAgICAgICAgICAgIGlmIChieXRlU2VnbWVudHMgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXRNZXRhZGF0YShSZXN1bHRNZXRhZGF0YVR5cGUkMS5CWVRFX1NFR01FTlRTLCBieXRlU2VnbWVudHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZWNMZXZlbCA9IGRlY29kZXJSZXN1bHQuZ2V0RUNMZXZlbCgpO1xuICAgICAgICAgICAgaWYgKGVjTGV2ZWwgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXRNZXRhZGF0YShSZXN1bHRNZXRhZGF0YVR5cGUkMS5FUlJPUl9DT1JSRUNUSU9OX0xFVkVMLCBlY0xldmVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIHJlc2V0KCkge1xuICAgICAgICAgICAgLy8gZG8gbm90aGluZ1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGlzIG1ldGhvZCBkZXRlY3RzIGEgY29kZSBpbiBhIFwicHVyZVwiIGltYWdlIC0tIHRoYXQgaXMsIHB1cmUgbW9ub2Nocm9tZSBpbWFnZVxuICAgICAgICAgKiB3aGljaCBjb250YWlucyBvbmx5IGFuIHVucm90YXRlZCwgdW5za2V3ZWQsIGltYWdlIG9mIGEgY29kZSwgd2l0aCBzb21lIHdoaXRlIGJvcmRlclxuICAgICAgICAgKiBhcm91bmQgaXQuIFRoaXMgaXMgYSBzcGVjaWFsaXplZCBtZXRob2QgdGhhdCB3b3JrcyBleGNlcHRpb25hbGx5IGZhc3QgaW4gdGhpcyBzcGVjaWFsXG4gICAgICAgICAqIGNhc2UuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBzZWUgY29tLmdvb2dsZS56eGluZy5xcmNvZGUuUVJDb2RlUmVhZGVyI2V4dHJhY3RQdXJlQml0cyhCaXRNYXRyaXgpXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZXh0cmFjdFB1cmVCaXRzKGltYWdlKSB7XG4gICAgICAgICAgICBjb25zdCBsZWZ0VG9wQmxhY2sgPSBpbWFnZS5nZXRUb3BMZWZ0T25CaXQoKTtcbiAgICAgICAgICAgIGNvbnN0IHJpZ2h0Qm90dG9tQmxhY2sgPSBpbWFnZS5nZXRCb3R0b21SaWdodE9uQml0KCk7XG4gICAgICAgICAgICBpZiAobGVmdFRvcEJsYWNrID09IG51bGwgfHwgcmlnaHRCb3R0b21CbGFjayA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBtb2R1bGVTaXplID0gdGhpcy5tb2R1bGVTaXplKGxlZnRUb3BCbGFjaywgaW1hZ2UpO1xuICAgICAgICAgICAgbGV0IHRvcCA9IGxlZnRUb3BCbGFja1sxXTtcbiAgICAgICAgICAgIGNvbnN0IGJvdHRvbSA9IHJpZ2h0Qm90dG9tQmxhY2tbMV07XG4gICAgICAgICAgICBsZXQgbGVmdCA9IGxlZnRUb3BCbGFja1swXTtcbiAgICAgICAgICAgIGNvbnN0IHJpZ2h0ID0gcmlnaHRCb3R0b21CbGFja1swXTtcbiAgICAgICAgICAgIGNvbnN0IG1hdHJpeFdpZHRoID0gKHJpZ2h0IC0gbGVmdCArIDEpIC8gbW9kdWxlU2l6ZTtcbiAgICAgICAgICAgIGNvbnN0IG1hdHJpeEhlaWdodCA9IChib3R0b20gLSB0b3AgKyAxKSAvIG1vZHVsZVNpemU7XG4gICAgICAgICAgICBpZiAobWF0cml4V2lkdGggPD0gMCB8fCBtYXRyaXhIZWlnaHQgPD0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gUHVzaCBpbiB0aGUgXCJib3JkZXJcIiBieSBoYWxmIHRoZSBtb2R1bGUgd2lkdGggc28gdGhhdCB3ZSBzdGFydFxuICAgICAgICAgICAgLy8gc2FtcGxpbmcgaW4gdGhlIG1pZGRsZSBvZiB0aGUgbW9kdWxlLiBKdXN0IGluIGNhc2UgdGhlIGltYWdlIGlzIGFcbiAgICAgICAgICAgIC8vIGxpdHRsZSBvZmYsIHRoaXMgd2lsbCBoZWxwIHJlY292ZXIuXG4gICAgICAgICAgICBjb25zdCBudWRnZSA9IG1vZHVsZVNpemUgLyAyO1xuICAgICAgICAgICAgdG9wICs9IG51ZGdlO1xuICAgICAgICAgICAgbGVmdCArPSBudWRnZTtcbiAgICAgICAgICAgIC8vIE5vdyBqdXN0IHJlYWQgb2ZmIHRoZSBiaXRzXG4gICAgICAgICAgICBjb25zdCBiaXRzID0gbmV3IEJpdE1hdHJpeChtYXRyaXhXaWR0aCwgbWF0cml4SGVpZ2h0KTtcbiAgICAgICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgbWF0cml4SGVpZ2h0OyB5KyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpT2Zmc2V0ID0gdG9wICsgeSAqIG1vZHVsZVNpemU7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCBtYXRyaXhXaWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbWFnZS5nZXQobGVmdCArIHggKiBtb2R1bGVTaXplLCBpT2Zmc2V0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYml0cy5zZXQoeCwgeSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYml0cztcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgbW9kdWxlU2l6ZShsZWZ0VG9wQmxhY2ssIGltYWdlKSB7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IGltYWdlLmdldFdpZHRoKCk7XG4gICAgICAgICAgICBsZXQgeCA9IGxlZnRUb3BCbGFja1swXTtcbiAgICAgICAgICAgIGNvbnN0IHkgPSBsZWZ0VG9wQmxhY2tbMV07XG4gICAgICAgICAgICB3aGlsZSAoeCA8IHdpZHRoICYmIGltYWdlLmdldCh4LCB5KSkge1xuICAgICAgICAgICAgICAgIHgrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh4ID09PSB3aWR0aCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbW9kdWxlU2l6ZSA9IHggLSBsZWZ0VG9wQmxhY2tbMF07XG4gICAgICAgICAgICBpZiAobW9kdWxlU2l6ZSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1vZHVsZVNpemU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgRGF0YU1hdHJpeFJlYWRlci5OT19QT0lOVFMgPSBbXTtcblxuICAgIC8qKlxuICAgICAqIEBkZXByZWNhdGVkIE1vdmluZyB0byBAenhpbmcvYnJvd3NlclxuICAgICAqXG4gICAgICogUVIgQ29kZSByZWFkZXIgdG8gdXNlIGZyb20gYnJvd3Nlci5cbiAgICAgKi9cbiAgICBjbGFzcyBCcm93c2VyRGF0YW1hdHJpeENvZGVSZWFkZXIgZXh0ZW5kcyBCcm93c2VyQ29kZVJlYWRlciB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIEJyb3dzZXJRUkNvZGVSZWFkZXIuXG4gICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbdGltZUJldHdlZW5TY2Fuc01pbGxpcz01MDBdIHRoZSB0aW1lIGRlbGF5IGJldHdlZW4gc3Vic2VxdWVudCBkZWNvZGUgdHJpZXNcbiAgICAgICAgICovXG4gICAgICAgIGNvbnN0cnVjdG9yKHRpbWVCZXR3ZWVuU2NhbnNNaWxsaXMgPSA1MDApIHtcbiAgICAgICAgICAgIHN1cGVyKG5ldyBEYXRhTWF0cml4UmVhZGVyKCksIHRpbWVCZXR3ZWVuU2NhbnNNaWxsaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICB2YXIgRXJyb3JDb3JyZWN0aW9uTGV2ZWxWYWx1ZXM7XG4gICAgKGZ1bmN0aW9uIChFcnJvckNvcnJlY3Rpb25MZXZlbFZhbHVlcykge1xuICAgICAgICBFcnJvckNvcnJlY3Rpb25MZXZlbFZhbHVlc1tFcnJvckNvcnJlY3Rpb25MZXZlbFZhbHVlc1tcIkxcIl0gPSAwXSA9IFwiTFwiO1xuICAgICAgICBFcnJvckNvcnJlY3Rpb25MZXZlbFZhbHVlc1tFcnJvckNvcnJlY3Rpb25MZXZlbFZhbHVlc1tcIk1cIl0gPSAxXSA9IFwiTVwiO1xuICAgICAgICBFcnJvckNvcnJlY3Rpb25MZXZlbFZhbHVlc1tFcnJvckNvcnJlY3Rpb25MZXZlbFZhbHVlc1tcIlFcIl0gPSAyXSA9IFwiUVwiO1xuICAgICAgICBFcnJvckNvcnJlY3Rpb25MZXZlbFZhbHVlc1tFcnJvckNvcnJlY3Rpb25MZXZlbFZhbHVlc1tcIkhcIl0gPSAzXSA9IFwiSFwiO1xuICAgIH0pKEVycm9yQ29ycmVjdGlvbkxldmVsVmFsdWVzIHx8IChFcnJvckNvcnJlY3Rpb25MZXZlbFZhbHVlcyA9IHt9KSk7XG4gICAgLyoqXG4gICAgICogPHA+U2VlIElTTyAxODAwNDoyMDA2LCA2LjUuMS4gVGhpcyBlbnVtIGVuY2Fwc3VsYXRlcyB0aGUgZm91ciBlcnJvciBjb3JyZWN0aW9uIGxldmVsc1xuICAgICAqIGRlZmluZWQgYnkgdGhlIFFSIGNvZGUgc3RhbmRhcmQuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBFcnJvckNvcnJlY3Rpb25MZXZlbCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHZhbHVlLCBzdHJpbmdWYWx1ZSwgYml0cyAvKmludCovKSB7XG4gICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB0aGlzLnN0cmluZ1ZhbHVlID0gc3RyaW5nVmFsdWU7XG4gICAgICAgICAgICB0aGlzLmJpdHMgPSBiaXRzO1xuICAgICAgICAgICAgRXJyb3JDb3JyZWN0aW9uTGV2ZWwuRk9SX0JJVFMuc2V0KGJpdHMsIHRoaXMpO1xuICAgICAgICAgICAgRXJyb3JDb3JyZWN0aW9uTGV2ZWwuRk9SX1ZBTFVFLnNldCh2YWx1ZSwgdGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0VmFsdWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRCaXRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYml0cztcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZnJvbVN0cmluZyhzKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHMpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdMJzogcmV0dXJuIEVycm9yQ29ycmVjdGlvbkxldmVsLkw7XG4gICAgICAgICAgICAgICAgY2FzZSAnTSc6IHJldHVybiBFcnJvckNvcnJlY3Rpb25MZXZlbC5NO1xuICAgICAgICAgICAgICAgIGNhc2UgJ1EnOiByZXR1cm4gRXJyb3JDb3JyZWN0aW9uTGV2ZWwuUTtcbiAgICAgICAgICAgICAgICBjYXNlICdIJzogcmV0dXJuIEVycm9yQ29ycmVjdGlvbkxldmVsLkg7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDogdGhyb3cgbmV3IEFyZ3VtZW50RXhjZXB0aW9uKHMgKyAnbm90IGF2YWlsYWJsZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RyaW5nVmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgZXF1YWxzKG8pIHtcbiAgICAgICAgICAgIGlmICghKG8gaW5zdGFuY2VvZiBFcnJvckNvcnJlY3Rpb25MZXZlbCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBvdGhlciA9IG87XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZSA9PT0gb3RoZXIudmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBiaXRzIGludCBjb250YWluaW5nIHRoZSB0d28gYml0cyBlbmNvZGluZyBhIFFSIENvZGUncyBlcnJvciBjb3JyZWN0aW9uIGxldmVsXG4gICAgICAgICAqIEByZXR1cm4gRXJyb3JDb3JyZWN0aW9uTGV2ZWwgcmVwcmVzZW50aW5nIHRoZSBlbmNvZGVkIGVycm9yIGNvcnJlY3Rpb24gbGV2ZWxcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBmb3JCaXRzKGJpdHMgLyppbnQqLykge1xuICAgICAgICAgICAgaWYgKGJpdHMgPCAwIHx8IGJpdHMgPj0gRXJyb3JDb3JyZWN0aW9uTGV2ZWwuRk9SX0JJVFMuc2l6ZSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBFcnJvckNvcnJlY3Rpb25MZXZlbC5GT1JfQklUUy5nZXQoYml0cyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgRXJyb3JDb3JyZWN0aW9uTGV2ZWwuRk9SX0JJVFMgPSBuZXcgTWFwKCk7XG4gICAgRXJyb3JDb3JyZWN0aW9uTGV2ZWwuRk9SX1ZBTFVFID0gbmV3IE1hcCgpO1xuICAgIC8qKiBMID0gfjclIGNvcnJlY3Rpb24gKi9cbiAgICBFcnJvckNvcnJlY3Rpb25MZXZlbC5MID0gbmV3IEVycm9yQ29ycmVjdGlvbkxldmVsKEVycm9yQ29ycmVjdGlvbkxldmVsVmFsdWVzLkwsICdMJywgMHgwMSk7XG4gICAgLyoqIE0gPSB+MTUlIGNvcnJlY3Rpb24gKi9cbiAgICBFcnJvckNvcnJlY3Rpb25MZXZlbC5NID0gbmV3IEVycm9yQ29ycmVjdGlvbkxldmVsKEVycm9yQ29ycmVjdGlvbkxldmVsVmFsdWVzLk0sICdNJywgMHgwMCk7XG4gICAgLyoqIFEgPSB+MjUlIGNvcnJlY3Rpb24gKi9cbiAgICBFcnJvckNvcnJlY3Rpb25MZXZlbC5RID0gbmV3IEVycm9yQ29ycmVjdGlvbkxldmVsKEVycm9yQ29ycmVjdGlvbkxldmVsVmFsdWVzLlEsICdRJywgMHgwMyk7XG4gICAgLyoqIEggPSB+MzAlIGNvcnJlY3Rpb24gKi9cbiAgICBFcnJvckNvcnJlY3Rpb25MZXZlbC5IID0gbmV3IEVycm9yQ29ycmVjdGlvbkxldmVsKEVycm9yQ29ycmVjdGlvbkxldmVsVmFsdWVzLkgsICdIJywgMHgwMik7XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIDxwPkVuY2Fwc3VsYXRlcyBhIFFSIENvZGUncyBmb3JtYXQgaW5mb3JtYXRpb24sIGluY2x1ZGluZyB0aGUgZGF0YSBtYXNrIHVzZWQgYW5kXG4gICAgICogZXJyb3IgY29ycmVjdGlvbiBsZXZlbC48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqIEBzZWUgRGF0YU1hc2tcbiAgICAgKiBAc2VlIEVycm9yQ29ycmVjdGlvbkxldmVsXG4gICAgICovXG4gICAgY2xhc3MgRm9ybWF0SW5mb3JtYXRpb24ge1xuICAgICAgICBjb25zdHJ1Y3Rvcihmb3JtYXRJbmZvIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIC8vIEJpdHMgMyw0XG4gICAgICAgICAgICB0aGlzLmVycm9yQ29ycmVjdGlvbkxldmVsID0gRXJyb3JDb3JyZWN0aW9uTGV2ZWwuZm9yQml0cygoZm9ybWF0SW5mbyA+PiAzKSAmIDB4MDMpO1xuICAgICAgICAgICAgLy8gQm90dG9tIDMgYml0c1xuICAgICAgICAgICAgdGhpcy5kYXRhTWFzayA9IC8qKGJ5dGUpICovIChmb3JtYXRJbmZvICYgMHgwNyk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIG51bUJpdHNEaWZmZXJpbmcoYSAvKmludCovLCBiIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHJldHVybiBJbnRlZ2VyLmJpdENvdW50KGEgXiBiKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIG1hc2tlZEZvcm1hdEluZm8xIGZvcm1hdCBpbmZvIGluZGljYXRvciwgd2l0aCBtYXNrIHN0aWxsIGFwcGxpZWRcbiAgICAgICAgICogQHBhcmFtIG1hc2tlZEZvcm1hdEluZm8yIHNlY29uZCBjb3B5IG9mIHNhbWUgaW5mbzsgYm90aCBhcmUgY2hlY2tlZCBhdCB0aGUgc2FtZSB0aW1lXG4gICAgICAgICAqICB0byBlc3RhYmxpc2ggYmVzdCBtYXRjaFxuICAgICAgICAgKiBAcmV0dXJuIGluZm9ybWF0aW9uIGFib3V0IHRoZSBmb3JtYXQgaXQgc3BlY2lmaWVzLCBvciB7QGNvZGUgbnVsbH1cbiAgICAgICAgICogIGlmIGRvZXNuJ3Qgc2VlbSB0byBtYXRjaCBhbnkga25vd24gcGF0dGVyblxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGRlY29kZUZvcm1hdEluZm9ybWF0aW9uKG1hc2tlZEZvcm1hdEluZm8xIC8qaW50Ki8sIG1hc2tlZEZvcm1hdEluZm8yIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IGZvcm1hdEluZm8gPSBGb3JtYXRJbmZvcm1hdGlvbi5kb0RlY29kZUZvcm1hdEluZm9ybWF0aW9uKG1hc2tlZEZvcm1hdEluZm8xLCBtYXNrZWRGb3JtYXRJbmZvMik7XG4gICAgICAgICAgICBpZiAoZm9ybWF0SW5mbyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmb3JtYXRJbmZvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gU2hvdWxkIHJldHVybiBudWxsLCBidXQsIHNvbWUgUVIgY29kZXMgYXBwYXJlbnRseVxuICAgICAgICAgICAgLy8gZG8gbm90IG1hc2sgdGhpcyBpbmZvLiBUcnkgYWdhaW4gYnkgYWN0dWFsbHkgbWFza2luZyB0aGUgcGF0dGVyblxuICAgICAgICAgICAgLy8gZmlyc3RcbiAgICAgICAgICAgIHJldHVybiBGb3JtYXRJbmZvcm1hdGlvbi5kb0RlY29kZUZvcm1hdEluZm9ybWF0aW9uKG1hc2tlZEZvcm1hdEluZm8xIF4gRm9ybWF0SW5mb3JtYXRpb24uRk9STUFUX0lORk9fTUFTS19RUiwgbWFza2VkRm9ybWF0SW5mbzIgXiBGb3JtYXRJbmZvcm1hdGlvbi5GT1JNQVRfSU5GT19NQVNLX1FSKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZG9EZWNvZGVGb3JtYXRJbmZvcm1hdGlvbihtYXNrZWRGb3JtYXRJbmZvMSAvKmludCovLCBtYXNrZWRGb3JtYXRJbmZvMiAvKmludCovKSB7XG4gICAgICAgICAgICAvLyBGaW5kIHRoZSBpbnQgaW4gRk9STUFUX0lORk9fREVDT0RFX0xPT0tVUCB3aXRoIGZld2VzdCBiaXRzIGRpZmZlcmluZ1xuICAgICAgICAgICAgbGV0IGJlc3REaWZmZXJlbmNlID0gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVI7XG4gICAgICAgICAgICBsZXQgYmVzdEZvcm1hdEluZm8gPSAwO1xuICAgICAgICAgICAgZm9yIChjb25zdCBkZWNvZGVJbmZvIG9mIEZvcm1hdEluZm9ybWF0aW9uLkZPUk1BVF9JTkZPX0RFQ09ERV9MT09LVVApIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0YXJnZXRJbmZvID0gZGVjb2RlSW5mb1swXTtcbiAgICAgICAgICAgICAgICBpZiAodGFyZ2V0SW5mbyA9PT0gbWFza2VkRm9ybWF0SW5mbzEgfHwgdGFyZ2V0SW5mbyA9PT0gbWFza2VkRm9ybWF0SW5mbzIpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRm91bmQgYW4gZXhhY3QgbWF0Y2hcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBGb3JtYXRJbmZvcm1hdGlvbihkZWNvZGVJbmZvWzFdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IGJpdHNEaWZmZXJlbmNlID0gRm9ybWF0SW5mb3JtYXRpb24ubnVtQml0c0RpZmZlcmluZyhtYXNrZWRGb3JtYXRJbmZvMSwgdGFyZ2V0SW5mbyk7XG4gICAgICAgICAgICAgICAgaWYgKGJpdHNEaWZmZXJlbmNlIDwgYmVzdERpZmZlcmVuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgYmVzdEZvcm1hdEluZm8gPSBkZWNvZGVJbmZvWzFdO1xuICAgICAgICAgICAgICAgICAgICBiZXN0RGlmZmVyZW5jZSA9IGJpdHNEaWZmZXJlbmNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobWFza2VkRm9ybWF0SW5mbzEgIT09IG1hc2tlZEZvcm1hdEluZm8yKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGFsc28gdHJ5IHRoZSBvdGhlciBvcHRpb25cbiAgICAgICAgICAgICAgICAgICAgYml0c0RpZmZlcmVuY2UgPSBGb3JtYXRJbmZvcm1hdGlvbi5udW1CaXRzRGlmZmVyaW5nKG1hc2tlZEZvcm1hdEluZm8yLCB0YXJnZXRJbmZvKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGJpdHNEaWZmZXJlbmNlIDwgYmVzdERpZmZlcmVuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlc3RGb3JtYXRJbmZvID0gZGVjb2RlSW5mb1sxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlc3REaWZmZXJlbmNlID0gYml0c0RpZmZlcmVuY2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBIYW1taW5nIGRpc3RhbmNlIG9mIHRoZSAzMiBtYXNrZWQgY29kZXMgaXMgNywgYnkgY29uc3RydWN0aW9uLCBzbyA8PSAzIGJpdHNcbiAgICAgICAgICAgIC8vIGRpZmZlcmluZyBtZWFucyB3ZSBmb3VuZCBhIG1hdGNoXG4gICAgICAgICAgICBpZiAoYmVzdERpZmZlcmVuY2UgPD0gMykge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRm9ybWF0SW5mb3JtYXRpb24oYmVzdEZvcm1hdEluZm8pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RXJyb3JDb3JyZWN0aW9uTGV2ZWwoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lcnJvckNvcnJlY3Rpb25MZXZlbDtcbiAgICAgICAgfVxuICAgICAgICBnZXREYXRhTWFzaygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGFNYXNrO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgaGFzaENvZGUoKSB7XG4gICAgICAgICAgICByZXR1cm4gKHRoaXMuZXJyb3JDb3JyZWN0aW9uTGV2ZWwuZ2V0Qml0cygpIDw8IDMpIHwgdGhpcy5kYXRhTWFzaztcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGVxdWFscyhvKSB7XG4gICAgICAgICAgICBpZiAoIShvIGluc3RhbmNlb2YgRm9ybWF0SW5mb3JtYXRpb24pKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgb3RoZXIgPSBvO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXJyb3JDb3JyZWN0aW9uTGV2ZWwgPT09IG90aGVyLmVycm9yQ29ycmVjdGlvbkxldmVsICYmXG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhTWFzayA9PT0gb3RoZXIuZGF0YU1hc2s7XG4gICAgICAgIH1cbiAgICB9XG4gICAgRm9ybWF0SW5mb3JtYXRpb24uRk9STUFUX0lORk9fTUFTS19RUiA9IDB4NTQxMjtcbiAgICAvKipcbiAgICAgKiBTZWUgSVNPIDE4MDA0OjIwMDYsIEFubmV4IEMsIFRhYmxlIEMuMVxuICAgICAqL1xuICAgIEZvcm1hdEluZm9ybWF0aW9uLkZPUk1BVF9JTkZPX0RFQ09ERV9MT09LVVAgPSBbXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHg1NDEyLCAweDAwXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHg1MTI1LCAweDAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHg1RTdDLCAweDAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHg1QjRCLCAweDAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHg0NUY5LCAweDA0XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHg0MENFLCAweDA1XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHg0Rjk3LCAweDA2XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHg0QUEwLCAweDA3XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHg3N0M0LCAweDA4XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHg3MkYzLCAweDA5XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHg3REFBLCAweDBBXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHg3ODlELCAweDBCXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHg2NjJGLCAweDBDXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHg2MzE4LCAweDBEXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHg2QzQxLCAweDBFXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHg2OTc2LCAweDBGXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgxNjg5LCAweDEwXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgxM0JFLCAweDExXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgxQ0U3LCAweDEyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgxOUQwLCAweDEzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgwNzYyLCAweDE0XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgwMjU1LCAweDE1XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgwRDBDLCAweDE2XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgwODNCLCAweDE3XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgzNTVGLCAweDE4XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgzMDY4LCAweDE5XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgzRjMxLCAweDFBXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgzQTA2LCAweDFCXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgyNEI0LCAweDFDXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgyMTgzLCAweDFEXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgyRURBLCAweDFFXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgyQkVELCAweDFGXSksXG4gICAgXTtcblxuICAgIC8qKlxuICAgICAqIDxwPkVuY2Fwc3VsYXRlcyBhIHNldCBvZiBlcnJvci1jb3JyZWN0aW9uIGJsb2NrcyBpbiBvbmUgc3ltYm9sIHZlcnNpb24uIE1vc3QgdmVyc2lvbnMgd2lsbFxuICAgICAqIHVzZSBibG9ja3Mgb2YgZGlmZmVyaW5nIHNpemVzIHdpdGhpbiBvbmUgdmVyc2lvbiwgc28sIHRoaXMgZW5jYXBzdWxhdGVzIHRoZSBwYXJhbWV0ZXJzIGZvclxuICAgICAqIGVhY2ggc2V0IG9mIGJsb2Nrcy4gSXQgYWxzbyBob2xkcyB0aGUgbnVtYmVyIG9mIGVycm9yLWNvcnJlY3Rpb24gY29kZXdvcmRzIHBlciBibG9jayBzaW5jZSBpdFxuICAgICAqIHdpbGwgYmUgdGhlIHNhbWUgYWNyb3NzIGFsbCBibG9ja3Mgd2l0aGluIG9uZSB2ZXJzaW9uLjwvcD5cbiAgICAgKi9cbiAgICBjbGFzcyBFQ0Jsb2NrcyQxIHtcbiAgICAgICAgY29uc3RydWN0b3IoZWNDb2Rld29yZHNQZXJCbG9jayAvKmludCovLCAuLi5lY0Jsb2Nrcykge1xuICAgICAgICAgICAgdGhpcy5lY0NvZGV3b3Jkc1BlckJsb2NrID0gZWNDb2Rld29yZHNQZXJCbG9jaztcbiAgICAgICAgICAgIHRoaXMuZWNCbG9ja3MgPSBlY0Jsb2NrcztcbiAgICAgICAgfVxuICAgICAgICBnZXRFQ0NvZGV3b3Jkc1BlckJsb2NrKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWNDb2Rld29yZHNQZXJCbG9jaztcbiAgICAgICAgfVxuICAgICAgICBnZXROdW1CbG9ja3MoKSB7XG4gICAgICAgICAgICBsZXQgdG90YWwgPSAwO1xuICAgICAgICAgICAgY29uc3QgZWNCbG9ja3MgPSB0aGlzLmVjQmxvY2tzO1xuICAgICAgICAgICAgZm9yIChjb25zdCBlY0Jsb2NrIG9mIGVjQmxvY2tzKSB7XG4gICAgICAgICAgICAgICAgdG90YWwgKz0gZWNCbG9jay5nZXRDb3VudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRvdGFsO1xuICAgICAgICB9XG4gICAgICAgIGdldFRvdGFsRUNDb2Rld29yZHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lY0NvZGV3b3Jkc1BlckJsb2NrICogdGhpcy5nZXROdW1CbG9ja3MoKTtcbiAgICAgICAgfVxuICAgICAgICBnZXRFQ0Jsb2NrcygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVjQmxvY2tzO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogPHA+RW5jYXBzdWxhdGVzIHRoZSBwYXJhbWV0ZXJzIGZvciBvbmUgZXJyb3ItY29ycmVjdGlvbiBibG9jayBpbiBvbmUgc3ltYm9sIHZlcnNpb24uXG4gICAgICogVGhpcyBpbmNsdWRlcyB0aGUgbnVtYmVyIG9mIGRhdGEgY29kZXdvcmRzLCBhbmQgdGhlIG51bWJlciBvZiB0aW1lcyBhIGJsb2NrIHdpdGggdGhlc2VcbiAgICAgKiBwYXJhbWV0ZXJzIGlzIHVzZWQgY29uc2VjdXRpdmVseSBpbiB0aGUgUVIgY29kZSB2ZXJzaW9uJ3MgZm9ybWF0LjwvcD5cbiAgICAgKi9cbiAgICBjbGFzcyBFQ0IkMSB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGNvdW50IC8qaW50Ki8sIGRhdGFDb2Rld29yZHMgLyppbnQqLykge1xuICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50O1xuICAgICAgICAgICAgdGhpcy5kYXRhQ29kZXdvcmRzID0gZGF0YUNvZGV3b3JkcztcbiAgICAgICAgfVxuICAgICAgICBnZXRDb3VudCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvdW50O1xuICAgICAgICB9XG4gICAgICAgIGdldERhdGFDb2Rld29yZHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRhQ29kZXdvcmRzO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiBTZWUgSVNPIDE4MDA0OjIwMDYgQW5uZXggRFxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBWZXJzaW9uJDEge1xuICAgICAgICBjb25zdHJ1Y3Rvcih2ZXJzaW9uTnVtYmVyIC8qaW50Ki8sIGFsaWdubWVudFBhdHRlcm5DZW50ZXJzLCAuLi5lY0Jsb2Nrcykge1xuICAgICAgICAgICAgdGhpcy52ZXJzaW9uTnVtYmVyID0gdmVyc2lvbk51bWJlcjtcbiAgICAgICAgICAgIHRoaXMuYWxpZ25tZW50UGF0dGVybkNlbnRlcnMgPSBhbGlnbm1lbnRQYXR0ZXJuQ2VudGVycztcbiAgICAgICAgICAgIHRoaXMuZWNCbG9ja3MgPSBlY0Jsb2NrcztcbiAgICAgICAgICAgIGxldCB0b3RhbCA9IDA7XG4gICAgICAgICAgICBjb25zdCBlY0NvZGV3b3JkcyA9IGVjQmxvY2tzWzBdLmdldEVDQ29kZXdvcmRzUGVyQmxvY2soKTtcbiAgICAgICAgICAgIGNvbnN0IGVjYkFycmF5ID0gZWNCbG9ja3NbMF0uZ2V0RUNCbG9ja3MoKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgZWNCbG9jayBvZiBlY2JBcnJheSkge1xuICAgICAgICAgICAgICAgIHRvdGFsICs9IGVjQmxvY2suZ2V0Q291bnQoKSAqIChlY0Jsb2NrLmdldERhdGFDb2Rld29yZHMoKSArIGVjQ29kZXdvcmRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudG90YWxDb2Rld29yZHMgPSB0b3RhbDtcbiAgICAgICAgfVxuICAgICAgICBnZXRWZXJzaW9uTnVtYmVyKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmVyc2lvbk51bWJlcjtcbiAgICAgICAgfVxuICAgICAgICBnZXRBbGlnbm1lbnRQYXR0ZXJuQ2VudGVycygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmFsaWdubWVudFBhdHRlcm5DZW50ZXJzO1xuICAgICAgICB9XG4gICAgICAgIGdldFRvdGFsQ29kZXdvcmRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudG90YWxDb2Rld29yZHM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RGltZW5zaW9uRm9yVmVyc2lvbigpIHtcbiAgICAgICAgICAgIHJldHVybiAxNyArIDQgKiB0aGlzLnZlcnNpb25OdW1iZXI7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RUNCbG9ja3NGb3JMZXZlbChlY0xldmVsKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lY0Jsb2Nrc1tlY0xldmVsLmdldFZhbHVlKCldO1xuICAgICAgICAgICAgLy8gVFlQRVNDUklQVFBPUlQ6IG9yaWdpbmFsIHdhcyB1c2luZyBvcmRpbmFsLCBhbmQgdXNpbmcgdGhlIG9yZGVyIG9mIGxldmVscyBhcyBkZWZpbmVkIGluIEVycm9yQ29ycmVjdGlvbkxldmVsIGVudW0gKExNUUgpXG4gICAgICAgICAgICAvLyBJIHdpbGwgdXNlIHRoZSBkaXJlY3QgdmFsdWUgZnJvbSBFcnJvckNvcnJlY3Rpb25MZXZlbFZhbHVlcyBlbnVtIHdoaWNoIGluIHR5cGVzY3JpcHQgZ29lcyB0byBhIG51bWJlclxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5EZWR1Y2VzIHZlcnNpb24gaW5mb3JtYXRpb24gcHVyZWx5IGZyb20gUVIgQ29kZSBkaW1lbnNpb25zLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGRpbWVuc2lvbiBkaW1lbnNpb24gaW4gbW9kdWxlc1xuICAgICAgICAgKiBAcmV0dXJuIFZlcnNpb24gZm9yIGEgUVIgQ29kZSBvZiB0aGF0IGRpbWVuc2lvblxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvbiBpZiBkaW1lbnNpb24gaXMgbm90IDEgbW9kIDRcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBnZXRQcm92aXNpb25hbFZlcnNpb25Gb3JEaW1lbnNpb24oZGltZW5zaW9uIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGlmIChkaW1lbnNpb24gJSA0ICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRWZXJzaW9uRm9yTnVtYmVyKChkaW1lbnNpb24gLSAxNykgLyA0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChpZ25vcmVkIC8qOiBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24qLykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZ2V0VmVyc2lvbkZvck51bWJlcih2ZXJzaW9uTnVtYmVyIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGlmICh2ZXJzaW9uTnVtYmVyIDwgMSB8fCB2ZXJzaW9uTnVtYmVyID4gNDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gVmVyc2lvbiQxLlZFUlNJT05TW3ZlcnNpb25OdW1iZXIgLSAxXTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZGVjb2RlVmVyc2lvbkluZm9ybWF0aW9uKHZlcnNpb25CaXRzIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGxldCBiZXN0RGlmZmVyZW5jZSA9IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSO1xuICAgICAgICAgICAgbGV0IGJlc3RWZXJzaW9uID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgVmVyc2lvbiQxLlZFUlNJT05fREVDT0RFX0lORk8ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0YXJnZXRWZXJzaW9uID0gVmVyc2lvbiQxLlZFUlNJT05fREVDT0RFX0lORk9baV07XG4gICAgICAgICAgICAgICAgLy8gRG8gdGhlIHZlcnNpb24gaW5mbyBiaXRzIG1hdGNoIGV4YWN0bHk/IGRvbmUuXG4gICAgICAgICAgICAgICAgaWYgKHRhcmdldFZlcnNpb24gPT09IHZlcnNpb25CaXRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBWZXJzaW9uJDEuZ2V0VmVyc2lvbkZvck51bWJlcihpICsgNyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBzZWUgaWYgdGhpcyBpcyB0aGUgY2xvc2VzdCB0byBhIHJlYWwgdmVyc2lvbiBpbmZvIGJpdCBzdHJpbmdcbiAgICAgICAgICAgICAgICAvLyB3ZSBoYXZlIHNlZW4gc28gZmFyXG4gICAgICAgICAgICAgICAgY29uc3QgYml0c0RpZmZlcmVuY2UgPSBGb3JtYXRJbmZvcm1hdGlvbi5udW1CaXRzRGlmZmVyaW5nKHZlcnNpb25CaXRzLCB0YXJnZXRWZXJzaW9uKTtcbiAgICAgICAgICAgICAgICBpZiAoYml0c0RpZmZlcmVuY2UgPCBiZXN0RGlmZmVyZW5jZSkge1xuICAgICAgICAgICAgICAgICAgICBiZXN0VmVyc2lvbiA9IGkgKyA3O1xuICAgICAgICAgICAgICAgICAgICBiZXN0RGlmZmVyZW5jZSA9IGJpdHNEaWZmZXJlbmNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFdlIGNhbiB0b2xlcmF0ZSB1cCB0byAzIGJpdHMgb2YgZXJyb3Igc2luY2Ugbm8gdHdvIHZlcnNpb24gaW5mbyBjb2Rld29yZHMgd2lsbFxuICAgICAgICAgICAgLy8gZGlmZmVyIGluIGxlc3MgdGhhbiA4IGJpdHMuXG4gICAgICAgICAgICBpZiAoYmVzdERpZmZlcmVuY2UgPD0gMykge1xuICAgICAgICAgICAgICAgIHJldHVybiBWZXJzaW9uJDEuZ2V0VmVyc2lvbkZvck51bWJlcihiZXN0VmVyc2lvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBJZiB3ZSBkaWRuJ3QgZmluZCBhIGNsb3NlIGVub3VnaCBtYXRjaCwgZmFpbFxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNlZSBJU08gMTgwMDQ6MjAwNiBBbm5leCBFXG4gICAgICAgICAqL1xuICAgICAgICBidWlsZEZ1bmN0aW9uUGF0dGVybigpIHtcbiAgICAgICAgICAgIGNvbnN0IGRpbWVuc2lvbiA9IHRoaXMuZ2V0RGltZW5zaW9uRm9yVmVyc2lvbigpO1xuICAgICAgICAgICAgY29uc3QgYml0TWF0cml4ID0gbmV3IEJpdE1hdHJpeChkaW1lbnNpb24pO1xuICAgICAgICAgICAgLy8gVG9wIGxlZnQgZmluZGVyIHBhdHRlcm4gKyBzZXBhcmF0b3IgKyBmb3JtYXRcbiAgICAgICAgICAgIGJpdE1hdHJpeC5zZXRSZWdpb24oMCwgMCwgOSwgOSk7XG4gICAgICAgICAgICAvLyBUb3AgcmlnaHQgZmluZGVyIHBhdHRlcm4gKyBzZXBhcmF0b3IgKyBmb3JtYXRcbiAgICAgICAgICAgIGJpdE1hdHJpeC5zZXRSZWdpb24oZGltZW5zaW9uIC0gOCwgMCwgOCwgOSk7XG4gICAgICAgICAgICAvLyBCb3R0b20gbGVmdCBmaW5kZXIgcGF0dGVybiArIHNlcGFyYXRvciArIGZvcm1hdFxuICAgICAgICAgICAgYml0TWF0cml4LnNldFJlZ2lvbigwLCBkaW1lbnNpb24gLSA4LCA5LCA4KTtcbiAgICAgICAgICAgIC8vIEFsaWdubWVudCBwYXR0ZXJuc1xuICAgICAgICAgICAgY29uc3QgbWF4ID0gdGhpcy5hbGlnbm1lbnRQYXR0ZXJuQ2VudGVycy5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IG1heDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaSA9IHRoaXMuYWxpZ25tZW50UGF0dGVybkNlbnRlcnNbeF0gLSAyO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgbWF4OyB5KyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCh4ID09PSAwICYmICh5ID09PSAwIHx8IHkgPT09IG1heCAtIDEpKSB8fCAoeCA9PT0gbWF4IC0gMSAmJiB5ID09PSAwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm8gYWxpZ25tZW50IHBhdHRlcm5zIG5lYXIgdGhlIHRocmVlIGZpbmRlciBwYXR0ZXJuc1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYml0TWF0cml4LnNldFJlZ2lvbih0aGlzLmFsaWdubWVudFBhdHRlcm5DZW50ZXJzW3ldIC0gMiwgaSwgNSwgNSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gVmVydGljYWwgdGltaW5nIHBhdHRlcm5cbiAgICAgICAgICAgIGJpdE1hdHJpeC5zZXRSZWdpb24oNiwgOSwgMSwgZGltZW5zaW9uIC0gMTcpO1xuICAgICAgICAgICAgLy8gSG9yaXpvbnRhbCB0aW1pbmcgcGF0dGVyblxuICAgICAgICAgICAgYml0TWF0cml4LnNldFJlZ2lvbig5LCA2LCBkaW1lbnNpb24gLSAxNywgMSk7XG4gICAgICAgICAgICBpZiAodGhpcy52ZXJzaW9uTnVtYmVyID4gNikge1xuICAgICAgICAgICAgICAgIC8vIFZlcnNpb24gaW5mbywgdG9wIHJpZ2h0XG4gICAgICAgICAgICAgICAgYml0TWF0cml4LnNldFJlZ2lvbihkaW1lbnNpb24gLSAxMSwgMCwgMywgNik7XG4gICAgICAgICAgICAgICAgLy8gVmVyc2lvbiBpbmZvLCBib3R0b20gbGVmdFxuICAgICAgICAgICAgICAgIGJpdE1hdHJpeC5zZXRSZWdpb24oMCwgZGltZW5zaW9uIC0gMTEsIDYsIDMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGJpdE1hdHJpeDtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgcmV0dXJuICcnICsgdGhpcy52ZXJzaW9uTnVtYmVyO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAgICogU2VlIElTTyAxODAwNDoyMDA2IEFubmV4IEQuXG4gICAgICAgKiBFbGVtZW50IGkgcmVwcmVzZW50cyB0aGUgcmF3IHZlcnNpb24gYml0cyB0aGF0IHNwZWNpZnkgdmVyc2lvbiBpICsgN1xuICAgICAgICovXG4gICAgVmVyc2lvbiQxLlZFUlNJT05fREVDT0RFX0lORk8gPSBJbnQzMkFycmF5LmZyb20oW1xuICAgICAgICAweDA3Qzk0LCAweDA4NUJDLCAweDA5QTk5LCAweDBBNEQzLCAweDBCQkY2LFxuICAgICAgICAweDBDNzYyLCAweDBEODQ3LCAweDBFNjBELCAweDBGOTI4LCAweDEwQjc4LFxuICAgICAgICAweDExNDVELCAweDEyQTE3LCAweDEzNTMyLCAweDE0OUE2LCAweDE1NjgzLFxuICAgICAgICAweDE2OEM5LCAweDE3N0VDLCAweDE4RUM0LCAweDE5MUUxLCAweDFBRkFCLFxuICAgICAgICAweDFCMDhFLCAweDFDQzFBLCAweDFEMzNGLCAweDFFRDc1LCAweDFGMjUwLFxuICAgICAgICAweDIwOUQ1LCAweDIxNkYwLCAweDIyOEJBLCAweDIzNzlGLCAweDI0QjBCLFxuICAgICAgICAweDI1NDJFLCAweDI2QTY0LCAweDI3NTQxLCAweDI4QzY5XG4gICAgXSk7XG4gICAgLyoqXG4gICAgICAgKiBTZWUgSVNPIDE4MDA0OjIwMDYgNi41LjEgVGFibGUgOVxuICAgICAgICovXG4gICAgVmVyc2lvbiQxLlZFUlNJT05TID0gW1xuICAgICAgICBuZXcgVmVyc2lvbiQxKDEsIG5ldyBJbnQzMkFycmF5KDApLCBuZXcgRUNCbG9ja3MkMSg3LCBuZXcgRUNCJDEoMSwgMTkpKSwgbmV3IEVDQmxvY2tzJDEoMTAsIG5ldyBFQ0IkMSgxLCAxNikpLCBuZXcgRUNCbG9ja3MkMSgxMywgbmV3IEVDQiQxKDEsIDEzKSksIG5ldyBFQ0Jsb2NrcyQxKDE3LCBuZXcgRUNCJDEoMSwgOSkpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgyLCBJbnQzMkFycmF5LmZyb20oWzYsIDE4XSksIG5ldyBFQ0Jsb2NrcyQxKDEwLCBuZXcgRUNCJDEoMSwgMzQpKSwgbmV3IEVDQmxvY2tzJDEoMTYsIG5ldyBFQ0IkMSgxLCAyOCkpLCBuZXcgRUNCbG9ja3MkMSgyMiwgbmV3IEVDQiQxKDEsIDIyKSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMSwgMTYpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMywgSW50MzJBcnJheS5mcm9tKFs2LCAyMl0pLCBuZXcgRUNCbG9ja3MkMSgxNSwgbmV3IEVDQiQxKDEsIDU1KSksIG5ldyBFQ0Jsb2NrcyQxKDI2LCBuZXcgRUNCJDEoMSwgNDQpKSwgbmV3IEVDQmxvY2tzJDEoMTgsIG5ldyBFQ0IkMSgyLCAxNykpLCBuZXcgRUNCbG9ja3MkMSgyMiwgbmV3IEVDQiQxKDIsIDEzKSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDQsIEludDMyQXJyYXkuZnJvbShbNiwgMjZdKSwgbmV3IEVDQmxvY2tzJDEoMjAsIG5ldyBFQ0IkMSgxLCA4MCkpLCBuZXcgRUNCbG9ja3MkMSgxOCwgbmV3IEVDQiQxKDIsIDMyKSksIG5ldyBFQ0Jsb2NrcyQxKDI2LCBuZXcgRUNCJDEoMiwgMjQpKSwgbmV3IEVDQmxvY2tzJDEoMTYsIG5ldyBFQ0IkMSg0LCA5KSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDUsIEludDMyQXJyYXkuZnJvbShbNiwgMzBdKSwgbmV3IEVDQmxvY2tzJDEoMjYsIG5ldyBFQ0IkMSgxLCAxMDgpKSwgbmV3IEVDQmxvY2tzJDEoMjQsIG5ldyBFQ0IkMSgyLCA0MykpLCBuZXcgRUNCbG9ja3MkMSgxOCwgbmV3IEVDQiQxKDIsIDE1KSwgbmV3IEVDQiQxKDIsIDE2KSksIG5ldyBFQ0Jsb2NrcyQxKDIyLCBuZXcgRUNCJDEoMiwgMTEpLCBuZXcgRUNCJDEoMiwgMTIpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoNiwgSW50MzJBcnJheS5mcm9tKFs2LCAzNF0pLCBuZXcgRUNCbG9ja3MkMSgxOCwgbmV3IEVDQiQxKDIsIDY4KSksIG5ldyBFQ0Jsb2NrcyQxKDE2LCBuZXcgRUNCJDEoNCwgMjcpKSwgbmV3IEVDQmxvY2tzJDEoMjQsIG5ldyBFQ0IkMSg0LCAxOSkpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDQsIDE1KSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDcsIEludDMyQXJyYXkuZnJvbShbNiwgMjIsIDM4XSksIG5ldyBFQ0Jsb2NrcyQxKDIwLCBuZXcgRUNCJDEoMiwgNzgpKSwgbmV3IEVDQmxvY2tzJDEoMTgsIG5ldyBFQ0IkMSg0LCAzMSkpLCBuZXcgRUNCbG9ja3MkMSgxOCwgbmV3IEVDQiQxKDIsIDE0KSwgbmV3IEVDQiQxKDQsIDE1KSksIG5ldyBFQ0Jsb2NrcyQxKDI2LCBuZXcgRUNCJDEoNCwgMTMpLCBuZXcgRUNCJDEoMSwgMTQpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoOCwgSW50MzJBcnJheS5mcm9tKFs2LCAyNCwgNDJdKSwgbmV3IEVDQmxvY2tzJDEoMjQsIG5ldyBFQ0IkMSgyLCA5NykpLCBuZXcgRUNCbG9ja3MkMSgyMiwgbmV3IEVDQiQxKDIsIDM4KSwgbmV3IEVDQiQxKDIsIDM5KSksIG5ldyBFQ0Jsb2NrcyQxKDIyLCBuZXcgRUNCJDEoNCwgMTgpLCBuZXcgRUNCJDEoMiwgMTkpKSwgbmV3IEVDQmxvY2tzJDEoMjYsIG5ldyBFQ0IkMSg0LCAxNCksIG5ldyBFQ0IkMSgyLCAxNSkpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSg5LCBJbnQzMkFycmF5LmZyb20oWzYsIDI2LCA0Nl0pLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDIsIDExNikpLCBuZXcgRUNCbG9ja3MkMSgyMiwgbmV3IEVDQiQxKDMsIDM2KSwgbmV3IEVDQiQxKDIsIDM3KSksIG5ldyBFQ0Jsb2NrcyQxKDIwLCBuZXcgRUNCJDEoNCwgMTYpLCBuZXcgRUNCJDEoNCwgMTcpKSwgbmV3IEVDQmxvY2tzJDEoMjQsIG5ldyBFQ0IkMSg0LCAxMiksIG5ldyBFQ0IkMSg0LCAxMykpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgxMCwgSW50MzJBcnJheS5mcm9tKFs2LCAyOCwgNTBdKSwgbmV3IEVDQmxvY2tzJDEoMTgsIG5ldyBFQ0IkMSgyLCA2OCksIG5ldyBFQ0IkMSgyLCA2OSkpLCBuZXcgRUNCbG9ja3MkMSgyNiwgbmV3IEVDQiQxKDQsIDQzKSwgbmV3IEVDQiQxKDEsIDQ0KSksIG5ldyBFQ0Jsb2NrcyQxKDI0LCBuZXcgRUNCJDEoNiwgMTkpLCBuZXcgRUNCJDEoMiwgMjApKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSg2LCAxNSksIG5ldyBFQ0IkMSgyLCAxNikpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgxMSwgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTRdKSwgbmV3IEVDQmxvY2tzJDEoMjAsIG5ldyBFQ0IkMSg0LCA4MSkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDEsIDUwKSwgbmV3IEVDQiQxKDQsIDUxKSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoNCwgMjIpLCBuZXcgRUNCJDEoNCwgMjMpKSwgbmV3IEVDQmxvY2tzJDEoMjQsIG5ldyBFQ0IkMSgzLCAxMiksIG5ldyBFQ0IkMSg4LCAxMykpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgxMiwgSW50MzJBcnJheS5mcm9tKFs2LCAzMiwgNThdKSwgbmV3IEVDQmxvY2tzJDEoMjQsIG5ldyBFQ0IkMSgyLCA5MiksIG5ldyBFQ0IkMSgyLCA5MykpLCBuZXcgRUNCbG9ja3MkMSgyMiwgbmV3IEVDQiQxKDYsIDM2KSwgbmV3IEVDQiQxKDIsIDM3KSksIG5ldyBFQ0Jsb2NrcyQxKDI2LCBuZXcgRUNCJDEoNCwgMjApLCBuZXcgRUNCJDEoNiwgMjEpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSg3LCAxNCksIG5ldyBFQ0IkMSg0LCAxNSkpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgxMywgSW50MzJBcnJheS5mcm9tKFs2LCAzNCwgNjJdKSwgbmV3IEVDQmxvY2tzJDEoMjYsIG5ldyBFQ0IkMSg0LCAxMDcpKSwgbmV3IEVDQmxvY2tzJDEoMjIsIG5ldyBFQ0IkMSg4LCAzNyksIG5ldyBFQ0IkMSgxLCAzOCkpLCBuZXcgRUNCbG9ja3MkMSgyNCwgbmV3IEVDQiQxKDgsIDIwKSwgbmV3IEVDQiQxKDQsIDIxKSksIG5ldyBFQ0Jsb2NrcyQxKDIyLCBuZXcgRUNCJDEoMTIsIDExKSwgbmV3IEVDQiQxKDQsIDEyKSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDE0LCBJbnQzMkFycmF5LmZyb20oWzYsIDI2LCA0NiwgNjZdKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgzLCAxMTUpLCBuZXcgRUNCJDEoMSwgMTE2KSksIG5ldyBFQ0Jsb2NrcyQxKDI0LCBuZXcgRUNCJDEoNCwgNDApLCBuZXcgRUNCJDEoNSwgNDEpKSwgbmV3IEVDQmxvY2tzJDEoMjAsIG5ldyBFQ0IkMSgxMSwgMTYpLCBuZXcgRUNCJDEoNSwgMTcpKSwgbmV3IEVDQmxvY2tzJDEoMjQsIG5ldyBFQ0IkMSgxMSwgMTIpLCBuZXcgRUNCJDEoNSwgMTMpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMTUsIEludDMyQXJyYXkuZnJvbShbNiwgMjYsIDQ4LCA3MF0pLCBuZXcgRUNCbG9ja3MkMSgyMiwgbmV3IEVDQiQxKDUsIDg3KSwgbmV3IEVDQiQxKDEsIDg4KSksIG5ldyBFQ0Jsb2NrcyQxKDI0LCBuZXcgRUNCJDEoNSwgNDEpLCBuZXcgRUNCJDEoNSwgNDIpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSg1LCAyNCksIG5ldyBFQ0IkMSg3LCAyNSkpLCBuZXcgRUNCbG9ja3MkMSgyNCwgbmV3IEVDQiQxKDExLCAxMiksIG5ldyBFQ0IkMSg3LCAxMykpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgxNiwgSW50MzJBcnJheS5mcm9tKFs2LCAyNiwgNTAsIDc0XSksIG5ldyBFQ0Jsb2NrcyQxKDI0LCBuZXcgRUNCJDEoNSwgOTgpLCBuZXcgRUNCJDEoMSwgOTkpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSg3LCA0NSksIG5ldyBFQ0IkMSgzLCA0NikpLCBuZXcgRUNCbG9ja3MkMSgyNCwgbmV3IEVDQiQxKDE1LCAxOSksIG5ldyBFQ0IkMSgyLCAyMCkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDMsIDE1KSwgbmV3IEVDQiQxKDEzLCAxNikpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgxNywgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTQsIDc4XSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMSwgMTA3KSwgbmV3IEVDQiQxKDUsIDEwOCkpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDEwLCA0NiksIG5ldyBFQ0IkMSgxLCA0NykpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDEsIDIyKSwgbmV3IEVDQiQxKDE1LCAyMykpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDIsIDE0KSwgbmV3IEVDQiQxKDE3LCAxNSkpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgxOCwgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTYsIDgyXSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoNSwgMTIwKSwgbmV3IEVDQiQxKDEsIDEyMSkpLCBuZXcgRUNCbG9ja3MkMSgyNiwgbmV3IEVDQiQxKDksIDQzKSwgbmV3IEVDQiQxKDQsIDQ0KSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMTcsIDIyKSwgbmV3IEVDQiQxKDEsIDIzKSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMiwgMTQpLCBuZXcgRUNCJDEoMTksIDE1KSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDE5LCBJbnQzMkFycmF5LmZyb20oWzYsIDMwLCA1OCwgODZdKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgzLCAxMTMpLCBuZXcgRUNCJDEoNCwgMTE0KSksIG5ldyBFQ0Jsb2NrcyQxKDI2LCBuZXcgRUNCJDEoMywgNDQpLCBuZXcgRUNCJDEoMTEsIDQ1KSksIG5ldyBFQ0Jsb2NrcyQxKDI2LCBuZXcgRUNCJDEoMTcsIDIxKSwgbmV3IEVDQiQxKDQsIDIyKSksIG5ldyBFQ0Jsb2NrcyQxKDI2LCBuZXcgRUNCJDEoOSwgMTMpLCBuZXcgRUNCJDEoMTYsIDE0KSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDIwLCBJbnQzMkFycmF5LmZyb20oWzYsIDM0LCA2MiwgOTBdKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgzLCAxMDcpLCBuZXcgRUNCJDEoNSwgMTA4KSksIG5ldyBFQ0Jsb2NrcyQxKDI2LCBuZXcgRUNCJDEoMywgNDEpLCBuZXcgRUNCJDEoMTMsIDQyKSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMTUsIDI0KSwgbmV3IEVDQiQxKDUsIDI1KSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMTUsIDE1KSwgbmV3IEVDQiQxKDEwLCAxNikpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgyMSwgSW50MzJBcnJheS5mcm9tKFs2LCAyOCwgNTAsIDcyLCA5NF0pLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDQsIDExNiksIG5ldyBFQ0IkMSg0LCAxMTcpKSwgbmV3IEVDQmxvY2tzJDEoMjYsIG5ldyBFQ0IkMSgxNywgNDIpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgxNywgMjIpLCBuZXcgRUNCJDEoNiwgMjMpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgxOSwgMTYpLCBuZXcgRUNCJDEoNiwgMTcpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMjIsIEludDMyQXJyYXkuZnJvbShbNiwgMjYsIDUwLCA3NCwgOThdKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgyLCAxMTEpLCBuZXcgRUNCJDEoNywgMTEyKSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMTcsIDQ2KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoNywgMjQpLCBuZXcgRUNCJDEoMTYsIDI1KSksIG5ldyBFQ0Jsb2NrcyQxKDI0LCBuZXcgRUNCJDEoMzQsIDEzKSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDIzLCBJbnQzMkFycmF5LmZyb20oWzYsIDMwLCA1NCwgNzgsIDEwMl0pLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDQsIDEyMSksIG5ldyBFQ0IkMSg1LCAxMjIpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSg0LCA0NyksIG5ldyBFQ0IkMSgxNCwgNDgpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgxMSwgMjQpLCBuZXcgRUNCJDEoMTQsIDI1KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMTYsIDE1KSwgbmV3IEVDQiQxKDE0LCAxNikpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgyNCwgSW50MzJBcnJheS5mcm9tKFs2LCAyOCwgNTQsIDgwLCAxMDZdKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSg2LCAxMTcpLCBuZXcgRUNCJDEoNCwgMTE4KSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoNiwgNDUpLCBuZXcgRUNCJDEoMTQsIDQ2KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMTEsIDI0KSwgbmV3IEVDQiQxKDE2LCAyNSkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDMwLCAxNiksIG5ldyBFQ0IkMSgyLCAxNykpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgyNSwgSW50MzJBcnJheS5mcm9tKFs2LCAzMiwgNTgsIDg0LCAxMTBdKSwgbmV3IEVDQmxvY2tzJDEoMjYsIG5ldyBFQ0IkMSg4LCAxMDYpLCBuZXcgRUNCJDEoNCwgMTA3KSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoOCwgNDcpLCBuZXcgRUNCJDEoMTMsIDQ4KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoNywgMjQpLCBuZXcgRUNCJDEoMjIsIDI1KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMjIsIDE1KSwgbmV3IEVDQiQxKDEzLCAxNikpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgyNiwgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTgsIDg2LCAxMTRdKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgxMCwgMTE0KSwgbmV3IEVDQiQxKDIsIDExNSkpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDE5LCA0NiksIG5ldyBFQ0IkMSg0LCA0NykpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDI4LCAyMiksIG5ldyBFQ0IkMSg2LCAyMykpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDMzLCAxNiksIG5ldyBFQ0IkMSg0LCAxNykpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgyNywgSW50MzJBcnJheS5mcm9tKFs2LCAzNCwgNjIsIDkwLCAxMThdKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSg4LCAxMjIpLCBuZXcgRUNCJDEoNCwgMTIzKSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMjIsIDQ1KSwgbmV3IEVDQiQxKDMsIDQ2KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoOCwgMjMpLCBuZXcgRUNCJDEoMjYsIDI0KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMTIsIDE1KSwgbmV3IEVDQiQxKDI4LCAxNikpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgyOCwgSW50MzJBcnJheS5mcm9tKFs2LCAyNiwgNTAsIDc0LCA5OCwgMTIyXSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMywgMTE3KSwgbmV3IEVDQiQxKDEwLCAxMTgpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgzLCA0NSksIG5ldyBFQ0IkMSgyMywgNDYpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSg0LCAyNCksIG5ldyBFQ0IkMSgzMSwgMjUpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgxMSwgMTUpLCBuZXcgRUNCJDEoMzEsIDE2KSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDI5LCBJbnQzMkFycmF5LmZyb20oWzYsIDMwLCA1NCwgNzgsIDEwMiwgMTI2XSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoNywgMTE2KSwgbmV3IEVDQiQxKDcsIDExNykpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDIxLCA0NSksIG5ldyBFQ0IkMSg3LCA0NikpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDEsIDIzKSwgbmV3IEVDQiQxKDM3LCAyNCkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDE5LCAxNSksIG5ldyBFQ0IkMSgyNiwgMTYpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMzAsIEludDMyQXJyYXkuZnJvbShbNiwgMjYsIDUyLCA3OCwgMTA0LCAxMzBdKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSg1LCAxMTUpLCBuZXcgRUNCJDEoMTAsIDExNikpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDE5LCA0NyksIG5ldyBFQ0IkMSgxMCwgNDgpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgxNSwgMjQpLCBuZXcgRUNCJDEoMjUsIDI1KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMjMsIDE1KSwgbmV3IEVDQiQxKDI1LCAxNikpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgzMSwgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTYsIDgyLCAxMDgsIDEzNF0pLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDEzLCAxMTUpLCBuZXcgRUNCJDEoMywgMTE2KSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMiwgNDYpLCBuZXcgRUNCJDEoMjksIDQ3KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoNDIsIDI0KSwgbmV3IEVDQiQxKDEsIDI1KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMjMsIDE1KSwgbmV3IEVDQiQxKDI4LCAxNikpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgzMiwgSW50MzJBcnJheS5mcm9tKFs2LCAzNCwgNjAsIDg2LCAxMTIsIDEzOF0pLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDE3LCAxMTUpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgxMCwgNDYpLCBuZXcgRUNCJDEoMjMsIDQ3KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMTAsIDI0KSwgbmV3IEVDQiQxKDM1LCAyNSkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDE5LCAxNSksIG5ldyBFQ0IkMSgzNSwgMTYpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMzMsIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIDU4LCA4NiwgMTE0LCAxNDJdKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgxNywgMTE1KSwgbmV3IEVDQiQxKDEsIDExNikpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDE0LCA0NiksIG5ldyBFQ0IkMSgyMSwgNDcpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgyOSwgMjQpLCBuZXcgRUNCJDEoMTksIDI1KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMTEsIDE1KSwgbmV3IEVDQiQxKDQ2LCAxNikpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgzNCwgSW50MzJBcnJheS5mcm9tKFs2LCAzNCwgNjIsIDkwLCAxMTgsIDE0Nl0pLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDEzLCAxMTUpLCBuZXcgRUNCJDEoNiwgMTE2KSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMTQsIDQ2KSwgbmV3IEVDQiQxKDIzLCA0NykpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDQ0LCAyNCksIG5ldyBFQ0IkMSg3LCAyNSkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDU5LCAxNiksIG5ldyBFQ0IkMSgxLCAxNykpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgzNSwgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTQsIDc4LCAxMDIsIDEyNiwgMTUwXSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMTIsIDEyMSksIG5ldyBFQ0IkMSg3LCAxMjIpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgxMiwgNDcpLCBuZXcgRUNCJDEoMjYsIDQ4KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMzksIDI0KSwgbmV3IEVDQiQxKDE0LCAyNSkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDIyLCAxNSksIG5ldyBFQ0IkMSg0MSwgMTYpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMzYsIEludDMyQXJyYXkuZnJvbShbNiwgMjQsIDUwLCA3NiwgMTAyLCAxMjgsIDE1NF0pLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDYsIDEyMSksIG5ldyBFQ0IkMSgxNCwgMTIyKSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoNiwgNDcpLCBuZXcgRUNCJDEoMzQsIDQ4KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoNDYsIDI0KSwgbmV3IEVDQiQxKDEwLCAyNSkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDIsIDE1KSwgbmV3IEVDQiQxKDY0LCAxNikpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgzNywgSW50MzJBcnJheS5mcm9tKFs2LCAyOCwgNTQsIDgwLCAxMDYsIDEzMiwgMTU4XSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMTcsIDEyMiksIG5ldyBFQ0IkMSg0LCAxMjMpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgyOSwgNDYpLCBuZXcgRUNCJDEoMTQsIDQ3KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoNDksIDI0KSwgbmV3IEVDQiQxKDEwLCAyNSkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDI0LCAxNSksIG5ldyBFQ0IkMSg0NiwgMTYpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMzgsIEludDMyQXJyYXkuZnJvbShbNiwgMzIsIDU4LCA4NCwgMTEwLCAxMzYsIDE2Ml0pLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDQsIDEyMiksIG5ldyBFQ0IkMSgxOCwgMTIzKSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMTMsIDQ2KSwgbmV3IEVDQiQxKDMyLCA0NykpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDQ4LCAyNCksIG5ldyBFQ0IkMSgxNCwgMjUpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSg0MiwgMTUpLCBuZXcgRUNCJDEoMzIsIDE2KSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDM5LCBJbnQzMkFycmF5LmZyb20oWzYsIDI2LCA1NCwgODIsIDExMCwgMTM4LCAxNjZdKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgyMCwgMTE3KSwgbmV3IEVDQiQxKDQsIDExOCkpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDQwLCA0NyksIG5ldyBFQ0IkMSg3LCA0OCkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDQzLCAyNCksIG5ldyBFQ0IkMSgyMiwgMjUpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgxMCwgMTUpLCBuZXcgRUNCJDEoNjcsIDE2KSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDQwLCBJbnQzMkFycmF5LmZyb20oWzYsIDMwLCA1OCwgODYsIDExNCwgMTQyLCAxNzBdKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgxOSwgMTE4KSwgbmV3IEVDQiQxKDYsIDExOSkpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDE4LCA0NyksIG5ldyBFQ0IkMSgzMSwgNDgpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgzNCwgMjQpLCBuZXcgRUNCJDEoMzQsIDI1KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMjAsIDE1KSwgbmV3IEVDQiQxKDYxLCAxNikpKVxuICAgIF07XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIHZhciBEYXRhTWFza1ZhbHVlcztcbiAgICAoZnVuY3Rpb24gKERhdGFNYXNrVmFsdWVzKSB7XG4gICAgICAgIERhdGFNYXNrVmFsdWVzW0RhdGFNYXNrVmFsdWVzW1wiREFUQV9NQVNLXzAwMFwiXSA9IDBdID0gXCJEQVRBX01BU0tfMDAwXCI7XG4gICAgICAgIERhdGFNYXNrVmFsdWVzW0RhdGFNYXNrVmFsdWVzW1wiREFUQV9NQVNLXzAwMVwiXSA9IDFdID0gXCJEQVRBX01BU0tfMDAxXCI7XG4gICAgICAgIERhdGFNYXNrVmFsdWVzW0RhdGFNYXNrVmFsdWVzW1wiREFUQV9NQVNLXzAxMFwiXSA9IDJdID0gXCJEQVRBX01BU0tfMDEwXCI7XG4gICAgICAgIERhdGFNYXNrVmFsdWVzW0RhdGFNYXNrVmFsdWVzW1wiREFUQV9NQVNLXzAxMVwiXSA9IDNdID0gXCJEQVRBX01BU0tfMDExXCI7XG4gICAgICAgIERhdGFNYXNrVmFsdWVzW0RhdGFNYXNrVmFsdWVzW1wiREFUQV9NQVNLXzEwMFwiXSA9IDRdID0gXCJEQVRBX01BU0tfMTAwXCI7XG4gICAgICAgIERhdGFNYXNrVmFsdWVzW0RhdGFNYXNrVmFsdWVzW1wiREFUQV9NQVNLXzEwMVwiXSA9IDVdID0gXCJEQVRBX01BU0tfMTAxXCI7XG4gICAgICAgIERhdGFNYXNrVmFsdWVzW0RhdGFNYXNrVmFsdWVzW1wiREFUQV9NQVNLXzExMFwiXSA9IDZdID0gXCJEQVRBX01BU0tfMTEwXCI7XG4gICAgICAgIERhdGFNYXNrVmFsdWVzW0RhdGFNYXNrVmFsdWVzW1wiREFUQV9NQVNLXzExMVwiXSA9IDddID0gXCJEQVRBX01BU0tfMTExXCI7XG4gICAgfSkoRGF0YU1hc2tWYWx1ZXMgfHwgKERhdGFNYXNrVmFsdWVzID0ge30pKTtcbiAgICAvKipcbiAgICAgKiA8cD5FbmNhcHN1bGF0ZXMgZGF0YSBtYXNrcyBmb3IgdGhlIGRhdGEgYml0cyBpbiBhIFFSIGNvZGUsIHBlciBJU08gMTgwMDQ6MjAwNiA2LjguIEltcGxlbWVudGF0aW9uc1xuICAgICAqIG9mIHRoaXMgY2xhc3MgY2FuIHVuLW1hc2sgYSByYXcgQml0TWF0cml4LiBGb3Igc2ltcGxpY2l0eSwgdGhleSB3aWxsIHVubWFzayB0aGUgZW50aXJlIEJpdE1hdHJpeCxcbiAgICAgKiBpbmNsdWRpbmcgYXJlYXMgdXNlZCBmb3IgZmluZGVyIHBhdHRlcm5zLCB0aW1pbmcgcGF0dGVybnMsIGV0Yy4gVGhlc2UgYXJlYXMgc2hvdWxkIGJlIHVudXNlZFxuICAgICAqIGFmdGVyIHRoZSBwb2ludCB0aGV5IGFyZSB1bm1hc2tlZCBhbnl3YXkuPC9wPlxuICAgICAqXG4gICAgICogPHA+Tm90ZSB0aGF0IHRoZSBkaWFncmFtIGluIHNlY3Rpb24gNi44LjEgaXMgbWlzbGVhZGluZyBzaW5jZSBpdCBpbmRpY2F0ZXMgdGhhdCBpIGlzIGNvbHVtbiBwb3NpdGlvblxuICAgICAqIGFuZCBqIGlzIHJvdyBwb3NpdGlvbi4gSW4gZmFjdCwgYXMgdGhlIHRleHQgc2F5cywgaSBpcyByb3cgcG9zaXRpb24gYW5kIGogaXMgY29sdW1uIHBvc2l0aW9uLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgRGF0YU1hc2sge1xuICAgICAgICAvLyBTZWUgSVNPIDE4MDA0OjIwMDYgNi44LjFcbiAgICAgICAgY29uc3RydWN0b3IodmFsdWUsIGlzTWFza2VkKSB7XG4gICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB0aGlzLmlzTWFza2VkID0gaXNNYXNrZWQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRW5kIG9mIGVudW0gY29uc3RhbnRzLlxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+SW1wbGVtZW50YXRpb25zIG9mIHRoaXMgbWV0aG9kIHJldmVyc2UgdGhlIGRhdGEgbWFza2luZyBwcm9jZXNzIGFwcGxpZWQgdG8gYSBRUiBDb2RlIGFuZFxuICAgICAgICAgKiBtYWtlIGl0cyBiaXRzIHJlYWR5IHRvIHJlYWQuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gYml0cyByZXByZXNlbnRhdGlvbiBvZiBRUiBDb2RlIGJpdHNcbiAgICAgICAgICogQHBhcmFtIGRpbWVuc2lvbiBkaW1lbnNpb24gb2YgUVIgQ29kZSwgcmVwcmVzZW50ZWQgYnkgYml0cywgYmVpbmcgdW5tYXNrZWRcbiAgICAgICAgICovXG4gICAgICAgIHVubWFza0JpdE1hdHJpeChiaXRzLCBkaW1lbnNpb24gLyppbnQqLykge1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkaW1lbnNpb247IGkrKykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgZGltZW5zaW9uOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNNYXNrZWQoaSwgaikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJpdHMuZmxpcChqLCBpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBEYXRhTWFzay52YWx1ZXMgPSBuZXcgTWFwKFtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIDAwMDogbWFzayBiaXRzIGZvciB3aGljaCAoeCArIHkpIG1vZCAyID09IDBcbiAgICAgICAgICovXG4gICAgICAgIFtEYXRhTWFza1ZhbHVlcy5EQVRBX01BU0tfMDAwLCBuZXcgRGF0YU1hc2soRGF0YU1hc2tWYWx1ZXMuREFUQV9NQVNLXzAwMCwgKGkgLyppbnQqLywgaiAvKmludCovKSA9PiB7IHJldHVybiAoKGkgKyBqKSAmIDB4MDEpID09PSAwOyB9KV0sXG4gICAgICAgIC8qKlxuICAgICAgICAgKiAwMDE6IG1hc2sgYml0cyBmb3Igd2hpY2ggeCBtb2QgMiA9PSAwXG4gICAgICAgICAqL1xuICAgICAgICBbRGF0YU1hc2tWYWx1ZXMuREFUQV9NQVNLXzAwMSwgbmV3IERhdGFNYXNrKERhdGFNYXNrVmFsdWVzLkRBVEFfTUFTS18wMDEsIChpIC8qaW50Ki8sIGogLyppbnQqLykgPT4geyByZXR1cm4gKGkgJiAweDAxKSA9PT0gMDsgfSldLFxuICAgICAgICAvKipcbiAgICAgICAgICogMDEwOiBtYXNrIGJpdHMgZm9yIHdoaWNoIHkgbW9kIDMgPT0gMFxuICAgICAgICAgKi9cbiAgICAgICAgW0RhdGFNYXNrVmFsdWVzLkRBVEFfTUFTS18wMTAsIG5ldyBEYXRhTWFzayhEYXRhTWFza1ZhbHVlcy5EQVRBX01BU0tfMDEwLCAoaSAvKmludCovLCBqIC8qaW50Ki8pID0+IHsgcmV0dXJuIGogJSAzID09PSAwOyB9KV0sXG4gICAgICAgIC8qKlxuICAgICAgICAgKiAwMTE6IG1hc2sgYml0cyBmb3Igd2hpY2ggKHggKyB5KSBtb2QgMyA9PSAwXG4gICAgICAgICAqL1xuICAgICAgICBbRGF0YU1hc2tWYWx1ZXMuREFUQV9NQVNLXzAxMSwgbmV3IERhdGFNYXNrKERhdGFNYXNrVmFsdWVzLkRBVEFfTUFTS18wMTEsIChpIC8qaW50Ki8sIGogLyppbnQqLykgPT4geyByZXR1cm4gKGkgKyBqKSAlIDMgPT09IDA7IH0pXSxcbiAgICAgICAgLyoqXG4gICAgICAgICAqIDEwMDogbWFzayBiaXRzIGZvciB3aGljaCAoeC8yICsgeS8zKSBtb2QgMiA9PSAwXG4gICAgICAgICAqL1xuICAgICAgICBbRGF0YU1hc2tWYWx1ZXMuREFUQV9NQVNLXzEwMCwgbmV3IERhdGFNYXNrKERhdGFNYXNrVmFsdWVzLkRBVEFfTUFTS18xMDAsIChpIC8qaW50Ki8sIGogLyppbnQqLykgPT4geyByZXR1cm4gKChNYXRoLmZsb29yKGkgLyAyKSArIE1hdGguZmxvb3IoaiAvIDMpKSAmIDB4MDEpID09PSAwOyB9KV0sXG4gICAgICAgIC8qKlxuICAgICAgICAgKiAxMDE6IG1hc2sgYml0cyBmb3Igd2hpY2ggeHkgbW9kIDIgKyB4eSBtb2QgMyA9PSAwXG4gICAgICAgICAqIGVxdWl2YWxlbnRseSwgc3VjaCB0aGF0IHh5IG1vZCA2ID09IDBcbiAgICAgICAgICovXG4gICAgICAgIFtEYXRhTWFza1ZhbHVlcy5EQVRBX01BU0tfMTAxLCBuZXcgRGF0YU1hc2soRGF0YU1hc2tWYWx1ZXMuREFUQV9NQVNLXzEwMSwgKGkgLyppbnQqLywgaiAvKmludCovKSA9PiB7IHJldHVybiAoaSAqIGopICUgNiA9PT0gMDsgfSldLFxuICAgICAgICAvKipcbiAgICAgICAgICogMTEwOiBtYXNrIGJpdHMgZm9yIHdoaWNoICh4eSBtb2QgMiArIHh5IG1vZCAzKSBtb2QgMiA9PSAwXG4gICAgICAgICAqIGVxdWl2YWxlbnRseSwgc3VjaCB0aGF0IHh5IG1vZCA2IDwgM1xuICAgICAgICAgKi9cbiAgICAgICAgW0RhdGFNYXNrVmFsdWVzLkRBVEFfTUFTS18xMTAsIG5ldyBEYXRhTWFzayhEYXRhTWFza1ZhbHVlcy5EQVRBX01BU0tfMTEwLCAoaSAvKmludCovLCBqIC8qaW50Ki8pID0+IHsgcmV0dXJuICgoaSAqIGopICUgNikgPCAzOyB9KV0sXG4gICAgICAgIC8qKlxuICAgICAgICAgKiAxMTE6IG1hc2sgYml0cyBmb3Igd2hpY2ggKCh4K3kpbW9kIDIgKyB4eSBtb2QgMykgbW9kIDIgPT0gMFxuICAgICAgICAgKiBlcXVpdmFsZW50bHksIHN1Y2ggdGhhdCAoeCArIHkgKyB4eSBtb2QgMykgbW9kIDIgPT0gMFxuICAgICAgICAgKi9cbiAgICAgICAgW0RhdGFNYXNrVmFsdWVzLkRBVEFfTUFTS18xMTEsIG5ldyBEYXRhTWFzayhEYXRhTWFza1ZhbHVlcy5EQVRBX01BU0tfMTExLCAoaSAvKmludCovLCBqIC8qaW50Ki8pID0+IHsgcmV0dXJuICgoaSArIGogKyAoKGkgKiBqKSAlIDMpKSAmIDB4MDEpID09PSAwOyB9KV0sXG4gICAgXSk7XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgQml0TWF0cml4UGFyc2VyJDEge1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIGJpdE1hdHJpeCB7QGxpbmsgQml0TWF0cml4fSB0byBwYXJzZVxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvbiBpZiBkaW1lbnNpb24gaXMgbm90ID49IDIxIGFuZCAxIG1vZCA0XG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3RvcihiaXRNYXRyaXgpIHtcbiAgICAgICAgICAgIGNvbnN0IGRpbWVuc2lvbiA9IGJpdE1hdHJpeC5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGlmIChkaW1lbnNpb24gPCAyMSB8fCAoZGltZW5zaW9uICYgMHgwMykgIT09IDEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmJpdE1hdHJpeCA9IGJpdE1hdHJpeDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+UmVhZHMgZm9ybWF0IGluZm9ybWF0aW9uIGZyb20gb25lIG9mIGl0cyB0d28gbG9jYXRpb25zIHdpdGhpbiB0aGUgUVIgQ29kZS48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4ge0BsaW5rIEZvcm1hdEluZm9ybWF0aW9ufSBlbmNhcHN1bGF0aW5nIHRoZSBRUiBDb2RlJ3MgZm9ybWF0IGluZm9cbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb24gaWYgYm90aCBmb3JtYXQgaW5mb3JtYXRpb24gbG9jYXRpb25zIGNhbm5vdCBiZSBwYXJzZWQgYXNcbiAgICAgICAgICogdGhlIHZhbGlkIGVuY29kaW5nIG9mIGZvcm1hdCBpbmZvcm1hdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgcmVhZEZvcm1hdEluZm9ybWF0aW9uKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMucGFyc2VkRm9ybWF0SW5mbyAhPT0gbnVsbCAmJiB0aGlzLnBhcnNlZEZvcm1hdEluZm8gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcnNlZEZvcm1hdEluZm87XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBSZWFkIHRvcC1sZWZ0IGZvcm1hdCBpbmZvIGJpdHNcbiAgICAgICAgICAgIGxldCBmb3JtYXRJbmZvQml0czEgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCA2OyBpKyspIHtcbiAgICAgICAgICAgICAgICBmb3JtYXRJbmZvQml0czEgPSB0aGlzLmNvcHlCaXQoaSwgOCwgZm9ybWF0SW5mb0JpdHMxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIC4uIGFuZCBza2lwIGEgYml0IGluIHRoZSB0aW1pbmcgcGF0dGVybiAuLi5cbiAgICAgICAgICAgIGZvcm1hdEluZm9CaXRzMSA9IHRoaXMuY29weUJpdCg3LCA4LCBmb3JtYXRJbmZvQml0czEpO1xuICAgICAgICAgICAgZm9ybWF0SW5mb0JpdHMxID0gdGhpcy5jb3B5Qml0KDgsIDgsIGZvcm1hdEluZm9CaXRzMSk7XG4gICAgICAgICAgICBmb3JtYXRJbmZvQml0czEgPSB0aGlzLmNvcHlCaXQoOCwgNywgZm9ybWF0SW5mb0JpdHMxKTtcbiAgICAgICAgICAgIC8vIC4uIGFuZCBza2lwIGEgYml0IGluIHRoZSB0aW1pbmcgcGF0dGVybiAuLi5cbiAgICAgICAgICAgIGZvciAobGV0IGogPSA1OyBqID49IDA7IGotLSkge1xuICAgICAgICAgICAgICAgIGZvcm1hdEluZm9CaXRzMSA9IHRoaXMuY29weUJpdCg4LCBqLCBmb3JtYXRJbmZvQml0czEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gUmVhZCB0aGUgdG9wLXJpZ2h0L2JvdHRvbS1sZWZ0IHBhdHRlcm4gdG9vXG4gICAgICAgICAgICBjb25zdCBkaW1lbnNpb24gPSB0aGlzLmJpdE1hdHJpeC5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGxldCBmb3JtYXRJbmZvQml0czIgPSAwO1xuICAgICAgICAgICAgY29uc3Qgak1pbiA9IGRpbWVuc2lvbiAtIDc7XG4gICAgICAgICAgICBmb3IgKGxldCBqID0gZGltZW5zaW9uIC0gMTsgaiA+PSBqTWluOyBqLS0pIHtcbiAgICAgICAgICAgICAgICBmb3JtYXRJbmZvQml0czIgPSB0aGlzLmNvcHlCaXQoOCwgaiwgZm9ybWF0SW5mb0JpdHMyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBkaW1lbnNpb24gLSA4OyBpIDwgZGltZW5zaW9uOyBpKyspIHtcbiAgICAgICAgICAgICAgICBmb3JtYXRJbmZvQml0czIgPSB0aGlzLmNvcHlCaXQoaSwgOCwgZm9ybWF0SW5mb0JpdHMyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucGFyc2VkRm9ybWF0SW5mbyA9IEZvcm1hdEluZm9ybWF0aW9uLmRlY29kZUZvcm1hdEluZm9ybWF0aW9uKGZvcm1hdEluZm9CaXRzMSwgZm9ybWF0SW5mb0JpdHMyKTtcbiAgICAgICAgICAgIGlmICh0aGlzLnBhcnNlZEZvcm1hdEluZm8gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJzZWRGb3JtYXRJbmZvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5SZWFkcyB2ZXJzaW9uIGluZm9ybWF0aW9uIGZyb20gb25lIG9mIGl0cyB0d28gbG9jYXRpb25zIHdpdGhpbiB0aGUgUVIgQ29kZS48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4ge0BsaW5rIFZlcnNpb259IGVuY2Fwc3VsYXRpbmcgdGhlIFFSIENvZGUncyB2ZXJzaW9uXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uIGlmIGJvdGggdmVyc2lvbiBpbmZvcm1hdGlvbiBsb2NhdGlvbnMgY2Fubm90IGJlIHBhcnNlZCBhc1xuICAgICAgICAgKiB0aGUgdmFsaWQgZW5jb2Rpbmcgb2YgdmVyc2lvbiBpbmZvcm1hdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgcmVhZFZlcnNpb24oKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5wYXJzZWRWZXJzaW9uICE9PSBudWxsICYmIHRoaXMucGFyc2VkVmVyc2lvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyc2VkVmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGRpbWVuc2lvbiA9IHRoaXMuYml0TWF0cml4LmdldEhlaWdodCgpO1xuICAgICAgICAgICAgY29uc3QgcHJvdmlzaW9uYWxWZXJzaW9uID0gTWF0aC5mbG9vcigoZGltZW5zaW9uIC0gMTcpIC8gNCk7XG4gICAgICAgICAgICBpZiAocHJvdmlzaW9uYWxWZXJzaW9uIDw9IDYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gVmVyc2lvbiQxLmdldFZlcnNpb25Gb3JOdW1iZXIocHJvdmlzaW9uYWxWZXJzaW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFJlYWQgdG9wLXJpZ2h0IHZlcnNpb24gaW5mbzogMyB3aWRlIGJ5IDYgdGFsbFxuICAgICAgICAgICAgbGV0IHZlcnNpb25CaXRzID0gMDtcbiAgICAgICAgICAgIGNvbnN0IGlqTWluID0gZGltZW5zaW9uIC0gMTE7XG4gICAgICAgICAgICBmb3IgKGxldCBqID0gNTsgaiA+PSAwOyBqLS0pIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gZGltZW5zaW9uIC0gOTsgaSA+PSBpak1pbjsgaS0tKSB7XG4gICAgICAgICAgICAgICAgICAgIHZlcnNpb25CaXRzID0gdGhpcy5jb3B5Qml0KGksIGosIHZlcnNpb25CaXRzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgdGhlUGFyc2VkVmVyc2lvbiA9IFZlcnNpb24kMS5kZWNvZGVWZXJzaW9uSW5mb3JtYXRpb24odmVyc2lvbkJpdHMpO1xuICAgICAgICAgICAgaWYgKHRoZVBhcnNlZFZlcnNpb24gIT09IG51bGwgJiYgdGhlUGFyc2VkVmVyc2lvbi5nZXREaW1lbnNpb25Gb3JWZXJzaW9uKCkgPT09IGRpbWVuc2lvbikge1xuICAgICAgICAgICAgICAgIHRoaXMucGFyc2VkVmVyc2lvbiA9IHRoZVBhcnNlZFZlcnNpb247XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoZVBhcnNlZFZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBIbW0sIGZhaWxlZC4gVHJ5IGJvdHRvbSBsZWZ0OiA2IHdpZGUgYnkgMyB0YWxsXG4gICAgICAgICAgICB2ZXJzaW9uQml0cyA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gNTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gZGltZW5zaW9uIC0gOTsgaiA+PSBpak1pbjsgai0tKSB7XG4gICAgICAgICAgICAgICAgICAgIHZlcnNpb25CaXRzID0gdGhpcy5jb3B5Qml0KGksIGosIHZlcnNpb25CaXRzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGVQYXJzZWRWZXJzaW9uID0gVmVyc2lvbiQxLmRlY29kZVZlcnNpb25JbmZvcm1hdGlvbih2ZXJzaW9uQml0cyk7XG4gICAgICAgICAgICBpZiAodGhlUGFyc2VkVmVyc2lvbiAhPT0gbnVsbCAmJiB0aGVQYXJzZWRWZXJzaW9uLmdldERpbWVuc2lvbkZvclZlcnNpb24oKSA9PT0gZGltZW5zaW9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXJzZWRWZXJzaW9uID0gdGhlUGFyc2VkVmVyc2lvbjtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhlUGFyc2VkVmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgfVxuICAgICAgICBjb3B5Qml0KGkgLyppbnQqLywgaiAvKmludCovLCB2ZXJzaW9uQml0cyAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBiaXQgPSB0aGlzLmlzTWlycm9yID8gdGhpcy5iaXRNYXRyaXguZ2V0KGosIGkpIDogdGhpcy5iaXRNYXRyaXguZ2V0KGksIGopO1xuICAgICAgICAgICAgcmV0dXJuIGJpdCA/ICh2ZXJzaW9uQml0cyA8PCAxKSB8IDB4MSA6IHZlcnNpb25CaXRzIDw8IDE7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPlJlYWRzIHRoZSBiaXRzIGluIHRoZSB7QGxpbmsgQml0TWF0cml4fSByZXByZXNlbnRpbmcgdGhlIGZpbmRlciBwYXR0ZXJuIGluIHRoZVxuICAgICAgICAgKiBjb3JyZWN0IG9yZGVyIGluIG9yZGVyIHRvIHJlY29uc3RydWN0IHRoZSBjb2Rld29yZHMgYnl0ZXMgY29udGFpbmVkIHdpdGhpbiB0aGVcbiAgICAgICAgICogUVIgQ29kZS48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gYnl0ZXMgZW5jb2RlZCB3aXRoaW4gdGhlIFFSIENvZGVcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb24gaWYgdGhlIGV4YWN0IG51bWJlciBvZiBieXRlcyBleHBlY3RlZCBpcyBub3QgcmVhZFxuICAgICAgICAgKi9cbiAgICAgICAgcmVhZENvZGV3b3JkcygpIHtcbiAgICAgICAgICAgIGNvbnN0IGZvcm1hdEluZm8gPSB0aGlzLnJlYWRGb3JtYXRJbmZvcm1hdGlvbigpO1xuICAgICAgICAgICAgY29uc3QgdmVyc2lvbiA9IHRoaXMucmVhZFZlcnNpb24oKTtcbiAgICAgICAgICAgIC8vIEdldCB0aGUgZGF0YSBtYXNrIGZvciB0aGUgZm9ybWF0IHVzZWQgaW4gdGhpcyBRUiBDb2RlLiBUaGlzIHdpbGwgZXhjbHVkZVxuICAgICAgICAgICAgLy8gc29tZSBiaXRzIGZyb20gcmVhZGluZyBhcyB3ZSB3aW5kIHRocm91Z2ggdGhlIGJpdCBtYXRyaXguXG4gICAgICAgICAgICBjb25zdCBkYXRhTWFzayA9IERhdGFNYXNrLnZhbHVlcy5nZXQoZm9ybWF0SW5mby5nZXREYXRhTWFzaygpKTtcbiAgICAgICAgICAgIGNvbnN0IGRpbWVuc2lvbiA9IHRoaXMuYml0TWF0cml4LmdldEhlaWdodCgpO1xuICAgICAgICAgICAgZGF0YU1hc2sudW5tYXNrQml0TWF0cml4KHRoaXMuYml0TWF0cml4LCBkaW1lbnNpb24pO1xuICAgICAgICAgICAgY29uc3QgZnVuY3Rpb25QYXR0ZXJuID0gdmVyc2lvbi5idWlsZEZ1bmN0aW9uUGF0dGVybigpO1xuICAgICAgICAgICAgbGV0IHJlYWRpbmdVcCA9IHRydWU7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgVWludDhBcnJheSh2ZXJzaW9uLmdldFRvdGFsQ29kZXdvcmRzKCkpO1xuICAgICAgICAgICAgbGV0IHJlc3VsdE9mZnNldCA9IDA7XG4gICAgICAgICAgICBsZXQgY3VycmVudEJ5dGUgPSAwO1xuICAgICAgICAgICAgbGV0IGJpdHNSZWFkID0gMDtcbiAgICAgICAgICAgIC8vIFJlYWQgY29sdW1ucyBpbiBwYWlycywgZnJvbSByaWdodCB0byBsZWZ0XG4gICAgICAgICAgICBmb3IgKGxldCBqID0gZGltZW5zaW9uIC0gMTsgaiA+IDA7IGogLT0gMikge1xuICAgICAgICAgICAgICAgIGlmIChqID09PSA2KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFNraXAgd2hvbGUgY29sdW1uIHdpdGggdmVydGljYWwgYWxpZ25tZW50IHBhdHRlcm5cbiAgICAgICAgICAgICAgICAgICAgLy8gc2F2ZXMgdGltZSBhbmQgbWFrZXMgdGhlIG90aGVyIGNvZGUgcHJvY2VlZCBtb3JlIGNsZWFubHlcbiAgICAgICAgICAgICAgICAgICAgai0tO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBSZWFkIGFsdGVybmF0aW5nbHkgZnJvbSBib3R0b20gdG8gdG9wIHRoZW4gdG9wIHRvIGJvdHRvbVxuICAgICAgICAgICAgICAgIGZvciAobGV0IGNvdW50ID0gMDsgY291bnQgPCBkaW1lbnNpb247IGNvdW50KyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaSA9IHJlYWRpbmdVcCA/IGRpbWVuc2lvbiAtIDEgLSBjb3VudCA6IGNvdW50O1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBjb2wgPSAwOyBjb2wgPCAyOyBjb2wrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWdub3JlIGJpdHMgY292ZXJlZCBieSB0aGUgZnVuY3Rpb24gcGF0dGVyblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFmdW5jdGlvblBhdHRlcm4uZ2V0KGogLSBjb2wsIGkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVhZCBhIGJpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpdHNSZWFkKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuYml0TWF0cml4LmdldChqIC0gY29sLCBpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB3ZSd2ZSBtYWRlIGEgd2hvbGUgYnl0ZSwgc2F2ZSBpdCBvZmZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYml0c1JlYWQgPT09IDgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0W3Jlc3VsdE9mZnNldCsrXSA9IC8qKGJ5dGUpICovIGN1cnJlbnRCeXRlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaXRzUmVhZCA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVhZGluZ1VwID0gIXJlYWRpbmdVcDsgLy8gcmVhZGluZ1VwIF49IHRydWU7IC8vIHJlYWRpbmdVcCA9ICFyZWFkaW5nVXA7IC8vIHN3aXRjaCBkaXJlY3Rpb25zXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmVzdWx0T2Zmc2V0ICE9PSB2ZXJzaW9uLmdldFRvdGFsQ29kZXdvcmRzKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXZlcnQgdGhlIG1hc2sgcmVtb3ZhbCBkb25lIHdoaWxlIHJlYWRpbmcgdGhlIGNvZGUgd29yZHMuIFRoZSBiaXQgbWF0cml4IHNob3VsZCByZXZlcnQgdG8gaXRzIG9yaWdpbmFsIHN0YXRlLlxuICAgICAgICAgKi9cbiAgICAgICAgcmVtYXNrKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMucGFyc2VkRm9ybWF0SW5mbyA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybjsgLy8gV2UgaGF2ZSBubyBmb3JtYXQgaW5mb3JtYXRpb24sIGFuZCBoYXZlIG5vIGRhdGEgbWFza1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZGF0YU1hc2sgPSBEYXRhTWFzay52YWx1ZXNbdGhpcy5wYXJzZWRGb3JtYXRJbmZvLmdldERhdGFNYXNrKCldO1xuICAgICAgICAgICAgY29uc3QgZGltZW5zaW9uID0gdGhpcy5iaXRNYXRyaXguZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICBkYXRhTWFzay51bm1hc2tCaXRNYXRyaXgodGhpcy5iaXRNYXRyaXgsIGRpbWVuc2lvbik7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFByZXBhcmUgdGhlIHBhcnNlciBmb3IgYSBtaXJyb3JlZCBvcGVyYXRpb24uXG4gICAgICAgICAqIFRoaXMgZmxhZyBoYXMgZWZmZWN0IG9ubHkgb24gdGhlIHtAbGluayAjcmVhZEZvcm1hdEluZm9ybWF0aW9uKCl9IGFuZCB0aGVcbiAgICAgICAgICoge0BsaW5rICNyZWFkVmVyc2lvbigpfS4gQmVmb3JlIHByb2NlZWRpbmcgd2l0aCB7QGxpbmsgI3JlYWRDb2Rld29yZHMoKX0gdGhlXG4gICAgICAgICAqIHtAbGluayAjbWlycm9yKCl9IG1ldGhvZCBzaG91bGQgYmUgY2FsbGVkLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gbWlycm9yIFdoZXRoZXIgdG8gcmVhZCB2ZXJzaW9uIGFuZCBmb3JtYXQgaW5mb3JtYXRpb24gbWlycm9yZWQuXG4gICAgICAgICAqL1xuICAgICAgICBzZXRNaXJyb3IoaXNNaXJyb3IpIHtcbiAgICAgICAgICAgIHRoaXMucGFyc2VkVmVyc2lvbiA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnBhcnNlZEZvcm1hdEluZm8gPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5pc01pcnJvciA9IGlzTWlycm9yO1xuICAgICAgICB9XG4gICAgICAgIC8qKiBNaXJyb3IgdGhlIGJpdCBtYXRyaXggaW4gb3JkZXIgdG8gYXR0ZW1wdCBhIHNlY29uZCByZWFkaW5nLiAqL1xuICAgICAgICBtaXJyb3IoKSB7XG4gICAgICAgICAgICBjb25zdCBiaXRNYXRyaXggPSB0aGlzLmJpdE1hdHJpeDtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwLCB3aWR0aCA9IGJpdE1hdHJpeC5nZXRXaWR0aCgpOyB4IDwgd2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHkgPSB4ICsgMSwgaGVpZ2h0ID0gYml0TWF0cml4LmdldEhlaWdodCgpOyB5IDwgaGVpZ2h0OyB5KyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGJpdE1hdHJpeC5nZXQoeCwgeSkgIT09IGJpdE1hdHJpeC5nZXQoeSwgeCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJpdE1hdHJpeC5mbGlwKHksIHgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYml0TWF0cml4LmZsaXAoeCwgeSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIDxwPkVuY2Fwc3VsYXRlcyBhIGJsb2NrIG9mIGRhdGEgd2l0aGluIGEgUVIgQ29kZS4gUVIgQ29kZXMgbWF5IHNwbGl0IHRoZWlyIGRhdGEgaW50b1xuICAgICAqIG11bHRpcGxlIGJsb2NrcywgZWFjaCBvZiB3aGljaCBpcyBhIHVuaXQgb2YgZGF0YSBhbmQgZXJyb3ItY29ycmVjdGlvbiBjb2Rld29yZHMuIEVhY2hcbiAgICAgKiBpcyByZXByZXNlbnRlZCBieSBhbiBpbnN0YW5jZSBvZiB0aGlzIGNsYXNzLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgRGF0YUJsb2NrJDEge1xuICAgICAgICBjb25zdHJ1Y3RvcihudW1EYXRhQ29kZXdvcmRzIC8qaW50Ki8sIGNvZGV3b3Jkcykge1xuICAgICAgICAgICAgdGhpcy5udW1EYXRhQ29kZXdvcmRzID0gbnVtRGF0YUNvZGV3b3JkcztcbiAgICAgICAgICAgIHRoaXMuY29kZXdvcmRzID0gY29kZXdvcmRzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5XaGVuIFFSIENvZGVzIHVzZSBtdWx0aXBsZSBkYXRhIGJsb2NrcywgdGhleSBhcmUgYWN0dWFsbHkgaW50ZXJsZWF2ZWQuXG4gICAgICAgICAqIFRoYXQgaXMsIHRoZSBmaXJzdCBieXRlIG9mIGRhdGEgYmxvY2sgMSB0byBuIGlzIHdyaXR0ZW4sIHRoZW4gdGhlIHNlY29uZCBieXRlcywgYW5kIHNvIG9uLiBUaGlzXG4gICAgICAgICAqIG1ldGhvZCB3aWxsIHNlcGFyYXRlIHRoZSBkYXRhIGludG8gb3JpZ2luYWwgYmxvY2tzLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHJhd0NvZGV3b3JkcyBieXRlcyBhcyByZWFkIGRpcmVjdGx5IGZyb20gdGhlIFFSIENvZGVcbiAgICAgICAgICogQHBhcmFtIHZlcnNpb24gdmVyc2lvbiBvZiB0aGUgUVIgQ29kZVxuICAgICAgICAgKiBAcGFyYW0gZWNMZXZlbCBlcnJvci1jb3JyZWN0aW9uIGxldmVsIG9mIHRoZSBRUiBDb2RlXG4gICAgICAgICAqIEByZXR1cm4gRGF0YUJsb2NrcyBjb250YWluaW5nIG9yaWdpbmFsIGJ5dGVzLCBcImRlLWludGVybGVhdmVkXCIgZnJvbSByZXByZXNlbnRhdGlvbiBpbiB0aGVcbiAgICAgICAgICogICAgICAgICBRUiBDb2RlXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZ2V0RGF0YUJsb2NrcyhyYXdDb2Rld29yZHMsIHZlcnNpb24sIGVjTGV2ZWwpIHtcbiAgICAgICAgICAgIGlmIChyYXdDb2Rld29yZHMubGVuZ3RoICE9PSB2ZXJzaW9uLmdldFRvdGFsQ29kZXdvcmRzKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBGaWd1cmUgb3V0IHRoZSBudW1iZXIgYW5kIHNpemUgb2YgZGF0YSBibG9ja3MgdXNlZCBieSB0aGlzIHZlcnNpb24gYW5kXG4gICAgICAgICAgICAvLyBlcnJvciBjb3JyZWN0aW9uIGxldmVsXG4gICAgICAgICAgICBjb25zdCBlY0Jsb2NrcyA9IHZlcnNpb24uZ2V0RUNCbG9ja3NGb3JMZXZlbChlY0xldmVsKTtcbiAgICAgICAgICAgIC8vIEZpcnN0IGNvdW50IHRoZSB0b3RhbCBudW1iZXIgb2YgZGF0YSBibG9ja3NcbiAgICAgICAgICAgIGxldCB0b3RhbEJsb2NrcyA9IDA7XG4gICAgICAgICAgICBjb25zdCBlY0Jsb2NrQXJyYXkgPSBlY0Jsb2Nrcy5nZXRFQ0Jsb2NrcygpO1xuICAgICAgICAgICAgZm9yIChjb25zdCBlY0Jsb2NrIG9mIGVjQmxvY2tBcnJheSkge1xuICAgICAgICAgICAgICAgIHRvdGFsQmxvY2tzICs9IGVjQmxvY2suZ2V0Q291bnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE5vdyBlc3RhYmxpc2ggRGF0YUJsb2NrcyBvZiB0aGUgYXBwcm9wcmlhdGUgc2l6ZSBhbmQgbnVtYmVyIG9mIGRhdGEgY29kZXdvcmRzXG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgQXJyYXkodG90YWxCbG9ja3MpO1xuICAgICAgICAgICAgbGV0IG51bVJlc3VsdEJsb2NrcyA9IDA7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGVjQmxvY2sgb2YgZWNCbG9ja0FycmF5KSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBlY0Jsb2NrLmdldENvdW50KCk7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBudW1EYXRhQ29kZXdvcmRzID0gZWNCbG9jay5nZXREYXRhQ29kZXdvcmRzKCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG51bUJsb2NrQ29kZXdvcmRzID0gZWNCbG9ja3MuZ2V0RUNDb2Rld29yZHNQZXJCbG9jaygpICsgbnVtRGF0YUNvZGV3b3JkcztcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W251bVJlc3VsdEJsb2NrcysrXSA9IG5ldyBEYXRhQmxvY2skMShudW1EYXRhQ29kZXdvcmRzLCBuZXcgVWludDhBcnJheShudW1CbG9ja0NvZGV3b3JkcykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEFsbCBibG9ja3MgaGF2ZSB0aGUgc2FtZSBhbW91bnQgb2YgZGF0YSwgZXhjZXB0IHRoYXQgdGhlIGxhc3QgblxuICAgICAgICAgICAgLy8gKHdoZXJlIG4gbWF5IGJlIDApIGhhdmUgMSBtb3JlIGJ5dGUuIEZpZ3VyZSBvdXQgd2hlcmUgdGhlc2Ugc3RhcnQuXG4gICAgICAgICAgICBjb25zdCBzaG9ydGVyQmxvY2tzVG90YWxDb2Rld29yZHMgPSByZXN1bHRbMF0uY29kZXdvcmRzLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBsb25nZXJCbG9ja3NTdGFydEF0ID0gcmVzdWx0Lmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAvLyBUWVBFU0NSSVBUUE9SVDogY2hlY2sgbGVuZ3RoIGlzIGNvcnJlY3QgaGVyZVxuICAgICAgICAgICAgd2hpbGUgKGxvbmdlckJsb2Nrc1N0YXJ0QXQgPj0gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG51bUNvZGV3b3JkcyA9IHJlc3VsdFtsb25nZXJCbG9ja3NTdGFydEF0XS5jb2Rld29yZHMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGlmIChudW1Db2Rld29yZHMgPT09IHNob3J0ZXJCbG9ja3NUb3RhbENvZGV3b3Jkcykge1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbG9uZ2VyQmxvY2tzU3RhcnRBdC0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbG9uZ2VyQmxvY2tzU3RhcnRBdCsrO1xuICAgICAgICAgICAgY29uc3Qgc2hvcnRlckJsb2Nrc051bURhdGFDb2Rld29yZHMgPSBzaG9ydGVyQmxvY2tzVG90YWxDb2Rld29yZHMgLSBlY0Jsb2Nrcy5nZXRFQ0NvZGV3b3Jkc1BlckJsb2NrKCk7XG4gICAgICAgICAgICAvLyBUaGUgbGFzdCBlbGVtZW50cyBvZiByZXN1bHQgbWF5IGJlIDEgZWxlbWVudCBsb25nZXJcbiAgICAgICAgICAgIC8vIGZpcnN0IGZpbGwgb3V0IGFzIG1hbnkgZWxlbWVudHMgYXMgYWxsIG9mIHRoZW0gaGF2ZVxuICAgICAgICAgICAgbGV0IHJhd0NvZGV3b3Jkc09mZnNldCA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNob3J0ZXJCbG9ja3NOdW1EYXRhQ29kZXdvcmRzOyBpKyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IG51bVJlc3VsdEJsb2NrczsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtqXS5jb2Rld29yZHNbaV0gPSByYXdDb2Rld29yZHNbcmF3Q29kZXdvcmRzT2Zmc2V0KytdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEZpbGwgb3V0IHRoZSBsYXN0IGRhdGEgYmxvY2sgaW4gdGhlIGxvbmdlciBvbmVzXG4gICAgICAgICAgICBmb3IgKGxldCBqID0gbG9uZ2VyQmxvY2tzU3RhcnRBdDsgaiA8IG51bVJlc3VsdEJsb2NrczsgaisrKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0W2pdLmNvZGV3b3Jkc1tzaG9ydGVyQmxvY2tzTnVtRGF0YUNvZGV3b3Jkc10gPSByYXdDb2Rld29yZHNbcmF3Q29kZXdvcmRzT2Zmc2V0KytdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gTm93IGFkZCBpbiBlcnJvciBjb3JyZWN0aW9uIGJsb2Nrc1xuICAgICAgICAgICAgY29uc3QgbWF4ID0gcmVzdWx0WzBdLmNvZGV3b3Jkcy5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gc2hvcnRlckJsb2Nrc051bURhdGFDb2Rld29yZHM7IGkgPCBtYXg7IGkrKykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgbnVtUmVzdWx0QmxvY2tzOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaU9mZnNldCA9IGogPCBsb25nZXJCbG9ja3NTdGFydEF0ID8gaSA6IGkgKyAxO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRbal0uY29kZXdvcmRzW2lPZmZzZXRdID0gcmF3Q29kZXdvcmRzW3Jhd0NvZGV3b3Jkc09mZnNldCsrXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIGdldE51bURhdGFDb2Rld29yZHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5udW1EYXRhQ29kZXdvcmRzO1xuICAgICAgICB9XG4gICAgICAgIGdldENvZGV3b3JkcygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvZGV3b3JkcztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgdmFyIE1vZGVWYWx1ZXM7XG4gICAgKGZ1bmN0aW9uIChNb2RlVmFsdWVzKSB7XG4gICAgICAgIE1vZGVWYWx1ZXNbTW9kZVZhbHVlc1tcIlRFUk1JTkFUT1JcIl0gPSAwXSA9IFwiVEVSTUlOQVRPUlwiO1xuICAgICAgICBNb2RlVmFsdWVzW01vZGVWYWx1ZXNbXCJOVU1FUklDXCJdID0gMV0gPSBcIk5VTUVSSUNcIjtcbiAgICAgICAgTW9kZVZhbHVlc1tNb2RlVmFsdWVzW1wiQUxQSEFOVU1FUklDXCJdID0gMl0gPSBcIkFMUEhBTlVNRVJJQ1wiO1xuICAgICAgICBNb2RlVmFsdWVzW01vZGVWYWx1ZXNbXCJTVFJVQ1RVUkVEX0FQUEVORFwiXSA9IDNdID0gXCJTVFJVQ1RVUkVEX0FQUEVORFwiO1xuICAgICAgICBNb2RlVmFsdWVzW01vZGVWYWx1ZXNbXCJCWVRFXCJdID0gNF0gPSBcIkJZVEVcIjtcbiAgICAgICAgTW9kZVZhbHVlc1tNb2RlVmFsdWVzW1wiRUNJXCJdID0gNV0gPSBcIkVDSVwiO1xuICAgICAgICBNb2RlVmFsdWVzW01vZGVWYWx1ZXNbXCJLQU5KSVwiXSA9IDZdID0gXCJLQU5KSVwiO1xuICAgICAgICBNb2RlVmFsdWVzW01vZGVWYWx1ZXNbXCJGTkMxX0ZJUlNUX1BPU0lUSU9OXCJdID0gN10gPSBcIkZOQzFfRklSU1RfUE9TSVRJT05cIjtcbiAgICAgICAgTW9kZVZhbHVlc1tNb2RlVmFsdWVzW1wiRk5DMV9TRUNPTkRfUE9TSVRJT05cIl0gPSA4XSA9IFwiRk5DMV9TRUNPTkRfUE9TSVRJT05cIjtcbiAgICAgICAgLyoqIFNlZSBHQlQgMTgyODQtMjAwMDsgXCJIYW56aVwiIGlzIGEgdHJhbnNsaXRlcmF0aW9uIG9mIHRoaXMgbW9kZSBuYW1lLiAqL1xuICAgICAgICBNb2RlVmFsdWVzW01vZGVWYWx1ZXNbXCJIQU5aSVwiXSA9IDldID0gXCJIQU5aSVwiO1xuICAgIH0pKE1vZGVWYWx1ZXMgfHwgKE1vZGVWYWx1ZXMgPSB7fSkpO1xuICAgIC8qKlxuICAgICAqIDxwPlNlZSBJU08gMTgwMDQ6MjAwNiwgNi40LjEsIFRhYmxlcyAyIGFuZCAzLiBUaGlzIGVudW0gZW5jYXBzdWxhdGVzIHRoZSB2YXJpb3VzIG1vZGVzIGluIHdoaWNoXG4gICAgICogZGF0YSBjYW4gYmUgZW5jb2RlZCB0byBiaXRzIGluIHRoZSBRUiBjb2RlIHN0YW5kYXJkLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgTW9kZSQxIHtcbiAgICAgICAgY29uc3RydWN0b3IodmFsdWUsIHN0cmluZ1ZhbHVlLCBjaGFyYWN0ZXJDb3VudEJpdHNGb3JWZXJzaW9ucywgYml0cyAvKmludCovKSB7XG4gICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB0aGlzLnN0cmluZ1ZhbHVlID0gc3RyaW5nVmFsdWU7XG4gICAgICAgICAgICB0aGlzLmNoYXJhY3RlckNvdW50Qml0c0ZvclZlcnNpb25zID0gY2hhcmFjdGVyQ291bnRCaXRzRm9yVmVyc2lvbnM7XG4gICAgICAgICAgICB0aGlzLmJpdHMgPSBiaXRzO1xuICAgICAgICAgICAgTW9kZSQxLkZPUl9CSVRTLnNldChiaXRzLCB0aGlzKTtcbiAgICAgICAgICAgIE1vZGUkMS5GT1JfVkFMVUUuc2V0KHZhbHVlLCB0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIGJpdHMgZm91ciBiaXRzIGVuY29kaW5nIGEgUVIgQ29kZSBkYXRhIG1vZGVcbiAgICAgICAgICogQHJldHVybiBNb2RlIGVuY29kZWQgYnkgdGhlc2UgYml0c1xuICAgICAgICAgKiBAdGhyb3dzIElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbiBpZiBiaXRzIGRvIG5vdCBjb3JyZXNwb25kIHRvIGEga25vd24gbW9kZVxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGZvckJpdHMoYml0cyAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBtb2RlID0gTW9kZSQxLkZPUl9CSVRTLmdldChiaXRzKTtcbiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IG1vZGUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbW9kZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHZlcnNpb24gdmVyc2lvbiBpbiBxdWVzdGlvblxuICAgICAgICAgKiBAcmV0dXJuIG51bWJlciBvZiBiaXRzIHVzZWQsIGluIHRoaXMgUVIgQ29kZSBzeW1ib2wge0BsaW5rIFZlcnNpb259LCB0byBlbmNvZGUgdGhlXG4gICAgICAgICAqICAgICAgICAgY291bnQgb2YgY2hhcmFjdGVycyB0aGF0IHdpbGwgZm9sbG93IGVuY29kZWQgaW4gdGhpcyBNb2RlXG4gICAgICAgICAqL1xuICAgICAgICBnZXRDaGFyYWN0ZXJDb3VudEJpdHModmVyc2lvbikge1xuICAgICAgICAgICAgY29uc3QgdmVyc2lvbk51bWJlciA9IHZlcnNpb24uZ2V0VmVyc2lvbk51bWJlcigpO1xuICAgICAgICAgICAgbGV0IG9mZnNldDtcbiAgICAgICAgICAgIGlmICh2ZXJzaW9uTnVtYmVyIDw9IDkpIHtcbiAgICAgICAgICAgICAgICBvZmZzZXQgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodmVyc2lvbk51bWJlciA8PSAyNikge1xuICAgICAgICAgICAgICAgIG9mZnNldCA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBvZmZzZXQgPSAyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2hhcmFjdGVyQ291bnRCaXRzRm9yVmVyc2lvbnNbb2Zmc2V0XTtcbiAgICAgICAgfVxuICAgICAgICBnZXRWYWx1ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGdldEJpdHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5iaXRzO1xuICAgICAgICB9XG4gICAgICAgIGVxdWFscyhvKSB7XG4gICAgICAgICAgICBpZiAoIShvIGluc3RhbmNlb2YgTW9kZSQxKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG90aGVyID0gbztcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlID09PSBvdGhlci52YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICB0b1N0cmluZygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0cmluZ1ZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIE1vZGUkMS5GT1JfQklUUyA9IG5ldyBNYXAoKTtcbiAgICBNb2RlJDEuRk9SX1ZBTFVFID0gbmV3IE1hcCgpO1xuICAgIE1vZGUkMS5URVJNSU5BVE9SID0gbmV3IE1vZGUkMShNb2RlVmFsdWVzLlRFUk1JTkFUT1IsICdURVJNSU5BVE9SJywgSW50MzJBcnJheS5mcm9tKFswLCAwLCAwXSksIDB4MDApOyAvLyBOb3QgcmVhbGx5IGEgbW9kZS4uLlxuICAgIE1vZGUkMS5OVU1FUklDID0gbmV3IE1vZGUkMShNb2RlVmFsdWVzLk5VTUVSSUMsICdOVU1FUklDJywgSW50MzJBcnJheS5mcm9tKFsxMCwgMTIsIDE0XSksIDB4MDEpO1xuICAgIE1vZGUkMS5BTFBIQU5VTUVSSUMgPSBuZXcgTW9kZSQxKE1vZGVWYWx1ZXMuQUxQSEFOVU1FUklDLCAnQUxQSEFOVU1FUklDJywgSW50MzJBcnJheS5mcm9tKFs5LCAxMSwgMTNdKSwgMHgwMik7XG4gICAgTW9kZSQxLlNUUlVDVFVSRURfQVBQRU5EID0gbmV3IE1vZGUkMShNb2RlVmFsdWVzLlNUUlVDVFVSRURfQVBQRU5ELCAnU1RSVUNUVVJFRF9BUFBFTkQnLCBJbnQzMkFycmF5LmZyb20oWzAsIDAsIDBdKSwgMHgwMyk7IC8vIE5vdCBzdXBwb3J0ZWRcbiAgICBNb2RlJDEuQllURSA9IG5ldyBNb2RlJDEoTW9kZVZhbHVlcy5CWVRFLCAnQllURScsIEludDMyQXJyYXkuZnJvbShbOCwgMTYsIDE2XSksIDB4MDQpO1xuICAgIE1vZGUkMS5FQ0kgPSBuZXcgTW9kZSQxKE1vZGVWYWx1ZXMuRUNJLCAnRUNJJywgSW50MzJBcnJheS5mcm9tKFswLCAwLCAwXSksIDB4MDcpOyAvLyBjaGFyYWN0ZXIgY291bnRzIGRvbid0IGFwcGx5XG4gICAgTW9kZSQxLktBTkpJID0gbmV3IE1vZGUkMShNb2RlVmFsdWVzLktBTkpJLCAnS0FOSkknLCBJbnQzMkFycmF5LmZyb20oWzgsIDEwLCAxMl0pLCAweDA4KTtcbiAgICBNb2RlJDEuRk5DMV9GSVJTVF9QT1NJVElPTiA9IG5ldyBNb2RlJDEoTW9kZVZhbHVlcy5GTkMxX0ZJUlNUX1BPU0lUSU9OLCAnRk5DMV9GSVJTVF9QT1NJVElPTicsIEludDMyQXJyYXkuZnJvbShbMCwgMCwgMF0pLCAweDA1KTtcbiAgICBNb2RlJDEuRk5DMV9TRUNPTkRfUE9TSVRJT04gPSBuZXcgTW9kZSQxKE1vZGVWYWx1ZXMuRk5DMV9TRUNPTkRfUE9TSVRJT04sICdGTkMxX1NFQ09ORF9QT1NJVElPTicsIEludDMyQXJyYXkuZnJvbShbMCwgMCwgMF0pLCAweDA5KTtcbiAgICAvKiogU2VlIEdCVCAxODI4NC0yMDAwOyBcIkhhbnppXCIgaXMgYSB0cmFuc2xpdGVyYXRpb24gb2YgdGhpcyBtb2RlIG5hbWUuICovXG4gICAgTW9kZSQxLkhBTlpJID0gbmV3IE1vZGUkMShNb2RlVmFsdWVzLkhBTlpJLCAnSEFOWkknLCBJbnQzMkFycmF5LmZyb20oWzgsIDEwLCAxMl0pLCAweDBEKTtcblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyppbXBvcnQgamF2YS5pby5VbnN1cHBvcnRlZEVuY29kaW5nRXhjZXB0aW9uOyovXG4gICAgLyppbXBvcnQgamF2YS51dGlsLkFycmF5TGlzdDsqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5Db2xsZWN0aW9uOyovXG4gICAgLyppbXBvcnQgamF2YS51dGlsLkxpc3Q7Ki9cbiAgICAvKmltcG9ydCBqYXZhLnV0aWwuTWFwOyovXG4gICAgLyoqXG4gICAgICogPHA+UVIgQ29kZXMgY2FuIGVuY29kZSB0ZXh0IGFzIGJpdHMgaW4gb25lIG9mIHNldmVyYWwgbW9kZXMsIGFuZCBjYW4gdXNlIG11bHRpcGxlIG1vZGVzXG4gICAgICogaW4gb25lIFFSIENvZGUuIFRoaXMgY2xhc3MgZGVjb2RlcyB0aGUgYml0cyBiYWNrIGludG8gdGV4dC48L3A+XG4gICAgICpcbiAgICAgKiA8cD5TZWUgSVNPIDE4MDA0OjIwMDYsIDYuNC4zIC0gNi40Ljc8L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMSB7XG4gICAgICAgIHN0YXRpYyBkZWNvZGUoYnl0ZXMsIHZlcnNpb24sIGVjTGV2ZWwsIGhpbnRzKSB7XG4gICAgICAgICAgICBjb25zdCBiaXRzID0gbmV3IEJpdFNvdXJjZShieXRlcyk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gbmV3IFN0cmluZ0J1aWxkZXIoKTtcbiAgICAgICAgICAgIGNvbnN0IGJ5dGVTZWdtZW50cyA9IG5ldyBBcnJheSgpOyAvLyAxXG4gICAgICAgICAgICAvLyBUWVBFU0NSSVBUUE9SVDogSSBkbyBub3QgdXNlIGNvbnN0cnVjdG9yIHdpdGggc2l6ZSAxIGFzIGluIG9yaWdpbmFsIEphdmEgbWVhbnMgY2FwYWNpdHkgYW5kIHRoZSBhcnJheSBsZW5ndGggaXMgY2hlY2tlZCBiZWxvd1xuICAgICAgICAgICAgbGV0IHN5bWJvbFNlcXVlbmNlID0gLTE7XG4gICAgICAgICAgICBsZXQgcGFyaXR5RGF0YSA9IC0xO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBsZXQgY3VycmVudENoYXJhY3RlclNldEVDSSA9IG51bGw7XG4gICAgICAgICAgICAgICAgbGV0IGZjMUluRWZmZWN0ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgbGV0IG1vZGU7XG4gICAgICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgICAgICAvLyBXaGlsZSBzdGlsbCBhbm90aGVyIHNlZ21lbnQgdG8gcmVhZC4uLlxuICAgICAgICAgICAgICAgICAgICBpZiAoYml0cy5hdmFpbGFibGUoKSA8IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9LLCBhc3N1bWUgd2UncmUgZG9uZS4gUmVhbGx5LCBhIFRFUk1JTkFUT1IgbW9kZSBzaG91bGQgaGF2ZSBiZWVuIHJlY29yZGVkIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vZGUgPSBNb2RlJDEuVEVSTUlOQVRPUjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1vZGVCaXRzID0gYml0cy5yZWFkQml0cyg0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vZGUgPSBNb2RlJDEuZm9yQml0cyhtb2RlQml0cyk7IC8vIG1vZGUgaXMgZW5jb2RlZCBieSA0IGJpdHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKG1vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgTW9kZSQxLlRFUk1JTkFUT1I6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIE1vZGUkMS5GTkMxX0ZJUlNUX1BPU0lUSU9OOlxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBNb2RlJDEuRk5DMV9TRUNPTkRfUE9TSVRJT046XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgZG8gbGl0dGxlIHdpdGggRk5DMSBleGNlcHQgYWx0ZXIgdGhlIHBhcnNlZCByZXN1bHQgYSBiaXQgYWNjb3JkaW5nIHRvIHRoZSBzcGVjXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmMxSW5FZmZlY3QgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBNb2RlJDEuU1RSVUNUVVJFRF9BUFBFTkQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJpdHMuYXZhaWxhYmxlKCkgPCAxNikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNlcXVlbmNlIG51bWJlciBhbmQgcGFyaXR5IGlzIGFkZGVkIGxhdGVyIHRvIHRoZSByZXN1bHQgbWV0YWRhdGFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZWFkIG5leHQgOCBiaXRzIChzeW1ib2wgc2VxdWVuY2UgIykgYW5kIDggYml0cyAoZGF0YTogcGFyaXR5KSwgdGhlbiBjb250aW51ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN5bWJvbFNlcXVlbmNlID0gYml0cy5yZWFkQml0cyg4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJpdHlEYXRhID0gYml0cy5yZWFkQml0cyg4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgTW9kZSQxLkVDSTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDb3VudCBkb2Vzbid0IGFwcGx5IHRvIEVDSVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQxLnBhcnNlRUNJVmFsdWUoYml0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudENoYXJhY3RlclNldEVDSSA9IENoYXJhY3RlclNldEVDSS5nZXRDaGFyYWN0ZXJTZXRFQ0lCeVZhbHVlKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudENoYXJhY3RlclNldEVDSSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBNb2RlJDEuSEFOWkk6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRmlyc3QgaGFuZGxlIEhhbnppIG1vZGUgd2hpY2ggZG9lcyBub3Qgc3RhcnQgd2l0aCBjaGFyYWN0ZXIgY291bnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDaGluZXNlIG1vZGUgY29udGFpbnMgYSBzdWIgc2V0IGluZGljYXRvciByaWdodCBhZnRlciBtb2RlIGluZGljYXRvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN1YnNldCA9IGJpdHMucmVhZEJpdHMoNCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY291bnRIYW56aSA9IGJpdHMucmVhZEJpdHMobW9kZS5nZXRDaGFyYWN0ZXJDb3VudEJpdHModmVyc2lvbikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdWJzZXQgPT09IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS5HQjIzMTJfU1VCU0VUKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS5kZWNvZGVIYW56aVNlZ21lbnQoYml0cywgcmVzdWx0LCBjb3VudEhhbnppKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFwiTm9ybWFsXCIgUVIgY29kZSBtb2RlczpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIb3cgbWFueSBjaGFyYWN0ZXJzIHdpbGwgZm9sbG93LCBlbmNvZGVkIGluIHRoaXMgbW9kZT9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb3VudCA9IGJpdHMucmVhZEJpdHMobW9kZS5nZXRDaGFyYWN0ZXJDb3VudEJpdHModmVyc2lvbikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAobW9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIE1vZGUkMS5OVU1FUklDOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQxLmRlY29kZU51bWVyaWNTZWdtZW50KGJpdHMsIHJlc3VsdCwgY291bnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgTW9kZSQxLkFMUEhBTlVNRVJJQzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS5kZWNvZGVBbHBoYW51bWVyaWNTZWdtZW50KGJpdHMsIHJlc3VsdCwgY291bnQsIGZjMUluRWZmZWN0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIE1vZGUkMS5CWVRFOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQxLmRlY29kZUJ5dGVTZWdtZW50KGJpdHMsIHJlc3VsdCwgY291bnQsIGN1cnJlbnRDaGFyYWN0ZXJTZXRFQ0ksIGJ5dGVTZWdtZW50cywgaGludHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgTW9kZSQxLktBTkpJOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQxLmRlY29kZUthbmppU2VnbWVudChiaXRzLCByZXN1bHQsIGNvdW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gd2hpbGUgKG1vZGUgIT09IE1vZGUkMS5URVJNSU5BVE9SKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChpYWUgLyo6IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbiovKSB7XG4gICAgICAgICAgICAgICAgLy8gZnJvbSByZWFkQml0cygpIGNhbGxzXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBEZWNvZGVyUmVzdWx0KGJ5dGVzLCByZXN1bHQudG9TdHJpbmcoKSwgYnl0ZVNlZ21lbnRzLmxlbmd0aCA9PT0gMCA/IG51bGwgOiBieXRlU2VnbWVudHMsIGVjTGV2ZWwgPT09IG51bGwgPyBudWxsIDogZWNMZXZlbC50b1N0cmluZygpLCBzeW1ib2xTZXF1ZW5jZSwgcGFyaXR5RGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNlZSBzcGVjaWZpY2F0aW9uIEdCVCAxODI4NC0yMDAwXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGVjb2RlSGFuemlTZWdtZW50KGJpdHMsIHJlc3VsdCwgY291bnQgLyppbnQqLykge1xuICAgICAgICAgICAgLy8gRG9uJ3QgY3Jhc2ggdHJ5aW5nIHRvIHJlYWQgbW9yZSBiaXRzIHRoYW4gd2UgaGF2ZSBhdmFpbGFibGUuXG4gICAgICAgICAgICBpZiAoY291bnQgKiAxMyA+IGJpdHMuYXZhaWxhYmxlKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBFYWNoIGNoYXJhY3RlciB3aWxsIHJlcXVpcmUgMiBieXRlcy4gUmVhZCB0aGUgY2hhcmFjdGVycyBhcyAyLWJ5dGUgcGFpcnNcbiAgICAgICAgICAgIC8vIGFuZCBkZWNvZGUgYXMgR0IyMzEyIGFmdGVyd2FyZHNcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBVaW50OEFycmF5KDIgKiBjb3VudCk7XG4gICAgICAgICAgICBsZXQgb2Zmc2V0ID0gMDtcbiAgICAgICAgICAgIHdoaWxlIChjb3VudCA+IDApIHtcbiAgICAgICAgICAgICAgICAvLyBFYWNoIDEzIGJpdHMgZW5jb2RlcyBhIDItYnl0ZSBjaGFyYWN0ZXJcbiAgICAgICAgICAgICAgICBjb25zdCB0d29CeXRlcyA9IGJpdHMucmVhZEJpdHMoMTMpO1xuICAgICAgICAgICAgICAgIGxldCBhc3NlbWJsZWRUd29CeXRlcyA9ICgoKHR3b0J5dGVzIC8gMHgwNjApIDw8IDgpICYgMHhGRkZGRkZGRikgfCAodHdvQnl0ZXMgJSAweDA2MCk7XG4gICAgICAgICAgICAgICAgaWYgKGFzc2VtYmxlZFR3b0J5dGVzIDwgMHgwMDNCRikge1xuICAgICAgICAgICAgICAgICAgICAvLyBJbiB0aGUgMHhBMUExIHRvIDB4QUFGRSByYW5nZVxuICAgICAgICAgICAgICAgICAgICBhc3NlbWJsZWRUd29CeXRlcyArPSAweDBBMUExO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSW4gdGhlIDB4QjBBMSB0byAweEZBRkUgcmFuZ2VcbiAgICAgICAgICAgICAgICAgICAgYXNzZW1ibGVkVHdvQnl0ZXMgKz0gMHgwQTZBMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnVmZmVyW29mZnNldF0gPSAvKihieXRlKSAqLyAoKGFzc2VtYmxlZFR3b0J5dGVzID4+IDgpICYgMHhGRik7XG4gICAgICAgICAgICAgICAgYnVmZmVyW29mZnNldCArIDFdID0gLyooYnl0ZSkgKi8gKGFzc2VtYmxlZFR3b0J5dGVzICYgMHhGRik7XG4gICAgICAgICAgICAgICAgb2Zmc2V0ICs9IDI7XG4gICAgICAgICAgICAgICAgY291bnQtLTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChTdHJpbmdFbmNvZGluZy5kZWNvZGUoYnVmZmVyLCBTdHJpbmdVdGlscy5HQjIzMTIpKTtcbiAgICAgICAgICAgICAgICAvLyBUWVBFU0NSSVBUUE9SVDogVE9ETzogaW1wbGVtZW50IEdCMjMxMiBkZWNvZGUuIFN0cmluZ1ZpZXcgZnJvbSBNRE4gY291bGQgYmUgYSBzdGFydGluZyBwb2ludFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGlnbm9yZWQgLyo6IFVuc3VwcG9ydGVkRW5jb2RpbmdFeGNlcHRpb24qLykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oaWdub3JlZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGRlY29kZUthbmppU2VnbWVudChiaXRzLCByZXN1bHQsIGNvdW50IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIC8vIERvbid0IGNyYXNoIHRyeWluZyB0byByZWFkIG1vcmUgYml0cyB0aGFuIHdlIGhhdmUgYXZhaWxhYmxlLlxuICAgICAgICAgICAgaWYgKGNvdW50ICogMTMgPiBiaXRzLmF2YWlsYWJsZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRWFjaCBjaGFyYWN0ZXIgd2lsbCByZXF1aXJlIDIgYnl0ZXMuIFJlYWQgdGhlIGNoYXJhY3RlcnMgYXMgMi1ieXRlIHBhaXJzXG4gICAgICAgICAgICAvLyBhbmQgZGVjb2RlIGFzIFNoaWZ0X0pJUyBhZnRlcndhcmRzXG4gICAgICAgICAgICBjb25zdCBidWZmZXIgPSBuZXcgVWludDhBcnJheSgyICogY291bnQpO1xuICAgICAgICAgICAgbGV0IG9mZnNldCA9IDA7XG4gICAgICAgICAgICB3aGlsZSAoY291bnQgPiAwKSB7XG4gICAgICAgICAgICAgICAgLy8gRWFjaCAxMyBiaXRzIGVuY29kZXMgYSAyLWJ5dGUgY2hhcmFjdGVyXG4gICAgICAgICAgICAgICAgY29uc3QgdHdvQnl0ZXMgPSBiaXRzLnJlYWRCaXRzKDEzKTtcbiAgICAgICAgICAgICAgICBsZXQgYXNzZW1ibGVkVHdvQnl0ZXMgPSAoKCh0d29CeXRlcyAvIDB4MEMwKSA8PCA4KSAmIDB4RkZGRkZGRkYpIHwgKHR3b0J5dGVzICUgMHgwQzApO1xuICAgICAgICAgICAgICAgIGlmIChhc3NlbWJsZWRUd29CeXRlcyA8IDB4MDFGMDApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSW4gdGhlIDB4ODE0MCB0byAweDlGRkMgcmFuZ2VcbiAgICAgICAgICAgICAgICAgICAgYXNzZW1ibGVkVHdvQnl0ZXMgKz0gMHgwODE0MDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEluIHRoZSAweEUwNDAgdG8gMHhFQkJGIHJhbmdlXG4gICAgICAgICAgICAgICAgICAgIGFzc2VtYmxlZFR3b0J5dGVzICs9IDB4MEMxNDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJ1ZmZlcltvZmZzZXRdID0gLyooYnl0ZSkgKi8gKGFzc2VtYmxlZFR3b0J5dGVzID4+IDgpO1xuICAgICAgICAgICAgICAgIGJ1ZmZlcltvZmZzZXQgKyAxXSA9IC8qKGJ5dGUpICovIGFzc2VtYmxlZFR3b0J5dGVzO1xuICAgICAgICAgICAgICAgIG9mZnNldCArPSAyO1xuICAgICAgICAgICAgICAgIGNvdW50LS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBTaGlmdF9KSVMgbWF5IG5vdCBiZSBzdXBwb3J0ZWQgaW4gc29tZSBlbnZpcm9ubWVudHM6XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoU3RyaW5nRW5jb2RpbmcuZGVjb2RlKGJ1ZmZlciwgU3RyaW5nVXRpbHMuU0hJRlRfSklTKSk7XG4gICAgICAgICAgICAgICAgLy8gVFlQRVNDUklQVFBPUlQ6IFRPRE86IGltcGxlbWVudCBTSElGVF9KSVMgZGVjb2RlLiBTdHJpbmdWaWV3IGZyb20gTUROIGNvdWxkIGJlIGEgc3RhcnRpbmcgcG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChpZ25vcmVkIC8qOiBVbnN1cHBvcnRlZEVuY29kaW5nRXhjZXB0aW9uKi8pIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKGlnbm9yZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBkZWNvZGVCeXRlU2VnbWVudChiaXRzLCByZXN1bHQsIGNvdW50IC8qaW50Ki8sIGN1cnJlbnRDaGFyYWN0ZXJTZXRFQ0ksIGJ5dGVTZWdtZW50cywgaGludHMpIHtcbiAgICAgICAgICAgIC8vIERvbid0IGNyYXNoIHRyeWluZyB0byByZWFkIG1vcmUgYml0cyB0aGFuIHdlIGhhdmUgYXZhaWxhYmxlLlxuICAgICAgICAgICAgaWYgKDggKiBjb3VudCA+IGJpdHMuYXZhaWxhYmxlKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZWFkQnl0ZXMgPSBuZXcgVWludDhBcnJheShjb3VudCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICByZWFkQnl0ZXNbaV0gPSAvKihieXRlKSAqLyBiaXRzLnJlYWRCaXRzKDgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGVuY29kaW5nO1xuICAgICAgICAgICAgaWYgKGN1cnJlbnRDaGFyYWN0ZXJTZXRFQ0kgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGUgc3BlYyBpc24ndCBjbGVhciBvbiB0aGlzIG1vZGU7IHNlZVxuICAgICAgICAgICAgICAgIC8vIHNlY3Rpb24gNi40LjU6IHQgZG9lcyBub3Qgc2F5IHdoaWNoIGVuY29kaW5nIHRvIGFzc3VtaW5nXG4gICAgICAgICAgICAgICAgLy8gdXBvbiBkZWNvZGluZy4gSSBoYXZlIHNlZW4gSVNPLTg4NTktMSB1c2VkIGFzIHdlbGwgYXNcbiAgICAgICAgICAgICAgICAvLyBTaGlmdF9KSVMgLS0gd2l0aG91dCBhbnl0aGluZyBsaWtlIGFuIEVDSSBkZXNpZ25hdG9yIHRvXG4gICAgICAgICAgICAgICAgLy8gZ2l2ZSBhIGhpbnQuXG4gICAgICAgICAgICAgICAgZW5jb2RpbmcgPSBTdHJpbmdVdGlscy5ndWVzc0VuY29kaW5nKHJlYWRCeXRlcywgaGludHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZW5jb2RpbmcgPSBjdXJyZW50Q2hhcmFjdGVyU2V0RUNJLmdldE5hbWUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChTdHJpbmdFbmNvZGluZy5kZWNvZGUocmVhZEJ5dGVzLCBlbmNvZGluZykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGlnbm9yZWQgLyo6IFVuc3VwcG9ydGVkRW5jb2RpbmdFeGNlcHRpb24qLykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oaWdub3JlZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBieXRlU2VnbWVudHMucHVzaChyZWFkQnl0ZXMpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyB0b0FscGhhTnVtZXJpY0NoYXIodmFsdWUgLyppbnQqLykge1xuICAgICAgICAgICAgaWYgKHZhbHVlID49IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS5BTFBIQU5VTUVSSUNfQ0hBUlMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS5BTFBIQU5VTUVSSUNfQ0hBUlNbdmFsdWVdO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBkZWNvZGVBbHBoYW51bWVyaWNTZWdtZW50KGJpdHMsIHJlc3VsdCwgY291bnQgLyppbnQqLywgZmMxSW5FZmZlY3QpIHtcbiAgICAgICAgICAgIC8vIFJlYWQgdHdvIGNoYXJhY3RlcnMgYXQgYSB0aW1lXG4gICAgICAgICAgICBjb25zdCBzdGFydCA9IHJlc3VsdC5sZW5ndGgoKTtcbiAgICAgICAgICAgIHdoaWxlIChjb3VudCA+IDEpIHtcbiAgICAgICAgICAgICAgICBpZiAoYml0cy5hdmFpbGFibGUoKSA8IDExKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgbmV4dFR3b0NoYXJzQml0cyA9IGJpdHMucmVhZEJpdHMoMTEpO1xuICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQxLnRvQWxwaGFOdW1lcmljQ2hhcihNYXRoLmZsb29yKG5leHRUd29DaGFyc0JpdHMgLyA0NSkpKTtcbiAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS50b0FscGhhTnVtZXJpY0NoYXIobmV4dFR3b0NoYXJzQml0cyAlIDQ1KSk7XG4gICAgICAgICAgICAgICAgY291bnQgLT0gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjb3VudCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIC8vIHNwZWNpYWwgY2FzZTogb25lIGNoYXJhY3RlciBsZWZ0XG4gICAgICAgICAgICAgICAgaWYgKGJpdHMuYXZhaWxhYmxlKCkgPCA2KSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDEudG9BbHBoYU51bWVyaWNDaGFyKGJpdHMucmVhZEJpdHMoNikpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFNlZSBzZWN0aW9uIDYuNC44LjEsIDYuNC44LjJcbiAgICAgICAgICAgIGlmIChmYzFJbkVmZmVjdCkge1xuICAgICAgICAgICAgICAgIC8vIFdlIG5lZWQgdG8gbWFzc2FnZSB0aGUgcmVzdWx0IGEgYml0IGlmIGluIGFuIEZOQzEgbW9kZTpcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCByZXN1bHQubGVuZ3RoKCk7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0LmNoYXJBdChpKSA9PT0gJyUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaSA8IHJlc3VsdC5sZW5ndGgoKSAtIDEgJiYgcmVzdWx0LmNoYXJBdChpICsgMSkgPT09ICclJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vICUlIGlzIHJlbmRlcmVkIGFzICVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuZGVsZXRlQ2hhckF0KGkgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluIGFscGhhIG1vZGUsICUgc2hvdWxkIGJlIGNvbnZlcnRlZCB0byBGTkMxIHNlcGFyYXRvciAweDFEXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnNldENoYXJBdChpLCBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4MUQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZGVjb2RlTnVtZXJpY1NlZ21lbnQoYml0cywgcmVzdWx0LCBjb3VudCAvKmludCovKSB7XG4gICAgICAgICAgICAvLyBSZWFkIHRocmVlIGRpZ2l0cyBhdCBhIHRpbWVcbiAgICAgICAgICAgIHdoaWxlIChjb3VudCA+PSAzKSB7XG4gICAgICAgICAgICAgICAgLy8gRWFjaCAxMCBiaXRzIGVuY29kZXMgdGhyZWUgZGlnaXRzXG4gICAgICAgICAgICAgICAgaWYgKGJpdHMuYXZhaWxhYmxlKCkgPCAxMCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IHRocmVlRGlnaXRzQml0cyA9IGJpdHMucmVhZEJpdHMoMTApO1xuICAgICAgICAgICAgICAgIGlmICh0aHJlZURpZ2l0c0JpdHMgPj0gMTAwMCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQxLnRvQWxwaGFOdW1lcmljQ2hhcihNYXRoLmZsb29yKHRocmVlRGlnaXRzQml0cyAvIDEwMCkpKTtcbiAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS50b0FscGhhTnVtZXJpY0NoYXIoTWF0aC5mbG9vcih0aHJlZURpZ2l0c0JpdHMgLyAxMCkgJSAxMCkpO1xuICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQxLnRvQWxwaGFOdW1lcmljQ2hhcih0aHJlZURpZ2l0c0JpdHMgJSAxMCkpO1xuICAgICAgICAgICAgICAgIGNvdW50IC09IDM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY291bnQgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAvLyBUd28gZGlnaXRzIGxlZnQgb3ZlciB0byByZWFkLCBlbmNvZGVkIGluIDcgYml0c1xuICAgICAgICAgICAgICAgIGlmIChiaXRzLmF2YWlsYWJsZSgpIDwgNykge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IHR3b0RpZ2l0c0JpdHMgPSBiaXRzLnJlYWRCaXRzKDcpO1xuICAgICAgICAgICAgICAgIGlmICh0d29EaWdpdHNCaXRzID49IDEwMCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQxLnRvQWxwaGFOdW1lcmljQ2hhcihNYXRoLmZsb29yKHR3b0RpZ2l0c0JpdHMgLyAxMCkpKTtcbiAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS50b0FscGhhTnVtZXJpY0NoYXIodHdvRGlnaXRzQml0cyAlIDEwKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjb3VudCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIC8vIE9uZSBkaWdpdCBsZWZ0IG92ZXIgdG8gcmVhZFxuICAgICAgICAgICAgICAgIGlmIChiaXRzLmF2YWlsYWJsZSgpIDwgNCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGRpZ2l0Qml0cyA9IGJpdHMucmVhZEJpdHMoNCk7XG4gICAgICAgICAgICAgICAgaWYgKGRpZ2l0Qml0cyA+PSAxMCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQxLnRvQWxwaGFOdW1lcmljQ2hhcihkaWdpdEJpdHMpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgcGFyc2VFQ0lWYWx1ZShiaXRzKSB7XG4gICAgICAgICAgICBjb25zdCBmaXJzdEJ5dGUgPSBiaXRzLnJlYWRCaXRzKDgpO1xuICAgICAgICAgICAgaWYgKChmaXJzdEJ5dGUgJiAweDgwKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIC8vIGp1c3Qgb25lIGJ5dGVcbiAgICAgICAgICAgICAgICByZXR1cm4gZmlyc3RCeXRlICYgMHg3RjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgoZmlyc3RCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgICAgICAvLyB0d28gYnl0ZXNcbiAgICAgICAgICAgICAgICBjb25zdCBzZWNvbmRCeXRlID0gYml0cy5yZWFkQml0cyg4KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gKCgoZmlyc3RCeXRlICYgMHgzRikgPDwgOCkgJiAweEZGRkZGRkZGKSB8IHNlY29uZEJ5dGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoKGZpcnN0Qnl0ZSAmIDB4RTApID09PSAweEMwKSB7XG4gICAgICAgICAgICAgICAgLy8gdGhyZWUgYnl0ZXNcbiAgICAgICAgICAgICAgICBjb25zdCBzZWNvbmRUaGlyZEJ5dGVzID0gYml0cy5yZWFkQml0cygxNik7XG4gICAgICAgICAgICAgICAgcmV0dXJuICgoKGZpcnN0Qnl0ZSAmIDB4MUYpIDw8IDE2KSAmIDB4RkZGRkZGRkYpIHwgc2Vjb25kVGhpcmRCeXRlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZWUgSVNPIDE4MDA0OjIwMDYsIDYuNC40IFRhYmxlIDVcbiAgICAgKi9cbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDEuQUxQSEFOVU1FUklDX0NIQVJTID0gJzAxMjM0NTY3ODlBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWiAkJSorLS4vOic7XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQxLkdCMjMxMl9TVUJTRVQgPSAxO1xuICAgIC8vIGZ1bmN0aW9uIFVpbnQ4QXJyYXlUb1N0cmluZyhhOiBVaW50OEFycmF5KTogc3RyaW5nIHtcbiAgICAvLyAgICAgY29uc3QgQ0hVTktfU1ogPSAweDgwMDA7XG4gICAgLy8gICAgIGNvbnN0IGMgPSBuZXcgU3RyaW5nQnVpbGRlcigpO1xuICAgIC8vICAgICBmb3IgKGxldCBpID0gMCwgbGVuZ3RoID0gYS5sZW5ndGg7IGkgPCBsZW5ndGg7IGkgKz0gQ0hVTktfU1opIHtcbiAgICAvLyAgICAgICAgIGMuYXBwZW5kKFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgYS5zdWJhcnJheShpLCBpICsgQ0hVTktfU1opKSk7XG4gICAgLy8gICAgIH1cbiAgICAvLyAgICAgcmV0dXJuIGMudG9TdHJpbmcoKTtcbiAgICAvLyB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDEzIFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIE1ldGEtZGF0YSBjb250YWluZXIgZm9yIFFSIENvZGUgZGVjb2RpbmcuIEluc3RhbmNlcyBvZiB0aGlzIGNsYXNzIG1heSBiZSB1c2VkIHRvIGNvbnZleSBpbmZvcm1hdGlvbiBiYWNrIHRvIHRoZVxuICAgICAqIGRlY29kaW5nIGNhbGxlci4gQ2FsbGVycyBhcmUgZXhwZWN0ZWQgdG8gcHJvY2VzcyB0aGlzLlxuICAgICAqXG4gICAgICogQHNlZSBjb20uZ29vZ2xlLnp4aW5nLmNvbW1vbi5EZWNvZGVyUmVzdWx0I2dldE90aGVyKClcbiAgICAgKi9cbiAgICBjbGFzcyBRUkNvZGVEZWNvZGVyTWV0YURhdGEge1xuICAgICAgICBjb25zdHJ1Y3RvcihtaXJyb3JlZCkge1xuICAgICAgICAgICAgdGhpcy5taXJyb3JlZCA9IG1pcnJvcmVkO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHRydWUgaWYgdGhlIFFSIENvZGUgd2FzIG1pcnJvcmVkLlxuICAgICAgICAgKi9cbiAgICAgICAgaXNNaXJyb3JlZCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1pcnJvcmVkO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBcHBseSB0aGUgcmVzdWx0IHBvaW50cycgb3JkZXIgY29ycmVjdGlvbiBkdWUgdG8gbWlycm9yaW5nLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gcG9pbnRzIEFycmF5IG9mIHBvaW50cyB0byBhcHBseSBtaXJyb3IgY29ycmVjdGlvbiB0by5cbiAgICAgICAgICovXG4gICAgICAgIGFwcGx5TWlycm9yZWRDb3JyZWN0aW9uKHBvaW50cykge1xuICAgICAgICAgICAgaWYgKCF0aGlzLm1pcnJvcmVkIHx8IHBvaW50cyA9PT0gbnVsbCB8fCBwb2ludHMubGVuZ3RoIDwgMykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGJvdHRvbUxlZnQgPSBwb2ludHNbMF07XG4gICAgICAgICAgICBwb2ludHNbMF0gPSBwb2ludHNbMl07XG4gICAgICAgICAgICBwb2ludHNbMl0gPSBib3R0b21MZWZ0O1xuICAgICAgICAgICAgLy8gTm8gbmVlZCB0byAnZml4JyB0b3AtbGVmdCBhbmQgYWxpZ25tZW50IHBhdHRlcm4uXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5NYXA7Ki9cbiAgICAvKipcbiAgICAgKiA8cD5UaGUgbWFpbiBjbGFzcyB3aGljaCBpbXBsZW1lbnRzIFFSIENvZGUgZGVjb2RpbmcgLS0gYXMgb3Bwb3NlZCB0byBsb2NhdGluZyBhbmQgZXh0cmFjdGluZ1xuICAgICAqIHRoZSBRUiBDb2RlIGZyb20gYW4gaW1hZ2UuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBEZWNvZGVyJDIge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICAgIHRoaXMucnNEZWNvZGVyID0gbmV3IFJlZWRTb2xvbW9uRGVjb2RlcihHZW5lcmljR0YuUVJfQ09ERV9GSUVMRF8yNTYpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHB1YmxpYyBkZWNvZGUoaW1hZ2U6IGJvb2xlYW5bXVtdKTogRGVjb2RlclJlc3VsdCAvKnRocm93cyBDaGVja3N1bUV4Y2VwdGlvbiwgRm9ybWF0RXhjZXB0aW9uKi8ge1xuICAgICAgICAvLyAgIHJldHVybiBkZWNvZGUoaW1hZ2UsIG51bGwpXG4gICAgICAgIC8vIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkNvbnZlbmllbmNlIG1ldGhvZCB0aGF0IGNhbiBkZWNvZGUgYSBRUiBDb2RlIHJlcHJlc2VudGVkIGFzIGEgMkQgYXJyYXkgb2YgYm9vbGVhbnMuXG4gICAgICAgICAqIFwidHJ1ZVwiIGlzIHRha2VuIHRvIG1lYW4gYSBibGFjayBtb2R1bGUuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gaW1hZ2UgYm9vbGVhbnMgcmVwcmVzZW50aW5nIHdoaXRlL2JsYWNrIFFSIENvZGUgbW9kdWxlc1xuICAgICAgICAgKiBAcGFyYW0gaGludHMgZGVjb2RpbmcgaGludHMgdGhhdCBzaG91bGQgYmUgdXNlZCB0byBpbmZsdWVuY2UgZGVjb2RpbmdcbiAgICAgICAgICogQHJldHVybiB0ZXh0IGFuZCBieXRlcyBlbmNvZGVkIHdpdGhpbiB0aGUgUVIgQ29kZVxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvbiBpZiB0aGUgUVIgQ29kZSBjYW5ub3QgYmUgZGVjb2RlZFxuICAgICAgICAgKiBAdGhyb3dzIENoZWNrc3VtRXhjZXB0aW9uIGlmIGVycm9yIGNvcnJlY3Rpb24gZmFpbHNcbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZUJvb2xlYW5BcnJheShpbWFnZSwgaGludHMpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZUJpdE1hdHJpeChCaXRNYXRyaXgucGFyc2VGcm9tQm9vbGVhbkFycmF5KGltYWdlKSwgaGludHMpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHB1YmxpYyBkZWNvZGVCaXRNYXRyaXgoYml0czogQml0TWF0cml4KTogRGVjb2RlclJlc3VsdCAvKnRocm93cyBDaGVja3N1bUV4Y2VwdGlvbiwgRm9ybWF0RXhjZXB0aW9uKi8ge1xuICAgICAgICAvLyAgIHJldHVybiBkZWNvZGUoYml0cywgbnVsbClcbiAgICAgICAgLy8gfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+RGVjb2RlcyBhIFFSIENvZGUgcmVwcmVzZW50ZWQgYXMgYSB7QGxpbmsgQml0TWF0cml4fS4gQSAxIG9yIFwidHJ1ZVwiIGlzIHRha2VuIHRvIG1lYW4gYSBibGFjayBtb2R1bGUuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gYml0cyBib29sZWFucyByZXByZXNlbnRpbmcgd2hpdGUvYmxhY2sgUVIgQ29kZSBtb2R1bGVzXG4gICAgICAgICAqIEBwYXJhbSBoaW50cyBkZWNvZGluZyBoaW50cyB0aGF0IHNob3VsZCBiZSB1c2VkIHRvIGluZmx1ZW5jZSBkZWNvZGluZ1xuICAgICAgICAgKiBAcmV0dXJuIHRleHQgYW5kIGJ5dGVzIGVuY29kZWQgd2l0aGluIHRoZSBRUiBDb2RlXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uIGlmIHRoZSBRUiBDb2RlIGNhbm5vdCBiZSBkZWNvZGVkXG4gICAgICAgICAqIEB0aHJvd3MgQ2hlY2tzdW1FeGNlcHRpb24gaWYgZXJyb3IgY29ycmVjdGlvbiBmYWlsc1xuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlQml0TWF0cml4KGJpdHMsIGhpbnRzKSB7XG4gICAgICAgICAgICAvLyBDb25zdHJ1Y3QgYSBwYXJzZXIgYW5kIHJlYWQgdmVyc2lvbiwgZXJyb3ItY29ycmVjdGlvbiBsZXZlbFxuICAgICAgICAgICAgY29uc3QgcGFyc2VyID0gbmV3IEJpdE1hdHJpeFBhcnNlciQxKGJpdHMpO1xuICAgICAgICAgICAgbGV0IGV4ID0gbnVsbDtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlQml0TWF0cml4UGFyc2VyKHBhcnNlciwgaGludHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUgLyo6IEZvcm1hdEV4Y2VwdGlvbiwgQ2hlY2tzdW1FeGNlcHRpb24qLykge1xuICAgICAgICAgICAgICAgIGV4ID0gZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgLy8gUmV2ZXJ0IHRoZSBiaXQgbWF0cml4XG4gICAgICAgICAgICAgICAgcGFyc2VyLnJlbWFzaygpO1xuICAgICAgICAgICAgICAgIC8vIFdpbGwgYmUgYXR0ZW1wdGluZyBhIG1pcnJvcmVkIHJlYWRpbmcgb2YgdGhlIHZlcnNpb24gYW5kIGZvcm1hdCBpbmZvLlxuICAgICAgICAgICAgICAgIHBhcnNlci5zZXRNaXJyb3IodHJ1ZSk7XG4gICAgICAgICAgICAgICAgLy8gUHJlZW1wdGl2ZWx5IHJlYWQgdGhlIHZlcnNpb24uXG4gICAgICAgICAgICAgICAgcGFyc2VyLnJlYWRWZXJzaW9uKCk7XG4gICAgICAgICAgICAgICAgLy8gUHJlZW1wdGl2ZWx5IHJlYWQgdGhlIGZvcm1hdCBpbmZvcm1hdGlvbi5cbiAgICAgICAgICAgICAgICBwYXJzZXIucmVhZEZvcm1hdEluZm9ybWF0aW9uKCk7XG4gICAgICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAgICAgKiBTaW5jZSB3ZSdyZSBoZXJlLCB0aGlzIG1lYW5zIHdlIGhhdmUgc3VjY2Vzc2Z1bGx5IGRldGVjdGVkIHNvbWUga2luZFxuICAgICAgICAgICAgICAgICAqIG9mIHZlcnNpb24gYW5kIGZvcm1hdCBpbmZvcm1hdGlvbiB3aGVuIG1pcnJvcmVkLiBUaGlzIGlzIGEgZ29vZCBzaWduLFxuICAgICAgICAgICAgICAgICAqIHRoYXQgdGhlIFFSIGNvZGUgbWF5IGJlIG1pcnJvcmVkLCBhbmQgd2Ugc2hvdWxkIHRyeSBvbmNlIG1vcmUgd2l0aCBhXG4gICAgICAgICAgICAgICAgICogbWlycm9yZWQgY29udGVudC5cbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAvLyBQcmVwYXJlIGZvciBhIG1pcnJvcmVkIHJlYWRpbmcuXG4gICAgICAgICAgICAgICAgcGFyc2VyLm1pcnJvcigpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuZGVjb2RlQml0TWF0cml4UGFyc2VyKHBhcnNlciwgaGludHMpO1xuICAgICAgICAgICAgICAgIC8vIFN1Y2Nlc3MhIE5vdGlmeSB0aGUgY2FsbGVyIHRoYXQgdGhlIGNvZGUgd2FzIG1pcnJvcmVkLlxuICAgICAgICAgICAgICAgIHJlc3VsdC5zZXRPdGhlcihuZXcgUVJDb2RlRGVjb2Rlck1ldGFEYXRhKHRydWUpKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUgLypGb3JtYXRFeGNlcHRpb24gfCBDaGVja3N1bUV4Y2VwdGlvbiovKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhyb3cgdGhlIGV4Y2VwdGlvbiBmcm9tIHRoZSBvcmlnaW5hbCByZWFkaW5nXG4gICAgICAgICAgICAgICAgaWYgKGV4ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGRlY29kZUJpdE1hdHJpeFBhcnNlcihwYXJzZXIsIGhpbnRzKSB7XG4gICAgICAgICAgICBjb25zdCB2ZXJzaW9uID0gcGFyc2VyLnJlYWRWZXJzaW9uKCk7XG4gICAgICAgICAgICBjb25zdCBlY0xldmVsID0gcGFyc2VyLnJlYWRGb3JtYXRJbmZvcm1hdGlvbigpLmdldEVycm9yQ29ycmVjdGlvbkxldmVsKCk7XG4gICAgICAgICAgICAvLyBSZWFkIGNvZGV3b3Jkc1xuICAgICAgICAgICAgY29uc3QgY29kZXdvcmRzID0gcGFyc2VyLnJlYWRDb2Rld29yZHMoKTtcbiAgICAgICAgICAgIC8vIFNlcGFyYXRlIGludG8gZGF0YSBibG9ja3NcbiAgICAgICAgICAgIGNvbnN0IGRhdGFCbG9ja3MgPSBEYXRhQmxvY2skMS5nZXREYXRhQmxvY2tzKGNvZGV3b3JkcywgdmVyc2lvbiwgZWNMZXZlbCk7XG4gICAgICAgICAgICAvLyBDb3VudCB0b3RhbCBudW1iZXIgb2YgZGF0YSBieXRlc1xuICAgICAgICAgICAgbGV0IHRvdGFsQnl0ZXMgPSAwO1xuICAgICAgICAgICAgZm9yIChjb25zdCBkYXRhQmxvY2sgb2YgZGF0YUJsb2Nrcykge1xuICAgICAgICAgICAgICAgIHRvdGFsQnl0ZXMgKz0gZGF0YUJsb2NrLmdldE51bURhdGFDb2Rld29yZHMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdEJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkodG90YWxCeXRlcyk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0T2Zmc2V0ID0gMDtcbiAgICAgICAgICAgIC8vIEVycm9yLWNvcnJlY3QgYW5kIGNvcHkgZGF0YSBibG9ja3MgdG9nZXRoZXIgaW50byBhIHN0cmVhbSBvZiBieXRlc1xuICAgICAgICAgICAgZm9yIChjb25zdCBkYXRhQmxvY2sgb2YgZGF0YUJsb2Nrcykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvZGV3b3JkQnl0ZXMgPSBkYXRhQmxvY2suZ2V0Q29kZXdvcmRzKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgbnVtRGF0YUNvZGV3b3JkcyA9IGRhdGFCbG9jay5nZXROdW1EYXRhQ29kZXdvcmRzKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5jb3JyZWN0RXJyb3JzKGNvZGV3b3JkQnl0ZXMsIG51bURhdGFDb2Rld29yZHMpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtRGF0YUNvZGV3b3JkczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdEJ5dGVzW3Jlc3VsdE9mZnNldCsrXSA9IGNvZGV3b3JkQnl0ZXNbaV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRGVjb2RlIHRoZSBjb250ZW50cyBvZiB0aGF0IHN0cmVhbSBvZiBieXRlc1xuICAgICAgICAgICAgcmV0dXJuIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS5kZWNvZGUocmVzdWx0Qnl0ZXMsIHZlcnNpb24sIGVjTGV2ZWwsIGhpbnRzKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+R2l2ZW4gZGF0YSBhbmQgZXJyb3ItY29ycmVjdGlvbiBjb2Rld29yZHMgcmVjZWl2ZWQsIHBvc3NpYmx5IGNvcnJ1cHRlZCBieSBlcnJvcnMsIGF0dGVtcHRzIHRvXG4gICAgICAgICAqIGNvcnJlY3QgdGhlIGVycm9ycyBpbi1wbGFjZSB1c2luZyBSZWVkLVNvbG9tb24gZXJyb3IgY29ycmVjdGlvbi48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBjb2Rld29yZEJ5dGVzIGRhdGEgYW5kIGVycm9yIGNvcnJlY3Rpb24gY29kZXdvcmRzXG4gICAgICAgICAqIEBwYXJhbSBudW1EYXRhQ29kZXdvcmRzIG51bWJlciBvZiBjb2Rld29yZHMgdGhhdCBhcmUgZGF0YSBieXRlc1xuICAgICAgICAgKiBAdGhyb3dzIENoZWNrc3VtRXhjZXB0aW9uIGlmIGVycm9yIGNvcnJlY3Rpb24gZmFpbHNcbiAgICAgICAgICovXG4gICAgICAgIGNvcnJlY3RFcnJvcnMoY29kZXdvcmRCeXRlcywgbnVtRGF0YUNvZGV3b3JkcyAvKmludCovKSB7XG4gICAgICAgICAgICAvLyBjb25zdCBudW1Db2Rld29yZHMgPSBjb2Rld29yZEJ5dGVzLmxlbmd0aDtcbiAgICAgICAgICAgIC8vIEZpcnN0IHJlYWQgaW50byBhbiBhcnJheSBvZiBpbnRzXG4gICAgICAgICAgICBjb25zdCBjb2Rld29yZHNJbnRzID0gbmV3IEludDMyQXJyYXkoY29kZXdvcmRCeXRlcyk7XG4gICAgICAgICAgICAvLyBUWVBFU0NSSVBUUE9SVDogbm90IHJlYWx5IG5lY2Vzc2FyeSB0byB0cmFuc2Zvcm0gdG8gaW50cz8gY291bGQgcmVkZXNpZ24gZXZlcnl0aGluZyB0byB3b3JrIHdpdGggdW5zaWduZWQgYnl0ZXM/XG4gICAgICAgICAgICAvLyBjb25zdCBjb2Rld29yZHNJbnRzID0gbmV3IEludDMyQXJyYXkobnVtQ29kZXdvcmRzKVxuICAgICAgICAgICAgLy8gZm9yIChsZXQgaSA9IDA7IGkgPCBudW1Db2Rld29yZHM7IGkrKykge1xuICAgICAgICAgICAgLy8gICBjb2Rld29yZHNJbnRzW2ldID0gY29kZXdvcmRCeXRlc1tpXSAmIDB4RkZcbiAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yc0RlY29kZXIuZGVjb2RlKGNvZGV3b3Jkc0ludHMsIGNvZGV3b3JkQnl0ZXMubGVuZ3RoIC0gbnVtRGF0YUNvZGV3b3Jkcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoaWdub3JlZCAvKjogUmVlZFNvbG9tb25FeGNlcHRpb24qLykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBDaGVja3N1bUV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQ29weSBiYWNrIGludG8gYXJyYXkgb2YgYnl0ZXMgLS0gb25seSBuZWVkIHRvIHdvcnJ5IGFib3V0IHRoZSBieXRlcyB0aGF0IHdlcmUgZGF0YVxuICAgICAgICAgICAgLy8gV2UgZG9uJ3QgY2FyZSBhYm91dCBlcnJvcnMgaW4gdGhlIGVycm9yLWNvcnJlY3Rpb24gY29kZXdvcmRzXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bURhdGFDb2Rld29yZHM7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvZGV3b3JkQnl0ZXNbaV0gPSAvKihieXRlKSAqLyBjb2Rld29yZHNJbnRzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiA8cD5FbmNhcHN1bGF0ZXMgYW4gYWxpZ25tZW50IHBhdHRlcm4sIHdoaWNoIGFyZSB0aGUgc21hbGxlciBzcXVhcmUgcGF0dGVybnMgZm91bmQgaW5cbiAgICAgKiBhbGwgYnV0IHRoZSBzaW1wbGVzdCBRUiBDb2Rlcy48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIEFsaWdubWVudFBhdHRlcm4gZXh0ZW5kcyBSZXN1bHRQb2ludCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHBvc1ggLypmbG9hdCovLCBwb3NZIC8qZmxvYXQqLywgZXN0aW1hdGVkTW9kdWxlU2l6ZSAvKmZsb2F0Ki8pIHtcbiAgICAgICAgICAgIHN1cGVyKHBvc1gsIHBvc1kpO1xuICAgICAgICAgICAgdGhpcy5lc3RpbWF0ZWRNb2R1bGVTaXplID0gZXN0aW1hdGVkTW9kdWxlU2l6ZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+RGV0ZXJtaW5lcyBpZiB0aGlzIGFsaWdubWVudCBwYXR0ZXJuIFwiYWJvdXQgZXF1YWxzXCIgYW4gYWxpZ25tZW50IHBhdHRlcm4gYXQgdGhlIHN0YXRlZFxuICAgICAgICAgKiBwb3NpdGlvbiBhbmQgc2l6ZSAtLSBtZWFuaW5nLCBpdCBpcyBhdCBuZWFybHkgdGhlIHNhbWUgY2VudGVyIHdpdGggbmVhcmx5IHRoZSBzYW1lIHNpemUuPC9wPlxuICAgICAgICAgKi9cbiAgICAgICAgYWJvdXRFcXVhbHMobW9kdWxlU2l6ZSAvKmZsb2F0Ki8sIGkgLypmbG9hdCovLCBqIC8qZmxvYXQqLykge1xuICAgICAgICAgICAgaWYgKE1hdGguYWJzKGkgLSB0aGlzLmdldFkoKSkgPD0gbW9kdWxlU2l6ZSAmJiBNYXRoLmFicyhqIC0gdGhpcy5nZXRYKCkpIDw9IG1vZHVsZVNpemUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBtb2R1bGVTaXplRGlmZiA9IE1hdGguYWJzKG1vZHVsZVNpemUgLSB0aGlzLmVzdGltYXRlZE1vZHVsZVNpemUpO1xuICAgICAgICAgICAgICAgIHJldHVybiBtb2R1bGVTaXplRGlmZiA8PSAxLjAgfHwgbW9kdWxlU2l6ZURpZmYgPD0gdGhpcy5lc3RpbWF0ZWRNb2R1bGVTaXplO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb21iaW5lcyB0aGlzIG9iamVjdCdzIGN1cnJlbnQgZXN0aW1hdGUgb2YgYSBmaW5kZXIgcGF0dGVybiBwb3NpdGlvbiBhbmQgbW9kdWxlIHNpemVcbiAgICAgICAgICogd2l0aCBhIG5ldyBlc3RpbWF0ZS4gSXQgcmV0dXJucyBhIG5ldyB7QGNvZGUgRmluZGVyUGF0dGVybn0gY29udGFpbmluZyBhbiBhdmVyYWdlIG9mIHRoZSB0d28uXG4gICAgICAgICAqL1xuICAgICAgICBjb21iaW5lRXN0aW1hdGUoaSAvKmZsb2F0Ki8sIGogLypmbG9hdCovLCBuZXdNb2R1bGVTaXplIC8qZmxvYXQqLykge1xuICAgICAgICAgICAgY29uc3QgY29tYmluZWRYID0gKHRoaXMuZ2V0WCgpICsgaikgLyAyLjA7XG4gICAgICAgICAgICBjb25zdCBjb21iaW5lZFkgPSAodGhpcy5nZXRZKCkgKyBpKSAvIDIuMDtcbiAgICAgICAgICAgIGNvbnN0IGNvbWJpbmVkTW9kdWxlU2l6ZSA9ICh0aGlzLmVzdGltYXRlZE1vZHVsZVNpemUgKyBuZXdNb2R1bGVTaXplKSAvIDIuMDtcbiAgICAgICAgICAgIHJldHVybiBuZXcgQWxpZ25tZW50UGF0dGVybihjb21iaW5lZFgsIGNvbWJpbmVkWSwgY29tYmluZWRNb2R1bGVTaXplKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyppbXBvcnQgamF2YS51dGlsLkFycmF5TGlzdDsqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5MaXN0OyovXG4gICAgLyoqXG4gICAgICogPHA+VGhpcyBjbGFzcyBhdHRlbXB0cyB0byBmaW5kIGFsaWdubWVudCBwYXR0ZXJucyBpbiBhIFFSIENvZGUuIEFsaWdubWVudCBwYXR0ZXJucyBsb29rIGxpa2UgZmluZGVyXG4gICAgICogcGF0dGVybnMgYnV0IGFyZSBzbWFsbGVyIGFuZCBhcHBlYXIgYXQgcmVndWxhciBpbnRlcnZhbHMgdGhyb3VnaG91dCB0aGUgaW1hZ2UuPC9wPlxuICAgICAqXG4gICAgICogPHA+QXQgdGhlIG1vbWVudCB0aGlzIG9ubHkgbG9va3MgZm9yIHRoZSBib3R0b20tcmlnaHQgYWxpZ25tZW50IHBhdHRlcm4uPC9wPlxuICAgICAqXG4gICAgICogPHA+VGhpcyBpcyBtb3N0bHkgYSBzaW1wbGlmaWVkIGNvcHkgb2Yge0BsaW5rIEZpbmRlclBhdHRlcm5GaW5kZXJ9LiBJdCBpcyBjb3BpZWQsXG4gICAgICogcGFzdGVkIGFuZCBzdHJpcHBlZCBkb3duIGhlcmUgZm9yIG1heGltdW0gcGVyZm9ybWFuY2UgYnV0IGRvZXMgdW5mb3J0dW5hdGVseSBkdXBsaWNhdGVcbiAgICAgKiBzb21lIGNvZGUuPC9wPlxuICAgICAqXG4gICAgICogPHA+VGhpcyBjbGFzcyBpcyB0aHJlYWQtc2FmZSBidXQgbm90IHJlZW50cmFudC4gRWFjaCB0aHJlYWQgbXVzdCBhbGxvY2F0ZSBpdHMgb3duIG9iamVjdC48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIEFsaWdubWVudFBhdHRlcm5GaW5kZXIge1xuICAgICAgICAvKipcbiAgICAgICAgICogPHA+Q3JlYXRlcyBhIGZpbmRlciB0aGF0IHdpbGwgbG9vayBpbiBhIHBvcnRpb24gb2YgdGhlIHdob2xlIGltYWdlLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGltYWdlIGltYWdlIHRvIHNlYXJjaFxuICAgICAgICAgKiBAcGFyYW0gc3RhcnRYIGxlZnQgY29sdW1uIGZyb20gd2hpY2ggdG8gc3RhcnQgc2VhcmNoaW5nXG4gICAgICAgICAqIEBwYXJhbSBzdGFydFkgdG9wIHJvdyBmcm9tIHdoaWNoIHRvIHN0YXJ0IHNlYXJjaGluZ1xuICAgICAgICAgKiBAcGFyYW0gd2lkdGggd2lkdGggb2YgcmVnaW9uIHRvIHNlYXJjaFxuICAgICAgICAgKiBAcGFyYW0gaGVpZ2h0IGhlaWdodCBvZiByZWdpb24gdG8gc2VhcmNoXG4gICAgICAgICAqIEBwYXJhbSBtb2R1bGVTaXplIGVzdGltYXRlZCBtb2R1bGUgc2l6ZSBzbyBmYXJcbiAgICAgICAgICovXG4gICAgICAgIGNvbnN0cnVjdG9yKGltYWdlLCBzdGFydFggLyppbnQqLywgc3RhcnRZIC8qaW50Ki8sIHdpZHRoIC8qaW50Ki8sIGhlaWdodCAvKmludCovLCBtb2R1bGVTaXplIC8qZmxvYXQqLywgcmVzdWx0UG9pbnRDYWxsYmFjaykge1xuICAgICAgICAgICAgdGhpcy5pbWFnZSA9IGltYWdlO1xuICAgICAgICAgICAgdGhpcy5zdGFydFggPSBzdGFydFg7XG4gICAgICAgICAgICB0aGlzLnN0YXJ0WSA9IHN0YXJ0WTtcbiAgICAgICAgICAgIHRoaXMud2lkdGggPSB3aWR0aDtcbiAgICAgICAgICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICAgICAgdGhpcy5tb2R1bGVTaXplID0gbW9kdWxlU2l6ZTtcbiAgICAgICAgICAgIHRoaXMucmVzdWx0UG9pbnRDYWxsYmFjayA9IHJlc3VsdFBvaW50Q2FsbGJhY2s7XG4gICAgICAgICAgICB0aGlzLnBvc3NpYmxlQ2VudGVycyA9IFtdOyAvLyBuZXcgQXJyYXk8YW55Pig1KSlcbiAgICAgICAgICAgIC8vIFRZUEVTQ1JJUFRQT1JUOiBhcnJheSBpbml0aWFsaXphdGlvbiB3aXRob3V0IHNpemUgYXMgdGhlIGxlbmd0aCBpcyBjaGVja2VkIGJlbG93XG4gICAgICAgICAgICB0aGlzLmNyb3NzQ2hlY2tTdGF0ZUNvdW50ID0gbmV3IEludDMyQXJyYXkoMyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPlRoaXMgbWV0aG9kIGF0dGVtcHRzIHRvIGZpbmQgdGhlIGJvdHRvbS1yaWdodCBhbGlnbm1lbnQgcGF0dGVybiBpbiB0aGUgaW1hZ2UuIEl0IGlzIGEgYml0IG1lc3N5IHNpbmNlXG4gICAgICAgICAqIGl0J3MgcHJldHR5IHBlcmZvcm1hbmNlLWNyaXRpY2FsIGFuZCBzbyBpcyB3cml0dGVuIHRvIGJlIGZhc3QgZm9yZW1vc3QuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIHtAbGluayBBbGlnbm1lbnRQYXR0ZXJufSBpZiBmb3VuZFxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIG5vdCBmb3VuZFxuICAgICAgICAgKi9cbiAgICAgICAgZmluZCgpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0WCA9IHRoaXMuc3RhcnRYO1xuICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMud2lkdGg7XG4gICAgICAgICAgICBjb25zdCBtYXhKID0gc3RhcnRYICsgd2lkdGg7XG4gICAgICAgICAgICBjb25zdCBtaWRkbGVJID0gdGhpcy5zdGFydFkgKyAoaGVpZ2h0IC8gMik7XG4gICAgICAgICAgICAvLyBXZSBhcmUgbG9va2luZyBmb3IgYmxhY2svd2hpdGUvYmxhY2sgbW9kdWxlcyBpbiAxOjE6MSByYXRpb1xuICAgICAgICAgICAgLy8gdGhpcyB0cmFja3MgdGhlIG51bWJlciBvZiBibGFjay93aGl0ZS9ibGFjayBtb2R1bGVzIHNlZW4gc28gZmFyXG4gICAgICAgICAgICBjb25zdCBzdGF0ZUNvdW50ID0gbmV3IEludDMyQXJyYXkoMyk7XG4gICAgICAgICAgICBjb25zdCBpbWFnZSA9IHRoaXMuaW1hZ2U7XG4gICAgICAgICAgICBmb3IgKGxldCBpR2VuID0gMDsgaUdlbiA8IGhlaWdodDsgaUdlbisrKSB7XG4gICAgICAgICAgICAgICAgLy8gU2VhcmNoIGZyb20gbWlkZGxlIG91dHdhcmRzXG4gICAgICAgICAgICAgICAgY29uc3QgaSA9IG1pZGRsZUkgKyAoKGlHZW4gJiAweDAxKSA9PT0gMCA/IE1hdGguZmxvb3IoKGlHZW4gKyAxKSAvIDIpIDogLU1hdGguZmxvb3IoKGlHZW4gKyAxKSAvIDIpKTtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzBdID0gMDtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzFdID0gMDtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzJdID0gMDtcbiAgICAgICAgICAgICAgICBsZXQgaiA9IHN0YXJ0WDtcbiAgICAgICAgICAgICAgICAvLyBCdXJuIG9mZiBsZWFkaW5nIHdoaXRlIHBpeGVscyBiZWZvcmUgYW55dGhpbmcgZWxzZTsgaWYgd2Ugc3RhcnQgaW4gdGhlIG1pZGRsZSBvZlxuICAgICAgICAgICAgICAgIC8vIGEgd2hpdGUgcnVuLCBpdCBkb2Vzbid0IG1ha2Ugc2Vuc2UgdG8gY291bnQgaXRzIGxlbmd0aCwgc2luY2Ugd2UgZG9uJ3Qga25vdyBpZiB0aGVcbiAgICAgICAgICAgICAgICAvLyB3aGl0ZSBydW4gY29udGludWVkIHRvIHRoZSBsZWZ0IG9mIHRoZSBzdGFydCBwb2ludFxuICAgICAgICAgICAgICAgIHdoaWxlIChqIDwgbWF4SiAmJiAhaW1hZ2UuZ2V0KGosIGkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGorKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IGN1cnJlbnRTdGF0ZSA9IDA7XG4gICAgICAgICAgICAgICAgd2hpbGUgKGogPCBtYXhKKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbWFnZS5nZXQoaiwgaSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrIHBpeGVsXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudFN0YXRlID09PSAxKSB7IC8vIENvdW50aW5nIGJsYWNrIHBpeGVsc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMV0rKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgeyAvLyBDb3VudGluZyB3aGl0ZSBwaXhlbHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudFN0YXRlID09PSAyKSB7IC8vIEEgd2lubmVyP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5mb3VuZFBhdHRlcm5Dcm9zcyhzdGF0ZUNvdW50KSkgeyAvLyBZZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbmZpcm1lZCA9IHRoaXMuaGFuZGxlUG9zc2libGVDZW50ZXIoc3RhdGVDb3VudCwgaSwgaik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29uZmlybWVkICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvbmZpcm1lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzBdID0gc3RhdGVDb3VudFsyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFsxXSA9IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMl0gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50U3RhdGUgPSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFsrK2N1cnJlbnRTdGF0ZV0rKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7IC8vIFdoaXRlIHBpeGVsXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudFN0YXRlID09PSAxKSB7IC8vIENvdW50aW5nIGJsYWNrIHBpeGVsc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTdGF0ZSsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFtjdXJyZW50U3RhdGVdKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaisrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5mb3VuZFBhdHRlcm5Dcm9zcyhzdGF0ZUNvdW50KSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25maXJtZWQgPSB0aGlzLmhhbmRsZVBvc3NpYmxlQ2VudGVyKHN0YXRlQ291bnQsIGksIG1heEopO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29uZmlybWVkICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29uZmlybWVkO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSG1tLCBub3RoaW5nIHdlIHNhdyB3YXMgb2JzZXJ2ZWQgYW5kIGNvbmZpcm1lZCB0d2ljZS4gSWYgd2UgaGFkXG4gICAgICAgICAgICAvLyBhbnkgZ3Vlc3MgYXQgYWxsLCByZXR1cm4gaXQuXG4gICAgICAgICAgICBpZiAodGhpcy5wb3NzaWJsZUNlbnRlcnMubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucG9zc2libGVDZW50ZXJzWzBdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdpdmVuIGEgY291bnQgb2YgYmxhY2svd2hpdGUvYmxhY2sgcGl4ZWxzIGp1c3Qgc2VlbiBhbmQgYW4gZW5kIHBvc2l0aW9uLFxuICAgICAgICAgKiBmaWd1cmVzIHRoZSBsb2NhdGlvbiBvZiB0aGUgY2VudGVyIG9mIHRoaXMgYmxhY2svd2hpdGUvYmxhY2sgcnVuLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGNlbnRlckZyb21FbmQoc3RhdGVDb3VudCwgZW5kIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHJldHVybiAoZW5kIC0gc3RhdGVDb3VudFsyXSkgLSBzdGF0ZUNvdW50WzFdIC8gMi4wO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gc3RhdGVDb3VudCBjb3VudCBvZiBibGFjay93aGl0ZS9ibGFjayBwaXhlbHMganVzdCByZWFkXG4gICAgICAgICAqIEByZXR1cm4gdHJ1ZSBpZmYgdGhlIHByb3BvcnRpb25zIG9mIHRoZSBjb3VudHMgaXMgY2xvc2UgZW5vdWdoIHRvIHRoZSAxLzEvMSByYXRpb3NcbiAgICAgICAgICogICAgICAgICB1c2VkIGJ5IGFsaWdubWVudCBwYXR0ZXJucyB0byBiZSBjb25zaWRlcmVkIGEgbWF0Y2hcbiAgICAgICAgICovXG4gICAgICAgIGZvdW5kUGF0dGVybkNyb3NzKHN0YXRlQ291bnQpIHtcbiAgICAgICAgICAgIGNvbnN0IG1vZHVsZVNpemUgPSB0aGlzLm1vZHVsZVNpemU7XG4gICAgICAgICAgICBjb25zdCBtYXhWYXJpYW5jZSA9IG1vZHVsZVNpemUgLyAyLjA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDM7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChNYXRoLmFicyhtb2R1bGVTaXplIC0gc3RhdGVDb3VudFtpXSkgPj0gbWF4VmFyaWFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5BZnRlciBhIGhvcml6b250YWwgc2NhbiBmaW5kcyBhIHBvdGVudGlhbCBhbGlnbm1lbnQgcGF0dGVybiwgdGhpcyBtZXRob2RcbiAgICAgICAgICogXCJjcm9zcy1jaGVja3NcIiBieSBzY2FubmluZyBkb3duIHZlcnRpY2FsbHkgdGhyb3VnaCB0aGUgY2VudGVyIG9mIHRoZSBwb3NzaWJsZVxuICAgICAgICAgKiBhbGlnbm1lbnQgcGF0dGVybiB0byBzZWUgaWYgdGhlIHNhbWUgcHJvcG9ydGlvbiBpcyBkZXRlY3RlZC48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBzdGFydEkgcm93IHdoZXJlIGFuIGFsaWdubWVudCBwYXR0ZXJuIHdhcyBkZXRlY3RlZFxuICAgICAgICAgKiBAcGFyYW0gY2VudGVySiBjZW50ZXIgb2YgdGhlIHNlY3Rpb24gdGhhdCBhcHBlYXJzIHRvIGNyb3NzIGFuIGFsaWdubWVudCBwYXR0ZXJuXG4gICAgICAgICAqIEBwYXJhbSBtYXhDb3VudCBtYXhpbXVtIHJlYXNvbmFibGUgbnVtYmVyIG9mIG1vZHVsZXMgdGhhdCBzaG91bGQgYmVcbiAgICAgICAgICogb2JzZXJ2ZWQgaW4gYW55IHJlYWRpbmcgc3RhdGUsIGJhc2VkIG9uIHRoZSByZXN1bHRzIG9mIHRoZSBob3Jpem9udGFsIHNjYW5cbiAgICAgICAgICogQHJldHVybiB2ZXJ0aWNhbCBjZW50ZXIgb2YgYWxpZ25tZW50IHBhdHRlcm4sIG9yIHtAbGluayBGbG9hdCNOYU59IGlmIG5vdCBmb3VuZFxuICAgICAgICAgKi9cbiAgICAgICAgY3Jvc3NDaGVja1ZlcnRpY2FsKHN0YXJ0SSAvKmludCovLCBjZW50ZXJKIC8qaW50Ki8sIG1heENvdW50IC8qaW50Ki8sIG9yaWdpbmFsU3RhdGVDb3VudFRvdGFsIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IGltYWdlID0gdGhpcy5pbWFnZTtcbiAgICAgICAgICAgIGNvbnN0IG1heEkgPSBpbWFnZS5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IHN0YXRlQ291bnQgPSB0aGlzLmNyb3NzQ2hlY2tTdGF0ZUNvdW50O1xuICAgICAgICAgICAgc3RhdGVDb3VudFswXSA9IDA7XG4gICAgICAgICAgICBzdGF0ZUNvdW50WzFdID0gMDtcbiAgICAgICAgICAgIHN0YXRlQ291bnRbMl0gPSAwO1xuICAgICAgICAgICAgLy8gU3RhcnQgY291bnRpbmcgdXAgZnJvbSBjZW50ZXJcbiAgICAgICAgICAgIGxldCBpID0gc3RhcnRJO1xuICAgICAgICAgICAgd2hpbGUgKGkgPj0gMCAmJiBpbWFnZS5nZXQoY2VudGVySiwgaSkgJiYgc3RhdGVDb3VudFsxXSA8PSBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMV0rKztcbiAgICAgICAgICAgICAgICBpLS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBJZiBhbHJlYWR5IHRvbyBtYW55IG1vZHVsZXMgaW4gdGhpcyBzdGF0ZSBvciByYW4gb2ZmIHRoZSBlZGdlOlxuICAgICAgICAgICAgaWYgKGkgPCAwIHx8IHN0YXRlQ291bnRbMV0gPiBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aGlsZSAoaSA+PSAwICYmICFpbWFnZS5nZXQoY2VudGVySiwgaSkgJiYgc3RhdGVDb3VudFswXSA8PSBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMF0rKztcbiAgICAgICAgICAgICAgICBpLS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RhdGVDb3VudFswXSA+IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE5vdyBhbHNvIGNvdW50IGRvd24gZnJvbSBjZW50ZXJcbiAgICAgICAgICAgIGkgPSBzdGFydEkgKyAxO1xuICAgICAgICAgICAgd2hpbGUgKGkgPCBtYXhJICYmIGltYWdlLmdldChjZW50ZXJKLCBpKSAmJiBzdGF0ZUNvdW50WzFdIDw9IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFsxXSsrO1xuICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpID09PSBtYXhJIHx8IHN0YXRlQ291bnRbMV0gPiBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aGlsZSAoaSA8IG1heEkgJiYgIWltYWdlLmdldChjZW50ZXJKLCBpKSAmJiBzdGF0ZUNvdW50WzJdIDw9IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFsyXSsrO1xuICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzdGF0ZUNvdW50WzJdID4gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgc3RhdGVDb3VudFRvdGFsID0gc3RhdGVDb3VudFswXSArIHN0YXRlQ291bnRbMV0gKyBzdGF0ZUNvdW50WzJdO1xuICAgICAgICAgICAgaWYgKDUgKiBNYXRoLmFicyhzdGF0ZUNvdW50VG90YWwgLSBvcmlnaW5hbFN0YXRlQ291bnRUb3RhbCkgPj0gMiAqIG9yaWdpbmFsU3RhdGVDb3VudFRvdGFsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZvdW5kUGF0dGVybkNyb3NzKHN0YXRlQ291bnQpID8gQWxpZ25tZW50UGF0dGVybkZpbmRlci5jZW50ZXJGcm9tRW5kKHN0YXRlQ291bnQsIGkpIDogTmFOO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5UaGlzIGlzIGNhbGxlZCB3aGVuIGEgaG9yaXpvbnRhbCBzY2FuIGZpbmRzIGEgcG9zc2libGUgYWxpZ25tZW50IHBhdHRlcm4uIEl0IHdpbGxcbiAgICAgICAgICogY3Jvc3MgY2hlY2sgd2l0aCBhIHZlcnRpY2FsIHNjYW4sIGFuZCBpZiBzdWNjZXNzZnVsLCB3aWxsIHNlZSBpZiB0aGlzIHBhdHRlcm4gaGFkIGJlZW5cbiAgICAgICAgICogZm91bmQgb24gYSBwcmV2aW91cyBob3Jpem9udGFsIHNjYW4uIElmIHNvLCB3ZSBjb25zaWRlciBpdCBjb25maXJtZWQgYW5kIGNvbmNsdWRlIHdlIGhhdmVcbiAgICAgICAgICogZm91bmQgdGhlIGFsaWdubWVudCBwYXR0ZXJuLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHN0YXRlQ291bnQgcmVhZGluZyBzdGF0ZSBtb2R1bGUgY291bnRzIGZyb20gaG9yaXpvbnRhbCBzY2FuXG4gICAgICAgICAqIEBwYXJhbSBpIHJvdyB3aGVyZSBhbGlnbm1lbnQgcGF0dGVybiBtYXkgYmUgZm91bmRcbiAgICAgICAgICogQHBhcmFtIGogZW5kIG9mIHBvc3NpYmxlIGFsaWdubWVudCBwYXR0ZXJuIGluIHJvd1xuICAgICAgICAgKiBAcmV0dXJuIHtAbGluayBBbGlnbm1lbnRQYXR0ZXJufSBpZiB3ZSBoYXZlIGZvdW5kIHRoZSBzYW1lIHBhdHRlcm4gdHdpY2UsIG9yIG51bGwgaWYgbm90XG4gICAgICAgICAqL1xuICAgICAgICBoYW5kbGVQb3NzaWJsZUNlbnRlcihzdGF0ZUNvdW50LCBpIC8qaW50Ki8sIGogLyppbnQqLykge1xuICAgICAgICAgICAgY29uc3Qgc3RhdGVDb3VudFRvdGFsID0gc3RhdGVDb3VudFswXSArIHN0YXRlQ291bnRbMV0gKyBzdGF0ZUNvdW50WzJdO1xuICAgICAgICAgICAgY29uc3QgY2VudGVySiA9IEFsaWdubWVudFBhdHRlcm5GaW5kZXIuY2VudGVyRnJvbUVuZChzdGF0ZUNvdW50LCBqKTtcbiAgICAgICAgICAgIGNvbnN0IGNlbnRlckkgPSB0aGlzLmNyb3NzQ2hlY2tWZXJ0aWNhbChpLCAvKihpbnQpICovIGNlbnRlckosIDIgKiBzdGF0ZUNvdW50WzFdLCBzdGF0ZUNvdW50VG90YWwpO1xuICAgICAgICAgICAgaWYgKCFpc05hTihjZW50ZXJJKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGVzdGltYXRlZE1vZHVsZVNpemUgPSAoc3RhdGVDb3VudFswXSArIHN0YXRlQ291bnRbMV0gKyBzdGF0ZUNvdW50WzJdKSAvIDMuMDtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGNlbnRlciBvZiB0aGlzLnBvc3NpYmxlQ2VudGVycykge1xuICAgICAgICAgICAgICAgICAgICAvLyBMb29rIGZvciBhYm91dCB0aGUgc2FtZSBjZW50ZXIgYW5kIG1vZHVsZSBzaXplOlxuICAgICAgICAgICAgICAgICAgICBpZiAoY2VudGVyLmFib3V0RXF1YWxzKGVzdGltYXRlZE1vZHVsZVNpemUsIGNlbnRlckksIGNlbnRlckopKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2VudGVyLmNvbWJpbmVFc3RpbWF0ZShjZW50ZXJJLCBjZW50ZXJKLCBlc3RpbWF0ZWRNb2R1bGVTaXplKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBIYWRuJ3QgZm91bmQgdGhpcyBiZWZvcmU7IHNhdmUgaXRcbiAgICAgICAgICAgICAgICBjb25zdCBwb2ludCA9IG5ldyBBbGlnbm1lbnRQYXR0ZXJuKGNlbnRlckosIGNlbnRlckksIGVzdGltYXRlZE1vZHVsZVNpemUpO1xuICAgICAgICAgICAgICAgIHRoaXMucG9zc2libGVDZW50ZXJzLnB1c2gocG9pbnQpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlc3VsdFBvaW50Q2FsbGJhY2sgIT09IG51bGwgJiYgdGhpcy5yZXN1bHRQb2ludENhbGxiYWNrICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXN1bHRQb2ludENhbGxiYWNrLmZvdW5kUG9zc2libGVSZXN1bHRQb2ludChwb2ludCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIDxwPkVuY2Fwc3VsYXRlcyBhIGZpbmRlciBwYXR0ZXJuLCB3aGljaCBhcmUgdGhlIHRocmVlIHNxdWFyZSBwYXR0ZXJucyBmb3VuZCBpblxuICAgICAqIHRoZSBjb3JuZXJzIG9mIFFSIENvZGVzLiBJdCBhbHNvIGVuY2Fwc3VsYXRlcyBhIGNvdW50IG9mIHNpbWlsYXIgZmluZGVyIHBhdHRlcm5zLFxuICAgICAqIGFzIGEgY29udmVuaWVuY2UgdG8gdGhlIGZpbmRlcidzIGJvb2trZWVwaW5nLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgRmluZGVyUGF0dGVybiQxIGV4dGVuZHMgUmVzdWx0UG9pbnQge1xuICAgICAgICAvLyBGaW5kZXJQYXR0ZXJuKHBvc1g6IG51bWJlci8qZmxvYXQqLywgcG9zWTogbnVtYmVyLypmbG9hdCovLCBlc3RpbWF0ZWRNb2R1bGVTaXplOiBudW1iZXIvKmZsb2F0Ki8pIHtcbiAgICAgICAgLy8gICB0aGlzKHBvc1gsIHBvc1ksIGVzdGltYXRlZE1vZHVsZVNpemUsIDEpXG4gICAgICAgIC8vIH1cbiAgICAgICAgY29uc3RydWN0b3IocG9zWCAvKmZsb2F0Ki8sIHBvc1kgLypmbG9hdCovLCBlc3RpbWF0ZWRNb2R1bGVTaXplIC8qZmxvYXQqLywgY291bnQgLyppbnQqLykge1xuICAgICAgICAgICAgc3VwZXIocG9zWCwgcG9zWSk7XG4gICAgICAgICAgICB0aGlzLmVzdGltYXRlZE1vZHVsZVNpemUgPSBlc3RpbWF0ZWRNb2R1bGVTaXplO1xuICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50O1xuICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCA9PT0gY291bnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBnZXRFc3RpbWF0ZWRNb2R1bGVTaXplKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXN0aW1hdGVkTW9kdWxlU2l6ZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRDb3VudCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvdW50O1xuICAgICAgICB9XG4gICAgICAgIC8qXG4gICAgICAgIHZvaWQgaW5jcmVtZW50Q291bnQoKSB7XG4gICAgICAgICAgdGhpcy5jb3VudCsrXG4gICAgICAgIH1cbiAgICAgICAgICovXG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5EZXRlcm1pbmVzIGlmIHRoaXMgZmluZGVyIHBhdHRlcm4gXCJhYm91dCBlcXVhbHNcIiBhIGZpbmRlciBwYXR0ZXJuIGF0IHRoZSBzdGF0ZWRcbiAgICAgICAgICogcG9zaXRpb24gYW5kIHNpemUgLS0gbWVhbmluZywgaXQgaXMgYXQgbmVhcmx5IHRoZSBzYW1lIGNlbnRlciB3aXRoIG5lYXJseSB0aGUgc2FtZSBzaXplLjwvcD5cbiAgICAgICAgICovXG4gICAgICAgIGFib3V0RXF1YWxzKG1vZHVsZVNpemUgLypmbG9hdCovLCBpIC8qZmxvYXQqLywgaiAvKmZsb2F0Ki8pIHtcbiAgICAgICAgICAgIGlmIChNYXRoLmFicyhpIC0gdGhpcy5nZXRZKCkpIDw9IG1vZHVsZVNpemUgJiYgTWF0aC5hYnMoaiAtIHRoaXMuZ2V0WCgpKSA8PSBtb2R1bGVTaXplKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbW9kdWxlU2l6ZURpZmYgPSBNYXRoLmFicyhtb2R1bGVTaXplIC0gdGhpcy5lc3RpbWF0ZWRNb2R1bGVTaXplKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9kdWxlU2l6ZURpZmYgPD0gMS4wIHx8IG1vZHVsZVNpemVEaWZmIDw9IHRoaXMuZXN0aW1hdGVkTW9kdWxlU2l6ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ29tYmluZXMgdGhpcyBvYmplY3QncyBjdXJyZW50IGVzdGltYXRlIG9mIGEgZmluZGVyIHBhdHRlcm4gcG9zaXRpb24gYW5kIG1vZHVsZSBzaXplXG4gICAgICAgICAqIHdpdGggYSBuZXcgZXN0aW1hdGUuIEl0IHJldHVybnMgYSBuZXcge0Bjb2RlIEZpbmRlclBhdHRlcm59IGNvbnRhaW5pbmcgYSB3ZWlnaHRlZCBhdmVyYWdlXG4gICAgICAgICAqIGJhc2VkIG9uIGNvdW50LlxuICAgICAgICAgKi9cbiAgICAgICAgY29tYmluZUVzdGltYXRlKGkgLypmbG9hdCovLCBqIC8qZmxvYXQqLywgbmV3TW9kdWxlU2l6ZSAvKmZsb2F0Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IGNvbWJpbmVkQ291bnQgPSB0aGlzLmNvdW50ICsgMTtcbiAgICAgICAgICAgIGNvbnN0IGNvbWJpbmVkWCA9ICh0aGlzLmNvdW50ICogdGhpcy5nZXRYKCkgKyBqKSAvIGNvbWJpbmVkQ291bnQ7XG4gICAgICAgICAgICBjb25zdCBjb21iaW5lZFkgPSAodGhpcy5jb3VudCAqIHRoaXMuZ2V0WSgpICsgaSkgLyBjb21iaW5lZENvdW50O1xuICAgICAgICAgICAgY29uc3QgY29tYmluZWRNb2R1bGVTaXplID0gKHRoaXMuY291bnQgKiB0aGlzLmVzdGltYXRlZE1vZHVsZVNpemUgKyBuZXdNb2R1bGVTaXplKSAvIGNvbWJpbmVkQ291bnQ7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEZpbmRlclBhdHRlcm4kMShjb21iaW5lZFgsIGNvbWJpbmVkWSwgY29tYmluZWRNb2R1bGVTaXplLCBjb21iaW5lZENvdW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogPHA+RW5jYXBzdWxhdGVzIGluZm9ybWF0aW9uIGFib3V0IGZpbmRlciBwYXR0ZXJucyBpbiBhbiBpbWFnZSwgaW5jbHVkaW5nIHRoZSBsb2NhdGlvbiBvZlxuICAgICAqIHRoZSB0aHJlZSBmaW5kZXIgcGF0dGVybnMsIGFuZCB0aGVpciBlc3RpbWF0ZWQgbW9kdWxlIHNpemUuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBGaW5kZXJQYXR0ZXJuSW5mbyB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHBhdHRlcm5DZW50ZXJzKSB7XG4gICAgICAgICAgICB0aGlzLmJvdHRvbUxlZnQgPSBwYXR0ZXJuQ2VudGVyc1swXTtcbiAgICAgICAgICAgIHRoaXMudG9wTGVmdCA9IHBhdHRlcm5DZW50ZXJzWzFdO1xuICAgICAgICAgICAgdGhpcy50b3BSaWdodCA9IHBhdHRlcm5DZW50ZXJzWzJdO1xuICAgICAgICB9XG4gICAgICAgIGdldEJvdHRvbUxlZnQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ib3R0b21MZWZ0O1xuICAgICAgICB9XG4gICAgICAgIGdldFRvcExlZnQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50b3BMZWZ0O1xuICAgICAgICB9XG4gICAgICAgIGdldFRvcFJpZ2h0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9wUmlnaHQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qaW1wb3J0IGphdmEuaW8uU2VyaWFsaXphYmxlOyovXG4gICAgLyppbXBvcnQgamF2YS51dGlsLkFycmF5TGlzdDsqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5Db2xsZWN0aW9uczsqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5Db21wYXJhdG9yOyovXG4gICAgLyppbXBvcnQgamF2YS51dGlsLkxpc3Q7Ki9cbiAgICAvKmltcG9ydCBqYXZhLnV0aWwuTWFwOyovXG4gICAgLyoqXG4gICAgICogPHA+VGhpcyBjbGFzcyBhdHRlbXB0cyB0byBmaW5kIGZpbmRlciBwYXR0ZXJucyBpbiBhIFFSIENvZGUuIEZpbmRlciBwYXR0ZXJucyBhcmUgdGhlIHNxdWFyZVxuICAgICAqIG1hcmtlcnMgYXQgdGhyZWUgY29ybmVycyBvZiBhIFFSIENvZGUuPC9wPlxuICAgICAqXG4gICAgICogPHA+VGhpcyBjbGFzcyBpcyB0aHJlYWQtc2FmZSBidXQgbm90IHJlZW50cmFudC4gRWFjaCB0aHJlYWQgbXVzdCBhbGxvY2F0ZSBpdHMgb3duIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgRmluZGVyUGF0dGVybkZpbmRlciB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5DcmVhdGVzIGEgZmluZGVyIHRoYXQgd2lsbCBzZWFyY2ggdGhlIGltYWdlIGZvciB0aHJlZSBmaW5kZXIgcGF0dGVybnMuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gaW1hZ2UgaW1hZ2UgdG8gc2VhcmNoXG4gICAgICAgICAqL1xuICAgICAgICAvLyBwdWJsaWMgY29uc3RydWN0b3IoaW1hZ2U6IEJpdE1hdHJpeCkge1xuICAgICAgICAvLyAgIHRoaXMoaW1hZ2UsIG51bGwpXG4gICAgICAgIC8vIH1cbiAgICAgICAgY29uc3RydWN0b3IoaW1hZ2UsIHJlc3VsdFBvaW50Q2FsbGJhY2spIHtcbiAgICAgICAgICAgIHRoaXMuaW1hZ2UgPSBpbWFnZTtcbiAgICAgICAgICAgIHRoaXMucmVzdWx0UG9pbnRDYWxsYmFjayA9IHJlc3VsdFBvaW50Q2FsbGJhY2s7XG4gICAgICAgICAgICB0aGlzLnBvc3NpYmxlQ2VudGVycyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5jcm9zc0NoZWNrU3RhdGVDb3VudCA9IG5ldyBJbnQzMkFycmF5KDUpO1xuICAgICAgICAgICAgdGhpcy5yZXN1bHRQb2ludENhbGxiYWNrID0gcmVzdWx0UG9pbnRDYWxsYmFjaztcbiAgICAgICAgfVxuICAgICAgICBnZXRJbWFnZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmltYWdlO1xuICAgICAgICB9XG4gICAgICAgIGdldFBvc3NpYmxlQ2VudGVycygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBvc3NpYmxlQ2VudGVycztcbiAgICAgICAgfVxuICAgICAgICBmaW5kKGhpbnRzKSB7XG4gICAgICAgICAgICBjb25zdCB0cnlIYXJkZXIgPSAoaGludHMgIT09IG51bGwgJiYgaGludHMgIT09IHVuZGVmaW5lZCkgJiYgdW5kZWZpbmVkICE9PSBoaW50cy5nZXQoRGVjb2RlSGludFR5cGUkMS5UUllfSEFSREVSKTtcbiAgICAgICAgICAgIGNvbnN0IHB1cmVCYXJjb2RlID0gKGhpbnRzICE9PSBudWxsICYmIGhpbnRzICE9PSB1bmRlZmluZWQpICYmIHVuZGVmaW5lZCAhPT0gaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuUFVSRV9CQVJDT0RFKTtcbiAgICAgICAgICAgIGNvbnN0IGltYWdlID0gdGhpcy5pbWFnZTtcbiAgICAgICAgICAgIGNvbnN0IG1heEkgPSBpbWFnZS5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IG1heEogPSBpbWFnZS5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgLy8gV2UgYXJlIGxvb2tpbmcgZm9yIGJsYWNrL3doaXRlL2JsYWNrL3doaXRlL2JsYWNrIG1vZHVsZXMgaW5cbiAgICAgICAgICAgIC8vIDE6MTozOjE6MSByYXRpbzsgdGhpcyB0cmFja3MgdGhlIG51bWJlciBvZiBzdWNoIG1vZHVsZXMgc2VlbiBzbyBmYXJcbiAgICAgICAgICAgIC8vIExldCdzIGFzc3VtZSB0aGF0IHRoZSBtYXhpbXVtIHZlcnNpb24gUVIgQ29kZSB3ZSBzdXBwb3J0IHRha2VzIHVwIDEvNCB0aGUgaGVpZ2h0IG9mIHRoZVxuICAgICAgICAgICAgLy8gaW1hZ2UsIGFuZCB0aGVuIGFjY291bnQgZm9yIHRoZSBjZW50ZXIgYmVpbmcgMyBtb2R1bGVzIGluIHNpemUuIFRoaXMgZ2l2ZXMgdGhlIHNtYWxsZXN0XG4gICAgICAgICAgICAvLyBudW1iZXIgb2YgcGl4ZWxzIHRoZSBjZW50ZXIgY291bGQgYmUsIHNvIHNraXAgdGhpcyBvZnRlbi4gV2hlbiB0cnlpbmcgaGFyZGVyLCBsb29rIGZvciBhbGxcbiAgICAgICAgICAgIC8vIFFSIHZlcnNpb25zIHJlZ2FyZGxlc3Mgb2YgaG93IGRlbnNlIHRoZXkgYXJlLlxuICAgICAgICAgICAgbGV0IGlTa2lwID0gTWF0aC5mbG9vcigoMyAqIG1heEkpIC8gKDQgKiBGaW5kZXJQYXR0ZXJuRmluZGVyLk1BWF9NT0RVTEVTKSk7XG4gICAgICAgICAgICBpZiAoaVNraXAgPCBGaW5kZXJQYXR0ZXJuRmluZGVyLk1JTl9TS0lQIHx8IHRyeUhhcmRlcikge1xuICAgICAgICAgICAgICAgIGlTa2lwID0gRmluZGVyUGF0dGVybkZpbmRlci5NSU5fU0tJUDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBkb25lID0gZmFsc2U7XG4gICAgICAgICAgICBjb25zdCBzdGF0ZUNvdW50ID0gbmV3IEludDMyQXJyYXkoNSk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gaVNraXAgLSAxOyBpIDwgbWF4SSAmJiAhZG9uZTsgaSArPSBpU2tpcCkge1xuICAgICAgICAgICAgICAgIC8vIEdldCBhIHJvdyBvZiBibGFjay93aGl0ZSB2YWx1ZXNcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzBdID0gMDtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzFdID0gMDtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzJdID0gMDtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzNdID0gMDtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzRdID0gMDtcbiAgICAgICAgICAgICAgICBsZXQgY3VycmVudFN0YXRlID0gMDtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IG1heEo7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW1hZ2UuZ2V0KGosIGkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBCbGFjayBwaXhlbFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChjdXJyZW50U3RhdGUgJiAxKSA9PT0gMSkgeyAvLyBDb3VudGluZyB3aGl0ZSBwaXhlbHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50U3RhdGUrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbY3VycmVudFN0YXRlXSsrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgeyAvLyBXaGl0ZSBwaXhlbFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChjdXJyZW50U3RhdGUgJiAxKSA9PT0gMCkgeyAvLyBDb3VudGluZyBibGFjayBwaXhlbHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudFN0YXRlID09PSA0KSB7IC8vIEEgd2lubmVyP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoRmluZGVyUGF0dGVybkZpbmRlci5mb3VuZFBhdHRlcm5Dcm9zcyhzdGF0ZUNvdW50KSkgeyAvLyBZZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbmZpcm1lZCA9IHRoaXMuaGFuZGxlUG9zc2libGVDZW50ZXIoc3RhdGVDb3VudCwgaSwgaiwgcHVyZUJhcmNvZGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbmZpcm1lZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN0YXJ0IGV4YW1pbmluZyBldmVyeSBvdGhlciBsaW5lLiBDaGVja2luZyBlYWNoIGxpbmUgdHVybmVkIG91dCB0byBiZSB0b29cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBleHBlbnNpdmUgYW5kIGRpZG4ndCBpbXByb3ZlIHBlcmZvcm1hbmNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlTa2lwID0gMjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5oYXNTa2lwcGVkID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmUgPSB0aGlzLmhhdmVNdWx0aXBseUNvbmZpcm1lZENlbnRlcnMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJvd1NraXAgPSB0aGlzLmZpbmRSb3dTa2lwKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyb3dTa2lwID4gc3RhdGVDb3VudFsyXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2tpcCByb3dzIGJldHdlZW4gcm93IG9mIGxvd2VyIGNvbmZpcm1lZCBjZW50ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFuZCB0b3Agb2YgcHJlc3VtZWQgdGhpcmQgY29uZmlybWVkIGNlbnRlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYnV0IGJhY2sgdXAgYSBiaXQgdG8gZ2V0IGEgZnVsbCBjaGFuY2Ugb2YgZGV0ZWN0aW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdCwgZW50aXJlIHdpZHRoIG9mIGNlbnRlciBvZiBmaW5kZXIgcGF0dGVyblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2tpcCBieSByb3dTa2lwLCBidXQgYmFjayBvZmYgYnkgc3RhdGVDb3VudFsyXSAoc2l6ZSBvZiBsYXN0IGNlbnRlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb2YgcGF0dGVybiB3ZSBzYXcpIHRvIGJlIGNvbnNlcnZhdGl2ZSwgYW5kIGFsc28gYmFjayBvZmYgYnkgaVNraXAgd2hpY2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlzIGFib3V0IHRvIGJlIHJlLWFkZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpICs9IHJvd1NraXAgLSBzdGF0ZUNvdW50WzJdIC0gaVNraXA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBqID0gbWF4SiAtIDE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzBdID0gc3RhdGVDb3VudFsyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzFdID0gc3RhdGVDb3VudFszXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzJdID0gc3RhdGVDb3VudFs0XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzNdID0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzRdID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50U3RhdGUgPSAzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2xlYXIgc3RhdGUgdG8gc3RhcnQgbG9va2luZyBhZ2FpblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFN0YXRlID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMF0gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFsxXSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzJdID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbM10gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFs0XSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7IC8vIE5vLCBzaGlmdCBjb3VudHMgYmFjayBieSB0d29cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMF0gPSBzdGF0ZUNvdW50WzJdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFsxXSA9IHN0YXRlQ291bnRbM107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzJdID0gc3RhdGVDb3VudFs0XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbM10gPSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFs0XSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50U3RhdGUgPSAzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WysrY3VycmVudFN0YXRlXSsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgeyAvLyBDb3VudGluZyB3aGl0ZSBwaXhlbHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50W2N1cnJlbnRTdGF0ZV0rKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoRmluZGVyUGF0dGVybkZpbmRlci5mb3VuZFBhdHRlcm5Dcm9zcyhzdGF0ZUNvdW50KSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25maXJtZWQgPSB0aGlzLmhhbmRsZVBvc3NpYmxlQ2VudGVyKHN0YXRlQ291bnQsIGksIG1heEosIHB1cmVCYXJjb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvbmZpcm1lZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaVNraXAgPSBzdGF0ZUNvdW50WzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaGFzU2tpcHBlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZvdW5kIGEgdGhpcmQgb25lXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9uZSA9IHRoaXMuaGF2ZU11bHRpcGx5Q29uZmlybWVkQ2VudGVycygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcGF0dGVybkluZm8gPSB0aGlzLnNlbGVjdEJlc3RQYXR0ZXJucygpO1xuICAgICAgICAgICAgUmVzdWx0UG9pbnQub3JkZXJCZXN0UGF0dGVybnMocGF0dGVybkluZm8pO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBGaW5kZXJQYXR0ZXJuSW5mbyhwYXR0ZXJuSW5mbyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdpdmVuIGEgY291bnQgb2YgYmxhY2svd2hpdGUvYmxhY2svd2hpdGUvYmxhY2sgcGl4ZWxzIGp1c3Qgc2VlbiBhbmQgYW4gZW5kIHBvc2l0aW9uLFxuICAgICAgICAgKiBmaWd1cmVzIHRoZSBsb2NhdGlvbiBvZiB0aGUgY2VudGVyIG9mIHRoaXMgcnVuLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGNlbnRlckZyb21FbmQoc3RhdGVDb3VudCwgZW5kIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHJldHVybiAoZW5kIC0gc3RhdGVDb3VudFs0XSAtIHN0YXRlQ291bnRbM10pIC0gc3RhdGVDb3VudFsyXSAvIDIuMDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHN0YXRlQ291bnQgY291bnQgb2YgYmxhY2svd2hpdGUvYmxhY2svd2hpdGUvYmxhY2sgcGl4ZWxzIGp1c3QgcmVhZFxuICAgICAgICAgKiBAcmV0dXJuIHRydWUgaWZmIHRoZSBwcm9wb3J0aW9ucyBvZiB0aGUgY291bnRzIGlzIGNsb3NlIGVub3VnaCB0byB0aGUgMS8xLzMvMS8xIHJhdGlvc1xuICAgICAgICAgKiAgICAgICAgIHVzZWQgYnkgZmluZGVyIHBhdHRlcm5zIHRvIGJlIGNvbnNpZGVyZWQgYSBtYXRjaFxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGZvdW5kUGF0dGVybkNyb3NzKHN0YXRlQ291bnQpIHtcbiAgICAgICAgICAgIGxldCB0b3RhbE1vZHVsZVNpemUgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCA1OyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb3VudCA9IHN0YXRlQ291bnRbaV07XG4gICAgICAgICAgICAgICAgaWYgKGNvdW50ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdG90YWxNb2R1bGVTaXplICs9IGNvdW50O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRvdGFsTW9kdWxlU2l6ZSA8IDcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBtb2R1bGVTaXplID0gdG90YWxNb2R1bGVTaXplIC8gNy4wO1xuICAgICAgICAgICAgY29uc3QgbWF4VmFyaWFuY2UgPSBtb2R1bGVTaXplIC8gMi4wO1xuICAgICAgICAgICAgLy8gQWxsb3cgbGVzcyB0aGFuIDUwJSB2YXJpYW5jZSBmcm9tIDEtMS0zLTEtMSBwcm9wb3J0aW9uc1xuICAgICAgICAgICAgcmV0dXJuIE1hdGguYWJzKG1vZHVsZVNpemUgLSBzdGF0ZUNvdW50WzBdKSA8IG1heFZhcmlhbmNlICYmXG4gICAgICAgICAgICAgICAgTWF0aC5hYnMobW9kdWxlU2l6ZSAtIHN0YXRlQ291bnRbMV0pIDwgbWF4VmFyaWFuY2UgJiZcbiAgICAgICAgICAgICAgICBNYXRoLmFicygzLjAgKiBtb2R1bGVTaXplIC0gc3RhdGVDb3VudFsyXSkgPCAzICogbWF4VmFyaWFuY2UgJiZcbiAgICAgICAgICAgICAgICBNYXRoLmFicyhtb2R1bGVTaXplIC0gc3RhdGVDb3VudFszXSkgPCBtYXhWYXJpYW5jZSAmJlxuICAgICAgICAgICAgICAgIE1hdGguYWJzKG1vZHVsZVNpemUgLSBzdGF0ZUNvdW50WzRdKSA8IG1heFZhcmlhbmNlO1xuICAgICAgICB9XG4gICAgICAgIGdldENyb3NzQ2hlY2tTdGF0ZUNvdW50KCkge1xuICAgICAgICAgICAgY29uc3QgY3Jvc3NDaGVja1N0YXRlQ291bnQgPSB0aGlzLmNyb3NzQ2hlY2tTdGF0ZUNvdW50O1xuICAgICAgICAgICAgY3Jvc3NDaGVja1N0YXRlQ291bnRbMF0gPSAwO1xuICAgICAgICAgICAgY3Jvc3NDaGVja1N0YXRlQ291bnRbMV0gPSAwO1xuICAgICAgICAgICAgY3Jvc3NDaGVja1N0YXRlQ291bnRbMl0gPSAwO1xuICAgICAgICAgICAgY3Jvc3NDaGVja1N0YXRlQ291bnRbM10gPSAwO1xuICAgICAgICAgICAgY3Jvc3NDaGVja1N0YXRlQ291bnRbNF0gPSAwO1xuICAgICAgICAgICAgcmV0dXJuIGNyb3NzQ2hlY2tTdGF0ZUNvdW50O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBZnRlciBhIHZlcnRpY2FsIGFuZCBob3Jpem9udGFsIHNjYW4gZmluZHMgYSBwb3RlbnRpYWwgZmluZGVyIHBhdHRlcm4sIHRoaXMgbWV0aG9kXG4gICAgICAgICAqIFwiY3Jvc3MtY3Jvc3MtY3Jvc3MtY2hlY2tzXCIgYnkgc2Nhbm5pbmcgZG93biBkaWFnb25hbGx5IHRocm91Z2ggdGhlIGNlbnRlciBvZiB0aGUgcG9zc2libGVcbiAgICAgICAgICogZmluZGVyIHBhdHRlcm4gdG8gc2VlIGlmIHRoZSBzYW1lIHByb3BvcnRpb24gaXMgZGV0ZWN0ZWQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBzdGFydEkgcm93IHdoZXJlIGEgZmluZGVyIHBhdHRlcm4gd2FzIGRldGVjdGVkXG4gICAgICAgICAqIEBwYXJhbSBjZW50ZXJKIGNlbnRlciBvZiB0aGUgc2VjdGlvbiB0aGF0IGFwcGVhcnMgdG8gY3Jvc3MgYSBmaW5kZXIgcGF0dGVyblxuICAgICAgICAgKiBAcGFyYW0gbWF4Q291bnQgbWF4aW11bSByZWFzb25hYmxlIG51bWJlciBvZiBtb2R1bGVzIHRoYXQgc2hvdWxkIGJlXG4gICAgICAgICAqICBvYnNlcnZlZCBpbiBhbnkgcmVhZGluZyBzdGF0ZSwgYmFzZWQgb24gdGhlIHJlc3VsdHMgb2YgdGhlIGhvcml6b250YWwgc2NhblxuICAgICAgICAgKiBAcGFyYW0gb3JpZ2luYWxTdGF0ZUNvdW50VG90YWwgVGhlIG9yaWdpbmFsIHN0YXRlIGNvdW50IHRvdGFsLlxuICAgICAgICAgKiBAcmV0dXJuIHRydWUgaWYgcHJvcG9ydGlvbnMgYXJlIHdpdGhpbmcgZXhwZWN0ZWQgbGltaXRzXG4gICAgICAgICAqL1xuICAgICAgICBjcm9zc0NoZWNrRGlhZ29uYWwoc3RhcnRJIC8qaW50Ki8sIGNlbnRlckogLyppbnQqLywgbWF4Q291bnQgLyppbnQqLywgb3JpZ2luYWxTdGF0ZUNvdW50VG90YWwgLyppbnQqLykge1xuICAgICAgICAgICAgY29uc3Qgc3RhdGVDb3VudCA9IHRoaXMuZ2V0Q3Jvc3NDaGVja1N0YXRlQ291bnQoKTtcbiAgICAgICAgICAgIC8vIFN0YXJ0IGNvdW50aW5nIHVwLCBsZWZ0IGZyb20gY2VudGVyIGZpbmRpbmcgYmxhY2sgY2VudGVyIG1hc3NcbiAgICAgICAgICAgIGxldCBpID0gMDtcbiAgICAgICAgICAgIGNvbnN0IGltYWdlID0gdGhpcy5pbWFnZTtcbiAgICAgICAgICAgIHdoaWxlIChzdGFydEkgPj0gaSAmJiBjZW50ZXJKID49IGkgJiYgaW1hZ2UuZ2V0KGNlbnRlckogLSBpLCBzdGFydEkgLSBpKSkge1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMl0rKztcbiAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RhcnRJIDwgaSB8fCBjZW50ZXJKIDwgaSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIENvbnRpbnVlIHVwLCBsZWZ0IGZpbmRpbmcgd2hpdGUgc3BhY2VcbiAgICAgICAgICAgIHdoaWxlIChzdGFydEkgPj0gaSAmJiBjZW50ZXJKID49IGkgJiYgIWltYWdlLmdldChjZW50ZXJKIC0gaSwgc3RhcnRJIC0gaSkgJiZcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzFdIDw9IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFsxXSsrO1xuICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIElmIGFscmVhZHkgdG9vIG1hbnkgbW9kdWxlcyBpbiB0aGlzIHN0YXRlIG9yIHJhbiBvZmYgdGhlIGVkZ2U6XG4gICAgICAgICAgICBpZiAoc3RhcnRJIDwgaSB8fCBjZW50ZXJKIDwgaSB8fCBzdGF0ZUNvdW50WzFdID4gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBDb250aW51ZSB1cCwgbGVmdCBmaW5kaW5nIGJsYWNrIGJvcmRlclxuICAgICAgICAgICAgd2hpbGUgKHN0YXJ0SSA+PSBpICYmIGNlbnRlckogPj0gaSAmJiBpbWFnZS5nZXQoY2VudGVySiAtIGksIHN0YXJ0SSAtIGkpICYmXG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFswXSA8PSBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMF0rKztcbiAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RhdGVDb3VudFswXSA+IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbWF4SSA9IGltYWdlLmdldEhlaWdodCgpO1xuICAgICAgICAgICAgY29uc3QgbWF4SiA9IGltYWdlLmdldFdpZHRoKCk7XG4gICAgICAgICAgICAvLyBOb3cgYWxzbyBjb3VudCBkb3duLCByaWdodCBmcm9tIGNlbnRlclxuICAgICAgICAgICAgaSA9IDE7XG4gICAgICAgICAgICB3aGlsZSAoc3RhcnRJICsgaSA8IG1heEkgJiYgY2VudGVySiArIGkgPCBtYXhKICYmIGltYWdlLmdldChjZW50ZXJKICsgaSwgc3RhcnRJICsgaSkpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzJdKys7XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gUmFuIG9mZiB0aGUgZWRnZT9cbiAgICAgICAgICAgIGlmIChzdGFydEkgKyBpID49IG1heEkgfHwgY2VudGVySiArIGkgPj0gbWF4Sikge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdoaWxlIChzdGFydEkgKyBpIDwgbWF4SSAmJiBjZW50ZXJKICsgaSA8IG1heEogJiYgIWltYWdlLmdldChjZW50ZXJKICsgaSwgc3RhcnRJICsgaSkgJiZcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzNdIDwgbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzNdKys7XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0YXJ0SSArIGkgPj0gbWF4SSB8fCBjZW50ZXJKICsgaSA+PSBtYXhKIHx8IHN0YXRlQ291bnRbM10gPj0gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aGlsZSAoc3RhcnRJICsgaSA8IG1heEkgJiYgY2VudGVySiArIGkgPCBtYXhKICYmIGltYWdlLmdldChjZW50ZXJKICsgaSwgc3RhcnRJICsgaSkgJiZcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzRdIDwgbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzRdKys7XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0YXRlQ291bnRbNF0gPj0gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBJZiB3ZSBmb3VuZCBhIGZpbmRlci1wYXR0ZXJuLWxpa2Ugc2VjdGlvbiwgYnV0IGl0cyBzaXplIGlzIG1vcmUgdGhhbiAxMDAlIGRpZmZlcmVudCB0aGFuXG4gICAgICAgICAgICAvLyB0aGUgb3JpZ2luYWwsIGFzc3VtZSBpdCdzIGEgZmFsc2UgcG9zaXRpdmVcbiAgICAgICAgICAgIGNvbnN0IHN0YXRlQ291bnRUb3RhbCA9IHN0YXRlQ291bnRbMF0gKyBzdGF0ZUNvdW50WzFdICsgc3RhdGVDb3VudFsyXSArIHN0YXRlQ291bnRbM10gKyBzdGF0ZUNvdW50WzRdO1xuICAgICAgICAgICAgcmV0dXJuIE1hdGguYWJzKHN0YXRlQ291bnRUb3RhbCAtIG9yaWdpbmFsU3RhdGVDb3VudFRvdGFsKSA8IDIgKiBvcmlnaW5hbFN0YXRlQ291bnRUb3RhbCAmJlxuICAgICAgICAgICAgICAgIEZpbmRlclBhdHRlcm5GaW5kZXIuZm91bmRQYXR0ZXJuQ3Jvc3Moc3RhdGVDb3VudCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkFmdGVyIGEgaG9yaXpvbnRhbCBzY2FuIGZpbmRzIGEgcG90ZW50aWFsIGZpbmRlciBwYXR0ZXJuLCB0aGlzIG1ldGhvZFxuICAgICAgICAgKiBcImNyb3NzLWNoZWNrc1wiIGJ5IHNjYW5uaW5nIGRvd24gdmVydGljYWxseSB0aHJvdWdoIHRoZSBjZW50ZXIgb2YgdGhlIHBvc3NpYmxlXG4gICAgICAgICAqIGZpbmRlciBwYXR0ZXJuIHRvIHNlZSBpZiB0aGUgc2FtZSBwcm9wb3J0aW9uIGlzIGRldGVjdGVkLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHN0YXJ0SSByb3cgd2hlcmUgYSBmaW5kZXIgcGF0dGVybiB3YXMgZGV0ZWN0ZWRcbiAgICAgICAgICogQHBhcmFtIGNlbnRlckogY2VudGVyIG9mIHRoZSBzZWN0aW9uIHRoYXQgYXBwZWFycyB0byBjcm9zcyBhIGZpbmRlciBwYXR0ZXJuXG4gICAgICAgICAqIEBwYXJhbSBtYXhDb3VudCBtYXhpbXVtIHJlYXNvbmFibGUgbnVtYmVyIG9mIG1vZHVsZXMgdGhhdCBzaG91bGQgYmVcbiAgICAgICAgICogb2JzZXJ2ZWQgaW4gYW55IHJlYWRpbmcgc3RhdGUsIGJhc2VkIG9uIHRoZSByZXN1bHRzIG9mIHRoZSBob3Jpem9udGFsIHNjYW5cbiAgICAgICAgICogQHJldHVybiB2ZXJ0aWNhbCBjZW50ZXIgb2YgZmluZGVyIHBhdHRlcm4sIG9yIHtAbGluayBGbG9hdCNOYU59IGlmIG5vdCBmb3VuZFxuICAgICAgICAgKi9cbiAgICAgICAgY3Jvc3NDaGVja1ZlcnRpY2FsKHN0YXJ0SSAvKmludCovLCBjZW50ZXJKIC8qaW50Ki8sIG1heENvdW50IC8qaW50Ki8sIG9yaWdpbmFsU3RhdGVDb3VudFRvdGFsIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IGltYWdlID0gdGhpcy5pbWFnZTtcbiAgICAgICAgICAgIGNvbnN0IG1heEkgPSBpbWFnZS5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IHN0YXRlQ291bnQgPSB0aGlzLmdldENyb3NzQ2hlY2tTdGF0ZUNvdW50KCk7XG4gICAgICAgICAgICAvLyBTdGFydCBjb3VudGluZyB1cCBmcm9tIGNlbnRlclxuICAgICAgICAgICAgbGV0IGkgPSBzdGFydEk7XG4gICAgICAgICAgICB3aGlsZSAoaSA+PSAwICYmIGltYWdlLmdldChjZW50ZXJKLCBpKSkge1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMl0rKztcbiAgICAgICAgICAgICAgICBpLS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaSA8IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2hpbGUgKGkgPj0gMCAmJiAhaW1hZ2UuZ2V0KGNlbnRlckosIGkpICYmIHN0YXRlQ291bnRbMV0gPD0gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzFdKys7XG4gICAgICAgICAgICAgICAgaS0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSWYgYWxyZWFkeSB0b28gbWFueSBtb2R1bGVzIGluIHRoaXMgc3RhdGUgb3IgcmFuIG9mZiB0aGUgZWRnZTpcbiAgICAgICAgICAgIGlmIChpIDwgMCB8fCBzdGF0ZUNvdW50WzFdID4gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2hpbGUgKGkgPj0gMCAmJiBpbWFnZS5nZXQoY2VudGVySiwgaSkgJiYgc3RhdGVDb3VudFswXSA8PSBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMF0rKztcbiAgICAgICAgICAgICAgICBpLS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RhdGVDb3VudFswXSA+IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE5vdyBhbHNvIGNvdW50IGRvd24gZnJvbSBjZW50ZXJcbiAgICAgICAgICAgIGkgPSBzdGFydEkgKyAxO1xuICAgICAgICAgICAgd2hpbGUgKGkgPCBtYXhJICYmIGltYWdlLmdldChjZW50ZXJKLCBpKSkge1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMl0rKztcbiAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaSA9PT0gbWF4SSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aGlsZSAoaSA8IG1heEkgJiYgIWltYWdlLmdldChjZW50ZXJKLCBpKSAmJiBzdGF0ZUNvdW50WzNdIDwgbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzNdKys7XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGkgPT09IG1heEkgfHwgc3RhdGVDb3VudFszXSA+PSBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aGlsZSAoaSA8IG1heEkgJiYgaW1hZ2UuZ2V0KGNlbnRlckosIGkpICYmIHN0YXRlQ291bnRbNF0gPCBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbNF0rKztcbiAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RhdGVDb3VudFs0XSA+PSBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBJZiB3ZSBmb3VuZCBhIGZpbmRlci1wYXR0ZXJuLWxpa2Ugc2VjdGlvbiwgYnV0IGl0cyBzaXplIGlzIG1vcmUgdGhhbiA0MCUgZGlmZmVyZW50IHRoYW5cbiAgICAgICAgICAgIC8vIHRoZSBvcmlnaW5hbCwgYXNzdW1lIGl0J3MgYSBmYWxzZSBwb3NpdGl2ZVxuICAgICAgICAgICAgY29uc3Qgc3RhdGVDb3VudFRvdGFsID0gc3RhdGVDb3VudFswXSArIHN0YXRlQ291bnRbMV0gKyBzdGF0ZUNvdW50WzJdICsgc3RhdGVDb3VudFszXSArXG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFs0XTtcbiAgICAgICAgICAgIGlmICg1ICogTWF0aC5hYnMoc3RhdGVDb3VudFRvdGFsIC0gb3JpZ2luYWxTdGF0ZUNvdW50VG90YWwpID49IDIgKiBvcmlnaW5hbFN0YXRlQ291bnRUb3RhbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gRmluZGVyUGF0dGVybkZpbmRlci5mb3VuZFBhdHRlcm5Dcm9zcyhzdGF0ZUNvdW50KSA/IEZpbmRlclBhdHRlcm5GaW5kZXIuY2VudGVyRnJvbUVuZChzdGF0ZUNvdW50LCBpKSA6IE5hTjtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+TGlrZSB7QGxpbmsgI2Nyb3NzQ2hlY2tWZXJ0aWNhbChpbnQsIGludCwgaW50LCBpbnQpfSwgYW5kIGluIGZhY3QgaXMgYmFzaWNhbGx5IGlkZW50aWNhbCxcbiAgICAgICAgICogZXhjZXB0IGl0IHJlYWRzIGhvcml6b250YWxseSBpbnN0ZWFkIG9mIHZlcnRpY2FsbHkuIFRoaXMgaXMgdXNlZCB0byBjcm9zcy1jcm9zc1xuICAgICAgICAgKiBjaGVjayBhIHZlcnRpY2FsIGNyb3NzIGNoZWNrIGFuZCBsb2NhdGUgdGhlIHJlYWwgY2VudGVyIG9mIHRoZSBhbGlnbm1lbnQgcGF0dGVybi48L3A+XG4gICAgICAgICAqL1xuICAgICAgICBjcm9zc0NoZWNrSG9yaXpvbnRhbChzdGFydEogLyppbnQqLywgY2VudGVySSAvKmludCovLCBtYXhDb3VudCAvKmludCovLCBvcmlnaW5hbFN0YXRlQ291bnRUb3RhbCAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBpbWFnZSA9IHRoaXMuaW1hZ2U7XG4gICAgICAgICAgICBjb25zdCBtYXhKID0gaW1hZ2UuZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGNvbnN0IHN0YXRlQ291bnQgPSB0aGlzLmdldENyb3NzQ2hlY2tTdGF0ZUNvdW50KCk7XG4gICAgICAgICAgICBsZXQgaiA9IHN0YXJ0SjtcbiAgICAgICAgICAgIHdoaWxlIChqID49IDAgJiYgaW1hZ2UuZ2V0KGosIGNlbnRlckkpKSB7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFsyXSsrO1xuICAgICAgICAgICAgICAgIGotLTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChqIDwgMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aGlsZSAoaiA+PSAwICYmICFpbWFnZS5nZXQoaiwgY2VudGVySSkgJiYgc3RhdGVDb3VudFsxXSA8PSBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMV0rKztcbiAgICAgICAgICAgICAgICBqLS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaiA8IDAgfHwgc3RhdGVDb3VudFsxXSA+IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdoaWxlIChqID49IDAgJiYgaW1hZ2UuZ2V0KGosIGNlbnRlckkpICYmIHN0YXRlQ291bnRbMF0gPD0gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzBdKys7XG4gICAgICAgICAgICAgICAgai0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0YXRlQ291bnRbMF0gPiBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBqID0gc3RhcnRKICsgMTtcbiAgICAgICAgICAgIHdoaWxlIChqIDwgbWF4SiAmJiBpbWFnZS5nZXQoaiwgY2VudGVySSkpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzJdKys7XG4gICAgICAgICAgICAgICAgaisrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGogPT09IG1heEopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2hpbGUgKGogPCBtYXhKICYmICFpbWFnZS5nZXQoaiwgY2VudGVySSkgJiYgc3RhdGVDb3VudFszXSA8IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFszXSsrO1xuICAgICAgICAgICAgICAgIGorKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChqID09PSBtYXhKIHx8IHN0YXRlQ291bnRbM10gPj0gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2hpbGUgKGogPCBtYXhKICYmIGltYWdlLmdldChqLCBjZW50ZXJJKSAmJiBzdGF0ZUNvdW50WzRdIDwgbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzRdKys7XG4gICAgICAgICAgICAgICAgaisrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0YXRlQ291bnRbNF0gPj0gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSWYgd2UgZm91bmQgYSBmaW5kZXItcGF0dGVybi1saWtlIHNlY3Rpb24sIGJ1dCBpdHMgc2l6ZSBpcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCB0aGFuXG4gICAgICAgICAgICAvLyB0aGUgb3JpZ2luYWwsIGFzc3VtZSBpdCdzIGEgZmFsc2UgcG9zaXRpdmVcbiAgICAgICAgICAgIGNvbnN0IHN0YXRlQ291bnRUb3RhbCA9IHN0YXRlQ291bnRbMF0gKyBzdGF0ZUNvdW50WzFdICsgc3RhdGVDb3VudFsyXSArIHN0YXRlQ291bnRbM10gK1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbNF07XG4gICAgICAgICAgICBpZiAoNSAqIE1hdGguYWJzKHN0YXRlQ291bnRUb3RhbCAtIG9yaWdpbmFsU3RhdGVDb3VudFRvdGFsKSA+PSBvcmlnaW5hbFN0YXRlQ291bnRUb3RhbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gRmluZGVyUGF0dGVybkZpbmRlci5mb3VuZFBhdHRlcm5Dcm9zcyhzdGF0ZUNvdW50KSA/IEZpbmRlclBhdHRlcm5GaW5kZXIuY2VudGVyRnJvbUVuZChzdGF0ZUNvdW50LCBqKSA6IE5hTjtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+VGhpcyBpcyBjYWxsZWQgd2hlbiBhIGhvcml6b250YWwgc2NhbiBmaW5kcyBhIHBvc3NpYmxlIGFsaWdubWVudCBwYXR0ZXJuLiBJdCB3aWxsXG4gICAgICAgICAqIGNyb3NzIGNoZWNrIHdpdGggYSB2ZXJ0aWNhbCBzY2FuLCBhbmQgaWYgc3VjY2Vzc2Z1bCwgd2lsbCwgYWgsIGNyb3NzLWNyb3NzLWNoZWNrXG4gICAgICAgICAqIHdpdGggYW5vdGhlciBob3Jpem9udGFsIHNjYW4uIFRoaXMgaXMgbmVlZGVkIHByaW1hcmlseSB0byBsb2NhdGUgdGhlIHJlYWwgaG9yaXpvbnRhbFxuICAgICAgICAgKiBjZW50ZXIgb2YgdGhlIHBhdHRlcm4gaW4gY2FzZXMgb2YgZXh0cmVtZSBza2V3LlxuICAgICAgICAgKiBBbmQgdGhlbiB3ZSBjcm9zcy1jcm9zcy1jcm9zcyBjaGVjayB3aXRoIGFub3RoZXIgZGlhZ29uYWwgc2Nhbi48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIDxwPklmIHRoYXQgc3VjY2VlZHMgdGhlIGZpbmRlciBwYXR0ZXJuIGxvY2F0aW9uIGlzIGFkZGVkIHRvIGEgbGlzdCB0aGF0IHRyYWNrc1xuICAgICAgICAgKiB0aGUgbnVtYmVyIG9mIHRpbWVzIGVhY2ggbG9jYXRpb24gaGFzIGJlZW4gbmVhcmx5LW1hdGNoZWQgYXMgYSBmaW5kZXIgcGF0dGVybi5cbiAgICAgICAgICogRWFjaCBhZGRpdGlvbmFsIGZpbmQgaXMgbW9yZSBldmlkZW5jZSB0aGF0IHRoZSBsb2NhdGlvbiBpcyBpbiBmYWN0IGEgZmluZGVyXG4gICAgICAgICAqIHBhdHRlcm4gY2VudGVyXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBzdGF0ZUNvdW50IHJlYWRpbmcgc3RhdGUgbW9kdWxlIGNvdW50cyBmcm9tIGhvcml6b250YWwgc2NhblxuICAgICAgICAgKiBAcGFyYW0gaSByb3cgd2hlcmUgZmluZGVyIHBhdHRlcm4gbWF5IGJlIGZvdW5kXG4gICAgICAgICAqIEBwYXJhbSBqIGVuZCBvZiBwb3NzaWJsZSBmaW5kZXIgcGF0dGVybiBpbiByb3dcbiAgICAgICAgICogQHBhcmFtIHB1cmVCYXJjb2RlIHRydWUgaWYgaW4gXCJwdXJlIGJhcmNvZGVcIiBtb2RlXG4gICAgICAgICAqIEByZXR1cm4gdHJ1ZSBpZiBhIGZpbmRlciBwYXR0ZXJuIGNhbmRpZGF0ZSB3YXMgZm91bmQgdGhpcyB0aW1lXG4gICAgICAgICAqL1xuICAgICAgICBoYW5kbGVQb3NzaWJsZUNlbnRlcihzdGF0ZUNvdW50LCBpIC8qaW50Ki8sIGogLyppbnQqLywgcHVyZUJhcmNvZGUpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0YXRlQ291bnRUb3RhbCA9IHN0YXRlQ291bnRbMF0gKyBzdGF0ZUNvdW50WzFdICsgc3RhdGVDb3VudFsyXSArIHN0YXRlQ291bnRbM10gK1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbNF07XG4gICAgICAgICAgICBsZXQgY2VudGVySiA9IEZpbmRlclBhdHRlcm5GaW5kZXIuY2VudGVyRnJvbUVuZChzdGF0ZUNvdW50LCBqKTtcbiAgICAgICAgICAgIGxldCBjZW50ZXJJID0gdGhpcy5jcm9zc0NoZWNrVmVydGljYWwoaSwgLyooaW50KSAqLyBNYXRoLmZsb29yKGNlbnRlckopLCBzdGF0ZUNvdW50WzJdLCBzdGF0ZUNvdW50VG90YWwpO1xuICAgICAgICAgICAgaWYgKCFpc05hTihjZW50ZXJJKSkge1xuICAgICAgICAgICAgICAgIC8vIFJlLWNyb3NzIGNoZWNrXG4gICAgICAgICAgICAgICAgY2VudGVySiA9IHRoaXMuY3Jvc3NDaGVja0hvcml6b250YWwoLyooaW50KSAqLyBNYXRoLmZsb29yKGNlbnRlckopLCAvKihpbnQpICovIE1hdGguZmxvb3IoY2VudGVySSksIHN0YXRlQ291bnRbMl0sIHN0YXRlQ291bnRUb3RhbCk7XG4gICAgICAgICAgICAgICAgaWYgKCFpc05hTihjZW50ZXJKKSAmJlxuICAgICAgICAgICAgICAgICAgICAoIXB1cmVCYXJjb2RlIHx8IHRoaXMuY3Jvc3NDaGVja0RpYWdvbmFsKC8qKGludCkgKi8gTWF0aC5mbG9vcihjZW50ZXJJKSwgLyooaW50KSAqLyBNYXRoLmZsb29yKGNlbnRlckopLCBzdGF0ZUNvdW50WzJdLCBzdGF0ZUNvdW50VG90YWwpKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBlc3RpbWF0ZWRNb2R1bGVTaXplID0gc3RhdGVDb3VudFRvdGFsIC8gNy4wO1xuICAgICAgICAgICAgICAgICAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9zc2libGVDZW50ZXJzID0gdGhpcy5wb3NzaWJsZUNlbnRlcnM7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGluZGV4ID0gMCwgbGVuZ3RoID0gcG9zc2libGVDZW50ZXJzLmxlbmd0aDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNlbnRlciA9IHBvc3NpYmxlQ2VudGVyc1tpbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBMb29rIGZvciBhYm91dCB0aGUgc2FtZSBjZW50ZXIgYW5kIG1vZHVsZSBzaXplOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNlbnRlci5hYm91dEVxdWFscyhlc3RpbWF0ZWRNb2R1bGVTaXplLCBjZW50ZXJJLCBjZW50ZXJKKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc3NpYmxlQ2VudGVyc1tpbmRleF0gPSBjZW50ZXIuY29tYmluZUVzdGltYXRlKGNlbnRlckksIGNlbnRlckosIGVzdGltYXRlZE1vZHVsZVNpemUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoIWZvdW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwb2ludCA9IG5ldyBGaW5kZXJQYXR0ZXJuJDEoY2VudGVySiwgY2VudGVySSwgZXN0aW1hdGVkTW9kdWxlU2l6ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NzaWJsZUNlbnRlcnMucHVzaChwb2ludCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5yZXN1bHRQb2ludENhbGxiYWNrICE9PSBudWxsICYmIHRoaXMucmVzdWx0UG9pbnRDYWxsYmFjayAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXN1bHRQb2ludENhbGxiYWNrLmZvdW5kUG9zc2libGVSZXN1bHRQb2ludChwb2ludCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIG51bWJlciBvZiByb3dzIHdlIGNvdWxkIHNhZmVseSBza2lwIGR1cmluZyBzY2FubmluZywgYmFzZWQgb24gdGhlIGZpcnN0XG4gICAgICAgICAqICAgICAgICAgdHdvIGZpbmRlciBwYXR0ZXJucyB0aGF0IGhhdmUgYmVlbiBsb2NhdGVkLiBJbiBzb21lIGNhc2VzIHRoZWlyIHBvc2l0aW9uIHdpbGxcbiAgICAgICAgICogICAgICAgICBhbGxvdyB1cyB0byBpbmZlciB0aGF0IHRoZSB0aGlyZCBwYXR0ZXJuIG11c3QgbGllIGJlbG93IGEgY2VydGFpbiBwb2ludCBmYXJ0aGVyXG4gICAgICAgICAqICAgICAgICAgZG93biBpbiB0aGUgaW1hZ2UuXG4gICAgICAgICAqL1xuICAgICAgICBmaW5kUm93U2tpcCgpIHtcbiAgICAgICAgICAgIGNvbnN0IG1heCA9IHRoaXMucG9zc2libGVDZW50ZXJzLmxlbmd0aDtcbiAgICAgICAgICAgIGlmIChtYXggPD0gMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGZpcnN0Q29uZmlybWVkQ2VudGVyID0gbnVsbDtcbiAgICAgICAgICAgIGZvciAoY29uc3QgY2VudGVyIG9mIHRoaXMucG9zc2libGVDZW50ZXJzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNlbnRlci5nZXRDb3VudCgpID49IEZpbmRlclBhdHRlcm5GaW5kZXIuQ0VOVEVSX1FVT1JVTSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZmlyc3RDb25maXJtZWRDZW50ZXIgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmlyc3RDb25maXJtZWRDZW50ZXIgPSBjZW50ZXI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBoYXZlIHR3byBjb25maXJtZWQgY2VudGVyc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSG93IGZhciBkb3duIGNhbiB3ZSBza2lwIGJlZm9yZSByZXN1bWluZyBsb29raW5nIGZvciB0aGUgbmV4dFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcGF0dGVybj8gSW4gdGhlIHdvcnN0IGNhc2UsIG9ubHkgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRpZmZlcmVuY2UgaW4gdGhlIHggLyB5IGNvb3JkaW5hdGVzIG9mIHRoZSB0d28gY2VudGVycy5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgdGhlIGNhc2Ugd2hlcmUgeW91IGZpbmQgdG9wIGxlZnQgbGFzdC5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaGFzU2tpcHBlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gLyooaW50KSAqLyBNYXRoLmZsb29yKChNYXRoLmFicyhmaXJzdENvbmZpcm1lZENlbnRlci5nZXRYKCkgLSBjZW50ZXIuZ2V0WCgpKSAtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5hYnMoZmlyc3RDb25maXJtZWRDZW50ZXIuZ2V0WSgpIC0gY2VudGVyLmdldFkoKSkpIC8gMik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB0cnVlIGlmZiB3ZSBoYXZlIGZvdW5kIGF0IGxlYXN0IDMgZmluZGVyIHBhdHRlcm5zIHRoYXQgaGF2ZSBiZWVuIGRldGVjdGVkXG4gICAgICAgICAqICAgICAgICAgYXQgbGVhc3Qge0BsaW5rICNDRU5URVJfUVVPUlVNfSB0aW1lcyBlYWNoLCBhbmQsIHRoZSBlc3RpbWF0ZWQgbW9kdWxlIHNpemUgb2YgdGhlXG4gICAgICAgICAqICAgICAgICAgY2FuZGlkYXRlcyBpcyBcInByZXR0eSBzaW1pbGFyXCJcbiAgICAgICAgICovXG4gICAgICAgIGhhdmVNdWx0aXBseUNvbmZpcm1lZENlbnRlcnMoKSB7XG4gICAgICAgICAgICBsZXQgY29uZmlybWVkQ291bnQgPSAwO1xuICAgICAgICAgICAgbGV0IHRvdGFsTW9kdWxlU2l6ZSA9IDAuMDtcbiAgICAgICAgICAgIGNvbnN0IG1heCA9IHRoaXMucG9zc2libGVDZW50ZXJzLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcGF0dGVybiBvZiB0aGlzLnBvc3NpYmxlQ2VudGVycykge1xuICAgICAgICAgICAgICAgIGlmIChwYXR0ZXJuLmdldENvdW50KCkgPj0gRmluZGVyUGF0dGVybkZpbmRlci5DRU5URVJfUVVPUlVNKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbmZpcm1lZENvdW50Kys7XG4gICAgICAgICAgICAgICAgICAgIHRvdGFsTW9kdWxlU2l6ZSArPSBwYXR0ZXJuLmdldEVzdGltYXRlZE1vZHVsZVNpemUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29uZmlybWVkQ291bnQgPCAzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gT0ssIHdlIGhhdmUgYXQgbGVhc3QgMyBjb25maXJtZWQgY2VudGVycywgYnV0LCBpdCdzIHBvc3NpYmxlIHRoYXQgb25lIGlzIGEgXCJmYWxzZSBwb3NpdGl2ZVwiXG4gICAgICAgICAgICAvLyBhbmQgdGhhdCB3ZSBuZWVkIHRvIGtlZXAgbG9va2luZy4gV2UgZGV0ZWN0IHRoaXMgYnkgYXNraW5nIGlmIHRoZSBlc3RpbWF0ZWQgbW9kdWxlIHNpemVzXG4gICAgICAgICAgICAvLyB2YXJ5IHRvbyBtdWNoLiBXZSBhcmJpdHJhcmlseSBzYXkgdGhhdCB3aGVuIHRoZSB0b3RhbCBkZXZpYXRpb24gZnJvbSBhdmVyYWdlIGV4Y2VlZHNcbiAgICAgICAgICAgIC8vIDUlIG9mIHRoZSB0b3RhbCBtb2R1bGUgc2l6ZSBlc3RpbWF0ZXMsIGl0J3MgdG9vIG11Y2guXG4gICAgICAgICAgICBjb25zdCBhdmVyYWdlID0gdG90YWxNb2R1bGVTaXplIC8gbWF4O1xuICAgICAgICAgICAgbGV0IHRvdGFsRGV2aWF0aW9uID0gMC4wO1xuICAgICAgICAgICAgZm9yIChjb25zdCBwYXR0ZXJuIG9mIHRoaXMucG9zc2libGVDZW50ZXJzKSB7XG4gICAgICAgICAgICAgICAgdG90YWxEZXZpYXRpb24gKz0gTWF0aC5hYnMocGF0dGVybi5nZXRFc3RpbWF0ZWRNb2R1bGVTaXplKCkgLSBhdmVyYWdlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0b3RhbERldmlhdGlvbiA8PSAwLjA1ICogdG90YWxNb2R1bGVTaXplO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHRoZSAzIGJlc3Qge0BsaW5rIEZpbmRlclBhdHRlcm59cyBmcm9tIG91ciBsaXN0IG9mIGNhbmRpZGF0ZXMuIFRoZSBcImJlc3RcIiBhcmVcbiAgICAgICAgICogICAgICAgICB0aG9zZSB0aGF0IGhhdmUgYmVlbiBkZXRlY3RlZCBhdCBsZWFzdCB7QGxpbmsgI0NFTlRFUl9RVU9SVU19IHRpbWVzLCBhbmQgd2hvc2UgbW9kdWxlXG4gICAgICAgICAqICAgICAgICAgc2l6ZSBkaWZmZXJzIGZyb20gdGhlIGF2ZXJhZ2UgYW1vbmcgdGhvc2UgcGF0dGVybnMgdGhlIGxlYXN0XG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gaWYgMyBzdWNoIGZpbmRlciBwYXR0ZXJucyBkbyBub3QgZXhpc3RcbiAgICAgICAgICovXG4gICAgICAgIHNlbGVjdEJlc3RQYXR0ZXJucygpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0U2l6ZSA9IHRoaXMucG9zc2libGVDZW50ZXJzLmxlbmd0aDtcbiAgICAgICAgICAgIGlmIChzdGFydFNpemUgPCAzKSB7XG4gICAgICAgICAgICAgICAgLy8gQ291bGRuJ3QgZmluZCBlbm91Z2ggZmluZGVyIHBhdHRlcm5zXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBwb3NzaWJsZUNlbnRlcnMgPSB0aGlzLnBvc3NpYmxlQ2VudGVycztcbiAgICAgICAgICAgIGxldCBhdmVyYWdlO1xuICAgICAgICAgICAgLy8gRmlsdGVyIG91dGxpZXIgcG9zc2liaWxpdGllcyB3aG9zZSBtb2R1bGUgc2l6ZSBpcyB0b28gZGlmZmVyZW50XG4gICAgICAgICAgICBpZiAoc3RhcnRTaXplID4gMykge1xuICAgICAgICAgICAgICAgIC8vIEJ1dCB3ZSBjYW4gb25seSBhZmZvcmQgdG8gZG8gc28gaWYgd2UgaGF2ZSBhdCBsZWFzdCA0IHBvc3NpYmlsaXRpZXMgdG8gY2hvb3NlIGZyb21cbiAgICAgICAgICAgICAgICBsZXQgdG90YWxNb2R1bGVTaXplID0gMC4wO1xuICAgICAgICAgICAgICAgIGxldCBzcXVhcmUgPSAwLjA7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBjZW50ZXIgb2YgdGhpcy5wb3NzaWJsZUNlbnRlcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IGNlbnRlci5nZXRFc3RpbWF0ZWRNb2R1bGVTaXplKCk7XG4gICAgICAgICAgICAgICAgICAgIHRvdGFsTW9kdWxlU2l6ZSArPSBzaXplO1xuICAgICAgICAgICAgICAgICAgICBzcXVhcmUgKz0gc2l6ZSAqIHNpemU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGF2ZXJhZ2UgPSB0b3RhbE1vZHVsZVNpemUgLyBzdGFydFNpemU7XG4gICAgICAgICAgICAgICAgbGV0IHN0ZERldiA9IE1hdGguc3FydChzcXVhcmUgLyBzdGFydFNpemUgLSBhdmVyYWdlICogYXZlcmFnZSk7XG4gICAgICAgICAgICAgICAgcG9zc2libGVDZW50ZXJzLnNvcnQoXG4gICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICogPHA+T3JkZXJzIGJ5IGZ1cnRoZXN0IGZyb20gYXZlcmFnZTwvcD5cbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAvLyBGdXJ0aGVzdEZyb21BdmVyYWdlQ29tcGFyYXRvciBpbXBsZW1lbnRzIENvbXBhcmF0b3I8RmluZGVyUGF0dGVybj5cbiAgICAgICAgICAgICAgICAoY2VudGVyMSwgY2VudGVyMikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkQSA9IE1hdGguYWJzKGNlbnRlcjIuZ2V0RXN0aW1hdGVkTW9kdWxlU2l6ZSgpIC0gYXZlcmFnZSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGRCID0gTWF0aC5hYnMoY2VudGVyMS5nZXRFc3RpbWF0ZWRNb2R1bGVTaXplKCkgLSBhdmVyYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRBIDwgZEIgPyAtMSA6IGRBID4gZEIgPyAxIDogMDtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBjb25zdCBsaW1pdCA9IE1hdGgubWF4KDAuMiAqIGF2ZXJhZ2UsIHN0ZERldik7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwb3NzaWJsZUNlbnRlcnMubGVuZ3RoICYmIHBvc3NpYmxlQ2VudGVycy5sZW5ndGggPiAzOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGF0dGVybiA9IHBvc3NpYmxlQ2VudGVyc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKE1hdGguYWJzKHBhdHRlcm4uZ2V0RXN0aW1hdGVkTW9kdWxlU2l6ZSgpIC0gYXZlcmFnZSkgPiBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zc2libGVDZW50ZXJzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGktLTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChwb3NzaWJsZUNlbnRlcnMubGVuZ3RoID4gMykge1xuICAgICAgICAgICAgICAgIC8vIFRocm93IGF3YXkgYWxsIGJ1dCB0aG9zZSBmaXJzdCBzaXplIGNhbmRpZGF0ZSBwb2ludHMgd2UgZm91bmQuXG4gICAgICAgICAgICAgICAgbGV0IHRvdGFsTW9kdWxlU2l6ZSA9IDAuMDtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHBvc3NpYmxlQ2VudGVyIG9mIHBvc3NpYmxlQ2VudGVycykge1xuICAgICAgICAgICAgICAgICAgICB0b3RhbE1vZHVsZVNpemUgKz0gcG9zc2libGVDZW50ZXIuZ2V0RXN0aW1hdGVkTW9kdWxlU2l6ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhdmVyYWdlID0gdG90YWxNb2R1bGVTaXplIC8gcG9zc2libGVDZW50ZXJzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBwb3NzaWJsZUNlbnRlcnMuc29ydChcbiAgICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICAgKiA8cD5PcmRlcnMgYnkge0BsaW5rIEZpbmRlclBhdHRlcm4jZ2V0Q291bnQoKX0sIGRlc2NlbmRpbmcuPC9wPlxuICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgIC8vIENlbnRlckNvbXBhcmF0b3IgaW1wbGVtZW50cyBDb21wYXJhdG9yPEZpbmRlclBhdHRlcm4+XG4gICAgICAgICAgICAgICAgKGNlbnRlcjEsIGNlbnRlcjIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNlbnRlcjIuZ2V0Q291bnQoKSA9PT0gY2VudGVyMS5nZXRDb3VudCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkQSA9IE1hdGguYWJzKGNlbnRlcjIuZ2V0RXN0aW1hdGVkTW9kdWxlU2l6ZSgpIC0gYXZlcmFnZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkQiA9IE1hdGguYWJzKGNlbnRlcjEuZ2V0RXN0aW1hdGVkTW9kdWxlU2l6ZSgpIC0gYXZlcmFnZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZEEgPCBkQiA/IDEgOiBkQSA+IGRCID8gLTEgOiAwO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNlbnRlcjIuZ2V0Q291bnQoKSAtIGNlbnRlcjEuZ2V0Q291bnQoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHBvc3NpYmxlQ2VudGVycy5zcGxpY2UoMyk7IC8vIHRoaXMgaXMgbm90IHJlYWx5IG5lY2Vzc2FyeSBhcyB3ZSBvbmx5IHJldHVybiBmaXJzdCAzIGFueXdheVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICBwb3NzaWJsZUNlbnRlcnNbMF0sXG4gICAgICAgICAgICAgICAgcG9zc2libGVDZW50ZXJzWzFdLFxuICAgICAgICAgICAgICAgIHBvc3NpYmxlQ2VudGVyc1syXVxuICAgICAgICAgICAgXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBGaW5kZXJQYXR0ZXJuRmluZGVyLkNFTlRFUl9RVU9SVU0gPSAyO1xuICAgIEZpbmRlclBhdHRlcm5GaW5kZXIuTUlOX1NLSVAgPSAzOyAvLyAxIHBpeGVsL21vZHVsZSB0aW1lcyAzIG1vZHVsZXMvY2VudGVyXG4gICAgRmluZGVyUGF0dGVybkZpbmRlci5NQVhfTU9EVUxFUyA9IDU3OyAvLyBzdXBwb3J0IHVwIHRvIHZlcnNpb24gMTAgZm9yIG1vYmlsZSBjbGllbnRzXG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5NYXA7Ki9cbiAgICAvKipcbiAgICAgKiA8cD5FbmNhcHN1bGF0ZXMgbG9naWMgdGhhdCBjYW4gZGV0ZWN0IGEgUVIgQ29kZSBpbiBhbiBpbWFnZSwgZXZlbiBpZiB0aGUgUVIgQ29kZVxuICAgICAqIGlzIHJvdGF0ZWQgb3Igc2tld2VkLCBvciBwYXJ0aWFsbHkgb2JzY3VyZWQuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBEZXRlY3RvciQyIHtcbiAgICAgICAgY29uc3RydWN0b3IoaW1hZ2UpIHtcbiAgICAgICAgICAgIHRoaXMuaW1hZ2UgPSBpbWFnZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRJbWFnZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmltYWdlO1xuICAgICAgICB9XG4gICAgICAgIGdldFJlc3VsdFBvaW50Q2FsbGJhY2soKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZXN1bHRQb2ludENhbGxiYWNrO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5EZXRlY3RzIGEgUVIgQ29kZSBpbiBhbiBpbWFnZS48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4ge0BsaW5rIERldGVjdG9yUmVzdWx0fSBlbmNhcHN1bGF0aW5nIHJlc3VsdHMgb2YgZGV0ZWN0aW5nIGEgUVIgQ29kZVxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIFFSIENvZGUgY2Fubm90IGJlIGZvdW5kXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uIGlmIGEgUVIgQ29kZSBjYW5ub3QgYmUgZGVjb2RlZFxuICAgICAgICAgKi9cbiAgICAgICAgLy8gcHVibGljIGRldGVjdCgpOiBEZXRlY3RvclJlc3VsdCAvKnRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiwgRm9ybWF0RXhjZXB0aW9uKi8ge1xuICAgICAgICAvLyAgIHJldHVybiBkZXRlY3QobnVsbClcbiAgICAgICAgLy8gfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+RGV0ZWN0cyBhIFFSIENvZGUgaW4gYW4gaW1hZ2UuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gaGludHMgb3B0aW9uYWwgaGludHMgdG8gZGV0ZWN0b3JcbiAgICAgICAgICogQHJldHVybiB7QGxpbmsgRGV0ZWN0b3JSZXN1bHR9IGVuY2Fwc3VsYXRpbmcgcmVzdWx0cyBvZiBkZXRlY3RpbmcgYSBRUiBDb2RlXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gaWYgUVIgQ29kZSBjYW5ub3QgYmUgZm91bmRcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb24gaWYgYSBRUiBDb2RlIGNhbm5vdCBiZSBkZWNvZGVkXG4gICAgICAgICAqL1xuICAgICAgICBkZXRlY3QoaGludHMpIHtcbiAgICAgICAgICAgIHRoaXMucmVzdWx0UG9pbnRDYWxsYmFjayA9IChoaW50cyA9PT0gbnVsbCB8fCBoaW50cyA9PT0gdW5kZWZpbmVkKSA/IG51bGwgOlxuICAgICAgICAgICAgICAgIC8qKFJlc3VsdFBvaW50Q2FsbGJhY2spICovIGhpbnRzLmdldChEZWNvZGVIaW50VHlwZSQxLk5FRURfUkVTVUxUX1BPSU5UX0NBTExCQUNLKTtcbiAgICAgICAgICAgIGNvbnN0IGZpbmRlciA9IG5ldyBGaW5kZXJQYXR0ZXJuRmluZGVyKHRoaXMuaW1hZ2UsIHRoaXMucmVzdWx0UG9pbnRDYWxsYmFjayk7XG4gICAgICAgICAgICBjb25zdCBpbmZvID0gZmluZGVyLmZpbmQoaGludHMpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJvY2Vzc0ZpbmRlclBhdHRlcm5JbmZvKGluZm8pO1xuICAgICAgICB9XG4gICAgICAgIHByb2Nlc3NGaW5kZXJQYXR0ZXJuSW5mbyhpbmZvKSB7XG4gICAgICAgICAgICBjb25zdCB0b3BMZWZ0ID0gaW5mby5nZXRUb3BMZWZ0KCk7XG4gICAgICAgICAgICBjb25zdCB0b3BSaWdodCA9IGluZm8uZ2V0VG9wUmlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IGJvdHRvbUxlZnQgPSBpbmZvLmdldEJvdHRvbUxlZnQoKTtcbiAgICAgICAgICAgIGNvbnN0IG1vZHVsZVNpemUgPSB0aGlzLmNhbGN1bGF0ZU1vZHVsZVNpemUodG9wTGVmdCwgdG9wUmlnaHQsIGJvdHRvbUxlZnQpO1xuICAgICAgICAgICAgaWYgKG1vZHVsZVNpemUgPCAxLjApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oJ05vIHBhdHRlcm4gZm91bmQgaW4gcHJvY2Nlc3MgZmluZGVyLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZGltZW5zaW9uID0gRGV0ZWN0b3IkMi5jb21wdXRlRGltZW5zaW9uKHRvcExlZnQsIHRvcFJpZ2h0LCBib3R0b21MZWZ0LCBtb2R1bGVTaXplKTtcbiAgICAgICAgICAgIGNvbnN0IHByb3Zpc2lvbmFsVmVyc2lvbiA9IFZlcnNpb24kMS5nZXRQcm92aXNpb25hbFZlcnNpb25Gb3JEaW1lbnNpb24oZGltZW5zaW9uKTtcbiAgICAgICAgICAgIGNvbnN0IG1vZHVsZXNCZXR3ZWVuRlBDZW50ZXJzID0gcHJvdmlzaW9uYWxWZXJzaW9uLmdldERpbWVuc2lvbkZvclZlcnNpb24oKSAtIDc7XG4gICAgICAgICAgICBsZXQgYWxpZ25tZW50UGF0dGVybiA9IG51bGw7XG4gICAgICAgICAgICAvLyBBbnl0aGluZyBhYm92ZSB2ZXJzaW9uIDEgaGFzIGFuIGFsaWdubWVudCBwYXR0ZXJuXG4gICAgICAgICAgICBpZiAocHJvdmlzaW9uYWxWZXJzaW9uLmdldEFsaWdubWVudFBhdHRlcm5DZW50ZXJzKCkubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIC8vIEd1ZXNzIHdoZXJlIGEgXCJib3R0b20gcmlnaHRcIiBmaW5kZXIgcGF0dGVybiB3b3VsZCBoYXZlIGJlZW5cbiAgICAgICAgICAgICAgICBjb25zdCBib3R0b21SaWdodFggPSB0b3BSaWdodC5nZXRYKCkgLSB0b3BMZWZ0LmdldFgoKSArIGJvdHRvbUxlZnQuZ2V0WCgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGJvdHRvbVJpZ2h0WSA9IHRvcFJpZ2h0LmdldFkoKSAtIHRvcExlZnQuZ2V0WSgpICsgYm90dG9tTGVmdC5nZXRZKCk7XG4gICAgICAgICAgICAgICAgLy8gRXN0aW1hdGUgdGhhdCBhbGlnbm1lbnQgcGF0dGVybiBpcyBjbG9zZXIgYnkgMyBtb2R1bGVzXG4gICAgICAgICAgICAgICAgLy8gZnJvbSBcImJvdHRvbSByaWdodFwiIHRvIGtub3duIHRvcCBsZWZ0IGxvY2F0aW9uXG4gICAgICAgICAgICAgICAgY29uc3QgY29ycmVjdGlvblRvVG9wTGVmdCA9IDEuMCAtIDMuMCAvIG1vZHVsZXNCZXR3ZWVuRlBDZW50ZXJzO1xuICAgICAgICAgICAgICAgIGNvbnN0IGVzdEFsaWdubWVudFggPSAvKihpbnQpICovIE1hdGguZmxvb3IodG9wTGVmdC5nZXRYKCkgKyBjb3JyZWN0aW9uVG9Ub3BMZWZ0ICogKGJvdHRvbVJpZ2h0WCAtIHRvcExlZnQuZ2V0WCgpKSk7XG4gICAgICAgICAgICAgICAgY29uc3QgZXN0QWxpZ25tZW50WSA9IC8qKGludCkgKi8gTWF0aC5mbG9vcih0b3BMZWZ0LmdldFkoKSArIGNvcnJlY3Rpb25Ub1RvcExlZnQgKiAoYm90dG9tUmlnaHRZIC0gdG9wTGVmdC5nZXRZKCkpKTtcbiAgICAgICAgICAgICAgICAvLyBLaW5kIG9mIGFyYml0cmFyeSAtLSBleHBhbmQgc2VhcmNoIHJhZGl1cyBiZWZvcmUgZ2l2aW5nIHVwXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDQ7IGkgPD0gMTY7IGkgPDw9IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsaWdubWVudFBhdHRlcm4gPSB0aGlzLmZpbmRBbGlnbm1lbnRJblJlZ2lvbihtb2R1bGVTaXplLCBlc3RBbGlnbm1lbnRYLCBlc3RBbGlnbm1lbnRZLCBpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNhdGNoIChyZSAvKk5vdEZvdW5kRXhjZXB0aW9uKi8pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghKHJlIGluc3RhbmNlb2YgTm90Rm91bmRFeGNlcHRpb24pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgcmU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0cnkgbmV4dCByb3VuZFxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIElmIHdlIGRpZG4ndCBmaW5kIGFsaWdubWVudCBwYXR0ZXJuLi4uIHdlbGwgdHJ5IGFueXdheSB3aXRob3V0IGl0XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCB0cmFuc2Zvcm0gPSBEZXRlY3RvciQyLmNyZWF0ZVRyYW5zZm9ybSh0b3BMZWZ0LCB0b3BSaWdodCwgYm90dG9tTGVmdCwgYWxpZ25tZW50UGF0dGVybiwgZGltZW5zaW9uKTtcbiAgICAgICAgICAgIGNvbnN0IGJpdHMgPSBEZXRlY3RvciQyLnNhbXBsZUdyaWQodGhpcy5pbWFnZSwgdHJhbnNmb3JtLCBkaW1lbnNpb24pO1xuICAgICAgICAgICAgbGV0IHBvaW50cztcbiAgICAgICAgICAgIGlmIChhbGlnbm1lbnRQYXR0ZXJuID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcG9pbnRzID0gW2JvdHRvbUxlZnQsIHRvcExlZnQsIHRvcFJpZ2h0XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHBvaW50cyA9IFtib3R0b21MZWZ0LCB0b3BMZWZ0LCB0b3BSaWdodCwgYWxpZ25tZW50UGF0dGVybl07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IERldGVjdG9yUmVzdWx0KGJpdHMsIHBvaW50cyk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGNyZWF0ZVRyYW5zZm9ybSh0b3BMZWZ0LCB0b3BSaWdodCwgYm90dG9tTGVmdCwgYWxpZ25tZW50UGF0dGVybiwgZGltZW5zaW9uIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IGRpbU1pbnVzVGhyZWUgPSBkaW1lbnNpb24gLSAzLjU7XG4gICAgICAgICAgICBsZXQgYm90dG9tUmlnaHRYOyAvKmZsb2F0Ki9cbiAgICAgICAgICAgIGxldCBib3R0b21SaWdodFk7IC8qZmxvYXQqL1xuICAgICAgICAgICAgbGV0IHNvdXJjZUJvdHRvbVJpZ2h0WDsgLypmbG9hdCovXG4gICAgICAgICAgICBsZXQgc291cmNlQm90dG9tUmlnaHRZOyAvKmZsb2F0Ki9cbiAgICAgICAgICAgIGlmIChhbGlnbm1lbnRQYXR0ZXJuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgYm90dG9tUmlnaHRYID0gYWxpZ25tZW50UGF0dGVybi5nZXRYKCk7XG4gICAgICAgICAgICAgICAgYm90dG9tUmlnaHRZID0gYWxpZ25tZW50UGF0dGVybi5nZXRZKCk7XG4gICAgICAgICAgICAgICAgc291cmNlQm90dG9tUmlnaHRYID0gZGltTWludXNUaHJlZSAtIDMuMDtcbiAgICAgICAgICAgICAgICBzb3VyY2VCb3R0b21SaWdodFkgPSBzb3VyY2VCb3R0b21SaWdodFg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBEb24ndCBoYXZlIGFuIGFsaWdubWVudCBwYXR0ZXJuLCBqdXN0IG1ha2UgdXAgdGhlIGJvdHRvbS1yaWdodCBwb2ludFxuICAgICAgICAgICAgICAgIGJvdHRvbVJpZ2h0WCA9ICh0b3BSaWdodC5nZXRYKCkgLSB0b3BMZWZ0LmdldFgoKSkgKyBib3R0b21MZWZ0LmdldFgoKTtcbiAgICAgICAgICAgICAgICBib3R0b21SaWdodFkgPSAodG9wUmlnaHQuZ2V0WSgpIC0gdG9wTGVmdC5nZXRZKCkpICsgYm90dG9tTGVmdC5nZXRZKCk7XG4gICAgICAgICAgICAgICAgc291cmNlQm90dG9tUmlnaHRYID0gZGltTWludXNUaHJlZTtcbiAgICAgICAgICAgICAgICBzb3VyY2VCb3R0b21SaWdodFkgPSBkaW1NaW51c1RocmVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIFBlcnNwZWN0aXZlVHJhbnNmb3JtLnF1YWRyaWxhdGVyYWxUb1F1YWRyaWxhdGVyYWwoMy41LCAzLjUsIGRpbU1pbnVzVGhyZWUsIDMuNSwgc291cmNlQm90dG9tUmlnaHRYLCBzb3VyY2VCb3R0b21SaWdodFksIDMuNSwgZGltTWludXNUaHJlZSwgdG9wTGVmdC5nZXRYKCksIHRvcExlZnQuZ2V0WSgpLCB0b3BSaWdodC5nZXRYKCksIHRvcFJpZ2h0LmdldFkoKSwgYm90dG9tUmlnaHRYLCBib3R0b21SaWdodFksIGJvdHRvbUxlZnQuZ2V0WCgpLCBib3R0b21MZWZ0LmdldFkoKSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHNhbXBsZUdyaWQoaW1hZ2UsIHRyYW5zZm9ybSwgZGltZW5zaW9uIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IHNhbXBsZXIgPSBHcmlkU2FtcGxlckluc3RhbmNlLmdldEluc3RhbmNlKCk7XG4gICAgICAgICAgICByZXR1cm4gc2FtcGxlci5zYW1wbGVHcmlkV2l0aFRyYW5zZm9ybShpbWFnZSwgZGltZW5zaW9uLCBkaW1lbnNpb24sIHRyYW5zZm9ybSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkNvbXB1dGVzIHRoZSBkaW1lbnNpb24gKG51bWJlciBvZiBtb2R1bGVzIG9uIGEgc2l6ZSkgb2YgdGhlIFFSIENvZGUgYmFzZWQgb24gdGhlIHBvc2l0aW9uXG4gICAgICAgICAqIG9mIHRoZSBmaW5kZXIgcGF0dGVybnMgYW5kIGVzdGltYXRlZCBtb2R1bGUgc2l6ZS48L3A+XG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgY29tcHV0ZURpbWVuc2lvbih0b3BMZWZ0LCB0b3BSaWdodCwgYm90dG9tTGVmdCwgbW9kdWxlU2l6ZSAvKmZsb2F0Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IHRsdHJDZW50ZXJzRGltZW5zaW9uID0gTWF0aFV0aWxzLnJvdW5kKFJlc3VsdFBvaW50LmRpc3RhbmNlKHRvcExlZnQsIHRvcFJpZ2h0KSAvIG1vZHVsZVNpemUpO1xuICAgICAgICAgICAgY29uc3QgdGxibENlbnRlcnNEaW1lbnNpb24gPSBNYXRoVXRpbHMucm91bmQoUmVzdWx0UG9pbnQuZGlzdGFuY2UodG9wTGVmdCwgYm90dG9tTGVmdCkgLyBtb2R1bGVTaXplKTtcbiAgICAgICAgICAgIGxldCBkaW1lbnNpb24gPSBNYXRoLmZsb29yKCh0bHRyQ2VudGVyc0RpbWVuc2lvbiArIHRsYmxDZW50ZXJzRGltZW5zaW9uKSAvIDIpICsgNztcbiAgICAgICAgICAgIHN3aXRjaCAoZGltZW5zaW9uICYgMHgwMykgeyAvLyBtb2QgNFxuICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgZGltZW5zaW9uKys7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIC8vIDE/IGRvIG5vdGhpbmdcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIGRpbWVuc2lvbi0tO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbignRGltZW5zaW9ucyBjb3VsZCBiZSBub3QgZm91bmQuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZGltZW5zaW9uO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5Db21wdXRlcyBhbiBhdmVyYWdlIGVzdGltYXRlZCBtb2R1bGUgc2l6ZSBiYXNlZCBvbiBlc3RpbWF0ZWQgZGVyaXZlZCBmcm9tIHRoZSBwb3NpdGlvbnNcbiAgICAgICAgICogb2YgdGhlIHRocmVlIGZpbmRlciBwYXR0ZXJucy48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB0b3BMZWZ0IGRldGVjdGVkIHRvcC1sZWZ0IGZpbmRlciBwYXR0ZXJuIGNlbnRlclxuICAgICAgICAgKiBAcGFyYW0gdG9wUmlnaHQgZGV0ZWN0ZWQgdG9wLXJpZ2h0IGZpbmRlciBwYXR0ZXJuIGNlbnRlclxuICAgICAgICAgKiBAcGFyYW0gYm90dG9tTGVmdCBkZXRlY3RlZCBib3R0b20tbGVmdCBmaW5kZXIgcGF0dGVybiBjZW50ZXJcbiAgICAgICAgICogQHJldHVybiBlc3RpbWF0ZWQgbW9kdWxlIHNpemVcbiAgICAgICAgICovXG4gICAgICAgIGNhbGN1bGF0ZU1vZHVsZVNpemUodG9wTGVmdCwgdG9wUmlnaHQsIGJvdHRvbUxlZnQpIHtcbiAgICAgICAgICAgIC8vIFRha2UgdGhlIGF2ZXJhZ2VcbiAgICAgICAgICAgIHJldHVybiAodGhpcy5jYWxjdWxhdGVNb2R1bGVTaXplT25lV2F5KHRvcExlZnQsIHRvcFJpZ2h0KSArXG4gICAgICAgICAgICAgICAgdGhpcy5jYWxjdWxhdGVNb2R1bGVTaXplT25lV2F5KHRvcExlZnQsIGJvdHRvbUxlZnQpKSAvIDIuMDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+RXN0aW1hdGVzIG1vZHVsZSBzaXplIGJhc2VkIG9uIHR3byBmaW5kZXIgcGF0dGVybnMgLS0gaXQgdXNlc1xuICAgICAgICAgKiB7QGxpbmsgI3NpemVPZkJsYWNrV2hpdGVCbGFja1J1bkJvdGhXYXlzKGludCwgaW50LCBpbnQsIGludCl9IHRvIGZpZ3VyZSB0aGVcbiAgICAgICAgICogd2lkdGggb2YgZWFjaCwgbWVhc3VyaW5nIGFsb25nIHRoZSBheGlzIGJldHdlZW4gdGhlaXIgY2VudGVycy48L3A+XG4gICAgICAgICAqL1xuICAgICAgICBjYWxjdWxhdGVNb2R1bGVTaXplT25lV2F5KHBhdHRlcm4sIG90aGVyUGF0dGVybikge1xuICAgICAgICAgICAgY29uc3QgbW9kdWxlU2l6ZUVzdDEgPSB0aGlzLnNpemVPZkJsYWNrV2hpdGVCbGFja1J1bkJvdGhXYXlzKC8qKGludCkgKi8gTWF0aC5mbG9vcihwYXR0ZXJuLmdldFgoKSksIFxuICAgICAgICAgICAgLyooaW50KSAqLyBNYXRoLmZsb29yKHBhdHRlcm4uZ2V0WSgpKSwgXG4gICAgICAgICAgICAvKihpbnQpICovIE1hdGguZmxvb3Iob3RoZXJQYXR0ZXJuLmdldFgoKSksIFxuICAgICAgICAgICAgLyooaW50KSAqLyBNYXRoLmZsb29yKG90aGVyUGF0dGVybi5nZXRZKCkpKTtcbiAgICAgICAgICAgIGNvbnN0IG1vZHVsZVNpemVFc3QyID0gdGhpcy5zaXplT2ZCbGFja1doaXRlQmxhY2tSdW5Cb3RoV2F5cygvKihpbnQpICovIE1hdGguZmxvb3Iob3RoZXJQYXR0ZXJuLmdldFgoKSksIFxuICAgICAgICAgICAgLyooaW50KSAqLyBNYXRoLmZsb29yKG90aGVyUGF0dGVybi5nZXRZKCkpLCBcbiAgICAgICAgICAgIC8qKGludCkgKi8gTWF0aC5mbG9vcihwYXR0ZXJuLmdldFgoKSksIFxuICAgICAgICAgICAgLyooaW50KSAqLyBNYXRoLmZsb29yKHBhdHRlcm4uZ2V0WSgpKSk7XG4gICAgICAgICAgICBpZiAoaXNOYU4obW9kdWxlU2l6ZUVzdDEpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vZHVsZVNpemVFc3QyIC8gNy4wO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzTmFOKG1vZHVsZVNpemVFc3QyKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb2R1bGVTaXplRXN0MSAvIDcuMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEF2ZXJhZ2UgdGhlbSwgYW5kIGRpdmlkZSBieSA3IHNpbmNlIHdlJ3ZlIGNvdW50ZWQgdGhlIHdpZHRoIG9mIDMgYmxhY2sgbW9kdWxlcyxcbiAgICAgICAgICAgIC8vIGFuZCAxIHdoaXRlIGFuZCAxIGJsYWNrIG1vZHVsZSBvbiBlaXRoZXIgc2lkZS4gRXJnbywgZGl2aWRlIHN1bSBieSAxNC5cbiAgICAgICAgICAgIHJldHVybiAobW9kdWxlU2l6ZUVzdDEgKyBtb2R1bGVTaXplRXN0MikgLyAxNC4wO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZWUge0BsaW5rICNzaXplT2ZCbGFja1doaXRlQmxhY2tSdW4oaW50LCBpbnQsIGludCwgaW50KX07IGNvbXB1dGVzIHRoZSB0b3RhbCB3aWR0aCBvZlxuICAgICAgICAgKiBhIGZpbmRlciBwYXR0ZXJuIGJ5IGxvb2tpbmcgZm9yIGEgYmxhY2std2hpdGUtYmxhY2sgcnVuIGZyb20gdGhlIGNlbnRlciBpbiB0aGUgZGlyZWN0aW9uXG4gICAgICAgICAqIG9mIGFub3RoZXIgcG9pbnQgKGFub3RoZXIgZmluZGVyIHBhdHRlcm4gY2VudGVyKSwgYW5kIGluIHRoZSBvcHBvc2l0ZSBkaXJlY3Rpb24gdG9vLlxuICAgICAgICAgKi9cbiAgICAgICAgc2l6ZU9mQmxhY2tXaGl0ZUJsYWNrUnVuQm90aFdheXMoZnJvbVggLyppbnQqLywgZnJvbVkgLyppbnQqLywgdG9YIC8qaW50Ki8sIHRvWSAvKmludCovKSB7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gdGhpcy5zaXplT2ZCbGFja1doaXRlQmxhY2tSdW4oZnJvbVgsIGZyb21ZLCB0b1gsIHRvWSk7XG4gICAgICAgICAgICAvLyBOb3cgY291bnQgb3RoZXIgd2F5IC0tIGRvbid0IHJ1biBvZmYgaW1hZ2UgdGhvdWdoIG9mIGNvdXJzZVxuICAgICAgICAgICAgbGV0IHNjYWxlID0gMS4wO1xuICAgICAgICAgICAgbGV0IG90aGVyVG9YID0gZnJvbVggLSAodG9YIC0gZnJvbVgpO1xuICAgICAgICAgICAgaWYgKG90aGVyVG9YIDwgMCkge1xuICAgICAgICAgICAgICAgIHNjYWxlID0gZnJvbVggLyAvKihmbG9hdCkgKi8gKGZyb21YIC0gb3RoZXJUb1gpO1xuICAgICAgICAgICAgICAgIG90aGVyVG9YID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKG90aGVyVG9YID49IHRoaXMuaW1hZ2UuZ2V0V2lkdGgoKSkge1xuICAgICAgICAgICAgICAgIHNjYWxlID0gKHRoaXMuaW1hZ2UuZ2V0V2lkdGgoKSAtIDEgLSBmcm9tWCkgLyAvKihmbG9hdCkgKi8gKG90aGVyVG9YIC0gZnJvbVgpO1xuICAgICAgICAgICAgICAgIG90aGVyVG9YID0gdGhpcy5pbWFnZS5nZXRXaWR0aCgpIC0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBvdGhlclRvWSA9IC8qKGludCkgKi8gTWF0aC5mbG9vcihmcm9tWSAtICh0b1kgLSBmcm9tWSkgKiBzY2FsZSk7XG4gICAgICAgICAgICBzY2FsZSA9IDEuMDtcbiAgICAgICAgICAgIGlmIChvdGhlclRvWSA8IDApIHtcbiAgICAgICAgICAgICAgICBzY2FsZSA9IGZyb21ZIC8gLyooZmxvYXQpICovIChmcm9tWSAtIG90aGVyVG9ZKTtcbiAgICAgICAgICAgICAgICBvdGhlclRvWSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChvdGhlclRvWSA+PSB0aGlzLmltYWdlLmdldEhlaWdodCgpKSB7XG4gICAgICAgICAgICAgICAgc2NhbGUgPSAodGhpcy5pbWFnZS5nZXRIZWlnaHQoKSAtIDEgLSBmcm9tWSkgLyAvKihmbG9hdCkgKi8gKG90aGVyVG9ZIC0gZnJvbVkpO1xuICAgICAgICAgICAgICAgIG90aGVyVG9ZID0gdGhpcy5pbWFnZS5nZXRIZWlnaHQoKSAtIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvdGhlclRvWCA9IC8qKGludCkgKi8gTWF0aC5mbG9vcihmcm9tWCArIChvdGhlclRvWCAtIGZyb21YKSAqIHNjYWxlKTtcbiAgICAgICAgICAgIHJlc3VsdCArPSB0aGlzLnNpemVPZkJsYWNrV2hpdGVCbGFja1J1bihmcm9tWCwgZnJvbVksIG90aGVyVG9YLCBvdGhlclRvWSk7XG4gICAgICAgICAgICAvLyBNaWRkbGUgcGl4ZWwgaXMgZG91YmxlLWNvdW50ZWQgdGhpcyB3YXk7IHN1YnRyYWN0IDFcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQgLSAxLjA7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPlRoaXMgbWV0aG9kIHRyYWNlcyBhIGxpbmUgZnJvbSBhIHBvaW50IGluIHRoZSBpbWFnZSwgaW4gdGhlIGRpcmVjdGlvbiB0b3dhcmRzIGFub3RoZXIgcG9pbnQuXG4gICAgICAgICAqIEl0IGJlZ2lucyBpbiBhIGJsYWNrIHJlZ2lvbiwgYW5kIGtlZXBzIGdvaW5nIHVudGlsIGl0IGZpbmRzIHdoaXRlLCB0aGVuIGJsYWNrLCB0aGVuIHdoaXRlIGFnYWluLlxuICAgICAgICAgKiBJdCByZXBvcnRzIHRoZSBkaXN0YW5jZSBmcm9tIHRoZSBzdGFydCB0byB0aGlzIHBvaW50LjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogPHA+VGhpcyBpcyB1c2VkIHdoZW4gZmlndXJpbmcgb3V0IGhvdyB3aWRlIGEgZmluZGVyIHBhdHRlcm4gaXMsIHdoZW4gdGhlIGZpbmRlciBwYXR0ZXJuXG4gICAgICAgICAqIG1heSBiZSBza2V3ZWQgb3Igcm90YXRlZC48L3A+XG4gICAgICAgICAqL1xuICAgICAgICBzaXplT2ZCbGFja1doaXRlQmxhY2tSdW4oZnJvbVggLyppbnQqLywgZnJvbVkgLyppbnQqLywgdG9YIC8qaW50Ki8sIHRvWSAvKmludCovKSB7XG4gICAgICAgICAgICAvLyBNaWxkIHZhcmlhbnQgb2YgQnJlc2VuaGFtJ3MgYWxnb3JpdGhtXG4gICAgICAgICAgICAvLyBzZWUgaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9CcmVzZW5oYW0nc19saW5lX2FsZ29yaXRobVxuICAgICAgICAgICAgY29uc3Qgc3RlZXAgPSBNYXRoLmFicyh0b1kgLSBmcm9tWSkgPiBNYXRoLmFicyh0b1ggLSBmcm9tWCk7XG4gICAgICAgICAgICBpZiAoc3RlZXApIHtcbiAgICAgICAgICAgICAgICBsZXQgdGVtcCA9IGZyb21YO1xuICAgICAgICAgICAgICAgIGZyb21YID0gZnJvbVk7XG4gICAgICAgICAgICAgICAgZnJvbVkgPSB0ZW1wO1xuICAgICAgICAgICAgICAgIHRlbXAgPSB0b1g7XG4gICAgICAgICAgICAgICAgdG9YID0gdG9ZO1xuICAgICAgICAgICAgICAgIHRvWSA9IHRlbXA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBkeCA9IE1hdGguYWJzKHRvWCAtIGZyb21YKTtcbiAgICAgICAgICAgIGNvbnN0IGR5ID0gTWF0aC5hYnModG9ZIC0gZnJvbVkpO1xuICAgICAgICAgICAgbGV0IGVycm9yID0gLWR4IC8gMjtcbiAgICAgICAgICAgIGNvbnN0IHhzdGVwID0gZnJvbVggPCB0b1ggPyAxIDogLTE7XG4gICAgICAgICAgICBjb25zdCB5c3RlcCA9IGZyb21ZIDwgdG9ZID8gMSA6IC0xO1xuICAgICAgICAgICAgLy8gSW4gYmxhY2sgcGl4ZWxzLCBsb29raW5nIGZvciB3aGl0ZSwgZmlyc3Qgb3Igc2Vjb25kIHRpbWUuXG4gICAgICAgICAgICBsZXQgc3RhdGUgPSAwO1xuICAgICAgICAgICAgLy8gTG9vcCB1cCB1bnRpbCB4ID09IHRvWCwgYnV0IG5vdCBiZXlvbmRcbiAgICAgICAgICAgIGNvbnN0IHhMaW1pdCA9IHRvWCArIHhzdGVwO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IGZyb21YLCB5ID0gZnJvbVk7IHggIT09IHhMaW1pdDsgeCArPSB4c3RlcCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlYWxYID0gc3RlZXAgPyB5IDogeDtcbiAgICAgICAgICAgICAgICBjb25zdCByZWFsWSA9IHN0ZWVwID8geCA6IHk7XG4gICAgICAgICAgICAgICAgLy8gRG9lcyBjdXJyZW50IHBpeGVsIG1lYW4gd2UgaGF2ZSBtb3ZlZCB3aGl0ZSB0byBibGFjayBvciB2aWNlIHZlcnNhP1xuICAgICAgICAgICAgICAgIC8vIFNjYW5uaW5nIGJsYWNrIGluIHN0YXRlIDAsMiBhbmQgd2hpdGUgaW4gc3RhdGUgMSwgc28gaWYgd2UgZmluZCB0aGUgd3JvbmdcbiAgICAgICAgICAgICAgICAvLyBjb2xvciwgYWR2YW5jZSB0byBuZXh0IHN0YXRlIG9yIGVuZCBpZiB3ZSBhcmUgaW4gc3RhdGUgMiBhbHJlYWR5XG4gICAgICAgICAgICAgICAgaWYgKChzdGF0ZSA9PT0gMSkgPT09IHRoaXMuaW1hZ2UuZ2V0KHJlYWxYLCByZWFsWSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXRlID09PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gTWF0aFV0aWxzLmRpc3RhbmNlKHgsIHksIGZyb21YLCBmcm9tWSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc3RhdGUrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZXJyb3IgKz0gZHk7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoeSA9PT0gdG9ZKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB5ICs9IHlzdGVwO1xuICAgICAgICAgICAgICAgICAgICBlcnJvciAtPSBkeDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBGb3VuZCBibGFjay13aGl0ZS1ibGFjazsgZ2l2ZSB0aGUgYmVuZWZpdCBvZiB0aGUgZG91YnQgdGhhdCB0aGUgbmV4dCBwaXhlbCBvdXRzaWRlIHRoZSBpbWFnZVxuICAgICAgICAgICAgLy8gaXMgXCJ3aGl0ZVwiIHNvIHRoaXMgbGFzdCBwb2ludCBhdCAodG9YK3hTdGVwLHRvWSkgaXMgdGhlIHJpZ2h0IGVuZGluZy4gVGhpcyBpcyByZWFsbHkgYVxuICAgICAgICAgICAgLy8gc21hbGwgYXBwcm94aW1hdGlvbjsgKHRvWCt4U3RlcCx0b1kreVN0ZXApIG1pZ2h0IGJlIHJlYWxseSBjb3JyZWN0LiBJZ25vcmUgdGhpcy5cbiAgICAgICAgICAgIGlmIChzdGF0ZSA9PT0gMikge1xuICAgICAgICAgICAgICAgIHJldHVybiBNYXRoVXRpbHMuZGlzdGFuY2UodG9YICsgeHN0ZXAsIHRvWSwgZnJvbVgsIGZyb21ZKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGVsc2Ugd2UgZGlkbid0IGZpbmQgZXZlbiBibGFjay13aGl0ZS1ibGFjazsgbm8gZXN0aW1hdGUgaXMgcmVhbGx5IHBvc3NpYmxlXG4gICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5BdHRlbXB0cyB0byBsb2NhdGUgYW4gYWxpZ25tZW50IHBhdHRlcm4gaW4gYSBsaW1pdGVkIHJlZ2lvbiBvZiB0aGUgaW1hZ2UsIHdoaWNoIGlzXG4gICAgICAgICAqIGd1ZXNzZWQgdG8gY29udGFpbiBpdC4gVGhpcyBtZXRob2QgdXNlcyB7QGxpbmsgQWxpZ25tZW50UGF0dGVybn0uPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gb3ZlcmFsbEVzdE1vZHVsZVNpemUgZXN0aW1hdGVkIG1vZHVsZSBzaXplIHNvIGZhclxuICAgICAgICAgKiBAcGFyYW0gZXN0QWxpZ25tZW50WCB4IGNvb3JkaW5hdGUgb2YgY2VudGVyIG9mIGFyZWEgcHJvYmFibHkgY29udGFpbmluZyBhbGlnbm1lbnQgcGF0dGVyblxuICAgICAgICAgKiBAcGFyYW0gZXN0QWxpZ25tZW50WSB5IGNvb3JkaW5hdGUgb2YgYWJvdmVcbiAgICAgICAgICogQHBhcmFtIGFsbG93YW5jZUZhY3RvciBudW1iZXIgb2YgcGl4ZWxzIGluIGFsbCBkaXJlY3Rpb25zIHRvIHNlYXJjaCBmcm9tIHRoZSBjZW50ZXJcbiAgICAgICAgICogQHJldHVybiB7QGxpbmsgQWxpZ25tZW50UGF0dGVybn0gaWYgZm91bmQsIG9yIG51bGwgb3RoZXJ3aXNlXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gaWYgYW4gdW5leHBlY3RlZCBlcnJvciBvY2N1cnMgZHVyaW5nIGRldGVjdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgZmluZEFsaWdubWVudEluUmVnaW9uKG92ZXJhbGxFc3RNb2R1bGVTaXplIC8qZmxvYXQqLywgZXN0QWxpZ25tZW50WCAvKmludCovLCBlc3RBbGlnbm1lbnRZIC8qaW50Ki8sIGFsbG93YW5jZUZhY3RvciAvKmZsb2F0Ki8pIHtcbiAgICAgICAgICAgIC8vIExvb2sgZm9yIGFuIGFsaWdubWVudCBwYXR0ZXJuICgzIG1vZHVsZXMgaW4gc2l6ZSkgYXJvdW5kIHdoZXJlIGl0XG4gICAgICAgICAgICAvLyBzaG91bGQgYmVcbiAgICAgICAgICAgIGNvbnN0IGFsbG93YW5jZSA9IC8qKGludCkgKi8gTWF0aC5mbG9vcihhbGxvd2FuY2VGYWN0b3IgKiBvdmVyYWxsRXN0TW9kdWxlU2l6ZSk7XG4gICAgICAgICAgICBjb25zdCBhbGlnbm1lbnRBcmVhTGVmdFggPSBNYXRoLm1heCgwLCBlc3RBbGlnbm1lbnRYIC0gYWxsb3dhbmNlKTtcbiAgICAgICAgICAgIGNvbnN0IGFsaWdubWVudEFyZWFSaWdodFggPSBNYXRoLm1pbih0aGlzLmltYWdlLmdldFdpZHRoKCkgLSAxLCBlc3RBbGlnbm1lbnRYICsgYWxsb3dhbmNlKTtcbiAgICAgICAgICAgIGlmIChhbGlnbm1lbnRBcmVhUmlnaHRYIC0gYWxpZ25tZW50QXJlYUxlZnRYIDwgb3ZlcmFsbEVzdE1vZHVsZVNpemUgKiAzKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCdBbGlnbm1lbnQgdG9wIGV4Y2VlZHMgZXN0aW1hdGVkIG1vZHVsZSBzaXplLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYWxpZ25tZW50QXJlYVRvcFkgPSBNYXRoLm1heCgwLCBlc3RBbGlnbm1lbnRZIC0gYWxsb3dhbmNlKTtcbiAgICAgICAgICAgIGNvbnN0IGFsaWdubWVudEFyZWFCb3R0b21ZID0gTWF0aC5taW4odGhpcy5pbWFnZS5nZXRIZWlnaHQoKSAtIDEsIGVzdEFsaWdubWVudFkgKyBhbGxvd2FuY2UpO1xuICAgICAgICAgICAgaWYgKGFsaWdubWVudEFyZWFCb3R0b21ZIC0gYWxpZ25tZW50QXJlYVRvcFkgPCBvdmVyYWxsRXN0TW9kdWxlU2l6ZSAqIDMpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oJ0FsaWdubWVudCBib3R0b20gZXhjZWVkcyBlc3RpbWF0ZWQgbW9kdWxlIHNpemUuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBhbGlnbm1lbnRGaW5kZXIgPSBuZXcgQWxpZ25tZW50UGF0dGVybkZpbmRlcih0aGlzLmltYWdlLCBhbGlnbm1lbnRBcmVhTGVmdFgsIGFsaWdubWVudEFyZWFUb3BZLCBhbGlnbm1lbnRBcmVhUmlnaHRYIC0gYWxpZ25tZW50QXJlYUxlZnRYLCBhbGlnbm1lbnRBcmVhQm90dG9tWSAtIGFsaWdubWVudEFyZWFUb3BZLCBvdmVyYWxsRXN0TW9kdWxlU2l6ZSwgdGhpcy5yZXN1bHRQb2ludENhbGxiYWNrKTtcbiAgICAgICAgICAgIHJldHVybiBhbGlnbm1lbnRGaW5kZXIuZmluZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKmltcG9ydCBqYXZhLnV0aWwuTGlzdDsqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5NYXA7Ki9cbiAgICAvKipcbiAgICAgKiBUaGlzIGltcGxlbWVudGF0aW9uIGNhbiBkZXRlY3QgYW5kIGRlY29kZSBRUiBDb2RlcyBpbiBhbiBpbWFnZS5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgUVJDb2RlUmVhZGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgICAgICB0aGlzLmRlY29kZXIgPSBuZXcgRGVjb2RlciQyKCk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RGVjb2RlcigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZXI7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIExvY2F0ZXMgYW5kIGRlY29kZXMgYSBRUiBjb2RlIGluIGFuIGltYWdlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIGEgcmVwcmVzZW50aW5nOiBzdHJpbmcgdGhlIGNvbnRlbnQgZW5jb2RlZCBieSB0aGUgUVIgY29kZVxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIGEgUVIgY29kZSBjYW5ub3QgYmUgZm91bmRcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb24gaWYgYSBRUiBjb2RlIGNhbm5vdCBiZSBkZWNvZGVkXG4gICAgICAgICAqIEB0aHJvd3MgQ2hlY2tzdW1FeGNlcHRpb24gaWYgZXJyb3IgY29ycmVjdGlvbiBmYWlsc1xuICAgICAgICAgKi9cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICAvLyBwdWJsaWMgZGVjb2RlKGltYWdlOiBCaW5hcnlCaXRtYXApOiBSZXN1bHQgLyp0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24sIENoZWNrc3VtRXhjZXB0aW9uLCBGb3JtYXRFeGNlcHRpb24gKi8ge1xuICAgICAgICAvLyAgIHJldHVybiB0aGlzLmRlY29kZShpbWFnZSwgbnVsbClcbiAgICAgICAgLy8gfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGRlY29kZShpbWFnZSwgaGludHMpIHtcbiAgICAgICAgICAgIGxldCBkZWNvZGVyUmVzdWx0O1xuICAgICAgICAgICAgbGV0IHBvaW50cztcbiAgICAgICAgICAgIGlmIChoaW50cyAhPT0gdW5kZWZpbmVkICYmIGhpbnRzICE9PSBudWxsICYmIHVuZGVmaW5lZCAhPT0gaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuUFVSRV9CQVJDT0RFKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGJpdHMgPSBRUkNvZGVSZWFkZXIuZXh0cmFjdFB1cmVCaXRzKGltYWdlLmdldEJsYWNrTWF0cml4KCkpO1xuICAgICAgICAgICAgICAgIGRlY29kZXJSZXN1bHQgPSB0aGlzLmRlY29kZXIuZGVjb2RlQml0TWF0cml4KGJpdHMsIGhpbnRzKTtcbiAgICAgICAgICAgICAgICBwb2ludHMgPSBRUkNvZGVSZWFkZXIuTk9fUE9JTlRTO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGV0ZWN0b3JSZXN1bHQgPSBuZXcgRGV0ZWN0b3IkMihpbWFnZS5nZXRCbGFja01hdHJpeCgpKS5kZXRlY3QoaGludHMpO1xuICAgICAgICAgICAgICAgIGRlY29kZXJSZXN1bHQgPSB0aGlzLmRlY29kZXIuZGVjb2RlQml0TWF0cml4KGRldGVjdG9yUmVzdWx0LmdldEJpdHMoKSwgaGludHMpO1xuICAgICAgICAgICAgICAgIHBvaW50cyA9IGRldGVjdG9yUmVzdWx0LmdldFBvaW50cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSWYgdGhlIGNvZGUgd2FzIG1pcnJvcmVkOiBzd2FwIHRoZSBib3R0b20tbGVmdCBhbmQgdGhlIHRvcC1yaWdodCBwb2ludHMuXG4gICAgICAgICAgICBpZiAoZGVjb2RlclJlc3VsdC5nZXRPdGhlcigpIGluc3RhbmNlb2YgUVJDb2RlRGVjb2Rlck1ldGFEYXRhKSB7XG4gICAgICAgICAgICAgICAgZGVjb2RlclJlc3VsdC5nZXRPdGhlcigpLmFwcGx5TWlycm9yZWRDb3JyZWN0aW9uKHBvaW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgUmVzdWx0KGRlY29kZXJSZXN1bHQuZ2V0VGV4dCgpLCBkZWNvZGVyUmVzdWx0LmdldFJhd0J5dGVzKCksIHVuZGVmaW5lZCwgcG9pbnRzLCBCYXJjb2RlRm9ybWF0JDEuUVJfQ09ERSwgdW5kZWZpbmVkKTtcbiAgICAgICAgICAgIGNvbnN0IGJ5dGVTZWdtZW50cyA9IGRlY29kZXJSZXN1bHQuZ2V0Qnl0ZVNlZ21lbnRzKCk7XG4gICAgICAgICAgICBpZiAoYnl0ZVNlZ21lbnRzICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1dE1ldGFkYXRhKFJlc3VsdE1ldGFkYXRhVHlwZSQxLkJZVEVfU0VHTUVOVFMsIGJ5dGVTZWdtZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBlY0xldmVsID0gZGVjb2RlclJlc3VsdC5nZXRFQ0xldmVsKCk7XG4gICAgICAgICAgICBpZiAoZWNMZXZlbCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXRNZXRhZGF0YShSZXN1bHRNZXRhZGF0YVR5cGUkMS5FUlJPUl9DT1JSRUNUSU9OX0xFVkVMLCBlY0xldmVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChkZWNvZGVyUmVzdWx0Lmhhc1N0cnVjdHVyZWRBcHBlbmQoKSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXRNZXRhZGF0YShSZXN1bHRNZXRhZGF0YVR5cGUkMS5TVFJVQ1RVUkVEX0FQUEVORF9TRVFVRU5DRSwgZGVjb2RlclJlc3VsdC5nZXRTdHJ1Y3R1cmVkQXBwZW5kU2VxdWVuY2VOdW1iZXIoKSk7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1dE1ldGFkYXRhKFJlc3VsdE1ldGFkYXRhVHlwZSQxLlNUUlVDVFVSRURfQVBQRU5EX1BBUklUWSwgZGVjb2RlclJlc3VsdC5nZXRTdHJ1Y3R1cmVkQXBwZW5kUGFyaXR5KCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIHJlc2V0KCkge1xuICAgICAgICAgICAgLy8gZG8gbm90aGluZ1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGlzIG1ldGhvZCBkZXRlY3RzIGEgY29kZSBpbiBhIFwicHVyZVwiIGltYWdlIC0tIHRoYXQgaXMsIHB1cmUgbW9ub2Nocm9tZSBpbWFnZVxuICAgICAgICAgKiB3aGljaCBjb250YWlucyBvbmx5IGFuIHVucm90YXRlZCwgdW5za2V3ZWQsIGltYWdlIG9mIGEgY29kZSwgd2l0aCBzb21lIHdoaXRlIGJvcmRlclxuICAgICAgICAgKiBhcm91bmQgaXQuIFRoaXMgaXMgYSBzcGVjaWFsaXplZCBtZXRob2QgdGhhdCB3b3JrcyBleGNlcHRpb25hbGx5IGZhc3QgaW4gdGhpcyBzcGVjaWFsXG4gICAgICAgICAqIGNhc2UuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBzZWUgY29tLmdvb2dsZS56eGluZy5kYXRhbWF0cml4LkRhdGFNYXRyaXhSZWFkZXIjZXh0cmFjdFB1cmVCaXRzKEJpdE1hdHJpeClcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBleHRyYWN0UHVyZUJpdHMoaW1hZ2UpIHtcbiAgICAgICAgICAgIGNvbnN0IGxlZnRUb3BCbGFjayA9IGltYWdlLmdldFRvcExlZnRPbkJpdCgpO1xuICAgICAgICAgICAgY29uc3QgcmlnaHRCb3R0b21CbGFjayA9IGltYWdlLmdldEJvdHRvbVJpZ2h0T25CaXQoKTtcbiAgICAgICAgICAgIGlmIChsZWZ0VG9wQmxhY2sgPT09IG51bGwgfHwgcmlnaHRCb3R0b21CbGFjayA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbW9kdWxlU2l6ZSA9IHRoaXMubW9kdWxlU2l6ZShsZWZ0VG9wQmxhY2ssIGltYWdlKTtcbiAgICAgICAgICAgIGxldCB0b3AgPSBsZWZ0VG9wQmxhY2tbMV07XG4gICAgICAgICAgICBsZXQgYm90dG9tID0gcmlnaHRCb3R0b21CbGFja1sxXTtcbiAgICAgICAgICAgIGxldCBsZWZ0ID0gbGVmdFRvcEJsYWNrWzBdO1xuICAgICAgICAgICAgbGV0IHJpZ2h0ID0gcmlnaHRCb3R0b21CbGFja1swXTtcbiAgICAgICAgICAgIC8vIFNhbml0eSBjaGVjayFcbiAgICAgICAgICAgIGlmIChsZWZ0ID49IHJpZ2h0IHx8IHRvcCA+PSBib3R0b20pIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChib3R0b20gLSB0b3AgIT09IHJpZ2h0IC0gbGVmdCkge1xuICAgICAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZSwgd2hlcmUgYm90dG9tLXJpZ2h0IG1vZHVsZSB3YXNuJ3QgYmxhY2sgc28gd2UgZm91bmQgc29tZXRoaW5nIGVsc2UgaW4gdGhlIGxhc3Qgcm93XG4gICAgICAgICAgICAgICAgLy8gQXNzdW1lIGl0J3MgYSBzcXVhcmUsIHNvIHVzZSBoZWlnaHQgYXMgdGhlIHdpZHRoXG4gICAgICAgICAgICAgICAgcmlnaHQgPSBsZWZ0ICsgKGJvdHRvbSAtIHRvcCk7XG4gICAgICAgICAgICAgICAgaWYgKHJpZ2h0ID49IGltYWdlLmdldFdpZHRoKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQWJvcnQgaWYgdGhhdCB3b3VsZCBub3QgbWFrZSBzZW5zZSAtLSBvZmYgaW1hZ2VcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbWF0cml4V2lkdGggPSBNYXRoLnJvdW5kKChyaWdodCAtIGxlZnQgKyAxKSAvIG1vZHVsZVNpemUpO1xuICAgICAgICAgICAgY29uc3QgbWF0cml4SGVpZ2h0ID0gTWF0aC5yb3VuZCgoYm90dG9tIC0gdG9wICsgMSkgLyBtb2R1bGVTaXplKTtcbiAgICAgICAgICAgIGlmIChtYXRyaXhXaWR0aCA8PSAwIHx8IG1hdHJpeEhlaWdodCA8PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWF0cml4SGVpZ2h0ICE9PSBtYXRyaXhXaWR0aCkge1xuICAgICAgICAgICAgICAgIC8vIE9ubHkgcG9zc2libHkgZGVjb2RlIHNxdWFyZSByZWdpb25zXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBQdXNoIGluIHRoZSBcImJvcmRlclwiIGJ5IGhhbGYgdGhlIG1vZHVsZSB3aWR0aCBzbyB0aGF0IHdlIHN0YXJ0XG4gICAgICAgICAgICAvLyBzYW1wbGluZyBpbiB0aGUgbWlkZGxlIG9mIHRoZSBtb2R1bGUuIEp1c3QgaW4gY2FzZSB0aGUgaW1hZ2UgaXMgYVxuICAgICAgICAgICAgLy8gbGl0dGxlIG9mZiwgdGhpcyB3aWxsIGhlbHAgcmVjb3Zlci5cbiAgICAgICAgICAgIGNvbnN0IG51ZGdlID0gLyooaW50KSAqLyBNYXRoLmZsb29yKG1vZHVsZVNpemUgLyAyLjApO1xuICAgICAgICAgICAgdG9wICs9IG51ZGdlO1xuICAgICAgICAgICAgbGVmdCArPSBudWRnZTtcbiAgICAgICAgICAgIC8vIEJ1dCBjYXJlZnVsIHRoYXQgdGhpcyBkb2VzIG5vdCBzYW1wbGUgb2ZmIHRoZSBlZGdlXG4gICAgICAgICAgICAvLyBcInJpZ2h0XCIgaXMgdGhlIGZhcnRoZXN0LXJpZ2h0IHZhbGlkIHBpeGVsIGxvY2F0aW9uIC0tIHJpZ2h0KzEgaXMgbm90IG5lY2Vzc2FyaWx5XG4gICAgICAgICAgICAvLyBUaGlzIGlzIHBvc2l0aXZlIGJ5IGhvdyBtdWNoIHRoZSBpbm5lciB4IGxvb3AgYmVsb3cgd291bGQgYmUgdG9vIGxhcmdlXG4gICAgICAgICAgICBjb25zdCBudWRnZWRUb29GYXJSaWdodCA9IGxlZnQgKyAvKihpbnQpICovIE1hdGguZmxvb3IoKG1hdHJpeFdpZHRoIC0gMSkgKiBtb2R1bGVTaXplKSAtIHJpZ2h0O1xuICAgICAgICAgICAgaWYgKG51ZGdlZFRvb0ZhclJpZ2h0ID4gMCkge1xuICAgICAgICAgICAgICAgIGlmIChudWRnZWRUb29GYXJSaWdodCA+IG51ZGdlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE5laXRoZXIgd2F5IGZpdHM7IGFib3J0XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZWZ0IC09IG51ZGdlZFRvb0ZhclJpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gU2VlIGxvZ2ljIGFib3ZlXG4gICAgICAgICAgICBjb25zdCBudWRnZWRUb29GYXJEb3duID0gdG9wICsgLyooaW50KSAqLyBNYXRoLmZsb29yKChtYXRyaXhIZWlnaHQgLSAxKSAqIG1vZHVsZVNpemUpIC0gYm90dG9tO1xuICAgICAgICAgICAgaWYgKG51ZGdlZFRvb0ZhckRvd24gPiAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKG51ZGdlZFRvb0ZhckRvd24gPiBudWRnZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBOZWl0aGVyIHdheSBmaXRzOyBhYm9ydFxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdG9wIC09IG51ZGdlZFRvb0ZhckRvd247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBOb3cganVzdCByZWFkIG9mZiB0aGUgYml0c1xuICAgICAgICAgICAgY29uc3QgYml0cyA9IG5ldyBCaXRNYXRyaXgobWF0cml4V2lkdGgsIG1hdHJpeEhlaWdodCk7XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IG1hdHJpeEhlaWdodDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaU9mZnNldCA9IHRvcCArIC8qKGludCkgKi8gTWF0aC5mbG9vcih5ICogbW9kdWxlU2l6ZSk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCBtYXRyaXhXaWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbWFnZS5nZXQobGVmdCArIC8qKGludCkgKi8gTWF0aC5mbG9vcih4ICogbW9kdWxlU2l6ZSksIGlPZmZzZXQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBiaXRzLnNldCh4LCB5KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBiaXRzO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBtb2R1bGVTaXplKGxlZnRUb3BCbGFjaywgaW1hZ2UpIHtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IGltYWdlLmdldEhlaWdodCgpO1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBpbWFnZS5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgbGV0IHggPSBsZWZ0VG9wQmxhY2tbMF07XG4gICAgICAgICAgICBsZXQgeSA9IGxlZnRUb3BCbGFja1sxXTtcbiAgICAgICAgICAgIGxldCBpbkJsYWNrID0gdHJ1ZTtcbiAgICAgICAgICAgIGxldCB0cmFuc2l0aW9ucyA9IDA7XG4gICAgICAgICAgICB3aGlsZSAoeCA8IHdpZHRoICYmIHkgPCBoZWlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5CbGFjayAhPT0gaW1hZ2UuZ2V0KHgsIHkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICgrK3RyYW5zaXRpb25zID09PSA1KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpbkJsYWNrID0gIWluQmxhY2s7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHgrKztcbiAgICAgICAgICAgICAgICB5Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoeCA9PT0gd2lkdGggfHwgeSA9PT0gaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gKHggLSBsZWZ0VG9wQmxhY2tbMF0pIC8gNy4wO1xuICAgICAgICB9XG4gICAgfVxuICAgIFFSQ29kZVJlYWRlci5OT19QT0lOVFMgPSBuZXcgQXJyYXkoKTtcblxuICAgIC8qXG4gICAgKiBDb3B5cmlnaHQgMjAwOSBaWGluZyBhdXRob3JzXG4gICAgKlxuICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICpcbiAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgKlxuICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAqL1xuICAgIC8qKlxuICAgICAqIEBhdXRob3IgU0lUQSBMYWIgKGtldmluLm9zdWxsaXZhbkBzaXRhLmFlcm8pXG4gICAgICogQGF1dGhvciBHdWVudGhlciBHcmF1XG4gICAgICovXG4gICAgLypwdWJsaWMgZmluYWwqLyBjbGFzcyBQREY0MTdDb21tb24ge1xuICAgICAgICBQREY0MTdDb21tb24oKSB7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBtb2R1bGVCaXRDb3VudCB2YWx1ZXMgdG8gc3VtXG4gICAgICAgICAqIEByZXR1cm4gc3VtIG9mIHZhbHVlc1xuICAgICAgICAgKiBAZGVwcmVjYXRlZCBjYWxsIHtAbGluayBNYXRoVXRpbHMjc3VtKGludFtdKX1cbiAgICAgICAgICovXG4gICAgICAgIC8vIEBEZXByZWNhdGVkXG4gICAgICAgIHN0YXRpYyBnZXRCaXRDb3VudFN1bShtb2R1bGVCaXRDb3VudCkge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGhVdGlscy5zdW0obW9kdWxlQml0Q291bnQpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyB0b0ludEFycmF5KGxpc3QpIHtcbiAgICAgICAgICAgIGlmIChsaXN0ID09IG51bGwgfHwgIWxpc3QubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFBERjQxN0NvbW1vbi5FTVBUWV9JTlRfQVJSQVk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgSW50MzJBcnJheShsaXN0Lmxlbmd0aCk7XG4gICAgICAgICAgICBsZXQgaSA9IDA7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGludGVnZXIgb2YgbGlzdCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdFtpKytdID0gaW50ZWdlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBzeW1ib2wgZW5jb2RlZCBzeW1ib2wgdG8gdHJhbnNsYXRlIHRvIGEgY29kZXdvcmRcbiAgICAgICAgICogQHJldHVybiB0aGUgY29kZXdvcmQgY29ycmVzcG9uZGluZyB0byB0aGUgc3ltYm9sLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGdldENvZGV3b3JkKHN5bWJvbCAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBpID0gQXJyYXlzLmJpbmFyeVNlYXJjaChQREY0MTdDb21tb24uU1lNQk9MX1RBQkxFLCBzeW1ib2wgJiAweDNGRkZGKTtcbiAgICAgICAgICAgIGlmIChpIDwgMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAoUERGNDE3Q29tbW9uLkNPREVXT1JEX1RBQkxFW2ldIC0gMSkgJSBQREY0MTdDb21tb24uTlVNQkVSX09GX0NPREVXT1JEUztcbiAgICAgICAgfVxuICAgIH1cbiAgICBQREY0MTdDb21tb24uTlVNQkVSX09GX0NPREVXT1JEUyA9IDkyOTtcbiAgICAvLyBNYXhpbXVtIENvZGV3b3JkcyAoRGF0YSArIEVycm9yKS5cbiAgICBQREY0MTdDb21tb24uTUFYX0NPREVXT1JEU19JTl9CQVJDT0RFID0gUERGNDE3Q29tbW9uLk5VTUJFUl9PRl9DT0RFV09SRFMgLSAxO1xuICAgIFBERjQxN0NvbW1vbi5NSU5fUk9XU19JTl9CQVJDT0RFID0gMztcbiAgICBQREY0MTdDb21tb24uTUFYX1JPV1NfSU5fQkFSQ09ERSA9IDkwO1xuICAgIC8vIE9uZSBsZWZ0IHJvdyBpbmRpY2F0aW9uIGNvbHVtbiArIG1heCAzMCBkYXRhIGNvbHVtbnMgKyBvbmUgcmlnaHQgcm93IGluZGljYXRvciBjb2x1bW5cbiAgICAvLyBwdWJsaWMgc3RhdGljIC8qZmluYWwqLyBNQVhfQ09ERVdPUkRTX0lOX1JPVzogLyppbnQqLyBudW1iZXIgPSAzMjtcbiAgICBQREY0MTdDb21tb24uTU9EVUxFU19JTl9DT0RFV09SRCA9IDE3O1xuICAgIFBERjQxN0NvbW1vbi5NT0RVTEVTX0lOX1NUT1BfUEFUVEVSTiA9IDE4O1xuICAgIFBERjQxN0NvbW1vbi5CQVJTX0lOX01PRFVMRSA9IDg7XG4gICAgUERGNDE3Q29tbW9uLkVNUFRZX0lOVF9BUlJBWSA9IG5ldyBJbnQzMkFycmF5KFtdKTtcbiAgICAvKipcbiAgICAgKiBUaGUgc29ydGVkIHRhYmxlIG9mIGFsbCBwb3NzaWJsZSBzeW1ib2xzLiBFeHRyYWN0ZWQgZnJvbSB0aGUgUERGNDE3XG4gICAgICogc3BlY2lmaWNhdGlvbi4gVGhlIGluZGV4IG9mIGEgc3ltYm9sIGluIHRoaXMgdGFibGUgY29ycmVzcG9uZHMgdG8gdGhlXG4gICAgICogaW5kZXggaW50byB0aGUgY29kZXdvcmQgdGFibGUuXG4gICAgICovXG4gICAgUERGNDE3Q29tbW9uLlNZTUJPTF9UQUJMRSA9IEludDMyQXJyYXkuZnJvbShbXG4gICAgICAgIDB4MTAyNWUsIDB4MTAyN2EsIDB4MTAyOWUsIDB4MTAyYmMsIDB4MTAyZjIsIDB4MTAyZjQsIDB4MTAzMmUsIDB4MTAzNGUsIDB4MTAzNWMsIDB4MTAzOTYsIDB4MTAzYTYsIDB4MTAzYWMsXG4gICAgICAgIDB4MTA0MjIsIDB4MTA0MjgsIDB4MTA0MzYsIDB4MTA0NDIsIDB4MTA0NDQsIDB4MTA0NDgsIDB4MTA0NTAsIDB4MTA0NWUsIDB4MTA0NjYsIDB4MTA0NmMsIDB4MTA0N2EsIDB4MTA0ODIsXG4gICAgICAgIDB4MTA0OWUsIDB4MTA0YTAsIDB4MTA0YmMsIDB4MTA0YzYsIDB4MTA0ZDgsIDB4MTA0ZWUsIDB4MTA0ZjIsIDB4MTA0ZjQsIDB4MTA1MDQsIDB4MTA1MDgsIDB4MTA1MTAsIDB4MTA1MWUsXG4gICAgICAgIDB4MTA1MjAsIDB4MTA1M2MsIDB4MTA1NDAsIDB4MTA1NzgsIDB4MTA1ODYsIDB4MTA1OGMsIDB4MTA1OTgsIDB4MTA1YjAsIDB4MTA1YmUsIDB4MTA1Y2UsIDB4MTA1ZGMsIDB4MTA1ZTIsXG4gICAgICAgIDB4MTA1ZTQsIDB4MTA1ZTgsIDB4MTA1ZjYsIDB4MTA2MmUsIDB4MTA2NGUsIDB4MTA2NWMsIDB4MTA2OGUsIDB4MTA2OWMsIDB4MTA2YjgsIDB4MTA2ZGUsIDB4MTA2ZmEsIDB4MTA3MTYsXG4gICAgICAgIDB4MTA3MjYsIDB4MTA3MmMsIDB4MTA3NDYsIDB4MTA3NGMsIDB4MTA3NTgsIDB4MTA3NmUsIDB4MTA3OTIsIDB4MTA3OTQsIDB4MTA3YTIsIDB4MTA3YTQsIDB4MTA3YTgsIDB4MTA3YjYsXG4gICAgICAgIDB4MTA4MjIsIDB4MTA4MjgsIDB4MTA4NDIsIDB4MTA4NDgsIDB4MTA4NTAsIDB4MTA4NWUsIDB4MTA4NjYsIDB4MTA4NmMsIDB4MTA4N2EsIDB4MTA4ODIsIDB4MTA4ODQsIDB4MTA4OTAsXG4gICAgICAgIDB4MTA4OWUsIDB4MTA4YTAsIDB4MTA4YmMsIDB4MTA4YzYsIDB4MTA4Y2MsIDB4MTA4ZDgsIDB4MTA4ZWUsIDB4MTA4ZjIsIDB4MTA4ZjQsIDB4MTA5MDIsIDB4MTA5MDgsIDB4MTA5MWUsXG4gICAgICAgIDB4MTA5MjAsIDB4MTA5M2MsIDB4MTA5NDAsIDB4MTA5NzgsIDB4MTA5ODYsIDB4MTA5OTgsIDB4MTA5YjAsIDB4MTA5YmUsIDB4MTA5Y2UsIDB4MTA5ZGMsIDB4MTA5ZTIsIDB4MTA5ZTQsXG4gICAgICAgIDB4MTA5ZTgsIDB4MTA5ZjYsIDB4MTBhMDgsIDB4MTBhMTAsIDB4MTBhMWUsIDB4MTBhMjAsIDB4MTBhM2MsIDB4MTBhNDAsIDB4MTBhNzgsIDB4MTBhZjAsIDB4MTBiMDYsIDB4MTBiMGMsXG4gICAgICAgIDB4MTBiMTgsIDB4MTBiMzAsIDB4MTBiM2UsIDB4MTBiNjAsIDB4MTBiN2MsIDB4MTBiOGUsIDB4MTBiOWMsIDB4MTBiYjgsIDB4MTBiYzIsIDB4MTBiYzQsIDB4MTBiYzgsIDB4MTBiZDAsXG4gICAgICAgIDB4MTBiZGUsIDB4MTBiZTYsIDB4MTBiZWMsIDB4MTBjMmUsIDB4MTBjNGUsIDB4MTBjNWMsIDB4MTBjNjIsIDB4MTBjNjQsIDB4MTBjNjgsIDB4MTBjNzYsIDB4MTBjOGUsIDB4MTBjOWMsXG4gICAgICAgIDB4MTBjYjgsIDB4MTBjYzIsIDB4MTBjYzQsIDB4MTBjYzgsIDB4MTBjZDAsIDB4MTBjZGUsIDB4MTBjZTYsIDB4MTBjZWMsIDB4MTBjZmEsIDB4MTBkMGUsIDB4MTBkMWMsIDB4MTBkMzgsXG4gICAgICAgIDB4MTBkNzAsIDB4MTBkN2UsIDB4MTBkODIsIDB4MTBkODQsIDB4MTBkODgsIDB4MTBkOTAsIDB4MTBkOWUsIDB4MTBkYTAsIDB4MTBkYmMsIDB4MTBkYzYsIDB4MTBkY2MsIDB4MTBkZDgsXG4gICAgICAgIDB4MTBkZWUsIDB4MTBkZjIsIDB4MTBkZjQsIDB4MTBlMTYsIDB4MTBlMjYsIDB4MTBlMmMsIDB4MTBlNDYsIDB4MTBlNTgsIDB4MTBlNmUsIDB4MTBlODYsIDB4MTBlOGMsIDB4MTBlOTgsXG4gICAgICAgIDB4MTBlYjAsIDB4MTBlYmUsIDB4MTBlY2UsIDB4MTBlZGMsIDB4MTBmMGEsIDB4MTBmMTIsIDB4MTBmMTQsIDB4MTBmMjIsIDB4MTBmMjgsIDB4MTBmMzYsIDB4MTBmNDIsIDB4MTBmNDQsXG4gICAgICAgIDB4MTBmNDgsIDB4MTBmNTAsIDB4MTBmNWUsIDB4MTBmNjYsIDB4MTBmNmMsIDB4MTBmYjIsIDB4MTBmYjQsIDB4MTEwMjIsIDB4MTEwMjgsIDB4MTEwNDIsIDB4MTEwNDgsIDB4MTEwNTAsXG4gICAgICAgIDB4MTEwNWUsIDB4MTEwN2EsIDB4MTEwODIsIDB4MTEwODQsIDB4MTEwOTAsIDB4MTEwOWUsIDB4MTEwYTAsIDB4MTEwYmMsIDB4MTEwYzYsIDB4MTEwY2MsIDB4MTEwZDgsIDB4MTEwZWUsXG4gICAgICAgIDB4MTEwZjIsIDB4MTEwZjQsIDB4MTExMDIsIDB4MTExMWUsIDB4MTExMjAsIDB4MTExM2MsIDB4MTExNDAsIDB4MTExNzgsIDB4MTExODYsIDB4MTExOTgsIDB4MTExYjAsIDB4MTExYmUsXG4gICAgICAgIDB4MTExY2UsIDB4MTExZGMsIDB4MTExZTIsIDB4MTExZTQsIDB4MTExZTgsIDB4MTExZjYsIDB4MTEyMDgsIDB4MTEyMWUsIDB4MTEyMjAsIDB4MTEyNzgsIDB4MTEyZjAsIDB4MTEzMGMsXG4gICAgICAgIDB4MTEzMzAsIDB4MTEzM2UsIDB4MTEzNjAsIDB4MTEzN2MsIDB4MTEzOGUsIDB4MTEzOWMsIDB4MTEzYjgsIDB4MTEzYzIsIDB4MTEzYzgsIDB4MTEzZDAsIDB4MTEzZGUsIDB4MTEzZTYsXG4gICAgICAgIDB4MTEzZWMsIDB4MTE0MDgsIDB4MTE0MTAsIDB4MTE0MWUsIDB4MTE0MjAsIDB4MTE0M2MsIDB4MTE0NDAsIDB4MTE0NzgsIDB4MTE0ZjAsIDB4MTE1ZTAsIDB4MTE2MGMsIDB4MTE2MTgsXG4gICAgICAgIDB4MTE2MzAsIDB4MTE2M2UsIDB4MTE2NjAsIDB4MTE2N2MsIDB4MTE2YzAsIDB4MTE2ZjgsIDB4MTE3MWMsIDB4MTE3MzgsIDB4MTE3NzAsIDB4MTE3N2UsIDB4MTE3ODIsIDB4MTE3ODQsXG4gICAgICAgIDB4MTE3ODgsIDB4MTE3OTAsIDB4MTE3OWUsIDB4MTE3YTAsIDB4MTE3YmMsIDB4MTE3YzYsIDB4MTE3Y2MsIDB4MTE3ZDgsIDB4MTE3ZWUsIDB4MTE4MmUsIDB4MTE4MzQsIDB4MTE4NGUsXG4gICAgICAgIDB4MTE4NWMsIDB4MTE4NjIsIDB4MTE4NjQsIDB4MTE4NjgsIDB4MTE4NzYsIDB4MTE4OGUsIDB4MTE4OWMsIDB4MTE4YjgsIDB4MTE4YzIsIDB4MTE4YzgsIDB4MTE4ZDAsIDB4MTE4ZGUsXG4gICAgICAgIDB4MTE4ZTYsIDB4MTE4ZWMsIDB4MTE4ZmEsIDB4MTE5MGUsIDB4MTE5MWMsIDB4MTE5MzgsIDB4MTE5NzAsIDB4MTE5N2UsIDB4MTE5ODIsIDB4MTE5ODQsIDB4MTE5OTAsIDB4MTE5OWUsXG4gICAgICAgIDB4MTE5YTAsIDB4MTE5YmMsIDB4MTE5YzYsIDB4MTE5Y2MsIDB4MTE5ZDgsIDB4MTE5ZWUsIDB4MTE5ZjIsIDB4MTE5ZjQsIDB4MTFhMGUsIDB4MTFhMWMsIDB4MTFhMzgsIDB4MTFhNzAsXG4gICAgICAgIDB4MTFhN2UsIDB4MTFhZTAsIDB4MTFhZmMsIDB4MTFiMDgsIDB4MTFiMTAsIDB4MTFiMWUsIDB4MTFiMjAsIDB4MTFiM2MsIDB4MTFiNDAsIDB4MTFiNzgsIDB4MTFiOGMsIDB4MTFiOTgsXG4gICAgICAgIDB4MTFiYjAsIDB4MTFiYmUsIDB4MTFiY2UsIDB4MTFiZGMsIDB4MTFiZTIsIDB4MTFiZTQsIDB4MTFiZTgsIDB4MTFiZjYsIDB4MTFjMTYsIDB4MTFjMjYsIDB4MTFjMmMsIDB4MTFjNDYsXG4gICAgICAgIDB4MTFjNGMsIDB4MTFjNTgsIDB4MTFjNmUsIDB4MTFjODYsIDB4MTFjOTgsIDB4MTFjYjAsIDB4MTFjYmUsIDB4MTFjY2UsIDB4MTFjZGMsIDB4MTFjZTIsIDB4MTFjZTQsIDB4MTFjZTgsXG4gICAgICAgIDB4MTFjZjYsIDB4MTFkMDYsIDB4MTFkMGMsIDB4MTFkMTgsIDB4MTFkMzAsIDB4MTFkM2UsIDB4MTFkNjAsIDB4MTFkN2MsIDB4MTFkOGUsIDB4MTFkOWMsIDB4MTFkYjgsIDB4MTFkYzQsXG4gICAgICAgIDB4MTFkYzgsIDB4MTFkZDAsIDB4MTFkZGUsIDB4MTFkZTYsIDB4MTFkZWMsIDB4MTFkZmEsIDB4MTFlMGEsIDB4MTFlMTIsIDB4MTFlMTQsIDB4MTFlMjIsIDB4MTFlMjQsIDB4MTFlMjgsXG4gICAgICAgIDB4MTFlMzYsIDB4MTFlNDIsIDB4MTFlNDQsIDB4MTFlNTAsIDB4MTFlNWUsIDB4MTFlNjYsIDB4MTFlNmMsIDB4MTFlODIsIDB4MTFlODQsIDB4MTFlODgsIDB4MTFlOTAsIDB4MTFlOWUsXG4gICAgICAgIDB4MTFlYTAsIDB4MTFlYmMsIDB4MTFlYzYsIDB4MTFlY2MsIDB4MTFlZDgsIDB4MTFlZWUsIDB4MTFmMWEsIDB4MTFmMmUsIDB4MTFmMzIsIDB4MTFmMzQsIDB4MTFmNGUsIDB4MTFmNWMsXG4gICAgICAgIDB4MTFmNjIsIDB4MTFmNjQsIDB4MTFmNjgsIDB4MTFmNzYsIDB4MTIwNDgsIDB4MTIwNWUsIDB4MTIwODIsIDB4MTIwODQsIDB4MTIwOTAsIDB4MTIwOWUsIDB4MTIwYTAsIDB4MTIwYmMsXG4gICAgICAgIDB4MTIwZDgsIDB4MTIwZjIsIDB4MTIwZjQsIDB4MTIxMDgsIDB4MTIxMWUsIDB4MTIxMjAsIDB4MTIxM2MsIDB4MTIxNDAsIDB4MTIxNzgsIDB4MTIxODYsIDB4MTIxOTgsIDB4MTIxYjAsXG4gICAgICAgIDB4MTIxYmUsIDB4MTIxZTIsIDB4MTIxZTQsIDB4MTIxZTgsIDB4MTIxZjYsIDB4MTIyMDQsIDB4MTIyMTAsIDB4MTIyMWUsIDB4MTIyMjAsIDB4MTIyNzgsIDB4MTIyZjAsIDB4MTIzMDYsXG4gICAgICAgIDB4MTIzMGMsIDB4MTIzMzAsIDB4MTIzM2UsIDB4MTIzNjAsIDB4MTIzN2MsIDB4MTIzOGUsIDB4MTIzOWMsIDB4MTIzYjgsIDB4MTIzYzIsIDB4MTIzYzgsIDB4MTIzZDAsIDB4MTIzZTYsXG4gICAgICAgIDB4MTIzZWMsIDB4MTI0MWUsIDB4MTI0MjAsIDB4MTI0M2MsIDB4MTI0ZjAsIDB4MTI1ZTAsIDB4MTI2MTgsIDB4MTI2M2UsIDB4MTI2NjAsIDB4MTI2N2MsIDB4MTI2YzAsIDB4MTI2ZjgsXG4gICAgICAgIDB4MTI3MzgsIDB4MTI3NzAsIDB4MTI3N2UsIDB4MTI3ODIsIDB4MTI3ODQsIDB4MTI3OTAsIDB4MTI3OWUsIDB4MTI3YTAsIDB4MTI3YmMsIDB4MTI3YzYsIDB4MTI3Y2MsIDB4MTI3ZDgsXG4gICAgICAgIDB4MTI3ZWUsIDB4MTI4MjAsIDB4MTI4M2MsIDB4MTI4NDAsIDB4MTI4NzgsIDB4MTI4ZjAsIDB4MTI5ZTAsIDB4MTJiYzAsIDB4MTJjMTgsIDB4MTJjMzAsIDB4MTJjM2UsIDB4MTJjNjAsXG4gICAgICAgIDB4MTJjN2MsIDB4MTJjYzAsIDB4MTJjZjgsIDB4MTJkZjAsIDB4MTJlMWMsIDB4MTJlMzgsIDB4MTJlNzAsIDB4MTJlN2UsIDB4MTJlZTAsIDB4MTJlZmMsIDB4MTJmMDQsIDB4MTJmMDgsXG4gICAgICAgIDB4MTJmMTAsIDB4MTJmMjAsIDB4MTJmM2MsIDB4MTJmNDAsIDB4MTJmNzgsIDB4MTJmODYsIDB4MTJmOGMsIDB4MTJmOTgsIDB4MTJmYjAsIDB4MTJmYmUsIDB4MTJmY2UsIDB4MTJmZGMsXG4gICAgICAgIDB4MTMwMmUsIDB4MTMwNGUsIDB4MTMwNWMsIDB4MTMwNjIsIDB4MTMwNjgsIDB4MTMwOGUsIDB4MTMwOWMsIDB4MTMwYjgsIDB4MTMwYzIsIDB4MTMwYzgsIDB4MTMwZDAsIDB4MTMwZGUsXG4gICAgICAgIDB4MTMwZWMsIDB4MTMwZmEsIDB4MTMxMGUsIDB4MTMxMzgsIDB4MTMxNzAsIDB4MTMxN2UsIDB4MTMxODIsIDB4MTMxODQsIDB4MTMxOTAsIDB4MTMxOWUsIDB4MTMxYTAsIDB4MTMxYmMsXG4gICAgICAgIDB4MTMxYzYsIDB4MTMxY2MsIDB4MTMxZDgsIDB4MTMxZjIsIDB4MTMxZjQsIDB4MTMyMGUsIDB4MTMyMWMsIDB4MTMyNzAsIDB4MTMyN2UsIDB4MTMyZTAsIDB4MTMyZmMsIDB4MTMzMDgsXG4gICAgICAgIDB4MTMzMWUsIDB4MTMzMjAsIDB4MTMzM2MsIDB4MTMzNDAsIDB4MTMzNzgsIDB4MTMzODYsIDB4MTMzOTgsIDB4MTMzYjAsIDB4MTMzYmUsIDB4MTMzY2UsIDB4MTMzZGMsIDB4MTMzZTIsXG4gICAgICAgIDB4MTMzZTQsIDB4MTMzZTgsIDB4MTMzZjYsIDB4MTM0MGUsIDB4MTM0MWMsIDB4MTM0MzgsIDB4MTM0NzAsIDB4MTM0N2UsIDB4MTM0ZTAsIDB4MTM0ZmMsIDB4MTM1YzAsIDB4MTM1ZjgsXG4gICAgICAgIDB4MTM2MDgsIDB4MTM2MTAsIDB4MTM2MWUsIDB4MTM2MjAsIDB4MTM2M2MsIDB4MTM2NDAsIDB4MTM2NzgsIDB4MTM2ZjAsIDB4MTM3MGMsIDB4MTM3MTgsIDB4MTM3MzAsIDB4MTM3M2UsXG4gICAgICAgIDB4MTM3NjAsIDB4MTM3N2MsIDB4MTM3OWMsIDB4MTM3YjgsIDB4MTM3YzIsIDB4MTM3YzQsIDB4MTM3YzgsIDB4MTM3ZDAsIDB4MTM3ZGUsIDB4MTM3ZTYsIDB4MTM3ZWMsIDB4MTM4MTYsXG4gICAgICAgIDB4MTM4MjYsIDB4MTM4MmMsIDB4MTM4NDYsIDB4MTM4NGMsIDB4MTM4NTgsIDB4MTM4NmUsIDB4MTM4NzQsIDB4MTM4ODYsIDB4MTM4OTgsIDB4MTM4YjAsIDB4MTM4YmUsIDB4MTM4Y2UsXG4gICAgICAgIDB4MTM4ZGMsIDB4MTM4ZTIsIDB4MTM4ZTQsIDB4MTM4ZTgsIDB4MTM5MDYsIDB4MTM5MGMsIDB4MTM5MzAsIDB4MTM5M2UsIDB4MTM5NjAsIDB4MTM5N2MsIDB4MTM5OGUsIDB4MTM5OWMsXG4gICAgICAgIDB4MTM5YjgsIDB4MTM5YzgsIDB4MTM5ZDAsIDB4MTM5ZGUsIDB4MTM5ZTYsIDB4MTM5ZWMsIDB4MTM5ZmEsIDB4MTNhMDYsIDB4MTNhMGMsIDB4MTNhMTgsIDB4MTNhMzAsIDB4MTNhM2UsXG4gICAgICAgIDB4MTNhNjAsIDB4MTNhN2MsIDB4MTNhYzAsIDB4MTNhZjgsIDB4MTNiMGUsIDB4MTNiMWMsIDB4MTNiMzgsIDB4MTNiNzAsIDB4MTNiN2UsIDB4MTNiODgsIDB4MTNiOTAsIDB4MTNiOWUsXG4gICAgICAgIDB4MTNiYTAsIDB4MTNiYmMsIDB4MTNiY2MsIDB4MTNiZDgsIDB4MTNiZWUsIDB4MTNiZjIsIDB4MTNiZjQsIDB4MTNjMTIsIDB4MTNjMTQsIDB4MTNjMjIsIDB4MTNjMjQsIDB4MTNjMjgsXG4gICAgICAgIDB4MTNjMzYsIDB4MTNjNDIsIDB4MTNjNDgsIDB4MTNjNTAsIDB4MTNjNWUsIDB4MTNjNjYsIDB4MTNjNmMsIDB4MTNjODIsIDB4MTNjODQsIDB4MTNjOTAsIDB4MTNjOWUsIDB4MTNjYTAsXG4gICAgICAgIDB4MTNjYmMsIDB4MTNjYzYsIDB4MTNjY2MsIDB4MTNjZDgsIDB4MTNjZWUsIDB4MTNkMDIsIDB4MTNkMDQsIDB4MTNkMDgsIDB4MTNkMTAsIDB4MTNkMWUsIDB4MTNkMjAsIDB4MTNkM2MsXG4gICAgICAgIDB4MTNkNDAsIDB4MTNkNzgsIDB4MTNkODYsIDB4MTNkOGMsIDB4MTNkOTgsIDB4MTNkYjAsIDB4MTNkYmUsIDB4MTNkY2UsIDB4MTNkZGMsIDB4MTNkZTQsIDB4MTNkZTgsIDB4MTNkZjYsXG4gICAgICAgIDB4MTNlMWEsIDB4MTNlMmUsIDB4MTNlMzIsIDB4MTNlMzQsIDB4MTNlNGUsIDB4MTNlNWMsIDB4MTNlNjIsIDB4MTNlNjQsIDB4MTNlNjgsIDB4MTNlNzYsIDB4MTNlOGUsIDB4MTNlOWMsXG4gICAgICAgIDB4MTNlYjgsIDB4MTNlYzIsIDB4MTNlYzQsIDB4MTNlYzgsIDB4MTNlZDAsIDB4MTNlZGUsIDB4MTNlZTYsIDB4MTNlZWMsIDB4MTNmMjYsIDB4MTNmMmMsIDB4MTNmM2EsIDB4MTNmNDYsXG4gICAgICAgIDB4MTNmNGMsIDB4MTNmNTgsIDB4MTNmNmUsIDB4MTNmNzIsIDB4MTNmNzQsIDB4MTQwODIsIDB4MTQwOWUsIDB4MTQwYTAsIDB4MTQwYmMsIDB4MTQxMDQsIDB4MTQxMDgsIDB4MTQxMTAsXG4gICAgICAgIDB4MTQxMWUsIDB4MTQxMjAsIDB4MTQxM2MsIDB4MTQxNDAsIDB4MTQxNzgsIDB4MTQxOGMsIDB4MTQxOTgsIDB4MTQxYjAsIDB4MTQxYmUsIDB4MTQxZTIsIDB4MTQxZTQsIDB4MTQxZTgsXG4gICAgICAgIDB4MTQyMDgsIDB4MTQyMTAsIDB4MTQyMWUsIDB4MTQyMjAsIDB4MTQyM2MsIDB4MTQyNDAsIDB4MTQyNzgsIDB4MTQyZjAsIDB4MTQzMDYsIDB4MTQzMGMsIDB4MTQzMTgsIDB4MTQzMzAsXG4gICAgICAgIDB4MTQzM2UsIDB4MTQzNjAsIDB4MTQzN2MsIDB4MTQzOGUsIDB4MTQzYzIsIDB4MTQzYzQsIDB4MTQzYzgsIDB4MTQzZDAsIDB4MTQzZTYsIDB4MTQzZWMsIDB4MTQ0MDgsIDB4MTQ0MTAsXG4gICAgICAgIDB4MTQ0MWUsIDB4MTQ0MjAsIDB4MTQ0M2MsIDB4MTQ0NDAsIDB4MTQ0NzgsIDB4MTQ0ZjAsIDB4MTQ1ZTAsIDB4MTQ2MGMsIDB4MTQ2MTgsIDB4MTQ2MzAsIDB4MTQ2M2UsIDB4MTQ2NjAsXG4gICAgICAgIDB4MTQ2N2MsIDB4MTQ2YzAsIDB4MTQ2ZjgsIDB4MTQ3MWMsIDB4MTQ3MzgsIDB4MTQ3NzAsIDB4MTQ3N2UsIDB4MTQ3ODIsIDB4MTQ3ODQsIDB4MTQ3ODgsIDB4MTQ3OTAsIDB4MTQ3YTAsXG4gICAgICAgIDB4MTQ3YmMsIDB4MTQ3YzYsIDB4MTQ3Y2MsIDB4MTQ3ZDgsIDB4MTQ3ZWUsIDB4MTQ4MTAsIDB4MTQ4MjAsIDB4MTQ4M2MsIDB4MTQ4NDAsIDB4MTQ4NzgsIDB4MTQ4ZjAsIDB4MTQ5ZTAsXG4gICAgICAgIDB4MTRiYzAsIDB4MTRjMzAsIDB4MTRjM2UsIDB4MTRjNjAsIDB4MTRjN2MsIDB4MTRjYzAsIDB4MTRjZjgsIDB4MTRkZjAsIDB4MTRlMzgsIDB4MTRlNzAsIDB4MTRlN2UsIDB4MTRlZTAsXG4gICAgICAgIDB4MTRlZmMsIDB4MTRmMDQsIDB4MTRmMDgsIDB4MTRmMTAsIDB4MTRmMWUsIDB4MTRmMjAsIDB4MTRmM2MsIDB4MTRmNDAsIDB4MTRmNzgsIDB4MTRmODYsIDB4MTRmOGMsIDB4MTRmOTgsXG4gICAgICAgIDB4MTRmYjAsIDB4MTRmY2UsIDB4MTRmZGMsIDB4MTUwMjAsIDB4MTUwNDAsIDB4MTUwNzgsIDB4MTUwZjAsIDB4MTUxZTAsIDB4MTUzYzAsIDB4MTU4NjAsIDB4MTU4N2MsIDB4MTU4YzAsXG4gICAgICAgIDB4MTU4ZjgsIDB4MTU5ZjAsIDB4MTViZTAsIDB4MTVjNzAsIDB4MTVjN2UsIDB4MTVjZTAsIDB4MTVjZmMsIDB4MTVkYzAsIDB4MTVkZjgsIDB4MTVlMDgsIDB4MTVlMTAsIDB4MTVlMjAsXG4gICAgICAgIDB4MTVlNDAsIDB4MTVlNzgsIDB4MTVlZjAsIDB4MTVmMGMsIDB4MTVmMTgsIDB4MTVmMzAsIDB4MTVmNjAsIDB4MTVmN2MsIDB4MTVmOGUsIDB4MTVmOWMsIDB4MTVmYjgsIDB4MTYwNGUsXG4gICAgICAgIDB4MTYwNWMsIDB4MTYwOGUsIDB4MTYwOWMsIDB4MTYwYjgsIDB4MTYwYzIsIDB4MTYwYzQsIDB4MTYwYzgsIDB4MTYwZGUsIDB4MTYxMGUsIDB4MTYxMWMsIDB4MTYxMzgsIDB4MTYxNzAsXG4gICAgICAgIDB4MTYxN2UsIDB4MTYxODQsIDB4MTYxODgsIDB4MTYxOTAsIDB4MTYxOWUsIDB4MTYxYTAsIDB4MTYxYmMsIDB4MTYxYzYsIDB4MTYxY2MsIDB4MTYxZDgsIDB4MTYxZjIsIDB4MTYxZjQsXG4gICAgICAgIDB4MTYyMGUsIDB4MTYyMWMsIDB4MTYyMzgsIDB4MTYyNzAsIDB4MTYyN2UsIDB4MTYyZTAsIDB4MTYyZmMsIDB4MTYzMDQsIDB4MTYzMDgsIDB4MTYzMTAsIDB4MTYzMWUsIDB4MTYzMjAsXG4gICAgICAgIDB4MTYzM2MsIDB4MTYzNDAsIDB4MTYzNzgsIDB4MTYzODYsIDB4MTYzOGMsIDB4MTYzOTgsIDB4MTYzYjAsIDB4MTYzYmUsIDB4MTYzY2UsIDB4MTYzZGMsIDB4MTYzZTIsIDB4MTYzZTQsXG4gICAgICAgIDB4MTYzZTgsIDB4MTYzZjYsIDB4MTY0MGUsIDB4MTY0MWMsIDB4MTY0MzgsIDB4MTY0NzAsIDB4MTY0N2UsIDB4MTY0ZTAsIDB4MTY0ZmMsIDB4MTY1YzAsIDB4MTY1ZjgsIDB4MTY2MTAsXG4gICAgICAgIDB4MTY2MWUsIDB4MTY2MjAsIDB4MTY2M2MsIDB4MTY2NDAsIDB4MTY2NzgsIDB4MTY2ZjAsIDB4MTY3MTgsIDB4MTY3MzAsIDB4MTY3M2UsIDB4MTY3NjAsIDB4MTY3N2MsIDB4MTY3OGUsXG4gICAgICAgIDB4MTY3OWMsIDB4MTY3YjgsIDB4MTY3YzIsIDB4MTY3YzQsIDB4MTY3YzgsIDB4MTY3ZDAsIDB4MTY3ZGUsIDB4MTY3ZTYsIDB4MTY3ZWMsIDB4MTY4MWMsIDB4MTY4MzgsIDB4MTY4NzAsXG4gICAgICAgIDB4MTY4ZTAsIDB4MTY4ZmMsIDB4MTY5YzAsIDB4MTY5ZjgsIDB4MTZiZjAsIDB4MTZjMTAsIDB4MTZjMWUsIDB4MTZjMjAsIDB4MTZjM2MsIDB4MTZjNDAsIDB4MTZjNzgsIDB4MTZjZjAsXG4gICAgICAgIDB4MTZkZTAsIDB4MTZlMTgsIDB4MTZlMzAsIDB4MTZlM2UsIDB4MTZlNjAsIDB4MTZlN2MsIDB4MTZlYzAsIDB4MTZlZjgsIDB4MTZmMWMsIDB4MTZmMzgsIDB4MTZmNzAsIDB4MTZmN2UsXG4gICAgICAgIDB4MTZmODQsIDB4MTZmODgsIDB4MTZmOTAsIDB4MTZmOWUsIDB4MTZmYTAsIDB4MTZmYmMsIDB4MTZmYzYsIDB4MTZmY2MsIDB4MTZmZDgsIDB4MTcwMjYsIDB4MTcwMmMsIDB4MTcwNDYsXG4gICAgICAgIDB4MTcwNGMsIDB4MTcwNTgsIDB4MTcwNmUsIDB4MTcwODYsIDB4MTcwOGMsIDB4MTcwOTgsIDB4MTcwYjAsIDB4MTcwYmUsIDB4MTcwY2UsIDB4MTcwZGMsIDB4MTcwZTgsIDB4MTcxMDYsXG4gICAgICAgIDB4MTcxMGMsIDB4MTcxMTgsIDB4MTcxMzAsIDB4MTcxM2UsIDB4MTcxNjAsIDB4MTcxN2MsIDB4MTcxOGUsIDB4MTcxOWMsIDB4MTcxYjgsIDB4MTcxYzIsIDB4MTcxYzQsIDB4MTcxYzgsXG4gICAgICAgIDB4MTcxZDAsIDB4MTcxZGUsIDB4MTcxZTYsIDB4MTcxZWMsIDB4MTcxZmEsIDB4MTcyMDYsIDB4MTcyMGMsIDB4MTcyMTgsIDB4MTcyMzAsIDB4MTcyM2UsIDB4MTcyNjAsIDB4MTcyN2MsXG4gICAgICAgIDB4MTcyYzAsIDB4MTcyZjgsIDB4MTczMGUsIDB4MTczMWMsIDB4MTczMzgsIDB4MTczNzAsIDB4MTczN2UsIDB4MTczODgsIDB4MTczOTAsIDB4MTczOWUsIDB4MTczYTAsIDB4MTczYmMsXG4gICAgICAgIDB4MTczY2MsIDB4MTczZDgsIDB4MTczZWUsIDB4MTczZjIsIDB4MTczZjQsIDB4MTc0MGMsIDB4MTc0MTgsIDB4MTc0MzAsIDB4MTc0M2UsIDB4MTc0NjAsIDB4MTc0N2MsIDB4MTc0YzAsXG4gICAgICAgIDB4MTc0ZjgsIDB4MTc1ZjAsIDB4MTc2MGUsIDB4MTc2MWMsIDB4MTc2MzgsIDB4MTc2NzAsIDB4MTc2N2UsIDB4MTc2ZTAsIDB4MTc2ZmMsIDB4MTc3MDgsIDB4MTc3MTAsIDB4MTc3MWUsXG4gICAgICAgIDB4MTc3MjAsIDB4MTc3M2MsIDB4MTc3NDAsIDB4MTc3NzgsIDB4MTc3OTgsIDB4MTc3YjAsIDB4MTc3YmUsIDB4MTc3ZGMsIDB4MTc3ZTIsIDB4MTc3ZTQsIDB4MTc3ZTgsIDB4MTc4MjIsXG4gICAgICAgIDB4MTc4MjQsIDB4MTc4MjgsIDB4MTc4MzYsIDB4MTc4NDIsIDB4MTc4NDQsIDB4MTc4NDgsIDB4MTc4NTAsIDB4MTc4NWUsIDB4MTc4NjYsIDB4MTc4NmMsIDB4MTc4ODIsIDB4MTc4ODQsXG4gICAgICAgIDB4MTc4ODgsIDB4MTc4OTAsIDB4MTc4OWUsIDB4MTc4YTAsIDB4MTc4YmMsIDB4MTc4YzYsIDB4MTc4Y2MsIDB4MTc4ZDgsIDB4MTc4ZWUsIDB4MTc4ZjIsIDB4MTc4ZjQsIDB4MTc5MDIsXG4gICAgICAgIDB4MTc5MDQsIDB4MTc5MDgsIDB4MTc5MTAsIDB4MTc5MWUsIDB4MTc5MjAsIDB4MTc5M2MsIDB4MTc5NDAsIDB4MTc5NzgsIDB4MTc5ODYsIDB4MTc5OGMsIDB4MTc5OTgsIDB4MTc5YjAsXG4gICAgICAgIDB4MTc5YmUsIDB4MTc5Y2UsIDB4MTc5ZGMsIDB4MTc5ZTIsIDB4MTc5ZTQsIDB4MTc5ZTgsIDB4MTc5ZjYsIDB4MTdhMDQsIDB4MTdhMDgsIDB4MTdhMTAsIDB4MTdhMWUsIDB4MTdhMjAsXG4gICAgICAgIDB4MTdhM2MsIDB4MTdhNDAsIDB4MTdhNzgsIDB4MTdhZjAsIDB4MTdiMDYsIDB4MTdiMGMsIDB4MTdiMTgsIDB4MTdiMzAsIDB4MTdiM2UsIDB4MTdiNjAsIDB4MTdiN2MsIDB4MTdiOGUsXG4gICAgICAgIDB4MTdiOWMsIDB4MTdiYjgsIDB4MTdiYzQsIDB4MTdiYzgsIDB4MTdiZDAsIDB4MTdiZGUsIDB4MTdiZTYsIDB4MTdiZWMsIDB4MTdjMmUsIDB4MTdjMzIsIDB4MTdjMzQsIDB4MTdjNGUsXG4gICAgICAgIDB4MTdjNWMsIDB4MTdjNjIsIDB4MTdjNjQsIDB4MTdjNjgsIDB4MTdjNzYsIDB4MTdjOGUsIDB4MTdjOWMsIDB4MTdjYjgsIDB4MTdjYzIsIDB4MTdjYzQsIDB4MTdjYzgsIDB4MTdjZDAsXG4gICAgICAgIDB4MTdjZGUsIDB4MTdjZTYsIDB4MTdjZWMsIDB4MTdkMGUsIDB4MTdkMWMsIDB4MTdkMzgsIDB4MTdkNzAsIDB4MTdkODIsIDB4MTdkODQsIDB4MTdkODgsIDB4MTdkOTAsIDB4MTdkOWUsXG4gICAgICAgIDB4MTdkYTAsIDB4MTdkYmMsIDB4MTdkYzYsIDB4MTdkY2MsIDB4MTdkZDgsIDB4MTdkZWUsIDB4MTdlMjYsIDB4MTdlMmMsIDB4MTdlM2EsIDB4MTdlNDYsIDB4MTdlNGMsIDB4MTdlNTgsXG4gICAgICAgIDB4MTdlNmUsIDB4MTdlNzIsIDB4MTdlNzQsIDB4MTdlODYsIDB4MTdlOGMsIDB4MTdlOTgsIDB4MTdlYjAsIDB4MTdlY2UsIDB4MTdlZGMsIDB4MTdlZTIsIDB4MTdlZTQsIDB4MTdlZTgsXG4gICAgICAgIDB4MTdlZjYsIDB4MTgxM2EsIDB4MTgxNzIsIDB4MTgxNzQsIDB4MTgyMTYsIDB4MTgyMjYsIDB4MTgyM2EsIDB4MTgyNGMsIDB4MTgyNTgsIDB4MTgyNmUsIDB4MTgyNzIsIDB4MTgyNzQsXG4gICAgICAgIDB4MTgyOTgsIDB4MTgyYmUsIDB4MTgyZTIsIDB4MTgyZTQsIDB4MTgyZTgsIDB4MTgyZjYsIDB4MTgzNWUsIDB4MTgzN2EsIDB4MTgzYWUsIDB4MTgzZDYsIDB4MTg0MTYsIDB4MTg0MjYsXG4gICAgICAgIDB4MTg0MmMsIDB4MTg0M2EsIDB4MTg0NDYsIDB4MTg0NTgsIDB4MTg0NmUsIDB4MTg0NzIsIDB4MTg0NzQsIDB4MTg0ODYsIDB4MTg0YjAsIDB4MTg0YmUsIDB4MTg0Y2UsIDB4MTg0ZGMsXG4gICAgICAgIDB4MTg0ZTIsIDB4MTg0ZTQsIDB4MTg0ZTgsIDB4MTg0ZjYsIDB4MTg1MDYsIDB4MTg1MGMsIDB4MTg1MTgsIDB4MTg1MzAsIDB4MTg1M2UsIDB4MTg1NjAsIDB4MTg1N2MsIDB4MTg1OGUsXG4gICAgICAgIDB4MTg1OWMsIDB4MTg1YjgsIDB4MTg1YzIsIDB4MTg1YzQsIDB4MTg1YzgsIDB4MTg1ZDAsIDB4MTg1ZGUsIDB4MTg1ZTYsIDB4MTg1ZWMsIDB4MTg1ZmEsIDB4MTg2MTIsIDB4MTg2MTQsXG4gICAgICAgIDB4MTg2MjIsIDB4MTg2MjgsIDB4MTg2MzYsIDB4MTg2NDIsIDB4MTg2NTAsIDB4MTg2NWUsIDB4MTg2N2EsIDB4MTg2ODIsIDB4MTg2ODQsIDB4MTg2ODgsIDB4MTg2OTAsIDB4MTg2OWUsXG4gICAgICAgIDB4MTg2YTAsIDB4MTg2YmMsIDB4MTg2YzYsIDB4MTg2Y2MsIDB4MTg2ZDgsIDB4MTg2ZWUsIDB4MTg2ZjIsIDB4MTg2ZjQsIDB4MTg3MmUsIDB4MTg3NGUsIDB4MTg3NWMsIDB4MTg3OTYsXG4gICAgICAgIDB4MTg3YTYsIDB4MTg3YWMsIDB4MTg3ZDIsIDB4MTg3ZDQsIDB4MTg4MjYsIDB4MTg4MmMsIDB4MTg4M2EsIDB4MTg4NDYsIDB4MTg4NGMsIDB4MTg4NTgsIDB4MTg4NmUsIDB4MTg4NzIsXG4gICAgICAgIDB4MTg4NzQsIDB4MTg4ODYsIDB4MTg4OTgsIDB4MTg4YjAsIDB4MTg4YmUsIDB4MTg4Y2UsIDB4MTg4ZGMsIDB4MTg4ZTIsIDB4MTg4ZTQsIDB4MTg4ZTgsIDB4MTg4ZjYsIDB4MTg5MGMsXG4gICAgICAgIDB4MTg5MzAsIDB4MTg5M2UsIDB4MTg5NjAsIDB4MTg5N2MsIDB4MTg5OGUsIDB4MTg5YjgsIDB4MTg5YzIsIDB4MTg5YzgsIDB4MTg5ZDAsIDB4MTg5ZGUsIDB4MTg5ZTYsIDB4MTg5ZWMsXG4gICAgICAgIDB4MTg5ZmEsIDB4MThhMTgsIDB4MThhMzAsIDB4MThhM2UsIDB4MThhNjAsIDB4MThhN2MsIDB4MThhYzAsIDB4MThhZjgsIDB4MThiMWMsIDB4MThiMzgsIDB4MThiNzAsIDB4MThiN2UsXG4gICAgICAgIDB4MThiODIsIDB4MThiODQsIDB4MThiODgsIDB4MThiOTAsIDB4MThiOWUsIDB4MThiYTAsIDB4MThiYmMsIDB4MThiYzYsIDB4MThiY2MsIDB4MThiZDgsIDB4MThiZWUsIDB4MThiZjIsXG4gICAgICAgIDB4MThiZjQsIDB4MThjMjIsIDB4MThjMjQsIDB4MThjMjgsIDB4MThjMzYsIDB4MThjNDIsIDB4MThjNDgsIDB4MThjNTAsIDB4MThjNWUsIDB4MThjNjYsIDB4MThjN2EsIDB4MThjODIsXG4gICAgICAgIDB4MThjODQsIDB4MThjOTAsIDB4MThjOWUsIDB4MThjYTAsIDB4MThjYmMsIDB4MThjY2MsIDB4MThjZjIsIDB4MThjZjQsIDB4MThkMDQsIDB4MThkMDgsIDB4MThkMTAsIDB4MThkMWUsXG4gICAgICAgIDB4MThkMjAsIDB4MThkM2MsIDB4MThkNDAsIDB4MThkNzgsIDB4MThkODYsIDB4MThkOTgsIDB4MThkY2UsIDB4MThkZTIsIDB4MThkZTQsIDB4MThkZTgsIDB4MThlMmUsIDB4MThlMzIsXG4gICAgICAgIDB4MThlMzQsIDB4MThlNGUsIDB4MThlNWMsIDB4MThlNjIsIDB4MThlNjQsIDB4MThlNjgsIDB4MThlOGUsIDB4MThlOWMsIDB4MThlYjgsIDB4MThlYzIsIDB4MThlYzQsIDB4MThlYzgsXG4gICAgICAgIDB4MThlZDAsIDB4MThlZmEsIDB4MThmMTYsIDB4MThmMjYsIDB4MThmMmMsIDB4MThmNDYsIDB4MThmNGMsIDB4MThmNTgsIDB4MThmNmUsIDB4MThmOGEsIDB4MThmOTIsIDB4MThmOTQsXG4gICAgICAgIDB4MThmYTIsIDB4MThmYTQsIDB4MThmYTgsIDB4MThmYjYsIDB4MTkwMmMsIDB4MTkwM2EsIDB4MTkwNDYsIDB4MTkwNGMsIDB4MTkwNTgsIDB4MTkwNzIsIDB4MTkwNzQsIDB4MTkwODYsXG4gICAgICAgIDB4MTkwOTgsIDB4MTkwYjAsIDB4MTkwYmUsIDB4MTkwY2UsIDB4MTkwZGMsIDB4MTkwZTIsIDB4MTkwZTgsIDB4MTkwZjYsIDB4MTkxMDYsIDB4MTkxMGMsIDB4MTkxMzAsIDB4MTkxM2UsXG4gICAgICAgIDB4MTkxNjAsIDB4MTkxN2MsIDB4MTkxOGUsIDB4MTkxOWMsIDB4MTkxYjgsIDB4MTkxYzIsIDB4MTkxYzgsIDB4MTkxZDAsIDB4MTkxZGUsIDB4MTkxZTYsIDB4MTkxZWMsIDB4MTkxZmEsXG4gICAgICAgIDB4MTkyMTgsIDB4MTkyM2UsIDB4MTkyNjAsIDB4MTkyN2MsIDB4MTkyYzAsIDB4MTkyZjgsIDB4MTkzMzgsIDB4MTkzNzAsIDB4MTkzN2UsIDB4MTkzODIsIDB4MTkzODQsIDB4MTkzOTAsXG4gICAgICAgIDB4MTkzOWUsIDB4MTkzYTAsIDB4MTkzYmMsIDB4MTkzYzYsIDB4MTkzY2MsIDB4MTkzZDgsIDB4MTkzZWUsIDB4MTkzZjIsIDB4MTkzZjQsIDB4MTk0MzAsIDB4MTk0M2UsIDB4MTk0NjAsXG4gICAgICAgIDB4MTk0N2MsIDB4MTk0YzAsIDB4MTk0ZjgsIDB4MTk1ZjAsIDB4MTk2MzgsIDB4MTk2NzAsIDB4MTk2N2UsIDB4MTk2ZTAsIDB4MTk2ZmMsIDB4MTk3MDIsIDB4MTk3MDQsIDB4MTk3MDgsXG4gICAgICAgIDB4MTk3MTAsIDB4MTk3MjAsIDB4MTk3M2MsIDB4MTk3NDAsIDB4MTk3NzgsIDB4MTk3ODYsIDB4MTk3OGMsIDB4MTk3OTgsIDB4MTk3YjAsIDB4MTk3YmUsIDB4MTk3Y2UsIDB4MTk3ZGMsXG4gICAgICAgIDB4MTk3ZTIsIDB4MTk3ZTQsIDB4MTk3ZTgsIDB4MTk4MjIsIDB4MTk4MjQsIDB4MTk4NDIsIDB4MTk4NDgsIDB4MTk4NTAsIDB4MTk4NWUsIDB4MTk4NjYsIDB4MTk4N2EsIDB4MTk4ODIsXG4gICAgICAgIDB4MTk4ODQsIDB4MTk4OTAsIDB4MTk4OWUsIDB4MTk4YTAsIDB4MTk4YmMsIDB4MTk4Y2MsIDB4MTk4ZjIsIDB4MTk4ZjQsIDB4MTk5MDIsIDB4MTk5MDgsIDB4MTk5MWUsIDB4MTk5MjAsXG4gICAgICAgIDB4MTk5M2MsIDB4MTk5NDAsIDB4MTk5NzgsIDB4MTk5ODYsIDB4MTk5OTgsIDB4MTk5Y2UsIDB4MTk5ZTIsIDB4MTk5ZTQsIDB4MTk5ZTgsIDB4MTlhMDgsIDB4MTlhMTAsIDB4MTlhMWUsXG4gICAgICAgIDB4MTlhMjAsIDB4MTlhM2MsIDB4MTlhNDAsIDB4MTlhNzgsIDB4MTlhZjAsIDB4MTliMTgsIDB4MTliM2UsIDB4MTliNjAsIDB4MTliOWMsIDB4MTliYzIsIDB4MTliYzQsIDB4MTliYzgsXG4gICAgICAgIDB4MTliZDAsIDB4MTliZTYsIDB4MTljMmUsIDB4MTljMzQsIDB4MTljNGUsIDB4MTljNWMsIDB4MTljNjIsIDB4MTljNjQsIDB4MTljNjgsIDB4MTljOGUsIDB4MTljOWMsIDB4MTljYjgsXG4gICAgICAgIDB4MTljYzIsIDB4MTljYzgsIDB4MTljZDAsIDB4MTljZTYsIDB4MTljZmEsIDB4MTlkMGUsIDB4MTlkMWMsIDB4MTlkMzgsIDB4MTlkNzAsIDB4MTlkN2UsIDB4MTlkODIsIDB4MTlkODQsXG4gICAgICAgIDB4MTlkODgsIDB4MTlkOTAsIDB4MTlkYTAsIDB4MTlkY2MsIDB4MTlkZjIsIDB4MTlkZjQsIDB4MTllMTYsIDB4MTllMjYsIDB4MTllMmMsIDB4MTllNDYsIDB4MTllNGMsIDB4MTllNTgsXG4gICAgICAgIDB4MTllNzQsIDB4MTllODYsIDB4MTllOGMsIDB4MTllOTgsIDB4MTllYjAsIDB4MTllYmUsIDB4MTllY2UsIDB4MTllZTIsIDB4MTllZTQsIDB4MTllZTgsIDB4MTlmMGEsIDB4MTlmMTIsXG4gICAgICAgIDB4MTlmMTQsIDB4MTlmMjIsIDB4MTlmMjQsIDB4MTlmMjgsIDB4MTlmNDIsIDB4MTlmNDQsIDB4MTlmNDgsIDB4MTlmNTAsIDB4MTlmNWUsIDB4MTlmNmMsIDB4MTlmOWEsIDB4MTlmYWUsXG4gICAgICAgIDB4MTlmYjIsIDB4MTlmYjQsIDB4MWEwNDYsIDB4MWEwNGMsIDB4MWEwNzIsIDB4MWEwNzQsIDB4MWEwODYsIDB4MWEwOGMsIDB4MWEwOTgsIDB4MWEwYjAsIDB4MWEwYmUsIDB4MWEwZTIsXG4gICAgICAgIDB4MWEwZTQsIDB4MWEwZTgsIDB4MWEwZjYsIDB4MWExMDYsIDB4MWExMGMsIDB4MWExMTgsIDB4MWExMzAsIDB4MWExM2UsIDB4MWExNjAsIDB4MWExN2MsIDB4MWExOGUsIDB4MWExOWMsXG4gICAgICAgIDB4MWExYjgsIDB4MWExYzIsIDB4MWExYzQsIDB4MWExYzgsIDB4MWExZDAsIDB4MWExZGUsIDB4MWExZTYsIDB4MWExZWMsIDB4MWEyMTgsIDB4MWEyMzAsIDB4MWEyM2UsIDB4MWEyNjAsXG4gICAgICAgIDB4MWEyN2MsIDB4MWEyYzAsIDB4MWEyZjgsIDB4MWEzMWMsIDB4MWEzMzgsIDB4MWEzNzAsIDB4MWEzN2UsIDB4MWEzODIsIDB4MWEzODQsIDB4MWEzODgsIDB4MWEzOTAsIDB4MWEzOWUsXG4gICAgICAgIDB4MWEzYTAsIDB4MWEzYmMsIDB4MWEzYzYsIDB4MWEzY2MsIDB4MWEzZDgsIDB4MWEzZWUsIDB4MWEzZjIsIDB4MWEzZjQsIDB4MWE0MTgsIDB4MWE0MzAsIDB4MWE0M2UsIDB4MWE0NjAsXG4gICAgICAgIDB4MWE0N2MsIDB4MWE0YzAsIDB4MWE0ZjgsIDB4MWE1ZjAsIDB4MWE2MWMsIDB4MWE2MzgsIDB4MWE2NzAsIDB4MWE2N2UsIDB4MWE2ZTAsIDB4MWE2ZmMsIDB4MWE3MDIsIDB4MWE3MDQsXG4gICAgICAgIDB4MWE3MDgsIDB4MWE3MTAsIDB4MWE3MWUsIDB4MWE3MjAsIDB4MWE3M2MsIDB4MWE3NDAsIDB4MWE3NzgsIDB4MWE3ODYsIDB4MWE3OGMsIDB4MWE3OTgsIDB4MWE3YjAsIDB4MWE3YmUsXG4gICAgICAgIDB4MWE3Y2UsIDB4MWE3ZGMsIDB4MWE3ZTIsIDB4MWE3ZTQsIDB4MWE3ZTgsIDB4MWE4MzAsIDB4MWE4NjAsIDB4MWE4N2MsIDB4MWE4YzAsIDB4MWE4ZjgsIDB4MWE5ZjAsIDB4MWFiZTAsXG4gICAgICAgIDB4MWFjNzAsIDB4MWFjN2UsIDB4MWFjZTAsIDB4MWFjZmMsIDB4MWFkYzAsIDB4MWFkZjgsIDB4MWFlMDQsIDB4MWFlMDgsIDB4MWFlMTAsIDB4MWFlMjAsIDB4MWFlM2MsIDB4MWFlNDAsXG4gICAgICAgIDB4MWFlNzgsIDB4MWFlZjAsIDB4MWFmMDYsIDB4MWFmMGMsIDB4MWFmMTgsIDB4MWFmMzAsIDB4MWFmM2UsIDB4MWFmNjAsIDB4MWFmN2MsIDB4MWFmOGUsIDB4MWFmOWMsIDB4MWFmYjgsXG4gICAgICAgIDB4MWFmYzQsIDB4MWFmYzgsIDB4MWFmZDAsIDB4MWFmZGUsIDB4MWIwNDIsIDB4MWIwNWUsIDB4MWIwN2EsIDB4MWIwODIsIDB4MWIwODQsIDB4MWIwODgsIDB4MWIwOTAsIDB4MWIwOWUsXG4gICAgICAgIDB4MWIwYTAsIDB4MWIwYmMsIDB4MWIwY2MsIDB4MWIwZjIsIDB4MWIwZjQsIDB4MWIxMDIsIDB4MWIxMDQsIDB4MWIxMDgsIDB4MWIxMTAsIDB4MWIxMWUsIDB4MWIxMjAsIDB4MWIxM2MsXG4gICAgICAgIDB4MWIxNDAsIDB4MWIxNzgsIDB4MWIxODYsIDB4MWIxOTgsIDB4MWIxY2UsIDB4MWIxZTIsIDB4MWIxZTQsIDB4MWIxZTgsIDB4MWIyMDQsIDB4MWIyMDgsIDB4MWIyMTAsIDB4MWIyMWUsXG4gICAgICAgIDB4MWIyMjAsIDB4MWIyM2MsIDB4MWIyNDAsIDB4MWIyNzgsIDB4MWIyZjAsIDB4MWIzMGMsIDB4MWIzM2UsIDB4MWIzNjAsIDB4MWIzOWMsIDB4MWIzYzIsIDB4MWIzYzQsIDB4MWIzYzgsXG4gICAgICAgIDB4MWIzZDAsIDB4MWIzZTYsIDB4MWI0MTAsIDB4MWI0MWUsIDB4MWI0MjAsIDB4MWI0M2MsIDB4MWI0NDAsIDB4MWI0NzgsIDB4MWI0ZjAsIDB4MWI1ZTAsIDB4MWI2MTgsIDB4MWI2NjAsXG4gICAgICAgIDB4MWI2N2MsIDB4MWI2YzAsIDB4MWI3MzgsIDB4MWI3ODIsIDB4MWI3ODQsIDB4MWI3ODgsIDB4MWI3OTAsIDB4MWI3OWUsIDB4MWI3YTAsIDB4MWI3Y2MsIDB4MWI4MmUsIDB4MWI4NGUsXG4gICAgICAgIDB4MWI4NWMsIDB4MWI4OGUsIDB4MWI4OWMsIDB4MWI4YjgsIDB4MWI4YzIsIDB4MWI4YzQsIDB4MWI4YzgsIDB4MWI4ZDAsIDB4MWI4ZTYsIDB4MWI4ZmEsIDB4MWI5MGUsIDB4MWI5MWMsXG4gICAgICAgIDB4MWI5MzgsIDB4MWI5NzAsIDB4MWI5N2UsIDB4MWI5ODIsIDB4MWI5ODQsIDB4MWI5ODgsIDB4MWI5OTAsIDB4MWI5OWUsIDB4MWI5YTAsIDB4MWI5Y2MsIDB4MWI5ZjIsIDB4MWI5ZjQsXG4gICAgICAgIDB4MWJhMGUsIDB4MWJhMWMsIDB4MWJhMzgsIDB4MWJhNzAsIDB4MWJhN2UsIDB4MWJhZTAsIDB4MWJhZmMsIDB4MWJiMDgsIDB4MWJiMTAsIDB4MWJiMjAsIDB4MWJiM2MsIDB4MWJiNDAsXG4gICAgICAgIDB4MWJiOTgsIDB4MWJiY2UsIDB4MWJiZTIsIDB4MWJiZTQsIDB4MWJiZTgsIDB4MWJjMTYsIDB4MWJjMjYsIDB4MWJjMmMsIDB4MWJjNDYsIDB4MWJjNGMsIDB4MWJjNTgsIDB4MWJjNzIsXG4gICAgICAgIDB4MWJjNzQsIDB4MWJjODYsIDB4MWJjOGMsIDB4MWJjOTgsIDB4MWJjYjAsIDB4MWJjYmUsIDB4MWJjY2UsIDB4MWJjZTIsIDB4MWJjZTQsIDB4MWJjZTgsIDB4MWJkMDYsIDB4MWJkMGMsXG4gICAgICAgIDB4MWJkMTgsIDB4MWJkMzAsIDB4MWJkM2UsIDB4MWJkNjAsIDB4MWJkN2MsIDB4MWJkOWMsIDB4MWJkYzIsIDB4MWJkYzQsIDB4MWJkYzgsIDB4MWJkZDAsIDB4MWJkZTYsIDB4MWJkZmEsXG4gICAgICAgIDB4MWJlMTIsIDB4MWJlMTQsIDB4MWJlMjIsIDB4MWJlMjQsIDB4MWJlMjgsIDB4MWJlNDIsIDB4MWJlNDQsIDB4MWJlNDgsIDB4MWJlNTAsIDB4MWJlNWUsIDB4MWJlNjYsIDB4MWJlODIsXG4gICAgICAgIDB4MWJlODQsIDB4MWJlODgsIDB4MWJlOTAsIDB4MWJlOWUsIDB4MWJlYTAsIDB4MWJlYmMsIDB4MWJlY2MsIDB4MWJlZjQsIDB4MWJmMWEsIDB4MWJmMmUsIDB4MWJmMzIsIDB4MWJmMzQsXG4gICAgICAgIDB4MWJmNGUsIDB4MWJmNWMsIDB4MWJmNjIsIDB4MWJmNjQsIDB4MWJmNjgsIDB4MWMwOWEsIDB4MWMwYjIsIDB4MWMwYjQsIDB4MWMxMWEsIDB4MWMxMzIsIDB4MWMxMzQsIDB4MWMxNjIsXG4gICAgICAgIDB4MWMxNjQsIDB4MWMxNjgsIDB4MWMxNzYsIDB4MWMxYmEsIDB4MWMyMWEsIDB4MWMyMzIsIDB4MWMyMzQsIDB4MWMyNGUsIDB4MWMyNWMsIDB4MWMyNjIsIDB4MWMyNjQsIDB4MWMyNjgsXG4gICAgICAgIDB4MWMyNzYsIDB4MWMyOGUsIDB4MWMyYzIsIDB4MWMyYzQsIDB4MWMyYzgsIDB4MWMyZDAsIDB4MWMyZGUsIDB4MWMyZTYsIDB4MWMyZWMsIDB4MWMyZmEsIDB4MWMzMTYsIDB4MWMzMjYsXG4gICAgICAgIDB4MWMzM2EsIDB4MWMzNDYsIDB4MWMzNGMsIDB4MWMzNzIsIDB4MWMzNzQsIDB4MWM0MWEsIDB4MWM0MmUsIDB4MWM0MzIsIDB4MWM0MzQsIDB4MWM0NGUsIDB4MWM0NWMsIDB4MWM0NjIsXG4gICAgICAgIDB4MWM0NjQsIDB4MWM0NjgsIDB4MWM0NzYsIDB4MWM0OGUsIDB4MWM0OWMsIDB4MWM0YjgsIDB4MWM0YzIsIDB4MWM0YzgsIDB4MWM0ZDAsIDB4MWM0ZGUsIDB4MWM0ZTYsIDB4MWM0ZWMsXG4gICAgICAgIDB4MWM0ZmEsIDB4MWM1MWMsIDB4MWM1MzgsIDB4MWM1NzAsIDB4MWM1N2UsIDB4MWM1ODIsIDB4MWM1ODQsIDB4MWM1ODgsIDB4MWM1OTAsIDB4MWM1OWUsIDB4MWM1YTAsIDB4MWM1YmMsXG4gICAgICAgIDB4MWM1YzYsIDB4MWM1Y2MsIDB4MWM1ZDgsIDB4MWM1ZWUsIDB4MWM1ZjIsIDB4MWM1ZjQsIDB4MWM2MTYsIDB4MWM2MjYsIDB4MWM2MmMsIDB4MWM2M2EsIDB4MWM2NDYsIDB4MWM2NGMsXG4gICAgICAgIDB4MWM2NTgsIDB4MWM2NmUsIDB4MWM2NzIsIDB4MWM2NzQsIDB4MWM2ODYsIDB4MWM2OGMsIDB4MWM2OTgsIDB4MWM2YjAsIDB4MWM2YmUsIDB4MWM2Y2UsIDB4MWM2ZGMsIDB4MWM2ZTIsXG4gICAgICAgIDB4MWM2ZTQsIDB4MWM2ZTgsIDB4MWM3MTIsIDB4MWM3MTQsIDB4MWM3MjIsIDB4MWM3MjgsIDB4MWM3MzYsIDB4MWM3NDIsIDB4MWM3NDQsIDB4MWM3NDgsIDB4MWM3NTAsIDB4MWM3NWUsXG4gICAgICAgIDB4MWM3NjYsIDB4MWM3NmMsIDB4MWM3N2EsIDB4MWM3YWUsIDB4MWM3ZDYsIDB4MWM3ZWEsIDB4MWM4MWEsIDB4MWM4MmUsIDB4MWM4MzIsIDB4MWM4MzQsIDB4MWM4NGUsIDB4MWM4NWMsXG4gICAgICAgIDB4MWM4NjIsIDB4MWM4NjQsIDB4MWM4NjgsIDB4MWM4NzYsIDB4MWM4OGUsIDB4MWM4OWMsIDB4MWM4YjgsIDB4MWM4YzIsIDB4MWM4YzgsIDB4MWM4ZDAsIDB4MWM4ZGUsIDB4MWM4ZTYsXG4gICAgICAgIDB4MWM4ZWMsIDB4MWM4ZmEsIDB4MWM5MGUsIDB4MWM5MzgsIDB4MWM5NzAsIDB4MWM5N2UsIDB4MWM5ODIsIDB4MWM5ODQsIDB4MWM5OTAsIDB4MWM5OWUsIDB4MWM5YTAsIDB4MWM5YmMsXG4gICAgICAgIDB4MWM5YzYsIDB4MWM5Y2MsIDB4MWM5ZDgsIDB4MWM5ZWUsIDB4MWM5ZjIsIDB4MWM5ZjQsIDB4MWNhMzgsIDB4MWNhNzAsIDB4MWNhN2UsIDB4MWNhZTAsIDB4MWNhZmMsIDB4MWNiMDIsXG4gICAgICAgIDB4MWNiMDQsIDB4MWNiMDgsIDB4MWNiMTAsIDB4MWNiMjAsIDB4MWNiM2MsIDB4MWNiNDAsIDB4MWNiNzgsIDB4MWNiODYsIDB4MWNiOGMsIDB4MWNiOTgsIDB4MWNiYjAsIDB4MWNiYmUsXG4gICAgICAgIDB4MWNiY2UsIDB4MWNiZGMsIDB4MWNiZTIsIDB4MWNiZTQsIDB4MWNiZTgsIDB4MWNiZjYsIDB4MWNjMTYsIDB4MWNjMjYsIDB4MWNjMmMsIDB4MWNjM2EsIDB4MWNjNDYsIDB4MWNjNTgsXG4gICAgICAgIDB4MWNjNzIsIDB4MWNjNzQsIDB4MWNjODYsIDB4MWNjYjAsIDB4MWNjYmUsIDB4MWNjY2UsIDB4MWNjZTIsIDB4MWNjZTQsIDB4MWNjZTgsIDB4MWNkMDYsIDB4MWNkMGMsIDB4MWNkMTgsXG4gICAgICAgIDB4MWNkMzAsIDB4MWNkM2UsIDB4MWNkNjAsIDB4MWNkN2MsIDB4MWNkOWMsIDB4MWNkYzIsIDB4MWNkYzQsIDB4MWNkYzgsIDB4MWNkZDAsIDB4MWNkZGUsIDB4MWNkZTYsIDB4MWNkZmEsXG4gICAgICAgIDB4MWNlMjIsIDB4MWNlMjgsIDB4MWNlNDIsIDB4MWNlNTAsIDB4MWNlNWUsIDB4MWNlNjYsIDB4MWNlN2EsIDB4MWNlODIsIDB4MWNlODQsIDB4MWNlODgsIDB4MWNlOTAsIDB4MWNlOWUsXG4gICAgICAgIDB4MWNlYTAsIDB4MWNlYmMsIDB4MWNlY2MsIDB4MWNlZjIsIDB4MWNlZjQsIDB4MWNmMmUsIDB4MWNmMzIsIDB4MWNmMzQsIDB4MWNmNGUsIDB4MWNmNWMsIDB4MWNmNjIsIDB4MWNmNjQsXG4gICAgICAgIDB4MWNmNjgsIDB4MWNmOTYsIDB4MWNmYTYsIDB4MWNmYWMsIDB4MWNmY2EsIDB4MWNmZDIsIDB4MWNmZDQsIDB4MWQwMmUsIDB4MWQwMzIsIDB4MWQwMzQsIDB4MWQwNGUsIDB4MWQwNWMsXG4gICAgICAgIDB4MWQwNjIsIDB4MWQwNjQsIDB4MWQwNjgsIDB4MWQwNzYsIDB4MWQwOGUsIDB4MWQwOWMsIDB4MWQwYjgsIDB4MWQwYzIsIDB4MWQwYzQsIDB4MWQwYzgsIDB4MWQwZDAsIDB4MWQwZGUsXG4gICAgICAgIDB4MWQwZTYsIDB4MWQwZWMsIDB4MWQwZmEsIDB4MWQxMWMsIDB4MWQxMzgsIDB4MWQxNzAsIDB4MWQxN2UsIDB4MWQxODIsIDB4MWQxODQsIDB4MWQxODgsIDB4MWQxOTAsIDB4MWQxOWUsXG4gICAgICAgIDB4MWQxYTAsIDB4MWQxYmMsIDB4MWQxYzYsIDB4MWQxY2MsIDB4MWQxZDgsIDB4MWQxZWUsIDB4MWQxZjIsIDB4MWQxZjQsIDB4MWQyMWMsIDB4MWQyMzgsIDB4MWQyNzAsIDB4MWQyN2UsXG4gICAgICAgIDB4MWQyZTAsIDB4MWQyZmMsIDB4MWQzMDIsIDB4MWQzMDQsIDB4MWQzMDgsIDB4MWQzMTAsIDB4MWQzMWUsIDB4MWQzMjAsIDB4MWQzM2MsIDB4MWQzNDAsIDB4MWQzNzgsIDB4MWQzODYsXG4gICAgICAgIDB4MWQzOGMsIDB4MWQzOTgsIDB4MWQzYjAsIDB4MWQzYmUsIDB4MWQzY2UsIDB4MWQzZGMsIDB4MWQzZTIsIDB4MWQzZTQsIDB4MWQzZTgsIDB4MWQzZjYsIDB4MWQ0NzAsIDB4MWQ0N2UsXG4gICAgICAgIDB4MWQ0ZTAsIDB4MWQ0ZmMsIDB4MWQ1YzAsIDB4MWQ1ZjgsIDB4MWQ2MDQsIDB4MWQ2MDgsIDB4MWQ2MTAsIDB4MWQ2MjAsIDB4MWQ2NDAsIDB4MWQ2NzgsIDB4MWQ2ZjAsIDB4MWQ3MDYsXG4gICAgICAgIDB4MWQ3MGMsIDB4MWQ3MTgsIDB4MWQ3MzAsIDB4MWQ3M2UsIDB4MWQ3NjAsIDB4MWQ3N2MsIDB4MWQ3OGUsIDB4MWQ3OWMsIDB4MWQ3YjgsIDB4MWQ3YzIsIDB4MWQ3YzQsIDB4MWQ3YzgsXG4gICAgICAgIDB4MWQ3ZDAsIDB4MWQ3ZGUsIDB4MWQ3ZTYsIDB4MWQ3ZWMsIDB4MWQ4MjYsIDB4MWQ4MmMsIDB4MWQ4M2EsIDB4MWQ4NDYsIDB4MWQ4NGMsIDB4MWQ4NTgsIDB4MWQ4NzIsIDB4MWQ4NzQsXG4gICAgICAgIDB4MWQ4ODYsIDB4MWQ4OGMsIDB4MWQ4OTgsIDB4MWQ4YjAsIDB4MWQ4YmUsIDB4MWQ4Y2UsIDB4MWQ4ZTIsIDB4MWQ4ZTQsIDB4MWQ4ZTgsIDB4MWQ4ZjYsIDB4MWQ5MGMsIDB4MWQ5MTgsXG4gICAgICAgIDB4MWQ5MzAsIDB4MWQ5M2UsIDB4MWQ5NjAsIDB4MWQ5N2MsIDB4MWQ5OWMsIDB4MWQ5YzIsIDB4MWQ5YzQsIDB4MWQ5YzgsIDB4MWQ5ZDAsIDB4MWQ5ZTYsIDB4MWQ5ZmEsIDB4MWRhMGMsXG4gICAgICAgIDB4MWRhMTgsIDB4MWRhMzAsIDB4MWRhM2UsIDB4MWRhNjAsIDB4MWRhN2MsIDB4MWRhYzAsIDB4MWRhZjgsIDB4MWRiMzgsIDB4MWRiODIsIDB4MWRiODQsIDB4MWRiODgsIDB4MWRiOTAsXG4gICAgICAgIDB4MWRiOWUsIDB4MWRiYTAsIDB4MWRiY2MsIDB4MWRiZjIsIDB4MWRiZjQsIDB4MWRjMjIsIDB4MWRjNDIsIDB4MWRjNDQsIDB4MWRjNDgsIDB4MWRjNTAsIDB4MWRjNWUsIDB4MWRjNjYsXG4gICAgICAgIDB4MWRjN2EsIDB4MWRjODIsIDB4MWRjODQsIDB4MWRjODgsIDB4MWRjOTAsIDB4MWRjOWUsIDB4MWRjYTAsIDB4MWRjYmMsIDB4MWRjY2MsIDB4MWRjZjIsIDB4MWRjZjQsIDB4MWRkMDQsXG4gICAgICAgIDB4MWRkMDgsIDB4MWRkMTAsIDB4MWRkMWUsIDB4MWRkMjAsIDB4MWRkM2MsIDB4MWRkNDAsIDB4MWRkNzgsIDB4MWRkODYsIDB4MWRkOTgsIDB4MWRkY2UsIDB4MWRkZTIsIDB4MWRkZTQsXG4gICAgICAgIDB4MWRkZTgsIDB4MWRlMmUsIDB4MWRlMzIsIDB4MWRlMzQsIDB4MWRlNGUsIDB4MWRlNWMsIDB4MWRlNjIsIDB4MWRlNjQsIDB4MWRlNjgsIDB4MWRlOGUsIDB4MWRlOWMsIDB4MWRlYjgsXG4gICAgICAgIDB4MWRlYzIsIDB4MWRlYzQsIDB4MWRlYzgsIDB4MWRlZDAsIDB4MWRlZTYsIDB4MWRlZmEsIDB4MWRmMTYsIDB4MWRmMjYsIDB4MWRmMmMsIDB4MWRmNDYsIDB4MWRmNGMsIDB4MWRmNTgsXG4gICAgICAgIDB4MWRmNzIsIDB4MWRmNzQsIDB4MWRmOGEsIDB4MWRmOTIsIDB4MWRmOTQsIDB4MWRmYTIsIDB4MWRmYTQsIDB4MWRmYTgsIDB4MWUwOGEsIDB4MWUwOTIsIDB4MWUwOTQsIDB4MWUwYTIsXG4gICAgICAgIDB4MWUwYTQsIDB4MWUwYTgsIDB4MWUwYjYsIDB4MWUwZGEsIDB4MWUxMGEsIDB4MWUxMTIsIDB4MWUxMTQsIDB4MWUxMjIsIDB4MWUxMjQsIDB4MWUxMjgsIDB4MWUxMzYsIDB4MWUxNDIsXG4gICAgICAgIDB4MWUxNDQsIDB4MWUxNDgsIDB4MWUxNTAsIDB4MWUxNjYsIDB4MWUxNmMsIDB4MWUxN2EsIDB4MWUxOWEsIDB4MWUxYjIsIDB4MWUxYjQsIDB4MWUyMGEsIDB4MWUyMTIsIDB4MWUyMTQsXG4gICAgICAgIDB4MWUyMjIsIDB4MWUyMjQsIDB4MWUyMjgsIDB4MWUyMzYsIDB4MWUyNDIsIDB4MWUyNDgsIDB4MWUyNTAsIDB4MWUyNWUsIDB4MWUyNjYsIDB4MWUyNmMsIDB4MWUyN2EsIDB4MWUyODIsXG4gICAgICAgIDB4MWUyODQsIDB4MWUyODgsIDB4MWUyOTAsIDB4MWUyYTAsIDB4MWUyYmMsIDB4MWUyYzYsIDB4MWUyY2MsIDB4MWUyZDgsIDB4MWUyZWUsIDB4MWUyZjIsIDB4MWUyZjQsIDB4MWUzMWEsXG4gICAgICAgIDB4MWUzMzIsIDB4MWUzMzQsIDB4MWUzNWMsIDB4MWUzNjIsIDB4MWUzNjQsIDB4MWUzNjgsIDB4MWUzYmEsIDB4MWU0MGEsIDB4MWU0MTIsIDB4MWU0MTQsIDB4MWU0MjIsIDB4MWU0MjgsXG4gICAgICAgIDB4MWU0MzYsIDB4MWU0NDIsIDB4MWU0NDgsIDB4MWU0NTAsIDB4MWU0NWUsIDB4MWU0NjYsIDB4MWU0NmMsIDB4MWU0N2EsIDB4MWU0ODIsIDB4MWU0ODQsIDB4MWU0OTAsIDB4MWU0OWUsXG4gICAgICAgIDB4MWU0YTAsIDB4MWU0YmMsIDB4MWU0YzYsIDB4MWU0Y2MsIDB4MWU0ZDgsIDB4MWU0ZWUsIDB4MWU0ZjIsIDB4MWU0ZjQsIDB4MWU1MDIsIDB4MWU1MDQsIDB4MWU1MDgsIDB4MWU1MTAsXG4gICAgICAgIDB4MWU1MWUsIDB4MWU1MjAsIDB4MWU1M2MsIDB4MWU1NDAsIDB4MWU1NzgsIDB4MWU1ODYsIDB4MWU1OGMsIDB4MWU1OTgsIDB4MWU1YjAsIDB4MWU1YmUsIDB4MWU1Y2UsIDB4MWU1ZGMsXG4gICAgICAgIDB4MWU1ZTIsIDB4MWU1ZTQsIDB4MWU1ZTgsIDB4MWU1ZjYsIDB4MWU2MWEsIDB4MWU2MmUsIDB4MWU2MzIsIDB4MWU2MzQsIDB4MWU2NGUsIDB4MWU2NWMsIDB4MWU2NjIsIDB4MWU2NjgsXG4gICAgICAgIDB4MWU2OGUsIDB4MWU2OWMsIDB4MWU2YjgsIDB4MWU2YzIsIDB4MWU2YzQsIDB4MWU2YzgsIDB4MWU2ZDAsIDB4MWU2ZTYsIDB4MWU2ZmEsIDB4MWU3MTYsIDB4MWU3MjYsIDB4MWU3MmMsXG4gICAgICAgIDB4MWU3M2EsIDB4MWU3NDYsIDB4MWU3NGMsIDB4MWU3NTgsIDB4MWU3NzIsIDB4MWU3NzQsIDB4MWU3OTIsIDB4MWU3OTQsIDB4MWU3YTIsIDB4MWU3YTQsIDB4MWU3YTgsIDB4MWU3YjYsXG4gICAgICAgIDB4MWU4MTIsIDB4MWU4MTQsIDB4MWU4MjIsIDB4MWU4MjQsIDB4MWU4MjgsIDB4MWU4MzYsIDB4MWU4NDIsIDB4MWU4NDQsIDB4MWU4NDgsIDB4MWU4NTAsIDB4MWU4NWUsIDB4MWU4NjYsXG4gICAgICAgIDB4MWU4NmMsIDB4MWU4N2EsIDB4MWU4ODIsIDB4MWU4ODQsIDB4MWU4ODgsIDB4MWU4OTAsIDB4MWU4OWUsIDB4MWU4YTAsIDB4MWU4YmMsIDB4MWU4YzYsIDB4MWU4Y2MsIDB4MWU4ZDgsXG4gICAgICAgIDB4MWU4ZWUsIDB4MWU4ZjIsIDB4MWU4ZjQsIDB4MWU5MDIsIDB4MWU5MDQsIDB4MWU5MDgsIDB4MWU5MTAsIDB4MWU5MjAsIDB4MWU5M2MsIDB4MWU5NDAsIDB4MWU5NzgsIDB4MWU5ODYsXG4gICAgICAgIDB4MWU5OGMsIDB4MWU5OTgsIDB4MWU5YjAsIDB4MWU5YmUsIDB4MWU5Y2UsIDB4MWU5ZGMsIDB4MWU5ZTIsIDB4MWU5ZTQsIDB4MWU5ZTgsIDB4MWU5ZjYsIDB4MWVhMDQsIDB4MWVhMDgsXG4gICAgICAgIDB4MWVhMTAsIDB4MWVhMjAsIDB4MWVhNDAsIDB4MWVhNzgsIDB4MWVhZjAsIDB4MWViMDYsIDB4MWViMGMsIDB4MWViMTgsIDB4MWViMzAsIDB4MWViM2UsIDB4MWViNjAsIDB4MWViN2MsXG4gICAgICAgIDB4MWViOGUsIDB4MWViOWMsIDB4MWViYjgsIDB4MWViYzIsIDB4MWViYzQsIDB4MWViYzgsIDB4MWViZDAsIDB4MWViZGUsIDB4MWViZTYsIDB4MWViZWMsIDB4MWVjMWEsIDB4MWVjMmUsXG4gICAgICAgIDB4MWVjMzIsIDB4MWVjMzQsIDB4MWVjNGUsIDB4MWVjNWMsIDB4MWVjNjIsIDB4MWVjNjQsIDB4MWVjNjgsIDB4MWVjOGUsIDB4MWVjOWMsIDB4MWVjYjgsIDB4MWVjYzIsIDB4MWVjYzQsXG4gICAgICAgIDB4MWVjYzgsIDB4MWVjZDAsIDB4MWVjZTYsIDB4MWVjZmEsIDB4MWVkMGUsIDB4MWVkMWMsIDB4MWVkMzgsIDB4MWVkNzAsIDB4MWVkN2UsIDB4MWVkODIsIDB4MWVkODQsIDB4MWVkODgsXG4gICAgICAgIDB4MWVkOTAsIDB4MWVkOWUsIDB4MWVkYTAsIDB4MWVkY2MsIDB4MWVkZjIsIDB4MWVkZjQsIDB4MWVlMTYsIDB4MWVlMjYsIDB4MWVlMmMsIDB4MWVlM2EsIDB4MWVlNDYsIDB4MWVlNGMsXG4gICAgICAgIDB4MWVlNTgsIDB4MWVlNmUsIDB4MWVlNzIsIDB4MWVlNzQsIDB4MWVlODYsIDB4MWVlOGMsIDB4MWVlOTgsIDB4MWVlYjAsIDB4MWVlYmUsIDB4MWVlY2UsIDB4MWVlZGMsIDB4MWVlZTIsXG4gICAgICAgIDB4MWVlZTQsIDB4MWVlZTgsIDB4MWVmMTIsIDB4MWVmMjIsIDB4MWVmMjQsIDB4MWVmMjgsIDB4MWVmMzYsIDB4MWVmNDIsIDB4MWVmNDQsIDB4MWVmNDgsIDB4MWVmNTAsIDB4MWVmNWUsXG4gICAgICAgIDB4MWVmNjYsIDB4MWVmNmMsIDB4MWVmN2EsIDB4MWVmYWUsIDB4MWVmYjIsIDB4MWVmYjQsIDB4MWVmZDYsIDB4MWYwOTYsIDB4MWYwYTYsIDB4MWYwYWMsIDB4MWYwYmEsIDB4MWYwY2EsXG4gICAgICAgIDB4MWYwZDIsIDB4MWYwZDQsIDB4MWYxMTYsIDB4MWYxMjYsIDB4MWYxMmMsIDB4MWYxM2EsIDB4MWYxNDYsIDB4MWYxNGMsIDB4MWYxNTgsIDB4MWYxNmUsIDB4MWYxNzIsIDB4MWYxNzQsXG4gICAgICAgIDB4MWYxOGEsIDB4MWYxOTIsIDB4MWYxOTQsIDB4MWYxYTIsIDB4MWYxYTQsIDB4MWYxYTgsIDB4MWYxZGEsIDB4MWYyMTYsIDB4MWYyMjYsIDB4MWYyMmMsIDB4MWYyM2EsIDB4MWYyNDYsXG4gICAgICAgIDB4MWYyNTgsIDB4MWYyNmUsIDB4MWYyNzIsIDB4MWYyNzQsIDB4MWYyODYsIDB4MWYyOGMsIDB4MWYyOTgsIDB4MWYyYjAsIDB4MWYyYmUsIDB4MWYyY2UsIDB4MWYyZGMsIDB4MWYyZTIsXG4gICAgICAgIDB4MWYyZTQsIDB4MWYyZTgsIDB4MWYyZjYsIDB4MWYzMGEsIDB4MWYzMTIsIDB4MWYzMTQsIDB4MWYzMjIsIDB4MWYzMjgsIDB4MWYzNDIsIDB4MWYzNDQsIDB4MWYzNDgsIDB4MWYzNTAsXG4gICAgICAgIDB4MWYzNWUsIDB4MWYzNjYsIDB4MWYzN2EsIDB4MWYzOWEsIDB4MWYzYWUsIDB4MWYzYjIsIDB4MWYzYjQsIDB4MWY0MTYsIDB4MWY0MjYsIDB4MWY0MmMsIDB4MWY0M2EsIDB4MWY0NDYsXG4gICAgICAgIDB4MWY0NGMsIDB4MWY0NTgsIDB4MWY0NmUsIDB4MWY0NzIsIDB4MWY0NzQsIDB4MWY0ODYsIDB4MWY0OGMsIDB4MWY0OTgsIDB4MWY0YjAsIDB4MWY0YmUsIDB4MWY0Y2UsIDB4MWY0ZGMsXG4gICAgICAgIDB4MWY0ZTIsIDB4MWY0ZTQsIDB4MWY0ZTgsIDB4MWY0ZjYsIDB4MWY1MDYsIDB4MWY1MGMsIDB4MWY1MTgsIDB4MWY1MzAsIDB4MWY1M2UsIDB4MWY1NjAsIDB4MWY1N2MsIDB4MWY1OGUsXG4gICAgICAgIDB4MWY1OWMsIDB4MWY1YjgsIDB4MWY1YzIsIDB4MWY1YzQsIDB4MWY1YzgsIDB4MWY1ZDAsIDB4MWY1ZGUsIDB4MWY1ZTYsIDB4MWY1ZWMsIDB4MWY1ZmEsIDB4MWY2MGEsIDB4MWY2MTIsXG4gICAgICAgIDB4MWY2MTQsIDB4MWY2MjIsIDB4MWY2MjQsIDB4MWY2MjgsIDB4MWY2MzYsIDB4MWY2NDIsIDB4MWY2NDQsIDB4MWY2NDgsIDB4MWY2NTAsIDB4MWY2NWUsIDB4MWY2NjYsIDB4MWY2N2EsXG4gICAgICAgIDB4MWY2ODIsIDB4MWY2ODQsIDB4MWY2ODgsIDB4MWY2OTAsIDB4MWY2OWUsIDB4MWY2YTAsIDB4MWY2YmMsIDB4MWY2Y2MsIDB4MWY2ZjIsIDB4MWY2ZjQsIDB4MWY3MWEsIDB4MWY3MmUsXG4gICAgICAgIDB4MWY3MzIsIDB4MWY3MzQsIDB4MWY3NGUsIDB4MWY3NWMsIDB4MWY3NjIsIDB4MWY3NjQsIDB4MWY3NjgsIDB4MWY3NzYsIDB4MWY3OTYsIDB4MWY3YTYsIDB4MWY3YWMsIDB4MWY3YmEsXG4gICAgICAgIDB4MWY3ZDIsIDB4MWY3ZDQsIDB4MWY4OWEsIDB4MWY4YWUsIDB4MWY4YjIsIDB4MWY4YjQsIDB4MWY4ZDYsIDB4MWY4ZWEsIDB4MWY5MWEsIDB4MWY5MmUsIDB4MWY5MzIsIDB4MWY5MzQsXG4gICAgICAgIDB4MWY5NGUsIDB4MWY5NWMsIDB4MWY5NjIsIDB4MWY5NjQsIDB4MWY5NjgsIDB4MWY5NzYsIDB4MWY5OTYsIDB4MWY5YTYsIDB4MWY5YWMsIDB4MWY5YmEsIDB4MWY5Y2EsIDB4MWY5ZDIsXG4gICAgICAgIDB4MWY5ZDQsIDB4MWZhMWEsIDB4MWZhMmUsIDB4MWZhMzIsIDB4MWZhMzQsIDB4MWZhNGUsIDB4MWZhNWMsIDB4MWZhNjIsIDB4MWZhNjQsIDB4MWZhNjgsIDB4MWZhNzYsIDB4MWZhOGUsXG4gICAgICAgIDB4MWZhOWMsIDB4MWZhYjgsIDB4MWZhYzIsIDB4MWZhYzQsIDB4MWZhYzgsIDB4MWZhZDAsIDB4MWZhZGUsIDB4MWZhZTYsIDB4MWZhZWMsIDB4MWZiMTYsIDB4MWZiMjYsIDB4MWZiMmMsXG4gICAgICAgIDB4MWZiM2EsIDB4MWZiNDYsIDB4MWZiNGMsIDB4MWZiNTgsIDB4MWZiNmUsIDB4MWZiNzIsIDB4MWZiNzQsIDB4MWZiOGEsIDB4MWZiOTIsIDB4MWZiOTQsIDB4MWZiYTIsIDB4MWZiYTQsXG4gICAgICAgIDB4MWZiYTgsIDB4MWZiYjYsIDB4MWZiZGFcbiAgICBdKTtcbiAgICAvKipcbiAgICAgKiBUaGlzIHRhYmxlIGNvbnRhaW5zIHRvIGNvZGV3b3JkcyBmb3IgYWxsIHN5bWJvbHMuXG4gICAgICovXG4gICAgUERGNDE3Q29tbW9uLkNPREVXT1JEX1RBQkxFID0gSW50MzJBcnJheS5mcm9tKFtcbiAgICAgICAgMjYyNywgMTgxOSwgMjYyMiwgMjYyMSwgMTgxMywgMTgxMiwgMjcyOSwgMjcyNCwgMjcyMywgMjc3OSwgMjc3NCwgMjc3MywgOTAyLCA4OTYsIDkwOCwgODY4LCA4NjUsIDg2MSwgODU5LCAyNTExLFxuICAgICAgICA4NzMsIDg3MSwgMTc4MCwgODM1LCAyNDkzLCA4MjUsIDI0OTEsIDg0MiwgODM3LCA4NDQsIDE3NjQsIDE3NjIsIDgxMSwgODEwLCA4MDksIDI0ODMsIDgwNywgMjQ4MiwgODA2LCAyNDgwLCA4MTUsXG4gICAgICAgIDgxNCwgODEzLCA4MTIsIDI0ODQsIDgxNywgODE2LCAxNzQ1LCAxNzQ0LCAxNzQyLCAxNzQ2LCAyNjU1LCAyNjM3LCAyNjM1LCAyNjI2LCAyNjI1LCAyNjIzLCAyNjI4LCAxODIwLCAyNzUyLFxuICAgICAgICAyNzM5LCAyNzM3LCAyNzI4LCAyNzI3LCAyNzI1LCAyNzMwLCAyNzg1LCAyNzgzLCAyNzc4LCAyNzc3LCAyNzc1LCAyNzgwLCA3ODcsIDc4MSwgNzQ3LCA3MzksIDczNiwgMjQxMywgNzU0LCA3NTIsXG4gICAgICAgIDE3MTksIDY5MiwgNjg5LCA2ODEsIDIzNzEsIDY3OCwgMjM2OSwgNzAwLCA2OTcsIDY5NCwgNzAzLCAxNjg4LCAxNjg2LCA2NDIsIDYzOCwgMjM0MywgNjMxLCAyMzQxLCA2MjcsIDIzMzgsIDY1MSxcbiAgICAgICAgNjQ2LCA2NDMsIDIzNDUsIDY1NCwgNjUyLCAxNjUyLCAxNjUwLCAxNjQ3LCAxNjU0LCA2MDEsIDU5OSwgMjMyMiwgNTk2LCAyMzIxLCA1OTQsIDIzMTksIDIzMTcsIDYxMSwgNjEwLCA2MDgsIDYwNixcbiAgICAgICAgMjMyNCwgNjAzLCAyMzIzLCA2MTUsIDYxNCwgNjEyLCAxNjE3LCAxNjE2LCAxNjE0LCAxNjEyLCA2MTYsIDE2MTksIDE2MTgsIDI1NzUsIDI1MzgsIDI1MzYsIDkwNSwgOTAxLCA4OTgsIDkwOSxcbiAgICAgICAgMjUwOSwgMjUwNywgMjUwNCwgODcwLCA4NjcsIDg2NCwgODYwLCAyNTEyLCA4NzUsIDg3MiwgMTc4MSwgMjQ5MCwgMjQ4OSwgMjQ4NywgMjQ4NSwgMTc0OCwgODM2LCA4MzQsIDgzMiwgODMwLFxuICAgICAgICAyNDk0LCA4MjcsIDI0OTIsIDg0MywgODQxLCA4MzksIDg0NSwgMTc2NSwgMTc2MywgMjcwMSwgMjY3NiwgMjY3NCwgMjY1MywgMjY0OCwgMjY1NiwgMjYzNCwgMjYzMywgMjYzMSwgMjYyOSxcbiAgICAgICAgMTgyMSwgMjYzOCwgMjYzNiwgMjc3MCwgMjc2MywgMjc2MSwgMjc1MCwgMjc0NSwgMjc1MywgMjczNiwgMjczNSwgMjczMywgMjczMSwgMTg0OCwgMjc0MCwgMjczOCwgMjc4NiwgMjc4NCwgNTkxLFxuICAgICAgICA1ODgsIDU3NiwgNTY5LCA1NjYsIDIyOTYsIDE1OTAsIDUzNywgNTM0LCA1MjYsIDIyNzYsIDUyMiwgMjI3NCwgNTQ1LCA1NDIsIDUzOSwgNTQ4LCAxNTcyLCAxNTcwLCA0ODEsIDIyNDUsIDQ2NixcbiAgICAgICAgMjI0MiwgNDYyLCAyMjM5LCA0OTIsIDQ4NSwgNDgyLCAyMjQ5LCA0OTYsIDQ5NCwgMTUzNCwgMTUzMSwgMTUyOCwgMTUzOCwgNDEzLCAyMTk2LCA0MDYsIDIxOTEsIDIxODgsIDQyNSwgNDE5LFxuICAgICAgICAyMjAyLCA0MTUsIDIxOTksIDQzMiwgNDMwLCA0MjcsIDE0NzIsIDE0NjcsIDE0NjQsIDQzMywgMTQ3NiwgMTQ3NCwgMzY4LCAzNjcsIDIxNjAsIDM2NSwgMjE1OSwgMzYyLCAyMTU3LCAyMTU1LFxuICAgICAgICAyMTUyLCAzNzgsIDM3NywgMzc1LCAyMTY2LCAzNzIsIDIxNjUsIDM2OSwgMjE2MiwgMzgzLCAzODEsIDM3OSwgMjE2OCwgMTQxOSwgMTQxOCwgMTQxNiwgMTQxNCwgMzg1LCAxNDExLCAzODQsXG4gICAgICAgIDE0MjMsIDE0MjIsIDE0MjAsIDE0MjQsIDI0NjEsIDgwMiwgMjQ0MSwgMjQzOSwgNzkwLCA3ODYsIDc4MywgNzk0LCAyNDA5LCAyNDA2LCAyNDAzLCA3NTAsIDc0MiwgNzM4LCAyNDE0LCA3NTYsXG4gICAgICAgIDc1MywgMTcyMCwgMjM2NywgMjM2NSwgMjM2MiwgMjM1OSwgMTY2MywgNjkzLCA2OTEsIDY4NCwgMjM3MywgNjgwLCAyMzcwLCA3MDIsIDY5OSwgNjk2LCA3MDQsIDE2OTAsIDE2ODcsIDIzMzcsXG4gICAgICAgIDIzMzYsIDIzMzQsIDIzMzIsIDE2MjQsIDIzMjksIDE2MjIsIDY0MCwgNjM3LCAyMzQ0LCA2MzQsIDIzNDIsIDYzMCwgMjM0MCwgNjUwLCA2NDgsIDY0NSwgMjM0NiwgNjU1LCA2NTMsIDE2NTMsXG4gICAgICAgIDE2NTEsIDE2NDksIDE2NTUsIDI2MTIsIDI1OTcsIDI1OTUsIDI1NzEsIDI1NjgsIDI1NjUsIDI1NzYsIDI1MzQsIDI1MjksIDI1MjYsIDE3ODcsIDI1NDAsIDI1MzcsIDkwNywgOTA0LCA5MDAsXG4gICAgICAgIDkxMCwgMjUwMywgMjUwMiwgMjUwMCwgMjQ5OCwgMTc2OCwgMjQ5NSwgMTc2NywgMjUxMCwgMjUwOCwgMjUwNiwgODY5LCA4NjYsIDg2MywgMjUxMywgODc2LCA4NzQsIDE3ODIsIDI3MjAsIDI3MTMsXG4gICAgICAgIDI3MTEsIDI2OTcsIDI2OTQsIDI2OTEsIDI3MDIsIDI2NzIsIDI2NzAsIDI2NjQsIDE4MjgsIDI2NzgsIDI2NzUsIDI2NDcsIDI2NDYsIDI2NDQsIDI2NDIsIDE4MjMsIDI2MzksIDE4MjIsIDI2NTQsXG4gICAgICAgIDI2NTIsIDI2NTAsIDI2NTcsIDI3NzEsIDE4NTUsIDI3NjUsIDI3NjIsIDE4NTAsIDE4NDksIDI3NTEsIDI3NDksIDI3NDcsIDI3NTQsIDM1MywgMjE0OCwgMzQ0LCAzNDIsIDMzNiwgMjE0MixcbiAgICAgICAgMzMyLCAyMTQwLCAzNDUsIDEzNzUsIDEzNzMsIDMwNiwgMjEzMCwgMjk5LCAyMTI4LCAyOTUsIDIxMjUsIDMxOSwgMzE0LCAzMTEsIDIxMzIsIDEzNTQsIDEzNTIsIDEzNDksIDEzNTYsIDI2MixcbiAgICAgICAgMjU3LCAyMTAxLCAyNTMsIDIwOTYsIDIwOTMsIDI3NCwgMjczLCAyNjcsIDIxMDcsIDI2MywgMjEwNCwgMjgwLCAyNzgsIDI3NSwgMTMxNiwgMTMxMSwgMTMwOCwgMTMyMCwgMTMxOCwgMjA1MixcbiAgICAgICAgMjAyLCAyMDUwLCAyMDQ0LCAyMDQwLCAyMTksIDIwNjMsIDIxMiwgMjA2MCwgMjA4LCAyMDU1LCAyMjQsIDIyMSwgMjA2NiwgMTI2MCwgMTI1OCwgMTI1MiwgMjMxLCAxMjQ4LCAyMjksIDEyNjYsXG4gICAgICAgIDEyNjQsIDEyNjEsIDEyNjgsIDE1NSwgMTk5OCwgMTUzLCAxOTk2LCAxOTk0LCAxOTkxLCAxOTg4LCAxNjUsIDE2NCwgMjAwNywgMTYyLCAyMDA2LCAxNTksIDIwMDMsIDIwMDAsIDE3MiwgMTcxLFxuICAgICAgICAxNjksIDIwMTIsIDE2NiwgMjAxMCwgMTE4NiwgMTE4NCwgMTE4MiwgMTE3OSwgMTc1LCAxMTc2LCAxNzMsIDExOTIsIDExOTEsIDExODksIDExODcsIDE3NiwgMTE5NCwgMTE5MywgMjMxMyxcbiAgICAgICAgMjMwNywgMjMwNSwgNTkyLCA1ODksIDIyOTQsIDIyOTIsIDIyODksIDU3OCwgNTcyLCA1NjgsIDIyOTcsIDU4MCwgMTU5MSwgMjI3MiwgMjI2NywgMjI2NCwgMTU0NywgNTM4LCA1MzYsIDUyOSxcbiAgICAgICAgMjI3OCwgNTI1LCAyMjc1LCA1NDcsIDU0NCwgNTQxLCAxNTc0LCAxNTcxLCAyMjM3LCAyMjM1LCAyMjI5LCAxNDkzLCAyMjI1LCAxNDg5LCA0NzgsIDIyNDcsIDQ3MCwgMjI0NCwgNDY1LCAyMjQxLFxuICAgICAgICA0OTMsIDQ4OCwgNDg0LCAyMjUwLCA0OTgsIDQ5NSwgMTUzNiwgMTUzMywgMTUzMCwgMTUzOSwgMjE4NywgMjE4NiwgMjE4NCwgMjE4MiwgMTQzMiwgMjE3OSwgMTQzMCwgMjE3NiwgMTQyNywgNDE0LFxuICAgICAgICA0MTIsIDIxOTcsIDQwOSwgMjE5NSwgNDA1LCAyMTkzLCAyMTkwLCA0MjYsIDQyNCwgNDIxLCAyMjAzLCA0MTgsIDIyMDEsIDQzMSwgNDI5LCAxNDczLCAxNDcxLCAxNDY5LCAxNDY2LCA0MzQsXG4gICAgICAgIDE0NzcsIDE0NzUsIDI0NzgsIDI0NzIsIDI0NzAsIDI0NTksIDI0NTcsIDI0NTQsIDI0NjIsIDgwMywgMjQzNywgMjQzMiwgMjQyOSwgMTcyNiwgMjQ0MywgMjQ0MCwgNzkyLCA3ODksIDc4NSxcbiAgICAgICAgMjQwMSwgMjM5OSwgMjM5MywgMTcwMiwgMjM4OSwgMTY5OSwgMjQxMSwgMjQwOCwgMjQwNSwgNzQ1LCA3NDEsIDI0MTUsIDc1OCwgNzU1LCAxNzIxLCAyMzU4LCAyMzU3LCAyMzU1LCAyMzUzLFxuICAgICAgICAxNjYxLCAyMzUwLCAxNjYwLCAyMzQ3LCAxNjU3LCAyMzY4LCAyMzY2LCAyMzY0LCAyMzYxLCAxNjY2LCA2OTAsIDY4NywgMjM3NCwgNjgzLCAyMzcyLCA3MDEsIDY5OCwgNzA1LCAxNjkxLCAxNjg5LFxuICAgICAgICAyNjE5LCAyNjE3LCAyNjEwLCAyNjA4LCAyNjA1LCAyNjEzLCAyNTkzLCAyNTg4LCAyNTg1LCAxODAzLCAyNTk5LCAyNTk2LCAyNTYzLCAyNTYxLCAyNTU1LCAxNzk3LCAyNTUxLCAxNzk1LCAyNTczLFxuICAgICAgICAyNTcwLCAyNTY3LCAyNTc3LCAyNTI1LCAyNTI0LCAyNTIyLCAyNTIwLCAxNzg2LCAyNTE3LCAxNzg1LCAyNTE0LCAxNzgzLCAyNTM1LCAyNTMzLCAyNTMxLCAyNTI4LCAxNzg4LCAyNTQxLCAyNTM5LFxuICAgICAgICA5MDYsIDkwMywgOTExLCAyNzIxLCAxODQ0LCAyNzE1LCAyNzEyLCAxODM4LCAxODM2LCAyNjk5LCAyNjk2LCAyNjkzLCAyNzAzLCAxODI3LCAxODI2LCAxODI0LCAyNjczLCAyNjcxLCAyNjY5LFxuICAgICAgICAyNjY2LCAxODI5LCAyNjc5LCAyNjc3LCAxODU4LCAxODU3LCAyNzcyLCAxODU0LCAxODUzLCAxODUxLCAxODU2LCAyNzY2LCAyNzY0LCAxNDMsIDE5ODcsIDEzOSwgMTk4NiwgMTM1LCAxMzMsXG4gICAgICAgIDEzMSwgMTk4NCwgMTI4LCAxOTgzLCAxMjUsIDE5ODEsIDEzOCwgMTM3LCAxMzYsIDE5ODUsIDExMzMsIDExMzIsIDExMzAsIDExMiwgMTEwLCAxOTc0LCAxMDcsIDE5NzMsIDEwNCwgMTk3MSxcbiAgICAgICAgMTk2OSwgMTIyLCAxMjEsIDExOSwgMTE3LCAxOTc3LCAxMTQsIDE5NzYsIDEyNCwgMTExNSwgMTExNCwgMTExMiwgMTExMCwgMTExNywgMTExNiwgODQsIDgzLCAxOTUzLCA4MSwgMTk1MiwgNzgsXG4gICAgICAgIDE5NTAsIDE5NDgsIDE5NDUsIDk0LCA5MywgOTEsIDE5NTksIDg4LCAxOTU4LCA4NSwgMTk1NSwgOTksIDk3LCA5NSwgMTk2MSwgMTA4NiwgMTA4NSwgMTA4MywgMTA4MSwgMTA3OCwgMTAwLFxuICAgICAgICAxMDkwLCAxMDg5LCAxMDg3LCAxMDkxLCA0OSwgNDcsIDE5MTcsIDQ0LCAxOTE1LCAxOTEzLCAxOTEwLCAxOTA3LCA1OSwgMTkyNiwgNTYsIDE5MjUsIDUzLCAxOTIyLCAxOTE5LCA2NiwgNjQsXG4gICAgICAgIDE5MzEsIDYxLCAxOTI5LCAxMDQyLCAxMDQwLCAxMDM4LCA3MSwgMTAzNSwgNzAsIDEwMzIsIDY4LCAxMDQ4LCAxMDQ3LCAxMDQ1LCAxMDQzLCAxMDUwLCAxMDQ5LCAxMiwgMTAsIDE4NjksIDE4NjcsXG4gICAgICAgIDE4NjQsIDE4NjEsIDIxLCAxODgwLCAxOSwgMTg3NywgMTg3NCwgMTg3MSwgMjgsIDE4ODgsIDI1LCAxODg2LCAyMiwgMTg4MywgOTgyLCA5ODAsIDk3NywgOTc0LCAzMiwgMzAsIDk5MSwgOTg5LFxuICAgICAgICA5ODcsIDk4NCwgMzQsIDk5NSwgOTk0LCA5OTIsIDIxNTEsIDIxNTAsIDIxNDcsIDIxNDYsIDIxNDQsIDM1NiwgMzU1LCAzNTQsIDIxNDksIDIxMzksIDIxMzgsIDIxMzYsIDIxMzQsIDEzNTksXG4gICAgICAgIDM0MywgMzQxLCAzMzgsIDIxNDMsIDMzNSwgMjE0MSwgMzQ4LCAzNDcsIDM0NiwgMTM3NiwgMTM3NCwgMjEyNCwgMjEyMywgMjEyMSwgMjExOSwgMTMyNiwgMjExNiwgMTMyNCwgMzEwLCAzMDgsXG4gICAgICAgIDMwNSwgMjEzMSwgMzAyLCAyMTI5LCAyOTgsIDIxMjcsIDMyMCwgMzE4LCAzMTYsIDMxMywgMjEzMywgMzIyLCAzMjEsIDEzNTUsIDEzNTMsIDEzNTEsIDEzNTcsIDIwOTIsIDIwOTEsIDIwODksXG4gICAgICAgIDIwODcsIDEyNzYsIDIwODQsIDEyNzQsIDIwODEsIDEyNzEsIDI1OSwgMjEwMiwgMjU2LCAyMTAwLCAyNTIsIDIwOTgsIDIwOTUsIDI3MiwgMjY5LCAyMTA4LCAyNjYsIDIxMDYsIDI4MSwgMjc5LFxuICAgICAgICAyNzcsIDEzMTcsIDEzMTUsIDEzMTMsIDEzMTAsIDI4MiwgMTMyMSwgMTMxOSwgMjAzOSwgMjAzNywgMjAzNSwgMjAzMiwgMTIwMywgMjAyOSwgMTIwMCwgMTE5NywgMjA3LCAyMDUzLCAyMDUsXG4gICAgICAgIDIwNTEsIDIwMSwgMjA0OSwgMjA0NiwgMjA0MywgMjIwLCAyMTgsIDIwNjQsIDIxNSwgMjA2MiwgMjExLCAyMDU5LCAyMjgsIDIyNiwgMjIzLCAyMDY5LCAxMjU5LCAxMjU3LCAxMjU0LCAyMzIsXG4gICAgICAgIDEyNTEsIDIzMCwgMTI2NywgMTI2NSwgMTI2MywgMjMxNiwgMjMxNSwgMjMxMiwgMjMxMSwgMjMwOSwgMjMxNCwgMjMwNCwgMjMwMywgMjMwMSwgMjI5OSwgMTU5MywgMjMwOCwgMjMwNiwgNTkwLFxuICAgICAgICAyMjg4LCAyMjg3LCAyMjg1LCAyMjgzLCAxNTc4LCAyMjgwLCAxNTc3LCAyMjk1LCAyMjkzLCAyMjkxLCA1NzksIDU3NywgNTc0LCA1NzEsIDIyOTgsIDU4MiwgNTgxLCAxNTkyLCAyMjYzLCAyMjYyLFxuICAgICAgICAyMjYwLCAyMjU4LCAxNTQ1LCAyMjU1LCAxNTQ0LCAyMjUyLCAxNTQxLCAyMjczLCAyMjcxLCAyMjY5LCAyMjY2LCAxNTUwLCA1MzUsIDUzMiwgMjI3OSwgNTI4LCAyMjc3LCA1NDYsIDU0MywgNTQ5LFxuICAgICAgICAxNTc1LCAxNTczLCAyMjI0LCAyMjIyLCAyMjIwLCAxNDg2LCAyMjE3LCAxNDg1LCAyMjE0LCAxNDgyLCAxNDc5LCAyMjM4LCAyMjM2LCAyMjM0LCAyMjMxLCAxNDk2LCAyMjI4LCAxNDkyLCA0ODAsXG4gICAgICAgIDQ3NywgMjI0OCwgNDczLCAyMjQ2LCA0NjksIDIyNDMsIDQ5MCwgNDg3LCAyMjUxLCA0OTcsIDE1MzcsIDE1MzUsIDE1MzIsIDI0NzcsIDI0NzYsIDI0NzQsIDI0NzksIDI0NjksIDI0NjgsIDI0NjYsXG4gICAgICAgIDI0NjQsIDE3MzAsIDI0NzMsIDI0NzEsIDI0NTMsIDI0NTIsIDI0NTAsIDI0NDgsIDE3MjksIDI0NDUsIDE3MjgsIDI0NjAsIDI0NTgsIDI0NTYsIDI0NjMsIDgwNSwgODA0LCAyNDI4LCAyNDI3LFxuICAgICAgICAyNDI1LCAyNDIzLCAxNzI1LCAyNDIwLCAxNzI0LCAyNDE3LCAxNzIyLCAyNDM4LCAyNDM2LCAyNDM0LCAyNDMxLCAxNzI3LCAyNDQ0LCAyNDQyLCA3OTMsIDc5MSwgNzg4LCA3OTUsIDIzODgsXG4gICAgICAgIDIzODYsIDIzODQsIDE2OTcsIDIzODEsIDE2OTYsIDIzNzgsIDE2OTQsIDE2OTIsIDI0MDIsIDI0MDAsIDIzOTgsIDIzOTUsIDE3MDMsIDIzOTIsIDE3MDEsIDI0MTIsIDI0MTAsIDI0MDcsIDc1MSxcbiAgICAgICAgNzQ4LCA3NDQsIDI0MTYsIDc1OSwgNzU3LCAxODA3LCAyNjIwLCAyNjE4LCAxODA2LCAxODA1LCAyNjExLCAyNjA5LCAyNjA3LCAyNjE0LCAxODAyLCAxODAxLCAxNzk5LCAyNTk0LCAyNTkyLFxuICAgICAgICAyNTkwLCAyNTg3LCAxODA0LCAyNjAwLCAyNTk4LCAxNzk0LCAxNzkzLCAxNzkxLCAxNzg5LCAyNTY0LCAyNTYyLCAyNTYwLCAyNTU3LCAxNzk4LCAyNTU0LCAxNzk2LCAyNTc0LCAyNTcyLCAyNTY5LFxuICAgICAgICAyNTc4LCAxODQ3LCAxODQ2LCAyNzIyLCAxODQzLCAxODQyLCAxODQwLCAxODQ1LCAyNzE2LCAyNzE0LCAxODM1LCAxODM0LCAxODMyLCAxODMwLCAxODM5LCAxODM3LCAyNzAwLCAyNjk4LCAyNjk1LFxuICAgICAgICAyNzA0LCAxODE3LCAxODExLCAxODEwLCA4OTcsIDg2MiwgMTc3NywgODI5LCA4MjYsIDgzOCwgMTc2MCwgMTc1OCwgODA4LCAyNDgxLCAxNzQxLCAxNzQwLCAxNzM4LCAxNzQzLCAyNjI0LCAxODE4LFxuICAgICAgICAyNzI2LCAyNzc2LCA3ODIsIDc0MCwgNzM3LCAxNzE1LCA2ODYsIDY3OSwgNjk1LCAxNjgyLCAxNjgwLCA2MzksIDYyOCwgMjMzOSwgNjQ3LCA2NDQsIDE2NDUsIDE2NDMsIDE2NDAsIDE2NDgsXG4gICAgICAgIDYwMiwgNjAwLCA1OTcsIDU5NSwgMjMyMCwgNTkzLCAyMzE4LCA2MDksIDYwNywgNjA0LCAxNjExLCAxNjEwLCAxNjA4LCAxNjA2LCA2MTMsIDE2MTUsIDE2MTMsIDIzMjgsIDkyNiwgOTI0LCA4OTIsXG4gICAgICAgIDg4NiwgODk5LCA4NTcsIDg1MCwgMjUwNSwgMTc3OCwgODI0LCA4MjMsIDgyMSwgODE5LCAyNDg4LCA4MTgsIDI0ODYsIDgzMywgODMxLCA4MjgsIDg0MCwgMTc2MSwgMTc1OSwgMjY0OSwgMjYzMixcbiAgICAgICAgMjYzMCwgMjc0NiwgMjczNCwgMjczMiwgMjc4MiwgMjc4MSwgNTcwLCA1NjcsIDE1ODcsIDUzMSwgNTI3LCA1MjMsIDU0MCwgMTU2NiwgMTU2NCwgNDc2LCA0NjcsIDQ2MywgMjI0MCwgNDg2LFxuICAgICAgICA0ODMsIDE1MjQsIDE1MjEsIDE1MTgsIDE1MjksIDQxMSwgNDAzLCAyMTkyLCAzOTksIDIxODksIDQyMywgNDE2LCAxNDYyLCAxNDU3LCAxNDU0LCA0MjgsIDE0NjgsIDE0NjUsIDIyMTAsIDM2NixcbiAgICAgICAgMzYzLCAyMTU4LCAzNjAsIDIxNTYsIDM1NywgMjE1MywgMzc2LCAzNzMsIDM3MCwgMjE2MywgMTQxMCwgMTQwOSwgMTQwNywgMTQwNSwgMzgyLCAxNDAyLCAzODAsIDE0MTcsIDE0MTUsIDE0MTIsXG4gICAgICAgIDE0MjEsIDIxNzUsIDIxNzQsIDc3NywgNzc0LCA3NzEsIDc4NCwgNzMyLCA3MjUsIDcyMiwgMjQwNCwgNzQzLCAxNzE2LCA2NzYsIDY3NCwgNjY4LCAyMzYzLCA2NjUsIDIzNjAsIDY4NSwgMTY4NCxcbiAgICAgICAgMTY4MSwgNjI2LCA2MjQsIDYyMiwgMjMzNSwgNjIwLCAyMzMzLCA2MTcsIDIzMzAsIDY0MSwgNjM1LCA2NDksIDE2NDYsIDE2NDQsIDE2NDIsIDI1NjYsIDkyOCwgOTI1LCAyNTMwLCAyNTI3LFxuICAgICAgICA4OTQsIDg5MSwgODg4LCAyNTAxLCAyNDk5LCAyNDk2LCA4NTgsIDg1NiwgODU0LCA4NTEsIDE3NzksIDI2OTIsIDI2NjgsIDI2NjUsIDI2NDUsIDI2NDMsIDI2NDAsIDI2NTEsIDI3NjgsIDI3NTksXG4gICAgICAgIDI3NTcsIDI3NDQsIDI3NDMsIDI3NDEsIDI3NDgsIDM1MiwgMTM4MiwgMzQwLCAzMzcsIDMzMywgMTM3MSwgMTM2OSwgMzA3LCAzMDAsIDI5NiwgMjEyNiwgMzE1LCAzMTIsIDEzNDcsIDEzNDIsXG4gICAgICAgIDEzNTAsIDI2MSwgMjU4LCAyNTAsIDIwOTcsIDI0NiwgMjA5NCwgMjcxLCAyNjgsIDI2NCwgMTMwNiwgMTMwMSwgMTI5OCwgMjc2LCAxMzEyLCAxMzA5LCAyMTE1LCAyMDMsIDIwNDgsIDE5NSxcbiAgICAgICAgMjA0NSwgMTkxLCAyMDQxLCAyMTMsIDIwOSwgMjA1NiwgMTI0NiwgMTI0NCwgMTIzOCwgMjI1LCAxMjM0LCAyMjIsIDEyNTYsIDEyNTMsIDEyNDksIDEyNjIsIDIwODAsIDIwNzksIDE1NCwgMTk5NyxcbiAgICAgICAgMTUwLCAxOTk1LCAxNDcsIDE5OTIsIDE5ODksIDE2MywgMTYwLCAyMDA0LCAxNTYsIDIwMDEsIDExNzUsIDExNzQsIDExNzIsIDExNzAsIDExNjcsIDE3MCwgMTE2NCwgMTY3LCAxMTg1LCAxMTgzLFxuICAgICAgICAxMTgwLCAxMTc3LCAxNzQsIDExOTAsIDExODgsIDIwMjUsIDIwMjQsIDIwMjIsIDU4NywgNTg2LCA1NjQsIDU1OSwgNTU2LCAyMjkwLCA1NzMsIDE1ODgsIDUyMCwgNTE4LCA1MTIsIDIyNjgsXG4gICAgICAgIDUwOCwgMjI2NSwgNTMwLCAxNTY4LCAxNTY1LCA0NjEsIDQ1NywgMjIzMywgNDUwLCAyMjMwLCA0NDYsIDIyMjYsIDQ3OSwgNDcxLCA0ODksIDE1MjYsIDE1MjMsIDE1MjAsIDM5NywgMzk1LFxuICAgICAgICAyMTg1LCAzOTIsIDIxODMsIDM4OSwgMjE4MCwgMjE3NywgNDEwLCAyMTk0LCA0MDIsIDQyMiwgMTQ2MywgMTQ2MSwgMTQ1OSwgMTQ1NiwgMTQ3MCwgMjQ1NSwgNzk5LCAyNDMzLCAyNDMwLCA3NzksXG4gICAgICAgIDc3NiwgNzczLCAyMzk3LCAyMzk0LCAyMzkwLCA3MzQsIDcyOCwgNzI0LCA3NDYsIDE3MTcsIDIzNTYsIDIzNTQsIDIzNTEsIDIzNDgsIDE2NTgsIDY3NywgNjc1LCA2NzMsIDY3MCwgNjY3LCA2ODgsXG4gICAgICAgIDE2ODUsIDE2ODMsIDI2MDYsIDI1ODksIDI1ODYsIDI1NTksIDI1NTYsIDI1NTIsIDkyNywgMjUyMywgMjUyMSwgMjUxOCwgMjUxNSwgMTc4NCwgMjUzMiwgODk1LCA4OTMsIDg5MCwgMjcxOCxcbiAgICAgICAgMjcwOSwgMjcwNywgMjY4OSwgMjY4NywgMjY4NCwgMjY2MywgMjY2MiwgMjY2MCwgMjY1OCwgMTgyNSwgMjY2NywgMjc2OSwgMTg1MiwgMjc2MCwgMjc1OCwgMTQyLCAxNDEsIDExMzksIDExMzgsXG4gICAgICAgIDEzNCwgMTMyLCAxMjksIDEyNiwgMTk4MiwgMTEyOSwgMTEyOCwgMTEyNiwgMTEzMSwgMTEzLCAxMTEsIDEwOCwgMTA1LCAxOTcyLCAxMDEsIDE5NzAsIDEyMCwgMTE4LCAxMTUsIDExMDksIDExMDgsXG4gICAgICAgIDExMDYsIDExMDQsIDEyMywgMTExMywgMTExMSwgODIsIDc5LCAxOTUxLCA3NSwgMTk0OSwgNzIsIDE5NDYsIDkyLCA4OSwgODYsIDE5NTYsIDEwNzcsIDEwNzYsIDEwNzQsIDEwNzIsIDk4LFxuICAgICAgICAxMDY5LCA5NiwgMTA4NCwgMTA4MiwgMTA3OSwgMTA4OCwgMTk2OCwgMTk2NywgNDgsIDQ1LCAxOTE2LCA0MiwgMTkxNCwgMzksIDE5MTEsIDE5MDgsIDYwLCA1NywgNTQsIDE5MjMsIDUwLCAxOTIwLFxuICAgICAgICAxMDMxLCAxMDMwLCAxMDI4LCAxMDI2LCA2NywgMTAyMywgNjUsIDEwMjAsIDYyLCAxMDQxLCAxMDM5LCAxMDM2LCAxMDMzLCA2OSwgMTA0NiwgMTA0NCwgMTk0NCwgMTk0MywgMTk0MSwgMTEsIDksXG4gICAgICAgIDE4NjgsIDcsIDE4NjUsIDE4NjIsIDE4NTksIDIwLCAxODc4LCAxNiwgMTg3NSwgMTMsIDE4NzIsIDk3MCwgOTY4LCA5NjYsIDk2MywgMjksIDk2MCwgMjYsIDIzLCA5ODMsIDk4MSwgOTc4LCA5NzUsXG4gICAgICAgIDMzLCA5NzEsIDMxLCA5OTAsIDk4OCwgOTg1LCAxOTA2LCAxOTA0LCAxOTAyLCA5OTMsIDM1MSwgMjE0NSwgMTM4MywgMzMxLCAzMzAsIDMyOCwgMzI2LCAyMTM3LCAzMjMsIDIxMzUsIDMzOSxcbiAgICAgICAgMTM3MiwgMTM3MCwgMjk0LCAyOTMsIDI5MSwgMjg5LCAyMTIyLCAyODYsIDIxMjAsIDI4MywgMjExNywgMzA5LCAzMDMsIDMxNywgMTM0OCwgMTM0NiwgMTM0NCwgMjQ1LCAyNDQsIDI0MiwgMjA5MCxcbiAgICAgICAgMjM5LCAyMDg4LCAyMzYsIDIwODUsIDIwODIsIDI2MCwgMjA5OSwgMjQ5LCAyNzAsIDEzMDcsIDEzMDUsIDEzMDMsIDEzMDAsIDEzMTQsIDE4OSwgMjAzOCwgMTg2LCAyMDM2LCAxODMsIDIwMzMsXG4gICAgICAgIDIwMzAsIDIwMjYsIDIwNiwgMTk4LCAyMDQ3LCAxOTQsIDIxNiwgMTI0NywgMTI0NSwgMTI0MywgMTI0MCwgMjI3LCAxMjM3LCAxMjU1LCAyMzEwLCAyMzAyLCAyMzAwLCAyMjg2LCAyMjg0LFxuICAgICAgICAyMjgxLCA1NjUsIDU2MywgNTYxLCA1NTgsIDU3NSwgMTU4OSwgMjI2MSwgMjI1OSwgMjI1NiwgMjI1MywgMTU0MiwgNTIxLCA1MTksIDUxNywgNTE0LCAyMjcwLCA1MTEsIDUzMywgMTU2OSxcbiAgICAgICAgMTU2NywgMjIyMywgMjIyMSwgMjIxOCwgMjIxNSwgMTQ4MywgMjIxMSwgMTQ4MCwgNDU5LCA0NTYsIDQ1MywgMjIzMiwgNDQ5LCA0NzQsIDQ5MSwgMTUyNywgMTUyNSwgMTUyMiwgMjQ3NSwgMjQ2NyxcbiAgICAgICAgMjQ2NSwgMjQ1MSwgMjQ0OSwgMjQ0NiwgODAxLCA4MDAsIDI0MjYsIDI0MjQsIDI0MjEsIDI0MTgsIDE3MjMsIDI0MzUsIDc4MCwgNzc4LCA3NzUsIDIzODcsIDIzODUsIDIzODIsIDIzNzksXG4gICAgICAgIDE2OTUsIDIzNzUsIDE2OTMsIDIzOTYsIDczNSwgNzMzLCA3MzAsIDcyNywgNzQ5LCAxNzE4LCAyNjE2LCAyNjE1LCAyNjA0LCAyNjAzLCAyNjAxLCAyNTg0LCAyNTgzLCAyNTgxLCAyNTc5LFxuICAgICAgICAxODAwLCAyNTkxLCAyNTUwLCAyNTQ5LCAyNTQ3LCAyNTQ1LCAxNzkyLCAyNTQyLCAxNzkwLCAyNTU4LCA5MjksIDI3MTksIDE4NDEsIDI3MTAsIDI3MDgsIDE4MzMsIDE4MzEsIDI2OTAsIDI2ODgsXG4gICAgICAgIDI2ODYsIDE4MTUsIDE4MDksIDE4MDgsIDE3NzQsIDE3NTYsIDE3NTQsIDE3MzcsIDE3MzYsIDE3MzQsIDE3MzksIDE4MTYsIDE3MTEsIDE2NzYsIDE2NzQsIDYzMywgNjI5LCAxNjM4LCAxNjM2LFxuICAgICAgICAxNjMzLCAxNjQxLCA1OTgsIDE2MDUsIDE2MDQsIDE2MDIsIDE2MDAsIDYwNSwgMTYwOSwgMTYwNywgMjMyNywgODg3LCA4NTMsIDE3NzUsIDgyMiwgODIwLCAxNzU3LCAxNzU1LCAxNTg0LCA1MjQsXG4gICAgICAgIDE1NjAsIDE1NTgsIDQ2OCwgNDY0LCAxNTE0LCAxNTExLCAxNTA4LCAxNTE5LCA0MDgsIDQwNCwgNDAwLCAxNDUyLCAxNDQ3LCAxNDQ0LCA0MTcsIDE0NTgsIDE0NTUsIDIyMDgsIDM2NCwgMzYxLFxuICAgICAgICAzNTgsIDIxNTQsIDE0MDEsIDE0MDAsIDEzOTgsIDEzOTYsIDM3NCwgMTM5MywgMzcxLCAxNDA4LCAxNDA2LCAxNDAzLCAxNDEzLCAyMTczLCAyMTcyLCA3NzIsIDcyNiwgNzIzLCAxNzEyLCA2NzIsXG4gICAgICAgIDY2OSwgNjY2LCA2ODIsIDE2NzgsIDE2NzUsIDYyNSwgNjIzLCA2MjEsIDYxOCwgMjMzMSwgNjM2LCA2MzIsIDE2MzksIDE2MzcsIDE2MzUsIDkyMCwgOTE4LCA4ODQsIDg4MCwgODg5LCA4NDksXG4gICAgICAgIDg0OCwgODQ3LCA4NDYsIDI0OTcsIDg1NSwgODUyLCAxNzc2LCAyNjQxLCAyNzQyLCAyNzg3LCAxMzgwLCAzMzQsIDEzNjcsIDEzNjUsIDMwMSwgMjk3LCAxMzQwLCAxMzM4LCAxMzM1LCAxMzQzLFxuICAgICAgICAyNTUsIDI1MSwgMjQ3LCAxMjk2LCAxMjkxLCAxMjg4LCAyNjUsIDEzMDIsIDEyOTksIDIxMTMsIDIwNCwgMTk2LCAxOTIsIDIwNDIsIDEyMzIsIDEyMzAsIDEyMjQsIDIxNCwgMTIyMCwgMjEwLFxuICAgICAgICAxMjQyLCAxMjM5LCAxMjM1LCAxMjUwLCAyMDc3LCAyMDc1LCAxNTEsIDE0OCwgMTk5MywgMTQ0LCAxOTkwLCAxMTYzLCAxMTYyLCAxMTYwLCAxMTU4LCAxMTU1LCAxNjEsIDExNTIsIDE1NyxcbiAgICAgICAgMTE3MywgMTE3MSwgMTE2OCwgMTE2NSwgMTY4LCAxMTgxLCAxMTc4LCAyMDIxLCAyMDIwLCAyMDE4LCAyMDIzLCA1ODUsIDU2MCwgNTU3LCAxNTg1LCA1MTYsIDUwOSwgMTU2MiwgMTU1OSwgNDU4LFxuICAgICAgICA0NDcsIDIyMjcsIDQ3MiwgMTUxNiwgMTUxMywgMTUxMCwgMzk4LCAzOTYsIDM5MywgMzkwLCAyMTgxLCAzODYsIDIxNzgsIDQwNywgMTQ1MywgMTQ1MSwgMTQ0OSwgMTQ0NiwgNDIwLCAxNDYwLFxuICAgICAgICAyMjA5LCA3NjksIDc2NCwgNzIwLCA3MTIsIDIzOTEsIDcyOSwgMTcxMywgNjY0LCA2NjMsIDY2MSwgNjU5LCAyMzUyLCA2NTYsIDIzNDksIDY3MSwgMTY3OSwgMTY3NywgMjU1MywgOTIyLCA5MTksXG4gICAgICAgIDI1MTksIDI1MTYsIDg4NSwgODgzLCA4ODEsIDI2ODUsIDI2NjEsIDI2NTksIDI3NjcsIDI3NTYsIDI3NTUsIDE0MCwgMTEzNywgMTEzNiwgMTMwLCAxMjcsIDExMjUsIDExMjQsIDExMjIsIDExMjcsXG4gICAgICAgIDEwOSwgMTA2LCAxMDIsIDExMDMsIDExMDIsIDExMDAsIDEwOTgsIDExNiwgMTEwNywgMTEwNSwgMTk4MCwgODAsIDc2LCA3MywgMTk0NywgMTA2OCwgMTA2NywgMTA2NSwgMTA2MywgOTAsIDEwNjAsXG4gICAgICAgIDg3LCAxMDc1LCAxMDczLCAxMDcwLCAxMDgwLCAxOTY2LCAxOTY1LCA0NiwgNDMsIDQwLCAxOTEyLCAzNiwgMTkwOSwgMTAxOSwgMTAxOCwgMTAxNiwgMTAxNCwgNTgsIDEwMTEsIDU1LCAxMDA4LFxuICAgICAgICA1MSwgMTAyOSwgMTAyNywgMTAyNCwgMTAyMSwgNjMsIDEwMzcsIDEwMzQsIDE5NDAsIDE5MzksIDE5MzcsIDE5NDIsIDgsIDE4NjYsIDQsIDE4NjMsIDEsIDE4NjAsIDk1NiwgOTU0LCA5NTIsXG4gICAgICAgIDk0OSwgOTQ2LCAxNywgMTQsIDk2OSwgOTY3LCA5NjQsIDk2MSwgMjcsIDk1NywgMjQsIDk3OSwgOTc2LCA5NzIsIDE5MDEsIDE5MDAsIDE4OTgsIDE4OTYsIDk4NiwgMTkwNSwgMTkwMywgMzUwLFxuICAgICAgICAzNDksIDEzODEsIDMyOSwgMzI3LCAzMjQsIDEzNjgsIDEzNjYsIDI5MiwgMjkwLCAyODcsIDI4NCwgMjExOCwgMzA0LCAxMzQxLCAxMzM5LCAxMzM3LCAxMzQ1LCAyNDMsIDI0MCwgMjM3LCAyMDg2LFxuICAgICAgICAyMzMsIDIwODMsIDI1NCwgMTI5NywgMTI5NSwgMTI5MywgMTI5MCwgMTMwNCwgMjExNCwgMTkwLCAxODcsIDE4NCwgMjAzNCwgMTgwLCAyMDMxLCAxNzcsIDIwMjcsIDE5OSwgMTIzMywgMTIzMSxcbiAgICAgICAgMTIyOSwgMTIyNiwgMjE3LCAxMjIzLCAxMjQxLCAyMDc4LCAyMDc2LCA1ODQsIDU1NSwgNTU0LCA1NTIsIDU1MCwgMjI4MiwgNTYyLCAxNTg2LCA1MDcsIDUwNiwgNTA0LCA1MDIsIDIyNTcsIDQ5OSxcbiAgICAgICAgMjI1NCwgNTE1LCAxNTYzLCAxNTYxLCA0NDUsIDQ0MywgNDQxLCAyMjE5LCA0MzgsIDIyMTYsIDQzNSwgMjIxMiwgNDYwLCA0NTQsIDQ3NSwgMTUxNywgMTUxNSwgMTUxMiwgMjQ0NywgNzk4LFxuICAgICAgICA3OTcsIDI0MjIsIDI0MTksIDc3MCwgNzY4LCA3NjYsIDIzODMsIDIzODAsIDIzNzYsIDcyMSwgNzE5LCA3MTcsIDcxNCwgNzMxLCAxNzE0LCAyNjAyLCAyNTgyLCAyNTgwLCAyNTQ4LCAyNTQ2LFxuICAgICAgICAyNTQzLCA5MjMsIDkyMSwgMjcxNywgMjcwNiwgMjcwNSwgMjY4MywgMjY4MiwgMjY4MCwgMTc3MSwgMTc1MiwgMTc1MCwgMTczMywgMTczMiwgMTczMSwgMTczNSwgMTgxNCwgMTcwNywgMTY3MCxcbiAgICAgICAgMTY2OCwgMTYzMSwgMTYyOSwgMTYyNiwgMTYzNCwgMTU5OSwgMTU5OCwgMTU5NiwgMTU5NCwgMTYwMywgMTYwMSwgMjMyNiwgMTc3MiwgMTc1MywgMTc1MSwgMTU4MSwgMTU1NCwgMTU1MiwgMTUwNCxcbiAgICAgICAgMTUwMSwgMTQ5OCwgMTUwOSwgMTQ0MiwgMTQzNywgMTQzNCwgNDAxLCAxNDQ4LCAxNDQ1LCAyMjA2LCAxMzkyLCAxMzkxLCAxMzg5LCAxMzg3LCAxMzg0LCAzNTksIDEzOTksIDEzOTcsIDEzOTQsXG4gICAgICAgIDE0MDQsIDIxNzEsIDIxNzAsIDE3MDgsIDE2NzIsIDE2NjksIDYxOSwgMTYzMiwgMTYzMCwgMTYyOCwgMTc3MywgMTM3OCwgMTM2MywgMTM2MSwgMTMzMywgMTMyOCwgMTMzNiwgMTI4NiwgMTI4MSxcbiAgICAgICAgMTI3OCwgMjQ4LCAxMjkyLCAxMjg5LCAyMTExLCAxMjE4LCAxMjE2LCAxMjEwLCAxOTcsIDEyMDYsIDE5MywgMTIyOCwgMTIyNSwgMTIyMSwgMTIzNiwgMjA3MywgMjA3MSwgMTE1MSwgMTE1MCxcbiAgICAgICAgMTE0OCwgMTE0NiwgMTUyLCAxMTQzLCAxNDksIDExNDAsIDE0NSwgMTE2MSwgMTE1OSwgMTE1NiwgMTE1MywgMTU4LCAxMTY5LCAxMTY2LCAyMDE3LCAyMDE2LCAyMDE0LCAyMDE5LCAxNTgyLFxuICAgICAgICA1MTAsIDE1NTYsIDE1NTMsIDQ1MiwgNDQ4LCAxNTA2LCAxNTAwLCAzOTQsIDM5MSwgMzg3LCAxNDQzLCAxNDQxLCAxNDM5LCAxNDM2LCAxNDUwLCAyMjA3LCA3NjUsIDcxNiwgNzEzLCAxNzA5LFxuICAgICAgICA2NjIsIDY2MCwgNjU3LCAxNjczLCAxNjcxLCA5MTYsIDkxNCwgODc5LCA4NzgsIDg3NywgODgyLCAxMTM1LCAxMTM0LCAxMTIxLCAxMTIwLCAxMTE4LCAxMTIzLCAxMDk3LCAxMDk2LCAxMDk0LFxuICAgICAgICAxMDkyLCAxMDMsIDExMDEsIDEwOTksIDE5NzksIDEwNTksIDEwNTgsIDEwNTYsIDEwNTQsIDc3LCAxMDUxLCA3NCwgMTA2NiwgMTA2NCwgMTA2MSwgMTA3MSwgMTk2NCwgMTk2MywgMTAwNyxcbiAgICAgICAgMTAwNiwgMTAwNCwgMTAwMiwgOTk5LCA0MSwgOTk2LCAzNywgMTAxNywgMTAxNSwgMTAxMiwgMTAwOSwgNTIsIDEwMjUsIDEwMjIsIDE5MzYsIDE5MzUsIDE5MzMsIDE5MzgsIDk0MiwgOTQwLFxuICAgICAgICA5MzgsIDkzNSwgOTMyLCA1LCAyLCA5NTUsIDk1MywgOTUwLCA5NDcsIDE4LCA5NDMsIDE1LCA5NjUsIDk2MiwgOTU4LCAxODk1LCAxODk0LCAxODkyLCAxODkwLCA5NzMsIDE4OTksIDE4OTcsXG4gICAgICAgIDEzNzksIDMyNSwgMTM2NCwgMTM2MiwgMjg4LCAyODUsIDEzMzQsIDEzMzIsIDEzMzAsIDI0MSwgMjM4LCAyMzQsIDEyODcsIDEyODUsIDEyODMsIDEyODAsIDEyOTQsIDIxMTIsIDE4OCwgMTg1LFxuICAgICAgICAxODEsIDE3OCwgMjAyOCwgMTIxOSwgMTIxNywgMTIxNSwgMTIxMiwgMjAwLCAxMjA5LCAxMjI3LCAyMDc0LCAyMDcyLCA1ODMsIDU1MywgNTUxLCAxNTgzLCA1MDUsIDUwMywgNTAwLCA1MTMsXG4gICAgICAgIDE1NTcsIDE1NTUsIDQ0NCwgNDQyLCA0MzksIDQzNiwgMjIxMywgNDU1LCA0NTEsIDE1MDcsIDE1MDUsIDE1MDIsIDc5NiwgNzYzLCA3NjIsIDc2MCwgNzY3LCA3MTEsIDcxMCwgNzA4LCA3MDYsXG4gICAgICAgIDIzNzcsIDcxOCwgNzE1LCAxNzEwLCAyNTQ0LCA5MTcsIDkxNSwgMjY4MSwgMTYyNywgMTU5NywgMTU5NSwgMjMyNSwgMTc2OSwgMTc0OSwgMTc0NywgMTQ5OSwgMTQzOCwgMTQzNSwgMjIwNCxcbiAgICAgICAgMTM5MCwgMTM4OCwgMTM4NSwgMTM5NSwgMjE2OSwgMjE2NywgMTcwNCwgMTY2NSwgMTY2MiwgMTYyNSwgMTYyMywgMTYyMCwgMTc3MCwgMTMyOSwgMTI4MiwgMTI3OSwgMjEwOSwgMTIxNCwgMTIwNyxcbiAgICAgICAgMTIyMiwgMjA2OCwgMjA2NSwgMTE0OSwgMTE0NywgMTE0NCwgMTE0MSwgMTQ2LCAxMTU3LCAxMTU0LCAyMDEzLCAyMDExLCAyMDA4LCAyMDE1LCAxNTc5LCAxNTQ5LCAxNTQ2LCAxNDk1LCAxNDg3LFxuICAgICAgICAxNDMzLCAxNDMxLCAxNDI4LCAxNDI1LCAzODgsIDE0NDAsIDIyMDUsIDE3MDUsIDY1OCwgMTY2NywgMTY2NCwgMTExOSwgMTA5NSwgMTA5MywgMTk3OCwgMTA1NywgMTA1NSwgMTA1MiwgMTA2MixcbiAgICAgICAgMTk2MiwgMTk2MCwgMTAwNSwgMTAwMywgMTAwMCwgOTk3LCAzOCwgMTAxMywgMTAxMCwgMTkzMiwgMTkzMCwgMTkyNywgMTkzNCwgOTQxLCA5MzksIDkzNiwgOTMzLCA2LCA5MzAsIDMsIDk1MSxcbiAgICAgICAgOTQ4LCA5NDQsIDE4ODksIDE4ODcsIDE4ODQsIDE4ODEsIDk1OSwgMTg5MywgMTg5MSwgMzUsIDEzNzcsIDEzNjAsIDEzNTgsIDEzMjcsIDEzMjUsIDEzMjIsIDEzMzEsIDEyNzcsIDEyNzUsXG4gICAgICAgIDEyNzIsIDEyNjksIDIzNSwgMTI4NCwgMjExMCwgMTIwNSwgMTIwNCwgMTIwMSwgMTE5OCwgMTgyLCAxMTk1LCAxNzksIDEyMTMsIDIwNzAsIDIwNjcsIDE1ODAsIDUwMSwgMTU1MSwgMTU0OCxcbiAgICAgICAgNDQwLCA0MzcsIDE0OTcsIDE0OTQsIDE0OTAsIDE1MDMsIDc2MSwgNzA5LCA3MDcsIDE3MDYsIDkxMywgOTEyLCAyMTk4LCAxMzg2LCAyMTY0LCAyMTYxLCAxNjIxLCAxNzY2LCAyMTAzLCAxMjA4LFxuICAgICAgICAyMDU4LCAyMDU0LCAxMTQ1LCAxMTQyLCAyMDA1LCAyMDAyLCAxOTk5LCAyMDA5LCAxNDg4LCAxNDI5LCAxNDI2LCAyMjAwLCAxNjk4LCAxNjU5LCAxNjU2LCAxOTc1LCAxMDUzLCAxOTU3LCAxOTU0LFxuICAgICAgICAxMDAxLCA5OTgsIDE5MjQsIDE5MjEsIDE5MTgsIDE5MjgsIDkzNywgOTM0LCA5MzEsIDE4NzksIDE4NzYsIDE4NzMsIDE4NzAsIDk0NSwgMTg4NSwgMTg4MiwgMTMyMywgMTI3MywgMTI3MCxcbiAgICAgICAgMjEwNSwgMTIwMiwgMTE5OSwgMTE5NiwgMTIxMSwgMjA2MSwgMjA1NywgMTU3NiwgMTU0MywgMTU0MCwgMTQ4NCwgMTQ4MSwgMTQ3OCwgMTQ5MSwgMTcwMFxuICAgIF0pO1xuXG4gICAgLypcbiAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAqXG4gICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgKlxuICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAqXG4gICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICovXG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5MaXN0O1xuICAgIC8qKlxuICAgICAqIEBhdXRob3IgR3VlbnRoZXIgR3JhdVxuICAgICAqL1xuICAgIC8qcHVibGljIGZpbmFsKi8gY2xhc3MgUERGNDE3RGV0ZWN0b3JSZXN1bHQge1xuICAgICAgICBjb25zdHJ1Y3RvcihiaXRzLCBwb2ludHMpIHtcbiAgICAgICAgICAgIHRoaXMuYml0cyA9IGJpdHM7XG4gICAgICAgICAgICB0aGlzLnBvaW50cyA9IHBvaW50cztcbiAgICAgICAgfVxuICAgICAgICBnZXRCaXRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYml0cztcbiAgICAgICAgfVxuICAgICAgICBnZXRQb2ludHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wb2ludHM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICogQ29weXJpZ2h0IDIwMDkgWlhpbmcgYXV0aG9yc1xuICAgICpcbiAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAqXG4gICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICpcbiAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgKi9cbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLkFycmF5TGlzdDtcbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLkFycmF5cztcbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLkxpc3Q7XG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5NYXA7XG4gICAgLyoqXG4gICAgICogPHA+RW5jYXBzdWxhdGVzIGxvZ2ljIHRoYXQgY2FuIGRldGVjdCBhIFBERjQxNyBDb2RlIGluIGFuIGltYWdlLCBldmVuIGlmIHRoZVxuICAgICAqIFBERjQxNyBDb2RlIGlzIHJvdGF0ZWQgb3Igc2tld2VkLCBvciBwYXJ0aWFsbHkgb2JzY3VyZWQuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTSVRBIExhYiAoa2V2aW4ub3N1bGxpdmFuQHNpdGEuYWVybylcbiAgICAgKiBAYXV0aG9yIGRzd2l0a2luQGdvb2dsZS5jb20gKERhbmllbCBTd2l0a2luKVxuICAgICAqIEBhdXRob3IgR3VlbnRoZXIgR3JhdVxuICAgICAqL1xuICAgIC8qcHVibGljKi8gLypmaW5hbCovIGNsYXNzIERldGVjdG9yJDMge1xuICAgICAgICAvKipcbiAgICAgICAgICogPHA+RGV0ZWN0cyBhIFBERjQxNyBDb2RlIGluIGFuIGltYWdlLiBPbmx5IGNoZWNrcyAwIGFuZCAxODAgZGVncmVlIHJvdGF0aW9ucy48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBpbWFnZSBiYXJjb2RlIGltYWdlIHRvIGRlY29kZVxuICAgICAgICAgKiBAcGFyYW0gaGludHMgb3B0aW9uYWwgaGludHMgdG8gZGV0ZWN0b3JcbiAgICAgICAgICogQHBhcmFtIG11bHRpcGxlIGlmIHRydWUsIHRoZW4gdGhlIGltYWdlIGlzIHNlYXJjaGVkIGZvciBtdWx0aXBsZSBjb2Rlcy4gSWYgZmFsc2UsIHRoZW4gYXQgbW9zdCBvbmUgY29kZSB3aWxsXG4gICAgICAgICAqIGJlIGZvdW5kIGFuZCByZXR1cm5lZFxuICAgICAgICAgKiBAcmV0dXJuIHtAbGluayBQREY0MTdEZXRlY3RvclJlc3VsdH0gZW5jYXBzdWxhdGluZyByZXN1bHRzIG9mIGRldGVjdGluZyBhIFBERjQxNyBjb2RlXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gaWYgbm8gUERGNDE3IENvZGUgY2FuIGJlIGZvdW5kXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGV0ZWN0TXVsdGlwbGUoaW1hZ2UsIGhpbnRzLCBtdWx0aXBsZSkge1xuICAgICAgICAgICAgLy8gVE9ETyBkZXRlY3Rpb24gaW1wcm92ZW1lbnQsIHRyeUhhcmRlciBjb3VsZCB0cnkgc2V2ZXJhbCBkaWZmZXJlbnQgbHVtaW5hbmNlIHRocmVzaG9sZHMvYmxhY2twb2ludHMgb3IgZXZlblxuICAgICAgICAgICAgLy8gZGlmZmVyZW50IGJpbmFyaXplcnNcbiAgICAgICAgICAgIC8vIGJvb2xlYW4gdHJ5SGFyZGVyID0gaGludHMgIT0gbnVsbCAmJiBoaW50cy5jb250YWluc0tleShEZWNvZGVIaW50VHlwZS5UUllfSEFSREVSKTtcbiAgICAgICAgICAgIGxldCBiaXRNYXRyaXggPSBpbWFnZS5nZXRCbGFja01hdHJpeCgpO1xuICAgICAgICAgICAgbGV0IGJhcmNvZGVDb29yZGluYXRlcyA9IERldGVjdG9yJDMuZGV0ZWN0KG11bHRpcGxlLCBiaXRNYXRyaXgpO1xuICAgICAgICAgICAgaWYgKCFiYXJjb2RlQ29vcmRpbmF0ZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgYml0TWF0cml4ID0gYml0TWF0cml4LmNsb25lKCk7XG4gICAgICAgICAgICAgICAgYml0TWF0cml4LnJvdGF0ZTE4MCgpO1xuICAgICAgICAgICAgICAgIGJhcmNvZGVDb29yZGluYXRlcyA9IERldGVjdG9yJDMuZGV0ZWN0KG11bHRpcGxlLCBiaXRNYXRyaXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBQREY0MTdEZXRlY3RvclJlc3VsdChiaXRNYXRyaXgsIGJhcmNvZGVDb29yZGluYXRlcyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERldGVjdHMgUERGNDE3IGNvZGVzIGluIGFuIGltYWdlLiBPbmx5IGNoZWNrcyAwIGRlZ3JlZSByb3RhdGlvblxuICAgICAgICAgKiBAcGFyYW0gbXVsdGlwbGUgaWYgdHJ1ZSwgdGhlbiB0aGUgaW1hZ2UgaXMgc2VhcmNoZWQgZm9yIG11bHRpcGxlIGNvZGVzLiBJZiBmYWxzZSwgdGhlbiBhdCBtb3N0IG9uZSBjb2RlIHdpbGxcbiAgICAgICAgICogYmUgZm91bmQgYW5kIHJldHVybmVkXG4gICAgICAgICAqIEBwYXJhbSBiaXRNYXRyaXggYml0IG1hdHJpeCB0byBkZXRlY3QgYmFyY29kZXMgaW5cbiAgICAgICAgICogQHJldHVybiBMaXN0IG9mIFJlc3VsdFBvaW50IGFycmF5cyBjb250YWluaW5nIHRoZSBjb29yZGluYXRlcyBvZiBmb3VuZCBiYXJjb2Rlc1xuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGRldGVjdChtdWx0aXBsZSwgYml0TWF0cml4KSB7XG4gICAgICAgICAgICBjb25zdCBiYXJjb2RlQ29vcmRpbmF0ZXMgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgICAgIGxldCByb3cgPSAwO1xuICAgICAgICAgICAgbGV0IGNvbHVtbiA9IDA7XG4gICAgICAgICAgICBsZXQgZm91bmRCYXJjb2RlSW5Sb3cgPSBmYWxzZTtcbiAgICAgICAgICAgIHdoaWxlIChyb3cgPCBiaXRNYXRyaXguZ2V0SGVpZ2h0KCkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB2ZXJ0aWNlcyA9IERldGVjdG9yJDMuZmluZFZlcnRpY2VzKGJpdE1hdHJpeCwgcm93LCBjb2x1bW4pO1xuICAgICAgICAgICAgICAgIGlmICh2ZXJ0aWNlc1swXSA9PSBudWxsICYmIHZlcnRpY2VzWzNdID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFmb3VuZEJhcmNvZGVJblJvdykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2UgZGlkbid0IGZpbmQgYW55IGJhcmNvZGUgc28gdGhhdCdzIHRoZSBlbmQgb2Ygc2VhcmNoaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyB3ZSBkaWRuJ3QgZmluZCBhIGJhcmNvZGUgc3RhcnRpbmcgYXQgdGhlIGdpdmVuIGNvbHVtbiBhbmQgcm93LiBUcnkgYWdhaW4gZnJvbSB0aGUgZmlyc3QgY29sdW1uIGFuZCBzbGlnaHRseVxuICAgICAgICAgICAgICAgICAgICAvLyBiZWxvdyB0aGUgbG93ZXN0IGJhcmNvZGUgd2UgZm91bmQgc28gZmFyLlxuICAgICAgICAgICAgICAgICAgICBmb3VuZEJhcmNvZGVJblJvdyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW4gPSAwO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGJhcmNvZGVDb29yZGluYXRlIG9mIGJhcmNvZGVDb29yZGluYXRlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJhcmNvZGVDb29yZGluYXRlWzFdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cgPSBNYXRoLnRydW5jKE1hdGgubWF4KHJvdywgYmFyY29kZUNvb3JkaW5hdGVbMV0uZ2V0WSgpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYmFyY29kZUNvb3JkaW5hdGVbM10gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdyA9IE1hdGgubWF4KHJvdywgTWF0aC50cnVuYyhiYXJjb2RlQ29vcmRpbmF0ZVszXS5nZXRZKCkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByb3cgKz0gRGV0ZWN0b3IkMy5ST1dfU1RFUDtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvdW5kQmFyY29kZUluUm93ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBiYXJjb2RlQ29vcmRpbmF0ZXMucHVzaCh2ZXJ0aWNlcyk7XG4gICAgICAgICAgICAgICAgaWYgKCFtdWx0aXBsZSkge1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gaWYgd2UgZGlkbid0IGZpbmQgYSByaWdodCByb3cgaW5kaWNhdG9yIGNvbHVtbiwgdGhlbiBjb250aW51ZSB0aGUgc2VhcmNoIGZvciB0aGUgbmV4dCBiYXJjb2RlIGFmdGVyIHRoZVxuICAgICAgICAgICAgICAgIC8vIHN0YXJ0IHBhdHRlcm4gb2YgdGhlIGJhcmNvZGUganVzdCBmb3VuZC5cbiAgICAgICAgICAgICAgICBpZiAodmVydGljZXNbMl0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW4gPSBNYXRoLnRydW5jKHZlcnRpY2VzWzJdLmdldFgoKSk7XG4gICAgICAgICAgICAgICAgICAgIHJvdyA9IE1hdGgudHJ1bmModmVydGljZXNbMl0uZ2V0WSgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbiA9IE1hdGgudHJ1bmModmVydGljZXNbNF0uZ2V0WCgpKTtcbiAgICAgICAgICAgICAgICAgICAgcm93ID0gTWF0aC50cnVuYyh2ZXJ0aWNlc1s0XS5nZXRZKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBiYXJjb2RlQ29vcmRpbmF0ZXM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIExvY2F0ZSB0aGUgdmVydGljZXMgYW5kIHRoZSBjb2Rld29yZHMgYXJlYSBvZiBhIGJsYWNrIGJsb2IgdXNpbmcgdGhlIFN0YXJ0XG4gICAgICAgICAqIGFuZCBTdG9wIHBhdHRlcm5zIGFzIGxvY2F0b3JzLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gbWF0cml4IHRoZSBzY2FubmVkIGJhcmNvZGUgaW1hZ2UuXG4gICAgICAgICAqIEByZXR1cm4gYW4gYXJyYXkgY29udGFpbmluZyB0aGUgdmVydGljZXM6XG4gICAgICAgICAqICAgICAgICAgICB2ZXJ0aWNlc1swXSB4LCB5IHRvcCBsZWZ0IGJhcmNvZGVcbiAgICAgICAgICogICAgICAgICAgIHZlcnRpY2VzWzFdIHgsIHkgYm90dG9tIGxlZnQgYmFyY29kZVxuICAgICAgICAgKiAgICAgICAgICAgdmVydGljZXNbMl0geCwgeSB0b3AgcmlnaHQgYmFyY29kZVxuICAgICAgICAgKiAgICAgICAgICAgdmVydGljZXNbM10geCwgeSBib3R0b20gcmlnaHQgYmFyY29kZVxuICAgICAgICAgKiAgICAgICAgICAgdmVydGljZXNbNF0geCwgeSB0b3AgbGVmdCBjb2Rld29yZCBhcmVhXG4gICAgICAgICAqICAgICAgICAgICB2ZXJ0aWNlc1s1XSB4LCB5IGJvdHRvbSBsZWZ0IGNvZGV3b3JkIGFyZWFcbiAgICAgICAgICogICAgICAgICAgIHZlcnRpY2VzWzZdIHgsIHkgdG9wIHJpZ2h0IGNvZGV3b3JkIGFyZWFcbiAgICAgICAgICogICAgICAgICAgIHZlcnRpY2VzWzddIHgsIHkgYm90dG9tIHJpZ2h0IGNvZGV3b3JkIGFyZWFcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBmaW5kVmVydGljZXMobWF0cml4LCBzdGFydFJvdywgc3RhcnRDb2x1bW4pIHtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IG1hdHJpeC5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gbWF0cml4LmdldFdpZHRoKCk7XG4gICAgICAgICAgICAvLyBjb25zdCByZXN1bHQgPSBuZXcgUmVzdWx0UG9pbnRbOF07XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgQXJyYXkoOCk7XG4gICAgICAgICAgICBEZXRlY3RvciQzLmNvcHlUb1Jlc3VsdChyZXN1bHQsIERldGVjdG9yJDMuZmluZFJvd3NXaXRoUGF0dGVybihtYXRyaXgsIGhlaWdodCwgd2lkdGgsIHN0YXJ0Um93LCBzdGFydENvbHVtbiwgRGV0ZWN0b3IkMy5TVEFSVF9QQVRURVJOKSwgRGV0ZWN0b3IkMy5JTkRFWEVTX1NUQVJUX1BBVFRFUk4pO1xuICAgICAgICAgICAgaWYgKHJlc3VsdFs0XSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgc3RhcnRDb2x1bW4gPSBNYXRoLnRydW5jKHJlc3VsdFs0XS5nZXRYKCkpO1xuICAgICAgICAgICAgICAgIHN0YXJ0Um93ID0gTWF0aC50cnVuYyhyZXN1bHRbNF0uZ2V0WSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIERldGVjdG9yJDMuY29weVRvUmVzdWx0KHJlc3VsdCwgRGV0ZWN0b3IkMy5maW5kUm93c1dpdGhQYXR0ZXJuKG1hdHJpeCwgaGVpZ2h0LCB3aWR0aCwgc3RhcnRSb3csIHN0YXJ0Q29sdW1uLCBEZXRlY3RvciQzLlNUT1BfUEFUVEVSTiksIERldGVjdG9yJDMuSU5ERVhFU19TVE9QX1BBVFRFUk4pO1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgY29weVRvUmVzdWx0KHJlc3VsdCwgdG1wUmVzdWx0LCBkZXN0aW5hdGlvbkluZGV4ZXMpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGVzdGluYXRpb25JbmRleGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0W2Rlc3RpbmF0aW9uSW5kZXhlc1tpXV0gPSB0bXBSZXN1bHRbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGZpbmRSb3dzV2l0aFBhdHRlcm4obWF0cml4LCBoZWlnaHQsIHdpZHRoLCBzdGFydFJvdywgc3RhcnRDb2x1bW4sIHBhdHRlcm4pIHtcbiAgICAgICAgICAgIC8vIGNvbnN0IHJlc3VsdCA9IG5ldyBSZXN1bHRQb2ludFs0XTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBBcnJheSg0KTtcbiAgICAgICAgICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3QgY291bnRlcnMgPSBuZXcgSW50MzJBcnJheShwYXR0ZXJuLmxlbmd0aCk7XG4gICAgICAgICAgICBmb3IgKDsgc3RhcnRSb3cgPCBoZWlnaHQ7IHN0YXJ0Um93ICs9IERldGVjdG9yJDMuUk9XX1NURVApIHtcbiAgICAgICAgICAgICAgICBsZXQgbG9jID0gRGV0ZWN0b3IkMy5maW5kR3VhcmRQYXR0ZXJuKG1hdHJpeCwgc3RhcnRDb2x1bW4sIHN0YXJ0Um93LCB3aWR0aCwgZmFsc2UsIHBhdHRlcm4sIGNvdW50ZXJzKTtcbiAgICAgICAgICAgICAgICBpZiAobG9jICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHN0YXJ0Um93ID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcHJldmlvdXNSb3dMb2MgPSBEZXRlY3RvciQzLmZpbmRHdWFyZFBhdHRlcm4obWF0cml4LCBzdGFydENvbHVtbiwgLS1zdGFydFJvdywgd2lkdGgsIGZhbHNlLCBwYXR0ZXJuLCBjb3VudGVycyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNSb3dMb2MgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvYyA9IHByZXZpb3VzUm93TG9jO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRSb3crKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXN1bHRbMF0gPSBuZXcgUmVzdWx0UG9pbnQobG9jWzBdLCBzdGFydFJvdyk7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFsxXSA9IG5ldyBSZXN1bHRQb2ludChsb2NbMV0sIHN0YXJ0Um93KTtcbiAgICAgICAgICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc3RvcFJvdyA9IHN0YXJ0Um93ICsgMTtcbiAgICAgICAgICAgIC8vIExhc3Qgcm93IG9mIHRoZSBjdXJyZW50IHN5bWJvbCB0aGF0IGNvbnRhaW5zIHBhdHRlcm5cbiAgICAgICAgICAgIGlmIChmb3VuZCkge1xuICAgICAgICAgICAgICAgIGxldCBza2lwcGVkUm93Q291bnQgPSAwO1xuICAgICAgICAgICAgICAgIGxldCBwcmV2aW91c1Jvd0xvYyA9IEludDMyQXJyYXkuZnJvbShbTWF0aC50cnVuYyhyZXN1bHRbMF0uZ2V0WCgpKSwgTWF0aC50cnVuYyhyZXN1bHRbMV0uZ2V0WCgpKV0pO1xuICAgICAgICAgICAgICAgIGZvciAoOyBzdG9wUm93IDwgaGVpZ2h0OyBzdG9wUm93KyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbG9jID0gRGV0ZWN0b3IkMy5maW5kR3VhcmRQYXR0ZXJuKG1hdHJpeCwgcHJldmlvdXNSb3dMb2NbMF0sIHN0b3BSb3csIHdpZHRoLCBmYWxzZSwgcGF0dGVybiwgY291bnRlcnMpO1xuICAgICAgICAgICAgICAgICAgICAvLyBhIGZvdW5kIHBhdHRlcm4gaXMgb25seSBjb25zaWRlcmVkIHRvIGJlbG9uZyB0byB0aGUgc2FtZSBiYXJjb2RlIGlmIHRoZSBzdGFydCBhbmQgZW5kIHBvc2l0aW9uc1xuICAgICAgICAgICAgICAgICAgICAvLyBkb24ndCBkaWZmZXIgdG9vIG11Y2guIFBhdHRlcm4gZHJpZnQgc2hvdWxkIGJlIG5vdCBiaWdnZXIgdGhhbiB0d28gZm9yIGNvbnNlY3V0aXZlIHJvd3MuIFdpdGhcbiAgICAgICAgICAgICAgICAgICAgLy8gYSBoaWdoZXIgbnVtYmVyIG9mIHNraXBwZWQgcm93cyBkcmlmdCBjb3VsZCBiZSBsYXJnZXIuIFRvIGtlZXAgaXQgc2ltcGxlIGZvciBub3csIHdlIGFsbG93IGEgc2xpZ2h0bHlcbiAgICAgICAgICAgICAgICAgICAgLy8gbGFyZ2VyIGRyaWZ0IGFuZCBkb24ndCBjaGVjayBmb3Igc2tpcHBlZCByb3dzLlxuICAgICAgICAgICAgICAgICAgICBpZiAobG9jICE9IG51bGwgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIE1hdGguYWJzKHByZXZpb3VzUm93TG9jWzBdIC0gbG9jWzBdKSA8IERldGVjdG9yJDMuTUFYX1BBVFRFUk5fRFJJRlQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIE1hdGguYWJzKHByZXZpb3VzUm93TG9jWzFdIC0gbG9jWzFdKSA8IERldGVjdG9yJDMuTUFYX1BBVFRFUk5fRFJJRlQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzUm93TG9jID0gbG9jO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2tpcHBlZFJvd0NvdW50ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChza2lwcGVkUm93Q291bnQgPiBEZXRlY3RvciQzLlNLSVBQRURfUk9XX0NPVU5UX01BWCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2tpcHBlZFJvd0NvdW50Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3RvcFJvdyAtPSBza2lwcGVkUm93Q291bnQgKyAxO1xuICAgICAgICAgICAgICAgIHJlc3VsdFsyXSA9IG5ldyBSZXN1bHRQb2ludChwcmV2aW91c1Jvd0xvY1swXSwgc3RvcFJvdyk7XG4gICAgICAgICAgICAgICAgcmVzdWx0WzNdID0gbmV3IFJlc3VsdFBvaW50KHByZXZpb3VzUm93TG9jWzFdLCBzdG9wUm93KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzdG9wUm93IC0gc3RhcnRSb3cgPCBEZXRlY3RvciQzLkJBUkNPREVfTUlOX0hFSUdIVCkge1xuICAgICAgICAgICAgICAgIEFycmF5cy5maWxsKHJlc3VsdCwgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gbWF0cml4IHJvdyBvZiBibGFjay93aGl0ZSB2YWx1ZXMgdG8gc2VhcmNoXG4gICAgICAgICAqIEBwYXJhbSBjb2x1bW4geCBwb3NpdGlvbiB0byBzdGFydCBzZWFyY2hcbiAgICAgICAgICogQHBhcmFtIHJvdyB5IHBvc2l0aW9uIHRvIHN0YXJ0IHNlYXJjaFxuICAgICAgICAgKiBAcGFyYW0gd2lkdGggdGhlIG51bWJlciBvZiBwaXhlbHMgdG8gc2VhcmNoIG9uIHRoaXMgcm93XG4gICAgICAgICAqIEBwYXJhbSBwYXR0ZXJuIHBhdHRlcm4gb2YgY291bnRzIG9mIG51bWJlciBvZiBibGFjayBhbmQgd2hpdGUgcGl4ZWxzIHRoYXQgYXJlXG4gICAgICAgICAqICAgICAgICAgICAgICAgICBiZWluZyBzZWFyY2hlZCBmb3IgYXMgYSBwYXR0ZXJuXG4gICAgICAgICAqIEBwYXJhbSBjb3VudGVycyBhcnJheSBvZiBjb3VudGVycywgYXMgbG9uZyBhcyBwYXR0ZXJuLCB0byByZS11c2VcbiAgICAgICAgICogQHJldHVybiBzdGFydC9lbmQgaG9yaXpvbnRhbCBvZmZzZXQgb2YgZ3VhcmQgcGF0dGVybiwgYXMgYW4gYXJyYXkgb2YgdHdvIGludHMuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZmluZEd1YXJkUGF0dGVybihtYXRyaXgsIGNvbHVtbiwgcm93LCB3aWR0aCwgd2hpdGVGaXJzdCwgcGF0dGVybiwgY291bnRlcnMpIHtcbiAgICAgICAgICAgIEFycmF5cy5maWxsV2l0aGluKGNvdW50ZXJzLCAwLCBjb3VudGVycy5sZW5ndGgsIDApO1xuICAgICAgICAgICAgbGV0IHBhdHRlcm5TdGFydCA9IGNvbHVtbjtcbiAgICAgICAgICAgIGxldCBwaXhlbERyaWZ0ID0gMDtcbiAgICAgICAgICAgIC8vIGlmIHRoZXJlIGFyZSBibGFjayBwaXhlbHMgbGVmdCBvZiB0aGUgY3VycmVudCBwaXhlbCBzaGlmdCB0byB0aGUgbGVmdCwgYnV0IG9ubHkgZm9yIE1BWF9QSVhFTF9EUklGVCBwaXhlbHNcbiAgICAgICAgICAgIHdoaWxlIChtYXRyaXguZ2V0KHBhdHRlcm5TdGFydCwgcm93KSAmJiBwYXR0ZXJuU3RhcnQgPiAwICYmIHBpeGVsRHJpZnQrKyA8IERldGVjdG9yJDMuTUFYX1BJWEVMX0RSSUZUKSB7XG4gICAgICAgICAgICAgICAgcGF0dGVyblN0YXJ0LS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgeCA9IHBhdHRlcm5TdGFydDtcbiAgICAgICAgICAgIGxldCBjb3VudGVyUG9zaXRpb24gPSAwO1xuICAgICAgICAgICAgbGV0IHBhdHRlcm5MZW5ndGggPSBwYXR0ZXJuLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAobGV0IGlzV2hpdGUgPSB3aGl0ZUZpcnN0OyB4IDwgd2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgIGxldCBwaXhlbCA9IG1hdHJpeC5nZXQoeCwgcm93KTtcbiAgICAgICAgICAgICAgICBpZiAocGl4ZWwgIT09IGlzV2hpdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbY291bnRlclBvc2l0aW9uXSsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvdW50ZXJQb3NpdGlvbiA9PT0gcGF0dGVybkxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChEZXRlY3RvciQzLnBhdHRlcm5NYXRjaFZhcmlhbmNlKGNvdW50ZXJzLCBwYXR0ZXJuLCBEZXRlY3RvciQzLk1BWF9JTkRJVklEVUFMX1ZBUklBTkNFKSA8IERldGVjdG9yJDMuTUFYX0FWR19WQVJJQU5DRSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgSW50MzJBcnJheShbcGF0dGVyblN0YXJ0LCB4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuU3RhcnQgKz0gY291bnRlcnNbMF0gKyBjb3VudGVyc1sxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkoY291bnRlcnMsIDIsIGNvdW50ZXJzLCAwLCBjb3VudGVyUG9zaXRpb24gLSAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbiAtIDFdID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbl0gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlclBvc2l0aW9uLS07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyUG9zaXRpb24rKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb25dID0gMTtcbiAgICAgICAgICAgICAgICAgICAgaXNXaGl0ZSA9ICFpc1doaXRlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjb3VudGVyUG9zaXRpb24gPT09IHBhdHRlcm5MZW5ndGggLSAxICYmXG4gICAgICAgICAgICAgICAgRGV0ZWN0b3IkMy5wYXR0ZXJuTWF0Y2hWYXJpYW5jZShjb3VudGVycywgcGF0dGVybiwgRGV0ZWN0b3IkMy5NQVhfSU5ESVZJRFVBTF9WQVJJQU5DRSkgPCBEZXRlY3RvciQzLk1BWF9BVkdfVkFSSUFOQ0UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEludDMyQXJyYXkoW3BhdHRlcm5TdGFydCwgeCAtIDFdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZXRlcm1pbmVzIGhvdyBjbG9zZWx5IGEgc2V0IG9mIG9ic2VydmVkIGNvdW50cyBvZiBydW5zIG9mIGJsYWNrL3doaXRlXG4gICAgICAgICAqIHZhbHVlcyBtYXRjaGVzIGEgZ2l2ZW4gdGFyZ2V0IHBhdHRlcm4uIFRoaXMgaXMgcmVwb3J0ZWQgYXMgdGhlIHJhdGlvIG9mXG4gICAgICAgICAqIHRoZSB0b3RhbCB2YXJpYW5jZSBmcm9tIHRoZSBleHBlY3RlZCBwYXR0ZXJuIHByb3BvcnRpb25zIGFjcm9zcyBhbGxcbiAgICAgICAgICogcGF0dGVybiBlbGVtZW50cywgdG8gdGhlIGxlbmd0aCBvZiB0aGUgcGF0dGVybi5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGNvdW50ZXJzIG9ic2VydmVkIGNvdW50ZXJzXG4gICAgICAgICAqIEBwYXJhbSBwYXR0ZXJuIGV4cGVjdGVkIHBhdHRlcm5cbiAgICAgICAgICogQHBhcmFtIG1heEluZGl2aWR1YWxWYXJpYW5jZSBUaGUgbW9zdCBhbnkgY291bnRlciBjYW4gZGlmZmVyIGJlZm9yZSB3ZSBnaXZlIHVwXG4gICAgICAgICAqIEByZXR1cm4gcmF0aW8gb2YgdG90YWwgdmFyaWFuY2UgYmV0d2VlbiBjb3VudGVycyBhbmQgcGF0dGVybiBjb21wYXJlZCB0byB0b3RhbCBwYXR0ZXJuIHNpemVcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBwYXR0ZXJuTWF0Y2hWYXJpYW5jZShjb3VudGVycywgcGF0dGVybiwgbWF4SW5kaXZpZHVhbFZhcmlhbmNlKSB7XG4gICAgICAgICAgICBsZXQgbnVtQ291bnRlcnMgPSBjb3VudGVycy5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgdG90YWwgPSAwO1xuICAgICAgICAgICAgbGV0IHBhdHRlcm5MZW5ndGggPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1Db3VudGVyczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdG90YWwgKz0gY291bnRlcnNbaV07XG4gICAgICAgICAgICAgICAgcGF0dGVybkxlbmd0aCArPSBwYXR0ZXJuW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRvdGFsIDwgcGF0dGVybkxlbmd0aCkge1xuICAgICAgICAgICAgICAgIC8vIElmIHdlIGRvbid0IGV2ZW4gaGF2ZSBvbmUgcGl4ZWwgcGVyIHVuaXQgb2YgYmFyIHdpZHRoLCBhc3N1bWUgdGhpc1xuICAgICAgICAgICAgICAgIC8vIGlzIHRvbyBzbWFsbCB0byByZWxpYWJseSBtYXRjaCwgc28gZmFpbDpcbiAgICAgICAgICAgICAgICByZXR1cm4gLypGbG9hdC5QT1NJVElWRV9JTkZJTklUWSovIEluZmluaXR5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gV2UncmUgZ29pbmcgdG8gZmFrZSBmbG9hdGluZy1wb2ludCBtYXRoIGluIGludGVnZXJzLiBXZSBqdXN0IG5lZWQgdG8gdXNlIG1vcmUgYml0cy5cbiAgICAgICAgICAgIC8vIFNjYWxlIHVwIHBhdHRlcm5MZW5ndGggc28gdGhhdCBpbnRlcm1lZGlhdGUgdmFsdWVzIGJlbG93IGxpa2Ugc2NhbGVkQ291bnRlciB3aWxsIGhhdmVcbiAgICAgICAgICAgIC8vIG1vcmUgXCJzaWduaWZpY2FudCBkaWdpdHNcIi5cbiAgICAgICAgICAgIGxldCB1bml0QmFyV2lkdGggPSB0b3RhbCAvIHBhdHRlcm5MZW5ndGg7XG4gICAgICAgICAgICBtYXhJbmRpdmlkdWFsVmFyaWFuY2UgKj0gdW5pdEJhcldpZHRoO1xuICAgICAgICAgICAgbGV0IHRvdGFsVmFyaWFuY2UgPSAwLjA7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IG51bUNvdW50ZXJzOyB4KyspIHtcbiAgICAgICAgICAgICAgICBsZXQgY291bnRlciA9IGNvdW50ZXJzW3hdO1xuICAgICAgICAgICAgICAgIGxldCBzY2FsZWRQYXR0ZXJuID0gcGF0dGVyblt4XSAqIHVuaXRCYXJXaWR0aDtcbiAgICAgICAgICAgICAgICBsZXQgdmFyaWFuY2UgPSBjb3VudGVyID4gc2NhbGVkUGF0dGVybiA/IGNvdW50ZXIgLSBzY2FsZWRQYXR0ZXJuIDogc2NhbGVkUGF0dGVybiAtIGNvdW50ZXI7XG4gICAgICAgICAgICAgICAgaWYgKHZhcmlhbmNlID4gbWF4SW5kaXZpZHVhbFZhcmlhbmNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAvKkZsb2F0LlBPU0lUSVZFX0lORklOSVRZKi8gSW5maW5pdHk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRvdGFsVmFyaWFuY2UgKz0gdmFyaWFuY2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdG90YWxWYXJpYW5jZSAvIHRvdGFsO1xuICAgICAgICB9XG4gICAgfVxuICAgIERldGVjdG9yJDMuSU5ERVhFU19TVEFSVF9QQVRURVJOID0gSW50MzJBcnJheS5mcm9tKFswLCA0LCAxLCA1XSk7XG4gICAgRGV0ZWN0b3IkMy5JTkRFWEVTX1NUT1BfUEFUVEVSTiA9IEludDMyQXJyYXkuZnJvbShbNiwgMiwgNywgM10pO1xuICAgIERldGVjdG9yJDMuTUFYX0FWR19WQVJJQU5DRSA9IDAuNDI7XG4gICAgRGV0ZWN0b3IkMy5NQVhfSU5ESVZJRFVBTF9WQVJJQU5DRSA9IDAuODtcbiAgICAvLyBCIFMgQiBTIEIgUyBCIFMgQmFyL1NwYWNlIHBhdHRlcm5cbiAgICAvLyAxMTExMTExMSAwIDEgMCAxIDAgMSAwMDBcbiAgICBEZXRlY3RvciQzLlNUQVJUX1BBVFRFUk4gPSBJbnQzMkFycmF5LmZyb20oWzgsIDEsIDEsIDEsIDEsIDEsIDEsIDNdKTtcbiAgICAvLyAxMTExMTExIDAgMSAwMDAgMSAwIDEgMDAgMVxuICAgIERldGVjdG9yJDMuU1RPUF9QQVRURVJOID0gSW50MzJBcnJheS5mcm9tKFs3LCAxLCAxLCAzLCAxLCAxLCAxLCAyLCAxXSk7XG4gICAgRGV0ZWN0b3IkMy5NQVhfUElYRUxfRFJJRlQgPSAzO1xuICAgIERldGVjdG9yJDMuTUFYX1BBVFRFUk5fRFJJRlQgPSA1O1xuICAgIC8vIGlmIHdlIHNldCB0aGUgdmFsdWUgdG9vIGxvdywgdGhlbiB3ZSBkb24ndCBkZXRlY3QgdGhlIGNvcnJlY3QgaGVpZ2h0IG9mIHRoZSBiYXIgaWYgdGhlIHN0YXJ0IHBhdHRlcm5zIGFyZSBkYW1hZ2VkLlxuICAgIC8vIGlmIHdlIHNldCB0aGUgdmFsdWUgdG9vIGhpZ2gsIHRoZW4gd2UgbWlnaHQgZGV0ZWN0IHRoZSBzdGFydCBwYXR0ZXJuIGZyb20gYSBuZWlnaGJvciBiYXJjb2RlLlxuICAgIERldGVjdG9yJDMuU0tJUFBFRF9ST1dfQ09VTlRfTUFYID0gMjU7XG4gICAgLy8gQSBQREY0NzEgYmFyY29kZSBzaG91bGQgaGF2ZSBhdCBsZWFzdCAzIHJvd3MsIHdpdGggZWFjaCByb3cgYmVpbmcgPj0gMyB0aW1lcyB0aGUgbW9kdWxlIHdpZHRoLiBUaGVyZWZvcmUgaXQgc2hvdWxkIGJlIGF0IGxlYXN0XG4gICAgLy8gOSBwaXhlbHMgdGFsbC4gVG8gYmUgY29uc2VydmF0aXZlLCB3ZSB1c2UgYWJvdXQgaGFsZiB0aGUgc2l6ZSB0byBlbnN1cmUgd2UgZG9uJ3QgbWlzcyBpdC5cbiAgICBEZXRlY3RvciQzLlJPV19TVEVQID0gNTtcbiAgICBEZXRlY3RvciQzLkJBUkNPREVfTUlOX0hFSUdIVCA9IDEwO1xuXG4gICAgLypcbiAgICAqIENvcHlyaWdodCAyMDEyIFpYaW5nIGF1dGhvcnNcbiAgICAqXG4gICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgKlxuICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAqXG4gICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICovXG4gICAgLyoqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKiBAc2VlIGNvbS5nb29nbGUuenhpbmcuY29tbW9uLnJlZWRzb2xvbW9uLkdlbmVyaWNHRlBvbHlcbiAgICAgKi9cbiAgICAvKmZpbmFsKi8gY2xhc3MgTW9kdWx1c1BvbHkge1xuICAgICAgICBjb25zdHJ1Y3RvcihmaWVsZCwgY29lZmZpY2llbnRzKSB7XG4gICAgICAgICAgICBpZiAoY29lZmZpY2llbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZmllbGQgPSBmaWVsZDtcbiAgICAgICAgICAgIGxldCBjb2VmZmljaWVudHNMZW5ndGggPSAvKmludCovIGNvZWZmaWNpZW50cy5sZW5ndGg7XG4gICAgICAgICAgICBpZiAoY29lZmZpY2llbnRzTGVuZ3RoID4gMSAmJiBjb2VmZmljaWVudHNbMF0gPT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyBMZWFkaW5nIHRlcm0gbXVzdCBiZSBub24temVybyBmb3IgYW55dGhpbmcgZXhjZXB0IHRoZSBjb25zdGFudCBwb2x5bm9taWFsIFwiMFwiXG4gICAgICAgICAgICAgICAgbGV0IGZpcnN0Tm9uWmVybyA9IC8qaW50Ki8gMTtcbiAgICAgICAgICAgICAgICB3aGlsZSAoZmlyc3ROb25aZXJvIDwgY29lZmZpY2llbnRzTGVuZ3RoICYmIGNvZWZmaWNpZW50c1tmaXJzdE5vblplcm9dID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpcnN0Tm9uWmVybysrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZmlyc3ROb25aZXJvID09PSBjb2VmZmljaWVudHNMZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb2VmZmljaWVudHMgPSBuZXcgSW50MzJBcnJheShbMF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb2VmZmljaWVudHMgPSBuZXcgSW50MzJBcnJheShjb2VmZmljaWVudHNMZW5ndGggLSBmaXJzdE5vblplcm8pO1xuICAgICAgICAgICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KGNvZWZmaWNpZW50cywgZmlyc3ROb25aZXJvLCB0aGlzLmNvZWZmaWNpZW50cywgMCwgdGhpcy5jb2VmZmljaWVudHMubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvZWZmaWNpZW50cyA9IGNvZWZmaWNpZW50cztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBnZXRDb2VmZmljaWVudHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2VmZmljaWVudHM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gZGVncmVlIG9mIHRoaXMgcG9seW5vbWlhbFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0RGVncmVlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29lZmZpY2llbnRzLmxlbmd0aCAtIDE7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gdHJ1ZSBpZmYgdGhpcyBwb2x5bm9taWFsIGlzIHRoZSBtb25vbWlhbCBcIjBcIlxuICAgICAgICAgKi9cbiAgICAgICAgaXNaZXJvKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29lZmZpY2llbnRzWzBdID09PSAwO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIGNvZWZmaWNpZW50IG9mIHheZGVncmVlIHRlcm0gaW4gdGhpcyBwb2x5bm9taWFsXG4gICAgICAgICAqL1xuICAgICAgICBnZXRDb2VmZmljaWVudChkZWdyZWUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvZWZmaWNpZW50c1t0aGlzLmNvZWZmaWNpZW50cy5sZW5ndGggLSAxIC0gZGVncmVlXTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBldmFsdWF0aW9uIG9mIHRoaXMgcG9seW5vbWlhbCBhdCBhIGdpdmVuIHBvaW50XG4gICAgICAgICAqL1xuICAgICAgICBldmFsdWF0ZUF0KGEpIHtcbiAgICAgICAgICAgIGlmIChhID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gSnVzdCByZXR1cm4gdGhlIHheMCBjb2VmZmljaWVudFxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldENvZWZmaWNpZW50KDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGEgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAvLyBKdXN0IHRoZSBzdW0gb2YgdGhlIGNvZWZmaWNpZW50c1xuICAgICAgICAgICAgICAgIGxldCBzdW0gPSAvKmludCovIDA7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgY29lZmZpY2llbnQgLyppbnQqLyBvZiB0aGlzLmNvZWZmaWNpZW50cykge1xuICAgICAgICAgICAgICAgICAgICBzdW0gPSB0aGlzLmZpZWxkLmFkZChzdW0sIGNvZWZmaWNpZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN1bTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCByZXN1bHQgPSAvKmludCovIHRoaXMuY29lZmZpY2llbnRzWzBdO1xuICAgICAgICAgICAgbGV0IHNpemUgPSAvKmludCovIHRoaXMuY29lZmZpY2llbnRzLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDE7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLmZpZWxkLmFkZCh0aGlzLmZpZWxkLm11bHRpcGx5KGEsIHJlc3VsdCksIHRoaXMuY29lZmZpY2llbnRzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgYWRkKG90aGVyKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZmllbGQuZXF1YWxzKG90aGVyLmZpZWxkKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ01vZHVsdXNQb2x5cyBkbyBub3QgaGF2ZSBzYW1lIE1vZHVsdXNHRiBmaWVsZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaXNaZXJvKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gb3RoZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob3RoZXIuaXNaZXJvKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBzbWFsbGVyQ29lZmZpY2llbnRzID0gdGhpcy5jb2VmZmljaWVudHM7XG4gICAgICAgICAgICBsZXQgbGFyZ2VyQ29lZmZpY2llbnRzID0gb3RoZXIuY29lZmZpY2llbnRzO1xuICAgICAgICAgICAgaWYgKHNtYWxsZXJDb2VmZmljaWVudHMubGVuZ3RoID4gbGFyZ2VyQ29lZmZpY2llbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGxldCB0ZW1wID0gc21hbGxlckNvZWZmaWNpZW50cztcbiAgICAgICAgICAgICAgICBzbWFsbGVyQ29lZmZpY2llbnRzID0gbGFyZ2VyQ29lZmZpY2llbnRzO1xuICAgICAgICAgICAgICAgIGxhcmdlckNvZWZmaWNpZW50cyA9IHRlbXA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc3VtRGlmZiA9IG5ldyBJbnQzMkFycmF5KGxhcmdlckNvZWZmaWNpZW50cy5sZW5ndGgpO1xuICAgICAgICAgICAgbGV0IGxlbmd0aERpZmYgPSAvKmludCovIGxhcmdlckNvZWZmaWNpZW50cy5sZW5ndGggLSBzbWFsbGVyQ29lZmZpY2llbnRzLmxlbmd0aDtcbiAgICAgICAgICAgIC8vIENvcHkgaGlnaC1vcmRlciB0ZXJtcyBvbmx5IGZvdW5kIGluIGhpZ2hlci1kZWdyZWUgcG9seW5vbWlhbCdzIGNvZWZmaWNpZW50c1xuICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weShsYXJnZXJDb2VmZmljaWVudHMsIDAsIHN1bURpZmYsIDAsIGxlbmd0aERpZmYpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gbGVuZ3RoRGlmZjsgaSA8IGxhcmdlckNvZWZmaWNpZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHN1bURpZmZbaV0gPSB0aGlzLmZpZWxkLmFkZChzbWFsbGVyQ29lZmZpY2llbnRzW2kgLSBsZW5ndGhEaWZmXSwgbGFyZ2VyQ29lZmZpY2llbnRzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgTW9kdWx1c1BvbHkodGhpcy5maWVsZCwgc3VtRGlmZik7XG4gICAgICAgIH1cbiAgICAgICAgc3VidHJhY3Qob3RoZXIpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5maWVsZC5lcXVhbHMob3RoZXIuZmllbGQpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignTW9kdWx1c1BvbHlzIGRvIG5vdCBoYXZlIHNhbWUgTW9kdWx1c0dGIGZpZWxkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob3RoZXIuaXNaZXJvKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmFkZChvdGhlci5uZWdhdGl2ZSgpKTtcbiAgICAgICAgfVxuICAgICAgICBtdWx0aXBseShvdGhlcikge1xuICAgICAgICAgICAgaWYgKG90aGVyIGluc3RhbmNlb2YgTW9kdWx1c1BvbHkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5tdWx0aXBseU90aGVyKG90aGVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLm11bHRpcGx5U2NhbGFyKG90aGVyKTtcbiAgICAgICAgfVxuICAgICAgICBtdWx0aXBseU90aGVyKG90aGVyKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZmllbGQuZXF1YWxzKG90aGVyLmZpZWxkKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ01vZHVsdXNQb2x5cyBkbyBub3QgaGF2ZSBzYW1lIE1vZHVsdXNHRiBmaWVsZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaXNaZXJvKCkgfHwgb3RoZXIuaXNaZXJvKCkpIHtcbiAgICAgICAgICAgICAgICAvLyByZXR1cm4gdGhpcy5maWVsZC5nZXRaZXJvKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBNb2R1bHVzUG9seSh0aGlzLmZpZWxkLCBuZXcgSW50MzJBcnJheShbMF0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBhQ29lZmZpY2llbnRzID0gdGhpcy5jb2VmZmljaWVudHM7XG4gICAgICAgICAgICBsZXQgYUxlbmd0aCA9IC8qaW50Ki8gYUNvZWZmaWNpZW50cy5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgYkNvZWZmaWNpZW50cyA9IG90aGVyLmNvZWZmaWNpZW50cztcbiAgICAgICAgICAgIGxldCBiTGVuZ3RoID0gLyppbnQqLyBiQ29lZmZpY2llbnRzLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBwcm9kdWN0ID0gbmV3IEludDMyQXJyYXkoYUxlbmd0aCArIGJMZW5ndGggLSAxKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCBhTGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgYUNvZWZmID0gLyppbnQqLyBhQ29lZmZpY2llbnRzW2ldO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogLyppbnQqLyA9IDA7IGogPCBiTGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvZHVjdFtpICsgal0gPSB0aGlzLmZpZWxkLmFkZChwcm9kdWN0W2kgKyBqXSwgdGhpcy5maWVsZC5tdWx0aXBseShhQ29lZmYsIGJDb2VmZmljaWVudHNbal0pKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IE1vZHVsdXNQb2x5KHRoaXMuZmllbGQsIHByb2R1Y3QpO1xuICAgICAgICB9XG4gICAgICAgIG5lZ2F0aXZlKCkge1xuICAgICAgICAgICAgbGV0IHNpemUgPSAvKmludCovIHRoaXMuY29lZmZpY2llbnRzLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBuZWdhdGl2ZUNvZWZmaWNpZW50cyA9IG5ldyBJbnQzMkFycmF5KHNpemUpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMDsgaSA8IHNpemU7IGkrKykge1xuICAgICAgICAgICAgICAgIG5lZ2F0aXZlQ29lZmZpY2llbnRzW2ldID0gdGhpcy5maWVsZC5zdWJ0cmFjdCgwLCB0aGlzLmNvZWZmaWNpZW50c1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IE1vZHVsdXNQb2x5KHRoaXMuZmllbGQsIG5lZ2F0aXZlQ29lZmZpY2llbnRzKTtcbiAgICAgICAgfVxuICAgICAgICBtdWx0aXBseVNjYWxhcihzY2FsYXIpIHtcbiAgICAgICAgICAgIGlmIChzY2FsYXIgPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IE1vZHVsdXNQb2x5KHRoaXMuZmllbGQsIG5ldyBJbnQzMkFycmF5KFswXSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHNjYWxhciA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHNpemUgPSAvKmludCovIHRoaXMuY29lZmZpY2llbnRzLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBwcm9kdWN0ID0gbmV3IEludDMyQXJyYXkoc2l6ZSk7XG4gICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAwOyBpIDwgc2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcHJvZHVjdFtpXSA9IHRoaXMuZmllbGQubXVsdGlwbHkodGhpcy5jb2VmZmljaWVudHNbaV0sIHNjYWxhcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IE1vZHVsdXNQb2x5KHRoaXMuZmllbGQsIHByb2R1Y3QpO1xuICAgICAgICB9XG4gICAgICAgIG11bHRpcGx5QnlNb25vbWlhbChkZWdyZWUsIGNvZWZmaWNpZW50KSB7XG4gICAgICAgICAgICBpZiAoZGVncmVlIDwgMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjb2VmZmljaWVudCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgTW9kdWx1c1BvbHkodGhpcy5maWVsZCwgbmV3IEludDMyQXJyYXkoWzBdKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc2l6ZSA9IC8qaW50Ki8gdGhpcy5jb2VmZmljaWVudHMubGVuZ3RoO1xuICAgICAgICAgICAgbGV0IHByb2R1Y3QgPSBuZXcgSW50MzJBcnJheShzaXplICsgZGVncmVlKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgICAgICAgICAgICBwcm9kdWN0W2ldID0gdGhpcy5maWVsZC5tdWx0aXBseSh0aGlzLmNvZWZmaWNpZW50c1tpXSwgY29lZmZpY2llbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBNb2R1bHVzUG9seSh0aGlzLmZpZWxkLCBwcm9kdWN0KTtcbiAgICAgICAgfVxuICAgICAgICAvKlxuICAgICAgICBNb2R1bHVzUG9seVtdIGRpdmlkZShvdGhlcjogTW9kdWx1c1BvbHkpIHtcbiAgICAgICAgICBpZiAoIWZpZWxkLmVxdWFscyhvdGhlci5maWVsZCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oXCJNb2R1bHVzUG9seXMgZG8gbm90IGhhdmUgc2FtZSBNb2R1bHVzR0YgZmllbGRcIik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChvdGhlci5pc1plcm8oKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbihcIkRpdmlkZSBieSAwXCIpO1xuICAgICAgICAgIH1cbiAgICAgIFxuICAgICAgICAgIGxldCBxdW90aWVudDogTW9kdWx1c1BvbHkgPSBmaWVsZC5nZXRaZXJvKCk7XG4gICAgICAgICAgbGV0IHJlbWFpbmRlcjogTW9kdWx1c1BvbHkgPSB0aGlzO1xuICAgICAgXG4gICAgICAgICAgbGV0IGRlbm9taW5hdG9yTGVhZGluZ1Rlcm06IC8qaW50LyBudW1iZXIgPSBvdGhlci5nZXRDb2VmZmljaWVudChvdGhlci5nZXREZWdyZWUoKSk7XG4gICAgICAgICAgbGV0IGludmVyc2VEZW5vbWluYXRvckxlYWRpbmdUZXJtOiAvKmludC8gbnVtYmVyID0gZmllbGQuaW52ZXJzZShkZW5vbWluYXRvckxlYWRpbmdUZXJtKTtcbiAgICAgIFxuICAgICAgICAgIHdoaWxlIChyZW1haW5kZXIuZ2V0RGVncmVlKCkgPj0gb3RoZXIuZ2V0RGVncmVlKCkgJiYgIXJlbWFpbmRlci5pc1plcm8oKSkge1xuICAgICAgICAgICAgbGV0IGRlZ3JlZURpZmZlcmVuY2U6IC8qaW50LyBudW1iZXIgPSByZW1haW5kZXIuZ2V0RGVncmVlKCkgLSBvdGhlci5nZXREZWdyZWUoKTtcbiAgICAgICAgICAgIGxldCBzY2FsZTogLyppbnQvIG51bWJlciA9IGZpZWxkLm11bHRpcGx5KHJlbWFpbmRlci5nZXRDb2VmZmljaWVudChyZW1haW5kZXIuZ2V0RGVncmVlKCkpLCBpbnZlcnNlRGVub21pbmF0b3JMZWFkaW5nVGVybSk7XG4gICAgICAgICAgICBsZXQgdGVybTogTW9kdWx1c1BvbHkgPSBvdGhlci5tdWx0aXBseUJ5TW9ub21pYWwoZGVncmVlRGlmZmVyZW5jZSwgc2NhbGUpO1xuICAgICAgICAgICAgbGV0IGl0ZXJhdGlvblF1b3RpZW50OiBNb2R1bHVzUG9seSA9IGZpZWxkLmJ1aWxkTW9ub21pYWwoZGVncmVlRGlmZmVyZW5jZSwgc2NhbGUpO1xuICAgICAgICAgICAgcXVvdGllbnQgPSBxdW90aWVudC5hZGQoaXRlcmF0aW9uUXVvdGllbnQpO1xuICAgICAgICAgICAgcmVtYWluZGVyID0gcmVtYWluZGVyLnN1YnRyYWN0KHRlcm0pO1xuICAgICAgICAgIH1cbiAgICAgIFxuICAgICAgICAgIHJldHVybiBuZXcgTW9kdWx1c1BvbHlbXSB7IHF1b3RpZW50LCByZW1haW5kZXIgfTtcbiAgICAgICAgfVxuICAgICAgICAqL1xuICAgICAgICAvLyBAT3ZlcnJpZGVcbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gbmV3IFN0cmluZ0J1aWxkZXIoIC8qOCAqIHRoaXMuZ2V0RGVncmVlKCkqLyk7IC8vIGR5bmFtaWMgc3RyaW5nIHNpemUgaW4gSlNcbiAgICAgICAgICAgIGZvciAobGV0IGRlZ3JlZSAvKmludCovID0gdGhpcy5nZXREZWdyZWUoKTsgZGVncmVlID49IDA7IGRlZ3JlZS0tKSB7XG4gICAgICAgICAgICAgICAgbGV0IGNvZWZmaWNpZW50ID0gLyppbnQqLyB0aGlzLmdldENvZWZmaWNpZW50KGRlZ3JlZSk7XG4gICAgICAgICAgICAgICAgaWYgKGNvZWZmaWNpZW50ICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb2VmZmljaWVudCA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoJyAtICcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29lZmZpY2llbnQgPSAtY29lZmZpY2llbnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCgpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoJyArICcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChkZWdyZWUgPT09IDAgfHwgY29lZmZpY2llbnQgIT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoY29lZmZpY2llbnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChkZWdyZWUgIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkZWdyZWUgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCd4Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCd4XicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoZGVncmVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNsYXNzIE1vZHVsdXNCYXNlIHtcbiAgICAgICAgYWRkKGEsIGIpIHtcbiAgICAgICAgICAgIHJldHVybiAoYSArIGIpICUgdGhpcy5tb2R1bHVzO1xuICAgICAgICB9XG4gICAgICAgIHN1YnRyYWN0KGEsIGIpIHtcbiAgICAgICAgICAgIHJldHVybiAodGhpcy5tb2R1bHVzICsgYSAtIGIpICUgdGhpcy5tb2R1bHVzO1xuICAgICAgICB9XG4gICAgICAgIGV4cChhKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5leHBUYWJsZVthXTtcbiAgICAgICAgfVxuICAgICAgICBsb2coYSkge1xuICAgICAgICAgICAgaWYgKGEgPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sb2dUYWJsZVthXTtcbiAgICAgICAgfVxuICAgICAgICBpbnZlcnNlKGEpIHtcbiAgICAgICAgICAgIGlmIChhID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEFyaXRobWV0aWNFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmV4cFRhYmxlW3RoaXMubW9kdWx1cyAtIHRoaXMubG9nVGFibGVbYV0gLSAxXTtcbiAgICAgICAgfVxuICAgICAgICBtdWx0aXBseShhLCBiKSB7XG4gICAgICAgICAgICBpZiAoYSA9PT0gMCB8fCBiID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5leHBUYWJsZVsodGhpcy5sb2dUYWJsZVthXSArIHRoaXMubG9nVGFibGVbYl0pICUgKHRoaXMubW9kdWx1cyAtIDEpXTtcbiAgICAgICAgfVxuICAgICAgICBnZXRTaXplKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubW9kdWx1cztcbiAgICAgICAgfVxuICAgICAgICBlcXVhbHMobykge1xuICAgICAgICAgICAgcmV0dXJuIG8gPT09IHRoaXM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDEyIFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIDxwPkEgZmllbGQgYmFzZWQgb24gcG93ZXJzIG9mIGEgZ2VuZXJhdG9yIGludGVnZXIsIG1vZHVsbyBzb21lIG1vZHVsdXMuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKiBAc2VlIGNvbS5nb29nbGUuenhpbmcuY29tbW9uLnJlZWRzb2xvbW9uLkdlbmVyaWNHRlxuICAgICAqL1xuICAgIC8qcHVibGljIGZpbmFsKi8gY2xhc3MgTW9kdWx1c0dGIGV4dGVuZHMgTW9kdWx1c0Jhc2Uge1xuICAgICAgICAvLyBwcml2YXRlIC8qZmluYWwqLyBtb2R1bHVzOiAvKmludCovIG51bWJlcjtcbiAgICAgICAgY29uc3RydWN0b3IobW9kdWx1cywgZ2VuZXJhdG9yKSB7XG4gICAgICAgICAgICBzdXBlcigpO1xuICAgICAgICAgICAgdGhpcy5tb2R1bHVzID0gbW9kdWx1cztcbiAgICAgICAgICAgIHRoaXMuZXhwVGFibGUgPSBuZXcgSW50MzJBcnJheShtb2R1bHVzKTtcbiAgICAgICAgICAgIHRoaXMubG9nVGFibGUgPSBuZXcgSW50MzJBcnJheShtb2R1bHVzKTtcbiAgICAgICAgICAgIGxldCB4ID0gLyppbnQqLyAxO1xuICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMDsgaSA8IG1vZHVsdXM7IGkrKykge1xuICAgICAgICAgICAgICAgIHRoaXMuZXhwVGFibGVbaV0gPSB4O1xuICAgICAgICAgICAgICAgIHggPSAoeCAqIGdlbmVyYXRvcikgJSBtb2R1bHVzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMDsgaSA8IG1vZHVsdXMgLSAxOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ1RhYmxlW3RoaXMuZXhwVGFibGVbaV1dID0gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGxvZ1RhYmxlWzBdID09IDAgYnV0IHRoaXMgc2hvdWxkIG5ldmVyIGJlIHVzZWRcbiAgICAgICAgICAgIHRoaXMuemVybyA9IG5ldyBNb2R1bHVzUG9seSh0aGlzLCBuZXcgSW50MzJBcnJheShbMF0pKTtcbiAgICAgICAgICAgIHRoaXMub25lID0gbmV3IE1vZHVsdXNQb2x5KHRoaXMsIG5ldyBJbnQzMkFycmF5KFsxXSkpO1xuICAgICAgICB9XG4gICAgICAgIGdldFplcm8oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy56ZXJvO1xuICAgICAgICB9XG4gICAgICAgIGdldE9uZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm9uZTtcbiAgICAgICAgfVxuICAgICAgICBidWlsZE1vbm9taWFsKGRlZ3JlZSwgY29lZmZpY2llbnQpIHtcbiAgICAgICAgICAgIGlmIChkZWdyZWUgPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvZWZmaWNpZW50ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuemVybztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBjb2VmZmljaWVudHMgPSBuZXcgSW50MzJBcnJheShkZWdyZWUgKyAxKTtcbiAgICAgICAgICAgIGNvZWZmaWNpZW50c1swXSA9IGNvZWZmaWNpZW50O1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBNb2R1bHVzUG9seSh0aGlzLCBjb2VmZmljaWVudHMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIE1vZHVsdXNHRi5QREY0MTdfR0YgPSBuZXcgTW9kdWx1c0dGKFBERjQxN0NvbW1vbi5OVU1CRVJfT0ZfQ09ERVdPUkRTLCAzKTtcblxuICAgIC8qXG4gICAgKiBDb3B5cmlnaHQgMjAxMiBaWGluZyBhdXRob3JzXG4gICAgKlxuICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICpcbiAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgKlxuICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAqL1xuICAgIC8qKlxuICAgICAqIDxwPlBERjQxNyBlcnJvciBjb3JyZWN0aW9uIGltcGxlbWVudGF0aW9uLjwvcD5cbiAgICAgKlxuICAgICAqIDxwPlRoaXMgPGEgaHJlZj1cImh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUmVlZCVFMiU4MCU5M1NvbG9tb25fZXJyb3JfY29ycmVjdGlvbiNFeGFtcGxlXCI+ZXhhbXBsZTwvYT5cbiAgICAgKiBpcyBxdWl0ZSB1c2VmdWwgaW4gdW5kZXJzdGFuZGluZyB0aGUgYWxnb3JpdGhtLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICogQHNlZSBjb20uZ29vZ2xlLnp4aW5nLmNvbW1vbi5yZWVkc29sb21vbi5SZWVkU29sb21vbkRlY29kZXJcbiAgICAgKi9cbiAgICAvKnB1YmxpYyBmaW5hbCovIGNsYXNzIEVycm9yQ29ycmVjdGlvbiB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgdGhpcy5maWVsZCA9IE1vZHVsdXNHRi5QREY0MTdfR0Y7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSByZWNlaXZlZCByZWNlaXZlZCBjb2Rld29yZHNcbiAgICAgICAgICogQHBhcmFtIG51bUVDQ29kZXdvcmRzIG51bWJlciBvZiB0aG9zZSBjb2Rld29yZHMgdXNlZCBmb3IgRUNcbiAgICAgICAgICogQHBhcmFtIGVyYXN1cmVzIGxvY2F0aW9uIG9mIGVyYXN1cmVzXG4gICAgICAgICAqIEByZXR1cm4gbnVtYmVyIG9mIGVycm9yc1xuICAgICAgICAgKiBAdGhyb3dzIENoZWNrc3VtRXhjZXB0aW9uIGlmIGVycm9ycyBjYW5ub3QgYmUgY29ycmVjdGVkLCBtYXliZSBiZWNhdXNlIG9mIHRvbyBtYW55IGVycm9yc1xuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlKHJlY2VpdmVkLCBudW1FQ0NvZGV3b3JkcywgZXJhc3VyZXMpIHtcbiAgICAgICAgICAgIGxldCBwb2x5ID0gbmV3IE1vZHVsdXNQb2x5KHRoaXMuZmllbGQsIHJlY2VpdmVkKTtcbiAgICAgICAgICAgIGxldCBTID0gbmV3IEludDMyQXJyYXkobnVtRUNDb2Rld29yZHMpO1xuICAgICAgICAgICAgbGV0IGVycm9yID0gZmFsc2U7XG4gICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSBudW1FQ0NvZGV3b3JkczsgaSA+IDA7IGktLSkge1xuICAgICAgICAgICAgICAgIGxldCBldmFsdWF0aW9uID0gcG9seS5ldmFsdWF0ZUF0KHRoaXMuZmllbGQuZXhwKGkpKTtcbiAgICAgICAgICAgICAgICBTW251bUVDQ29kZXdvcmRzIC0gaV0gPSBldmFsdWF0aW9uO1xuICAgICAgICAgICAgICAgIGlmIChldmFsdWF0aW9uICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQga25vd25FcnJvcnMgPSB0aGlzLmZpZWxkLmdldE9uZSgpO1xuICAgICAgICAgICAgaWYgKGVyYXN1cmVzICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGVyYXN1cmUgb2YgZXJhc3VyZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGIgPSB0aGlzLmZpZWxkLmV4cChyZWNlaXZlZC5sZW5ndGggLSAxIC0gZXJhc3VyZSk7XG4gICAgICAgICAgICAgICAgICAgIC8vIEFkZCAoMSAtIGJ4KSB0ZXJtOlxuICAgICAgICAgICAgICAgICAgICBsZXQgdGVybSA9IG5ldyBNb2R1bHVzUG9seSh0aGlzLmZpZWxkLCBuZXcgSW50MzJBcnJheShbdGhpcy5maWVsZC5zdWJ0cmFjdCgwLCBiKSwgMV0pKTtcbiAgICAgICAgICAgICAgICAgICAga25vd25FcnJvcnMgPSBrbm93bkVycm9ycy5tdWx0aXBseSh0ZXJtKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc3luZHJvbWUgPSBuZXcgTW9kdWx1c1BvbHkodGhpcy5maWVsZCwgUyk7XG4gICAgICAgICAgICAvLyBzeW5kcm9tZSA9IHN5bmRyb21lLm11bHRpcGx5KGtub3duRXJyb3JzKTtcbiAgICAgICAgICAgIGxldCBzaWdtYU9tZWdhID0gdGhpcy5ydW5FdWNsaWRlYW5BbGdvcml0aG0odGhpcy5maWVsZC5idWlsZE1vbm9taWFsKG51bUVDQ29kZXdvcmRzLCAxKSwgc3luZHJvbWUsIG51bUVDQ29kZXdvcmRzKTtcbiAgICAgICAgICAgIGxldCBzaWdtYSA9IHNpZ21hT21lZ2FbMF07XG4gICAgICAgICAgICBsZXQgb21lZ2EgPSBzaWdtYU9tZWdhWzFdO1xuICAgICAgICAgICAgLy8gc2lnbWEgPSBzaWdtYS5tdWx0aXBseShrbm93bkVycm9ycyk7XG4gICAgICAgICAgICBsZXQgZXJyb3JMb2NhdGlvbnMgPSB0aGlzLmZpbmRFcnJvckxvY2F0aW9ucyhzaWdtYSk7XG4gICAgICAgICAgICBsZXQgZXJyb3JNYWduaXR1ZGVzID0gdGhpcy5maW5kRXJyb3JNYWduaXR1ZGVzKG9tZWdhLCBzaWdtYSwgZXJyb3JMb2NhdGlvbnMpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMDsgaSA8IGVycm9yTG9jYXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IHBvc2l0aW9uID0gcmVjZWl2ZWQubGVuZ3RoIC0gMSAtIHRoaXMuZmllbGQubG9nKGVycm9yTG9jYXRpb25zW2ldKTtcbiAgICAgICAgICAgICAgICBpZiAocG9zaXRpb24gPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IENoZWNrc3VtRXhjZXB0aW9uLmdldENoZWNrc3VtSW5zdGFuY2UoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVjZWl2ZWRbcG9zaXRpb25dID0gdGhpcy5maWVsZC5zdWJ0cmFjdChyZWNlaXZlZFtwb3NpdGlvbl0sIGVycm9yTWFnbml0dWRlc1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZXJyb3JMb2NhdGlvbnMubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gTW9kdWx1c1BvbHlcbiAgICAgICAgICogQHBhcmFtIGFcbiAgICAgICAgICogQHBhcmFtIE1vZHVsdXNQb2x5XG4gICAgICAgICAqIEBwYXJhbSBiXG4gICAgICAgICAqIEBwYXJhbSBpbnRcbiAgICAgICAgICogQHBhcmFtIFJcbiAgICAgICAgICogQHRocm93cyBDaGVja3N1bUV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgcnVuRXVjbGlkZWFuQWxnb3JpdGhtKGEsIGIsIFIpIHtcbiAgICAgICAgICAgIC8vIEFzc3VtZSBhJ3MgZGVncmVlIGlzID49IGInc1xuICAgICAgICAgICAgaWYgKGEuZ2V0RGVncmVlKCkgPCBiLmdldERlZ3JlZSgpKSB7XG4gICAgICAgICAgICAgICAgbGV0IHRlbXAgPSBhO1xuICAgICAgICAgICAgICAgIGEgPSBiO1xuICAgICAgICAgICAgICAgIGIgPSB0ZW1wO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHJMYXN0ID0gYTtcbiAgICAgICAgICAgIGxldCByID0gYjtcbiAgICAgICAgICAgIGxldCB0TGFzdCA9IHRoaXMuZmllbGQuZ2V0WmVybygpO1xuICAgICAgICAgICAgbGV0IHQgPSB0aGlzLmZpZWxkLmdldE9uZSgpO1xuICAgICAgICAgICAgLy8gUnVuIEV1Y2xpZGVhbiBhbGdvcml0aG0gdW50aWwgcidzIGRlZ3JlZSBpcyBsZXNzIHRoYW4gUi8yXG4gICAgICAgICAgICB3aGlsZSAoci5nZXREZWdyZWUoKSA+PSBNYXRoLnJvdW5kKFIgLyAyKSkge1xuICAgICAgICAgICAgICAgIGxldCByTGFzdExhc3QgPSByTGFzdDtcbiAgICAgICAgICAgICAgICBsZXQgdExhc3RMYXN0ID0gdExhc3Q7XG4gICAgICAgICAgICAgICAgckxhc3QgPSByO1xuICAgICAgICAgICAgICAgIHRMYXN0ID0gdDtcbiAgICAgICAgICAgICAgICAvLyBEaXZpZGUgckxhc3RMYXN0IGJ5IHJMYXN0LCB3aXRoIHF1b3RpZW50IGluIHEgYW5kIHJlbWFpbmRlciBpbiByXG4gICAgICAgICAgICAgICAgaWYgKHJMYXN0LmlzWmVybygpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE9vcHMsIEV1Y2xpZGVhbiBhbGdvcml0aG0gYWxyZWFkeSB0ZXJtaW5hdGVkP1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBDaGVja3N1bUV4Y2VwdGlvbi5nZXRDaGVja3N1bUluc3RhbmNlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHIgPSByTGFzdExhc3Q7XG4gICAgICAgICAgICAgICAgbGV0IHEgPSB0aGlzLmZpZWxkLmdldFplcm8oKTtcbiAgICAgICAgICAgICAgICBsZXQgZGVub21pbmF0b3JMZWFkaW5nVGVybSA9IHJMYXN0LmdldENvZWZmaWNpZW50KHJMYXN0LmdldERlZ3JlZSgpKTtcbiAgICAgICAgICAgICAgICBsZXQgZGx0SW52ZXJzZSA9IHRoaXMuZmllbGQuaW52ZXJzZShkZW5vbWluYXRvckxlYWRpbmdUZXJtKTtcbiAgICAgICAgICAgICAgICB3aGlsZSAoci5nZXREZWdyZWUoKSA+PSByTGFzdC5nZXREZWdyZWUoKSAmJiAhci5pc1plcm8oKSkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgZGVncmVlRGlmZiA9IHIuZ2V0RGVncmVlKCkgLSByTGFzdC5nZXREZWdyZWUoKTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHNjYWxlID0gdGhpcy5maWVsZC5tdWx0aXBseShyLmdldENvZWZmaWNpZW50KHIuZ2V0RGVncmVlKCkpLCBkbHRJbnZlcnNlKTtcbiAgICAgICAgICAgICAgICAgICAgcSA9IHEuYWRkKHRoaXMuZmllbGQuYnVpbGRNb25vbWlhbChkZWdyZWVEaWZmLCBzY2FsZSkpO1xuICAgICAgICAgICAgICAgICAgICByID0gci5zdWJ0cmFjdChyTGFzdC5tdWx0aXBseUJ5TW9ub21pYWwoZGVncmVlRGlmZiwgc2NhbGUpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdCA9IHEubXVsdGlwbHkodExhc3QpLnN1YnRyYWN0KHRMYXN0TGFzdCkubmVnYXRpdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBzaWdtYVRpbGRlQXRaZXJvID0gdC5nZXRDb2VmZmljaWVudCgwKTtcbiAgICAgICAgICAgIGlmIChzaWdtYVRpbGRlQXRaZXJvID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgQ2hlY2tzdW1FeGNlcHRpb24uZ2V0Q2hlY2tzdW1JbnN0YW5jZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGludmVyc2UgPSB0aGlzLmZpZWxkLmludmVyc2Uoc2lnbWFUaWxkZUF0WmVybyk7XG4gICAgICAgICAgICBsZXQgc2lnbWEgPSB0Lm11bHRpcGx5KGludmVyc2UpO1xuICAgICAgICAgICAgbGV0IG9tZWdhID0gci5tdWx0aXBseShpbnZlcnNlKTtcbiAgICAgICAgICAgIHJldHVybiBbc2lnbWEsIG9tZWdhXTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGVycm9yTG9jYXRvclxuICAgICAgICAgKiBAdGhyb3dzIENoZWNrc3VtRXhjZXB0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBmaW5kRXJyb3JMb2NhdGlvbnMoZXJyb3JMb2NhdG9yKSB7XG4gICAgICAgICAgICAvLyBUaGlzIGlzIGEgZGlyZWN0IGFwcGxpY2F0aW9uIG9mIENoaWVuJ3Mgc2VhcmNoXG4gICAgICAgICAgICBsZXQgbnVtRXJyb3JzID0gZXJyb3JMb2NhdG9yLmdldERlZ3JlZSgpO1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IG5ldyBJbnQzMkFycmF5KG51bUVycm9ycyk7XG4gICAgICAgICAgICBsZXQgZSA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAxOyBpIDwgdGhpcy5maWVsZC5nZXRTaXplKCkgJiYgZSA8IG51bUVycm9yczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yTG9jYXRvci5ldmFsdWF0ZUF0KGkpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtlXSA9IHRoaXMuZmllbGQuaW52ZXJzZShpKTtcbiAgICAgICAgICAgICAgICAgICAgZSsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChlICE9PSBudW1FcnJvcnMpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBDaGVja3N1bUV4Y2VwdGlvbi5nZXRDaGVja3N1bUluc3RhbmNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIGZpbmRFcnJvck1hZ25pdHVkZXMoZXJyb3JFdmFsdWF0b3IsIGVycm9yTG9jYXRvciwgZXJyb3JMb2NhdGlvbnMpIHtcbiAgICAgICAgICAgIGxldCBlcnJvckxvY2F0b3JEZWdyZWUgPSBlcnJvckxvY2F0b3IuZ2V0RGVncmVlKCk7XG4gICAgICAgICAgICBsZXQgZm9ybWFsRGVyaXZhdGl2ZUNvZWZmaWNpZW50cyA9IG5ldyBJbnQzMkFycmF5KGVycm9yTG9jYXRvckRlZ3JlZSk7XG4gICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAxOyBpIDw9IGVycm9yTG9jYXRvckRlZ3JlZTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgZm9ybWFsRGVyaXZhdGl2ZUNvZWZmaWNpZW50c1tlcnJvckxvY2F0b3JEZWdyZWUgLSBpXSA9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZmllbGQubXVsdGlwbHkoaSwgZXJyb3JMb2NhdG9yLmdldENvZWZmaWNpZW50KGkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBmb3JtYWxEZXJpdmF0aXZlID0gbmV3IE1vZHVsdXNQb2x5KHRoaXMuZmllbGQsIGZvcm1hbERlcml2YXRpdmVDb2VmZmljaWVudHMpO1xuICAgICAgICAgICAgLy8gVGhpcyBpcyBkaXJlY3RseSBhcHBseWluZyBGb3JuZXkncyBGb3JtdWxhXG4gICAgICAgICAgICBsZXQgcyA9IGVycm9yTG9jYXRpb25zLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSBuZXcgSW50MzJBcnJheShzKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCBzOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgeGlJbnZlcnNlID0gdGhpcy5maWVsZC5pbnZlcnNlKGVycm9yTG9jYXRpb25zW2ldKTtcbiAgICAgICAgICAgICAgICBsZXQgbnVtZXJhdG9yID0gdGhpcy5maWVsZC5zdWJ0cmFjdCgwLCBlcnJvckV2YWx1YXRvci5ldmFsdWF0ZUF0KHhpSW52ZXJzZSkpO1xuICAgICAgICAgICAgICAgIGxldCBkZW5vbWluYXRvciA9IHRoaXMuZmllbGQuaW52ZXJzZShmb3JtYWxEZXJpdmF0aXZlLmV2YWx1YXRlQXQoeGlJbnZlcnNlKSk7XG4gICAgICAgICAgICAgICAgcmVzdWx0W2ldID0gdGhpcy5maWVsZC5tdWx0aXBseShudW1lcmF0b3IsIGRlbm9taW5hdG9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICogQ29weXJpZ2h0IDIwMTMgWlhpbmcgYXV0aG9yc1xuICAgICpcbiAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAqXG4gICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICpcbiAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgKi9cbiAgICAvKipcbiAgICAgKiBAYXV0aG9yIEd1ZW50aGVyIEdyYXVcbiAgICAgKi9cbiAgICAvKmZpbmFsKi8gY2xhc3MgQm91bmRpbmdCb3gge1xuICAgICAgICBjb25zdHJ1Y3RvcihpbWFnZSwgdG9wTGVmdCwgYm90dG9tTGVmdCwgdG9wUmlnaHQsIGJvdHRvbVJpZ2h0KSB7XG4gICAgICAgICAgICBpZiAoaW1hZ2UgaW5zdGFuY2VvZiBCb3VuZGluZ0JveCkge1xuICAgICAgICAgICAgICAgIHRoaXMuY29uc3RydWN0b3JfMihpbWFnZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnN0cnVjdG9yXzEoaW1hZ2UsIHRvcExlZnQsIGJvdHRvbUxlZnQsIHRvcFJpZ2h0LCBib3R0b21SaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBpbWFnZVxuICAgICAgICAgKiBAcGFyYW0gdG9wTGVmdFxuICAgICAgICAgKiBAcGFyYW0gYm90dG9tTGVmdFxuICAgICAgICAgKiBAcGFyYW0gdG9wUmlnaHRcbiAgICAgICAgICogQHBhcmFtIGJvdHRvbVJpZ2h0XG4gICAgICAgICAqXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIGNvbnN0cnVjdG9yXzEoaW1hZ2UsIHRvcExlZnQsIGJvdHRvbUxlZnQsIHRvcFJpZ2h0LCBib3R0b21SaWdodCkge1xuICAgICAgICAgICAgY29uc3QgbGVmdFVuc3BlY2lmaWVkID0gdG9wTGVmdCA9PSBudWxsIHx8IGJvdHRvbUxlZnQgPT0gbnVsbDtcbiAgICAgICAgICAgIGNvbnN0IHJpZ2h0VW5zcGVjaWZpZWQgPSB0b3BSaWdodCA9PSBudWxsIHx8IGJvdHRvbVJpZ2h0ID09IG51bGw7XG4gICAgICAgICAgICBpZiAobGVmdFVuc3BlY2lmaWVkICYmIHJpZ2h0VW5zcGVjaWZpZWQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChsZWZ0VW5zcGVjaWZpZWQpIHtcbiAgICAgICAgICAgICAgICB0b3BMZWZ0ID0gbmV3IFJlc3VsdFBvaW50KDAsIHRvcFJpZ2h0LmdldFkoKSk7XG4gICAgICAgICAgICAgICAgYm90dG9tTGVmdCA9IG5ldyBSZXN1bHRQb2ludCgwLCBib3R0b21SaWdodC5nZXRZKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAocmlnaHRVbnNwZWNpZmllZCkge1xuICAgICAgICAgICAgICAgIHRvcFJpZ2h0ID0gbmV3IFJlc3VsdFBvaW50KGltYWdlLmdldFdpZHRoKCkgLSAxLCB0b3BMZWZ0LmdldFkoKSk7XG4gICAgICAgICAgICAgICAgYm90dG9tUmlnaHQgPSBuZXcgUmVzdWx0UG9pbnQoaW1hZ2UuZ2V0V2lkdGgoKSAtIDEsIGJvdHRvbUxlZnQuZ2V0WSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuaW1hZ2UgPSBpbWFnZTtcbiAgICAgICAgICAgIHRoaXMudG9wTGVmdCA9IHRvcExlZnQ7XG4gICAgICAgICAgICB0aGlzLmJvdHRvbUxlZnQgPSBib3R0b21MZWZ0O1xuICAgICAgICAgICAgdGhpcy50b3BSaWdodCA9IHRvcFJpZ2h0O1xuICAgICAgICAgICAgdGhpcy5ib3R0b21SaWdodCA9IGJvdHRvbVJpZ2h0O1xuICAgICAgICAgICAgdGhpcy5taW5YID0gTWF0aC50cnVuYyhNYXRoLm1pbih0b3BMZWZ0LmdldFgoKSwgYm90dG9tTGVmdC5nZXRYKCkpKTtcbiAgICAgICAgICAgIHRoaXMubWF4WCA9IE1hdGgudHJ1bmMoTWF0aC5tYXgodG9wUmlnaHQuZ2V0WCgpLCBib3R0b21SaWdodC5nZXRYKCkpKTtcbiAgICAgICAgICAgIHRoaXMubWluWSA9IE1hdGgudHJ1bmMoTWF0aC5taW4odG9wTGVmdC5nZXRZKCksIHRvcFJpZ2h0LmdldFkoKSkpO1xuICAgICAgICAgICAgdGhpcy5tYXhZID0gTWF0aC50cnVuYyhNYXRoLm1heChib3R0b21MZWZ0LmdldFkoKSwgYm90dG9tUmlnaHQuZ2V0WSgpKSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3RydWN0b3JfMihib3VuZGluZ0JveCkge1xuICAgICAgICAgICAgdGhpcy5pbWFnZSA9IGJvdW5kaW5nQm94LmltYWdlO1xuICAgICAgICAgICAgdGhpcy50b3BMZWZ0ID0gYm91bmRpbmdCb3guZ2V0VG9wTGVmdCgpO1xuICAgICAgICAgICAgdGhpcy5ib3R0b21MZWZ0ID0gYm91bmRpbmdCb3guZ2V0Qm90dG9tTGVmdCgpO1xuICAgICAgICAgICAgdGhpcy50b3BSaWdodCA9IGJvdW5kaW5nQm94LmdldFRvcFJpZ2h0KCk7XG4gICAgICAgICAgICB0aGlzLmJvdHRvbVJpZ2h0ID0gYm91bmRpbmdCb3guZ2V0Qm90dG9tUmlnaHQoKTtcbiAgICAgICAgICAgIHRoaXMubWluWCA9IGJvdW5kaW5nQm94LmdldE1pblgoKTtcbiAgICAgICAgICAgIHRoaXMubWF4WCA9IGJvdW5kaW5nQm94LmdldE1heFgoKTtcbiAgICAgICAgICAgIHRoaXMubWluWSA9IGJvdW5kaW5nQm94LmdldE1pblkoKTtcbiAgICAgICAgICAgIHRoaXMubWF4WSA9IGJvdW5kaW5nQm94LmdldE1heFkoKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIG1lcmdlKGxlZnRCb3gsIHJpZ2h0Qm94KSB7XG4gICAgICAgICAgICBpZiAobGVmdEJveCA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJpZ2h0Qm94O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJpZ2h0Qm94ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVmdEJveDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgQm91bmRpbmdCb3gobGVmdEJveC5pbWFnZSwgbGVmdEJveC50b3BMZWZ0LCBsZWZ0Qm94LmJvdHRvbUxlZnQsIHJpZ2h0Qm94LnRvcFJpZ2h0LCByaWdodEJveC5ib3R0b21SaWdodCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIGFkZE1pc3NpbmdSb3dzKG1pc3NpbmdTdGFydFJvd3MsIG1pc3NpbmdFbmRSb3dzLCBpc0xlZnQpIHtcbiAgICAgICAgICAgIGxldCBuZXdUb3BMZWZ0ID0gdGhpcy50b3BMZWZ0O1xuICAgICAgICAgICAgbGV0IG5ld0JvdHRvbUxlZnQgPSB0aGlzLmJvdHRvbUxlZnQ7XG4gICAgICAgICAgICBsZXQgbmV3VG9wUmlnaHQgPSB0aGlzLnRvcFJpZ2h0O1xuICAgICAgICAgICAgbGV0IG5ld0JvdHRvbVJpZ2h0ID0gdGhpcy5ib3R0b21SaWdodDtcbiAgICAgICAgICAgIGlmIChtaXNzaW5nU3RhcnRSb3dzID4gMCkge1xuICAgICAgICAgICAgICAgIGxldCB0b3AgPSBpc0xlZnQgPyB0aGlzLnRvcExlZnQgOiB0aGlzLnRvcFJpZ2h0O1xuICAgICAgICAgICAgICAgIGxldCBuZXdNaW5ZID0gTWF0aC50cnVuYyh0b3AuZ2V0WSgpIC0gbWlzc2luZ1N0YXJ0Um93cyk7XG4gICAgICAgICAgICAgICAgaWYgKG5ld01pblkgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld01pblkgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgbmV3VG9wID0gbmV3IFJlc3VsdFBvaW50KHRvcC5nZXRYKCksIG5ld01pblkpO1xuICAgICAgICAgICAgICAgIGlmIChpc0xlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3VG9wTGVmdCA9IG5ld1RvcDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld1RvcFJpZ2h0ID0gbmV3VG9wO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtaXNzaW5nRW5kUm93cyA+IDApIHtcbiAgICAgICAgICAgICAgICBsZXQgYm90dG9tID0gaXNMZWZ0ID8gdGhpcy5ib3R0b21MZWZ0IDogdGhpcy5ib3R0b21SaWdodDtcbiAgICAgICAgICAgICAgICBsZXQgbmV3TWF4WSA9IE1hdGgudHJ1bmMoYm90dG9tLmdldFkoKSArIG1pc3NpbmdFbmRSb3dzKTtcbiAgICAgICAgICAgICAgICBpZiAobmV3TWF4WSA+PSB0aGlzLmltYWdlLmdldEhlaWdodCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld01heFkgPSB0aGlzLmltYWdlLmdldEhlaWdodCgpIC0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IG5ld0JvdHRvbSA9IG5ldyBSZXN1bHRQb2ludChib3R0b20uZ2V0WCgpLCBuZXdNYXhZKTtcbiAgICAgICAgICAgICAgICBpZiAoaXNMZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld0JvdHRvbUxlZnQgPSBuZXdCb3R0b207XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdCb3R0b21SaWdodCA9IG5ld0JvdHRvbTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IEJvdW5kaW5nQm94KHRoaXMuaW1hZ2UsIG5ld1RvcExlZnQsIG5ld0JvdHRvbUxlZnQsIG5ld1RvcFJpZ2h0LCBuZXdCb3R0b21SaWdodCk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0TWluWCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1pblg7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0TWF4WCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1heFg7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0TWluWSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1pblk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0TWF4WSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1heFk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0VG9wTGVmdCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRvcExlZnQ7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0VG9wUmlnaHQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50b3BSaWdodDtcbiAgICAgICAgfVxuICAgICAgICBnZXRCb3R0b21MZWZ0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYm90dG9tTGVmdDtcbiAgICAgICAgfVxuICAgICAgICBnZXRCb3R0b21SaWdodCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJvdHRvbVJpZ2h0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAxMyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvLyBwYWNrYWdlIGNvbS5nb29nbGUuenhpbmcucGRmNDE3LmRlY29kZXI7XG4gICAgLyoqXG4gICAgICogQGF1dGhvciBHdWVudGhlciBHcmF1XG4gICAgICovXG4gICAgLypmaW5hbCovIGNsYXNzIEJhcmNvZGVNZXRhZGF0YSB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGNvbHVtbkNvdW50LCByb3dDb3VudFVwcGVyUGFydCwgcm93Q291bnRMb3dlclBhcnQsIGVycm9yQ29ycmVjdGlvbkxldmVsKSB7XG4gICAgICAgICAgICB0aGlzLmNvbHVtbkNvdW50ID0gY29sdW1uQ291bnQ7XG4gICAgICAgICAgICB0aGlzLmVycm9yQ29ycmVjdGlvbkxldmVsID0gZXJyb3JDb3JyZWN0aW9uTGV2ZWw7XG4gICAgICAgICAgICB0aGlzLnJvd0NvdW50VXBwZXJQYXJ0ID0gcm93Q291bnRVcHBlclBhcnQ7XG4gICAgICAgICAgICB0aGlzLnJvd0NvdW50TG93ZXJQYXJ0ID0gcm93Q291bnRMb3dlclBhcnQ7XG4gICAgICAgICAgICB0aGlzLnJvd0NvdW50ID0gcm93Q291bnRVcHBlclBhcnQgKyByb3dDb3VudExvd2VyUGFydDtcbiAgICAgICAgfVxuICAgICAgICBnZXRDb2x1bW5Db3VudCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbHVtbkNvdW50O1xuICAgICAgICB9XG4gICAgICAgIGdldEVycm9yQ29ycmVjdGlvbkxldmVsKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXJyb3JDb3JyZWN0aW9uTGV2ZWw7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Um93Q291bnQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yb3dDb3VudDtcbiAgICAgICAgfVxuICAgICAgICBnZXRSb3dDb3VudFVwcGVyUGFydCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJvd0NvdW50VXBwZXJQYXJ0O1xuICAgICAgICB9XG4gICAgICAgIGdldFJvd0NvdW50TG93ZXJQYXJ0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucm93Q291bnRMb3dlclBhcnQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBKYXZhIEZvcm1hdHRlciBjbGFzcyBwb2x5ZmlsbCB0aGF0IHdvcmtzIGluIHRoZSBKUyB3YXkuXG4gICAgICovXG4gICAgY2xhc3MgRm9ybWF0dGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgICAgICB0aGlzLmJ1ZmZlciA9ICcnO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKlxuICAgICAgICAgKiBAc2VlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8xMzQzOTcxMS80MzY3NjgzXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBzdHJcbiAgICAgICAgICogQHBhcmFtIGFyclxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGZvcm0oc3RyLCBhcnIpIHtcbiAgICAgICAgICAgIGxldCBpID0gLTE7XG4gICAgICAgICAgICBmdW5jdGlvbiBjYWxsYmFjayhleHAsIHAwLCBwMSwgcDIsIHAzLCBwNCkge1xuICAgICAgICAgICAgICAgIGlmIChleHAgPT09ICclJScpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnJSc7XG4gICAgICAgICAgICAgICAgaWYgKGFyclsrK2ldID09PSB1bmRlZmluZWQpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgZXhwID0gcDIgPyBwYXJzZUludChwMi5zdWJzdHIoMSkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGxldCBiYXNlID0gcDMgPyBwYXJzZUludChwMy5zdWJzdHIoMSkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGxldCB2YWw7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChwNCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdzJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbCA9IGFycltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdjJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbCA9IGFycltpXVswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdmJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbCA9IHBhcnNlRmxvYXQoYXJyW2ldKS50b0ZpeGVkKGV4cCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAncCc6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWwgPSBwYXJzZUZsb2F0KGFycltpXSkudG9QcmVjaXNpb24oZXhwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdlJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbCA9IHBhcnNlRmxvYXQoYXJyW2ldKS50b0V4cG9uZW50aWFsKGV4cCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAneCc6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWwgPSBwYXJzZUludChhcnJbaV0pLnRvU3RyaW5nKGJhc2UgPyBiYXNlIDogMTYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsID0gcGFyc2VGbG9hdChwYXJzZUludChhcnJbaV0sIGJhc2UgPyBiYXNlIDogMTApLnRvUHJlY2lzaW9uKGV4cCkpLnRvRml4ZWQoMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFsID0gdHlwZW9mIHZhbCA9PT0gJ29iamVjdCcgPyBKU09OLnN0cmluZ2lmeSh2YWwpIDogKCt2YWwpLnRvU3RyaW5nKGJhc2UpO1xuICAgICAgICAgICAgICAgIGxldCBzaXplID0gcGFyc2VJbnQocDEpOyAvKiBwYWRkaW5nIHNpemUgKi9cbiAgICAgICAgICAgICAgICBsZXQgY2ggPSBwMSAmJiAocDFbMF0gKyAnJykgPT09ICcwJyA/ICcwJyA6ICcgJzsgLyogaXNudWxsPyAqL1xuICAgICAgICAgICAgICAgIHdoaWxlICh2YWwubGVuZ3RoIDwgc2l6ZSlcbiAgICAgICAgICAgICAgICAgICAgdmFsID0gcDAgIT09IHVuZGVmaW5lZCA/IHZhbCArIGNoIDogY2ggKyB2YWw7IC8qIGlzbWludXM/ICovXG4gICAgICAgICAgICAgICAgcmV0dXJuIHZhbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCByZWdleCA9IC8lKC0pPygwP1swLTldKyk/KFsuXVswLTldKyk/KFsjXVswLTldKyk/KFtzY2ZwZXhkJV0pL2c7XG4gICAgICAgICAgICByZXR1cm4gc3RyLnJlcGxhY2UocmVnZXgsIGNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGFwcGVuZCBUaGUgbmV3IHN0cmluZyB0byBhcHBlbmQuXG4gICAgICAgICAqIEBwYXJhbSBhcmdzIEFyZ3VtZXRzIHZhbHVlcyB0byBiZSBmb3JtYXRlZC5cbiAgICAgICAgICovXG4gICAgICAgIGZvcm1hdChhcHBlbmQsIC4uLmFyZ3MpIHtcbiAgICAgICAgICAgIHRoaXMuYnVmZmVyICs9IEZvcm1hdHRlci5mb3JtKGFwcGVuZCwgYXJncyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldHVybnMgdGhlIEZvcm1hdHRlciBzdHJpbmcgdmFsdWUuXG4gICAgICAgICAqL1xuICAgICAgICB0b1N0cmluZygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJ1ZmZlcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMTMgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogQGF1dGhvciBHdWVudGhlciBHcmF1XG4gICAgICovXG4gICAgY2xhc3MgRGV0ZWN0aW9uUmVzdWx0Q29sdW1uIHtcbiAgICAgICAgY29uc3RydWN0b3IoYm91bmRpbmdCb3gpIHtcbiAgICAgICAgICAgIHRoaXMuYm91bmRpbmdCb3ggPSBuZXcgQm91bmRpbmdCb3goYm91bmRpbmdCb3gpO1xuICAgICAgICAgICAgLy8gdGhpcy5jb2Rld29yZHMgPSBuZXcgQ29kZXdvcmRbYm91bmRpbmdCb3guZ2V0TWF4WSgpIC0gYm91bmRpbmdCb3guZ2V0TWluWSgpICsgMV07XG4gICAgICAgICAgICB0aGlzLmNvZGV3b3JkcyA9IG5ldyBBcnJheShib3VuZGluZ0JveC5nZXRNYXhZKCkgLSBib3VuZGluZ0JveC5nZXRNaW5ZKCkgKyAxKTtcbiAgICAgICAgfVxuICAgICAgICAvKmZpbmFsKi8gZ2V0Q29kZXdvcmROZWFyYnkoaW1hZ2VSb3cpIHtcbiAgICAgICAgICAgIGxldCBjb2Rld29yZCA9IHRoaXMuZ2V0Q29kZXdvcmQoaW1hZ2VSb3cpO1xuICAgICAgICAgICAgaWYgKGNvZGV3b3JkICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY29kZXdvcmQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IERldGVjdGlvblJlc3VsdENvbHVtbi5NQVhfTkVBUkJZX0RJU1RBTkNFOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgbmVhckltYWdlUm93ID0gdGhpcy5pbWFnZVJvd1RvQ29kZXdvcmRJbmRleChpbWFnZVJvdykgLSBpO1xuICAgICAgICAgICAgICAgIGlmIChuZWFySW1hZ2VSb3cgPj0gMCkge1xuICAgICAgICAgICAgICAgICAgICBjb2Rld29yZCA9IHRoaXMuY29kZXdvcmRzW25lYXJJbWFnZVJvd107XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb2Rld29yZCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29kZXdvcmQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbmVhckltYWdlUm93ID0gdGhpcy5pbWFnZVJvd1RvQ29kZXdvcmRJbmRleChpbWFnZVJvdykgKyBpO1xuICAgICAgICAgICAgICAgIGlmIChuZWFySW1hZ2VSb3cgPCB0aGlzLmNvZGV3b3Jkcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgY29kZXdvcmQgPSB0aGlzLmNvZGV3b3Jkc1tuZWFySW1hZ2VSb3ddO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvZGV3b3JkO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgLypmaW5hbCBpbnQqLyBpbWFnZVJvd1RvQ29kZXdvcmRJbmRleChpbWFnZVJvdykge1xuICAgICAgICAgICAgcmV0dXJuIGltYWdlUm93IC0gdGhpcy5ib3VuZGluZ0JveC5nZXRNaW5ZKCk7XG4gICAgICAgIH1cbiAgICAgICAgLypmaW5hbCB2b2lkKi8gc2V0Q29kZXdvcmQoaW1hZ2VSb3csIGNvZGV3b3JkKSB7XG4gICAgICAgICAgICB0aGlzLmNvZGV3b3Jkc1t0aGlzLmltYWdlUm93VG9Db2Rld29yZEluZGV4KGltYWdlUm93KV0gPSBjb2Rld29yZDtcbiAgICAgICAgfVxuICAgICAgICAvKmZpbmFsKi8gZ2V0Q29kZXdvcmQoaW1hZ2VSb3cpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvZGV3b3Jkc1t0aGlzLmltYWdlUm93VG9Db2Rld29yZEluZGV4KGltYWdlUm93KV07XG4gICAgICAgIH1cbiAgICAgICAgLypmaW5hbCovIGdldEJvdW5kaW5nQm94KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYm91bmRpbmdCb3g7XG4gICAgICAgIH1cbiAgICAgICAgLypmaW5hbCovIGdldENvZGV3b3JkcygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvZGV3b3JkcztcbiAgICAgICAgfVxuICAgICAgICAvLyBAT3ZlcnJpZGVcbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICBjb25zdCBmb3JtYXR0ZXIgPSBuZXcgRm9ybWF0dGVyKCk7XG4gICAgICAgICAgICBsZXQgcm93ID0gMDtcbiAgICAgICAgICAgIGZvciAoY29uc3QgY29kZXdvcmQgb2YgdGhpcy5jb2Rld29yZHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBmb3JtYXR0ZXIuZm9ybWF0KCclM2Q6ICAgIHwgICAlbicsIHJvdysrKTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvcm1hdHRlci5mb3JtYXQoJyUzZDogJTNkfCUzZCVuJywgcm93KyssIGNvZGV3b3JkLmdldFJvd051bWJlcigpLCBjb2Rld29yZC5nZXRWYWx1ZSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmb3JtYXR0ZXIudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBEZXRlY3Rpb25SZXN1bHRDb2x1bW4uTUFYX05FQVJCWV9ESVNUQU5DRSA9IDU7XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDEzIFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8vIGltcG9ydCBqYXZhLnV0aWwuQXJyYXlMaXN0O1xuICAgIC8vIGltcG9ydCBqYXZhLnV0aWwuQ29sbGVjdGlvbjtcbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLkhhc2hNYXA7XG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5NYXA7XG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5NYXAuRW50cnk7XG4gICAgLyoqXG4gICAgICogQGF1dGhvciBHdWVudGhlciBHcmF1XG4gICAgICovXG4gICAgLypmaW5hbCovIGNsYXNzIEJhcmNvZGVWYWx1ZSB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgdGhpcy52YWx1ZXMgPSBuZXcgTWFwKCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEFkZCBhbiBvY2N1cnJlbmNlIG9mIGEgdmFsdWVcbiAgICAgICAgICovXG4gICAgICAgIHNldFZhbHVlKHZhbHVlKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IE1hdGgudHJ1bmModmFsdWUpO1xuICAgICAgICAgICAgbGV0IGNvbmZpZGVuY2UgPSB0aGlzLnZhbHVlcy5nZXQodmFsdWUpO1xuICAgICAgICAgICAgaWYgKGNvbmZpZGVuY2UgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbmZpZGVuY2UgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uZmlkZW5jZSsrO1xuICAgICAgICAgICAgdGhpcy52YWx1ZXMuc2V0KHZhbHVlLCBjb25maWRlbmNlKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGV0ZXJtaW5lcyB0aGUgbWF4aW11bSBvY2N1cnJlbmNlIG9mIGEgc2V0IHZhbHVlIGFuZCByZXR1cm5zIGFsbCB2YWx1ZXMgd2hpY2ggd2VyZSBzZXQgd2l0aCB0aGlzIG9jY3VycmVuY2UuXG4gICAgICAgICAqIEByZXR1cm4gYW4gYXJyYXkgb2YgaW50LCBjb250YWluaW5nIHRoZSB2YWx1ZXMgd2l0aCB0aGUgaGlnaGVzdCBvY2N1cnJlbmNlLCBvciBudWxsLCBpZiBubyB2YWx1ZSB3YXMgc2V0XG4gICAgICAgICAqL1xuICAgICAgICBnZXRWYWx1ZSgpIHtcbiAgICAgICAgICAgIGxldCBtYXhDb25maWRlbmNlID0gLTE7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gbmV3IEFycmF5KCk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiB0aGlzLnZhbHVlcy5lbnRyaWVzKCkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBlbnRyeSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZ2V0S2V5OiAoKSA9PiBrZXksXG4gICAgICAgICAgICAgICAgICAgIGdldFZhbHVlOiAoKSA9PiB2YWx1ZSxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGlmIChlbnRyeS5nZXRWYWx1ZSgpID4gbWF4Q29uZmlkZW5jZSkge1xuICAgICAgICAgICAgICAgICAgICBtYXhDb25maWRlbmNlID0gZW50cnkuZ2V0VmFsdWUoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gW107XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKGVudHJ5LmdldEtleSgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZW50cnkuZ2V0VmFsdWUoKSA9PT0gbWF4Q29uZmlkZW5jZSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChlbnRyeS5nZXRLZXkoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIFBERjQxN0NvbW1vbi50b0ludEFycmF5KHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Q29uZmlkZW5jZSh2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWVzLmdldCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDEzIFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIEBhdXRob3IgR3VlbnRoZXIgR3JhdVxuICAgICAqL1xuICAgIC8qZmluYWwqLyBjbGFzcyBEZXRlY3Rpb25SZXN1bHRSb3dJbmRpY2F0b3JDb2x1bW4gZXh0ZW5kcyBEZXRlY3Rpb25SZXN1bHRDb2x1bW4ge1xuICAgICAgICBjb25zdHJ1Y3Rvcihib3VuZGluZ0JveCwgaXNMZWZ0KSB7XG4gICAgICAgICAgICBzdXBlcihib3VuZGluZ0JveCk7XG4gICAgICAgICAgICB0aGlzLl9pc0xlZnQgPSBpc0xlZnQ7XG4gICAgICAgIH1cbiAgICAgICAgc2V0Um93TnVtYmVycygpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGNvZGV3b3JkIC8qQ29kZXdvcmQqLyBvZiB0aGlzLmdldENvZGV3b3JkcygpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvZGV3b3JkICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgY29kZXdvcmQuc2V0Um93TnVtYmVyQXNSb3dJbmRpY2F0b3JDb2x1bW4oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gVE9ETyBpbXBsZW1lbnQgcHJvcGVybHlcbiAgICAgICAgLy8gVE9ETyBtYXliZSB3ZSBzaG91bGQgYWRkIG1pc3NpbmcgY29kZXdvcmRzIHRvIHN0b3JlIHRoZSBjb3JyZWN0IHJvdyBudW1iZXIgdG8gbWFrZVxuICAgICAgICAvLyBmaW5kaW5nIHJvdyBudW1iZXJzIGZvciBvdGhlciBjb2x1bW5zIGVhc2llclxuICAgICAgICAvLyB1c2Ugcm93IGhlaWdodCBjb3VudCB0byBtYWtlIGRldGVjdGlvbiBvZiBpbnZhbGlkIHJvdyBudW1iZXJzIG1vcmUgcmVsaWFibGVcbiAgICAgICAgYWRqdXN0Q29tcGxldGVJbmRpY2F0b3JDb2x1bW5Sb3dOdW1iZXJzKGJhcmNvZGVNZXRhZGF0YSkge1xuICAgICAgICAgICAgbGV0IGNvZGV3b3JkcyA9IHRoaXMuZ2V0Q29kZXdvcmRzKCk7XG4gICAgICAgICAgICB0aGlzLnNldFJvd051bWJlcnMoKTtcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlSW5jb3JyZWN0Q29kZXdvcmRzKGNvZGV3b3JkcywgYmFyY29kZU1ldGFkYXRhKTtcbiAgICAgICAgICAgIGxldCBib3VuZGluZ0JveCA9IHRoaXMuZ2V0Qm91bmRpbmdCb3goKTtcbiAgICAgICAgICAgIGxldCB0b3AgPSB0aGlzLl9pc0xlZnQgPyBib3VuZGluZ0JveC5nZXRUb3BMZWZ0KCkgOiBib3VuZGluZ0JveC5nZXRUb3BSaWdodCgpO1xuICAgICAgICAgICAgbGV0IGJvdHRvbSA9IHRoaXMuX2lzTGVmdCA/IGJvdW5kaW5nQm94LmdldEJvdHRvbUxlZnQoKSA6IGJvdW5kaW5nQm94LmdldEJvdHRvbVJpZ2h0KCk7XG4gICAgICAgICAgICBsZXQgZmlyc3RSb3cgPSB0aGlzLmltYWdlUm93VG9Db2Rld29yZEluZGV4KE1hdGgudHJ1bmModG9wLmdldFkoKSkpO1xuICAgICAgICAgICAgbGV0IGxhc3RSb3cgPSB0aGlzLmltYWdlUm93VG9Db2Rld29yZEluZGV4KE1hdGgudHJ1bmMoYm90dG9tLmdldFkoKSkpO1xuICAgICAgICAgICAgLy8gV2UgbmVlZCB0byBiZSBjYXJlZnVsIHVzaW5nIHRoZSBhdmVyYWdlIHJvdyBoZWlnaHQuIEJhcmNvZGUgY291bGQgYmUgc2tld2VkIHNvIHRoYXQgd2UgaGF2ZSBzbWFsbGVyIGFuZFxuICAgICAgICAgICAgLy8gdGFsbGVyIHJvd3NcbiAgICAgICAgICAgIC8vIGZsb2F0IGF2ZXJhZ2VSb3dIZWlnaHQgPSAobGFzdFJvdyAtIGZpcnN0Um93KSAvIC8qKGZsb2F0KSovIGJhcmNvZGVNZXRhZGF0YS5nZXRSb3dDb3VudCgpO1xuICAgICAgICAgICAgbGV0IGJhcmNvZGVSb3cgPSAtMTtcbiAgICAgICAgICAgIGxldCBtYXhSb3dIZWlnaHQgPSAxO1xuICAgICAgICAgICAgbGV0IGN1cnJlbnRSb3dIZWlnaHQgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgY29kZXdvcmRzUm93IC8qaW50Ki8gPSBmaXJzdFJvdzsgY29kZXdvcmRzUm93IDwgbGFzdFJvdzsgY29kZXdvcmRzUm93KyspIHtcbiAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmRzW2NvZGV3b3Jkc1Jvd10gPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IGNvZGV3b3JkID0gY29kZXdvcmRzW2NvZGV3b3Jkc1Jvd107XG4gICAgICAgICAgICAgICAgLy8gICAgICBmbG9hdCBleHBlY3RlZFJvd051bWJlciA9IChjb2Rld29yZHNSb3cgLSBmaXJzdFJvdykgLyBhdmVyYWdlUm93SGVpZ2h0O1xuICAgICAgICAgICAgICAgIC8vICAgICAgaWYgKE1hdGguYWJzKGNvZGV3b3JkLmdldFJvd051bWJlcigpIC0gZXhwZWN0ZWRSb3dOdW1iZXIpID4gMikge1xuICAgICAgICAgICAgICAgIC8vICAgICAgICBTaW1wbGVMb2cubG9nKExFVkVMLldBUk5JTkcsXG4gICAgICAgICAgICAgICAgLy8gICAgICAgICAgICBcIlJlbW92aW5nIGNvZGV3b3JkLCByb3dOdW1iZXJTa2V3IHRvbyBoaWdoLCBjb2Rld29yZFtcIiArIGNvZGV3b3Jkc1JvdyArIFwiXTogRXhwZWN0ZWQgUm93OiBcIiArXG4gICAgICAgICAgICAgICAgLy8gICAgICAgICAgICAgICAgZXhwZWN0ZWRSb3dOdW1iZXIgKyBcIiwgUmVhbFJvdzogXCIgKyBjb2Rld29yZC5nZXRSb3dOdW1iZXIoKSArIFwiLCB2YWx1ZTogXCIgKyBjb2Rld29yZC5nZXRWYWx1ZSgpKTtcbiAgICAgICAgICAgICAgICAvLyAgICAgICAgY29kZXdvcmRzW2NvZGV3b3Jkc1Jvd10gPSBudWxsO1xuICAgICAgICAgICAgICAgIC8vICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCByb3dEaWZmZXJlbmNlID0gY29kZXdvcmQuZ2V0Um93TnVtYmVyKCkgLSBiYXJjb2RlUm93O1xuICAgICAgICAgICAgICAgIC8vIFRPRE8gaW1wcm92ZSBoYW5kbGluZyB3aXRoIGNhc2Ugd2hlcmUgZmlyc3Qgcm93IGluZGljYXRvciBkb2Vzbid0IHN0YXJ0IHdpdGggMFxuICAgICAgICAgICAgICAgIGlmIChyb3dEaWZmZXJlbmNlID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRSb3dIZWlnaHQrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAocm93RGlmZmVyZW5jZSA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICBtYXhSb3dIZWlnaHQgPSBNYXRoLm1heChtYXhSb3dIZWlnaHQsIGN1cnJlbnRSb3dIZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50Um93SGVpZ2h0ID0gMTtcbiAgICAgICAgICAgICAgICAgICAgYmFyY29kZVJvdyA9IGNvZGV3b3JkLmdldFJvd051bWJlcigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChyb3dEaWZmZXJlbmNlIDwgMCB8fFxuICAgICAgICAgICAgICAgICAgICBjb2Rld29yZC5nZXRSb3dOdW1iZXIoKSA+PSBiYXJjb2RlTWV0YWRhdGEuZ2V0Um93Q291bnQoKSB8fFxuICAgICAgICAgICAgICAgICAgICByb3dEaWZmZXJlbmNlID4gY29kZXdvcmRzUm93KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvZGV3b3Jkc1tjb2Rld29yZHNSb3ddID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBjaGVja2VkUm93cztcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1heFJvd0hlaWdodCA+IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrZWRSb3dzID0gKG1heFJvd0hlaWdodCAtIDIpICogcm93RGlmZmVyZW5jZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrZWRSb3dzID0gcm93RGlmZmVyZW5jZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBsZXQgY2xvc2VQcmV2aW91c0NvZGV3b3JkRm91bmQgPSBjaGVja2VkUm93cyA+PSBjb2Rld29yZHNSb3c7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDE7IGkgPD0gY2hlY2tlZFJvd3MgJiYgIWNsb3NlUHJldmlvdXNDb2Rld29yZEZvdW5kOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZXJlIG11c3QgYmUgKGhlaWdodCAqIHJvd0RpZmZlcmVuY2UpIG51bWJlciBvZiBjb2Rld29yZHMgbWlzc2luZy4gRm9yIG5vdyB3ZSBhc3N1bWUgaGVpZ2h0ID0gMS5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgc2hvdWxkIGhvcGVmdWxseSBnZXQgcmlkIG9mIG1vc3QgcHJvYmxlbXMgYWxyZWFkeS5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNsb3NlUHJldmlvdXNDb2Rld29yZEZvdW5kID0gY29kZXdvcmRzW2NvZGV3b3Jkc1JvdyAtIGldICE9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNsb3NlUHJldmlvdXNDb2Rld29yZEZvdW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb2Rld29yZHNbY29kZXdvcmRzUm93XSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBiYXJjb2RlUm93ID0gY29kZXdvcmQuZ2V0Um93TnVtYmVyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50Um93SGVpZ2h0ID0gMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHJldHVybiAoaW50KSAoYXZlcmFnZVJvd0hlaWdodCArIDAuNSk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Um93SGVpZ2h0cygpIHtcbiAgICAgICAgICAgIGxldCBiYXJjb2RlTWV0YWRhdGEgPSB0aGlzLmdldEJhcmNvZGVNZXRhZGF0YSgpO1xuICAgICAgICAgICAgaWYgKGJhcmNvZGVNZXRhZGF0YSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmFkanVzdEluY29tcGxldGVJbmRpY2F0b3JDb2x1bW5Sb3dOdW1iZXJzKGJhcmNvZGVNZXRhZGF0YSk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gbmV3IEludDMyQXJyYXkoYmFyY29kZU1ldGFkYXRhLmdldFJvd0NvdW50KCkpO1xuICAgICAgICAgICAgZm9yIChsZXQgY29kZXdvcmQgLypDb2Rld29yZCovIG9mIHRoaXMuZ2V0Q29kZXdvcmRzKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgcm93TnVtYmVyID0gY29kZXdvcmQuZ2V0Um93TnVtYmVyKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyb3dOdW1iZXIgPj0gcmVzdWx0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgaGF2ZSBtb3JlIHJvd3MgdGhhbiB0aGUgYmFyY29kZSBtZXRhZGF0YSBhbGxvd3MgZm9yLCBpZ25vcmUgdGhlbS5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtyb3dOdW1iZXJdKys7XG4gICAgICAgICAgICAgICAgfSAvLyBlbHNlIHRocm93IGV4Y2VwdGlvbj9cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVE9ETyBtYXliZSB3ZSBzaG91bGQgYWRkIG1pc3NpbmcgY29kZXdvcmRzIHRvIHN0b3JlIHRoZSBjb3JyZWN0IHJvdyBudW1iZXIgdG8gbWFrZVxuICAgICAgICAvLyBmaW5kaW5nIHJvdyBudW1iZXJzIGZvciBvdGhlciBjb2x1bW5zIGVhc2llclxuICAgICAgICAvLyB1c2Ugcm93IGhlaWdodCBjb3VudCB0byBtYWtlIGRldGVjdGlvbiBvZiBpbnZhbGlkIHJvdyBudW1iZXJzIG1vcmUgcmVsaWFibGVcbiAgICAgICAgYWRqdXN0SW5jb21wbGV0ZUluZGljYXRvckNvbHVtblJvd051bWJlcnMoYmFyY29kZU1ldGFkYXRhKSB7XG4gICAgICAgICAgICBsZXQgYm91bmRpbmdCb3ggPSB0aGlzLmdldEJvdW5kaW5nQm94KCk7XG4gICAgICAgICAgICBsZXQgdG9wID0gdGhpcy5faXNMZWZ0ID8gYm91bmRpbmdCb3guZ2V0VG9wTGVmdCgpIDogYm91bmRpbmdCb3guZ2V0VG9wUmlnaHQoKTtcbiAgICAgICAgICAgIGxldCBib3R0b20gPSB0aGlzLl9pc0xlZnQgPyBib3VuZGluZ0JveC5nZXRCb3R0b21MZWZ0KCkgOiBib3VuZGluZ0JveC5nZXRCb3R0b21SaWdodCgpO1xuICAgICAgICAgICAgbGV0IGZpcnN0Um93ID0gdGhpcy5pbWFnZVJvd1RvQ29kZXdvcmRJbmRleChNYXRoLnRydW5jKHRvcC5nZXRZKCkpKTtcbiAgICAgICAgICAgIGxldCBsYXN0Um93ID0gdGhpcy5pbWFnZVJvd1RvQ29kZXdvcmRJbmRleChNYXRoLnRydW5jKGJvdHRvbS5nZXRZKCkpKTtcbiAgICAgICAgICAgIC8vIGZsb2F0IGF2ZXJhZ2VSb3dIZWlnaHQgPSAobGFzdFJvdyAtIGZpcnN0Um93KSAvIC8qKGZsb2F0KSovIGJhcmNvZGVNZXRhZGF0YS5nZXRSb3dDb3VudCgpO1xuICAgICAgICAgICAgbGV0IGNvZGV3b3JkcyA9IHRoaXMuZ2V0Q29kZXdvcmRzKCk7XG4gICAgICAgICAgICBsZXQgYmFyY29kZVJvdyA9IC0xO1xuICAgICAgICAgICAgZm9yIChsZXQgY29kZXdvcmRzUm93IC8qaW50Ki8gPSBmaXJzdFJvdzsgY29kZXdvcmRzUm93IDwgbGFzdFJvdzsgY29kZXdvcmRzUm93KyspIHtcbiAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmRzW2NvZGV3b3Jkc1Jvd10gPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IGNvZGV3b3JkID0gY29kZXdvcmRzW2NvZGV3b3Jkc1Jvd107XG4gICAgICAgICAgICAgICAgY29kZXdvcmQuc2V0Um93TnVtYmVyQXNSb3dJbmRpY2F0b3JDb2x1bW4oKTtcbiAgICAgICAgICAgICAgICBsZXQgcm93RGlmZmVyZW5jZSA9IGNvZGV3b3JkLmdldFJvd051bWJlcigpIC0gYmFyY29kZVJvdztcbiAgICAgICAgICAgICAgICAvLyBUT0RPIGltcHJvdmUgaGFuZGxpbmcgd2l0aCBjYXNlIHdoZXJlIGZpcnN0IHJvdyBpbmRpY2F0b3IgZG9lc24ndCBzdGFydCB3aXRoIDBcbiAgICAgICAgICAgICAgICBpZiAocm93RGlmZmVyZW5jZSA9PT0gMCkgO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHJvd0RpZmZlcmVuY2UgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgYmFyY29kZVJvdyA9IGNvZGV3b3JkLmdldFJvd051bWJlcigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChjb2Rld29yZC5nZXRSb3dOdW1iZXIoKSA+PSBiYXJjb2RlTWV0YWRhdGEuZ2V0Um93Q291bnQoKSkge1xuICAgICAgICAgICAgICAgICAgICBjb2Rld29yZHNbY29kZXdvcmRzUm93XSA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBiYXJjb2RlUm93ID0gY29kZXdvcmQuZ2V0Um93TnVtYmVyKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gcmV0dXJuIChpbnQpIChhdmVyYWdlUm93SGVpZ2h0ICsgMC41KTtcbiAgICAgICAgfVxuICAgICAgICBnZXRCYXJjb2RlTWV0YWRhdGEoKSB7XG4gICAgICAgICAgICBsZXQgY29kZXdvcmRzID0gdGhpcy5nZXRDb2Rld29yZHMoKTtcbiAgICAgICAgICAgIGxldCBiYXJjb2RlQ29sdW1uQ291bnQgPSBuZXcgQmFyY29kZVZhbHVlKCk7XG4gICAgICAgICAgICBsZXQgYmFyY29kZVJvd0NvdW50VXBwZXJQYXJ0ID0gbmV3IEJhcmNvZGVWYWx1ZSgpO1xuICAgICAgICAgICAgbGV0IGJhcmNvZGVSb3dDb3VudExvd2VyUGFydCA9IG5ldyBCYXJjb2RlVmFsdWUoKTtcbiAgICAgICAgICAgIGxldCBiYXJjb2RlRUNMZXZlbCA9IG5ldyBCYXJjb2RlVmFsdWUoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGNvZGV3b3JkIC8qQ29kZXdvcmQqLyBvZiBjb2Rld29yZHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29kZXdvcmQuc2V0Um93TnVtYmVyQXNSb3dJbmRpY2F0b3JDb2x1bW4oKTtcbiAgICAgICAgICAgICAgICBsZXQgcm93SW5kaWNhdG9yVmFsdWUgPSBjb2Rld29yZC5nZXRWYWx1ZSgpICUgMzA7XG4gICAgICAgICAgICAgICAgbGV0IGNvZGV3b3JkUm93TnVtYmVyID0gY29kZXdvcmQuZ2V0Um93TnVtYmVyKCk7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9pc0xlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29kZXdvcmRSb3dOdW1iZXIgKz0gMjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3dpdGNoIChjb2Rld29yZFJvd051bWJlciAlIDMpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgYmFyY29kZVJvd0NvdW50VXBwZXJQYXJ0LnNldFZhbHVlKHJvd0luZGljYXRvclZhbHVlICogMyArIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIGJhcmNvZGVFQ0xldmVsLnNldFZhbHVlKHJvd0luZGljYXRvclZhbHVlIC8gMyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBiYXJjb2RlUm93Q291bnRMb3dlclBhcnQuc2V0VmFsdWUocm93SW5kaWNhdG9yVmFsdWUgJSAzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgICAgICBiYXJjb2RlQ29sdW1uQ291bnQuc2V0VmFsdWUocm93SW5kaWNhdG9yVmFsdWUgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE1heWJlIHdlIHNob3VsZCBjaGVjayBpZiB3ZSBoYXZlIGFtYmlndW91cyB2YWx1ZXM/XG4gICAgICAgICAgICBpZiAoKGJhcmNvZGVDb2x1bW5Db3VudC5nZXRWYWx1ZSgpLmxlbmd0aCA9PT0gMCkgfHxcbiAgICAgICAgICAgICAgICAoYmFyY29kZVJvd0NvdW50VXBwZXJQYXJ0LmdldFZhbHVlKCkubGVuZ3RoID09PSAwKSB8fFxuICAgICAgICAgICAgICAgIChiYXJjb2RlUm93Q291bnRMb3dlclBhcnQuZ2V0VmFsdWUoKS5sZW5ndGggPT09IDApIHx8XG4gICAgICAgICAgICAgICAgKGJhcmNvZGVFQ0xldmVsLmdldFZhbHVlKCkubGVuZ3RoID09PSAwKSB8fFxuICAgICAgICAgICAgICAgIGJhcmNvZGVDb2x1bW5Db3VudC5nZXRWYWx1ZSgpWzBdIDwgMSB8fFxuICAgICAgICAgICAgICAgIGJhcmNvZGVSb3dDb3VudFVwcGVyUGFydC5nZXRWYWx1ZSgpWzBdICsgYmFyY29kZVJvd0NvdW50TG93ZXJQYXJ0LmdldFZhbHVlKClbMF0gPCBQREY0MTdDb21tb24uTUlOX1JPV1NfSU5fQkFSQ09ERSB8fFxuICAgICAgICAgICAgICAgIGJhcmNvZGVSb3dDb3VudFVwcGVyUGFydC5nZXRWYWx1ZSgpWzBdICsgYmFyY29kZVJvd0NvdW50TG93ZXJQYXJ0LmdldFZhbHVlKClbMF0gPiBQREY0MTdDb21tb24uTUFYX1JPV1NfSU5fQkFSQ09ERSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGJhcmNvZGVNZXRhZGF0YSA9IG5ldyBCYXJjb2RlTWV0YWRhdGEoYmFyY29kZUNvbHVtbkNvdW50LmdldFZhbHVlKClbMF0sIGJhcmNvZGVSb3dDb3VudFVwcGVyUGFydC5nZXRWYWx1ZSgpWzBdLCBiYXJjb2RlUm93Q291bnRMb3dlclBhcnQuZ2V0VmFsdWUoKVswXSwgYmFyY29kZUVDTGV2ZWwuZ2V0VmFsdWUoKVswXSk7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZUluY29ycmVjdENvZGV3b3Jkcyhjb2Rld29yZHMsIGJhcmNvZGVNZXRhZGF0YSk7XG4gICAgICAgICAgICByZXR1cm4gYmFyY29kZU1ldGFkYXRhO1xuICAgICAgICB9XG4gICAgICAgIHJlbW92ZUluY29ycmVjdENvZGV3b3Jkcyhjb2Rld29yZHMsIGJhcmNvZGVNZXRhZGF0YSkge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGNvZGV3b3JkcyB3aGljaCBkbyBub3QgbWF0Y2ggdGhlIG1ldGFkYXRhXG4gICAgICAgICAgICAvLyBUT0RPIE1heWJlIHdlIHNob3VsZCBrZWVwIHRoZSBpbmNvcnJlY3QgY29kZXdvcmRzIGZvciB0aGUgc3RhcnQgYW5kIGVuZCBwb3NpdGlvbnM/XG4gICAgICAgICAgICBmb3IgKGxldCBjb2Rld29yZFJvdyAvKmludCovID0gMDsgY29kZXdvcmRSb3cgPCBjb2Rld29yZHMubGVuZ3RoOyBjb2Rld29yZFJvdysrKSB7XG4gICAgICAgICAgICAgICAgbGV0IGNvZGV3b3JkID0gY29kZXdvcmRzW2NvZGV3b3JkUm93XTtcbiAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmRzW2NvZGV3b3JkUm93XSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgcm93SW5kaWNhdG9yVmFsdWUgPSBjb2Rld29yZC5nZXRWYWx1ZSgpICUgMzA7XG4gICAgICAgICAgICAgICAgbGV0IGNvZGV3b3JkUm93TnVtYmVyID0gY29kZXdvcmQuZ2V0Um93TnVtYmVyKCk7XG4gICAgICAgICAgICAgICAgaWYgKGNvZGV3b3JkUm93TnVtYmVyID4gYmFyY29kZU1ldGFkYXRhLmdldFJvd0NvdW50KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29kZXdvcmRzW2NvZGV3b3JkUm93XSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX2lzTGVmdCkge1xuICAgICAgICAgICAgICAgICAgICBjb2Rld29yZFJvd051bWJlciArPSAyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGNvZGV3b3JkUm93TnVtYmVyICUgMykge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocm93SW5kaWNhdG9yVmFsdWUgKiAzICsgMSAhPT0gYmFyY29kZU1ldGFkYXRhLmdldFJvd0NvdW50VXBwZXJQYXJ0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2Rld29yZHNbY29kZXdvcmRSb3ddID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoTWF0aC50cnVuYyhyb3dJbmRpY2F0b3JWYWx1ZSAvIDMpICE9PSBiYXJjb2RlTWV0YWRhdGEuZ2V0RXJyb3JDb3JyZWN0aW9uTGV2ZWwoKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvd0luZGljYXRvclZhbHVlICUgMyAhPT0gYmFyY29kZU1ldGFkYXRhLmdldFJvd0NvdW50TG93ZXJQYXJ0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2Rld29yZHNbY29kZXdvcmRSb3ddID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocm93SW5kaWNhdG9yVmFsdWUgKyAxICE9PSBiYXJjb2RlTWV0YWRhdGEuZ2V0Q29sdW1uQ291bnQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGV3b3Jkc1tjb2Rld29yZFJvd10gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlzTGVmdCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9pc0xlZnQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgcmV0dXJuICdJc0xlZnQ6ICcgKyB0aGlzLl9pc0xlZnQgKyAnXFxuJyArIHN1cGVyLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDEzIFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIEBhdXRob3IgR3VlbnRoZXIgR3JhdVxuICAgICAqL1xuICAgIC8qZmluYWwqLyBjbGFzcyBEZXRlY3Rpb25SZXN1bHQge1xuICAgICAgICBjb25zdHJ1Y3RvcihiYXJjb2RlTWV0YWRhdGEsIGJvdW5kaW5nQm94KSB7XG4gICAgICAgICAgICAvKmZpbmFsKi8gdGhpcy5BREpVU1RfUk9XX05VTUJFUl9TS0lQID0gMjtcbiAgICAgICAgICAgIHRoaXMuYmFyY29kZU1ldGFkYXRhID0gYmFyY29kZU1ldGFkYXRhO1xuICAgICAgICAgICAgdGhpcy5iYXJjb2RlQ29sdW1uQ291bnQgPSBiYXJjb2RlTWV0YWRhdGEuZ2V0Q29sdW1uQ291bnQoKTtcbiAgICAgICAgICAgIHRoaXMuYm91bmRpbmdCb3ggPSBib3VuZGluZ0JveDtcbiAgICAgICAgICAgIC8vIHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1ucyA9IG5ldyBEZXRlY3Rpb25SZXN1bHRDb2x1bW5bdGhpcy5iYXJjb2RlQ29sdW1uQ291bnQgKyAyXTtcbiAgICAgICAgICAgIHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1ucyA9IG5ldyBBcnJheSh0aGlzLmJhcmNvZGVDb2x1bW5Db3VudCArIDIpO1xuICAgICAgICB9XG4gICAgICAgIGdldERldGVjdGlvblJlc3VsdENvbHVtbnMoKSB7XG4gICAgICAgICAgICB0aGlzLmFkanVzdEluZGljYXRvckNvbHVtblJvd051bWJlcnModGhpcy5kZXRlY3Rpb25SZXN1bHRDb2x1bW5zWzBdKTtcbiAgICAgICAgICAgIHRoaXMuYWRqdXN0SW5kaWNhdG9yQ29sdW1uUm93TnVtYmVycyh0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbdGhpcy5iYXJjb2RlQ29sdW1uQ291bnQgKyAxXSk7XG4gICAgICAgICAgICBsZXQgdW5hZGp1c3RlZENvZGV3b3JkQ291bnQgPSBQREY0MTdDb21tb24uTUFYX0NPREVXT1JEU19JTl9CQVJDT0RFO1xuICAgICAgICAgICAgbGV0IHByZXZpb3VzVW5hZGp1c3RlZENvdW50O1xuICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgIHByZXZpb3VzVW5hZGp1c3RlZENvdW50ID0gdW5hZGp1c3RlZENvZGV3b3JkQ291bnQ7XG4gICAgICAgICAgICAgICAgdW5hZGp1c3RlZENvZGV3b3JkQ291bnQgPSB0aGlzLmFkanVzdFJvd051bWJlcnNBbmRHZXRDb3VudCgpO1xuICAgICAgICAgICAgfSB3aGlsZSAodW5hZGp1c3RlZENvZGV3b3JkQ291bnQgPiAwICYmIHVuYWRqdXN0ZWRDb2Rld29yZENvdW50IDwgcHJldmlvdXNVbmFkanVzdGVkQ291bnQpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1ucztcbiAgICAgICAgfVxuICAgICAgICBhZGp1c3RJbmRpY2F0b3JDb2x1bW5Sb3dOdW1iZXJzKGRldGVjdGlvblJlc3VsdENvbHVtbikge1xuICAgICAgICAgICAgaWYgKGRldGVjdGlvblJlc3VsdENvbHVtbiAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgZGV0ZWN0aW9uUmVzdWx0Q29sdW1uXG4gICAgICAgICAgICAgICAgICAgIC5hZGp1c3RDb21wbGV0ZUluZGljYXRvckNvbHVtblJvd051bWJlcnModGhpcy5iYXJjb2RlTWV0YWRhdGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIFRPRE8gZW5zdXJlIHRoYXQgbm8gZGV0ZWN0ZWQgY29kZXdvcmRzIHdpdGggdW5rbm93biByb3cgbnVtYmVyIGFyZSBsZWZ0XG4gICAgICAgIC8vIHdlIHNob3VsZCBiZSBhYmxlIHRvIGVzdGltYXRlIHRoZSByb3cgaGVpZ2h0IGFuZCB1c2UgaXQgYXMgYSBoaW50IGZvciB0aGUgcm93IG51bWJlclxuICAgICAgICAvLyB3ZSBzaG91bGQgYWxzbyBmaWxsIHRoZSByb3dzIHRvcCB0byBib3R0b20gYW5kIGJvdHRvbSB0byB0b3BcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gbnVtYmVyIG9mIGNvZGV3b3JkcyB3aGljaCBkb24ndCBoYXZlIGEgdmFsaWQgcm93IG51bWJlci4gTm90ZSB0aGF0IHRoZSBjb3VudCBpcyBub3QgYWNjdXJhdGUgYXMgY29kZXdvcmRzXG4gICAgICAgICAqIHdpbGwgYmUgY291bnRlZCBzZXZlcmFsIHRpbWVzLiBJdCBqdXN0IHNlcnZlcyBhcyBhbiBpbmRpY2F0b3IgdG8gc2VlIHdoZW4gd2UgY2FuIHN0b3AgYWRqdXN0aW5nIHJvdyBudW1iZXJzXG4gICAgICAgICAqL1xuICAgICAgICBhZGp1c3RSb3dOdW1iZXJzQW5kR2V0Q291bnQoKSB7XG4gICAgICAgICAgICBsZXQgdW5hZGp1c3RlZENvdW50ID0gdGhpcy5hZGp1c3RSb3dOdW1iZXJzQnlSb3coKTtcbiAgICAgICAgICAgIGlmICh1bmFkanVzdGVkQ291bnQgPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAobGV0IGJhcmNvZGVDb2x1bW4gLyppbnQqLyA9IDE7IGJhcmNvZGVDb2x1bW4gPCB0aGlzLmJhcmNvZGVDb2x1bW5Db3VudCArIDE7IGJhcmNvZGVDb2x1bW4rKykge1xuICAgICAgICAgICAgICAgIGxldCBjb2Rld29yZHMgPSB0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbYmFyY29kZUNvbHVtbl0uZ2V0Q29kZXdvcmRzKCk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgY29kZXdvcmRzUm93IC8qaW50Ki8gPSAwOyBjb2Rld29yZHNSb3cgPCBjb2Rld29yZHMubGVuZ3RoOyBjb2Rld29yZHNSb3crKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmRzW2NvZGV3b3Jkc1Jvd10gPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb2Rld29yZHNbY29kZXdvcmRzUm93XS5oYXNWYWxpZFJvd051bWJlcigpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkanVzdFJvd051bWJlcnMoYmFyY29kZUNvbHVtbiwgY29kZXdvcmRzUm93LCBjb2Rld29yZHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHVuYWRqdXN0ZWRDb3VudDtcbiAgICAgICAgfVxuICAgICAgICBhZGp1c3RSb3dOdW1iZXJzQnlSb3coKSB7XG4gICAgICAgICAgICB0aGlzLmFkanVzdFJvd051bWJlcnNGcm9tQm90aFJJKCk7XG4gICAgICAgICAgICAvLyBUT0RPIHdlIHNob3VsZCBvbmx5IGRvIGZ1bGwgcm93IGFkanVzdG1lbnRzIGlmIHJvdyBudW1iZXJzIG9mIGxlZnQgYW5kIHJpZ2h0IHJvdyBpbmRpY2F0b3IgY29sdW1uIG1hdGNoLlxuICAgICAgICAgICAgLy8gTWF5YmUgaXQncyBldmVuIGJldHRlciB0byBjYWxjdWxhdGVkIHRoZSBoZWlnaHQgKHJvd3M6IGQpIGFuZCBkaXZpZGUgaXQgYnkgdGhlIG51bWJlciBvZiBiYXJjb2RlXG4gICAgICAgICAgICAvLyByb3dzLiBUaGlzLCB0b2dldGhlciB3aXRoIHRoZSBMUkkgYW5kIFJSSSByb3cgbnVtYmVycyBzaG91bGQgYWxsb3cgdXMgdG8gZ2V0IGEgZ29vZCBlc3RpbWF0ZSB3aGVyZSBhIHJvd1xuICAgICAgICAgICAgLy8gbnVtYmVyIHN0YXJ0cyBhbmQgZW5kcy5cbiAgICAgICAgICAgIGxldCB1bmFkanVzdGVkQ291bnQgPSB0aGlzLmFkanVzdFJvd051bWJlcnNGcm9tTFJJKCk7XG4gICAgICAgICAgICByZXR1cm4gdW5hZGp1c3RlZENvdW50ICsgdGhpcy5hZGp1c3RSb3dOdW1iZXJzRnJvbVJSSSgpO1xuICAgICAgICB9XG4gICAgICAgIGFkanVzdFJvd051bWJlcnNGcm9tQm90aFJJKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1swXSA9PSBudWxsIHx8IHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1t0aGlzLmJhcmNvZGVDb2x1bW5Db3VudCArIDFdID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgTFJJY29kZXdvcmRzID0gdGhpcy5kZXRlY3Rpb25SZXN1bHRDb2x1bW5zWzBdLmdldENvZGV3b3JkcygpO1xuICAgICAgICAgICAgbGV0IFJSSWNvZGV3b3JkcyA9IHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1t0aGlzLmJhcmNvZGVDb2x1bW5Db3VudCArIDFdLmdldENvZGV3b3JkcygpO1xuICAgICAgICAgICAgZm9yIChsZXQgY29kZXdvcmRzUm93IC8qaW50Ki8gPSAwOyBjb2Rld29yZHNSb3cgPCBMUkljb2Rld29yZHMubGVuZ3RoOyBjb2Rld29yZHNSb3crKykge1xuICAgICAgICAgICAgICAgIGlmIChMUkljb2Rld29yZHNbY29kZXdvcmRzUm93XSAhPSBudWxsICYmXG4gICAgICAgICAgICAgICAgICAgIFJSSWNvZGV3b3Jkc1tjb2Rld29yZHNSb3ddICE9IG51bGwgJiZcbiAgICAgICAgICAgICAgICAgICAgTFJJY29kZXdvcmRzW2NvZGV3b3Jkc1Jvd10uZ2V0Um93TnVtYmVyKCkgPT09IFJSSWNvZGV3b3Jkc1tjb2Rld29yZHNSb3ddLmdldFJvd051bWJlcigpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGJhcmNvZGVDb2x1bW4gLyppbnQqLyA9IDE7IGJhcmNvZGVDb2x1bW4gPD0gdGhpcy5iYXJjb2RlQ29sdW1uQ291bnQ7IGJhcmNvZGVDb2x1bW4rKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNvZGV3b3JkID0gdGhpcy5kZXRlY3Rpb25SZXN1bHRDb2x1bW5zW2JhcmNvZGVDb2x1bW5dLmdldENvZGV3b3JkcygpW2NvZGV3b3Jkc1Jvd107XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY29kZXdvcmQuc2V0Um93TnVtYmVyKExSSWNvZGV3b3Jkc1tjb2Rld29yZHNSb3ddLmdldFJvd051bWJlcigpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29kZXdvcmQuaGFzVmFsaWRSb3dOdW1iZXIoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1tiYXJjb2RlQ29sdW1uXS5nZXRDb2Rld29yZHMoKVtjb2Rld29yZHNSb3ddID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBhZGp1c3RSb3dOdW1iZXJzRnJvbVJSSSgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbdGhpcy5iYXJjb2RlQ29sdW1uQ291bnQgKyAxXSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgdW5hZGp1c3RlZENvdW50ID0gMDtcbiAgICAgICAgICAgIGxldCBjb2Rld29yZHMgPSB0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbdGhpcy5iYXJjb2RlQ29sdW1uQ291bnQgKyAxXS5nZXRDb2Rld29yZHMoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGNvZGV3b3Jkc1JvdyAvKmludCovID0gMDsgY29kZXdvcmRzUm93IDwgY29kZXdvcmRzLmxlbmd0aDsgY29kZXdvcmRzUm93KyspIHtcbiAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmRzW2NvZGV3b3Jkc1Jvd10gPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IHJvd0luZGljYXRvclJvd051bWJlciA9IGNvZGV3b3Jkc1tjb2Rld29yZHNSb3ddLmdldFJvd051bWJlcigpO1xuICAgICAgICAgICAgICAgIGxldCBpbnZhbGlkUm93Q291bnRzID0gMDtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBiYXJjb2RlQ29sdW1uIC8qaW50Ki8gPSB0aGlzLmJhcmNvZGVDb2x1bW5Db3VudCArIDE7IGJhcmNvZGVDb2x1bW4gPiAwICYmIGludmFsaWRSb3dDb3VudHMgPCB0aGlzLkFESlVTVF9ST1dfTlVNQkVSX1NLSVA7IGJhcmNvZGVDb2x1bW4tLSkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgY29kZXdvcmQgPSB0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbYmFyY29kZUNvbHVtbl0uZ2V0Q29kZXdvcmRzKClbY29kZXdvcmRzUm93XTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvZGV3b3JkICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGludmFsaWRSb3dDb3VudHMgPSBEZXRlY3Rpb25SZXN1bHQuYWRqdXN0Um93TnVtYmVySWZWYWxpZChyb3dJbmRpY2F0b3JSb3dOdW1iZXIsIGludmFsaWRSb3dDb3VudHMsIGNvZGV3b3JkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29kZXdvcmQuaGFzVmFsaWRSb3dOdW1iZXIoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuYWRqdXN0ZWRDb3VudCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHVuYWRqdXN0ZWRDb3VudDtcbiAgICAgICAgfVxuICAgICAgICBhZGp1c3RSb3dOdW1iZXJzRnJvbUxSSSgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbMF0gPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHVuYWRqdXN0ZWRDb3VudCA9IDA7XG4gICAgICAgICAgICBsZXQgY29kZXdvcmRzID0gdGhpcy5kZXRlY3Rpb25SZXN1bHRDb2x1bW5zWzBdLmdldENvZGV3b3JkcygpO1xuICAgICAgICAgICAgZm9yIChsZXQgY29kZXdvcmRzUm93IC8qaW50Ki8gPSAwOyBjb2Rld29yZHNSb3cgPCBjb2Rld29yZHMubGVuZ3RoOyBjb2Rld29yZHNSb3crKykge1xuICAgICAgICAgICAgICAgIGlmIChjb2Rld29yZHNbY29kZXdvcmRzUm93XSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgcm93SW5kaWNhdG9yUm93TnVtYmVyID0gY29kZXdvcmRzW2NvZGV3b3Jkc1Jvd10uZ2V0Um93TnVtYmVyKCk7XG4gICAgICAgICAgICAgICAgbGV0IGludmFsaWRSb3dDb3VudHMgPSAwO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGJhcmNvZGVDb2x1bW4gLyppbnQqLyA9IDE7IGJhcmNvZGVDb2x1bW4gPCB0aGlzLmJhcmNvZGVDb2x1bW5Db3VudCArIDEgJiYgaW52YWxpZFJvd0NvdW50cyA8IHRoaXMuQURKVVNUX1JPV19OVU1CRVJfU0tJUDsgYmFyY29kZUNvbHVtbisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBjb2Rld29yZCA9IHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1tiYXJjb2RlQ29sdW1uXS5nZXRDb2Rld29yZHMoKVtjb2Rld29yZHNSb3ddO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW52YWxpZFJvd0NvdW50cyA9IERldGVjdGlvblJlc3VsdC5hZGp1c3RSb3dOdW1iZXJJZlZhbGlkKHJvd0luZGljYXRvclJvd051bWJlciwgaW52YWxpZFJvd0NvdW50cywgY29kZXdvcmQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjb2Rld29yZC5oYXNWYWxpZFJvd051bWJlcigpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5hZGp1c3RlZENvdW50Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdW5hZGp1c3RlZENvdW50O1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBhZGp1c3RSb3dOdW1iZXJJZlZhbGlkKHJvd0luZGljYXRvclJvd051bWJlciwgaW52YWxpZFJvd0NvdW50cywgY29kZXdvcmQpIHtcbiAgICAgICAgICAgIGlmIChjb2Rld29yZCA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGludmFsaWRSb3dDb3VudHM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWNvZGV3b3JkLmhhc1ZhbGlkUm93TnVtYmVyKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmQuaXNWYWxpZFJvd051bWJlcihyb3dJbmRpY2F0b3JSb3dOdW1iZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvZGV3b3JkLnNldFJvd051bWJlcihyb3dJbmRpY2F0b3JSb3dOdW1iZXIpO1xuICAgICAgICAgICAgICAgICAgICBpbnZhbGlkUm93Q291bnRzID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICsraW52YWxpZFJvd0NvdW50cztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaW52YWxpZFJvd0NvdW50cztcbiAgICAgICAgfVxuICAgICAgICBhZGp1c3RSb3dOdW1iZXJzKGJhcmNvZGVDb2x1bW4sIGNvZGV3b3Jkc1JvdywgY29kZXdvcmRzKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1tiYXJjb2RlQ29sdW1uIC0gMV0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgY29kZXdvcmQgPSBjb2Rld29yZHNbY29kZXdvcmRzUm93XTtcbiAgICAgICAgICAgIGxldCBwcmV2aW91c0NvbHVtbkNvZGV3b3JkcyA9IHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1tiYXJjb2RlQ29sdW1uIC0gMV0uZ2V0Q29kZXdvcmRzKCk7XG4gICAgICAgICAgICBsZXQgbmV4dENvbHVtbkNvZGV3b3JkcyA9IHByZXZpb3VzQ29sdW1uQ29kZXdvcmRzO1xuICAgICAgICAgICAgaWYgKHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1tiYXJjb2RlQ29sdW1uICsgMV0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIG5leHRDb2x1bW5Db2Rld29yZHMgPSB0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbYmFyY29kZUNvbHVtbiArIDFdLmdldENvZGV3b3JkcygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gbGV0IG90aGVyQ29kZXdvcmRzOiBDb2Rld29yZFtdID0gbmV3IENvZGV3b3JkWzE0XTtcbiAgICAgICAgICAgIGxldCBvdGhlckNvZGV3b3JkcyA9IG5ldyBBcnJheSgxNCk7XG4gICAgICAgICAgICBvdGhlckNvZGV3b3Jkc1syXSA9IHByZXZpb3VzQ29sdW1uQ29kZXdvcmRzW2NvZGV3b3Jkc1Jvd107XG4gICAgICAgICAgICBvdGhlckNvZGV3b3Jkc1szXSA9IG5leHRDb2x1bW5Db2Rld29yZHNbY29kZXdvcmRzUm93XTtcbiAgICAgICAgICAgIGlmIChjb2Rld29yZHNSb3cgPiAwKSB7XG4gICAgICAgICAgICAgICAgb3RoZXJDb2Rld29yZHNbMF0gPSBjb2Rld29yZHNbY29kZXdvcmRzUm93IC0gMV07XG4gICAgICAgICAgICAgICAgb3RoZXJDb2Rld29yZHNbNF0gPSBwcmV2aW91c0NvbHVtbkNvZGV3b3Jkc1tjb2Rld29yZHNSb3cgLSAxXTtcbiAgICAgICAgICAgICAgICBvdGhlckNvZGV3b3Jkc1s1XSA9IG5leHRDb2x1bW5Db2Rld29yZHNbY29kZXdvcmRzUm93IC0gMV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29kZXdvcmRzUm93ID4gMSkge1xuICAgICAgICAgICAgICAgIG90aGVyQ29kZXdvcmRzWzhdID0gY29kZXdvcmRzW2NvZGV3b3Jkc1JvdyAtIDJdO1xuICAgICAgICAgICAgICAgIG90aGVyQ29kZXdvcmRzWzEwXSA9IHByZXZpb3VzQ29sdW1uQ29kZXdvcmRzW2NvZGV3b3Jkc1JvdyAtIDJdO1xuICAgICAgICAgICAgICAgIG90aGVyQ29kZXdvcmRzWzExXSA9IG5leHRDb2x1bW5Db2Rld29yZHNbY29kZXdvcmRzUm93IC0gMl07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29kZXdvcmRzUm93IDwgY29kZXdvcmRzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICBvdGhlckNvZGV3b3Jkc1sxXSA9IGNvZGV3b3Jkc1tjb2Rld29yZHNSb3cgKyAxXTtcbiAgICAgICAgICAgICAgICBvdGhlckNvZGV3b3Jkc1s2XSA9IHByZXZpb3VzQ29sdW1uQ29kZXdvcmRzW2NvZGV3b3Jkc1JvdyArIDFdO1xuICAgICAgICAgICAgICAgIG90aGVyQ29kZXdvcmRzWzddID0gbmV4dENvbHVtbkNvZGV3b3Jkc1tjb2Rld29yZHNSb3cgKyAxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjb2Rld29yZHNSb3cgPCBjb2Rld29yZHMubGVuZ3RoIC0gMikge1xuICAgICAgICAgICAgICAgIG90aGVyQ29kZXdvcmRzWzldID0gY29kZXdvcmRzW2NvZGV3b3Jkc1JvdyArIDJdO1xuICAgICAgICAgICAgICAgIG90aGVyQ29kZXdvcmRzWzEyXSA9IHByZXZpb3VzQ29sdW1uQ29kZXdvcmRzW2NvZGV3b3Jkc1JvdyArIDJdO1xuICAgICAgICAgICAgICAgIG90aGVyQ29kZXdvcmRzWzEzXSA9IG5leHRDb2x1bW5Db2Rld29yZHNbY29kZXdvcmRzUm93ICsgMl07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBvdGhlckNvZGV3b3JkIG9mIG90aGVyQ29kZXdvcmRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKERldGVjdGlvblJlc3VsdC5hZGp1c3RSb3dOdW1iZXIoY29kZXdvcmQsIG90aGVyQ29kZXdvcmQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gdHJ1ZSwgaWYgcm93IG51bWJlciB3YXMgYWRqdXN0ZWQsIGZhbHNlIG90aGVyd2lzZVxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGFkanVzdFJvd051bWJlcihjb2Rld29yZCwgb3RoZXJDb2Rld29yZCkge1xuICAgICAgICAgICAgaWYgKG90aGVyQ29kZXdvcmQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvdGhlckNvZGV3b3JkLmhhc1ZhbGlkUm93TnVtYmVyKCkgJiYgb3RoZXJDb2Rld29yZC5nZXRCdWNrZXQoKSA9PT0gY29kZXdvcmQuZ2V0QnVja2V0KCkpIHtcbiAgICAgICAgICAgICAgICBjb2Rld29yZC5zZXRSb3dOdW1iZXIob3RoZXJDb2Rld29yZC5nZXRSb3dOdW1iZXIoKSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0QmFyY29kZUNvbHVtbkNvdW50KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmFyY29kZUNvbHVtbkNvdW50O1xuICAgICAgICB9XG4gICAgICAgIGdldEJhcmNvZGVSb3dDb3VudCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJhcmNvZGVNZXRhZGF0YS5nZXRSb3dDb3VudCgpO1xuICAgICAgICB9XG4gICAgICAgIGdldEJhcmNvZGVFQ0xldmVsKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmFyY29kZU1ldGFkYXRhLmdldEVycm9yQ29ycmVjdGlvbkxldmVsKCk7XG4gICAgICAgIH1cbiAgICAgICAgc2V0Qm91bmRpbmdCb3goYm91bmRpbmdCb3gpIHtcbiAgICAgICAgICAgIHRoaXMuYm91bmRpbmdCb3ggPSBib3VuZGluZ0JveDtcbiAgICAgICAgfVxuICAgICAgICBnZXRCb3VuZGluZ0JveCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJvdW5kaW5nQm94O1xuICAgICAgICB9XG4gICAgICAgIHNldERldGVjdGlvblJlc3VsdENvbHVtbihiYXJjb2RlQ29sdW1uLCBkZXRlY3Rpb25SZXN1bHRDb2x1bW4pIHtcbiAgICAgICAgICAgIHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1tiYXJjb2RlQ29sdW1uXSA9IGRldGVjdGlvblJlc3VsdENvbHVtbjtcbiAgICAgICAgfVxuICAgICAgICBnZXREZXRlY3Rpb25SZXN1bHRDb2x1bW4oYmFyY29kZUNvbHVtbikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1tiYXJjb2RlQ29sdW1uXTtcbiAgICAgICAgfVxuICAgICAgICAvLyBAT3ZlcnJpZGVcbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICBsZXQgcm93SW5kaWNhdG9yQ29sdW1uID0gdGhpcy5kZXRlY3Rpb25SZXN1bHRDb2x1bW5zWzBdO1xuICAgICAgICAgICAgaWYgKHJvd0luZGljYXRvckNvbHVtbiA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcm93SW5kaWNhdG9yQ29sdW1uID0gdGhpcy5kZXRlY3Rpb25SZXN1bHRDb2x1bW5zW3RoaXMuYmFyY29kZUNvbHVtbkNvdW50ICsgMV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyB0cnkgKFxuICAgICAgICAgICAgbGV0IGZvcm1hdHRlciA9IG5ldyBGb3JtYXR0ZXIoKTtcbiAgICAgICAgICAgIC8vICkge1xuICAgICAgICAgICAgZm9yIChsZXQgY29kZXdvcmRzUm93IC8qaW50Ki8gPSAwOyBjb2Rld29yZHNSb3cgPCByb3dJbmRpY2F0b3JDb2x1bW4uZ2V0Q29kZXdvcmRzKCkubGVuZ3RoOyBjb2Rld29yZHNSb3crKykge1xuICAgICAgICAgICAgICAgIGZvcm1hdHRlci5mb3JtYXQoJ0NXICUzZDonLCBjb2Rld29yZHNSb3cpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGJhcmNvZGVDb2x1bW4gLyppbnQqLyA9IDA7IGJhcmNvZGVDb2x1bW4gPCB0aGlzLmJhcmNvZGVDb2x1bW5Db3VudCArIDI7IGJhcmNvZGVDb2x1bW4rKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kZXRlY3Rpb25SZXN1bHRDb2x1bW5zW2JhcmNvZGVDb2x1bW5dID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1hdHRlci5mb3JtYXQoJyAgICB8ICAgJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBsZXQgY29kZXdvcmQgPSB0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbYmFyY29kZUNvbHVtbl0uZ2V0Q29kZXdvcmRzKClbY29kZXdvcmRzUm93XTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvZGV3b3JkID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1hdHRlci5mb3JtYXQoJyAgICB8ICAgJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBmb3JtYXR0ZXIuZm9ybWF0KCcgJTNkfCUzZCcsIGNvZGV3b3JkLmdldFJvd051bWJlcigpLCBjb2Rld29yZC5nZXRWYWx1ZSgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZm9ybWF0dGVyLmZvcm1hdCgnJW4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmb3JtYXR0ZXIudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIC8vIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMTMgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLy8gcGFja2FnZSBjb20uZ29vZ2xlLnp4aW5nLnBkZjQxNy5kZWNvZGVyO1xuICAgIC8qKlxuICAgICAqIEBhdXRob3IgR3VlbnRoZXIgR3JhdVxuICAgICAqL1xuICAgIC8qZmluYWwqLyBjbGFzcyBDb2Rld29yZCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHN0YXJ0WCwgZW5kWCwgYnVja2V0LCB2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5yb3dOdW1iZXIgPSBDb2Rld29yZC5CQVJDT0RFX1JPV19VTktOT1dOO1xuICAgICAgICAgICAgdGhpcy5zdGFydFggPSBNYXRoLnRydW5jKHN0YXJ0WCk7XG4gICAgICAgICAgICB0aGlzLmVuZFggPSBNYXRoLnRydW5jKGVuZFgpO1xuICAgICAgICAgICAgdGhpcy5idWNrZXQgPSBNYXRoLnRydW5jKGJ1Y2tldCk7XG4gICAgICAgICAgICB0aGlzLnZhbHVlID0gTWF0aC50cnVuYyh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgaGFzVmFsaWRSb3dOdW1iZXIoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5pc1ZhbGlkUm93TnVtYmVyKHRoaXMucm93TnVtYmVyKTtcbiAgICAgICAgfVxuICAgICAgICBpc1ZhbGlkUm93TnVtYmVyKHJvd051bWJlcikge1xuICAgICAgICAgICAgcmV0dXJuIHJvd051bWJlciAhPT0gQ29kZXdvcmQuQkFSQ09ERV9ST1dfVU5LTk9XTiAmJiB0aGlzLmJ1Y2tldCA9PT0gKHJvd051bWJlciAlIDMpICogMztcbiAgICAgICAgfVxuICAgICAgICBzZXRSb3dOdW1iZXJBc1Jvd0luZGljYXRvckNvbHVtbigpIHtcbiAgICAgICAgICAgIHRoaXMucm93TnVtYmVyID0gTWF0aC50cnVuYygoTWF0aC50cnVuYyh0aGlzLnZhbHVlIC8gMzApKSAqIDMgKyBNYXRoLnRydW5jKHRoaXMuYnVja2V0IC8gMykpO1xuICAgICAgICB9XG4gICAgICAgIGdldFdpZHRoKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5kWCAtIHRoaXMuc3RhcnRYO1xuICAgICAgICB9XG4gICAgICAgIGdldFN0YXJ0WCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0YXJ0WDtcbiAgICAgICAgfVxuICAgICAgICBnZXRFbmRYKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5kWDtcbiAgICAgICAgfVxuICAgICAgICBnZXRCdWNrZXQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5idWNrZXQ7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0VmFsdWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRSb3dOdW1iZXIoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yb3dOdW1iZXI7XG4gICAgICAgIH1cbiAgICAgICAgc2V0Um93TnVtYmVyKHJvd051bWJlcikge1xuICAgICAgICAgICAgdGhpcy5yb3dOdW1iZXIgPSByb3dOdW1iZXI7XG4gICAgICAgIH1cbiAgICAgICAgLy8gICBAT3ZlcnJpZGVcbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yb3dOdW1iZXIgKyAnfCcgKyB0aGlzLnZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIENvZGV3b3JkLkJBUkNPREVfUk9XX1VOS05PV04gPSAtMTtcblxuICAgIC8qXG4gICAgKiBDb3B5cmlnaHQgMjAxMyBaWGluZyBhdXRob3JzXG4gICAgKlxuICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICpcbiAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgKlxuICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAqL1xuICAgIC8qKlxuICAgICAqIEBhdXRob3IgR3VlbnRoZXIgR3JhdVxuICAgICAqIEBhdXRob3IgY3JlYXRhbGUgR21iSCAoY2hyaXN0b3BoLnNjaHVsekBjcmVhdGFsZS5kZSlcbiAgICAgKi9cbiAgICAvKmZpbmFsKi8gY2xhc3MgUERGNDE3Q29kZXdvcmREZWNvZGVyIHtcbiAgICAgICAgLyogQG5vdGVcbiAgICAgICAgICogdGhpcyBhY3Rpb24gaGF2ZSB0byBiZSBwZXJmb3JtZWQgYmVmb3JlIGZpcnN0IHVzZSBvZiBjbGFzc1xuICAgICAgICAgKiAtIHN0YXRpYyBjb25zdHJ1Y3RvclxuICAgICAgICAgKiB3b3JraW5nIHdpdGggMzJiaXQgZmxvYXQgKGJhc2VkIGZyb20gSmF2YSBsb2dpYylcbiAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGluaXRpYWxpemUoKSB7XG4gICAgICAgICAgICAvLyBQcmUtY29tcHV0ZXMgdGhlIHN5bWJvbCByYXRpbyB0YWJsZS5cbiAgICAgICAgICAgIGZvciAoIC8qaW50Ki9sZXQgaSA9IDA7IGkgPCBQREY0MTdDb21tb24uU1lNQk9MX1RBQkxFLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IGN1cnJlbnRTeW1ib2wgPSBQREY0MTdDb21tb24uU1lNQk9MX1RBQkxFW2ldO1xuICAgICAgICAgICAgICAgIGxldCBjdXJyZW50Qml0ID0gY3VycmVudFN5bWJvbCAmIDB4MTtcbiAgICAgICAgICAgICAgICBmb3IgKCAvKmludCovbGV0IGogPSAwOyBqIDwgUERGNDE3Q29tbW9uLkJBUlNfSU5fTU9EVUxFOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHNpemUgPSAwLjA7XG4gICAgICAgICAgICAgICAgICAgIHdoaWxlICgoY3VycmVudFN5bWJvbCAmIDB4MSkgPT09IGN1cnJlbnRCaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgKz0gMS4wO1xuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFN5bWJvbCA+Pj0gMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50Qml0ID0gY3VycmVudFN5bWJvbCAmIDB4MTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFQREY0MTdDb2Rld29yZERlY29kZXIuUkFUSU9TX1RBQkxFW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBQREY0MTdDb2Rld29yZERlY29kZXIuUkFUSU9TX1RBQkxFW2ldID0gbmV3IEFycmF5KFBERjQxN0NvbW1vbi5CQVJTX0lOX01PRFVMRSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgUERGNDE3Q29kZXdvcmREZWNvZGVyLlJBVElPU19UQUJMRVtpXVtQREY0MTdDb21tb24uQkFSU19JTl9NT0RVTEUgLSBqIC0gMV0gPSBNYXRoLmZyb3VuZChzaXplIC8gUERGNDE3Q29tbW9uLk1PRFVMRVNfSU5fQ09ERVdPUkQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuYlN5bWJvbFRhYmxlUmVhZHkgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXREZWNvZGVkVmFsdWUobW9kdWxlQml0Q291bnQpIHtcbiAgICAgICAgICAgIGxldCBkZWNvZGVkVmFsdWUgPSBQREY0MTdDb2Rld29yZERlY29kZXIuZ2V0RGVjb2RlZENvZGV3b3JkVmFsdWUoUERGNDE3Q29kZXdvcmREZWNvZGVyLnNhbXBsZUJpdENvdW50cyhtb2R1bGVCaXRDb3VudCkpO1xuICAgICAgICAgICAgaWYgKGRlY29kZWRWYWx1ZSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGVjb2RlZFZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIFBERjQxN0NvZGV3b3JkRGVjb2Rlci5nZXRDbG9zZXN0RGVjb2RlZFZhbHVlKG1vZHVsZUJpdENvdW50KTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgc2FtcGxlQml0Q291bnRzKG1vZHVsZUJpdENvdW50KSB7XG4gICAgICAgICAgICBsZXQgYml0Q291bnRTdW0gPSBNYXRoVXRpbHMuc3VtKG1vZHVsZUJpdENvdW50KTtcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSBuZXcgSW50MzJBcnJheShQREY0MTdDb21tb24uQkFSU19JTl9NT0RVTEUpO1xuICAgICAgICAgICAgbGV0IGJpdENvdW50SW5kZXggPSAwO1xuICAgICAgICAgICAgbGV0IHN1bVByZXZpb3VzQml0cyA9IDA7XG4gICAgICAgICAgICBmb3IgKCAvKmludCovbGV0IGkgPSAwOyBpIDwgUERGNDE3Q29tbW9uLk1PRFVMRVNfSU5fQ09ERVdPUkQ7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCBzYW1wbGVJbmRleCA9IGJpdENvdW50U3VtIC8gKDIgKiBQREY0MTdDb21tb24uTU9EVUxFU19JTl9DT0RFV09SRCkgK1xuICAgICAgICAgICAgICAgICAgICAoaSAqIGJpdENvdW50U3VtKSAvIFBERjQxN0NvbW1vbi5NT0RVTEVTX0lOX0NPREVXT1JEO1xuICAgICAgICAgICAgICAgIGlmIChzdW1QcmV2aW91c0JpdHMgKyBtb2R1bGVCaXRDb3VudFtiaXRDb3VudEluZGV4XSA8PSBzYW1wbGVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICBzdW1QcmV2aW91c0JpdHMgKz0gbW9kdWxlQml0Q291bnRbYml0Q291bnRJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIGJpdENvdW50SW5kZXgrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzdWx0W2JpdENvdW50SW5kZXhdKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXREZWNvZGVkQ29kZXdvcmRWYWx1ZShtb2R1bGVCaXRDb3VudCkge1xuICAgICAgICAgICAgbGV0IGRlY29kZWRWYWx1ZSA9IFBERjQxN0NvZGV3b3JkRGVjb2Rlci5nZXRCaXRWYWx1ZShtb2R1bGVCaXRDb3VudCk7XG4gICAgICAgICAgICByZXR1cm4gUERGNDE3Q29tbW9uLmdldENvZGV3b3JkKGRlY29kZWRWYWx1ZSkgPT09IC0xID8gLTEgOiBkZWNvZGVkVmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdldEJpdFZhbHVlKG1vZHVsZUJpdENvdW50KSB7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gLypsb25nKi8gMDtcbiAgICAgICAgICAgIGZvciAobGV0IC8qaW50Ki8gaSA9IDA7IGkgPCBtb2R1bGVCaXRDb3VudC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGZvciAoIC8qaW50Ki9sZXQgYml0ID0gMDsgYml0IDwgbW9kdWxlQml0Q291bnRbaV07IGJpdCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IChyZXN1bHQgPDwgMSkgfCAoaSAlIDIgPT09IDAgPyAxIDogMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIE1hdGgudHJ1bmMocmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgICAvLyB3b3JraW5nIHdpdGggMzJiaXQgZmxvYXQgKGFzIGluIEphdmEpXG4gICAgICAgIHN0YXRpYyBnZXRDbG9zZXN0RGVjb2RlZFZhbHVlKG1vZHVsZUJpdENvdW50KSB7XG4gICAgICAgICAgICBsZXQgYml0Q291bnRTdW0gPSBNYXRoVXRpbHMuc3VtKG1vZHVsZUJpdENvdW50KTtcbiAgICAgICAgICAgIGxldCBiaXRDb3VudFJhdGlvcyA9IG5ldyBBcnJheShQREY0MTdDb21tb24uQkFSU19JTl9NT0RVTEUpO1xuICAgICAgICAgICAgaWYgKGJpdENvdW50U3VtID4gMSkge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IC8qaW50Ki8gaSA9IDA7IGkgPCBiaXRDb3VudFJhdGlvcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBiaXRDb3VudFJhdGlvc1tpXSA9IE1hdGguZnJvdW5kKG1vZHVsZUJpdENvdW50W2ldIC8gYml0Q291bnRTdW0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBiZXN0TWF0Y2hFcnJvciA9IEZsb2F0Lk1BWF9WQUxVRTtcbiAgICAgICAgICAgIGxldCBiZXN0TWF0Y2ggPSAtMTtcbiAgICAgICAgICAgIGlmICghdGhpcy5iU3ltYm9sVGFibGVSZWFkeSkge1xuICAgICAgICAgICAgICAgIFBERjQxN0NvZGV3b3JkRGVjb2Rlci5pbml0aWFsaXplKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKCAvKmludCovbGV0IGogPSAwOyBqIDwgUERGNDE3Q29kZXdvcmREZWNvZGVyLlJBVElPU19UQUJMRS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGxldCBlcnJvciA9IDAuMDtcbiAgICAgICAgICAgICAgICBsZXQgcmF0aW9UYWJsZVJvdyA9IFBERjQxN0NvZGV3b3JkRGVjb2Rlci5SQVRJT1NfVEFCTEVbal07XG4gICAgICAgICAgICAgICAgZm9yICggLyppbnQqL2xldCBrID0gMDsgayA8IFBERjQxN0NvbW1vbi5CQVJTX0lOX01PRFVMRTsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBkaWZmID0gTWF0aC5mcm91bmQocmF0aW9UYWJsZVJvd1trXSAtIGJpdENvdW50UmF0aW9zW2tdKTtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3IgKz0gTWF0aC5mcm91bmQoZGlmZiAqIGRpZmYpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IgPj0gYmVzdE1hdGNoRXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChlcnJvciA8IGJlc3RNYXRjaEVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RNYXRjaEVycm9yID0gZXJyb3I7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RNYXRjaCA9IFBERjQxN0NvbW1vbi5TWU1CT0xfVEFCTEVbal07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGJlc3RNYXRjaDtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBmbGFnIHRoYXQgdGhlIHRhYmxlIGlzIHJlYWR5IGZvciB1c2VcbiAgICBQREY0MTdDb2Rld29yZERlY29kZXIuYlN5bWJvbFRhYmxlUmVhZHkgPSBmYWxzZTtcbiAgICBQREY0MTdDb2Rld29yZERlY29kZXIuUkFUSU9TX1RBQkxFID0gbmV3IEFycmF5KFBERjQxN0NvbW1vbi5TWU1CT0xfVEFCTEUubGVuZ3RoKS5tYXAoeCA9PiB4ID0gbmV3IEFycmF5KFBERjQxN0NvbW1vbi5CQVJTX0lOX01PRFVMRSkpO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAxMyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvLyBwYWNrYWdlIGNvbS5nb29nbGUuenhpbmcucGRmNDE3O1xuICAgIC8qKlxuICAgICAqIEBhdXRob3IgR3VlbnRoZXIgR3JhdVxuICAgICAqL1xuICAgIC8qcHVibGljIGZpbmFsKi8gY2xhc3MgUERGNDE3UmVzdWx0TWV0YWRhdGEge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICAgIHRoaXMuc2VnbWVudENvdW50ID0gLTE7XG4gICAgICAgICAgICB0aGlzLmZpbGVTaXplID0gLTE7XG4gICAgICAgICAgICB0aGlzLnRpbWVzdGFtcCA9IC0xO1xuICAgICAgICAgICAgdGhpcy5jaGVja3N1bSA9IC0xO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgU2VnbWVudCBJRCByZXByZXNlbnRzIHRoZSBzZWdtZW50IG9mIHRoZSB3aG9sZSBmaWxlIGRpc3RyaWJ1dGVkIG92ZXIgZGlmZmVyZW50IHN5bWJvbHMuXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gRmlsZSBzZWdtZW50IGluZGV4XG4gICAgICAgICAqL1xuICAgICAgICBnZXRTZWdtZW50SW5kZXgoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zZWdtZW50SW5kZXg7XG4gICAgICAgIH1cbiAgICAgICAgc2V0U2VnbWVudEluZGV4KHNlZ21lbnRJbmRleCkge1xuICAgICAgICAgICAgdGhpcy5zZWdtZW50SW5kZXggPSBzZWdtZW50SW5kZXg7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIElzIHRoZSBzYW1lIGZvciBlYWNoIHJlbGF0ZWQgUERGNDE3IHN5bWJvbFxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIEZpbGUgSURcbiAgICAgICAgICovXG4gICAgICAgIGdldEZpbGVJZCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbGVJZDtcbiAgICAgICAgfVxuICAgICAgICBzZXRGaWxlSWQoZmlsZUlkKSB7XG4gICAgICAgICAgICB0aGlzLmZpbGVJZCA9IGZpbGVJZDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBhbHdheXMgbnVsbFxuICAgICAgICAgKiBAZGVwcmVjYXRlZCB1c2UgZGVkaWNhdGVkIGFscmVhZHkgcGFyc2VkIGZpZWxkc1xuICAgICAgICAgKi9cbiAgICAgICAgLy8gICBARGVwcmVjYXRlZFxuICAgICAgICBnZXRPcHRpb25hbERhdGEoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vcHRpb25hbERhdGE7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBvcHRpb25hbERhdGEgb2xkIG9wdGlvbmFsIGRhdGEgZm9ybWF0IGFzIGludCBhcnJheVxuICAgICAgICAgKiBAZGVwcmVjYXRlZCBwYXJzZSBhbmQgdXNlIG5ldyBmaWVsZHNcbiAgICAgICAgICovXG4gICAgICAgIC8vICAgQERlcHJlY2F0ZWRcbiAgICAgICAgc2V0T3B0aW9uYWxEYXRhKG9wdGlvbmFsRGF0YSkge1xuICAgICAgICAgICAgdGhpcy5vcHRpb25hbERhdGEgPSBvcHRpb25hbERhdGE7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gdHJ1ZSBpZiBpdCBpcyB0aGUgbGFzdCBzZWdtZW50XG4gICAgICAgICAqL1xuICAgICAgICBpc0xhc3RTZWdtZW50KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubGFzdFNlZ21lbnQ7XG4gICAgICAgIH1cbiAgICAgICAgc2V0TGFzdFNlZ21lbnQobGFzdFNlZ21lbnQpIHtcbiAgICAgICAgICAgIHRoaXMubGFzdFNlZ21lbnQgPSBsYXN0U2VnbWVudDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBjb3VudCBvZiBzZWdtZW50cywgLTEgaWYgbm90IHNldFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0U2VnbWVudENvdW50KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2VnbWVudENvdW50O1xuICAgICAgICB9XG4gICAgICAgIHNldFNlZ21lbnRDb3VudChzZWdtZW50Q291bnQgLyppbnQqLykge1xuICAgICAgICAgICAgdGhpcy5zZWdtZW50Q291bnQgPSBzZWdtZW50Q291bnQ7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0U2VuZGVyKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2VuZGVyIHx8IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgc2V0U2VuZGVyKHNlbmRlcikge1xuICAgICAgICAgICAgdGhpcy5zZW5kZXIgPSBzZW5kZXI7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0QWRkcmVzc2VlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRkcmVzc2VlIHx8IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgc2V0QWRkcmVzc2VlKGFkZHJlc3NlZSkge1xuICAgICAgICAgICAgdGhpcy5hZGRyZXNzZWUgPSBhZGRyZXNzZWU7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEZpbGVuYW1lIG9mIHRoZSBlbmNvZGVkIGZpbGVcbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiBmaWxlbmFtZVxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0RmlsZU5hbWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5maWxlTmFtZTtcbiAgICAgICAgfVxuICAgICAgICBzZXRGaWxlTmFtZShmaWxlTmFtZSkge1xuICAgICAgICAgICAgdGhpcy5maWxlTmFtZSA9IGZpbGVOYW1lO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBmaWxlc2l6ZSBpbiBieXRlcyBvZiB0aGUgZW5jb2RlZCBmaWxlXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gZmlsZXNpemUgaW4gYnl0ZXMsIC0xIGlmIG5vdCBzZXRcbiAgICAgICAgICovXG4gICAgICAgIGdldEZpbGVTaXplKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmlsZVNpemU7XG4gICAgICAgIH1cbiAgICAgICAgc2V0RmlsZVNpemUoZmlsZVNpemUgLypsb25nKi8pIHtcbiAgICAgICAgICAgIHRoaXMuZmlsZVNpemUgPSBmaWxlU2l6ZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogMTYtYml0IENSQyBjaGVja3N1bSB1c2luZyBDQ0lUVC0xNlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIGNyYyBjaGVja3N1bSwgLTEgaWYgbm90IHNldFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0Q2hlY2tzdW0oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jaGVja3N1bTtcbiAgICAgICAgfVxuICAgICAgICBzZXRDaGVja3N1bShjaGVja3N1bSAvKmludCovKSB7XG4gICAgICAgICAgICB0aGlzLmNoZWNrc3VtID0gY2hlY2tzdW07XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIHVuaXggZXBvY2sgdGltZXN0YW1wLCBlbGFwc2VkIHNlY29uZHMgc2luY2UgMTk3MC0wMS0wMVxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIGVsYXBzZWQgc2Vjb25kcywgLTEgaWYgbm90IHNldFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0VGltZXN0YW1wKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudGltZXN0YW1wO1xuICAgICAgICB9XG4gICAgICAgIHNldFRpbWVzdGFtcCh0aW1lc3RhbXAgLypsb25nKi8pIHtcbiAgICAgICAgICAgIHRoaXMudGltZXN0YW1wID0gdGltZXN0YW1wO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUG9ueWZpbGwgZm9yIEphdmEncyBMb25nIGNsYXNzLlxuICAgICAqL1xuICAgIGNsYXNzIExvbmcge1xuICAgICAgICAvKipcbiAgICAgICAgICogUGFyc2VzIGEgc3RyaW5nIHRvIGEgbnVtYmVyLCBzaW5jZSBKUyBoYXMgbm8gcmVhbGx5IEludDY0LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gbnVtIE51bWVyaWMgc3RyaW5nLlxuICAgICAgICAgKiBAcGFyYW0gcmFkaXggRGVzdGluYXRpb24gcmFkaXguXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgcGFyc2VMb25nKG51bSwgcmFkaXggPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZUludChudW0sIHJhZGl4KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEN1c3RvbSBFcnJvciBjbGFzcyBvZiB0eXBlIEV4Y2VwdGlvbi5cbiAgICAgKi9cbiAgICBjbGFzcyBOdWxsUG9pbnRlckV4Y2VwdGlvbiBleHRlbmRzIEV4Y2VwdGlvbiB7XG4gICAgfVxuICAgIE51bGxQb2ludGVyRXhjZXB0aW9uLmtpbmQgPSAnTnVsbFBvaW50ZXJFeGNlcHRpb24nO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgKGMpIDE5OTQsIDIwMDQsIE9yYWNsZSBhbmQvb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gICAgICogRE8gTk9UIEFMVEVSIE9SIFJFTU9WRSBDT1BZUklHSFQgTk9USUNFUyBPUiBUSElTIEZJTEUgSEVBREVSLlxuICAgICAqXG4gICAgICogVGhpcyBjb2RlIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICAgKiB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHZlcnNpb24gMiBvbmx5LCBhc1xuICAgICAqIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLiAgT3JhY2xlIGRlc2lnbmF0ZXMgdGhpc1xuICAgICAqIHBhcnRpY3VsYXIgZmlsZSBhcyBzdWJqZWN0IHRvIHRoZSBcIkNsYXNzcGF0aFwiIGV4Y2VwdGlvbiBhcyBwcm92aWRlZFxuICAgICAqIGJ5IE9yYWNsZSBpbiB0aGUgTElDRU5TRSBmaWxlIHRoYXQgYWNjb21wYW5pZWQgdGhpcyBjb2RlLlxuICAgICAqXG4gICAgICogVGhpcyBjb2RlIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgICogQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZIG9yXG4gICAgICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgICogdmVyc2lvbiAyIGZvciBtb3JlIGRldGFpbHMgKGEgY29weSBpcyBpbmNsdWRlZCBpbiB0aGUgTElDRU5TRSBmaWxlIHRoYXRcbiAgICAgKiBhY2NvbXBhbmllZCB0aGlzIGNvZGUpLlxuICAgICAqXG4gICAgICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgdmVyc2lvblxuICAgICAqIDIgYWxvbmcgd2l0aCB0aGlzIHdvcms7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbixcbiAgICAgKiBJbmMuLCA1MSBGcmFua2xpbiBTdCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgMDIxMTAtMTMwMSBVU0EuXG4gICAgICpcbiAgICAgKiBQbGVhc2UgY29udGFjdCBPcmFjbGUsIDUwMCBPcmFjbGUgUGFya3dheSwgUmVkd29vZCBTaG9yZXMsIENBIDk0MDY1IFVTQVxuICAgICAqIG9yIHZpc2l0IHd3dy5vcmFjbGUuY29tIGlmIHlvdSBuZWVkIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gb3IgaGF2ZSBhbnlcbiAgICAgKiBxdWVzdGlvbnMuXG4gICAgICovXG4gICAgLy8gcGFja2FnZSBqYXZhLmlvO1xuICAgIC8qKlxuICAgICAqIFRoaXMgYWJzdHJhY3QgY2xhc3MgaXMgdGhlIHN1cGVyY2xhc3Mgb2YgYWxsIGNsYXNzZXMgcmVwcmVzZW50aW5nXG4gICAgICogYW4gb3V0cHV0IHN0cmVhbSBvZiBieXRlcy4gQW4gb3V0cHV0IHN0cmVhbSBhY2NlcHRzIG91dHB1dCBieXRlc1xuICAgICAqIGFuZCBzZW5kcyB0aGVtIHRvIHNvbWUgc2luay5cbiAgICAgKiA8cD5cbiAgICAgKiBBcHBsaWNhdGlvbnMgdGhhdCBuZWVkIHRvIGRlZmluZSBhIHN1YmNsYXNzIG9mXG4gICAgICogPGNvZGU+T3V0cHV0U3RyZWFtPC9jb2RlPiBtdXN0IGFsd2F5cyBwcm92aWRlIGF0IGxlYXN0IGEgbWV0aG9kXG4gICAgICogdGhhdCB3cml0ZXMgb25lIGJ5dGUgb2Ygb3V0cHV0LlxuICAgICAqXG4gICAgICogQGF1dGhvciAgQXJ0aHVyIHZhbiBIb2ZmXG4gICAgICogQHNlZSAgICAgamF2YS5pby5CdWZmZXJlZE91dHB1dFN0cmVhbVxuICAgICAqIEBzZWUgICAgIGphdmEuaW8uQnl0ZUFycmF5T3V0cHV0U3RyZWFtXG4gICAgICogQHNlZSAgICAgamF2YS5pby5EYXRhT3V0cHV0U3RyZWFtXG4gICAgICogQHNlZSAgICAgamF2YS5pby5GaWx0ZXJPdXRwdXRTdHJlYW1cbiAgICAgKiBAc2VlICAgICBqYXZhLmlvLklucHV0U3RyZWFtXG4gICAgICogQHNlZSAgICAgamF2YS5pby5PdXRwdXRTdHJlYW0jd3JpdGUoaW50KVxuICAgICAqIEBzaW5jZSAgIEpESzEuMFxuICAgICAqL1xuICAgIC8qcHVibGljKi8gY2xhc3MgT3V0cHV0U3RyZWFtIC8qaW1wbGVtZW50cyBDbG9zZWFibGUsIEZsdXNoYWJsZSovIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdyaXRlcyA8Y29kZT5iLmxlbmd0aDwvY29kZT4gYnl0ZXMgZnJvbSB0aGUgc3BlY2lmaWVkIGJ5dGUgYXJyYXlcbiAgICAgICAgICogdG8gdGhpcyBvdXRwdXQgc3RyZWFtLiBUaGUgZ2VuZXJhbCBjb250cmFjdCBmb3IgPGNvZGU+d3JpdGUoYik8L2NvZGU+XG4gICAgICAgICAqIGlzIHRoYXQgaXQgc2hvdWxkIGhhdmUgZXhhY3RseSB0aGUgc2FtZSBlZmZlY3QgYXMgdGhlIGNhbGxcbiAgICAgICAgICogPGNvZGU+d3JpdGUoYiwgMCwgYi5sZW5ndGgpPC9jb2RlPi5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtICAgICAgYiAgIHRoZSBkYXRhLlxuICAgICAgICAgKiBAZXhjZXB0aW9uICBJT0V4Y2VwdGlvbiAgaWYgYW4gSS9PIGVycm9yIG9jY3Vycy5cbiAgICAgICAgICogQHNlZSAgICAgICAgamF2YS5pby5PdXRwdXRTdHJlYW0jd3JpdGUoYnl0ZVtdLCBpbnQsIGludClcbiAgICAgICAgICovXG4gICAgICAgIHdyaXRlQnl0ZXMoYikge1xuICAgICAgICAgICAgdGhpcy53cml0ZUJ5dGVzT2Zmc2V0KGIsIDAsIGIubGVuZ3RoKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogV3JpdGVzIDxjb2RlPmxlbjwvY29kZT4gYnl0ZXMgZnJvbSB0aGUgc3BlY2lmaWVkIGJ5dGUgYXJyYXlcbiAgICAgICAgICogc3RhcnRpbmcgYXQgb2Zmc2V0IDxjb2RlPm9mZjwvY29kZT4gdG8gdGhpcyBvdXRwdXQgc3RyZWFtLlxuICAgICAgICAgKiBUaGUgZ2VuZXJhbCBjb250cmFjdCBmb3IgPGNvZGU+d3JpdGUoYiwgb2ZmLCBsZW4pPC9jb2RlPiBpcyB0aGF0XG4gICAgICAgICAqIHNvbWUgb2YgdGhlIGJ5dGVzIGluIHRoZSBhcnJheSA8Y29kZT5iPC9jb2RlPiBhcmUgd3JpdHRlbiB0byB0aGVcbiAgICAgICAgICogb3V0cHV0IHN0cmVhbSBpbiBvcmRlcjsgZWxlbWVudCA8Y29kZT5iW29mZl08L2NvZGU+IGlzIHRoZSBmaXJzdFxuICAgICAgICAgKiBieXRlIHdyaXR0ZW4gYW5kIDxjb2RlPmJbb2ZmK2xlbi0xXTwvY29kZT4gaXMgdGhlIGxhc3QgYnl0ZSB3cml0dGVuXG4gICAgICAgICAqIGJ5IHRoaXMgb3BlcmF0aW9uLlxuICAgICAgICAgKiA8cD5cbiAgICAgICAgICogVGhlIDxjb2RlPndyaXRlPC9jb2RlPiBtZXRob2Qgb2YgPGNvZGU+T3V0cHV0U3RyZWFtPC9jb2RlPiBjYWxsc1xuICAgICAgICAgKiB0aGUgd3JpdGUgbWV0aG9kIG9mIG9uZSBhcmd1bWVudCBvbiBlYWNoIG9mIHRoZSBieXRlcyB0byBiZVxuICAgICAgICAgKiB3cml0dGVuIG91dC4gU3ViY2xhc3NlcyBhcmUgZW5jb3VyYWdlZCB0byBvdmVycmlkZSB0aGlzIG1ldGhvZCBhbmRcbiAgICAgICAgICogcHJvdmlkZSBhIG1vcmUgZWZmaWNpZW50IGltcGxlbWVudGF0aW9uLlxuICAgICAgICAgKiA8cD5cbiAgICAgICAgICogSWYgPGNvZGU+YjwvY29kZT4gaXMgPGNvZGU+bnVsbDwvY29kZT4sIGFcbiAgICAgICAgICogPGNvZGU+TnVsbFBvaW50ZXJFeGNlcHRpb248L2NvZGU+IGlzIHRocm93bi5cbiAgICAgICAgICogPHA+XG4gICAgICAgICAqIElmIDxjb2RlPm9mZjwvY29kZT4gaXMgbmVnYXRpdmUsIG9yIDxjb2RlPmxlbjwvY29kZT4gaXMgbmVnYXRpdmUsIG9yXG4gICAgICAgICAqIDxjb2RlPm9mZitsZW48L2NvZGU+IGlzIGdyZWF0ZXIgdGhhbiB0aGUgbGVuZ3RoIG9mIHRoZSBhcnJheVxuICAgICAgICAgKiA8Y29kZT5iPC9jb2RlPiwgdGhlbiBhbiA8dHQ+SW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbjwvdHQ+IGlzIHRocm93bi5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtICAgICAgYiAgICAgdGhlIGRhdGEuXG4gICAgICAgICAqIEBwYXJhbSAgICAgIG9mZiAgIHRoZSBzdGFydCBvZmZzZXQgaW4gdGhlIGRhdGEuXG4gICAgICAgICAqIEBwYXJhbSAgICAgIGxlbiAgIHRoZSBudW1iZXIgb2YgYnl0ZXMgdG8gd3JpdGUuXG4gICAgICAgICAqIEBleGNlcHRpb24gIElPRXhjZXB0aW9uICBpZiBhbiBJL08gZXJyb3Igb2NjdXJzLiBJbiBwYXJ0aWN1bGFyLFxuICAgICAgICAgKiAgICAgICAgICAgICBhbiA8Y29kZT5JT0V4Y2VwdGlvbjwvY29kZT4gaXMgdGhyb3duIGlmIHRoZSBvdXRwdXRcbiAgICAgICAgICogICAgICAgICAgICAgc3RyZWFtIGlzIGNsb3NlZC5cbiAgICAgICAgICovXG4gICAgICAgIHdyaXRlQnl0ZXNPZmZzZXQoYiwgb2ZmLCBsZW4pIHtcbiAgICAgICAgICAgIGlmIChiID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTnVsbFBvaW50ZXJFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKChvZmYgPCAwKSB8fCAob2ZmID4gYi5sZW5ndGgpIHx8IChsZW4gPCAwKSB8fFxuICAgICAgICAgICAgICAgICgob2ZmICsgbGVuKSA+IGIubGVuZ3RoKSB8fCAoKG9mZiArIGxlbikgPCAwKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChsZW4gPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53cml0ZShiW29mZiArIGldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRmx1c2hlcyB0aGlzIG91dHB1dCBzdHJlYW0gYW5kIGZvcmNlcyBhbnkgYnVmZmVyZWQgb3V0cHV0IGJ5dGVzXG4gICAgICAgICAqIHRvIGJlIHdyaXR0ZW4gb3V0LiBUaGUgZ2VuZXJhbCBjb250cmFjdCBvZiA8Y29kZT5mbHVzaDwvY29kZT4gaXNcbiAgICAgICAgICogdGhhdCBjYWxsaW5nIGl0IGlzIGFuIGluZGljYXRpb24gdGhhdCwgaWYgYW55IGJ5dGVzIHByZXZpb3VzbHlcbiAgICAgICAgICogd3JpdHRlbiBoYXZlIGJlZW4gYnVmZmVyZWQgYnkgdGhlIGltcGxlbWVudGF0aW9uIG9mIHRoZSBvdXRwdXRcbiAgICAgICAgICogc3RyZWFtLCBzdWNoIGJ5dGVzIHNob3VsZCBpbW1lZGlhdGVseSBiZSB3cml0dGVuIHRvIHRoZWlyXG4gICAgICAgICAqIGludGVuZGVkIGRlc3RpbmF0aW9uLlxuICAgICAgICAgKiA8cD5cbiAgICAgICAgICogSWYgdGhlIGludGVuZGVkIGRlc3RpbmF0aW9uIG9mIHRoaXMgc3RyZWFtIGlzIGFuIGFic3RyYWN0aW9uIHByb3ZpZGVkIGJ5XG4gICAgICAgICAqIHRoZSB1bmRlcmx5aW5nIG9wZXJhdGluZyBzeXN0ZW0sIGZvciBleGFtcGxlIGEgZmlsZSwgdGhlbiBmbHVzaGluZyB0aGVcbiAgICAgICAgICogc3RyZWFtIGd1YXJhbnRlZXMgb25seSB0aGF0IGJ5dGVzIHByZXZpb3VzbHkgd3JpdHRlbiB0byB0aGUgc3RyZWFtIGFyZVxuICAgICAgICAgKiBwYXNzZWQgdG8gdGhlIG9wZXJhdGluZyBzeXN0ZW0gZm9yIHdyaXRpbmc7IGl0IGRvZXMgbm90IGd1YXJhbnRlZSB0aGF0XG4gICAgICAgICAqIHRoZXkgYXJlIGFjdHVhbGx5IHdyaXR0ZW4gdG8gYSBwaHlzaWNhbCBkZXZpY2Ugc3VjaCBhcyBhIGRpc2sgZHJpdmUuXG4gICAgICAgICAqIDxwPlxuICAgICAgICAgKiBUaGUgPGNvZGU+Zmx1c2g8L2NvZGU+IG1ldGhvZCBvZiA8Y29kZT5PdXRwdXRTdHJlYW08L2NvZGU+IGRvZXMgbm90aGluZy5cbiAgICAgICAgICpcbiAgICAgICAgICogQGV4Y2VwdGlvbiAgSU9FeGNlcHRpb24gIGlmIGFuIEkvTyBlcnJvciBvY2N1cnMuXG4gICAgICAgICAqL1xuICAgICAgICBmbHVzaCgpIHtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ2xvc2VzIHRoaXMgb3V0cHV0IHN0cmVhbSBhbmQgcmVsZWFzZXMgYW55IHN5c3RlbSByZXNvdXJjZXNcbiAgICAgICAgICogYXNzb2NpYXRlZCB3aXRoIHRoaXMgc3RyZWFtLiBUaGUgZ2VuZXJhbCBjb250cmFjdCBvZiA8Y29kZT5jbG9zZTwvY29kZT5cbiAgICAgICAgICogaXMgdGhhdCBpdCBjbG9zZXMgdGhlIG91dHB1dCBzdHJlYW0uIEEgY2xvc2VkIHN0cmVhbSBjYW5ub3QgcGVyZm9ybVxuICAgICAgICAgKiBvdXRwdXQgb3BlcmF0aW9ucyBhbmQgY2Fubm90IGJlIHJlb3BlbmVkLlxuICAgICAgICAgKiA8cD5cbiAgICAgICAgICogVGhlIDxjb2RlPmNsb3NlPC9jb2RlPiBtZXRob2Qgb2YgPGNvZGU+T3V0cHV0U3RyZWFtPC9jb2RlPiBkb2VzIG5vdGhpbmcuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBleGNlcHRpb24gIElPRXhjZXB0aW9uICBpZiBhbiBJL08gZXJyb3Igb2NjdXJzLlxuICAgICAgICAgKi9cbiAgICAgICAgY2xvc2UoKSB7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDdXN0b20gRXJyb3IgY2xhc3Mgb2YgdHlwZSBFeGNlcHRpb24uXG4gICAgICovXG4gICAgY2xhc3MgT3V0T2ZNZW1vcnlFcnJvciBleHRlbmRzIEV4Y2VwdGlvbiB7XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgKGMpIDE5OTQsIDIwMTAsIE9yYWNsZSBhbmQvb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gICAgICogRE8gTk9UIEFMVEVSIE9SIFJFTU9WRSBDT1BZUklHSFQgTk9USUNFUyBPUiBUSElTIEZJTEUgSEVBREVSLlxuICAgICAqXG4gICAgICogVGhpcyBjb2RlIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICAgKiB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHZlcnNpb24gMiBvbmx5LCBhc1xuICAgICAqIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLiAgT3JhY2xlIGRlc2lnbmF0ZXMgdGhpc1xuICAgICAqIHBhcnRpY3VsYXIgZmlsZSBhcyBzdWJqZWN0IHRvIHRoZSBcIkNsYXNzcGF0aFwiIGV4Y2VwdGlvbiBhcyBwcm92aWRlZFxuICAgICAqIGJ5IE9yYWNsZSBpbiB0aGUgTElDRU5TRSBmaWxlIHRoYXQgYWNjb21wYW5pZWQgdGhpcyBjb2RlLlxuICAgICAqXG4gICAgICogVGhpcyBjb2RlIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgICogQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZIG9yXG4gICAgICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgICogdmVyc2lvbiAyIGZvciBtb3JlIGRldGFpbHMgKGEgY29weSBpcyBpbmNsdWRlZCBpbiB0aGUgTElDRU5TRSBmaWxlIHRoYXRcbiAgICAgKiBhY2NvbXBhbmllZCB0aGlzIGNvZGUpLlxuICAgICAqXG4gICAgICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgdmVyc2lvblxuICAgICAqIDIgYWxvbmcgd2l0aCB0aGlzIHdvcms7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbixcbiAgICAgKiBJbmMuLCA1MSBGcmFua2xpbiBTdCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgMDIxMTAtMTMwMSBVU0EuXG4gICAgICpcbiAgICAgKiBQbGVhc2UgY29udGFjdCBPcmFjbGUsIDUwMCBPcmFjbGUgUGFya3dheSwgUmVkd29vZCBTaG9yZXMsIENBIDk0MDY1IFVTQVxuICAgICAqIG9yIHZpc2l0IHd3dy5vcmFjbGUuY29tIGlmIHlvdSBuZWVkIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gb3IgaGF2ZSBhbnlcbiAgICAgKiBxdWVzdGlvbnMuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogVGhpcyBjbGFzcyBpbXBsZW1lbnRzIGFuIG91dHB1dCBzdHJlYW0gaW4gd2hpY2ggdGhlIGRhdGEgaXNcbiAgICAgKiB3cml0dGVuIGludG8gYSBieXRlIGFycmF5LiBUaGUgYnVmZmVyIGF1dG9tYXRpY2FsbHkgZ3Jvd3MgYXMgZGF0YVxuICAgICAqIGlzIHdyaXR0ZW4gdG8gaXQuXG4gICAgICogVGhlIGRhdGEgY2FuIGJlIHJldHJpZXZlZCB1c2luZyA8Y29kZT50b0J5dGVBcnJheSgpPC9jb2RlPiBhbmRcbiAgICAgKiA8Y29kZT50b1N0cmluZygpPC9jb2RlPi5cbiAgICAgKiA8cD5cbiAgICAgKiBDbG9zaW5nIGEgPHR0PkJ5dGVBcnJheU91dHB1dFN0cmVhbTwvdHQ+IGhhcyBubyBlZmZlY3QuIFRoZSBtZXRob2RzIGluXG4gICAgICogdGhpcyBjbGFzcyBjYW4gYmUgY2FsbGVkIGFmdGVyIHRoZSBzdHJlYW0gaGFzIGJlZW4gY2xvc2VkIHdpdGhvdXRcbiAgICAgKiBnZW5lcmF0aW5nIGFuIDx0dD5JT0V4Y2VwdGlvbjwvdHQ+LlxuICAgICAqXG4gICAgICogQGF1dGhvciAgQXJ0aHVyIHZhbiBIb2ZmXG4gICAgICogQHNpbmNlICAgSkRLMS4wXG4gICAgICovXG4gICAgLypwdWJsaWMqLyBjbGFzcyBCeXRlQXJyYXlPdXRwdXRTdHJlYW0gZXh0ZW5kcyBPdXRwdXRTdHJlYW0ge1xuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIG5ldyBieXRlIGFycmF5IG91dHB1dCBzdHJlYW0uIFRoZSBidWZmZXIgY2FwYWNpdHkgaXNcbiAgICAgICAgICogaW5pdGlhbGx5IDMyIGJ5dGVzLCB0aG91Z2ggaXRzIHNpemUgaW5jcmVhc2VzIGlmIG5lY2Vzc2FyeS5cbiAgICAgICAgICovXG4gICAgICAgIC8vIHB1YmxpYyBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgLy8gICAgIHRoaXMoMzIpO1xuICAgICAgICAvLyB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgbmV3IGJ5dGUgYXJyYXkgb3V0cHV0IHN0cmVhbSwgd2l0aCBhIGJ1ZmZlciBjYXBhY2l0eSBvZlxuICAgICAgICAgKiB0aGUgc3BlY2lmaWVkIHNpemUsIGluIGJ5dGVzLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gICBzaXplICAgdGhlIGluaXRpYWwgc2l6ZS5cbiAgICAgICAgICogQGV4Y2VwdGlvbiAgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uIGlmIHNpemUgaXMgbmVnYXRpdmUuXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3RvcihzaXplID0gMzIpIHtcbiAgICAgICAgICAgIHN1cGVyKCk7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFRoZSBudW1iZXIgb2YgdmFsaWQgYnl0ZXMgaW4gdGhlIGJ1ZmZlci5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgdGhpcy5jb3VudCA9IDA7XG4gICAgICAgICAgICBpZiAoc2l6ZSA8IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdOZWdhdGl2ZSBpbml0aWFsIHNpemU6ICdcbiAgICAgICAgICAgICAgICAgICAgKyBzaXplKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuYnVmID0gbmV3IFVpbnQ4QXJyYXkoc2l6ZSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEluY3JlYXNlcyB0aGUgY2FwYWNpdHkgaWYgbmVjZXNzYXJ5IHRvIGVuc3VyZSB0aGF0IGl0IGNhbiBob2xkXG4gICAgICAgICAqIGF0IGxlYXN0IHRoZSBudW1iZXIgb2YgZWxlbWVudHMgc3BlY2lmaWVkIGJ5IHRoZSBtaW5pbXVtXG4gICAgICAgICAqIGNhcGFjaXR5IGFyZ3VtZW50LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gbWluQ2FwYWNpdHkgdGhlIGRlc2lyZWQgbWluaW11bSBjYXBhY2l0eVxuICAgICAgICAgKiBAdGhyb3dzIE91dE9mTWVtb3J5RXJyb3IgaWYge0Bjb2RlIG1pbkNhcGFjaXR5IDwgMH0uICBUaGlzIGlzXG4gICAgICAgICAqIGludGVycHJldGVkIGFzIGEgcmVxdWVzdCBmb3IgdGhlIHVuc2F0aXNmaWFibHkgbGFyZ2UgY2FwYWNpdHlcbiAgICAgICAgICoge0Bjb2RlIChsb25nKSBJbnRlZ2VyLk1BWF9WQUxVRSArIChtaW5DYXBhY2l0eSAtIEludGVnZXIuTUFYX1ZBTFVFKX0uXG4gICAgICAgICAqL1xuICAgICAgICBlbnN1cmVDYXBhY2l0eShtaW5DYXBhY2l0eSkge1xuICAgICAgICAgICAgLy8gb3ZlcmZsb3ctY29uc2Npb3VzIGNvZGVcbiAgICAgICAgICAgIGlmIChtaW5DYXBhY2l0eSAtIHRoaXMuYnVmLmxlbmd0aCA+IDApXG4gICAgICAgICAgICAgICAgdGhpcy5ncm93KG1pbkNhcGFjaXR5KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogSW5jcmVhc2VzIHRoZSBjYXBhY2l0eSB0byBlbnN1cmUgdGhhdCBpdCBjYW4gaG9sZCBhdCBsZWFzdCB0aGVcbiAgICAgICAgICogbnVtYmVyIG9mIGVsZW1lbnRzIHNwZWNpZmllZCBieSB0aGUgbWluaW11bSBjYXBhY2l0eSBhcmd1bWVudC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIG1pbkNhcGFjaXR5IHRoZSBkZXNpcmVkIG1pbmltdW0gY2FwYWNpdHlcbiAgICAgICAgICovXG4gICAgICAgIGdyb3cobWluQ2FwYWNpdHkpIHtcbiAgICAgICAgICAgIC8vIG92ZXJmbG93LWNvbnNjaW91cyBjb2RlXG4gICAgICAgICAgICBsZXQgb2xkQ2FwYWNpdHkgPSB0aGlzLmJ1Zi5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgbmV3Q2FwYWNpdHkgPSBvbGRDYXBhY2l0eSA8PCAxO1xuICAgICAgICAgICAgaWYgKG5ld0NhcGFjaXR5IC0gbWluQ2FwYWNpdHkgPCAwKVxuICAgICAgICAgICAgICAgIG5ld0NhcGFjaXR5ID0gbWluQ2FwYWNpdHk7XG4gICAgICAgICAgICBpZiAobmV3Q2FwYWNpdHkgPCAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKG1pbkNhcGFjaXR5IDwgMCkgLy8gb3ZlcmZsb3dcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE91dE9mTWVtb3J5RXJyb3IoKTtcbiAgICAgICAgICAgICAgICBuZXdDYXBhY2l0eSA9IEludGVnZXIuTUFYX1ZBTFVFO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5idWYgPSBBcnJheXMuY29weU9mVWludDhBcnJheSh0aGlzLmJ1ZiwgbmV3Q2FwYWNpdHkpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXcml0ZXMgdGhlIHNwZWNpZmllZCBieXRlIHRvIHRoaXMgYnl0ZSBhcnJheSBvdXRwdXQgc3RyZWFtLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gICBiICAgdGhlIGJ5dGUgdG8gYmUgd3JpdHRlbi5cbiAgICAgICAgICovXG4gICAgICAgIHdyaXRlKGIpIHtcbiAgICAgICAgICAgIHRoaXMuZW5zdXJlQ2FwYWNpdHkodGhpcy5jb3VudCArIDEpO1xuICAgICAgICAgICAgdGhpcy5idWZbdGhpcy5jb3VudF0gPSAvKihieXRlKSovIGI7XG4gICAgICAgICAgICB0aGlzLmNvdW50ICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdyaXRlcyA8Y29kZT5sZW48L2NvZGU+IGJ5dGVzIGZyb20gdGhlIHNwZWNpZmllZCBieXRlIGFycmF5XG4gICAgICAgICAqIHN0YXJ0aW5nIGF0IG9mZnNldCA8Y29kZT5vZmY8L2NvZGU+IHRvIHRoaXMgYnl0ZSBhcnJheSBvdXRwdXQgc3RyZWFtLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gICBiICAgICB0aGUgZGF0YS5cbiAgICAgICAgICogQHBhcmFtICAgb2ZmICAgdGhlIHN0YXJ0IG9mZnNldCBpbiB0aGUgZGF0YS5cbiAgICAgICAgICogQHBhcmFtICAgbGVuICAgdGhlIG51bWJlciBvZiBieXRlcyB0byB3cml0ZS5cbiAgICAgICAgICovXG4gICAgICAgIHdyaXRlQnl0ZXNPZmZzZXQoYiwgb2ZmLCBsZW4pIHtcbiAgICAgICAgICAgIGlmICgob2ZmIDwgMCkgfHwgKG9mZiA+IGIubGVuZ3RoKSB8fCAobGVuIDwgMCkgfHxcbiAgICAgICAgICAgICAgICAoKG9mZiArIGxlbikgLSBiLmxlbmd0aCA+IDApKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEluZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZW5zdXJlQ2FwYWNpdHkodGhpcy5jb3VudCArIGxlbik7XG4gICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KGIsIG9mZiwgdGhpcy5idWYsIHRoaXMuY291bnQsIGxlbik7XG4gICAgICAgICAgICB0aGlzLmNvdW50ICs9IGxlbjtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogV3JpdGVzIHRoZSBjb21wbGV0ZSBjb250ZW50cyBvZiB0aGlzIGJ5dGUgYXJyYXkgb3V0cHV0IHN0cmVhbSB0b1xuICAgICAgICAgKiB0aGUgc3BlY2lmaWVkIG91dHB1dCBzdHJlYW0gYXJndW1lbnQsIGFzIGlmIGJ5IGNhbGxpbmcgdGhlIG91dHB1dFxuICAgICAgICAgKiBzdHJlYW0ncyB3cml0ZSBtZXRob2QgdXNpbmcgPGNvZGU+b3V0LndyaXRlKGJ1ZiwgMCwgY291bnQpPC9jb2RlPi5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtICAgICAgb3V0ICAgdGhlIG91dHB1dCBzdHJlYW0gdG8gd2hpY2ggdG8gd3JpdGUgdGhlIGRhdGEuXG4gICAgICAgICAqIEBleGNlcHRpb24gIElPRXhjZXB0aW9uICBpZiBhbiBJL08gZXJyb3Igb2NjdXJzLlxuICAgICAgICAgKi9cbiAgICAgICAgd3JpdGVUbyhvdXQpIHtcbiAgICAgICAgICAgIG91dC53cml0ZUJ5dGVzT2Zmc2V0KHRoaXMuYnVmLCAwLCB0aGlzLmNvdW50KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogUmVzZXRzIHRoZSA8Y29kZT5jb3VudDwvY29kZT4gZmllbGQgb2YgdGhpcyBieXRlIGFycmF5IG91dHB1dFxuICAgICAgICAgKiBzdHJlYW0gdG8gemVybywgc28gdGhhdCBhbGwgY3VycmVudGx5IGFjY3VtdWxhdGVkIG91dHB1dCBpbiB0aGVcbiAgICAgICAgICogb3V0cHV0IHN0cmVhbSBpcyBkaXNjYXJkZWQuIFRoZSBvdXRwdXQgc3RyZWFtIGNhbiBiZSB1c2VkIGFnYWluLFxuICAgICAgICAgKiByZXVzaW5nIHRoZSBhbHJlYWR5IGFsbG9jYXRlZCBidWZmZXIgc3BhY2UuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBzZWUgICAgIGphdmEuaW8uQnl0ZUFycmF5SW5wdXRTdHJlYW0jY291bnRcbiAgICAgICAgICovXG4gICAgICAgIHJlc2V0KCkge1xuICAgICAgICAgICAgdGhpcy5jb3VudCA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBuZXdseSBhbGxvY2F0ZWQgYnl0ZSBhcnJheS4gSXRzIHNpemUgaXMgdGhlIGN1cnJlbnRcbiAgICAgICAgICogc2l6ZSBvZiB0aGlzIG91dHB1dCBzdHJlYW0gYW5kIHRoZSB2YWxpZCBjb250ZW50cyBvZiB0aGUgYnVmZmVyXG4gICAgICAgICAqIGhhdmUgYmVlbiBjb3BpZWQgaW50byBpdC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiAgdGhlIGN1cnJlbnQgY29udGVudHMgb2YgdGhpcyBvdXRwdXQgc3RyZWFtLCBhcyBhIGJ5dGUgYXJyYXkuXG4gICAgICAgICAqIEBzZWUgICAgIGphdmEuaW8uQnl0ZUFycmF5T3V0cHV0U3RyZWFtI3NpemUoKVxuICAgICAgICAgKi9cbiAgICAgICAgdG9CeXRlQXJyYXkoKSB7XG4gICAgICAgICAgICByZXR1cm4gQXJyYXlzLmNvcHlPZlVpbnQ4QXJyYXkodGhpcy5idWYsIHRoaXMuY291bnQpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHNpemUgb2YgdGhlIGJ1ZmZlci5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiAgdGhlIHZhbHVlIG9mIHRoZSA8Y29kZT5jb3VudDwvY29kZT4gZmllbGQsIHdoaWNoIGlzIHRoZSBudW1iZXJcbiAgICAgICAgICogICAgICAgICAgb2YgdmFsaWQgYnl0ZXMgaW4gdGhpcyBvdXRwdXQgc3RyZWFtLlxuICAgICAgICAgKiBAc2VlICAgICBqYXZhLmlvLkJ5dGVBcnJheU91dHB1dFN0cmVhbSNjb3VudFxuICAgICAgICAgKi9cbiAgICAgICAgc2l6ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvdW50O1xuICAgICAgICB9XG4gICAgICAgIHRvU3RyaW5nKHBhcmFtKSB7XG4gICAgICAgICAgICBpZiAoIXBhcmFtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9TdHJpbmdfdm9pZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBwYXJhbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy50b1N0cmluZ19zdHJpbmcocGFyYW0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9TdHJpbmdfbnVtYmVyKHBhcmFtKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ29udmVydHMgdGhlIGJ1ZmZlcidzIGNvbnRlbnRzIGludG8gYSBzdHJpbmcgZGVjb2RpbmcgYnl0ZXMgdXNpbmcgdGhlXG4gICAgICAgICAqIHBsYXRmb3JtJ3MgZGVmYXVsdCBjaGFyYWN0ZXIgc2V0LiBUaGUgbGVuZ3RoIG9mIHRoZSBuZXcgPHR0PlN0cmluZzwvdHQ+XG4gICAgICAgICAqIGlzIGEgZnVuY3Rpb24gb2YgdGhlIGNoYXJhY3RlciBzZXQsIGFuZCBoZW5jZSBtYXkgbm90IGJlIGVxdWFsIHRvIHRoZVxuICAgICAgICAgKiBzaXplIG9mIHRoZSBidWZmZXIuXG4gICAgICAgICAqXG4gICAgICAgICAqIDxwPiBUaGlzIG1ldGhvZCBhbHdheXMgcmVwbGFjZXMgbWFsZm9ybWVkLWlucHV0IGFuZCB1bm1hcHBhYmxlLWNoYXJhY3RlclxuICAgICAgICAgKiBzZXF1ZW5jZXMgd2l0aCB0aGUgZGVmYXVsdCByZXBsYWNlbWVudCBzdHJpbmcgZm9yIHRoZSBwbGF0Zm9ybSdzXG4gICAgICAgICAqIGRlZmF1bHQgY2hhcmFjdGVyIHNldC4gVGhlIHtAbGlua3BsYWluIGphdmEubmlvLmNoYXJzZXQuQ2hhcnNldERlY29kZXJ9XG4gICAgICAgICAqIGNsYXNzIHNob3VsZCBiZSB1c2VkIHdoZW4gbW9yZSBjb250cm9sIG92ZXIgdGhlIGRlY29kaW5nIHByb2Nlc3MgaXNcbiAgICAgICAgICogcmVxdWlyZWQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gU3RyaW5nIGRlY29kZWQgZnJvbSB0aGUgYnVmZmVyJ3MgY29udGVudHMuXG4gICAgICAgICAqIEBzaW5jZSAgSkRLMS4xXG4gICAgICAgICAqL1xuICAgICAgICB0b1N0cmluZ192b2lkKCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBTdHJpbmcodGhpcy5idWYgLyosIDAsIHRoaXMuY291bnQqLykudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ29udmVydHMgdGhlIGJ1ZmZlcidzIGNvbnRlbnRzIGludG8gYSBzdHJpbmcgYnkgZGVjb2RpbmcgdGhlIGJ5dGVzIHVzaW5nXG4gICAgICAgICAqIHRoZSBzcGVjaWZpZWQge0BsaW5rIGphdmEubmlvLmNoYXJzZXQuQ2hhcnNldCBjaGFyc2V0TmFtZX0uIFRoZSBsZW5ndGggb2ZcbiAgICAgICAgICogdGhlIG5ldyA8dHQ+U3RyaW5nPC90dD4gaXMgYSBmdW5jdGlvbiBvZiB0aGUgY2hhcnNldCwgYW5kIGhlbmNlIG1heSBub3QgYmVcbiAgICAgICAgICogZXF1YWwgdG8gdGhlIGxlbmd0aCBvZiB0aGUgYnl0ZSBhcnJheS5cbiAgICAgICAgICpcbiAgICAgICAgICogPHA+IFRoaXMgbWV0aG9kIGFsd2F5cyByZXBsYWNlcyBtYWxmb3JtZWQtaW5wdXQgYW5kIHVubWFwcGFibGUtY2hhcmFjdGVyXG4gICAgICAgICAqIHNlcXVlbmNlcyB3aXRoIHRoaXMgY2hhcnNldCdzIGRlZmF1bHQgcmVwbGFjZW1lbnQgc3RyaW5nLiBUaGUge0BsaW5rXG4gICAgICAgICAqIGphdmEubmlvLmNoYXJzZXQuQ2hhcnNldERlY29kZXJ9IGNsYXNzIHNob3VsZCBiZSB1c2VkIHdoZW4gbW9yZSBjb250cm9sXG4gICAgICAgICAqIG92ZXIgdGhlIGRlY29kaW5nIHByb2Nlc3MgaXMgcmVxdWlyZWQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSAgY2hhcnNldE5hbWUgIHRoZSBuYW1lIG9mIGEgc3VwcG9ydGVkXG4gICAgICAgICAqICAgICAgICAgICAgICB7QGxpbmtwbGFpbiBqYXZhLm5pby5jaGFyc2V0LkNoYXJzZXQgPC9jb2RlPmNoYXJzZXQ8Y29kZT59XG4gICAgICAgICAqIEByZXR1cm4gU3RyaW5nIGRlY29kZWQgZnJvbSB0aGUgYnVmZmVyJ3MgY29udGVudHMuXG4gICAgICAgICAqIEBleGNlcHRpb24gIFVuc3VwcG9ydGVkRW5jb2RpbmdFeGNlcHRpb25cbiAgICAgICAgICogICAgICAgICAgICAgSWYgdGhlIG5hbWVkIGNoYXJzZXQgaXMgbm90IHN1cHBvcnRlZFxuICAgICAgICAgKiBAc2luY2UgICBKREsxLjFcbiAgICAgICAgICovXG4gICAgICAgIHRvU3RyaW5nX3N0cmluZyhjaGFyc2V0TmFtZSkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBTdHJpbmcodGhpcy5idWYgLyosIDAsIHRoaXMuY291bnQsIGNoYXJzZXROYW1lKi8pLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBuZXdseSBhbGxvY2F0ZWQgc3RyaW5nLiBJdHMgc2l6ZSBpcyB0aGUgY3VycmVudCBzaXplIG9mXG4gICAgICAgICAqIHRoZSBvdXRwdXQgc3RyZWFtIGFuZCB0aGUgdmFsaWQgY29udGVudHMgb2YgdGhlIGJ1ZmZlciBoYXZlIGJlZW5cbiAgICAgICAgICogY29waWVkIGludG8gaXQuIEVhY2ggY2hhcmFjdGVyIDxpPmM8L2k+IGluIHRoZSByZXN1bHRpbmcgc3RyaW5nIGlzXG4gICAgICAgICAqIGNvbnN0cnVjdGVkIGZyb20gdGhlIGNvcnJlc3BvbmRpbmcgZWxlbWVudCA8aT5iPC9pPiBpbiB0aGUgYnl0ZVxuICAgICAgICAgKiBhcnJheSBzdWNoIHRoYXQ6XG4gICAgICAgICAqIDxibG9ja3F1b3RlPjxwcmU+XG4gICAgICAgICAqICAgICBjID09IChjaGFyKSgoKGhpYnl0ZSAmYW1wOyAweGZmKSAmbHQ7Jmx0OyA4KSB8IChiICZhbXA7IDB4ZmYpKVxuICAgICAgICAgKiA8L3ByZT48L2Jsb2NrcXVvdGU+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBkZXByZWNhdGVkIFRoaXMgbWV0aG9kIGRvZXMgbm90IHByb3Blcmx5IGNvbnZlcnQgYnl0ZXMgaW50byBjaGFyYWN0ZXJzLlxuICAgICAgICAgKiBBcyBvZiBKREsmbmJzcDsxLjEsIHRoZSBwcmVmZXJyZWQgd2F5IHRvIGRvIHRoaXMgaXMgdmlhIHRoZVxuICAgICAgICAgKiA8Y29kZT50b1N0cmluZyhTdHJpbmcgZW5jKTwvY29kZT4gbWV0aG9kLCB3aGljaCB0YWtlcyBhbiBlbmNvZGluZy1uYW1lXG4gICAgICAgICAqIGFyZ3VtZW50LCBvciB0aGUgPGNvZGU+dG9TdHJpbmcoKTwvY29kZT4gbWV0aG9kLCB3aGljaCB1c2VzIHRoZVxuICAgICAgICAgKiBwbGF0Zm9ybSdzIGRlZmF1bHQgY2hhcmFjdGVyIGVuY29kaW5nLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gICAgICBoaWJ5dGUgICAgdGhlIGhpZ2ggYnl0ZSBvZiBlYWNoIHJlc3VsdGluZyBVbmljb2RlIGNoYXJhY3Rlci5cbiAgICAgICAgICogQHJldHVybiAgICAgdGhlIGN1cnJlbnQgY29udGVudHMgb2YgdGhlIG91dHB1dCBzdHJlYW0sIGFzIGEgc3RyaW5nLlxuICAgICAgICAgKiBAc2VlICAgICAgICBqYXZhLmlvLkJ5dGVBcnJheU91dHB1dFN0cmVhbSNzaXplKClcbiAgICAgICAgICogQHNlZSAgICAgICAgamF2YS5pby5CeXRlQXJyYXlPdXRwdXRTdHJlYW0jdG9TdHJpbmcoU3RyaW5nKVxuICAgICAgICAgKiBAc2VlICAgICAgICBqYXZhLmlvLkJ5dGVBcnJheU91dHB1dFN0cmVhbSN0b1N0cmluZygpXG4gICAgICAgICAqL1xuICAgICAgICAvLyBARGVwcmVjYXRlZFxuICAgICAgICB0b1N0cmluZ19udW1iZXIoaGlieXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFN0cmluZyh0aGlzLmJ1ZiAvKiwgaGlieXRlLCAwLCB0aGlzLmNvdW50Ki8pLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENsb3NpbmcgYSA8dHQ+Qnl0ZUFycmF5T3V0cHV0U3RyZWFtPC90dD4gaGFzIG5vIGVmZmVjdC4gVGhlIG1ldGhvZHMgaW5cbiAgICAgICAgICogdGhpcyBjbGFzcyBjYW4gYmUgY2FsbGVkIGFmdGVyIHRoZSBzdHJlYW0gaGFzIGJlZW4gY2xvc2VkIHdpdGhvdXRcbiAgICAgICAgICogZ2VuZXJhdGluZyBhbiA8dHQ+SU9FeGNlcHRpb248L3R0Pi5cbiAgICAgICAgICogPHA+XG4gICAgICAgICAqXG4gICAgICAgICAqIEB0aHJvd3MgSU9FeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIGNsb3NlKCkge1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwOSBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKnByaXZhdGUqLyB2YXIgTW9kZSQyO1xuICAgIChmdW5jdGlvbiAoTW9kZSkge1xuICAgICAgICBNb2RlW01vZGVbXCJBTFBIQVwiXSA9IDBdID0gXCJBTFBIQVwiO1xuICAgICAgICBNb2RlW01vZGVbXCJMT1dFUlwiXSA9IDFdID0gXCJMT1dFUlwiO1xuICAgICAgICBNb2RlW01vZGVbXCJNSVhFRFwiXSA9IDJdID0gXCJNSVhFRFwiO1xuICAgICAgICBNb2RlW01vZGVbXCJQVU5DVFwiXSA9IDNdID0gXCJQVU5DVFwiO1xuICAgICAgICBNb2RlW01vZGVbXCJBTFBIQV9TSElGVFwiXSA9IDRdID0gXCJBTFBIQV9TSElGVFwiO1xuICAgICAgICBNb2RlW01vZGVbXCJQVU5DVF9TSElGVFwiXSA9IDVdID0gXCJQVU5DVF9TSElGVFwiO1xuICAgIH0pKE1vZGUkMiB8fCAoTW9kZSQyID0ge30pKTtcbiAgICAvKipcbiAgICAgKiBJbmRpcmVjdGx5IGFjY2VzcyB0aGUgZ2xvYmFsIEJpZ0ludCBjb25zdHJ1Y3RvciwgaXRcbiAgICAgKiBhbGxvd3MgYnJvd3NlcnMgdGhhdCBkb2Vzbid0IHN1cHBvcnQgQmlnSW50IHRvIHJ1blxuICAgICAqIHRoZSBsaWJyYXJ5IHdpdGhvdXQgYnJlYWtpbmcgZHVlIHRvIFwidW5kZWZpbmVkIEJpZ0ludFwiXG4gICAgICogZXJyb3JzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldEJpZ0ludENvbnN0cnVjdG9yKCkge1xuICAgICAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHJldHVybiB3aW5kb3dbJ0JpZ0ludCddIHx8IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICByZXR1cm4gZ2xvYmFsWydCaWdJbnQnXSB8fCBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHJldHVybiBzZWxmWydCaWdJbnQnXSB8fCBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuXFwndCBzZWFyY2ggZ2xvYmFscyBmb3IgQmlnSW50IScpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBVc2VkIHRvIHN0b3JlIHRoZSBCaWdJbnQgY29uc3RydWN0b3IuXG4gICAgICovXG4gICAgbGV0IEJpZ0ludGVnZXI7XG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiBjcmVhdGVzIGEgYmlnaW50IHZhbHVlLiBJdCBhbGxvd3MgYnJvd3NlcnNcbiAgICAgKiB0aGF0IGRvZXNuJ3Qgc3VwcG9ydCBCaWdJbnQgdG8gcnVuIHRoZSByZXN0IG9mIHRoZSBsaWJyYXJ5XG4gICAgICogYnkgbm90IGRpcmVjdGx5IGFjY2Vzc2luZyB0aGUgQmlnSW50IGNvbnN0cnVjdG9yLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUJpZ0ludChudW0pIHtcbiAgICAgICAgaWYgKHR5cGVvZiBCaWdJbnRlZ2VyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgQmlnSW50ZWdlciA9IGdldEJpZ0ludENvbnN0cnVjdG9yKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKEJpZ0ludGVnZXIgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQmlnSW50IGlzIG5vdCBzdXBwb3J0ZWQhJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIEJpZ0ludGVnZXIobnVtKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZ2V0RVhQOTAwKCkge1xuICAgICAgICAvLyBpbiBKYXZhIC0gYXJyYXkgd2l0aCBsZW5ndGggPSAxNlxuICAgICAgICBsZXQgRVhQOTAwID0gW107XG4gICAgICAgIEVYUDkwMFswXSA9IGNyZWF0ZUJpZ0ludCgxKTtcbiAgICAgICAgbGV0IG5pbmVIdW5kcmVkID0gY3JlYXRlQmlnSW50KDkwMCk7XG4gICAgICAgIEVYUDkwMFsxXSA9IG5pbmVIdW5kcmVkO1xuICAgICAgICAvLyBpbiBKYXZhIC0gYXJyYXkgd2l0aCBsZW5ndGggPSAxNlxuICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAyOyBpIDwgMTY7IGkrKykge1xuICAgICAgICAgICAgRVhQOTAwW2ldID0gRVhQOTAwW2kgLSAxXSAqIG5pbmVIdW5kcmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBFWFA5MDA7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIDxwPlRoaXMgY2xhc3MgY29udGFpbnMgdGhlIG1ldGhvZHMgZm9yIGRlY29kaW5nIHRoZSBQREY0MTcgY29kZXdvcmRzLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU0lUQSBMYWIgKGtldmluLm9zdWxsaXZhbkBzaXRhLmFlcm8pXG4gICAgICogQGF1dGhvciBHdWVudGhlciBHcmF1XG4gICAgICovXG4gICAgLypmaW5hbCovIGNsYXNzIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMiB7XG4gICAgICAgIC8vICAgcHJpdmF0ZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyKCkge1xuICAgICAgICAvLyB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gY29kZXdvcmRzXG4gICAgICAgICAqIEBwYXJhbSBlY0xldmVsXG4gICAgICAgICAqXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGVjb2RlKGNvZGV3b3JkcywgZWNMZXZlbCkge1xuICAgICAgICAgICAgLy8gcGFzcyBlbmNvZGluZyB0byByZXN1bHQgKHdpbGwgYmUgdXNlZCBmb3IgZGVjb2RlIHN5bWJvbHMgaW4gYnl0ZSBtb2RlKVxuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IG5ldyBTdHJpbmdCdWlsZGVyKCcnKTtcbiAgICAgICAgICAgIC8vIGxldCBlbmNvZGluZzogQ2hhcnNldCA9IFN0YW5kYXJkQ2hhcnNldHMuSVNPXzg4NTlfMTtcbiAgICAgICAgICAgIGxldCBlbmNvZGluZyA9IENoYXJhY3RlclNldEVDSS5JU084ODU5XzE7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEBub3RlIHRoZSBuZXh0IGNvbW1hbmQgaXMgc3BlY2lmaWMgZnJvbSB0aGlzIFR5cGVTY3JpcHQgbGlicmFyeVxuICAgICAgICAgICAgICogYmVjYXVzZSBUUyBjYW4ndCBwcm9wZXJseSBjYXN0IHNvbWUgdmFsdWVzIHRvIGNoYXIgYW5kXG4gICAgICAgICAgICAgKiBjb252ZXJ0IGl0IHRvIHN0cmluZyBsYXRlciBjb3JyZWN0bHkgZHVlIHRvIGVuY29kaW5nXG4gICAgICAgICAgICAgKiBkaWZmZXJlbmNlcyBmcm9tIEphdmEgdmVyc2lvbi4gQXMgcmVwb3J0ZWQgaGVyZTpcbiAgICAgICAgICAgICAqIGh0dHBzOi8vZ2l0aHViLmNvbS96eGluZy1qcy9saWJyYXJ5L3B1bGwvMjY0L2ZpbGVzI3IzODI4MzE1OTNcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgcmVzdWx0LmVuYWJsZURlY29kaW5nKGVuY29kaW5nKTtcbiAgICAgICAgICAgIC8vIEdldCBjb21wYWN0aW9uIG1vZGVcbiAgICAgICAgICAgIGxldCBjb2RlSW5kZXggPSAxO1xuICAgICAgICAgICAgbGV0IGNvZGUgPSBjb2Rld29yZHNbY29kZUluZGV4KytdO1xuICAgICAgICAgICAgbGV0IHJlc3VsdE1ldGFkYXRhID0gbmV3IFBERjQxN1Jlc3VsdE1ldGFkYXRhKCk7XG4gICAgICAgICAgICB3aGlsZSAoY29kZUluZGV4IDwgY29kZXdvcmRzWzBdKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChjb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlRFWFRfQ09NUEFDVElPTl9NT0RFX0xBVENIOlxuICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4ID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLnRleHRDb21wYWN0aW9uKGNvZGV3b3JkcywgY29kZUluZGV4LCByZXN1bHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJZVEVfQ09NUEFDVElPTl9NT0RFX0xBVENIOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CWVRFX0NPTVBBQ1RJT05fTU9ERV9MQVRDSF82OlxuICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4ID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLmJ5dGVDb21wYWN0aW9uKGNvZGUsIGNvZGV3b3JkcywgZW5jb2RpbmcsIGNvZGVJbmRleCwgcmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NT0RFX1NISUZUX1RPX0JZVEVfQ09NUEFDVElPTl9NT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgvKihjaGFyKSovIGNvZGV3b3Jkc1tjb2RlSW5kZXgrK10pO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk5VTUVSSUNfQ09NUEFDVElPTl9NT0RFX0xBVENIOlxuICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4ID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLm51bWVyaWNDb21wYWN0aW9uKGNvZGV3b3JkcywgY29kZUluZGV4LCByZXN1bHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkVDSV9DSEFSU0VUOlxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNoYXJzZXRFQ0kgPSBDaGFyYWN0ZXJTZXRFQ0kuZ2V0Q2hhcmFjdGVyU2V0RUNJQnlWYWx1ZShjb2Rld29yZHNbY29kZUluZGV4KytdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGVuY29kaW5nID0gQ2hhcnNldC5mb3JOYW1lKGNoYXJzZXRFQ0kuZ2V0TmFtZSgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5FQ0lfR0VORVJBTF9QVVJQT1NFOlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2FuJ3QgZG8gYW55dGhpbmcgd2l0aCBnZW5lcmljIEVDSTsgc2tpcCBpdHMgMiBjaGFyYWN0ZXJzXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2RlSW5kZXggKz0gMjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5FQ0lfVVNFUl9ERUZJTkVEOlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2FuJ3QgZG8gYW55dGhpbmcgd2l0aCB1c2VyIEVDSTsgc2tpcCBpdHMgMSBjaGFyYWN0ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJFR0lOX01BQ1JPX1BERjQxN19DT05UUk9MX0JMT0NLOlxuICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4ID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLmRlY29kZU1hY3JvQmxvY2soY29kZXdvcmRzLCBjb2RlSW5kZXgsIHJlc3VsdE1ldGFkYXRhKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CRUdJTl9NQUNST19QREY0MTdfT1BUSU9OQUxfRklFTEQ6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BQ1JPX1BERjQxN19URVJNSU5BVE9SOlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2hvdWxkIG5vdCBzZWUgdGhlc2Ugb3V0c2lkZSBhIG1hY3JvIGJsb2NrXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEZWZhdWx0IHRvIHRleHQgY29tcGFjdGlvbi4gRHVyaW5nIHRlc3RpbmcgbnVtZXJvdXMgYmFyY29kZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFwcGVhcmVkIHRvIGJlIG1pc3NpbmcgdGhlIHN0YXJ0aW5nIG1vZGUuIEluIHRoZXNlIGNhc2VzIGRlZmF1bHRpbmdcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRvIHRleHQgY29tcGFjdGlvbiBzZWVtcyB0byB3b3JrLlxuICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4LS07XG4gICAgICAgICAgICAgICAgICAgICAgICBjb2RlSW5kZXggPSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIudGV4dENvbXBhY3Rpb24oY29kZXdvcmRzLCBjb2RlSW5kZXgsIHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGNvZGVJbmRleCA8IGNvZGV3b3Jkcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgY29kZSA9IGNvZGV3b3Jkc1tjb2RlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBGb3JtYXRFeGNlcHRpb24uZ2V0Rm9ybWF0SW5zdGFuY2UoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCgpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgRm9ybWF0RXhjZXB0aW9uLmdldEZvcm1hdEluc3RhbmNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZGVjb2RlclJlc3VsdCA9IG5ldyBEZWNvZGVyUmVzdWx0KG51bGwsIHJlc3VsdC50b1N0cmluZygpLCBudWxsLCBlY0xldmVsKTtcbiAgICAgICAgICAgIGRlY29kZXJSZXN1bHQuc2V0T3RoZXIocmVzdWx0TWV0YWRhdGEpO1xuICAgICAgICAgICAgcmV0dXJuIGRlY29kZXJSZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBpbnRcbiAgICAgICAgICogQHBhcmFtIHBhcmFtMVxuICAgICAgICAgKiBAcGFyYW0gY29kZXdvcmRzXG4gICAgICAgICAqIEBwYXJhbSBpbnRcbiAgICAgICAgICogQHBhcmFtIGNvZGVJbmRleFxuICAgICAgICAgKiBAcGFyYW0gUERGNDE3UmVzdWx0TWV0YWRhdGFcbiAgICAgICAgICogQHBhcmFtIHJlc3VsdE1ldGFkYXRhXG4gICAgICAgICAqXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uXG4gICAgICAgICAqL1xuICAgICAgICAvLyBAU3VwcHJlc3NXYXJuaW5ncyhcImRlcHJlY2F0aW9uXCIpXG4gICAgICAgIHN0YXRpYyBkZWNvZGVNYWNyb0Jsb2NrKGNvZGV3b3JkcywgY29kZUluZGV4LCByZXN1bHRNZXRhZGF0YSkge1xuICAgICAgICAgICAgaWYgKGNvZGVJbmRleCArIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5OVU1CRVJfT0ZfU0VRVUVOQ0VfQ09ERVdPUkRTID4gY29kZXdvcmRzWzBdKSB7XG4gICAgICAgICAgICAgICAgLy8gd2UgbXVzdCBoYXZlIGF0IGxlYXN0IHR3byBieXRlcyBsZWZ0IGZvciB0aGUgc2VnbWVudCBpbmRleFxuICAgICAgICAgICAgICAgIHRocm93IEZvcm1hdEV4Y2VwdGlvbi5nZXRGb3JtYXRJbnN0YW5jZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHNlZ21lbnRJbmRleEFycmF5ID0gbmV3IEludDMyQXJyYXkoRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk5VTUJFUl9PRl9TRVFVRU5DRV9DT0RFV09SRFMpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMDsgaSA8IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5OVU1CRVJfT0ZfU0VRVUVOQ0VfQ09ERVdPUkRTOyBpKyssIGNvZGVJbmRleCsrKSB7XG4gICAgICAgICAgICAgICAgc2VnbWVudEluZGV4QXJyYXlbaV0gPSBjb2Rld29yZHNbY29kZUluZGV4XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc3VsdE1ldGFkYXRhLnNldFNlZ21lbnRJbmRleChJbnRlZ2VyLnBhcnNlSW50KERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5kZWNvZGVCYXNlOTAwdG9CYXNlMTAoc2VnbWVudEluZGV4QXJyYXksIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5OVU1CRVJfT0ZfU0VRVUVOQ0VfQ09ERVdPUkRTKSkpO1xuICAgICAgICAgICAgbGV0IGZpbGVJZCA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICBjb2RlSW5kZXggPSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIudGV4dENvbXBhY3Rpb24oY29kZXdvcmRzLCBjb2RlSW5kZXgsIGZpbGVJZCk7XG4gICAgICAgICAgICByZXN1bHRNZXRhZGF0YS5zZXRGaWxlSWQoZmlsZUlkLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgbGV0IG9wdGlvbmFsRmllbGRzU3RhcnQgPSAtMTtcbiAgICAgICAgICAgIGlmIChjb2Rld29yZHNbY29kZUluZGV4XSA9PT0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJFR0lOX01BQ1JPX1BERjQxN19PUFRJT05BTF9GSUVMRCkge1xuICAgICAgICAgICAgICAgIG9wdGlvbmFsRmllbGRzU3RhcnQgPSBjb2RlSW5kZXggKyAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2hpbGUgKGNvZGVJbmRleCA8IGNvZGV3b3Jkc1swXSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoY29kZXdvcmRzW2NvZGVJbmRleF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQkVHSU5fTUFDUk9fUERGNDE3X09QVElPTkFMX0ZJRUxEOlxuICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGNvZGV3b3Jkc1tjb2RlSW5kZXhdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUFDUk9fUERGNDE3X09QVElPTkFMX0ZJRUxEX0ZJTEVfTkFNRTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGZpbGVOYW1lID0gbmV3IFN0cmluZ0J1aWxkZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4ID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLnRleHRDb21wYWN0aW9uKGNvZGV3b3JkcywgY29kZUluZGV4ICsgMSwgZmlsZU5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRNZXRhZGF0YS5zZXRGaWxlTmFtZShmaWxlTmFtZS50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUFDUk9fUERGNDE3X09QVElPTkFMX0ZJRUxEX1NFTkRFUjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNlbmRlciA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVJbmRleCA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi50ZXh0Q29tcGFjdGlvbihjb2Rld29yZHMsIGNvZGVJbmRleCArIDEsIHNlbmRlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdE1ldGFkYXRhLnNldFNlbmRlcihzZW5kZXIudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BQ1JPX1BERjQxN19PUFRJT05BTF9GSUVMRF9BRERSRVNTRUU6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBhZGRyZXNzZWUgPSBuZXcgU3RyaW5nQnVpbGRlcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2RlSW5kZXggPSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIudGV4dENvbXBhY3Rpb24oY29kZXdvcmRzLCBjb2RlSW5kZXggKyAxLCBhZGRyZXNzZWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRNZXRhZGF0YS5zZXRBZGRyZXNzZWUoYWRkcmVzc2VlLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQUNST19QREY0MTdfT1BUSU9OQUxfRklFTERfU0VHTUVOVF9DT1VOVDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNlZ21lbnRDb3VudCA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVJbmRleCA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5udW1lcmljQ29tcGFjdGlvbihjb2Rld29yZHMsIGNvZGVJbmRleCArIDEsIHNlZ21lbnRDb3VudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdE1ldGFkYXRhLnNldFNlZ21lbnRDb3VudChJbnRlZ2VyLnBhcnNlSW50KHNlZ21lbnRDb3VudC50b1N0cmluZygpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BQ1JPX1BERjQxN19PUFRJT05BTF9GSUVMRF9USU1FX1NUQU1QOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgdGltZXN0YW1wID0gbmV3IFN0cmluZ0J1aWxkZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4ID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLm51bWVyaWNDb21wYWN0aW9uKGNvZGV3b3JkcywgY29kZUluZGV4ICsgMSwgdGltZXN0YW1wKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0TWV0YWRhdGEuc2V0VGltZXN0YW1wKExvbmcucGFyc2VMb25nKHRpbWVzdGFtcC50b1N0cmluZygpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BQ1JPX1BERjQxN19PUFRJT05BTF9GSUVMRF9DSEVDS1NVTTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNoZWNrc3VtID0gbmV3IFN0cmluZ0J1aWxkZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4ID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLm51bWVyaWNDb21wYWN0aW9uKGNvZGV3b3JkcywgY29kZUluZGV4ICsgMSwgY2hlY2tzdW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRNZXRhZGF0YS5zZXRDaGVja3N1bShJbnRlZ2VyLnBhcnNlSW50KGNoZWNrc3VtLnRvU3RyaW5nKCkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUFDUk9fUERGNDE3X09QVElPTkFMX0ZJRUxEX0ZJTEVfU0laRTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGZpbGVTaXplID0gbmV3IFN0cmluZ0J1aWxkZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4ID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLm51bWVyaWNDb21wYWN0aW9uKGNvZGV3b3JkcywgY29kZUluZGV4ICsgMSwgZmlsZVNpemUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRNZXRhZGF0YS5zZXRGaWxlU2l6ZShMb25nLnBhcnNlTG9uZyhmaWxlU2l6ZS50b1N0cmluZygpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IEZvcm1hdEV4Y2VwdGlvbi5nZXRGb3JtYXRJbnN0YW5jZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BQ1JPX1BERjQxN19URVJNSU5BVE9SOlxuICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRNZXRhZGF0YS5zZXRMYXN0U2VnbWVudCh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgRm9ybWF0RXhjZXB0aW9uLmdldEZvcm1hdEluc3RhbmNlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gY29weSBvcHRpb25hbCBmaWVsZHMgdG8gYWRkaXRpb25hbCBvcHRpb25zXG4gICAgICAgICAgICBpZiAob3B0aW9uYWxGaWVsZHNTdGFydCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBsZXQgb3B0aW9uYWxGaWVsZHNMZW5ndGggPSBjb2RlSW5kZXggLSBvcHRpb25hbEZpZWxkc1N0YXJ0O1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHRNZXRhZGF0YS5pc0xhc3RTZWdtZW50KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gZG8gbm90IGluY2x1ZGUgdGVybWluYXRvclxuICAgICAgICAgICAgICAgICAgICBvcHRpb25hbEZpZWxkc0xlbmd0aC0tO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXN1bHRNZXRhZGF0YS5zZXRPcHRpb25hbERhdGEoQXJyYXlzLmNvcHlPZlJhbmdlKGNvZGV3b3Jkcywgb3B0aW9uYWxGaWVsZHNTdGFydCwgb3B0aW9uYWxGaWVsZHNTdGFydCArIG9wdGlvbmFsRmllbGRzTGVuZ3RoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY29kZUluZGV4O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUZXh0IENvbXBhY3Rpb24gbW9kZSAoc2VlIDUuNC4xLjUpIHBlcm1pdHMgYWxsIHByaW50YWJsZSBBU0NJSSBjaGFyYWN0ZXJzIHRvIGJlXG4gICAgICAgICAqIGVuY29kZWQsIGkuZS4gdmFsdWVzIDMyIC0gMTI2IGluY2x1c2l2ZSBpbiBhY2NvcmRhbmNlIHdpdGggSVNPL0lFQyA2NDYgKElSViksIGFzXG4gICAgICAgICAqIHdlbGwgYXMgc2VsZWN0ZWQgY29udHJvbCBjaGFyYWN0ZXJzLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gY29kZXdvcmRzIFRoZSBhcnJheSBvZiBjb2Rld29yZHMgKGRhdGEgKyBlcnJvcilcbiAgICAgICAgICogQHBhcmFtIGNvZGVJbmRleCBUaGUgY3VycmVudCBpbmRleCBpbnRvIHRoZSBjb2Rld29yZCBhcnJheS5cbiAgICAgICAgICogQHBhcmFtIHJlc3VsdCAgICBUaGUgZGVjb2RlZCBkYXRhIGlzIGFwcGVuZGVkIHRvIHRoZSByZXN1bHQuXG4gICAgICAgICAqIEByZXR1cm4gVGhlIG5leHQgaW5kZXggaW50byB0aGUgY29kZXdvcmQgYXJyYXkuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgdGV4dENvbXBhY3Rpb24oY29kZXdvcmRzLCBjb2RlSW5kZXgsIHJlc3VsdCkge1xuICAgICAgICAgICAgLy8gMiBjaGFyYWN0ZXIgcGVyIGNvZGV3b3JkXG4gICAgICAgICAgICBsZXQgdGV4dENvbXBhY3Rpb25EYXRhID0gbmV3IEludDMyQXJyYXkoKGNvZGV3b3Jkc1swXSAtIGNvZGVJbmRleCkgKiAyKTtcbiAgICAgICAgICAgIC8vIFVzZWQgdG8gaG9sZCB0aGUgYnl0ZSBjb21wYWN0aW9uIHZhbHVlIGlmIHRoZXJlIGlzIGEgbW9kZSBzaGlmdFxuICAgICAgICAgICAgbGV0IGJ5dGVDb21wYWN0aW9uRGF0YSA9IG5ldyBJbnQzMkFycmF5KChjb2Rld29yZHNbMF0gLSBjb2RlSW5kZXgpICogMik7XG4gICAgICAgICAgICBsZXQgaW5kZXggPSAwO1xuICAgICAgICAgICAgbGV0IGVuZCA9IGZhbHNlO1xuICAgICAgICAgICAgd2hpbGUgKChjb2RlSW5kZXggPCBjb2Rld29yZHNbMF0pICYmICFlbmQpIHtcbiAgICAgICAgICAgICAgICBsZXQgY29kZSA9IGNvZGV3b3Jkc1tjb2RlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgaWYgKGNvZGUgPCBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuVEVYVF9DT01QQUNUSU9OX01PREVfTEFUQ0gpIHtcbiAgICAgICAgICAgICAgICAgICAgdGV4dENvbXBhY3Rpb25EYXRhW2luZGV4XSA9IGNvZGUgLyAzMDtcbiAgICAgICAgICAgICAgICAgICAgdGV4dENvbXBhY3Rpb25EYXRhW2luZGV4ICsgMV0gPSBjb2RlICUgMzA7XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGNvZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlRFWFRfQ09NUEFDVElPTl9NT0RFX0xBVENIOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlaW5pdGlhbGl6ZSB0ZXh0IGNvbXBhY3Rpb24gbW9kZSB0byBhbHBoYSBzdWIgbW9kZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHRDb21wYWN0aW9uRGF0YVtpbmRleCsrXSA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5URVhUX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJZVEVfQ09NUEFDVElPTl9NT0RFX0xBVENIOlxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQllURV9DT01QQUNUSU9OX01PREVfTEFUQ0hfNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk5VTUVSSUNfQ09NUEFDVElPTl9NT0RFX0xBVENIOlxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQkVHSU5fTUFDUk9fUERGNDE3X0NPTlRST0xfQkxPQ0s6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CRUdJTl9NQUNST19QREY0MTdfT1BUSU9OQUxfRklFTEQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQUNST19QREY0MTdfVEVSTUlOQVRPUjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2RlSW5kZXgtLTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTU9ERV9TSElGVF9UT19CWVRFX0NPTVBBQ1RJT05fTU9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgTW9kZSBTaGlmdCBjb2Rld29yZCA5MTMgc2hhbGwgY2F1c2UgYSB0ZW1wb3JhcnlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBzd2l0Y2ggZnJvbSBUZXh0IENvbXBhY3Rpb24gbW9kZSB0byBCeXRlIENvbXBhY3Rpb24gbW9kZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHN3aXRjaCBzaGFsbCBiZSBpbiBlZmZlY3QgZm9yIG9ubHkgdGhlIG5leHQgY29kZXdvcmQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWZ0ZXIgd2hpY2ggdGhlIG1vZGUgc2hhbGwgcmV2ZXJ0IHRvIHRoZSBwcmV2YWlsaW5nIHN1Yi1tb2RlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb2YgdGhlIFRleHQgQ29tcGFjdGlvbiBtb2RlLiBDb2Rld29yZCA5MTMgaXMgb25seSBhdmFpbGFibGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBUZXh0IENvbXBhY3Rpb24gbW9kZTsgaXRzIHVzZSBpcyBkZXNjcmliZWQgaW4gNS40LjIuNC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0Q29tcGFjdGlvbkRhdGFbaW5kZXhdID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1PREVfU0hJRlRfVE9fQllURV9DT01QQUNUSU9OX01PREU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZSA9IGNvZGV3b3Jkc1tjb2RlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZUNvbXBhY3Rpb25EYXRhW2luZGV4XSA9IGNvZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5kZWNvZGVUZXh0Q29tcGFjdGlvbih0ZXh0Q29tcGFjdGlvbkRhdGEsIGJ5dGVDb21wYWN0aW9uRGF0YSwgaW5kZXgsIHJlc3VsdCk7XG4gICAgICAgICAgICByZXR1cm4gY29kZUluZGV4O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgVGV4dCBDb21wYWN0aW9uIG1vZGUgaW5jbHVkZXMgYWxsIHRoZSBwcmludGFibGUgQVNDSUkgY2hhcmFjdGVyc1xuICAgICAgICAgKiAoaS5lLiB2YWx1ZXMgZnJvbSAzMiB0byAxMjYpIGFuZCB0aHJlZSBBU0NJSSBjb250cm9sIGNoYXJhY3RlcnM6IEhUIG9yIHRhYlxuICAgICAgICAgKiAoOTogZSksIExGIG9yIGxpbmUgZmVlZCAoMTA6IGUpLCBhbmQgQ1Igb3IgY2FycmlhZ2VcbiAgICAgICAgICogcmV0dXJuICgxMzogZSkuIFRoZSBUZXh0IENvbXBhY3Rpb24gbW9kZSBhbHNvIGluY2x1ZGVzIHZhcmlvdXMgbGF0Y2hcbiAgICAgICAgICogYW5kIHNoaWZ0IGNoYXJhY3RlcnMgd2hpY2ggYXJlIHVzZWQgZXhjbHVzaXZlbHkgd2l0aGluIHRoZSBtb2RlLiBUaGUgVGV4dFxuICAgICAgICAgKiBDb21wYWN0aW9uIG1vZGUgZW5jb2RlcyB1cCB0byAyIGNoYXJhY3RlcnMgcGVyIGNvZGV3b3JkLiBUaGUgY29tcGFjdGlvbiBydWxlc1xuICAgICAgICAgKiBmb3IgY29udmVydGluZyBkYXRhIGludG8gUERGNDE3IGNvZGV3b3JkcyBhcmUgZGVmaW5lZCBpbiA1LjQuMi4yLiBUaGUgc3ViLW1vZGVcbiAgICAgICAgICogc3dpdGNoZXMgYXJlIGRlZmluZWQgaW4gNS40LjIuMy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHRleHRDb21wYWN0aW9uRGF0YSBUaGUgdGV4dCBjb21wYWN0aW9uIGRhdGEuXG4gICAgICAgICAqIEBwYXJhbSBieXRlQ29tcGFjdGlvbkRhdGEgVGhlIGJ5dGUgY29tcGFjdGlvbiBkYXRhIGlmIHRoZXJlXG4gICAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FzIGEgbW9kZSBzaGlmdC5cbiAgICAgICAgICogQHBhcmFtIGxlbmd0aCAgICAgICAgICAgICBUaGUgc2l6ZSBvZiB0aGUgdGV4dCBjb21wYWN0aW9uIGFuZCBieXRlIGNvbXBhY3Rpb24gZGF0YS5cbiAgICAgICAgICogQHBhcmFtIHJlc3VsdCAgICAgICAgICAgICBUaGUgZGVjb2RlZCBkYXRhIGlzIGFwcGVuZGVkIHRvIHRoZSByZXN1bHQuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGVjb2RlVGV4dENvbXBhY3Rpb24odGV4dENvbXBhY3Rpb25EYXRhLCBieXRlQ29tcGFjdGlvbkRhdGEsIGxlbmd0aCwgcmVzdWx0KSB7XG4gICAgICAgICAgICAvLyBCZWdpbm5pbmcgZnJvbSBhbiBpbml0aWFsIHN0YXRlIG9mIHRoZSBBbHBoYSBzdWItbW9kZVxuICAgICAgICAgICAgLy8gVGhlIGRlZmF1bHQgY29tcGFjdGlvbiBtb2RlIGZvciBQREY0MTcgaW4gZWZmZWN0IGF0IHRoZSBzdGFydCBvZiBlYWNoIHN5bWJvbCBzaGFsbCBhbHdheXMgYmUgVGV4dFxuICAgICAgICAgICAgLy8gQ29tcGFjdGlvbiBtb2RlIEFscGhhIHN1Yi1tb2RlIChhbHBoYWJldGljOiB1cHBlcmNhc2UpLiBBIGxhdGNoIGNvZGV3b3JkIGZyb20gYW5vdGhlciBtb2RlIHRvIHRoZSBUZXh0XG4gICAgICAgICAgICAvLyBDb21wYWN0aW9uIG1vZGUgc2hhbGwgYWx3YXlzIHN3aXRjaCB0byB0aGUgVGV4dCBDb21wYWN0aW9uIEFscGhhIHN1Yi1tb2RlLlxuICAgICAgICAgICAgbGV0IHN1Yk1vZGUgPSBNb2RlJDIuQUxQSEE7XG4gICAgICAgICAgICBsZXQgcHJpb3JUb1NoaWZ0TW9kZSA9IE1vZGUkMi5BTFBIQTtcbiAgICAgICAgICAgIGxldCBpID0gMDtcbiAgICAgICAgICAgIHdoaWxlIChpIDwgbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgbGV0IHN1Yk1vZGVDaCA9IHRleHRDb21wYWN0aW9uRGF0YVtpXTtcbiAgICAgICAgICAgICAgICBsZXQgY2ggPSAvKmNoYXIqLyAnJztcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHN1Yk1vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBNb2RlJDIuQUxQSEE6XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBbHBoYSAoYWxwaGFiZXRpYzogdXBwZXJjYXNlKVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN1Yk1vZGVDaCA8IDI2KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVXBwZXIgY2FzZSBBbHBoYSBDaGFyYWN0ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOb3RlOiA2NSA9ICdBJyBBU0NJSSAtPiB0aGVyZSBpcyBieXRlIGNvZGUgb2Ygc3ltYm9sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2ggPSAvKihjaGFyKSgnQScgKyBzdWJNb2RlQ2gpICovIFN0cmluZy5mcm9tQ2hhckNvZGUoNjUgKyBzdWJNb2RlQ2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChzdWJNb2RlQ2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyNjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoID0gJyAnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkxMOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ViTW9kZSA9IE1vZGUkMi5MT1dFUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NTDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Yk1vZGUgPSBNb2RlJDIuTUlYRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuUFM6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaGlmdCB0byBwdW5jdHVhdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3JUb1NoaWZ0TW9kZSA9IHN1Yk1vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJNb2RlID0gTW9kZSQyLlBVTkNUX1NISUZUO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1PREVfU0hJRlRfVE9fQllURV9DT01QQUNUSU9OX01PREU6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKC8qKGNoYXIpKi8gYnl0ZUNvbXBhY3Rpb25EYXRhW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5URVhUX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Yk1vZGUgPSBNb2RlJDIuQUxQSEE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBNb2RlJDIuTE9XRVI6XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBMb3dlciAoYWxwaGFiZXRpYzogbG93ZXJjYXNlKVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN1Yk1vZGVDaCA8IDI2KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2ggPSAvKihjaGFyKSgnYScgKyBzdWJNb2RlQ2gpKi8gU3RyaW5nLmZyb21DaGFyQ29kZSg5NyArIHN1Yk1vZGVDaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHN1Yk1vZGVDaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDI2OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2ggPSAnICc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQVM6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaGlmdCB0byBhbHBoYVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3JUb1NoaWZ0TW9kZSA9IHN1Yk1vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJNb2RlID0gTW9kZSQyLkFMUEhBX1NISUZUO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1MOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ViTW9kZSA9IE1vZGUkMi5NSVhFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNoaWZ0IHRvIHB1bmN0dWF0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmlvclRvU2hpZnRNb2RlID0gc3ViTW9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Yk1vZGUgPSBNb2RlJDIuUFVOQ1RfU0hJRlQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTU9ERV9TSElGVF9UT19CWVRFX0NPTVBBQ1RJT05fTU9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE8gRG9lcyB0aGlzIG5lZWQgdG8gdXNlIHRoZSBjdXJyZW50IGNoYXJhY3RlciBlbmNvZGluZz8gU2VlIG90aGVyIG9jY3VycmVuY2VzIGJlbG93XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKC8qKGNoYXIpKi8gYnl0ZUNvbXBhY3Rpb25EYXRhW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5URVhUX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Yk1vZGUgPSBNb2RlJDIuQUxQSEE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBNb2RlJDIuTUlYRUQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNaXhlZCAocHVuY3R1YXRpb246IGUpXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3ViTW9kZUNoIDwgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlBMKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2ggPSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUlYRURfQ0hBUlNbc3ViTW9kZUNoXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoc3ViTW9kZUNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlBMOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ViTW9kZSA9IE1vZGUkMi5QVU5DVDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDI2OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2ggPSAnICc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTEw6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJNb2RlID0gTW9kZSQyLkxPV0VSO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkFMOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ViTW9kZSA9IE1vZGUkMi5BTFBIQTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNoaWZ0IHRvIHB1bmN0dWF0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmlvclRvU2hpZnRNb2RlID0gc3ViTW9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Yk1vZGUgPSBNb2RlJDIuUFVOQ1RfU0hJRlQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTU9ERV9TSElGVF9UT19CWVRFX0NPTVBBQ1RJT05fTU9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoLyooY2hhcikqLyBieXRlQ29tcGFjdGlvbkRhdGFbaV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlRFWFRfQ09NUEFDVElPTl9NT0RFX0xBVENIOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ViTW9kZSA9IE1vZGUkMi5BTFBIQTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIE1vZGUkMi5QVU5DVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFB1bmN0dWF0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3ViTW9kZUNoIDwgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlBBTCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlBVTkNUX0NIQVJTW3N1Yk1vZGVDaF07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHN1Yk1vZGVDaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5QQUw6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJNb2RlID0gTW9kZSQyLkFMUEhBO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1PREVfU0hJRlRfVE9fQllURV9DT01QQUNUSU9OX01PREU6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKC8qKGNoYXIpKi8gYnl0ZUNvbXBhY3Rpb25EYXRhW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5URVhUX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Yk1vZGUgPSBNb2RlJDIuQUxQSEE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBNb2RlJDIuQUxQSEFfU0hJRlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBSZXN0b3JlIHN1Yi1tb2RlXG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJNb2RlID0gcHJpb3JUb1NoaWZ0TW9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdWJNb2RlQ2ggPCAyNikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoID0gLyooY2hhcikoJ0EnICsgc3ViTW9kZUNoKSovIFN0cmluZy5mcm9tQ2hhckNvZGUoNjUgKyBzdWJNb2RlQ2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChzdWJNb2RlQ2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyNjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoID0gJyAnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlRFWFRfQ09NUEFDVElPTl9NT0RFX0xBVENIOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ViTW9kZSA9IE1vZGUkMi5BTFBIQTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIE1vZGUkMi5QVU5DVF9TSElGVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlc3RvcmUgc3ViLW1vZGVcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1Yk1vZGUgPSBwcmlvclRvU2hpZnRNb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN1Yk1vZGVDaCA8IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5QQUwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaCA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5QVU5DVF9DSEFSU1tzdWJNb2RlQ2hdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChzdWJNb2RlQ2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuUEFMOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ViTW9kZSA9IE1vZGUkMi5BTFBIQTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NT0RFX1NISUZUX1RPX0JZVEVfQ09NUEFDVElPTl9NT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUFMgYmVmb3JlIFNoaWZ0LXRvLUJ5dGUgaXMgdXNlZCBhcyBhIHBhZGRpbmcgY2hhcmFjdGVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2VlIDUuNC4yLjQgb2YgdGhlIHNwZWNpZmljYXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoLyooY2hhcikqLyBieXRlQ29tcGFjdGlvbkRhdGFbaV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlRFWFRfQ09NUEFDVElPTl9NT0RFX0xBVENIOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ViTW9kZSA9IE1vZGUkMi5BTFBIQTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBpZiAoY2ggIT09IDApIHtcbiAgICAgICAgICAgICAgICBpZiAoY2ggIT09ICcnKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEFwcGVuZCBkZWNvZGVkIGNoYXJhY3RlciB0byByZXN1bHRcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQnl0ZSBDb21wYWN0aW9uIG1vZGUgKHNlZSA1LjQuMykgcGVybWl0cyBhbGwgMjU2IHBvc3NpYmxlIDgtYml0IGJ5dGUgdmFsdWVzIHRvIGJlIGVuY29kZWQuXG4gICAgICAgICAqIFRoaXMgaW5jbHVkZXMgYWxsIEFTQ0lJIGNoYXJhY3RlcnMgdmFsdWUgMCB0byAxMjcgaW5jbHVzaXZlIGFuZCBwcm92aWRlcyBmb3IgaW50ZXJuYXRpb25hbFxuICAgICAgICAgKiBjaGFyYWN0ZXIgc2V0IHN1cHBvcnQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBtb2RlICAgICAgVGhlIGJ5dGUgY29tcGFjdGlvbiBtb2RlIGkuZS4gOTAxIG9yIDkyNFxuICAgICAgICAgKiBAcGFyYW0gY29kZXdvcmRzIFRoZSBhcnJheSBvZiBjb2Rld29yZHMgKGRhdGEgKyBlcnJvcilcbiAgICAgICAgICogQHBhcmFtIGVuY29kaW5nICBDdXJyZW50bHkgYWN0aXZlIGNoYXJhY3RlciBlbmNvZGluZ1xuICAgICAgICAgKiBAcGFyYW0gY29kZUluZGV4IFRoZSBjdXJyZW50IGluZGV4IGludG8gdGhlIGNvZGV3b3JkIGFycmF5LlxuICAgICAgICAgKiBAcGFyYW0gcmVzdWx0ICAgIFRoZSBkZWNvZGVkIGRhdGEgaXMgYXBwZW5kZWQgdG8gdGhlIHJlc3VsdC5cbiAgICAgICAgICogQHJldHVybiBUaGUgbmV4dCBpbmRleCBpbnRvIHRoZSBjb2Rld29yZCBhcnJheS5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyAvKmludCovIGJ5dGVDb21wYWN0aW9uKG1vZGUsIGNvZGV3b3JkcywgZW5jb2RpbmcsIGNvZGVJbmRleCwgcmVzdWx0KSB7XG4gICAgICAgICAgICBsZXQgZGVjb2RlZEJ5dGVzID0gbmV3IEJ5dGVBcnJheU91dHB1dFN0cmVhbSgpO1xuICAgICAgICAgICAgbGV0IGNvdW50ID0gMDtcbiAgICAgICAgICAgIGxldCB2YWx1ZSA9IC8qbG9uZyovIDA7XG4gICAgICAgICAgICBsZXQgZW5kID0gZmFsc2U7XG4gICAgICAgICAgICBzd2l0Y2ggKG1vZGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CWVRFX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgLy8gVG90YWwgbnVtYmVyIG9mIEJ5dGUgQ29tcGFjdGlvbiBjaGFyYWN0ZXJzIHRvIGJlIGVuY29kZWRcbiAgICAgICAgICAgICAgICAgICAgLy8gaXMgbm90IGEgbXVsdGlwbGUgb2YgNlxuICAgICAgICAgICAgICAgICAgICBsZXQgYnl0ZUNvbXBhY3RlZENvZGV3b3JkcyA9IG5ldyBJbnQzMkFycmF5KDYpO1xuICAgICAgICAgICAgICAgICAgICBsZXQgbmV4dENvZGUgPSBjb2Rld29yZHNbY29kZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoKGNvZGVJbmRleCA8IGNvZGV3b3Jkc1swXSkgJiYgIWVuZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZUNvbXBhY3RlZENvZGV3b3Jkc1tjb3VudCsrXSA9IG5leHRDb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQmFzZSA5MDBcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gOTAwICogdmFsdWUgKyBuZXh0Q29kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRDb2RlID0gY29kZXdvcmRzW2NvZGVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHBlcmhhcHMgaXQgc2hvdWxkIGJlIG9rIHRvIGNoZWNrIG9ubHkgbmV4dENvZGUgPj0gVEVYVF9DT01QQUNUSU9OX01PREVfTEFUQ0hcbiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAobmV4dENvZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5URVhUX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CWVRFX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5OVU1FUklDX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CWVRFX0NPTVBBQ1RJT05fTU9ERV9MQVRDSF82OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJFR0lOX01BQ1JPX1BERjQxN19DT05UUk9MX0JMT0NLOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJFR0lOX01BQ1JPX1BERjQxN19PUFRJT05BTF9GSUVMRDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQUNST19QREY0MTdfVEVSTUlOQVRPUjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4LS07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoY291bnQgJSA1ID09PSAwKSAmJiAoY291bnQgPiAwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRGVjb2RlIGV2ZXJ5IDUgY29kZXdvcmRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDb252ZXJ0IHRvIEJhc2UgMjU2XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBqIC8qaW50Ki8gPSAwOyBqIDwgNjsgKytqKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLyogQG5vdGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBKYXZhU2NyaXB0IHN0b3JlcyBudW1iZXJzIGFzIDY0IGJpdHMgZmxvYXRpbmcgcG9pbnQgbnVtYmVycywgYnV0IGFsbCBiaXR3aXNlIG9wZXJhdGlvbnMgYXJlIHBlcmZvcm1lZCBvbiAzMiBiaXRzIGJpbmFyeSBudW1iZXJzLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIFNvIHRoZSBuZXh0IGJpdHdpc2Ugb3BlcmF0aW9uIGNvdWxkIG5vdCBiZSBkb25lIHdpdGggc2ltcGxlIG51bWJlcnNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNvZGVkQnl0ZXMud3JpdGUoLyooYnl0ZSkqLyBOdW1iZXIoY3JlYXRlQmlnSW50KHZhbHVlKSA+PiBjcmVhdGVCaWdJbnQoOCAqICg1IC0gaikpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3VudCA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIGVuZCBvZiBhbGwgY29kZXdvcmRzIGlzIHJlYWNoZWQgdGhlIGxhc3QgY29kZXdvcmQgbmVlZHMgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvZGVJbmRleCA9PT0gY29kZXdvcmRzWzBdICYmIG5leHRDb2RlIDwgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlRFWFRfQ09NUEFDVElPTl9NT0RFX0xBVENIKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBieXRlQ29tcGFjdGVkQ29kZXdvcmRzW2NvdW50KytdID0gbmV4dENvZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgQnl0ZSBDb21wYWN0aW9uIG1vZGUgaXMgaW52b2tlZCB3aXRoIGNvZGV3b3JkIDkwMSxcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGxhc3QgZ3JvdXAgb2YgY29kZXdvcmRzIGlzIGludGVycHJldGVkIGRpcmVjdGx5XG4gICAgICAgICAgICAgICAgICAgIC8vIGFzIG9uZSBieXRlIHBlciBjb2Rld29yZCwgd2l0aG91dCBjb21wYWN0aW9uLlxuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVjb2RlZEJ5dGVzLndyaXRlKC8qKGJ5dGUpKi8gYnl0ZUNvbXBhY3RlZENvZGV3b3Jkc1tpXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQllURV9DT01QQUNUSU9OX01PREVfTEFUQ0hfNjpcbiAgICAgICAgICAgICAgICAgICAgLy8gVG90YWwgbnVtYmVyIG9mIEJ5dGUgQ29tcGFjdGlvbiBjaGFyYWN0ZXJzIHRvIGJlIGVuY29kZWRcbiAgICAgICAgICAgICAgICAgICAgLy8gaXMgYW4gaW50ZWdlciBtdWx0aXBsZSBvZiA2XG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChjb2RlSW5kZXggPCBjb2Rld29yZHNbMF0gJiYgIWVuZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNvZGUgPSBjb2Rld29yZHNbY29kZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvZGUgPCBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuVEVYVF9DT01QQUNUSU9OX01PREVfTEFUQ0gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3VudCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJhc2UgOTAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSA5MDAgKiB2YWx1ZSArIGNvZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGNvZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuVEVYVF9DT01QQUNUSU9OX01PREVfTEFUQ0g6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJZVEVfQ09NUEFDVElPTl9NT0RFX0xBVENIOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5OVU1FUklDX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQllURV9DT01QQUNUSU9OX01PREVfTEFUQ0hfNjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQkVHSU5fTUFDUk9fUERGNDE3X0NPTlRST0xfQkxPQ0s6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJFR0lOX01BQ1JPX1BERjQxN19PUFRJT05BTF9GSUVMRDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUFDUk9fUERGNDE3X1RFUk1JTkFUT1I6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2RlSW5kZXgtLTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoKGNvdW50ICUgNSA9PT0gMCkgJiYgKGNvdW50ID4gMCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBEZWNvZGUgZXZlcnkgNSBjb2Rld29yZHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDb252ZXJ0IHRvIEJhc2UgMjU2XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLyogQG5vdGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBKYXZhU2NyaXB0IHN0b3JlcyBudW1iZXJzIGFzIDY0IGJpdHMgZmxvYXRpbmcgcG9pbnQgbnVtYmVycywgYnV0IGFsbCBiaXR3aXNlIG9wZXJhdGlvbnMgYXJlIHBlcmZvcm1lZCBvbiAzMiBiaXRzIGJpbmFyeSBudW1iZXJzLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIFNvIHRoZSBuZXh0IGJpdHdpc2Ugb3BlcmF0aW9uIGNvdWxkIG5vdCBiZSBkb25lIHdpdGggc2ltcGxlIG51bWJlcnNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGogLyppbnQqLyA9IDA7IGogPCA2OyArK2opIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjb2RlZEJ5dGVzLndyaXRlKC8qKGJ5dGUpKi8gTnVtYmVyKGNyZWF0ZUJpZ0ludCh2YWx1ZSkgPj4gY3JlYXRlQmlnSW50KDggKiAoNSAtIGopKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnQgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChTdHJpbmdFbmNvZGluZy5kZWNvZGUoZGVjb2RlZEJ5dGVzLnRvQnl0ZUFycmF5KCksIGVuY29kaW5nKSk7XG4gICAgICAgICAgICByZXR1cm4gY29kZUluZGV4O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBOdW1lcmljIENvbXBhY3Rpb24gbW9kZSAoc2VlIDUuNC40KSBwZXJtaXRzIGVmZmljaWVudCBlbmNvZGluZyBvZiBudW1lcmljIGRhdGEgc3RyaW5ncy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGNvZGV3b3JkcyBUaGUgYXJyYXkgb2YgY29kZXdvcmRzIChkYXRhICsgZXJyb3IpXG4gICAgICAgICAqIEBwYXJhbSBjb2RlSW5kZXggVGhlIGN1cnJlbnQgaW5kZXggaW50byB0aGUgY29kZXdvcmQgYXJyYXkuXG4gICAgICAgICAqIEBwYXJhbSByZXN1bHQgICAgVGhlIGRlY29kZWQgZGF0YSBpcyBhcHBlbmRlZCB0byB0aGUgcmVzdWx0LlxuICAgICAgICAgKiBAcmV0dXJuIFRoZSBuZXh0IGluZGV4IGludG8gdGhlIGNvZGV3b3JkIGFycmF5LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIG51bWVyaWNDb21wYWN0aW9uKGNvZGV3b3JkcywgY29kZUluZGV4IC8qaW50Ki8sIHJlc3VsdCkge1xuICAgICAgICAgICAgbGV0IGNvdW50ID0gMDtcbiAgICAgICAgICAgIGxldCBlbmQgPSBmYWxzZTtcbiAgICAgICAgICAgIGxldCBudW1lcmljQ29kZXdvcmRzID0gbmV3IEludDMyQXJyYXkoRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BWF9OVU1FUklDX0NPREVXT1JEUyk7XG4gICAgICAgICAgICB3aGlsZSAoY29kZUluZGV4IDwgY29kZXdvcmRzWzBdICYmICFlbmQpIHtcbiAgICAgICAgICAgICAgICBsZXQgY29kZSA9IGNvZGV3b3Jkc1tjb2RlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgaWYgKGNvZGVJbmRleCA9PT0gY29kZXdvcmRzWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIGVuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjb2RlIDwgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlRFWFRfQ09NUEFDVElPTl9NT0RFX0xBVENIKSB7XG4gICAgICAgICAgICAgICAgICAgIG51bWVyaWNDb2Rld29yZHNbY291bnRdID0gY29kZTtcbiAgICAgICAgICAgICAgICAgICAgY291bnQrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoY29kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuVEVYVF9DT01QQUNUSU9OX01PREVfTEFUQ0g6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CWVRFX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJZVEVfQ09NUEFDVElPTl9NT0RFX0xBVENIXzY6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CRUdJTl9NQUNST19QREY0MTdfQ09OVFJPTF9CTE9DSzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJFR0lOX01BQ1JPX1BERjQxN19PUFRJT05BTF9GSUVMRDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BQ1JPX1BERjQxN19URVJNSU5BVE9SOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVJbmRleC0tO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKChjb3VudCAlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQVhfTlVNRVJJQ19DT0RFV09SRFMgPT09IDAgfHwgY29kZSA9PT0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk5VTUVSSUNfQ09NUEFDVElPTl9NT0RFX0xBVENIIHx8IGVuZCkgJiYgY291bnQgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlLWludm9raW5nIE51bWVyaWMgQ29tcGFjdGlvbiBtb2RlIChieSB1c2luZyBjb2Rld29yZCA5MDJcbiAgICAgICAgICAgICAgICAgICAgLy8gd2hpbGUgaW4gTnVtZXJpYyBDb21wYWN0aW9uIG1vZGUpIHNlcnZlcyAgdG8gdGVybWluYXRlIHRoZVxuICAgICAgICAgICAgICAgICAgICAvLyBjdXJyZW50IE51bWVyaWMgQ29tcGFjdGlvbiBtb2RlIGdyb3VwaW5nIGFzIGRlc2NyaWJlZCBpbiA1LjQuNC4yLFxuICAgICAgICAgICAgICAgICAgICAvLyBhbmQgdGhlbiB0byBzdGFydCBhIG5ldyBvbmUgZ3JvdXBpbmcuXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLmRlY29kZUJhc2U5MDB0b0Jhc2UxMChudW1lcmljQ29kZXdvcmRzLCBjb3VudCkpO1xuICAgICAgICAgICAgICAgICAgICBjb3VudCA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGNvZGVJbmRleDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ29udmVydCBhIGxpc3Qgb2YgTnVtZXJpYyBDb21wYWN0ZWQgY29kZXdvcmRzIGZyb20gQmFzZSA5MDAgdG8gQmFzZSAxMC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGNvZGV3b3JkcyBUaGUgYXJyYXkgb2YgY29kZXdvcmRzXG4gICAgICAgICAqIEBwYXJhbSBjb3VudCAgICAgVGhlIG51bWJlciBvZiBjb2Rld29yZHNcbiAgICAgICAgICogQHJldHVybiBUaGUgZGVjb2RlZCBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBOdW1lcmljIGRhdGEuXG4gICAgICAgICAqXG4gICAgICAgICAqIEVYQU1QTEVcbiAgICAgICAgICogRW5jb2RlIHRoZSBmaWZ0ZWVuIGRpZ2l0IG51bWVyaWMgc3RyaW5nIDAwMDIxMzI5ODE3NDAwMFxuICAgICAgICAgKiBQcmVmaXggdGhlIG51bWVyaWMgc3RyaW5nIHdpdGggYSAxIGFuZCBzZXQgdGhlIGluaXRpYWwgdmFsdWUgb2ZcbiAgICAgICAgICogdCA9IDEgMDAwIDIxMyAyOTggMTc0IDAwMFxuICAgICAgICAgKiBDYWxjdWxhdGUgY29kZXdvcmQgMFxuICAgICAgICAgKiBkMCA9IDEgMDAwIDIxMyAyOTggMTc0IDAwMCBtb2QgOTAwID0gMjAwXG4gICAgICAgICAqXG4gICAgICAgICAqIHQgPSAxIDAwMCAyMTMgMjk4IDE3NCAwMDAgZGl2IDkwMCA9IDEgMTExIDM0OCAxMDkgMDgyXG4gICAgICAgICAqIENhbGN1bGF0ZSBjb2Rld29yZCAxXG4gICAgICAgICAqIGQxID0gMSAxMTEgMzQ4IDEwOSAwODIgbW9kIDkwMCA9IDI4MlxuICAgICAgICAgKlxuICAgICAgICAgKiB0ID0gMSAxMTEgMzQ4IDEwOSAwODIgZGl2IDkwMCA9IDEgMjM0IDgzMSAyMzJcbiAgICAgICAgICogQ2FsY3VsYXRlIGNvZGV3b3JkIDJcbiAgICAgICAgICogZDIgPSAxIDIzNCA4MzEgMjMyIG1vZCA5MDAgPSA2MzJcbiAgICAgICAgICpcbiAgICAgICAgICogdCA9IDEgMjM0IDgzMSAyMzIgZGl2IDkwMCA9IDEgMzcyIDAzNFxuICAgICAgICAgKiBDYWxjdWxhdGUgY29kZXdvcmQgM1xuICAgICAgICAgKiBkMyA9IDEgMzcyIDAzNCBtb2QgOTAwID0gNDM0XG4gICAgICAgICAqXG4gICAgICAgICAqIHQgPSAxIDM3MiAwMzQgZGl2IDkwMCA9IDEgNTI0XG4gICAgICAgICAqIENhbGN1bGF0ZSBjb2Rld29yZCA0XG4gICAgICAgICAqIGQ0ID0gMSA1MjQgbW9kIDkwMCA9IDYyNFxuICAgICAgICAgKlxuICAgICAgICAgKiB0ID0gMSA1MjQgZGl2IDkwMCA9IDFcbiAgICAgICAgICogQ2FsY3VsYXRlIGNvZGV3b3JkIDVcbiAgICAgICAgICogZDUgPSAxIG1vZCA5MDAgPSAxXG4gICAgICAgICAqIHQgPSAxIGRpdiA5MDAgPSAwXG4gICAgICAgICAqIENvZGV3b3JkIHNlcXVlbmNlIGlzOiAxLCA2MjQsIDQzNCwgNjMyLCAyODIsIDIwMFxuICAgICAgICAgKlxuICAgICAgICAgKiBEZWNvZGUgdGhlIGFib3ZlIGNvZGV3b3JkcyBpbnZvbHZlc1xuICAgICAgICAgKiAgIDEgeCA5MDAgcG93ZXIgb2YgNSArIDYyNCB4IDkwMCBwb3dlciBvZiA0ICsgNDM0IHggOTAwIHBvd2VyIG9mIDMgK1xuICAgICAgICAgKiA2MzIgeCA5MDAgcG93ZXIgb2YgMiArIDI4MiB4IDkwMCBwb3dlciBvZiAxICsgMjAwIHggOTAwIHBvd2VyIG9mIDAgPSAxMDAwMjEzMjk4MTc0MDAwXG4gICAgICAgICAqXG4gICAgICAgICAqIFJlbW92ZSBsZWFkaW5nIDEgPT4gIFJlc3VsdCBpcyAwMDAyMTMyOTgxNzQwMDBcbiAgICAgICAgICpcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBkZWNvZGVCYXNlOTAwdG9CYXNlMTAoY29kZXdvcmRzLCBjb3VudCkge1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IGNyZWF0ZUJpZ0ludCgwKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5FWFA5MDBbY291bnQgLSBpIC0gMV0gKiBjcmVhdGVCaWdJbnQoY29kZXdvcmRzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCByZXN1bHRTdHJpbmcgPSByZXN1bHQudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGlmIChyZXN1bHRTdHJpbmcuY2hhckF0KDApICE9PSAnMScpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0U3RyaW5nLnN1YnN0cmluZygxKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuVEVYVF9DT01QQUNUSU9OX01PREVfTEFUQ0ggPSA5MDA7XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJZVEVfQ09NUEFDVElPTl9NT0RFX0xBVENIID0gOTAxO1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5OVU1FUklDX0NPTVBBQ1RJT05fTU9ERV9MQVRDSCA9IDkwMjtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQllURV9DT01QQUNUSU9OX01PREVfTEFUQ0hfNiA9IDkyNDtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuRUNJX1VTRVJfREVGSU5FRCA9IDkyNTtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuRUNJX0dFTkVSQUxfUFVSUE9TRSA9IDkyNjtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuRUNJX0NIQVJTRVQgPSA5Mjc7XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJFR0lOX01BQ1JPX1BERjQxN19DT05UUk9MX0JMT0NLID0gOTI4O1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CRUdJTl9NQUNST19QREY0MTdfT1BUSU9OQUxfRklFTEQgPSA5MjM7XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BQ1JPX1BERjQxN19URVJNSU5BVE9SID0gOTIyO1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NT0RFX1NISUZUX1RPX0JZVEVfQ09NUEFDVElPTl9NT0RFID0gOTEzO1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQVhfTlVNRVJJQ19DT0RFV09SRFMgPSAxNTtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUFDUk9fUERGNDE3X09QVElPTkFMX0ZJRUxEX0ZJTEVfTkFNRSA9IDA7XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BQ1JPX1BERjQxN19PUFRJT05BTF9GSUVMRF9TRUdNRU5UX0NPVU5UID0gMTtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUFDUk9fUERGNDE3X09QVElPTkFMX0ZJRUxEX1RJTUVfU1RBTVAgPSAyO1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQUNST19QREY0MTdfT1BUSU9OQUxfRklFTERfU0VOREVSID0gMztcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUFDUk9fUERGNDE3X09QVElPTkFMX0ZJRUxEX0FERFJFU1NFRSA9IDQ7XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BQ1JPX1BERjQxN19PUFRJT05BTF9GSUVMRF9GSUxFX1NJWkUgPSA1O1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQUNST19QREY0MTdfT1BUSU9OQUxfRklFTERfQ0hFQ0tTVU0gPSA2O1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5QTCA9IDI1O1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5MTCA9IDI3O1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5BUyA9IDI3O1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NTCA9IDI4O1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5BTCA9IDI4O1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5QUyA9IDI5O1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5QQUwgPSAyOTtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuUFVOQ1RfQ0hBUlMgPSAnOzw+QFtcXFxcXV9gfiFcXHJcXHQsOlxcbi0uJC9cInwqKCk/e31cXCcnO1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NSVhFRF9DSEFSUyA9ICcwMTIzNDU2Nzg5JlxcclxcdCw6Iy0uJC8rJSo9Xic7XG4gICAgLyoqXG4gICAgICogVGFibGUgY29udGFpbmluZyB2YWx1ZXMgZm9yIHRoZSBleHBvbmVudCBvZiA5MDAuXG4gICAgICogVGhpcyBpcyB1c2VkIGluIHRoZSBudW1lcmljIGNvbXBhY3Rpb24gZGVjb2RlIGFsZ29yaXRobS5cbiAgICAgKi9cbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuRVhQOTAwID0gZ2V0QmlnSW50Q29uc3RydWN0b3IoKSA/IGdldEVYUDkwMCgpIDogW107XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk5VTUJFUl9PRl9TRVFVRU5DRV9DT0RFV09SRFMgPSAyO1xuXG4gICAgLypcbiAgICAqIENvcHlyaWdodCAyMDEzIFpYaW5nIGF1dGhvcnNcbiAgICAqXG4gICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgKlxuICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAqXG4gICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICovXG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7XG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5Db2xsZWN0aW9uO1xuICAgIC8vIGltcG9ydCBqYXZhLnV0aWwuRm9ybWF0dGVyO1xuICAgIC8vIGltcG9ydCBqYXZhLnV0aWwuTGlzdDtcbiAgICAvKipcbiAgICAgKiBAYXV0aG9yIEd1ZW50aGVyIEdyYXVcbiAgICAgKi9cbiAgICAvKnB1YmxpYyBmaW5hbCovIGNsYXNzIFBERjQxN1NjYW5uaW5nRGVjb2RlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkgeyB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAVE9ETyBkb24ndCBwYXNzIGluIG1pbkNvZGV3b3JkV2lkdGggYW5kIG1heENvZGV3b3JkV2lkdGgsIHBhc3MgaW4gYmFyY29kZSBjb2x1bW5zIGZvciBzdGFydCBhbmQgc3RvcCBwYXR0ZXJuXG4gICAgICAgICAqXG4gICAgICAgICAqIGNvbHVtbnMuIFRoYXQgd2F5IHdpZHRoIGNhbiBiZSBkZWR1Y3RlZCBmcm9tIHRoZSBwYXR0ZXJuIGNvbHVtbi5cbiAgICAgICAgICogVGhpcyBhcHByb2FjaCBhbHNvIGFsbG93cyB0byBkZXRlY3QgbW9yZSBkZXRhaWxzIGFib3V0IHRoZSBiYXJjb2RlLCBlLmcuIGlmIGEgYmFyIHR5cGUgKHdoaXRlIG9yIGJsYWNrKSBpcyB3aWRlclxuICAgICAgICAgKiB0aGFuIGl0IHNob3VsZCBiZS4gVGhpcyBjYW4gaGFwcGVuIGlmIHRoZSBzY2FubmVyIHVzZWQgYSBiYWQgYmxhY2twb2ludC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIEJpdE1hdHJpeFxuICAgICAgICAgKiBAcGFyYW0gaW1hZ2VcbiAgICAgICAgICogQHBhcmFtIFJlc3VsdFBvaW50XG4gICAgICAgICAqIEBwYXJhbSBpbWFnZVRvcExlZnRcbiAgICAgICAgICogQHBhcmFtIFJlc3VsdFBvaW50XG4gICAgICAgICAqIEBwYXJhbSBpbWFnZUJvdHRvbUxlZnRcbiAgICAgICAgICogQHBhcmFtIFJlc3VsdFBvaW50XG4gICAgICAgICAqIEBwYXJhbSBpbWFnZVRvcFJpZ2h0XG4gICAgICAgICAqIEBwYXJhbSBSZXN1bHRQb2ludFxuICAgICAgICAgKiBAcGFyYW0gaW1hZ2VCb3R0b21SaWdodFxuICAgICAgICAgKiBAcGFyYW0gaW50XG4gICAgICAgICAqIEBwYXJhbSBtaW5Db2Rld29yZFdpZHRoXG4gICAgICAgICAqIEBwYXJhbSBpbnRcbiAgICAgICAgICogQHBhcmFtIG1heENvZGV3b3JkV2lkdGhcbiAgICAgICAgICpcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvblxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvblxuICAgICAgICAgKiBAdGhyb3dzIENoZWNrc3VtRXhjZXB0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGVjb2RlKGltYWdlLCBpbWFnZVRvcExlZnQsIGltYWdlQm90dG9tTGVmdCwgaW1hZ2VUb3BSaWdodCwgaW1hZ2VCb3R0b21SaWdodCwgbWluQ29kZXdvcmRXaWR0aCwgbWF4Q29kZXdvcmRXaWR0aCkge1xuICAgICAgICAgICAgbGV0IGJvdW5kaW5nQm94ID0gbmV3IEJvdW5kaW5nQm94KGltYWdlLCBpbWFnZVRvcExlZnQsIGltYWdlQm90dG9tTGVmdCwgaW1hZ2VUb3BSaWdodCwgaW1hZ2VCb3R0b21SaWdodCk7XG4gICAgICAgICAgICBsZXQgbGVmdFJvd0luZGljYXRvckNvbHVtbiA9IG51bGw7XG4gICAgICAgICAgICBsZXQgcmlnaHRSb3dJbmRpY2F0b3JDb2x1bW4gPSBudWxsO1xuICAgICAgICAgICAgbGV0IGRldGVjdGlvblJlc3VsdDtcbiAgICAgICAgICAgIGZvciAobGV0IGZpcnN0UGFzcyAvKmJvb2xlYW4qLyA9IHRydWU7OyBmaXJzdFBhc3MgPSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIGlmIChpbWFnZVRvcExlZnQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBsZWZ0Um93SW5kaWNhdG9yQ29sdW1uID0gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmdldFJvd0luZGljYXRvckNvbHVtbihpbWFnZSwgYm91bmRpbmdCb3gsIGltYWdlVG9wTGVmdCwgdHJ1ZSwgbWluQ29kZXdvcmRXaWR0aCwgbWF4Q29kZXdvcmRXaWR0aCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChpbWFnZVRvcFJpZ2h0ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmlnaHRSb3dJbmRpY2F0b3JDb2x1bW4gPSBQREY0MTdTY2FubmluZ0RlY29kZXIuZ2V0Um93SW5kaWNhdG9yQ29sdW1uKGltYWdlLCBib3VuZGluZ0JveCwgaW1hZ2VUb3BSaWdodCwgZmFsc2UsIG1pbkNvZGV3b3JkV2lkdGgsIG1heENvZGV3b3JkV2lkdGgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZXRlY3Rpb25SZXN1bHQgPSBQREY0MTdTY2FubmluZ0RlY29kZXIubWVyZ2UobGVmdFJvd0luZGljYXRvckNvbHVtbiwgcmlnaHRSb3dJbmRpY2F0b3JDb2x1bW4pO1xuICAgICAgICAgICAgICAgIGlmIChkZXRlY3Rpb25SZXN1bHQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBOb3RGb3VuZEV4Y2VwdGlvbi5nZXROb3RGb3VuZEluc3RhbmNlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCByZXN1bHRCb3ggPSBkZXRlY3Rpb25SZXN1bHQuZ2V0Qm91bmRpbmdCb3goKTtcbiAgICAgICAgICAgICAgICBpZiAoZmlyc3RQYXNzICYmIHJlc3VsdEJveCAhPSBudWxsICYmXG4gICAgICAgICAgICAgICAgICAgIChyZXN1bHRCb3guZ2V0TWluWSgpIDwgYm91bmRpbmdCb3guZ2V0TWluWSgpIHx8IHJlc3VsdEJveC5nZXRNYXhZKCkgPiBib3VuZGluZ0JveC5nZXRNYXhZKCkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGJvdW5kaW5nQm94ID0gcmVzdWx0Qm94O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGV0ZWN0aW9uUmVzdWx0LnNldEJvdW5kaW5nQm94KGJvdW5kaW5nQm94KTtcbiAgICAgICAgICAgIGxldCBtYXhCYXJjb2RlQ29sdW1uID0gZGV0ZWN0aW9uUmVzdWx0LmdldEJhcmNvZGVDb2x1bW5Db3VudCgpICsgMTtcbiAgICAgICAgICAgIGRldGVjdGlvblJlc3VsdC5zZXREZXRlY3Rpb25SZXN1bHRDb2x1bW4oMCwgbGVmdFJvd0luZGljYXRvckNvbHVtbik7XG4gICAgICAgICAgICBkZXRlY3Rpb25SZXN1bHQuc2V0RGV0ZWN0aW9uUmVzdWx0Q29sdW1uKG1heEJhcmNvZGVDb2x1bW4sIHJpZ2h0Um93SW5kaWNhdG9yQ29sdW1uKTtcbiAgICAgICAgICAgIGxldCBsZWZ0VG9SaWdodCA9IGxlZnRSb3dJbmRpY2F0b3JDb2x1bW4gIT0gbnVsbDtcbiAgICAgICAgICAgIGZvciAobGV0IGJhcmNvZGVDb2x1bW5Db3VudCAvKmludCovID0gMTsgYmFyY29kZUNvbHVtbkNvdW50IDw9IG1heEJhcmNvZGVDb2x1bW47IGJhcmNvZGVDb2x1bW5Db3VudCsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IGJhcmNvZGVDb2x1bW4gPSBsZWZ0VG9SaWdodCA/IGJhcmNvZGVDb2x1bW5Db3VudCA6IG1heEJhcmNvZGVDb2x1bW4gLSBiYXJjb2RlQ29sdW1uQ291bnQ7XG4gICAgICAgICAgICAgICAgaWYgKGRldGVjdGlvblJlc3VsdC5nZXREZXRlY3Rpb25SZXN1bHRDb2x1bW4oYmFyY29kZUNvbHVtbikgIT09IC8qIG51bGwgKi8gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgd2lsbCBiZSB0aGUgY2FzZSBmb3IgdGhlIG9wcG9zaXRlIHJvdyBpbmRpY2F0b3IgY29sdW1uLCB3aGljaCBkb2Vzbid0IG5lZWQgdG8gYmUgZGVjb2RlZCBhZ2Fpbi5cbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCBkZXRlY3Rpb25SZXN1bHRDb2x1bW47XG4gICAgICAgICAgICAgICAgaWYgKGJhcmNvZGVDb2x1bW4gPT09IDAgfHwgYmFyY29kZUNvbHVtbiA9PT0gbWF4QmFyY29kZUNvbHVtbikge1xuICAgICAgICAgICAgICAgICAgICBkZXRlY3Rpb25SZXN1bHRDb2x1bW4gPSBuZXcgRGV0ZWN0aW9uUmVzdWx0Um93SW5kaWNhdG9yQ29sdW1uKGJvdW5kaW5nQm94LCBiYXJjb2RlQ29sdW1uID09PSAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRldGVjdGlvblJlc3VsdENvbHVtbiA9IG5ldyBEZXRlY3Rpb25SZXN1bHRDb2x1bW4oYm91bmRpbmdCb3gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZXRlY3Rpb25SZXN1bHQuc2V0RGV0ZWN0aW9uUmVzdWx0Q29sdW1uKGJhcmNvZGVDb2x1bW4sIGRldGVjdGlvblJlc3VsdENvbHVtbik7XG4gICAgICAgICAgICAgICAgbGV0IHN0YXJ0Q29sdW1uID0gLTE7XG4gICAgICAgICAgICAgICAgbGV0IHByZXZpb3VzU3RhcnRDb2x1bW4gPSBzdGFydENvbHVtbjtcbiAgICAgICAgICAgICAgICAvLyBUT0RPIHN0YXJ0IGF0IGEgcm93IGZvciB3aGljaCB3ZSBrbm93IHRoZSBzdGFydCBwb3NpdGlvbiwgdGhlbiBkZXRlY3QgdXB3YXJkcyBhbmQgZG93bndhcmRzIGZyb20gdGhlcmUuXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaW1hZ2VSb3cgLyppbnQqLyA9IGJvdW5kaW5nQm94LmdldE1pblkoKTsgaW1hZ2VSb3cgPD0gYm91bmRpbmdCb3guZ2V0TWF4WSgpOyBpbWFnZVJvdysrKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0Q29sdW1uID0gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmdldFN0YXJ0Q29sdW1uKGRldGVjdGlvblJlc3VsdCwgYmFyY29kZUNvbHVtbiwgaW1hZ2VSb3csIGxlZnRUb1JpZ2h0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXJ0Q29sdW1uIDwgMCB8fCBzdGFydENvbHVtbiA+IGJvdW5kaW5nQm94LmdldE1heFgoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzU3RhcnRDb2x1bW4gPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydENvbHVtbiA9IHByZXZpb3VzU3RhcnRDb2x1bW47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbGV0IGNvZGV3b3JkID0gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmRldGVjdENvZGV3b3JkKGltYWdlLCBib3VuZGluZ0JveC5nZXRNaW5YKCksIGJvdW5kaW5nQm94LmdldE1heFgoKSwgbGVmdFRvUmlnaHQsIHN0YXJ0Q29sdW1uLCBpbWFnZVJvdywgbWluQ29kZXdvcmRXaWR0aCwgbWF4Q29kZXdvcmRXaWR0aCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb2Rld29yZCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXRlY3Rpb25SZXN1bHRDb2x1bW4uc2V0Q29kZXdvcmQoaW1hZ2VSb3csIGNvZGV3b3JkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzU3RhcnRDb2x1bW4gPSBzdGFydENvbHVtbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkNvZGV3b3JkV2lkdGggPSBNYXRoLm1pbihtaW5Db2Rld29yZFdpZHRoLCBjb2Rld29yZC5nZXRXaWR0aCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heENvZGV3b3JkV2lkdGggPSBNYXRoLm1heChtYXhDb2Rld29yZFdpZHRoLCBjb2Rld29yZC5nZXRXaWR0aCgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBQREY0MTdTY2FubmluZ0RlY29kZXIuY3JlYXRlRGVjb2RlclJlc3VsdChkZXRlY3Rpb25SZXN1bHQpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gbGVmdFJvd0luZGljYXRvckNvbHVtblxuICAgICAgICAgKiBAcGFyYW0gcmlnaHRSb3dJbmRpY2F0b3JDb2x1bW5cbiAgICAgICAgICpcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIG1lcmdlKGxlZnRSb3dJbmRpY2F0b3JDb2x1bW4sIHJpZ2h0Um93SW5kaWNhdG9yQ29sdW1uKSB7XG4gICAgICAgICAgICBpZiAobGVmdFJvd0luZGljYXRvckNvbHVtbiA9PSBudWxsICYmIHJpZ2h0Um93SW5kaWNhdG9yQ29sdW1uID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBiYXJjb2RlTWV0YWRhdGEgPSBQREY0MTdTY2FubmluZ0RlY29kZXIuZ2V0QmFyY29kZU1ldGFkYXRhKGxlZnRSb3dJbmRpY2F0b3JDb2x1bW4sIHJpZ2h0Um93SW5kaWNhdG9yQ29sdW1uKTtcbiAgICAgICAgICAgIGlmIChiYXJjb2RlTWV0YWRhdGEgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGJvdW5kaW5nQm94ID0gQm91bmRpbmdCb3gubWVyZ2UoUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmFkanVzdEJvdW5kaW5nQm94KGxlZnRSb3dJbmRpY2F0b3JDb2x1bW4pLCBQREY0MTdTY2FubmluZ0RlY29kZXIuYWRqdXN0Qm91bmRpbmdCb3gocmlnaHRSb3dJbmRpY2F0b3JDb2x1bW4pKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRGV0ZWN0aW9uUmVzdWx0KGJhcmNvZGVNZXRhZGF0YSwgYm91bmRpbmdCb3gpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gcm93SW5kaWNhdG9yQ29sdW1uXG4gICAgICAgICAqXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBhZGp1c3RCb3VuZGluZ0JveChyb3dJbmRpY2F0b3JDb2x1bW4pIHtcbiAgICAgICAgICAgIGlmIChyb3dJbmRpY2F0b3JDb2x1bW4gPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHJvd0hlaWdodHMgPSByb3dJbmRpY2F0b3JDb2x1bW4uZ2V0Um93SGVpZ2h0cygpO1xuICAgICAgICAgICAgaWYgKHJvd0hlaWdodHMgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IG1heFJvd0hlaWdodCA9IFBERjQxN1NjYW5uaW5nRGVjb2Rlci5nZXRNYXgocm93SGVpZ2h0cyk7XG4gICAgICAgICAgICBsZXQgbWlzc2luZ1N0YXJ0Um93cyA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCByb3dIZWlnaHQgLyppbnQqLyBvZiByb3dIZWlnaHRzKSB7XG4gICAgICAgICAgICAgICAgbWlzc2luZ1N0YXJ0Um93cyArPSBtYXhSb3dIZWlnaHQgLSByb3dIZWlnaHQ7XG4gICAgICAgICAgICAgICAgaWYgKHJvd0hlaWdodCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGNvZGV3b3JkcyA9IHJvd0luZGljYXRvckNvbHVtbi5nZXRDb2Rld29yZHMoKTtcbiAgICAgICAgICAgIGZvciAobGV0IHJvdyAvKmludCovID0gMDsgbWlzc2luZ1N0YXJ0Um93cyA+IDAgJiYgY29kZXdvcmRzW3Jvd10gPT0gbnVsbDsgcm93KyspIHtcbiAgICAgICAgICAgICAgICBtaXNzaW5nU3RhcnRSb3dzLS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgbWlzc2luZ0VuZFJvd3MgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgcm93IC8qaW50Ki8gPSByb3dIZWlnaHRzLmxlbmd0aCAtIDE7IHJvdyA+PSAwOyByb3ctLSkge1xuICAgICAgICAgICAgICAgIG1pc3NpbmdFbmRSb3dzICs9IG1heFJvd0hlaWdodCAtIHJvd0hlaWdodHNbcm93XTtcbiAgICAgICAgICAgICAgICBpZiAocm93SGVpZ2h0c1tyb3ddID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCByb3cgLyppbnQqLyA9IGNvZGV3b3Jkcy5sZW5ndGggLSAxOyBtaXNzaW5nRW5kUm93cyA+IDAgJiYgY29kZXdvcmRzW3Jvd10gPT0gbnVsbDsgcm93LS0pIHtcbiAgICAgICAgICAgICAgICBtaXNzaW5nRW5kUm93cy0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJvd0luZGljYXRvckNvbHVtbi5nZXRCb3VuZGluZ0JveCgpLmFkZE1pc3NpbmdSb3dzKG1pc3NpbmdTdGFydFJvd3MsIG1pc3NpbmdFbmRSb3dzLCByb3dJbmRpY2F0b3JDb2x1bW4uaXNMZWZ0KCkpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXRNYXgodmFsdWVzKSB7XG4gICAgICAgICAgICBsZXQgbWF4VmFsdWUgPSAtMTtcbiAgICAgICAgICAgIGZvciAobGV0IHZhbHVlIC8qaW50Ki8gb2YgdmFsdWVzKSB7XG4gICAgICAgICAgICAgICAgbWF4VmFsdWUgPSBNYXRoLm1heChtYXhWYWx1ZSwgdmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1heFZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXRCYXJjb2RlTWV0YWRhdGEobGVmdFJvd0luZGljYXRvckNvbHVtbiwgcmlnaHRSb3dJbmRpY2F0b3JDb2x1bW4pIHtcbiAgICAgICAgICAgIGxldCBsZWZ0QmFyY29kZU1ldGFkYXRhO1xuICAgICAgICAgICAgaWYgKGxlZnRSb3dJbmRpY2F0b3JDb2x1bW4gPT0gbnVsbCB8fFxuICAgICAgICAgICAgICAgIChsZWZ0QmFyY29kZU1ldGFkYXRhID0gbGVmdFJvd0luZGljYXRvckNvbHVtbi5nZXRCYXJjb2RlTWV0YWRhdGEoKSkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiByaWdodFJvd0luZGljYXRvckNvbHVtbiA9PSBudWxsID8gbnVsbCA6IHJpZ2h0Um93SW5kaWNhdG9yQ29sdW1uLmdldEJhcmNvZGVNZXRhZGF0YSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHJpZ2h0QmFyY29kZU1ldGFkYXRhO1xuICAgICAgICAgICAgaWYgKHJpZ2h0Um93SW5kaWNhdG9yQ29sdW1uID09IG51bGwgfHxcbiAgICAgICAgICAgICAgICAocmlnaHRCYXJjb2RlTWV0YWRhdGEgPSByaWdodFJvd0luZGljYXRvckNvbHVtbi5nZXRCYXJjb2RlTWV0YWRhdGEoKSkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBsZWZ0QmFyY29kZU1ldGFkYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGxlZnRCYXJjb2RlTWV0YWRhdGEuZ2V0Q29sdW1uQ291bnQoKSAhPT0gcmlnaHRCYXJjb2RlTWV0YWRhdGEuZ2V0Q29sdW1uQ291bnQoKSAmJlxuICAgICAgICAgICAgICAgIGxlZnRCYXJjb2RlTWV0YWRhdGEuZ2V0RXJyb3JDb3JyZWN0aW9uTGV2ZWwoKSAhPT0gcmlnaHRCYXJjb2RlTWV0YWRhdGEuZ2V0RXJyb3JDb3JyZWN0aW9uTGV2ZWwoKSAmJlxuICAgICAgICAgICAgICAgIGxlZnRCYXJjb2RlTWV0YWRhdGEuZ2V0Um93Q291bnQoKSAhPT0gcmlnaHRCYXJjb2RlTWV0YWRhdGEuZ2V0Um93Q291bnQoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGxlZnRCYXJjb2RlTWV0YWRhdGE7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdldFJvd0luZGljYXRvckNvbHVtbihpbWFnZSwgYm91bmRpbmdCb3gsIHN0YXJ0UG9pbnQsIGxlZnRUb1JpZ2h0LCBtaW5Db2Rld29yZFdpZHRoLCBtYXhDb2Rld29yZFdpZHRoKSB7XG4gICAgICAgICAgICBsZXQgcm93SW5kaWNhdG9yQ29sdW1uID0gbmV3IERldGVjdGlvblJlc3VsdFJvd0luZGljYXRvckNvbHVtbihib3VuZGluZ0JveCwgbGVmdFRvUmlnaHQpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMDsgaSA8IDI7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCBpbmNyZW1lbnQgPSBpID09PSAwID8gMSA6IC0xO1xuICAgICAgICAgICAgICAgIGxldCBzdGFydENvbHVtbiA9IE1hdGgudHJ1bmMoTWF0aC50cnVuYyhzdGFydFBvaW50LmdldFgoKSkpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGltYWdlUm93IC8qaW50Ki8gPSBNYXRoLnRydW5jKE1hdGgudHJ1bmMoc3RhcnRQb2ludC5nZXRZKCkpKTsgaW1hZ2VSb3cgPD0gYm91bmRpbmdCb3guZ2V0TWF4WSgpICYmXG4gICAgICAgICAgICAgICAgICAgIGltYWdlUm93ID49IGJvdW5kaW5nQm94LmdldE1pblkoKTsgaW1hZ2VSb3cgKz0gaW5jcmVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBjb2Rld29yZCA9IFBERjQxN1NjYW5uaW5nRGVjb2Rlci5kZXRlY3RDb2Rld29yZChpbWFnZSwgMCwgaW1hZ2UuZ2V0V2lkdGgoKSwgbGVmdFRvUmlnaHQsIHN0YXJ0Q29sdW1uLCBpbWFnZVJvdywgbWluQ29kZXdvcmRXaWR0aCwgbWF4Q29kZXdvcmRXaWR0aCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb2Rld29yZCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb3dJbmRpY2F0b3JDb2x1bW4uc2V0Q29kZXdvcmQoaW1hZ2VSb3csIGNvZGV3b3JkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsZWZ0VG9SaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0Q29sdW1uID0gY29kZXdvcmQuZ2V0U3RhcnRYKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydENvbHVtbiA9IGNvZGV3b3JkLmdldEVuZFgoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByb3dJbmRpY2F0b3JDb2x1bW47XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBkZXRlY3Rpb25SZXN1bHRcbiAgICAgICAgICogQHBhcmFtIEJhcmNvZGVWYWx1ZVxuICAgICAgICAgKiBAcGFyYW0gcGFyYW0yXG4gICAgICAgICAqIEBwYXJhbSBwYXJhbTNcbiAgICAgICAgICogQHBhcmFtIGJhcmNvZGVNYXRyaXhcbiAgICAgICAgICpcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGFkanVzdENvZGV3b3JkQ291bnQoZGV0ZWN0aW9uUmVzdWx0LCBiYXJjb2RlTWF0cml4KSB7XG4gICAgICAgICAgICBsZXQgYmFyY29kZU1hdHJpeDAxID0gYmFyY29kZU1hdHJpeFswXVsxXTtcbiAgICAgICAgICAgIGxldCBudW1iZXJPZkNvZGV3b3JkcyA9IGJhcmNvZGVNYXRyaXgwMS5nZXRWYWx1ZSgpO1xuICAgICAgICAgICAgbGV0IGNhbGN1bGF0ZWROdW1iZXJPZkNvZGV3b3JkcyA9IGRldGVjdGlvblJlc3VsdC5nZXRCYXJjb2RlQ29sdW1uQ291bnQoKSAqXG4gICAgICAgICAgICAgICAgZGV0ZWN0aW9uUmVzdWx0LmdldEJhcmNvZGVSb3dDb3VudCgpIC1cbiAgICAgICAgICAgICAgICBQREY0MTdTY2FubmluZ0RlY29kZXIuZ2V0TnVtYmVyT2ZFQ0NvZGVXb3JkcyhkZXRlY3Rpb25SZXN1bHQuZ2V0QmFyY29kZUVDTGV2ZWwoKSk7XG4gICAgICAgICAgICBpZiAobnVtYmVyT2ZDb2Rld29yZHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNhbGN1bGF0ZWROdW1iZXJPZkNvZGV3b3JkcyA8IDEgfHwgY2FsY3VsYXRlZE51bWJlck9mQ29kZXdvcmRzID4gUERGNDE3Q29tbW9uLk1BWF9DT0RFV09SRFNfSU5fQkFSQ09ERSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBOb3RGb3VuZEV4Y2VwdGlvbi5nZXROb3RGb3VuZEluc3RhbmNlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJhcmNvZGVNYXRyaXgwMS5zZXRWYWx1ZShjYWxjdWxhdGVkTnVtYmVyT2ZDb2Rld29yZHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAobnVtYmVyT2ZDb2Rld29yZHNbMF0gIT09IGNhbGN1bGF0ZWROdW1iZXJPZkNvZGV3b3Jkcykge1xuICAgICAgICAgICAgICAgIC8vIFRoZSBjYWxjdWxhdGVkIG9uZSBpcyBtb3JlIHJlbGlhYmxlIGFzIGl0IGlzIGRlcml2ZWQgZnJvbSB0aGUgcm93IGluZGljYXRvciBjb2x1bW5zXG4gICAgICAgICAgICAgICAgYmFyY29kZU1hdHJpeDAxLnNldFZhbHVlKGNhbGN1bGF0ZWROdW1iZXJPZkNvZGV3b3Jkcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBkZXRlY3Rpb25SZXN1bHRcbiAgICAgICAgICpcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb25cbiAgICAgICAgICogQHRocm93cyBDaGVja3N1bUV4Y2VwdGlvblxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgY3JlYXRlRGVjb2RlclJlc3VsdChkZXRlY3Rpb25SZXN1bHQpIHtcbiAgICAgICAgICAgIGxldCBiYXJjb2RlTWF0cml4ID0gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmNyZWF0ZUJhcmNvZGVNYXRyaXgoZGV0ZWN0aW9uUmVzdWx0KTtcbiAgICAgICAgICAgIFBERjQxN1NjYW5uaW5nRGVjb2Rlci5hZGp1c3RDb2Rld29yZENvdW50KGRldGVjdGlvblJlc3VsdCwgYmFyY29kZU1hdHJpeCk7XG4gICAgICAgICAgICBsZXQgZXJhc3VyZXMgLypDb2xsZWN0aW9uPEludGVnZXI+Ki8gPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgICAgIGxldCBjb2Rld29yZHMgPSBuZXcgSW50MzJBcnJheShkZXRlY3Rpb25SZXN1bHQuZ2V0QmFyY29kZVJvd0NvdW50KCkgKiBkZXRlY3Rpb25SZXN1bHQuZ2V0QmFyY29kZUNvbHVtbkNvdW50KCkpO1xuICAgICAgICAgICAgbGV0IGFtYmlndW91c0luZGV4VmFsdWVzTGlzdCA9IC8qTGlzdDxpbnRbXT4qLyBbXTtcbiAgICAgICAgICAgIGxldCBhbWJpZ3VvdXNJbmRleGVzTGlzdCA9IC8qQ29sbGVjdGlvbjxJbnRlZ2VyPiovIG5ldyBBcnJheSgpO1xuICAgICAgICAgICAgZm9yIChsZXQgcm93IC8qaW50Ki8gPSAwOyByb3cgPCBkZXRlY3Rpb25SZXN1bHQuZ2V0QmFyY29kZVJvd0NvdW50KCk7IHJvdysrKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgY29sdW1uIC8qaW50Ki8gPSAwOyBjb2x1bW4gPCBkZXRlY3Rpb25SZXN1bHQuZ2V0QmFyY29kZUNvbHVtbkNvdW50KCk7IGNvbHVtbisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCB2YWx1ZXMgPSBiYXJjb2RlTWF0cml4W3Jvd11bY29sdW1uICsgMV0uZ2V0VmFsdWUoKTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNvZGV3b3JkSW5kZXggPSByb3cgKiBkZXRlY3Rpb25SZXN1bHQuZ2V0QmFyY29kZUNvbHVtbkNvdW50KCkgKyBjb2x1bW47XG4gICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcmFzdXJlcy5wdXNoKGNvZGV3b3JkSW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHZhbHVlcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGV3b3Jkc1tjb2Rld29yZEluZGV4XSA9IHZhbHVlc1swXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFtYmlndW91c0luZGV4ZXNMaXN0LnB1c2goY29kZXdvcmRJbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbWJpZ3VvdXNJbmRleFZhbHVlc0xpc3QucHVzaCh2YWx1ZXMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGFtYmlndW91c0luZGV4VmFsdWVzID0gbmV3IEFycmF5KGFtYmlndW91c0luZGV4VmFsdWVzTGlzdC5sZW5ndGgpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMDsgaSA8IGFtYmlndW91c0luZGV4VmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgYW1iaWd1b3VzSW5kZXhWYWx1ZXNbaV0gPSBhbWJpZ3VvdXNJbmRleFZhbHVlc0xpc3RbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmNyZWF0ZURlY29kZXJSZXN1bHRGcm9tQW1iaWd1b3VzVmFsdWVzKGRldGVjdGlvblJlc3VsdC5nZXRCYXJjb2RlRUNMZXZlbCgpLCBjb2Rld29yZHMsIFBERjQxN0NvbW1vbi50b0ludEFycmF5KGVyYXN1cmVzKSwgUERGNDE3Q29tbW9uLnRvSW50QXJyYXkoYW1iaWd1b3VzSW5kZXhlc0xpc3QpLCBhbWJpZ3VvdXNJbmRleFZhbHVlcyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoaXMgbWV0aG9kIGRlYWxzIHdpdGggdGhlIGZhY3QsIHRoYXQgdGhlIGRlY29kaW5nIHByb2Nlc3MgZG9lc24ndCBhbHdheXMgeWllbGQgYSBzaW5nbGUgbW9zdCBsaWtlbHkgdmFsdWUuIFRoZVxuICAgICAgICAgKiBjdXJyZW50IGVycm9yIGNvcnJlY3Rpb24gaW1wbGVtZW50YXRpb24gZG9lc24ndCBkZWFsIHdpdGggZXJhc3VyZXMgdmVyeSB3ZWxsLCBzbyBpdCdzIGJldHRlciB0byBwcm92aWRlIGEgdmFsdWVcbiAgICAgICAgICogZm9yIHRoZXNlIGFtYmlndW91cyBjb2Rld29yZHMgaW5zdGVhZCBvZiB0cmVhdGluZyBpdCBhcyBhbiBlcmFzdXJlLiBUaGUgcHJvYmxlbSBpcyB0aGF0IHdlIGRvbid0IGtub3cgd2hpY2ggb2ZcbiAgICAgICAgICogdGhlIGFtYmlndW91cyB2YWx1ZXMgdG8gY2hvb3NlLiBXZSB0cnkgZGVjb2RlIHVzaW5nIHRoZSBmaXJzdCB2YWx1ZSwgYW5kIGlmIHRoYXQgZmFpbHMsIHdlIHVzZSBhbm90aGVyIG9mIHRoZVxuICAgICAgICAgKiBhbWJpZ3VvdXMgdmFsdWVzIGFuZCB0cnkgdG8gZGVjb2RlIGFnYWluLiBUaGlzIHVzdWFsbHkgb25seSBoYXBwZW5zIG9uIHZlcnkgaGFyZCB0byByZWFkIGFuZCBkZWNvZGUgYmFyY29kZXMsXG4gICAgICAgICAqIHNvIGRlY29kaW5nIHRoZSBub3JtYWwgYmFyY29kZXMgaXMgbm90IGFmZmVjdGVkIGJ5IHRoaXMuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBlcmFzdXJlQXJyYXkgY29udGFpbnMgdGhlIGluZGV4ZXMgb2YgZXJhc3VyZXNcbiAgICAgICAgICogQHBhcmFtIGFtYmlndW91c0luZGV4ZXMgYXJyYXkgd2l0aCB0aGUgaW5kZXhlcyB0aGF0IGhhdmUgbW9yZSB0aGFuIG9uZSBtb3N0IGxpa2VseSB2YWx1ZVxuICAgICAgICAgKiBAcGFyYW0gYW1iaWd1b3VzSW5kZXhWYWx1ZXMgdHdvIGRpbWVuc2lvbmFsIGFycmF5IHRoYXQgY29udGFpbnMgdGhlIGFtYmlndW91cyB2YWx1ZXMuIFRoZSBmaXJzdCBkaW1lbnNpb24gbXVzdFxuICAgICAgICAgKiBiZSB0aGUgc2FtZSBsZW5ndGggYXMgdGhlIGFtYmlndW91c0luZGV4ZXMgYXJyYXlcbiAgICAgICAgICpcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb25cbiAgICAgICAgICogQHRocm93cyBDaGVja3N1bUV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGNyZWF0ZURlY29kZXJSZXN1bHRGcm9tQW1iaWd1b3VzVmFsdWVzKGVjTGV2ZWwsIGNvZGV3b3JkcywgZXJhc3VyZUFycmF5LCBhbWJpZ3VvdXNJbmRleGVzLCBhbWJpZ3VvdXNJbmRleFZhbHVlcykge1xuICAgICAgICAgICAgbGV0IGFtYmlndW91c0luZGV4Q291bnQgPSBuZXcgSW50MzJBcnJheShhbWJpZ3VvdXNJbmRleGVzLmxlbmd0aCk7XG4gICAgICAgICAgICBsZXQgdHJpZXMgPSAxMDA7XG4gICAgICAgICAgICB3aGlsZSAodHJpZXMtLSA+IDApIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAwOyBpIDwgYW1iaWd1b3VzSW5kZXhDb3VudC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBjb2Rld29yZHNbYW1iaWd1b3VzSW5kZXhlc1tpXV0gPSBhbWJpZ3VvdXNJbmRleFZhbHVlc1tpXVthbWJpZ3VvdXNJbmRleENvdW50W2ldXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFBERjQxN1NjYW5uaW5nRGVjb2Rlci5kZWNvZGVDb2Rld29yZHMoY29kZXdvcmRzLCBlY0xldmVsLCBlcmFzdXJlQXJyYXkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBpZ25vcmVkID0gZXJyIGluc3RhbmNlb2YgQ2hlY2tzdW1FeGNlcHRpb247XG4gICAgICAgICAgICAgICAgICAgIGlmICghaWdub3JlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChhbWJpZ3VvdXNJbmRleENvdW50Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBDaGVja3N1bUV4Y2VwdGlvbi5nZXRDaGVja3N1bUluc3RhbmNlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCBhbWJpZ3VvdXNJbmRleENvdW50Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhbWJpZ3VvdXNJbmRleENvdW50W2ldIDwgYW1iaWd1b3VzSW5kZXhWYWx1ZXNbaV0ubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYW1iaWd1b3VzSW5kZXhDb3VudFtpXSsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbWJpZ3VvdXNJbmRleENvdW50W2ldID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpID09PSBhbWJpZ3VvdXNJbmRleENvdW50Lmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBDaGVja3N1bUV4Y2VwdGlvbi5nZXRDaGVja3N1bUluc3RhbmNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBDaGVja3N1bUV4Y2VwdGlvbi5nZXRDaGVja3N1bUluc3RhbmNlKCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGNyZWF0ZUJhcmNvZGVNYXRyaXgoZGV0ZWN0aW9uUmVzdWx0KSB7XG4gICAgICAgICAgICAvLyBsZXQgYmFyY29kZU1hdHJpeDogQmFyY29kZVZhbHVlW11bXSA9XG4gICAgICAgICAgICAvLyBuZXcgQmFyY29kZVZhbHVlW2RldGVjdGlvblJlc3VsdC5nZXRCYXJjb2RlUm93Q291bnQoKV1bZGV0ZWN0aW9uUmVzdWx0LmdldEJhcmNvZGVDb2x1bW5Db3VudCgpICsgMl07XG4gICAgICAgICAgICBsZXQgYmFyY29kZU1hdHJpeCA9IEFycmF5LmZyb20oeyBsZW5ndGg6IGRldGVjdGlvblJlc3VsdC5nZXRCYXJjb2RlUm93Q291bnQoKSB9LCAoKSA9PiBuZXcgQXJyYXkoZGV0ZWN0aW9uUmVzdWx0LmdldEJhcmNvZGVDb2x1bW5Db3VudCgpICsgMikpO1xuICAgICAgICAgICAgZm9yIChsZXQgcm93IC8qaW50Ki8gPSAwOyByb3cgPCBiYXJjb2RlTWF0cml4Lmxlbmd0aDsgcm93KyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBjb2x1bW4gLyppbnQqLyA9IDA7IGNvbHVtbiA8IGJhcmNvZGVNYXRyaXhbcm93XS5sZW5ndGg7IGNvbHVtbisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGJhcmNvZGVNYXRyaXhbcm93XVtjb2x1bW5dID0gbmV3IEJhcmNvZGVWYWx1ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBjb2x1bW4gPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgZGV0ZWN0aW9uUmVzdWx0Q29sdW1uIC8qRGV0ZWN0aW9uUmVzdWx0Q29sdW1uKi8gb2YgZGV0ZWN0aW9uUmVzdWx0LmdldERldGVjdGlvblJlc3VsdENvbHVtbnMoKSkge1xuICAgICAgICAgICAgICAgIGlmIChkZXRlY3Rpb25SZXN1bHRDb2x1bW4gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBjb2Rld29yZCAvKkNvZGV3b3JkKi8gb2YgZGV0ZWN0aW9uUmVzdWx0Q29sdW1uLmdldENvZGV3b3JkcygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCByb3dOdW1iZXIgPSBjb2Rld29yZC5nZXRSb3dOdW1iZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocm93TnVtYmVyID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJvd051bWJlciA+PSBiYXJjb2RlTWF0cml4Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgaGF2ZSBtb3JlIHJvd3MgdGhhbiB0aGUgYmFyY29kZSBtZXRhZGF0YSBhbGxvd3MgZm9yLCBpZ25vcmUgdGhlbS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhcmNvZGVNYXRyaXhbcm93TnVtYmVyXVtjb2x1bW5dLnNldFZhbHVlKGNvZGV3b3JkLmdldFZhbHVlKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb2x1bW4rKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBiYXJjb2RlTWF0cml4O1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBpc1ZhbGlkQmFyY29kZUNvbHVtbihkZXRlY3Rpb25SZXN1bHQsIGJhcmNvZGVDb2x1bW4pIHtcbiAgICAgICAgICAgIHJldHVybiBiYXJjb2RlQ29sdW1uID49IDAgJiYgYmFyY29kZUNvbHVtbiA8PSBkZXRlY3Rpb25SZXN1bHQuZ2V0QmFyY29kZUNvbHVtbkNvdW50KCkgKyAxO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXRTdGFydENvbHVtbihkZXRlY3Rpb25SZXN1bHQsIGJhcmNvZGVDb2x1bW4sIGltYWdlUm93LCBsZWZ0VG9SaWdodCkge1xuICAgICAgICAgICAgbGV0IG9mZnNldCA9IGxlZnRUb1JpZ2h0ID8gMSA6IC0xO1xuICAgICAgICAgICAgbGV0IGNvZGV3b3JkID0gbnVsbDtcbiAgICAgICAgICAgIGlmIChQREY0MTdTY2FubmluZ0RlY29kZXIuaXNWYWxpZEJhcmNvZGVDb2x1bW4oZGV0ZWN0aW9uUmVzdWx0LCBiYXJjb2RlQ29sdW1uIC0gb2Zmc2V0KSkge1xuICAgICAgICAgICAgICAgIGNvZGV3b3JkID0gZGV0ZWN0aW9uUmVzdWx0LmdldERldGVjdGlvblJlc3VsdENvbHVtbihiYXJjb2RlQ29sdW1uIC0gb2Zmc2V0KS5nZXRDb2Rld29yZChpbWFnZVJvdyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29kZXdvcmQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBsZWZ0VG9SaWdodCA/IGNvZGV3b3JkLmdldEVuZFgoKSA6IGNvZGV3b3JkLmdldFN0YXJ0WCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29kZXdvcmQgPSBkZXRlY3Rpb25SZXN1bHQuZ2V0RGV0ZWN0aW9uUmVzdWx0Q29sdW1uKGJhcmNvZGVDb2x1bW4pLmdldENvZGV3b3JkTmVhcmJ5KGltYWdlUm93KTtcbiAgICAgICAgICAgIGlmIChjb2Rld29yZCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxlZnRUb1JpZ2h0ID8gY29kZXdvcmQuZ2V0U3RhcnRYKCkgOiBjb2Rld29yZC5nZXRFbmRYKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmlzVmFsaWRCYXJjb2RlQ29sdW1uKGRldGVjdGlvblJlc3VsdCwgYmFyY29kZUNvbHVtbiAtIG9mZnNldCkpIHtcbiAgICAgICAgICAgICAgICBjb2Rld29yZCA9IGRldGVjdGlvblJlc3VsdC5nZXREZXRlY3Rpb25SZXN1bHRDb2x1bW4oYmFyY29kZUNvbHVtbiAtIG9mZnNldCkuZ2V0Q29kZXdvcmROZWFyYnkoaW1hZ2VSb3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvZGV3b3JkICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVmdFRvUmlnaHQgPyBjb2Rld29yZC5nZXRFbmRYKCkgOiBjb2Rld29yZC5nZXRTdGFydFgoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBza2lwcGVkQ29sdW1ucyA9IDA7XG4gICAgICAgICAgICB3aGlsZSAoUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmlzVmFsaWRCYXJjb2RlQ29sdW1uKGRldGVjdGlvblJlc3VsdCwgYmFyY29kZUNvbHVtbiAtIG9mZnNldCkpIHtcbiAgICAgICAgICAgICAgICBiYXJjb2RlQ29sdW1uIC09IG9mZnNldDtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBwcmV2aW91c1Jvd0NvZGV3b3JkIC8qQ29kZXdvcmQqLyBvZiBkZXRlY3Rpb25SZXN1bHQuZ2V0RGV0ZWN0aW9uUmVzdWx0Q29sdW1uKGJhcmNvZGVDb2x1bW4pLmdldENvZGV3b3JkcygpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1Jvd0NvZGV3b3JkICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAobGVmdFRvUmlnaHQgPyBwcmV2aW91c1Jvd0NvZGV3b3JkLmdldEVuZFgoKSA6IHByZXZpb3VzUm93Q29kZXdvcmQuZ2V0U3RhcnRYKCkpICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQgKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBza2lwcGVkQ29sdW1ucyAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChwcmV2aW91c1Jvd0NvZGV3b3JkLmdldEVuZFgoKSAtIHByZXZpb3VzUm93Q29kZXdvcmQuZ2V0U3RhcnRYKCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNraXBwZWRDb2x1bW5zKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbGVmdFRvUmlnaHQgPyBkZXRlY3Rpb25SZXN1bHQuZ2V0Qm91bmRpbmdCb3goKS5nZXRNaW5YKCkgOiBkZXRlY3Rpb25SZXN1bHQuZ2V0Qm91bmRpbmdCb3goKS5nZXRNYXhYKCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGRldGVjdENvZGV3b3JkKGltYWdlLCBtaW5Db2x1bW4sIG1heENvbHVtbiwgbGVmdFRvUmlnaHQsIHN0YXJ0Q29sdW1uLCBpbWFnZVJvdywgbWluQ29kZXdvcmRXaWR0aCwgbWF4Q29kZXdvcmRXaWR0aCkge1xuICAgICAgICAgICAgc3RhcnRDb2x1bW4gPSBQREY0MTdTY2FubmluZ0RlY29kZXIuYWRqdXN0Q29kZXdvcmRTdGFydENvbHVtbihpbWFnZSwgbWluQ29sdW1uLCBtYXhDb2x1bW4sIGxlZnRUb1JpZ2h0LCBzdGFydENvbHVtbiwgaW1hZ2VSb3cpO1xuICAgICAgICAgICAgLy8gd2UgdXN1YWxseSBrbm93IGZhaXJseSBleGFjdCBub3cgaG93IGxvbmcgYSBjb2Rld29yZCBpcy4gV2Ugc2hvdWxkIHByb3ZpZGUgbWluaW11bSBhbmQgbWF4aW11bSBleHBlY3RlZCBsZW5ndGhcbiAgICAgICAgICAgIC8vIGFuZCB0cnkgdG8gYWRqdXN0IHRoZSByZWFkIHBpeGVscywgZS5nLiByZW1vdmUgc2luZ2xlIHBpeGVsIGVycm9ycyBvciB0cnkgdG8gY3V0IG9mZiBleGNlZWRpbmcgcGl4ZWxzLlxuICAgICAgICAgICAgLy8gbWluIGFuZCBtYXhDb2Rld29yZFdpZHRoIHNob3VsZCBub3QgYmUgdXNlZCBhcyB0aGV5IGFyZSBjYWxjdWxhdGVkIGZvciB0aGUgd2hvbGUgYmFyY29kZSBhbiBjYW4gYmUgaW5hY2N1cmF0ZVxuICAgICAgICAgICAgLy8gZm9yIHRoZSBjdXJyZW50IHBvc2l0aW9uXG4gICAgICAgICAgICBsZXQgbW9kdWxlQml0Q291bnQgPSBQREY0MTdTY2FubmluZ0RlY29kZXIuZ2V0TW9kdWxlQml0Q291bnQoaW1hZ2UsIG1pbkNvbHVtbiwgbWF4Q29sdW1uLCBsZWZ0VG9SaWdodCwgc3RhcnRDb2x1bW4sIGltYWdlUm93KTtcbiAgICAgICAgICAgIGlmIChtb2R1bGVCaXRDb3VudCA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZW5kQ29sdW1uO1xuICAgICAgICAgICAgbGV0IGNvZGV3b3JkQml0Q291bnQgPSBNYXRoVXRpbHMuc3VtKG1vZHVsZUJpdENvdW50KTtcbiAgICAgICAgICAgIGlmIChsZWZ0VG9SaWdodCkge1xuICAgICAgICAgICAgICAgIGVuZENvbHVtbiA9IHN0YXJ0Q29sdW1uICsgY29kZXdvcmRCaXRDb3VudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCBtb2R1bGVCaXRDb3VudC5sZW5ndGggLyAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHRtcENvdW50ID0gbW9kdWxlQml0Q291bnRbaV07XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZUJpdENvdW50W2ldID0gbW9kdWxlQml0Q291bnRbbW9kdWxlQml0Q291bnQubGVuZ3RoIC0gMSAtIGldO1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGVCaXRDb3VudFttb2R1bGVCaXRDb3VudC5sZW5ndGggLSAxIC0gaV0gPSB0bXBDb3VudDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZW5kQ29sdW1uID0gc3RhcnRDb2x1bW47XG4gICAgICAgICAgICAgICAgc3RhcnRDb2x1bW4gPSBlbmRDb2x1bW4gLSBjb2Rld29yZEJpdENvdW50O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gVE9ETyBpbXBsZW1lbnQgY2hlY2sgZm9yIHdpZHRoIGFuZCBjb3JyZWN0aW9uIG9mIGJsYWNrIGFuZCB3aGl0ZSBiYXJzXG4gICAgICAgICAgICAvLyB1c2Ugc3RhcnQgKGFuZCBtYXliZSBzdG9wIHBhdHRlcm4pIHRvIGRldGVybWluZSBpZiBibGFjayBiYXJzIGFyZSB3aWRlciB0aGFuIHdoaXRlIGJhcnMuIElmIHNvLCBhZGp1c3QuXG4gICAgICAgICAgICAvLyBzaG91bGQgcHJvYmFibHkgZG9uZSBvbmx5IGZvciBjb2Rld29yZHMgd2l0aCBhIGxvdCBtb3JlIHRoYW4gMTcgYml0cy5cbiAgICAgICAgICAgIC8vIFRoZSBmb2xsb3dpbmcgZml4ZXMgMTAtMS5wbmcsIHdoaWNoIGhhcyB3aWRlIGJsYWNrIGJhcnMgYW5kIHNtYWxsIHdoaXRlIGJhcnNcbiAgICAgICAgICAgIC8vICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCBtb2R1bGVCaXRDb3VudC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgLy8gICAgICBpZiAoaSAlIDIgPT09IDApIHtcbiAgICAgICAgICAgIC8vICAgICAgICBtb2R1bGVCaXRDb3VudFtpXS0tO1xuICAgICAgICAgICAgLy8gICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gICAgICAgIG1vZHVsZUJpdENvdW50W2ldKys7XG4gICAgICAgICAgICAvLyAgICAgIH1cbiAgICAgICAgICAgIC8vICAgIH1cbiAgICAgICAgICAgIC8vIFdlIGNvdWxkIGFsc28gdXNlIHRoZSB3aWR0aCBvZiBzdXJyb3VuZGluZyBjb2Rld29yZHMgZm9yIG1vcmUgYWNjdXJhdGUgcmVzdWx0cywgYnV0IHRoaXMgc2VlbXNcbiAgICAgICAgICAgIC8vIHN1ZmZpY2llbnQgZm9yIG5vd1xuICAgICAgICAgICAgaWYgKCFQREY0MTdTY2FubmluZ0RlY29kZXIuY2hlY2tDb2Rld29yZFNrZXcoY29kZXdvcmRCaXRDb3VudCwgbWluQ29kZXdvcmRXaWR0aCwgbWF4Q29kZXdvcmRXaWR0aCkpIHtcbiAgICAgICAgICAgICAgICAvLyBXZSBjb3VsZCB0cnkgdG8gdXNlIHRoZSBzdGFydFggYW5kIGVuZFggcG9zaXRpb24gb2YgdGhlIGNvZGV3b3JkIGluIHRoZSBzYW1lIGNvbHVtbiBpbiB0aGUgcHJldmlvdXMgcm93LFxuICAgICAgICAgICAgICAgIC8vIGNyZWF0ZSB0aGUgYml0IGNvdW50IGZyb20gaXQgYW5kIG5vcm1hbGl6ZSBpdCB0byA4LiBUaGlzIHdvdWxkIGhlbHAgd2l0aCBzaW5nbGUgcGl4ZWwgZXJyb3JzLlxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGRlY29kZWRWYWx1ZSA9IFBERjQxN0NvZGV3b3JkRGVjb2Rlci5nZXREZWNvZGVkVmFsdWUobW9kdWxlQml0Q291bnQpO1xuICAgICAgICAgICAgbGV0IGNvZGV3b3JkID0gUERGNDE3Q29tbW9uLmdldENvZGV3b3JkKGRlY29kZWRWYWx1ZSk7XG4gICAgICAgICAgICBpZiAoY29kZXdvcmQgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IENvZGV3b3JkKHN0YXJ0Q29sdW1uLCBlbmRDb2x1bW4sIFBERjQxN1NjYW5uaW5nRGVjb2Rlci5nZXRDb2Rld29yZEJ1Y2tldE51bWJlcihkZWNvZGVkVmFsdWUpLCBjb2Rld29yZCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdldE1vZHVsZUJpdENvdW50KGltYWdlLCBtaW5Db2x1bW4sIG1heENvbHVtbiwgbGVmdFRvUmlnaHQsIHN0YXJ0Q29sdW1uLCBpbWFnZVJvdykge1xuICAgICAgICAgICAgbGV0IGltYWdlQ29sdW1uID0gc3RhcnRDb2x1bW47XG4gICAgICAgICAgICBsZXQgbW9kdWxlQml0Q291bnQgPSBuZXcgSW50MzJBcnJheSg4KTtcbiAgICAgICAgICAgIGxldCBtb2R1bGVOdW1iZXIgPSAwO1xuICAgICAgICAgICAgbGV0IGluY3JlbWVudCA9IGxlZnRUb1JpZ2h0ID8gMSA6IC0xO1xuICAgICAgICAgICAgbGV0IHByZXZpb3VzUGl4ZWxWYWx1ZSA9IGxlZnRUb1JpZ2h0O1xuICAgICAgICAgICAgd2hpbGUgKChsZWZ0VG9SaWdodCA/IGltYWdlQ29sdW1uIDwgbWF4Q29sdW1uIDogaW1hZ2VDb2x1bW4gPj0gbWluQ29sdW1uKSAmJlxuICAgICAgICAgICAgICAgIG1vZHVsZU51bWJlciA8IG1vZHVsZUJpdENvdW50Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGlmIChpbWFnZS5nZXQoaW1hZ2VDb2x1bW4sIGltYWdlUm93KSA9PT0gcHJldmlvdXNQaXhlbFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZUJpdENvdW50W21vZHVsZU51bWJlcl0rKztcbiAgICAgICAgICAgICAgICAgICAgaW1hZ2VDb2x1bW4gKz0gaW5jcmVtZW50O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlTnVtYmVyKys7XG4gICAgICAgICAgICAgICAgICAgIHByZXZpb3VzUGl4ZWxWYWx1ZSA9ICFwcmV2aW91c1BpeGVsVmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1vZHVsZU51bWJlciA9PT0gbW9kdWxlQml0Q291bnQubGVuZ3RoIHx8XG4gICAgICAgICAgICAgICAgKChpbWFnZUNvbHVtbiA9PT0gKGxlZnRUb1JpZ2h0ID8gbWF4Q29sdW1uIDogbWluQ29sdW1uKSkgJiZcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlTnVtYmVyID09PSBtb2R1bGVCaXRDb3VudC5sZW5ndGggLSAxKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb2R1bGVCaXRDb3VudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXROdW1iZXJPZkVDQ29kZVdvcmRzKGJhcmNvZGVFQ0xldmVsKSB7XG4gICAgICAgICAgICByZXR1cm4gMiA8PCBiYXJjb2RlRUNMZXZlbDtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgYWRqdXN0Q29kZXdvcmRTdGFydENvbHVtbihpbWFnZSwgbWluQ29sdW1uLCBtYXhDb2x1bW4sIGxlZnRUb1JpZ2h0LCBjb2Rld29yZFN0YXJ0Q29sdW1uLCBpbWFnZVJvdykge1xuICAgICAgICAgICAgbGV0IGNvcnJlY3RlZFN0YXJ0Q29sdW1uID0gY29kZXdvcmRTdGFydENvbHVtbjtcbiAgICAgICAgICAgIGxldCBpbmNyZW1lbnQgPSBsZWZ0VG9SaWdodCA/IC0xIDogMTtcbiAgICAgICAgICAgIC8vIHRoZXJlIHNob3VsZCBiZSBubyBibGFjayBwaXhlbHMgYmVmb3JlIHRoZSBzdGFydCBjb2x1bW4uIElmIHRoZXJlIGFyZSwgdGhlbiB3ZSBuZWVkIHRvIHN0YXJ0IGVhcmxpZXIuXG4gICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAwOyBpIDwgMjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKChsZWZ0VG9SaWdodCA/IGNvcnJlY3RlZFN0YXJ0Q29sdW1uID49IG1pbkNvbHVtbiA6IGNvcnJlY3RlZFN0YXJ0Q29sdW1uIDwgbWF4Q29sdW1uKSAmJlxuICAgICAgICAgICAgICAgICAgICBsZWZ0VG9SaWdodCA9PT0gaW1hZ2UuZ2V0KGNvcnJlY3RlZFN0YXJ0Q29sdW1uLCBpbWFnZVJvdykpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKE1hdGguYWJzKGNvZGV3b3JkU3RhcnRDb2x1bW4gLSBjb3JyZWN0ZWRTdGFydENvbHVtbikgPiBQREY0MTdTY2FubmluZ0RlY29kZXIuQ09ERVdPUkRfU0tFV19TSVpFKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29kZXdvcmRTdGFydENvbHVtbjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb3JyZWN0ZWRTdGFydENvbHVtbiArPSBpbmNyZW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGluY3JlbWVudCA9IC1pbmNyZW1lbnQ7XG4gICAgICAgICAgICAgICAgbGVmdFRvUmlnaHQgPSAhbGVmdFRvUmlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY29ycmVjdGVkU3RhcnRDb2x1bW47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGNoZWNrQ29kZXdvcmRTa2V3KGNvZGV3b3JkU2l6ZSwgbWluQ29kZXdvcmRXaWR0aCwgbWF4Q29kZXdvcmRXaWR0aCkge1xuICAgICAgICAgICAgcmV0dXJuIG1pbkNvZGV3b3JkV2lkdGggLSBQREY0MTdTY2FubmluZ0RlY29kZXIuQ09ERVdPUkRfU0tFV19TSVpFIDw9IGNvZGV3b3JkU2l6ZSAmJlxuICAgICAgICAgICAgICAgIGNvZGV3b3JkU2l6ZSA8PSBtYXhDb2Rld29yZFdpZHRoICsgUERGNDE3U2Nhbm5pbmdEZWNvZGVyLkNPREVXT1JEX1NLRVdfU0laRTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb24sXG4gICAgICAgICAqIEB0aHJvd3MgQ2hlY2tzdW1FeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBkZWNvZGVDb2Rld29yZHMoY29kZXdvcmRzLCBlY0xldmVsLCBlcmFzdXJlcykge1xuICAgICAgICAgICAgaWYgKGNvZGV3b3Jkcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBGb3JtYXRFeGNlcHRpb24uZ2V0Rm9ybWF0SW5zdGFuY2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBudW1FQ0NvZGV3b3JkcyA9IDEgPDwgKGVjTGV2ZWwgKyAxKTtcbiAgICAgICAgICAgIGxldCBjb3JyZWN0ZWRFcnJvcnNDb3VudCA9IFBERjQxN1NjYW5uaW5nRGVjb2Rlci5jb3JyZWN0RXJyb3JzKGNvZGV3b3JkcywgZXJhc3VyZXMsIG51bUVDQ29kZXdvcmRzKTtcbiAgICAgICAgICAgIFBERjQxN1NjYW5uaW5nRGVjb2Rlci52ZXJpZnlDb2Rld29yZENvdW50KGNvZGV3b3JkcywgbnVtRUNDb2Rld29yZHMpO1xuICAgICAgICAgICAgLy8gRGVjb2RlIHRoZSBjb2Rld29yZHNcbiAgICAgICAgICAgIGxldCBkZWNvZGVyUmVzdWx0ID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLmRlY29kZShjb2Rld29yZHMsICcnICsgZWNMZXZlbCk7XG4gICAgICAgICAgICBkZWNvZGVyUmVzdWx0LnNldEVycm9yc0NvcnJlY3RlZChjb3JyZWN0ZWRFcnJvcnNDb3VudCk7XG4gICAgICAgICAgICBkZWNvZGVyUmVzdWx0LnNldEVyYXN1cmVzKGVyYXN1cmVzLmxlbmd0aCk7XG4gICAgICAgICAgICByZXR1cm4gZGVjb2RlclJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+R2l2ZW4gZGF0YSBhbmQgZXJyb3ItY29ycmVjdGlvbiBjb2Rld29yZHMgcmVjZWl2ZWQsIHBvc3NpYmx5IGNvcnJ1cHRlZCBieSBlcnJvcnMsIGF0dGVtcHRzIHRvXG4gICAgICAgICAqIGNvcnJlY3QgdGhlIGVycm9ycyBpbi1wbGFjZS48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBjb2Rld29yZHMgICBkYXRhIGFuZCBlcnJvciBjb3JyZWN0aW9uIGNvZGV3b3Jkc1xuICAgICAgICAgKiBAcGFyYW0gZXJhc3VyZXMgcG9zaXRpb25zIG9mIGFueSBrbm93biBlcmFzdXJlc1xuICAgICAgICAgKiBAcGFyYW0gbnVtRUNDb2Rld29yZHMgbnVtYmVyIG9mIGVycm9yIGNvcnJlY3Rpb24gY29kZXdvcmRzIHRoYXQgYXJlIGF2YWlsYWJsZSBpbiBjb2Rld29yZHNcbiAgICAgICAgICogQHRocm93cyBDaGVja3N1bUV4Y2VwdGlvbiBpZiBlcnJvciBjb3JyZWN0aW9uIGZhaWxzXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgY29ycmVjdEVycm9ycyhjb2Rld29yZHMsIGVyYXN1cmVzLCBudW1FQ0NvZGV3b3Jkcykge1xuICAgICAgICAgICAgaWYgKGVyYXN1cmVzICE9IG51bGwgJiZcbiAgICAgICAgICAgICAgICBlcmFzdXJlcy5sZW5ndGggPiBudW1FQ0NvZGV3b3JkcyAvIDIgKyBQREY0MTdTY2FubmluZ0RlY29kZXIuTUFYX0VSUk9SUyB8fFxuICAgICAgICAgICAgICAgIG51bUVDQ29kZXdvcmRzIDwgMCB8fFxuICAgICAgICAgICAgICAgIG51bUVDQ29kZXdvcmRzID4gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLk1BWF9FQ19DT0RFV09SRFMpIHtcbiAgICAgICAgICAgICAgICAvLyBUb28gbWFueSBlcnJvcnMgb3IgRUMgQ29kZXdvcmRzIGlzIGNvcnJ1cHRlZFxuICAgICAgICAgICAgICAgIHRocm93IENoZWNrc3VtRXhjZXB0aW9uLmdldENoZWNrc3VtSW5zdGFuY2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBQREY0MTdTY2FubmluZ0RlY29kZXIuZXJyb3JDb3JyZWN0aW9uLmRlY29kZShjb2Rld29yZHMsIG51bUVDQ29kZXdvcmRzLCBlcmFzdXJlcyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFZlcmlmeSB0aGF0IGFsbCBpcyBPSyB3aXRoIHRoZSBjb2Rld29yZCBhcnJheS5cbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyB2ZXJpZnlDb2Rld29yZENvdW50KGNvZGV3b3JkcywgbnVtRUNDb2Rld29yZHMpIHtcbiAgICAgICAgICAgIGlmIChjb2Rld29yZHMubGVuZ3RoIDwgNCkge1xuICAgICAgICAgICAgICAgIC8vIENvZGV3b3JkIGFycmF5IHNpemUgc2hvdWxkIGJlIGF0IGxlYXN0IDQgYWxsb3dpbmcgZm9yXG4gICAgICAgICAgICAgICAgLy8gQ291bnQgQ1csIEF0IGxlYXN0IG9uZSBEYXRhIENXLCBFcnJvciBDb3JyZWN0aW9uIENXLCBFcnJvciBDb3JyZWN0aW9uIENXXG4gICAgICAgICAgICAgICAgdGhyb3cgRm9ybWF0RXhjZXB0aW9uLmdldEZvcm1hdEluc3RhbmNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBUaGUgZmlyc3QgY29kZXdvcmQsIHRoZSBTeW1ib2wgTGVuZ3RoIERlc2NyaXB0b3IsIHNoYWxsIGFsd2F5cyBlbmNvZGUgdGhlIHRvdGFsIG51bWJlciBvZiBkYXRhXG4gICAgICAgICAgICAvLyBjb2Rld29yZHMgaW4gdGhlIHN5bWJvbCwgaW5jbHVkaW5nIHRoZSBTeW1ib2wgTGVuZ3RoIERlc2NyaXB0b3IgaXRzZWxmLCBkYXRhIGNvZGV3b3JkcyBhbmQgcGFkXG4gICAgICAgICAgICAvLyBjb2Rld29yZHMsIGJ1dCBleGNsdWRpbmcgdGhlIG51bWJlciBvZiBlcnJvciBjb3JyZWN0aW9uIGNvZGV3b3Jkcy5cbiAgICAgICAgICAgIGxldCBudW1iZXJPZkNvZGV3b3JkcyA9IGNvZGV3b3Jkc1swXTtcbiAgICAgICAgICAgIGlmIChudW1iZXJPZkNvZGV3b3JkcyA+IGNvZGV3b3Jkcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBGb3JtYXRFeGNlcHRpb24uZ2V0Rm9ybWF0SW5zdGFuY2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChudW1iZXJPZkNvZGV3b3JkcyA9PT0gMCkge1xuICAgICAgICAgICAgICAgIC8vIFJlc2V0IHRvIHRoZSBsZW5ndGggb2YgdGhlIGFycmF5IC0gOCAoQWxsb3cgZm9yIGF0IGxlYXN0IGxldmVsIDMgRXJyb3IgQ29ycmVjdGlvbiAoOCBFcnJvciBDb2Rld29yZHMpXG4gICAgICAgICAgICAgICAgaWYgKG51bUVDQ29kZXdvcmRzIDwgY29kZXdvcmRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBjb2Rld29yZHNbMF0gPSBjb2Rld29yZHMubGVuZ3RoIC0gbnVtRUNDb2Rld29yZHM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBGb3JtYXRFeGNlcHRpb24uZ2V0Rm9ybWF0SW5zdGFuY2UoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdldEJpdENvdW50Rm9yQ29kZXdvcmQoY29kZXdvcmQpIHtcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSBuZXcgSW50MzJBcnJheSg4KTtcbiAgICAgICAgICAgIGxldCBwcmV2aW91c1ZhbHVlID0gMDtcbiAgICAgICAgICAgIGxldCBpID0gcmVzdWx0Lmxlbmd0aCAtIDE7XG4gICAgICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgICAgICAgIGlmICgoY29kZXdvcmQgJiAweDEpICE9PSBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHByZXZpb3VzVmFsdWUgPSBjb2Rld29yZCAmIDB4MTtcbiAgICAgICAgICAgICAgICAgICAgaS0tO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc3VsdFtpXSsrO1xuICAgICAgICAgICAgICAgIGNvZGV3b3JkID4+PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZ2V0Q29kZXdvcmRCdWNrZXROdW1iZXIoY29kZXdvcmQpIHtcbiAgICAgICAgICAgIGlmIChjb2Rld29yZCBpbnN0YW5jZW9mIEludDMyQXJyYXkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRDb2Rld29yZEJ1Y2tldE51bWJlcl9JbnQzMkFycmF5KGNvZGV3b3JkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldENvZGV3b3JkQnVja2V0TnVtYmVyX251bWJlcihjb2Rld29yZCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdldENvZGV3b3JkQnVja2V0TnVtYmVyX251bWJlcihjb2Rld29yZCkge1xuICAgICAgICAgICAgcmV0dXJuIFBERjQxN1NjYW5uaW5nRGVjb2Rlci5nZXRDb2Rld29yZEJ1Y2tldE51bWJlcihQREY0MTdTY2FubmluZ0RlY29kZXIuZ2V0Qml0Q291bnRGb3JDb2Rld29yZChjb2Rld29yZCkpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXRDb2Rld29yZEJ1Y2tldE51bWJlcl9JbnQzMkFycmF5KG1vZHVsZUJpdENvdW50KSB7XG4gICAgICAgICAgICByZXR1cm4gKG1vZHVsZUJpdENvdW50WzBdIC0gbW9kdWxlQml0Q291bnRbMl0gKyBtb2R1bGVCaXRDb3VudFs0XSAtIG1vZHVsZUJpdENvdW50WzZdICsgOSkgJSA5O1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyB0b1N0cmluZyhiYXJjb2RlTWF0cml4KSB7XG4gICAgICAgICAgICBsZXQgZm9ybWF0dGVyID0gbmV3IEZvcm1hdHRlcigpO1xuICAgICAgICAgICAgLy8gdHJ5IChsZXQgZm9ybWF0dGVyID0gbmV3IEZvcm1hdHRlcigpKSB7XG4gICAgICAgICAgICBmb3IgKGxldCByb3cgLyppbnQqLyA9IDA7IHJvdyA8IGJhcmNvZGVNYXRyaXgubGVuZ3RoOyByb3crKykge1xuICAgICAgICAgICAgICAgIGZvcm1hdHRlci5mb3JtYXQoJ1JvdyAlMmQ6ICcsIHJvdyk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgY29sdW1uIC8qaW50Ki8gPSAwOyBjb2x1bW4gPCBiYXJjb2RlTWF0cml4W3Jvd10ubGVuZ3RoOyBjb2x1bW4rKykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgYmFyY29kZVZhbHVlID0gYmFyY29kZU1hdHJpeFtyb3ddW2NvbHVtbl07XG4gICAgICAgICAgICAgICAgICAgIGlmIChiYXJjb2RlVmFsdWUuZ2V0VmFsdWUoKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1hdHRlci5mb3JtYXQoJyAgICAgICAgJywgbnVsbCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXR0ZXIuZm9ybWF0KCclNGQoJTJkKScsIGJhcmNvZGVWYWx1ZS5nZXRWYWx1ZSgpWzBdLCBiYXJjb2RlVmFsdWUuZ2V0Q29uZmlkZW5jZShiYXJjb2RlVmFsdWUuZ2V0VmFsdWUoKVswXSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvcm1hdHRlci5mb3JtYXQoJyVuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZm9ybWF0dGVyLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAvLyB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgLypmaW5hbCovIFBERjQxN1NjYW5uaW5nRGVjb2Rlci5DT0RFV09SRF9TS0VXX1NJWkUgPSAyO1xuICAgIC8qZmluYWwqLyBQREY0MTdTY2FubmluZ0RlY29kZXIuTUFYX0VSUk9SUyA9IDM7XG4gICAgLypmaW5hbCovIFBERjQxN1NjYW5uaW5nRGVjb2Rlci5NQVhfRUNfQ09ERVdPUkRTID0gNTEyO1xuICAgIC8qZmluYWwqLyBQREY0MTdTY2FubmluZ0RlY29kZXIuZXJyb3JDb3JyZWN0aW9uID0gbmV3IEVycm9yQ29ycmVjdGlvbigpO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwOSBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLkFycmF5TGlzdDtcbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLkxpc3Q7XG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5NYXA7XG4gICAgLyoqXG4gICAgICogVGhpcyBpbXBsZW1lbnRhdGlvbiBjYW4gZGV0ZWN0IGFuZCBkZWNvZGUgUERGNDE3IGNvZGVzIGluIGFuIGltYWdlLlxuICAgICAqXG4gICAgICogQGF1dGhvciBHdWVudGhlciBHcmF1XG4gICAgICovXG4gICAgLypwdWJsaWMgZmluYWwqLyBjbGFzcyBQREY0MTdSZWFkZXIge1xuICAgICAgICAvLyBwcml2YXRlIHN0YXRpYyAvKmZpbmFsIFJlc3VsdFtdKi8gRU1QVFlfUkVTVUxUX0FSUkFZOiBSZXN1bHRbXSA9IG5ldyBSZXN1bHQoWzBdKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIExvY2F0ZXMgYW5kIGRlY29kZXMgYSBQREY0MTcgY29kZSBpbiBhbiBpbWFnZS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiBhIFN0cmluZyByZXByZXNlbnRpbmcgdGhlIGNvbnRlbnQgZW5jb2RlZCBieSB0aGUgUERGNDE3IGNvZGVcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBpZiBhIFBERjQxNyBjb2RlIGNhbm5vdCBiZSBmb3VuZCxcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb24gaWYgYSBQREY0MTcgY2Fubm90IGJlIGRlY29kZWRcbiAgICAgICAgICogQHRocm93cyBDaGVja3N1bUV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIGRlY29kZShpbWFnZSwgaGludHMgPSBudWxsKSB7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gUERGNDE3UmVhZGVyLmRlY29kZShpbWFnZSwgaGludHMsIGZhbHNlKTtcbiAgICAgICAgICAgIGlmIChyZXN1bHQgPT0gbnVsbCB8fCByZXN1bHQubGVuZ3RoID09PSAwIHx8IHJlc3VsdFswXSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgTm90Rm91bmRFeGNlcHRpb24uZ2V0Tm90Rm91bmRJbnN0YW5jZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdFswXTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIEJpbmFyeUJpdG1hcFxuICAgICAgICAgKiBAcGFyYW0gaW1hZ2VcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgLy8gICBAT3ZlcnJpZGVcbiAgICAgICAgZGVjb2RlTXVsdGlwbGUoaW1hZ2UsIGhpbnRzID0gbnVsbCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gUERGNDE3UmVhZGVyLmRlY29kZShpbWFnZSwgaGludHMsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGlnbm9yZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaWdub3JlZCBpbnN0YW5jZW9mIEZvcm1hdEV4Y2VwdGlvbiB8fCBpZ25vcmVkIGluc3RhbmNlb2YgQ2hlY2tzdW1FeGNlcHRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgTm90Rm91bmRFeGNlcHRpb24uZ2V0Tm90Rm91bmRJbnN0YW5jZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aHJvdyBpZ25vcmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gaW1hZ2VcbiAgICAgICAgICogQHBhcmFtIGhpbnRzXG4gICAgICAgICAqIEBwYXJhbSBtdWx0aXBsZVxuICAgICAgICAgKlxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uw59cbiAgICAgICAgICogQHRocm93cyBDaGVja3N1bUV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGRlY29kZShpbWFnZSwgaGludHMsIG11bHRpcGxlKSB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHRzID0gbmV3IEFycmF5KCk7XG4gICAgICAgICAgICBjb25zdCBkZXRlY3RvclJlc3VsdCA9IERldGVjdG9yJDMuZGV0ZWN0TXVsdGlwbGUoaW1hZ2UsIGhpbnRzLCBtdWx0aXBsZSk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHBvaW50cyBvZiBkZXRlY3RvclJlc3VsdC5nZXRQb2ludHMoKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRlY29kZXJSZXN1bHQgPSBQREY0MTdTY2FubmluZ0RlY29kZXIuZGVjb2RlKGRldGVjdG9yUmVzdWx0LmdldEJpdHMoKSwgcG9pbnRzWzRdLCBwb2ludHNbNV0sIHBvaW50c1s2XSwgcG9pbnRzWzddLCBQREY0MTdSZWFkZXIuZ2V0TWluQ29kZXdvcmRXaWR0aChwb2ludHMpLCBQREY0MTdSZWFkZXIuZ2V0TWF4Q29kZXdvcmRXaWR0aChwb2ludHMpKTtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgUmVzdWx0KGRlY29kZXJSZXN1bHQuZ2V0VGV4dCgpLCBkZWNvZGVyUmVzdWx0LmdldFJhd0J5dGVzKCksIHVuZGVmaW5lZCwgcG9pbnRzLCBCYXJjb2RlRm9ybWF0JDEuUERGXzQxNyk7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1dE1ldGFkYXRhKFJlc3VsdE1ldGFkYXRhVHlwZSQxLkVSUk9SX0NPUlJFQ1RJT05fTEVWRUwsIGRlY29kZXJSZXN1bHQuZ2V0RUNMZXZlbCgpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBwZGY0MTdSZXN1bHRNZXRhZGF0YSA9IGRlY29kZXJSZXN1bHQuZ2V0T3RoZXIoKTtcbiAgICAgICAgICAgICAgICBpZiAocGRmNDE3UmVzdWx0TWV0YWRhdGEgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHV0TWV0YWRhdGEoUmVzdWx0TWV0YWRhdGFUeXBlJDEuUERGNDE3X0VYVFJBX01FVEFEQVRBLCBwZGY0MTdSZXN1bHRNZXRhZGF0YSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc3VsdHMucHVzaChyZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdHMubWFwKHggPT4geCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdldE1heFdpZHRoKHAxLCBwMikge1xuICAgICAgICAgICAgaWYgKHAxID09IG51bGwgfHwgcDIgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIE1hdGgudHJ1bmMoTWF0aC5hYnMocDEuZ2V0WCgpIC0gcDIuZ2V0WCgpKSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdldE1pbldpZHRoKHAxLCBwMikge1xuICAgICAgICAgICAgaWYgKHAxID09IG51bGwgfHwgcDIgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBJbnRlZ2VyLk1BWF9WQUxVRTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBNYXRoLnRydW5jKE1hdGguYWJzKHAxLmdldFgoKSAtIHAyLmdldFgoKSkpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXRNYXhDb2Rld29yZFdpZHRoKHApIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKE1hdGgubWF4KE1hdGgubWF4KFBERjQxN1JlYWRlci5nZXRNYXhXaWR0aChwWzBdLCBwWzRdKSwgUERGNDE3UmVhZGVyLmdldE1heFdpZHRoKHBbNl0sIHBbMl0pICogUERGNDE3Q29tbW9uLk1PRFVMRVNfSU5fQ09ERVdPUkQgL1xuICAgICAgICAgICAgICAgIFBERjQxN0NvbW1vbi5NT0RVTEVTX0lOX1NUT1BfUEFUVEVSTiksIE1hdGgubWF4KFBERjQxN1JlYWRlci5nZXRNYXhXaWR0aChwWzFdLCBwWzVdKSwgUERGNDE3UmVhZGVyLmdldE1heFdpZHRoKHBbN10sIHBbM10pICogUERGNDE3Q29tbW9uLk1PRFVMRVNfSU5fQ09ERVdPUkQgL1xuICAgICAgICAgICAgICAgIFBERjQxN0NvbW1vbi5NT0RVTEVTX0lOX1NUT1BfUEFUVEVSTikpKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZ2V0TWluQ29kZXdvcmRXaWR0aChwKSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLm1pbihNYXRoLm1pbihQREY0MTdSZWFkZXIuZ2V0TWluV2lkdGgocFswXSwgcFs0XSksIFBERjQxN1JlYWRlci5nZXRNaW5XaWR0aChwWzZdLCBwWzJdKSAqIFBERjQxN0NvbW1vbi5NT0RVTEVTX0lOX0NPREVXT1JEIC9cbiAgICAgICAgICAgICAgICBQREY0MTdDb21tb24uTU9EVUxFU19JTl9TVE9QX1BBVFRFUk4pLCBNYXRoLm1pbihQREY0MTdSZWFkZXIuZ2V0TWluV2lkdGgocFsxXSwgcFs1XSksIFBERjQxN1JlYWRlci5nZXRNaW5XaWR0aChwWzddLCBwWzNdKSAqIFBERjQxN0NvbW1vbi5NT0RVTEVTX0lOX0NPREVXT1JEIC9cbiAgICAgICAgICAgICAgICBQREY0MTdDb21tb24uTU9EVUxFU19JTl9TVE9QX1BBVFRFUk4pKSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIHJlc2V0KCkge1xuICAgICAgICAgICAgLy8gbm90aGluZyBuZWVkcyB0byBiZSByZXNldFxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3VzdG9tIEVycm9yIGNsYXNzIG9mIHR5cGUgRXhjZXB0aW9uLlxuICAgICAqL1xuICAgIGNsYXNzIFJlYWRlckV4Y2VwdGlvbiBleHRlbmRzIEV4Y2VwdGlvbiB7XG4gICAgfVxuICAgIFJlYWRlckV4Y2VwdGlvbi5raW5kID0gJ1JlYWRlckV4Y2VwdGlvbic7XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA5IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qbmFtZXNwYWNlIGNvbS5nb29nbGUuenhpbmcgeyovXG4gICAgLyoqXG4gICAgICogTXVsdGlGb3JtYXRSZWFkZXIgaXMgYSBjb252ZW5pZW5jZSBjbGFzcyBhbmQgdGhlIG1haW4gZW50cnkgcG9pbnQgaW50byB0aGUgbGlicmFyeSBmb3IgbW9zdCB1c2VzLlxuICAgICAqIEJ5IGRlZmF1bHQgaXQgYXR0ZW1wdHMgdG8gZGVjb2RlIGFsbCBiYXJjb2RlIGZvcm1hdHMgdGhhdCB0aGUgbGlicmFyeSBzdXBwb3J0cy4gT3B0aW9uYWxseSwgeW91XG4gICAgICogY2FuIHByb3ZpZGUgYSBoaW50cyBvYmplY3QgdG8gcmVxdWVzdCBkaWZmZXJlbnQgYmVoYXZpb3IsIGZvciBleGFtcGxlIG9ubHkgZGVjb2RpbmcgUVIgY29kZXMuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pXG4gICAgICovXG4gICAgY2xhc3MgTXVsdGlGb3JtYXRSZWFkZXIge1xuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiB0aGlzIGNsYXNzXG4gICAgICAgICAqIFxuICAgICAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IHZlcmJvc2UgaWYgJ3RydWUnIGxvZ3Mgd2lsbCBiZSBkdW1wZWQgdG8gY29uc29sZSwgb3RoZXJ3aXNlIGhpZGRlbi5cbiAgICAgICAgICogQHBhcmFtIGhpbnRzIFRoZSBoaW50cyB0byB1c2UsIGNsZWFyaW5nIHRoZSBwcmV2aW91cyBzdGF0ZS5cbiAgICAgICAgICovXG4gICAgICAgIGNvbnN0cnVjdG9yKHZlcmJvc2UsIGhpbnRzKSB7XG4gICAgICAgICAgICB0aGlzLnZlcmJvc2UgPSAodmVyYm9zZSA9PT0gdHJ1ZSk7XG4gICAgICAgICAgICBpZiAoaGludHMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldEhpbnRzKGhpbnRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogVGhpcyB2ZXJzaW9uIG9mIGRlY29kZSBob25vcnMgdGhlIGludGVudCBvZiBSZWFkZXIuZGVjb2RlKEJpbmFyeUJpdG1hcCkgaW4gdGhhdCBpdFxuICAgICAgICAgKiBwYXNzZXMgbnVsbCBhcyBhIGhpbnQgdG8gdGhlIGRlY29kZXJzLiBIb3dldmVyLCB0aGF0IG1ha2VzIGl0IGluZWZmaWNpZW50IHRvIGNhbGwgcmVwZWF0ZWRseS5cbiAgICAgICAgICogVXNlIHNldEhpbnRzKCkgZm9sbG93ZWQgYnkgZGVjb2RlV2l0aFN0YXRlKCkgZm9yIGNvbnRpbnVvdXMgc2NhbiBhcHBsaWNhdGlvbnMuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBpbWFnZSBUaGUgcGl4ZWwgZGF0YSB0byBkZWNvZGVcbiAgICAgICAgICogQHJldHVybiBUaGUgY29udGVudHMgb2YgdGhlIGltYWdlXG4gICAgICAgICAqXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gQW55IGVycm9ycyB3aGljaCBvY2N1cnJlZFxuICAgICAgICAgKi9cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICAvLyBwdWJsaWMgZGVjb2RlKGltYWdlOiBCaW5hcnlCaXRtYXApOiBSZXN1bHQge1xuICAgICAgICAvLyAgIHNldEhpbnRzKG51bGwpXG4gICAgICAgIC8vICAgcmV0dXJuIGRlY29kZUludGVybmFsKGltYWdlKVxuICAgICAgICAvLyB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGUgYW4gaW1hZ2UgdXNpbmcgdGhlIGhpbnRzIHByb3ZpZGVkLiBEb2VzIG5vdCBob25vciBleGlzdGluZyBzdGF0ZS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGltYWdlIFRoZSBwaXhlbCBkYXRhIHRvIGRlY29kZVxuICAgICAgICAgKiBAcGFyYW0gaGludHMgVGhlIGhpbnRzIHRvIHVzZSwgY2xlYXJpbmcgdGhlIHByZXZpb3VzIHN0YXRlLlxuICAgICAgICAgKiBAcmV0dXJuIFRoZSBjb250ZW50cyBvZiB0aGUgaW1hZ2VcbiAgICAgICAgICpcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBBbnkgZXJyb3JzIHdoaWNoIG9jY3VycmVkXG4gICAgICAgICAqL1xuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGRlY29kZShpbWFnZSwgaGludHMpIHtcbiAgICAgICAgICAgIGlmIChoaW50cykge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0SGludHMoaGludHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlSW50ZXJuYWwoaW1hZ2UpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGUgYW4gaW1hZ2UgdXNpbmcgdGhlIHN0YXRlIHNldCB1cCBieSBjYWxsaW5nIHNldEhpbnRzKCkgcHJldmlvdXNseS4gQ29udGludW91cyBzY2FuXG4gICAgICAgICAqIGNsaWVudHMgd2lsbCBnZXQgYSA8Yj5sYXJnZTwvYj4gc3BlZWQgaW5jcmVhc2UgYnkgdXNpbmcgdGhpcyBpbnN0ZWFkIG9mIGRlY29kZSgpLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gaW1hZ2UgVGhlIHBpeGVsIGRhdGEgdG8gZGVjb2RlXG4gICAgICAgICAqIEByZXR1cm4gVGhlIGNvbnRlbnRzIG9mIHRoZSBpbWFnZVxuICAgICAgICAgKlxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIEFueSBlcnJvcnMgd2hpY2ggb2NjdXJyZWRcbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZVdpdGhTdGF0ZShpbWFnZSkge1xuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHRvIHNldCB1cCB0aGUgZGVmYXVsdCBzdGF0ZSBzbyB3ZSBkb24ndCBjcmFzaFxuICAgICAgICAgICAgaWYgKHRoaXMucmVhZGVycyA9PT0gbnVsbCB8fCB0aGlzLnJlYWRlcnMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0SGludHMobnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGVJbnRlcm5hbChpbWFnZSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoaXMgbWV0aG9kIGFkZHMgc3RhdGUgdG8gdGhlIE11bHRpRm9ybWF0UmVhZGVyLiBCeSBzZXR0aW5nIHRoZSBoaW50cyBvbmNlLCBzdWJzZXF1ZW50IGNhbGxzXG4gICAgICAgICAqIHRvIGRlY29kZVdpdGhTdGF0ZShpbWFnZSkgY2FuIHJldXNlIHRoZSBzYW1lIHNldCBvZiByZWFkZXJzIHdpdGhvdXQgcmVhbGxvY2F0aW5nIG1lbW9yeS4gVGhpc1xuICAgICAgICAgKiBpcyBpbXBvcnRhbnQgZm9yIHBlcmZvcm1hbmNlIGluIGNvbnRpbnVvdXMgc2NhbiBjbGllbnRzLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gaGludHMgVGhlIHNldCBvZiBoaW50cyB0byB1c2UgZm9yIHN1YnNlcXVlbnQgY2FsbHMgdG8gZGVjb2RlKGltYWdlKVxuICAgICAgICAgKi9cbiAgICAgICAgc2V0SGludHMoaGludHMpIHtcbiAgICAgICAgICAgIHRoaXMuaGludHMgPSBoaW50cztcbiAgICAgICAgICAgIGNvbnN0IHRyeUhhcmRlciA9ICFpc051bGxPclVuZGVmaW5lZChoaW50cylcbiAgICAgICAgICAgICAgICAmJiBoaW50cy5nZXQoRGVjb2RlSGludFR5cGUkMS5UUllfSEFSREVSKSA9PT0gdHJ1ZTtcbiAgICAgICAgICAgIGNvbnN0IGZvcm1hdHMgPSBpc051bGxPclVuZGVmaW5lZChoaW50cykgPyBudWxsIDogaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuUE9TU0lCTEVfRk9STUFUUyk7XG4gICAgICAgICAgICBjb25zdCByZWFkZXJzID0gbmV3IEFycmF5KCk7XG4gICAgICAgICAgICBpZiAoIWlzTnVsbE9yVW5kZWZpbmVkKGZvcm1hdHMpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYWRkT25lRFJlYWRlciA9IGZvcm1hdHMuc29tZShmID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgICAgICAgIGYgPT09IEJhcmNvZGVGb3JtYXQkMS5VUENfQSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgZiA9PT0gQmFyY29kZUZvcm1hdCQxLlVQQ19FIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICBmID09PSBCYXJjb2RlRm9ybWF0JDEuRUFOXzEzIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICBmID09PSBCYXJjb2RlRm9ybWF0JDEuRUFOXzggfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIGYgPT09IEJhcmNvZGVGb3JtYXQkMS5DT0RBQkFSIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICBmID09PSBCYXJjb2RlRm9ybWF0JDEuQ09ERV8zOSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgZiA9PT0gQmFyY29kZUZvcm1hdCQxLkNPREVfOTMgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIGYgPT09IEJhcmNvZGVGb3JtYXQkMS5DT0RFXzEyOCB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgZiA9PT0gQmFyY29kZUZvcm1hdCQxLklURiB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgZiA9PT0gQmFyY29kZUZvcm1hdCQxLlJTU18xNCB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgZiA9PT0gQmFyY29kZUZvcm1hdCQxLlJTU19FWFBBTkRFRCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgLy8gUHV0IDFEIHJlYWRlcnMgdXBmcm9udCBpbiBcIm5vcm1hbFwiIG1vZGVcbiAgICAgICAgICAgICAgICBpZiAoYWRkT25lRFJlYWRlciAmJiAhdHJ5SGFyZGVyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlcnMucHVzaChuZXcgTXVsdGlGb3JtYXRPbmVEUmVhZGVyKGhpbnRzLCB0aGlzLnZlcmJvc2UpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGZvcm1hdHMuaW5jbHVkZXMoQmFyY29kZUZvcm1hdCQxLlFSX0NPREUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlcnMucHVzaChuZXcgUVJDb2RlUmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZm9ybWF0cy5pbmNsdWRlcyhCYXJjb2RlRm9ybWF0JDEuREFUQV9NQVRSSVgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlcnMucHVzaChuZXcgRGF0YU1hdHJpeFJlYWRlcigpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGZvcm1hdHMuaW5jbHVkZXMoQmFyY29kZUZvcm1hdCQxLkFaVEVDKSkge1xuICAgICAgICAgICAgICAgICAgICByZWFkZXJzLnB1c2gobmV3IEF6dGVjUmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZm9ybWF0cy5pbmNsdWRlcyhCYXJjb2RlRm9ybWF0JDEuUERGXzQxNykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVycy5wdXNoKG5ldyBQREY0MTdSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGlmIChmb3JtYXRzLmluY2x1ZGVzKEJhcmNvZGVGb3JtYXQuTUFYSUNPREUpKSB7XG4gICAgICAgICAgICAgICAgLy8gICAgcmVhZGVycy5wdXNoKG5ldyBNYXhpQ29kZVJlYWRlcigpKVxuICAgICAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgICAgICAvLyBBdCBlbmQgaW4gXCJ0cnkgaGFyZGVyXCIgbW9kZVxuICAgICAgICAgICAgICAgIGlmIChhZGRPbmVEUmVhZGVyICYmIHRyeUhhcmRlcikge1xuICAgICAgICAgICAgICAgICAgICByZWFkZXJzLnB1c2gobmV3IE11bHRpRm9ybWF0T25lRFJlYWRlcihoaW50cywgdGhpcy52ZXJib3NlKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJlYWRlcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0cnlIYXJkZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVycy5wdXNoKG5ldyBNdWx0aUZvcm1hdE9uZURSZWFkZXIoaGludHMsIHRoaXMudmVyYm9zZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZWFkZXJzLnB1c2gobmV3IFFSQ29kZVJlYWRlcigpKTtcbiAgICAgICAgICAgICAgICByZWFkZXJzLnB1c2gobmV3IERhdGFNYXRyaXhSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgcmVhZGVycy5wdXNoKG5ldyBBenRlY1JlYWRlcigpKTtcbiAgICAgICAgICAgICAgICByZWFkZXJzLnB1c2gobmV3IFBERjQxN1JlYWRlcigpKTtcbiAgICAgICAgICAgICAgICAvLyByZWFkZXJzLnB1c2gobmV3IE1heGlDb2RlUmVhZGVyKCkpXG4gICAgICAgICAgICAgICAgaWYgKHRyeUhhcmRlcikge1xuICAgICAgICAgICAgICAgICAgICByZWFkZXJzLnB1c2gobmV3IE11bHRpRm9ybWF0T25lRFJlYWRlcihoaW50cywgdGhpcy52ZXJib3NlKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yZWFkZXJzID0gcmVhZGVyczsgLy8gLnRvQXJyYXkobmV3IFJlYWRlcltyZWFkZXJzLnNpemUoKV0pXG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICByZXNldCgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRlcnMgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHJlYWRlciBvZiB0aGlzLnJlYWRlcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnJlc2V0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGVJbnRlcm5hbChpbWFnZSkge1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZGVycyA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBSZWFkZXJFeGNlcHRpb24oJ05vIHJlYWRlcnMgd2hlcmUgc2VsZWN0ZWQsIG5vdGhpbmcgY2FuIGJlIHJlYWQuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHJlYWRlciBvZiB0aGlzLnJlYWRlcnMpIHtcbiAgICAgICAgICAgICAgICAvLyBUcnlpbmcgdG8gZGVjb2RlIHdpdGggJHtyZWFkZXJ9IHJlYWRlci5cbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVhZGVyLmRlY29kZShpbWFnZSwgdGhpcy5oaW50cyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChleCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBSZWFkZXJFeGNlcHRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIEJhZCBFeGNlcHRpb24uXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCdObyBNdWx0aUZvcm1hdCBSZWFkZXJzIHdlcmUgYWJsZSB0byBkZXRlY3QgdGhlIGNvZGUuJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjbGFzcyBCcm93c2VyTXVsdGlGb3JtYXRSZWFkZXIgZXh0ZW5kcyBCcm93c2VyQ29kZVJlYWRlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGhpbnRzID0gbnVsbCwgdGltZUJldHdlZW5TY2Fuc01pbGxpcyA9IDUwMCkge1xuICAgICAgICAgICAgY29uc3QgcmVhZGVyID0gbmV3IE11bHRpRm9ybWF0UmVhZGVyKCk7XG4gICAgICAgICAgICByZWFkZXIuc2V0SGludHMoaGludHMpO1xuICAgICAgICAgICAgc3VwZXIocmVhZGVyLCB0aW1lQmV0d2VlblNjYW5zTWlsbGlzKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogT3ZlcndyaXRlIGRlY29kZUJpdG1hcCB0byBjYWxsIGRlY29kZVdpdGhTdGF0ZSwgd2hpY2ggd2lsbCBwYXlcbiAgICAgICAgICogYXR0ZW50aW9uIHRvIHRoZSBoaW50cyBzZXQgaW4gdGhlIGNvbnN0cnVjdG9yIGZ1bmN0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGVCaXRtYXAoYmluYXJ5Qml0bWFwKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZWFkZXIuZGVjb2RlV2l0aFN0YXRlKGJpbmFyeUJpdG1hcCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAZGVwcmVjYXRlZCBNb3ZpbmcgdG8gQHp4aW5nL2Jyb3dzZXJcbiAgICAgKlxuICAgICAqIFFSIENvZGUgcmVhZGVyIHRvIHVzZSBmcm9tIGJyb3dzZXIuXG4gICAgICovXG4gICAgY2xhc3MgQnJvd3NlclBERjQxN1JlYWRlciBleHRlbmRzIEJyb3dzZXJDb2RlUmVhZGVyIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgQnJvd3NlclBERjQxN1JlYWRlci5cbiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IFt0aW1lQmV0d2VlblNjYW5zTWlsbGlzPTUwMF0gdGhlIHRpbWUgZGVsYXkgYmV0d2VlbiBzdWJzZXF1ZW50IGRlY29kZSB0cmllc1xuICAgICAgICAgKi9cbiAgICAgICAgY29uc3RydWN0b3IodGltZUJldHdlZW5TY2Fuc01pbGxpcyA9IDUwMCkge1xuICAgICAgICAgICAgc3VwZXIobmV3IFBERjQxN1JlYWRlcigpLCB0aW1lQmV0d2VlblNjYW5zTWlsbGlzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBkZXByZWNhdGVkIE1vdmluZyB0byBAenhpbmcvYnJvd3NlclxuICAgICAqXG4gICAgICogUVIgQ29kZSByZWFkZXIgdG8gdXNlIGZyb20gYnJvd3Nlci5cbiAgICAgKi9cbiAgICBjbGFzcyBCcm93c2VyUVJDb2RlUmVhZGVyIGV4dGVuZHMgQnJvd3NlckNvZGVSZWFkZXIge1xuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBCcm93c2VyUVJDb2RlUmVhZGVyLlxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gW3RpbWVCZXR3ZWVuU2NhbnNNaWxsaXM9NTAwXSB0aGUgdGltZSBkZWxheSBiZXR3ZWVuIHN1YnNlcXVlbnQgZGVjb2RlIHRyaWVzXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3Rvcih0aW1lQmV0d2VlblNjYW5zTWlsbGlzID0gNTAwKSB7XG4gICAgICAgICAgICBzdXBlcihuZXcgUVJDb2RlUmVhZGVyKCksIHRpbWVCZXR3ZWVuU2NhbnNNaWxsaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwOSBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKm5hbWVzcGFjZSBjb20uZ29vZ2xlLnp4aW5nIHsqL1xuICAgIC8qKlxuICAgICAqIFRoZXNlIGFyZSBhIHNldCBvZiBoaW50cyB0aGF0IHlvdSBtYXkgcGFzcyB0byBXcml0ZXJzIHRvIHNwZWNpZnkgdGhlaXIgYmVoYXZpb3IuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIGRzd2l0a2luQGdvb2dsZS5jb20gKERhbmllbCBTd2l0a2luKVxuICAgICAqL1xuICAgIHZhciBFbmNvZGVIaW50VHlwZTtcbiAgICAoZnVuY3Rpb24gKEVuY29kZUhpbnRUeXBlKSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTcGVjaWZpZXMgd2hhdCBkZWdyZWUgb2YgZXJyb3IgY29ycmVjdGlvbiB0byB1c2UsIGZvciBleGFtcGxlIGluIFFSIENvZGVzLlxuICAgICAgICAgKiBUeXBlIGRlcGVuZHMgb24gdGhlIGVuY29kZXIuIEZvciBleGFtcGxlIGZvciBRUiBjb2RlcyBpdCdzIHR5cGVcbiAgICAgICAgICoge0BsaW5rIGNvbS5nb29nbGUuenhpbmcucXJjb2RlLmRlY29kZXIuRXJyb3JDb3JyZWN0aW9uTGV2ZWwgRXJyb3JDb3JyZWN0aW9uTGV2ZWx9LlxuICAgICAgICAgKiBGb3IgQXp0ZWMgaXQgaXMgb2YgdHlwZSB7QGxpbmsgSW50ZWdlcn0sIHJlcHJlc2VudGluZyB0aGUgbWluaW1hbCBwZXJjZW50YWdlIG9mIGVycm9yIGNvcnJlY3Rpb24gd29yZHMuXG4gICAgICAgICAqIEZvciBQREY0MTcgaXQgaXMgb2YgdHlwZSB7QGxpbmsgSW50ZWdlcn0sIHZhbGlkIHZhbHVlcyBiZWluZyAwIHRvIDguXG4gICAgICAgICAqIEluIGFsbCBjYXNlcywgaXQgY2FuIGFsc28gYmUgYSB7QGxpbmsgU3RyaW5nfSByZXByZXNlbnRhdGlvbiBvZiB0aGUgZGVzaXJlZCB2YWx1ZSBhcyB3ZWxsLlxuICAgICAgICAgKiBOb3RlOiBhbiBBenRlYyBzeW1ib2wgc2hvdWxkIGhhdmUgYSBtaW5pbXVtIG9mIDI1JSBFQyB3b3Jkcy5cbiAgICAgICAgICovXG4gICAgICAgIEVuY29kZUhpbnRUeXBlW0VuY29kZUhpbnRUeXBlW1wiRVJST1JfQ09SUkVDVElPTlwiXSA9IDBdID0gXCJFUlJPUl9DT1JSRUNUSU9OXCI7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTcGVjaWZpZXMgd2hhdCBjaGFyYWN0ZXIgZW5jb2RpbmcgdG8gdXNlIHdoZXJlIGFwcGxpY2FibGUgKHR5cGUge0BsaW5rIFN0cmluZ30pXG4gICAgICAgICAqL1xuICAgICAgICBFbmNvZGVIaW50VHlwZVtFbmNvZGVIaW50VHlwZVtcIkNIQVJBQ1RFUl9TRVRcIl0gPSAxXSA9IFwiQ0hBUkFDVEVSX1NFVFwiO1xuICAgICAgICAvKipcbiAgICAgICAgICogU3BlY2lmaWVzIHRoZSBtYXRyaXggc2hhcGUgZm9yIERhdGEgTWF0cml4ICh0eXBlIHtAbGluayBjb20uZ29vZ2xlLnp4aW5nLmRhdGFtYXRyaXguZW5jb2Rlci5TeW1ib2xTaGFwZUhpbnR9KVxuICAgICAgICAgKi9cbiAgICAgICAgRW5jb2RlSGludFR5cGVbRW5jb2RlSGludFR5cGVbXCJEQVRBX01BVFJJWF9TSEFQRVwiXSA9IDJdID0gXCJEQVRBX01BVFJJWF9TSEFQRVwiO1xuICAgICAgICAvKipcbiAgICAgICAgICogU3BlY2lmaWVzIGEgbWluaW11bSBiYXJjb2RlIHNpemUgKHR5cGUge0BsaW5rIERpbWVuc2lvbn0pLiBPbmx5IGFwcGxpY2FibGUgdG8gRGF0YSBNYXRyaXggbm93LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAZGVwcmVjYXRlZCB1c2Ugd2lkdGgvaGVpZ2h0IHBhcmFtcyBpblxuICAgICAgICAgKiB7QGxpbmsgY29tLmdvb2dsZS56eGluZy5kYXRhbWF0cml4LkRhdGFNYXRyaXhXcml0ZXIjZW5jb2RlKFN0cmluZywgQmFyY29kZUZvcm1hdCwgaW50LCBpbnQpfVxuICAgICAgICAgKi9cbiAgICAgICAgLypARGVwcmVjYXRlZCovXG4gICAgICAgIEVuY29kZUhpbnRUeXBlW0VuY29kZUhpbnRUeXBlW1wiTUlOX1NJWkVcIl0gPSAzXSA9IFwiTUlOX1NJWkVcIjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNwZWNpZmllcyBhIG1heGltdW0gYmFyY29kZSBzaXplICh0eXBlIHtAbGluayBEaW1lbnNpb259KS4gT25seSBhcHBsaWNhYmxlIHRvIERhdGEgTWF0cml4IG5vdy5cbiAgICAgICAgICpcbiAgICAgICAgICogQGRlcHJlY2F0ZWQgd2l0aG91dCByZXBsYWNlbWVudFxuICAgICAgICAgKi9cbiAgICAgICAgLypARGVwcmVjYXRlZCovXG4gICAgICAgIEVuY29kZUhpbnRUeXBlW0VuY29kZUhpbnRUeXBlW1wiTUFYX1NJWkVcIl0gPSA0XSA9IFwiTUFYX1NJWkVcIjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNwZWNpZmllcyBtYXJnaW4sIGluIHBpeGVscywgdG8gdXNlIHdoZW4gZ2VuZXJhdGluZyB0aGUgYmFyY29kZS4gVGhlIG1lYW5pbmcgY2FuIHZhcnlcbiAgICAgICAgICogYnkgZm9ybWF0OyBmb3IgZXhhbXBsZSBpdCBjb250cm9scyBtYXJnaW4gYmVmb3JlIGFuZCBhZnRlciB0aGUgYmFyY29kZSBob3Jpem9udGFsbHkgZm9yXG4gICAgICAgICAqIG1vc3QgMUQgZm9ybWF0cy4gKFR5cGUge0BsaW5rIEludGVnZXJ9LCBvciB7QGxpbmsgU3RyaW5nfSByZXByZXNlbnRhdGlvbiBvZiB0aGUgaW50ZWdlciB2YWx1ZSkuXG4gICAgICAgICAqL1xuICAgICAgICBFbmNvZGVIaW50VHlwZVtFbmNvZGVIaW50VHlwZVtcIk1BUkdJTlwiXSA9IDVdID0gXCJNQVJHSU5cIjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNwZWNpZmllcyB3aGV0aGVyIHRvIHVzZSBjb21wYWN0IG1vZGUgZm9yIFBERjQxNyAodHlwZSB7QGxpbmsgQm9vbGVhbn0sIG9yIFwidHJ1ZVwiIG9yIFwiZmFsc2VcIlxuICAgICAgICAgKiB7QGxpbmsgU3RyaW5nfSB2YWx1ZSkuXG4gICAgICAgICAqL1xuICAgICAgICBFbmNvZGVIaW50VHlwZVtFbmNvZGVIaW50VHlwZVtcIlBERjQxN19DT01QQUNUXCJdID0gNl0gPSBcIlBERjQxN19DT01QQUNUXCI7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTcGVjaWZpZXMgd2hhdCBjb21wYWN0aW9uIG1vZGUgdG8gdXNlIGZvciBQREY0MTcgKHR5cGVcbiAgICAgICAgICoge0BsaW5rIGNvbS5nb29nbGUuenhpbmcucGRmNDE3LmVuY29kZXIuQ29tcGFjdGlvbiBDb21wYWN0aW9ufSBvciB7QGxpbmsgU3RyaW5nfSB2YWx1ZSBvZiBvbmUgb2YgaXRzXG4gICAgICAgICAqIGVudW0gdmFsdWVzKS5cbiAgICAgICAgICovXG4gICAgICAgIEVuY29kZUhpbnRUeXBlW0VuY29kZUhpbnRUeXBlW1wiUERGNDE3X0NPTVBBQ1RJT05cIl0gPSA3XSA9IFwiUERGNDE3X0NPTVBBQ1RJT05cIjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNwZWNpZmllcyB0aGUgbWluaW11bSBhbmQgbWF4aW11bSBudW1iZXIgb2Ygcm93cyBhbmQgY29sdW1ucyBmb3IgUERGNDE3ICh0eXBlXG4gICAgICAgICAqIHtAbGluayBjb20uZ29vZ2xlLnp4aW5nLnBkZjQxNy5lbmNvZGVyLkRpbWVuc2lvbnMgRGltZW5zaW9uc30pLlxuICAgICAgICAgKi9cbiAgICAgICAgRW5jb2RlSGludFR5cGVbRW5jb2RlSGludFR5cGVbXCJQREY0MTdfRElNRU5TSU9OU1wiXSA9IDhdID0gXCJQREY0MTdfRElNRU5TSU9OU1wiO1xuICAgICAgICAvKipcbiAgICAgICAgICogU3BlY2lmaWVzIHRoZSByZXF1aXJlZCBudW1iZXIgb2YgbGF5ZXJzIGZvciBhbiBBenRlYyBjb2RlLlxuICAgICAgICAgKiBBIG5lZ2F0aXZlIG51bWJlciAoLTEsIC0yLCAtMywgLTQpIHNwZWNpZmllcyBhIGNvbXBhY3QgQXp0ZWMgY29kZS5cbiAgICAgICAgICogMCBpbmRpY2F0ZXMgdG8gdXNlIHRoZSBtaW5pbXVtIG51bWJlciBvZiBsYXllcnMgKHRoZSBkZWZhdWx0KS5cbiAgICAgICAgICogQSBwb3NpdGl2ZSBudW1iZXIgKDEsIDIsIC4uIDMyKSBzcGVjaWZpZXMgYSBub3JtYWwgKG5vbi1jb21wYWN0KSBBenRlYyBjb2RlLlxuICAgICAgICAgKiAoVHlwZSB7QGxpbmsgSW50ZWdlcn0sIG9yIHtAbGluayBTdHJpbmd9IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBpbnRlZ2VyIHZhbHVlKS5cbiAgICAgICAgICovXG4gICAgICAgIEVuY29kZUhpbnRUeXBlW0VuY29kZUhpbnRUeXBlW1wiQVpURUNfTEFZRVJTXCJdID0gOV0gPSBcIkFaVEVDX0xBWUVSU1wiO1xuICAgICAgICAvKipcbiAgICAgICAgICogU3BlY2lmaWVzIHRoZSBleGFjdCB2ZXJzaW9uIG9mIFFSIGNvZGUgdG8gYmUgZW5jb2RlZC5cbiAgICAgICAgICogKFR5cGUge0BsaW5rIEludGVnZXJ9LCBvciB7QGxpbmsgU3RyaW5nfSByZXByZXNlbnRhdGlvbiBvZiB0aGUgaW50ZWdlciB2YWx1ZSkuXG4gICAgICAgICAqL1xuICAgICAgICBFbmNvZGVIaW50VHlwZVtFbmNvZGVIaW50VHlwZVtcIlFSX1ZFUlNJT05cIl0gPSAxMF0gPSBcIlFSX1ZFUlNJT05cIjtcbiAgICB9KShFbmNvZGVIaW50VHlwZSB8fCAoRW5jb2RlSGludFR5cGUgPSB7fSkpO1xuICAgIHZhciBFbmNvZGVIaW50VHlwZSQxID0gRW5jb2RlSGludFR5cGU7XG5cbiAgICAvKipcbiAgICAgKiA8cD5JbXBsZW1lbnRzIFJlZWQtU29sb21vbiBlbmNvZGluZywgYXMgdGhlIG5hbWUgaW1wbGllcy48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqIEBhdXRob3IgV2lsbGlhbSBSdWNrbGlkZ2VcbiAgICAgKi9cbiAgICBjbGFzcyBSZWVkU29sb21vbkVuY29kZXIge1xuICAgICAgICAvKipcbiAgICAgICAgICogQSByZWVkIHNvbG9tb24gZXJyb3ItY29ycmVjdGluZyBlbmNvZGluZyBjb25zdHJ1Y3RvciBpcyBjcmVhdGVkIGJ5XG4gICAgICAgICAqIHBhc3NpbmcgYXMgR2Fsb2lzIEZpZWxkIHdpdGggb2Ygc2l6ZSBlcXVhbCB0byB0aGUgbnVtYmVyIG9mIGNvZGVcbiAgICAgICAgICogd29yZHMgKHN5bWJvbHMpIGluIHRoZSBhbHBoYWJldCAodGhlIG51bWJlciBvZiB2YWx1ZXMgaW4gZWFjaFxuICAgICAgICAgKiBlbGVtZW50IG9mIGFycmF5cyB0aGF0IGFyZSBlbmNvZGVkL2RlY29kZWQpLlxuICAgICAgICAgKiBAcGFyYW0gZmllbGQgQSBnYWxvaXMgZmllbGQgd2l0aCBhIG51bWJlciBvZiBlbGVtZW50cyBlcXVhbCB0byB0aGUgc2l6ZVxuICAgICAgICAgKiBvZiB0aGUgYWxwaGFiZXQgb2Ygc3ltYm9scyB0byBlbmNvZGUuXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3RvcihmaWVsZCkge1xuICAgICAgICAgICAgdGhpcy5maWVsZCA9IGZpZWxkO1xuICAgICAgICAgICAgdGhpcy5jYWNoZWRHZW5lcmF0b3JzID0gW107XG4gICAgICAgICAgICB0aGlzLmNhY2hlZEdlbmVyYXRvcnMucHVzaChuZXcgR2VuZXJpY0dGUG9seShmaWVsZCwgSW50MzJBcnJheS5mcm9tKFsxXSkpKTtcbiAgICAgICAgfVxuICAgICAgICBidWlsZEdlbmVyYXRvcihkZWdyZWUgLyppbnQqLykge1xuICAgICAgICAgICAgY29uc3QgY2FjaGVkR2VuZXJhdG9ycyA9IHRoaXMuY2FjaGVkR2VuZXJhdG9ycztcbiAgICAgICAgICAgIGlmIChkZWdyZWUgPj0gY2FjaGVkR2VuZXJhdG9ycy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBsZXQgbGFzdEdlbmVyYXRvciA9IGNhY2hlZEdlbmVyYXRvcnNbY2FjaGVkR2VuZXJhdG9ycy5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgICAgICBjb25zdCBmaWVsZCA9IHRoaXMuZmllbGQ7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgZCA9IGNhY2hlZEdlbmVyYXRvcnMubGVuZ3RoOyBkIDw9IGRlZ3JlZTsgZCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5leHRHZW5lcmF0b3IgPSBsYXN0R2VuZXJhdG9yLm11bHRpcGx5KG5ldyBHZW5lcmljR0ZQb2x5KGZpZWxkLCBJbnQzMkFycmF5LmZyb20oWzEsIGZpZWxkLmV4cChkIC0gMSArIGZpZWxkLmdldEdlbmVyYXRvckJhc2UoKSldKSkpO1xuICAgICAgICAgICAgICAgICAgICBjYWNoZWRHZW5lcmF0b3JzLnB1c2gobmV4dEdlbmVyYXRvcik7XG4gICAgICAgICAgICAgICAgICAgIGxhc3RHZW5lcmF0b3IgPSBuZXh0R2VuZXJhdG9yO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRHZW5lcmF0b3JzW2RlZ3JlZV07XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkVuY29kZSBhIHNlcXVlbmNlIG9mIGNvZGUgd29yZHMgKHN5bWJvbHMpIHVzaW5nIFJlZWQtU29sb21vbiB0byBhbGxvdyBkZWNvZGVyc1xuICAgICAgICAgKiB0byBkZXRlY3QgYW5kIGNvcnJlY3QgZXJyb3JzIHRoYXQgbWF5IGhhdmUgYmVlbiBpbnRyb2R1Y2VkIHdoZW4gdGhlIHJlc3VsdGluZ1xuICAgICAgICAgKiBkYXRhIGlzIHN0b3JlZCBvciB0cmFuc21pdHRlZC48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB0b0VuY29kZSBhcnJheSB1c2VkIGZvciBib3RoIGFuZCBvdXRwdXQuIENhbGxlciBpbml0aWFsaXplcyB0aGUgYXJyYXkgd2l0aFxuICAgICAgICAgKiB0aGUgY29kZSB3b3JkcyAoc3ltYm9scykgdG8gYmUgZW5jb2RlZCBmb2xsb3dlZCBieSBlbXB0eSBlbGVtZW50cyBhbGxvY2F0ZWQgdG8gbWFrZVxuICAgICAgICAgKiBzcGFjZSBmb3IgZXJyb3ItY29ycmVjdGlvbiBjb2RlIHdvcmRzIGluIHRoZSBlbmNvZGVkIG91dHB1dC4gVGhlIGFycmF5IGNvbnRhaW5zXG4gICAgICAgICAqIHRoZSBlbmNkb2RlZCBvdXRwdXQgd2hlbiBlbmNvZGUgcmV0dXJucy4gQ29kZSB3b3JkcyBhcmUgZW5jb2RlZCBhcyBudW1iZXJzIGZyb21cbiAgICAgICAgICogMCB0byBuLTEsIHdoZXJlIG4gaXMgdGhlIG51bWJlciBvZiBwb3NzaWJsZSBjb2RlIHdvcmRzIChzeW1ib2xzKSwgYXMgZGV0ZXJtaW5lZFxuICAgICAgICAgKiBieSB0aGUgc2l6ZSBvZiB0aGUgR2Fsb2lzIEZpZWxkIHBhc3NlZCBpbiB0aGUgY29uc3RydWN0b3Igb2YgdGhpcyBvYmplY3QuXG4gICAgICAgICAqIEBwYXJhbSBlY0J5dGVzIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgcmVzZXJ2ZWQgaW4gdGhlIGFycmF5IChmaXJzdCBwYXJhbWV0ZXIpXG4gICAgICAgICAqIHRvIHN0b3JlIGVycm9yLWNvcnJlY3Rpb24gY29kZSB3b3Jkcy4gVGh1cywgdGhlIG51bWJlciBvZiBjb2RlIHdvcmRzIChzeW1ib2xzKVxuICAgICAgICAgKiB0byBlbmNvZGUgaW4gdGhlIGZpcnN0IHBhcmFtZXRlciBpcyB0aHVzIHRvRW5jb2RlLmxlbmd0aCAtIGVjQnl0ZXMuXG4gICAgICAgICAqIE5vdGUsIHRoZSB1c2Ugb2YgXCJieXRlc1wiIGluIHRoZSBuYW1lIG9mIHRoaXMgcGFyYW1ldGVyIGlzIG1pc2xlYWRpbmcsIGFzIHRoZXJlIG1heVxuICAgICAgICAgKiBiZSBtb3JlIG9yIGZld2VyIHRoYW4gMjU2IHN5bWJvbHMgYmVpbmcgZW5jb2RlZCwgYXMgZGV0ZXJtaW5lZCBieSB0aGUgbnVtYmVyIG9mXG4gICAgICAgICAqIGVsZW1lbnRzIGluIHRoZSBHYWxvaXMgRmllbGQgcGFzc2VkIGFzIGEgY29uc3RydWN0b3IgdG8gdGhpcyBvYmplY3QuXG4gICAgICAgICAqIEB0aHJvd3MgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uIHRocm93biBpbiByZXNwb25zZSB0byB2YWxpZGF0aW9uIGVycnJvcy5cbiAgICAgICAgICovXG4gICAgICAgIGVuY29kZSh0b0VuY29kZSwgZWNCeXRlcyAvKmludCovKSB7XG4gICAgICAgICAgICBpZiAoZWNCeXRlcyA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ05vIGVycm9yIGNvcnJlY3Rpb24gYnl0ZXMnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGRhdGFCeXRlcyA9IHRvRW5jb2RlLmxlbmd0aCAtIGVjQnl0ZXM7XG4gICAgICAgICAgICBpZiAoZGF0YUJ5dGVzIDw9IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdObyBkYXRhIGJ5dGVzIHByb3ZpZGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBnZW5lcmF0b3IgPSB0aGlzLmJ1aWxkR2VuZXJhdG9yKGVjQnl0ZXMpO1xuICAgICAgICAgICAgY29uc3QgaW5mb0NvZWZmaWNpZW50cyA9IG5ldyBJbnQzMkFycmF5KGRhdGFCeXRlcyk7XG4gICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KHRvRW5jb2RlLCAwLCBpbmZvQ29lZmZpY2llbnRzLCAwLCBkYXRhQnl0ZXMpO1xuICAgICAgICAgICAgbGV0IGluZm8gPSBuZXcgR2VuZXJpY0dGUG9seSh0aGlzLmZpZWxkLCBpbmZvQ29lZmZpY2llbnRzKTtcbiAgICAgICAgICAgIGluZm8gPSBpbmZvLm11bHRpcGx5QnlNb25vbWlhbChlY0J5dGVzLCAxKTtcbiAgICAgICAgICAgIGNvbnN0IHJlbWFpbmRlciA9IGluZm8uZGl2aWRlKGdlbmVyYXRvcilbMV07XG4gICAgICAgICAgICBjb25zdCBjb2VmZmljaWVudHMgPSByZW1haW5kZXIuZ2V0Q29lZmZpY2llbnRzKCk7XG4gICAgICAgICAgICBjb25zdCBudW1aZXJvQ29lZmZpY2llbnRzID0gZWNCeXRlcyAtIGNvZWZmaWNpZW50cy5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bVplcm9Db2VmZmljaWVudHM7IGkrKykge1xuICAgICAgICAgICAgICAgIHRvRW5jb2RlW2RhdGFCeXRlcyArIGldID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkoY29lZmZpY2llbnRzLCAwLCB0b0VuY29kZSwgZGF0YUJ5dGVzICsgbnVtWmVyb0NvZWZmaWNpZW50cywgY29lZmZpY2llbnRzLmxlbmd0aCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAYXV0aG9yIFNhdG9ydSBUYWthYmF5YXNoaVxuICAgICAqIEBhdXRob3IgRGFuaWVsIFN3aXRraW5cbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIE1hc2tVdGlsIHtcbiAgICAgICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgICAgICAvLyBkbyBub3RoaW5nXG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEFwcGx5IG1hc2sgcGVuYWx0eSBydWxlIDEgYW5kIHJldHVybiB0aGUgcGVuYWx0eS4gRmluZCByZXBldGl0aXZlIGNlbGxzIHdpdGggdGhlIHNhbWUgY29sb3IgYW5kXG4gICAgICAgICAqIGdpdmUgcGVuYWx0eSB0byB0aGVtLiBFeGFtcGxlOiAwMDAwMCBvciAxMTExMS5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBhcHBseU1hc2tQZW5hbHR5UnVsZTEobWF0cml4KSB7XG4gICAgICAgICAgICByZXR1cm4gTWFza1V0aWwuYXBwbHlNYXNrUGVuYWx0eVJ1bGUxSW50ZXJuYWwobWF0cml4LCB0cnVlKSArIE1hc2tVdGlsLmFwcGx5TWFza1BlbmFsdHlSdWxlMUludGVybmFsKG1hdHJpeCwgZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBcHBseSBtYXNrIHBlbmFsdHkgcnVsZSAyIGFuZCByZXR1cm4gdGhlIHBlbmFsdHkuIEZpbmQgMngyIGJsb2NrcyB3aXRoIHRoZSBzYW1lIGNvbG9yIGFuZCBnaXZlXG4gICAgICAgICAqIHBlbmFsdHkgdG8gdGhlbS4gVGhpcyBpcyBhY3R1YWxseSBlcXVpdmFsZW50IHRvIHRoZSBzcGVjJ3MgcnVsZSwgd2hpY2ggaXMgdG8gZmluZCBNeE4gYmxvY2tzIGFuZCBnaXZlIGFcbiAgICAgICAgICogcGVuYWx0eSBwcm9wb3J0aW9uYWwgdG8gKE0tMSl4KE4tMSksIGJlY2F1c2UgdGhpcyBpcyB0aGUgbnVtYmVyIG9mIDJ4MiBibG9ja3MgaW5zaWRlIHN1Y2ggYSBibG9jay5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBhcHBseU1hc2tQZW5hbHR5UnVsZTIobWF0cml4KSB7XG4gICAgICAgICAgICBsZXQgcGVuYWx0eSA9IDA7XG4gICAgICAgICAgICBjb25zdCBhcnJheSA9IG1hdHJpeC5nZXRBcnJheSgpO1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBtYXRyaXguZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IG1hdHJpeC5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgaGVpZ2h0IC0gMTsgeSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYXJyYXlZID0gYXJyYXlbeV07XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCB3aWR0aCAtIDE7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IGFycmF5WVt4XTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlID09PSBhcnJheVlbeCArIDFdICYmIHZhbHVlID09PSBhcnJheVt5ICsgMV1beF0gJiYgdmFsdWUgPT09IGFycmF5W3kgKyAxXVt4ICsgMV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBlbmFsdHkrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBNYXNrVXRpbC5OMiAqIHBlbmFsdHk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEFwcGx5IG1hc2sgcGVuYWx0eSBydWxlIDMgYW5kIHJldHVybiB0aGUgcGVuYWx0eS4gRmluZCBjb25zZWN1dGl2ZSBydW5zIG9mIDE6MTozOjE6MTo0XG4gICAgICAgICAqIHN0YXJ0aW5nIHdpdGggYmxhY2ssIG9yIDQ6MToxOjM6MToxIHN0YXJ0aW5nIHdpdGggd2hpdGUsIGFuZCBnaXZlIHBlbmFsdHkgdG8gdGhlbS4gIElmIHdlXG4gICAgICAgICAqIGZpbmQgcGF0dGVybnMgbGlrZSAwMDAwMTAxMTEwMTAwMDAsIHdlIGdpdmUgcGVuYWx0eSBvbmNlLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGFwcGx5TWFza1BlbmFsdHlSdWxlMyhtYXRyaXgpIHtcbiAgICAgICAgICAgIGxldCBudW1QZW5hbHRpZXMgPSAwO1xuICAgICAgICAgICAgY29uc3QgYXJyYXkgPSBtYXRyaXguZ2V0QXJyYXkoKTtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gbWF0cml4LmdldFdpZHRoKCk7XG4gICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBtYXRyaXguZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGFycmF5WSA9IGFycmF5W3ldOyAvLyBXZSBjYW4gYXQgbGVhc3Qgb3B0aW1pemUgdGhpcyBhY2Nlc3NcbiAgICAgICAgICAgICAgICAgICAgaWYgKHggKyA2IDwgd2lkdGggJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5WVt4XSA9PT0gMSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXlZW3ggKyAxXSA9PT0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXlZW3ggKyAyXSA9PT0gMSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXlZW3ggKyAzXSA9PT0gMSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXlZW3ggKyA0XSA9PT0gMSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXlZW3ggKyA1XSA9PT0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXlZW3ggKyA2XSA9PT0gMSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKE1hc2tVdGlsLmlzV2hpdGVIb3Jpem9udGFsKGFycmF5WSwgeCAtIDQsIHgpIHx8IE1hc2tVdGlsLmlzV2hpdGVIb3Jpem9udGFsKGFycmF5WSwgeCArIDcsIHggKyAxMSkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBudW1QZW5hbHRpZXMrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoeSArIDYgPCBoZWlnaHQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5W3ldW3hdID09PSAxICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBhcnJheVt5ICsgMV1beF0gPT09IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5W3kgKyAyXVt4XSA9PT0gMSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXlbeSArIDNdW3hdID09PSAxICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBhcnJheVt5ICsgNF1beF0gPT09IDEgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5W3kgKyA1XVt4XSA9PT0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXlbeSArIDZdW3hdID09PSAxICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoTWFza1V0aWwuaXNXaGl0ZVZlcnRpY2FsKGFycmF5LCB4LCB5IC0gNCwgeSkgfHwgTWFza1V0aWwuaXNXaGl0ZVZlcnRpY2FsKGFycmF5LCB4LCB5ICsgNywgeSArIDExKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG51bVBlbmFsdGllcysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bVBlbmFsdGllcyAqIE1hc2tVdGlsLk4zO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBpc1doaXRlSG9yaXpvbnRhbChyb3dBcnJheSwgZnJvbSAvKmludCovLCB0byAvKmludCovKSB7XG4gICAgICAgICAgICBmcm9tID0gTWF0aC5tYXgoZnJvbSwgMCk7XG4gICAgICAgICAgICB0byA9IE1hdGgubWluKHRvLCByb3dBcnJheS5sZW5ndGgpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGZyb207IGkgPCB0bzsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJvd0FycmF5W2ldID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgaXNXaGl0ZVZlcnRpY2FsKGFycmF5LCBjb2wgLyppbnQqLywgZnJvbSAvKmludCovLCB0byAvKmludCovKSB7XG4gICAgICAgICAgICBmcm9tID0gTWF0aC5tYXgoZnJvbSwgMCk7XG4gICAgICAgICAgICB0byA9IE1hdGgubWluKHRvLCBhcnJheS5sZW5ndGgpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGZyb207IGkgPCB0bzsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFycmF5W2ldW2NvbF0gPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBcHBseSBtYXNrIHBlbmFsdHkgcnVsZSA0IGFuZCByZXR1cm4gdGhlIHBlbmFsdHkuIENhbGN1bGF0ZSB0aGUgcmF0aW8gb2YgZGFyayBjZWxscyBhbmQgZ2l2ZVxuICAgICAgICAgKiBwZW5hbHR5IGlmIHRoZSByYXRpbyBpcyBmYXIgZnJvbSA1MCUuIEl0IGdpdmVzIDEwIHBlbmFsdHkgZm9yIDUlIGRpc3RhbmNlLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGFwcGx5TWFza1BlbmFsdHlSdWxlNChtYXRyaXgpIHtcbiAgICAgICAgICAgIGxldCBudW1EYXJrQ2VsbHMgPSAwO1xuICAgICAgICAgICAgY29uc3QgYXJyYXkgPSBtYXRyaXguZ2V0QXJyYXkoKTtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gbWF0cml4LmdldFdpZHRoKCk7XG4gICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBtYXRyaXguZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYXJyYXlZID0gYXJyYXlbeV07XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhcnJheVlbeF0gPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG51bURhcmtDZWxscysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbnVtVG90YWxDZWxscyA9IG1hdHJpeC5nZXRIZWlnaHQoKSAqIG1hdHJpeC5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgY29uc3QgZml2ZVBlcmNlbnRWYXJpYW5jZXMgPSBNYXRoLmZsb29yKE1hdGguYWJzKG51bURhcmtDZWxscyAqIDIgLSBudW1Ub3RhbENlbGxzKSAqIDEwIC8gbnVtVG90YWxDZWxscyk7XG4gICAgICAgICAgICByZXR1cm4gZml2ZVBlcmNlbnRWYXJpYW5jZXMgKiBNYXNrVXRpbC5ONDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogUmV0dXJuIHRoZSBtYXNrIGJpdCBmb3IgXCJnZXRNYXNrUGF0dGVyblwiIGF0IFwieFwiIGFuZCBcInlcIi4gU2VlIDguOCBvZiBKSVNYMDUxMDoyMDA0IGZvciBtYXNrXG4gICAgICAgICAqIHBhdHRlcm4gY29uZGl0aW9ucy5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBnZXREYXRhTWFza0JpdChtYXNrUGF0dGVybiAvKmludCovLCB4IC8qaW50Ki8sIHkgLyppbnQqLykge1xuICAgICAgICAgICAgbGV0IGludGVybWVkaWF0ZTsgLyppbnQqL1xuICAgICAgICAgICAgbGV0IHRlbXA7IC8qaW50Ki9cbiAgICAgICAgICAgIHN3aXRjaCAobWFza1BhdHRlcm4pIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIGludGVybWVkaWF0ZSA9ICh5ICsgeCkgJiAweDE7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJtZWRpYXRlID0geSAmIDB4MTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBpbnRlcm1lZGlhdGUgPSB4ICUgMztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICBpbnRlcm1lZGlhdGUgPSAoeSArIHgpICUgMztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICBpbnRlcm1lZGlhdGUgPSAoTWF0aC5mbG9vcih5IC8gMikgKyBNYXRoLmZsb29yKHggLyAzKSkgJiAweDE7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgdGVtcCA9IHkgKiB4O1xuICAgICAgICAgICAgICAgICAgICBpbnRlcm1lZGlhdGUgPSAodGVtcCAmIDB4MSkgKyAodGVtcCAlIDMpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHRlbXAgPSB5ICogeDtcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJtZWRpYXRlID0gKCh0ZW1wICYgMHgxKSArICh0ZW1wICUgMykpICYgMHgxO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDc6XG4gICAgICAgICAgICAgICAgICAgIHRlbXAgPSB5ICogeDtcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJtZWRpYXRlID0gKCh0ZW1wICUgMykgKyAoKHkgKyB4KSAmIDB4MSkpICYgMHgxO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdJbnZhbGlkIG1hc2sgcGF0dGVybjogJyArIG1hc2tQYXR0ZXJuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBpbnRlcm1lZGlhdGUgPT09IDA7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEhlbHBlciBmdW5jdGlvbiBmb3IgYXBwbHlNYXNrUGVuYWx0eVJ1bGUxLiBXZSBuZWVkIHRoaXMgZm9yIGRvaW5nIHRoaXMgY2FsY3VsYXRpb24gaW4gYm90aFxuICAgICAgICAgKiB2ZXJ0aWNhbCBhbmQgaG9yaXpvbnRhbCBvcmRlcnMgcmVzcGVjdGl2ZWx5LlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGFwcGx5TWFza1BlbmFsdHlSdWxlMUludGVybmFsKG1hdHJpeCwgaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICBsZXQgcGVuYWx0eSA9IDA7XG4gICAgICAgICAgICBjb25zdCBpTGltaXQgPSBpc0hvcml6b250YWwgPyBtYXRyaXguZ2V0SGVpZ2h0KCkgOiBtYXRyaXguZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGNvbnN0IGpMaW1pdCA9IGlzSG9yaXpvbnRhbCA/IG1hdHJpeC5nZXRXaWR0aCgpIDogbWF0cml4LmdldEhlaWdodCgpO1xuICAgICAgICAgICAgY29uc3QgYXJyYXkgPSBtYXRyaXguZ2V0QXJyYXkoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaUxpbWl0OyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgbnVtU2FtZUJpdENlbGxzID0gMDtcbiAgICAgICAgICAgICAgICBsZXQgcHJldkJpdCA9IC0xO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgakxpbWl0OyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYml0ID0gaXNIb3Jpem9udGFsID8gYXJyYXlbaV1bal0gOiBhcnJheVtqXVtpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGJpdCA9PT0gcHJldkJpdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbnVtU2FtZUJpdENlbGxzKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobnVtU2FtZUJpdENlbGxzID49IDUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZW5hbHR5ICs9IE1hc2tVdGlsLk4xICsgKG51bVNhbWVCaXRDZWxscyAtIDUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgbnVtU2FtZUJpdENlbGxzID0gMTsgLy8gSW5jbHVkZSB0aGUgY2VsbCBpdHNlbGYuXG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2Qml0ID0gYml0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChudW1TYW1lQml0Q2VsbHMgPj0gNSkge1xuICAgICAgICAgICAgICAgICAgICBwZW5hbHR5ICs9IE1hc2tVdGlsLk4xICsgKG51bVNhbWVCaXRDZWxscyAtIDUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBwZW5hbHR5O1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIFBlbmFsdHkgd2VpZ2h0cyBmcm9tIHNlY3Rpb24gNi44LjIuMVxuICAgIE1hc2tVdGlsLk4xID0gMztcbiAgICBNYXNrVXRpbC5OMiA9IDM7XG4gICAgTWFza1V0aWwuTjMgPSA0MDtcbiAgICBNYXNrVXRpbC5ONCA9IDEwO1xuXG4gICAgLyoqXG4gICAgICogSkFWQVBPUlQ6IFRoZSBvcmlnaW5hbCBjb2RlIHdhcyBhIDJEIGFycmF5IG9mIGludHMsIGJ1dCBzaW5jZSBpdCBvbmx5IGV2ZXIgZ2V0cyBhc3NpZ25lZFxuICAgICAqIC0xLCAwLCBhbmQgMSwgSSdtIGdvaW5nIHRvIHVzZSBsZXNzIG1lbW9yeSBhbmQgZ28gd2l0aCBieXRlcy5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pXG4gICAgICovXG4gICAgY2xhc3MgQnl0ZU1hdHJpeCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHdpZHRoIC8qaW50Ki8sIGhlaWdodCAvKmludCovKSB7XG4gICAgICAgICAgICB0aGlzLndpZHRoID0gd2lkdGg7XG4gICAgICAgICAgICB0aGlzLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgICAgIGNvbnN0IGJ5dGVzID0gbmV3IEFycmF5KGhlaWdodCk7IC8vIFtoZWlnaHRdW3dpZHRoXVxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgIT09IGhlaWdodDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgYnl0ZXNbaV0gPSBuZXcgVWludDhBcnJheSh3aWR0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmJ5dGVzID0gYnl0ZXM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0SGVpZ2h0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaGVpZ2h0O1xuICAgICAgICB9XG4gICAgICAgIGdldFdpZHRoKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lkdGg7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0KHggLyppbnQqLywgeSAvKmludCovKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ieXRlc1t5XVt4XTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBhbiBpbnRlcm5hbCByZXByZXNlbnRhdGlvbiBhcyBieXRlcywgaW4gcm93LW1ham9yIG9yZGVyLiBhcnJheVt5XVt4XSByZXByZXNlbnRzIHBvaW50ICh4LHkpXG4gICAgICAgICAqL1xuICAgICAgICBnZXRBcnJheSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJ5dGVzO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRZUEVTQ1JJUFRQT1JUOiBwcmVmZmVyIHRvIGxldCB0d28gbWV0aG9kcyBpbnN0ZWFkIG9mIG92ZXJyaWRlIHRvIGF2b2lkIHR5cGUgY29tcGFyaXNvbiBpbnNpZGVcbiAgICAgICAgc2V0TnVtYmVyKHggLyppbnQqLywgeSAvKmludCovLCB2YWx1ZSAvKmJ5dGV8aW50Ki8pIHtcbiAgICAgICAgICAgIHRoaXMuYnl0ZXNbeV1beF0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBwdWJsaWMgc2V0KHg6IG51bWJlciAvKmludCovLCB5OiBudW1iZXIgLyppbnQqLywgdmFsdWU6IG51bWJlciAvKmludCovKTogdm9pZCB7XG4gICAgICAgIC8vICAgYnl0ZXNbeV1beF0gPSAoYnl0ZSkgdmFsdWVcbiAgICAgICAgLy8gfVxuICAgICAgICBzZXRCb29sZWFuKHggLyppbnQqLywgeSAvKmludCovLCB2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5ieXRlc1t5XVt4XSA9IC8qKGJ5dGUpICovICh2YWx1ZSA/IDEgOiAwKTtcbiAgICAgICAgfVxuICAgICAgICBjbGVhcih2YWx1ZSAvKmJ5dGUqLykge1xuICAgICAgICAgICAgZm9yIChjb25zdCBhQnl0ZSBvZiB0aGlzLmJ5dGVzKSB7XG4gICAgICAgICAgICAgICAgQXJyYXlzLmZpbGwoYUJ5dGUsIHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlcXVhbHMobykge1xuICAgICAgICAgICAgaWYgKCEobyBpbnN0YW5jZW9mIEJ5dGVNYXRyaXgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgb3RoZXIgPSBvO1xuICAgICAgICAgICAgaWYgKHRoaXMud2lkdGggIT09IG90aGVyLndpZHRoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaGVpZ2h0ICE9PSBvdGhlci5oZWlnaHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMCwgaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7IHkgPCBoZWlnaHQ7ICsreSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGJ5dGVzWSA9IHRoaXMuYnl0ZXNbeV07XG4gICAgICAgICAgICAgICAgY29uc3Qgb3RoZXJCeXRlc1kgPSBvdGhlci5ieXRlc1t5XTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB4ID0gMCwgd2lkdGggPSB0aGlzLndpZHRoOyB4IDwgd2lkdGg7ICsreCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoYnl0ZXNZW3hdICE9PSBvdGhlckJ5dGVzWVt4XSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICB0b1N0cmluZygpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7IC8vICgyICogd2lkdGggKiBoZWlnaHQgKyAyKVxuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDAsIGhlaWdodCA9IHRoaXMuaGVpZ2h0OyB5IDwgaGVpZ2h0OyArK3kpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBieXRlc1kgPSB0aGlzLmJ5dGVzW3ldO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAwLCB3aWR0aCA9IHRoaXMud2lkdGg7IHggPCB3aWR0aDsgKyt4KSB7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoYnl0ZXNZW3hdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnIDAnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCcgMScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCcgICcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoJ1xcbicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC50b1N0cmluZygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGF1dGhvciBzYXRvcnV4QGdvb2dsZS5jb20gKFNhdG9ydSBUYWthYmF5YXNoaSkgLSBjcmVhdG9yXG4gICAgICogQGF1dGhvciBkc3dpdGtpbkBnb29nbGUuY29tIChEYW5pZWwgU3dpdGtpbikgLSBwb3J0ZWQgZnJvbSBDKytcbiAgICAgKi9cbiAgICBjbGFzcyBRUkNvZGUge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICAgIHRoaXMubWFza1BhdHRlcm4gPSAtMTtcbiAgICAgICAgfVxuICAgICAgICBnZXRNb2RlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubW9kZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRFQ0xldmVsKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWNMZXZlbDtcbiAgICAgICAgfVxuICAgICAgICBnZXRWZXJzaW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmVyc2lvbjtcbiAgICAgICAgfVxuICAgICAgICBnZXRNYXNrUGF0dGVybigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1hc2tQYXR0ZXJuO1xuICAgICAgICB9XG4gICAgICAgIGdldE1hdHJpeCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1hdHJpeDtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IFN0cmluZ0J1aWxkZXIoKTsgLy8gKDIwMClcbiAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoJzw8XFxuJyk7XG4gICAgICAgICAgICByZXN1bHQuYXBwZW5kKCcgbW9kZTogJyk7XG4gICAgICAgICAgICByZXN1bHQuYXBwZW5kKHRoaXMubW9kZSA/IHRoaXMubW9kZS50b1N0cmluZygpIDogJ251bGwnKTtcbiAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoJ1xcbiBlY0xldmVsOiAnKTtcbiAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQodGhpcy5lY0xldmVsID8gdGhpcy5lY0xldmVsLnRvU3RyaW5nKCkgOiAnbnVsbCcpO1xuICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnXFxuIHZlcnNpb246ICcpO1xuICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCh0aGlzLnZlcnNpb24gPyB0aGlzLnZlcnNpb24udG9TdHJpbmcoKSA6ICdudWxsJyk7XG4gICAgICAgICAgICByZXN1bHQuYXBwZW5kKCdcXG4gbWFza1BhdHRlcm46ICcpO1xuICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCh0aGlzLm1hc2tQYXR0ZXJuLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgaWYgKHRoaXMubWF0cml4KSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnXFxuIG1hdHJpeDpcXG4nKTtcbiAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKHRoaXMubWF0cml4LnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnXFxuIG1hdHJpeDogbnVsbFxcbicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnPj5cXG4nKTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgICAgICBzZXRNb2RlKHZhbHVlKSB7XG4gICAgICAgICAgICB0aGlzLm1vZGUgPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBzZXRFQ0xldmVsKHZhbHVlKSB7XG4gICAgICAgICAgICB0aGlzLmVjTGV2ZWwgPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBzZXRWZXJzaW9uKHZlcnNpb24pIHtcbiAgICAgICAgICAgIHRoaXMudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgIH1cbiAgICAgICAgc2V0TWFza1BhdHRlcm4odmFsdWUgLyppbnQqLykge1xuICAgICAgICAgICAgdGhpcy5tYXNrUGF0dGVybiA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHNldE1hdHJpeCh2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5tYXRyaXggPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBDaGVjayBpZiBcIm1hc2tfcGF0dGVyblwiIGlzIHZhbGlkLlxuICAgICAgICBzdGF0aWMgaXNWYWxpZE1hc2tQYXR0ZXJuKG1hc2tQYXR0ZXJuIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHJldHVybiBtYXNrUGF0dGVybiA+PSAwICYmIG1hc2tQYXR0ZXJuIDwgUVJDb2RlLk5VTV9NQVNLX1BBVFRFUk5TO1xuICAgICAgICB9XG4gICAgfVxuICAgIFFSQ29kZS5OVU1fTUFTS19QQVRURVJOUyA9IDg7XG5cbiAgICAvKipcbiAgICAgKiBDdXN0b20gRXJyb3IgY2xhc3Mgb2YgdHlwZSBFeGNlcHRpb24uXG4gICAgICovXG4gICAgY2xhc3MgV3JpdGVyRXhjZXB0aW9uIGV4dGVuZHMgRXhjZXB0aW9uIHtcbiAgICB9XG4gICAgV3JpdGVyRXhjZXB0aW9uLmtpbmQgPSAnV3JpdGVyRXhjZXB0aW9uJztcblxuICAgIC8qKlxuICAgICAqIEBhdXRob3Igc2F0b3J1eEBnb29nbGUuY29tIChTYXRvcnUgVGFrYWJheWFzaGkpIC0gY3JlYXRvclxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pIC0gcG9ydGVkIGZyb20gQysrXG4gICAgICovXG4gICAgY2xhc3MgTWF0cml4VXRpbCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgLy8gZG8gbm90aGluZ1xuICAgICAgICB9XG4gICAgICAgIC8vIFNldCBhbGwgY2VsbHMgdG8gLTEgKFRZUEVTQ1JJUFRQT1JUOiAyNTUpLiAgLTEgKFRZUEVTQ1JJUFRQT1JUOiAyNTUpIG1lYW5zIHRoYXQgdGhlIGNlbGwgaXMgZW1wdHkgKG5vdCBzZXQgeWV0KS5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gSkFWQVBPUlQ6IFdlIHNob3VsZG4ndCBuZWVkIHRvIGRvIHRoaXMgYXQgYWxsLiBUaGUgY29kZSBzaG91bGQgYmUgcmV3cml0dGVuIHRvIGJlZ2luIGVuY29kaW5nXG4gICAgICAgIC8vIHdpdGggdGhlIEJ5dGVNYXRyaXggaW5pdGlhbGl6ZWQgYWxsIHRvIHplcm8uXG4gICAgICAgIHN0YXRpYyBjbGVhck1hdHJpeChtYXRyaXgpIHtcbiAgICAgICAgICAgIC8vIFRZUEVTQ1JJUFRQT1JUOiB3ZSB1c2UgVWludEFycmF5IHNlIGNoYW5nZWQgaGVyZSBmcm9tIC0xIHRvIDI1NVxuICAgICAgICAgICAgbWF0cml4LmNsZWFyKC8qKGJ5dGUpICovIC8qLTEqLyAyNTUpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEJ1aWxkIDJEIG1hdHJpeCBvZiBRUiBDb2RlIGZyb20gXCJkYXRhQml0c1wiIHdpdGggXCJlY0xldmVsXCIsIFwidmVyc2lvblwiIGFuZCBcImdldE1hc2tQYXR0ZXJuXCIuIE9uXG4gICAgICAgIC8vIHN1Y2Nlc3MsIHN0b3JlIHRoZSByZXN1bHQgaW4gXCJtYXRyaXhcIiBhbmQgcmV0dXJuIHRydWUuXG4gICAgICAgIHN0YXRpYyBidWlsZE1hdHJpeChkYXRhQml0cywgZWNMZXZlbCwgdmVyc2lvbiwgbWFza1BhdHRlcm4gLyppbnQqLywgbWF0cml4KSB7XG4gICAgICAgICAgICBNYXRyaXhVdGlsLmNsZWFyTWF0cml4KG1hdHJpeCk7XG4gICAgICAgICAgICBNYXRyaXhVdGlsLmVtYmVkQmFzaWNQYXR0ZXJucyh2ZXJzaW9uLCBtYXRyaXgpO1xuICAgICAgICAgICAgLy8gVHlwZSBpbmZvcm1hdGlvbiBhcHBlYXIgd2l0aCBhbnkgdmVyc2lvbi5cbiAgICAgICAgICAgIE1hdHJpeFV0aWwuZW1iZWRUeXBlSW5mbyhlY0xldmVsLCBtYXNrUGF0dGVybiwgbWF0cml4KTtcbiAgICAgICAgICAgIC8vIFZlcnNpb24gaW5mbyBhcHBlYXIgaWYgdmVyc2lvbiA+PSA3LlxuICAgICAgICAgICAgTWF0cml4VXRpbC5tYXliZUVtYmVkVmVyc2lvbkluZm8odmVyc2lvbiwgbWF0cml4KTtcbiAgICAgICAgICAgIC8vIERhdGEgc2hvdWxkIGJlIGVtYmVkZGVkIGF0IGVuZC5cbiAgICAgICAgICAgIE1hdHJpeFV0aWwuZW1iZWREYXRhQml0cyhkYXRhQml0cywgbWFza1BhdHRlcm4sIG1hdHJpeCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRW1iZWQgYmFzaWMgcGF0dGVybnMuIE9uIHN1Y2Nlc3MsIG1vZGlmeSB0aGUgbWF0cml4IGFuZCByZXR1cm4gdHJ1ZS5cbiAgICAgICAgLy8gVGhlIGJhc2ljIHBhdHRlcm5zIGFyZTpcbiAgICAgICAgLy8gLSBQb3NpdGlvbiBkZXRlY3Rpb24gcGF0dGVybnNcbiAgICAgICAgLy8gLSBUaW1pbmcgcGF0dGVybnNcbiAgICAgICAgLy8gLSBEYXJrIGRvdCBhdCB0aGUgbGVmdCBib3R0b20gY29ybmVyXG4gICAgICAgIC8vIC0gUG9zaXRpb24gYWRqdXN0bWVudCBwYXR0ZXJucywgaWYgbmVlZCBiZVxuICAgICAgICBzdGF0aWMgZW1iZWRCYXNpY1BhdHRlcm5zKHZlcnNpb24sIG1hdHJpeCkge1xuICAgICAgICAgICAgLy8gTGV0J3MgZ2V0IHN0YXJ0ZWQgd2l0aCBlbWJlZGRpbmcgYmlnIHNxdWFyZXMgYXQgY29ybmVycy5cbiAgICAgICAgICAgIE1hdHJpeFV0aWwuZW1iZWRQb3NpdGlvbkRldGVjdGlvblBhdHRlcm5zQW5kU2VwYXJhdG9ycyhtYXRyaXgpO1xuICAgICAgICAgICAgLy8gVGhlbiwgZW1iZWQgdGhlIGRhcmsgZG90IGF0IHRoZSBsZWZ0IGJvdHRvbSBjb3JuZXIuXG4gICAgICAgICAgICBNYXRyaXhVdGlsLmVtYmVkRGFya0RvdEF0TGVmdEJvdHRvbUNvcm5lcihtYXRyaXgpO1xuICAgICAgICAgICAgLy8gUG9zaXRpb24gYWRqdXN0bWVudCBwYXR0ZXJucyBhcHBlYXIgaWYgdmVyc2lvbiA+PSAyLlxuICAgICAgICAgICAgTWF0cml4VXRpbC5tYXliZUVtYmVkUG9zaXRpb25BZGp1c3RtZW50UGF0dGVybnModmVyc2lvbiwgbWF0cml4KTtcbiAgICAgICAgICAgIC8vIFRpbWluZyBwYXR0ZXJucyBzaG91bGQgYmUgZW1iZWRkZWQgYWZ0ZXIgcG9zaXRpb24gYWRqLiBwYXR0ZXJucy5cbiAgICAgICAgICAgIE1hdHJpeFV0aWwuZW1iZWRUaW1pbmdQYXR0ZXJucyhtYXRyaXgpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEVtYmVkIHR5cGUgaW5mb3JtYXRpb24uIE9uIHN1Y2Nlc3MsIG1vZGlmeSB0aGUgbWF0cml4LlxuICAgICAgICBzdGF0aWMgZW1iZWRUeXBlSW5mbyhlY0xldmVsLCBtYXNrUGF0dGVybiAvKmludCovLCBtYXRyaXgpIHtcbiAgICAgICAgICAgIGNvbnN0IHR5cGVJbmZvQml0cyA9IG5ldyBCaXRBcnJheSgpO1xuICAgICAgICAgICAgTWF0cml4VXRpbC5tYWtlVHlwZUluZm9CaXRzKGVjTGV2ZWwsIG1hc2tQYXR0ZXJuLCB0eXBlSW5mb0JpdHMpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIHNpemUgPSB0eXBlSW5mb0JpdHMuZ2V0U2l6ZSgpOyBpIDwgc2l6ZTsgKytpKSB7XG4gICAgICAgICAgICAgICAgLy8gUGxhY2UgYml0cyBpbiBMU0IgdG8gTVNCIG9yZGVyLiAgTFNCIChsZWFzdCBzaWduaWZpY2FudCBiaXQpIGlzIHRoZSBsYXN0IHZhbHVlIGluXG4gICAgICAgICAgICAgICAgLy8gXCJ0eXBlSW5mb0JpdHNcIi5cbiAgICAgICAgICAgICAgICBjb25zdCBiaXQgPSB0eXBlSW5mb0JpdHMuZ2V0KHR5cGVJbmZvQml0cy5nZXRTaXplKCkgLSAxIC0gaSk7XG4gICAgICAgICAgICAgICAgLy8gVHlwZSBpbmZvIGJpdHMgYXQgdGhlIGxlZnQgdG9wIGNvcm5lci4gU2VlIDguOSBvZiBKSVNYMDUxMDoyMDA0IChwLjQ2KS5cbiAgICAgICAgICAgICAgICBjb25zdCBjb29yZGluYXRlcyA9IE1hdHJpeFV0aWwuVFlQRV9JTkZPX0NPT1JESU5BVEVTW2ldO1xuICAgICAgICAgICAgICAgIGNvbnN0IHgxID0gY29vcmRpbmF0ZXNbMF07XG4gICAgICAgICAgICAgICAgY29uc3QgeTEgPSBjb29yZGluYXRlc1sxXTtcbiAgICAgICAgICAgICAgICBtYXRyaXguc2V0Qm9vbGVhbih4MSwgeTEsIGJpdCk7XG4gICAgICAgICAgICAgICAgaWYgKGkgPCA4KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJpZ2h0IHRvcCBjb3JuZXIuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHgyID0gbWF0cml4LmdldFdpZHRoKCkgLSBpIC0gMTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgeTIgPSA4O1xuICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0Qm9vbGVhbih4MiwgeTIsIGJpdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBMZWZ0IGJvdHRvbSBjb3JuZXIuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHgyID0gODtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgeTIgPSBtYXRyaXguZ2V0SGVpZ2h0KCkgLSA3ICsgKGkgLSA4KTtcbiAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldEJvb2xlYW4oeDIsIHkyLCBiaXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBFbWJlZCB2ZXJzaW9uIGluZm9ybWF0aW9uIGlmIG5lZWQgYmUuIE9uIHN1Y2Nlc3MsIG1vZGlmeSB0aGUgbWF0cml4IGFuZCByZXR1cm4gdHJ1ZS5cbiAgICAgICAgLy8gU2VlIDguMTAgb2YgSklTWDA1MTA6MjAwNCAocC40NykgZm9yIGhvdyB0byBlbWJlZCB2ZXJzaW9uIGluZm9ybWF0aW9uLlxuICAgICAgICBzdGF0aWMgbWF5YmVFbWJlZFZlcnNpb25JbmZvKHZlcnNpb24sIG1hdHJpeCkge1xuICAgICAgICAgICAgaWYgKHZlcnNpb24uZ2V0VmVyc2lvbk51bWJlcigpIDwgNykgeyAvLyBWZXJzaW9uIGluZm8gaXMgbmVjZXNzYXJ5IGlmIHZlcnNpb24gPj0gNy5cbiAgICAgICAgICAgICAgICByZXR1cm47IC8vIERvbid0IG5lZWQgdmVyc2lvbiBpbmZvLlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgdmVyc2lvbkluZm9CaXRzID0gbmV3IEJpdEFycmF5KCk7XG4gICAgICAgICAgICBNYXRyaXhVdGlsLm1ha2VWZXJzaW9uSW5mb0JpdHModmVyc2lvbiwgdmVyc2lvbkluZm9CaXRzKTtcbiAgICAgICAgICAgIGxldCBiaXRJbmRleCA9IDYgKiAzIC0gMTsgLy8gSXQgd2lsbCBkZWNyZWFzZSBmcm9tIDE3IHRvIDAuXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDY7ICsraSkge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgMzsgKytqKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFBsYWNlIGJpdHMgaW4gTFNCIChsZWFzdCBzaWduaWZpY2FudCBiaXQpIHRvIE1TQiBvcmRlci5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYml0ID0gdmVyc2lvbkluZm9CaXRzLmdldChiaXRJbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIGJpdEluZGV4LS07XG4gICAgICAgICAgICAgICAgICAgIC8vIExlZnQgYm90dG9tIGNvcm5lci5cbiAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldEJvb2xlYW4oaSwgbWF0cml4LmdldEhlaWdodCgpIC0gMTEgKyBqLCBiaXQpO1xuICAgICAgICAgICAgICAgICAgICAvLyBSaWdodCBib3R0b20gY29ybmVyLlxuICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0Qm9vbGVhbihtYXRyaXguZ2V0SGVpZ2h0KCkgLSAxMSArIGosIGksIGJpdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIEVtYmVkIFwiZGF0YUJpdHNcIiB1c2luZyBcImdldE1hc2tQYXR0ZXJuXCIuIE9uIHN1Y2Nlc3MsIG1vZGlmeSB0aGUgbWF0cml4IGFuZCByZXR1cm4gdHJ1ZS5cbiAgICAgICAgLy8gRm9yIGRlYnVnZ2luZyBwdXJwb3NlcywgaXQgc2tpcHMgbWFza2luZyBwcm9jZXNzIGlmIFwiZ2V0TWFza1BhdHRlcm5cIiBpcyAtMShUWVBFU0NSSVBUUE9SVDogMjU1KS5cbiAgICAgICAgLy8gU2VlIDguNyBvZiBKSVNYMDUxMDoyMDA0IChwLjM4KSBmb3IgaG93IHRvIGVtYmVkIGRhdGEgYml0cy5cbiAgICAgICAgc3RhdGljIGVtYmVkRGF0YUJpdHMoZGF0YUJpdHMsIG1hc2tQYXR0ZXJuIC8qaW50Ki8sIG1hdHJpeCkge1xuICAgICAgICAgICAgbGV0IGJpdEluZGV4ID0gMDtcbiAgICAgICAgICAgIGxldCBkaXJlY3Rpb24gPSAtMTtcbiAgICAgICAgICAgIC8vIFN0YXJ0IGZyb20gdGhlIHJpZ2h0IGJvdHRvbSBjZWxsLlxuICAgICAgICAgICAgbGV0IHggPSBtYXRyaXguZ2V0V2lkdGgoKSAtIDE7XG4gICAgICAgICAgICBsZXQgeSA9IG1hdHJpeC5nZXRIZWlnaHQoKSAtIDE7XG4gICAgICAgICAgICB3aGlsZSAoeCA+IDApIHtcbiAgICAgICAgICAgICAgICAvLyBTa2lwIHRoZSB2ZXJ0aWNhbCB0aW1pbmcgcGF0dGVybi5cbiAgICAgICAgICAgICAgICBpZiAoeCA9PT0gNikge1xuICAgICAgICAgICAgICAgICAgICB4IC09IDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHdoaWxlICh5ID49IDAgJiYgeSA8IG1hdHJpeC5nZXRIZWlnaHQoKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeHggPSB4IC0gaTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNraXAgdGhlIGNlbGwgaWYgaXQncyBub3QgZW1wdHkuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIU1hdHJpeFV0aWwuaXNFbXB0eShtYXRyaXguZ2V0KHh4LCB5KSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBiaXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYml0SW5kZXggPCBkYXRhQml0cy5nZXRTaXplKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaXQgPSBkYXRhQml0cy5nZXQoYml0SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICsrYml0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQYWRkaW5nIGJpdC4gSWYgdGhlcmUgaXMgbm8gYml0IGxlZnQsIHdlJ2xsIGZpbGwgdGhlIGxlZnQgY2VsbHMgd2l0aCAwLCBhcyBkZXNjcmliZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiA4LjQuOSBvZiBKSVNYMDUxMDoyMDA0IChwLiAyNCkuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYml0ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTa2lwIG1hc2tpbmcgaWYgbWFza19wYXR0ZXJuIGlzIC0xIChUWVBFU0NSSVBUUE9SVDogMjU1KS5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXNrUGF0dGVybiAhPT0gMjU1ICYmIE1hc2tVdGlsLmdldERhdGFNYXNrQml0KG1hc2tQYXR0ZXJuLCB4eCwgeSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaXQgPSAhYml0O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldEJvb2xlYW4oeHgsIHksIGJpdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgeSArPSBkaXJlY3Rpb247XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRpcmVjdGlvbiA9IC1kaXJlY3Rpb247IC8vIFJldmVyc2UgdGhlIGRpcmVjdGlvbi5cbiAgICAgICAgICAgICAgICB5ICs9IGRpcmVjdGlvbjtcbiAgICAgICAgICAgICAgICB4IC09IDI7IC8vIE1vdmUgdG8gdGhlIGxlZnQuXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBBbGwgYml0cyBzaG91bGQgYmUgY29uc3VtZWQuXG4gICAgICAgICAgICBpZiAoYml0SW5kZXggIT09IGRhdGFCaXRzLmdldFNpemUoKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oJ05vdCBhbGwgYml0cyBjb25zdW1lZDogJyArIGJpdEluZGV4ICsgJy8nICsgZGF0YUJpdHMuZ2V0U2l6ZSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBSZXR1cm4gdGhlIHBvc2l0aW9uIG9mIHRoZSBtb3N0IHNpZ25pZmljYW50IGJpdCBzZXQgKG9uZTogdG8pIGluIHRoZSBcInZhbHVlXCIuIFRoZSBtb3N0XG4gICAgICAgIC8vIHNpZ25pZmljYW50IGJpdCBpcyBwb3NpdGlvbiAzMi4gSWYgdGhlcmUgaXMgbm8gYml0IHNldCwgcmV0dXJuIDAuIEV4YW1wbGVzOlxuICAgICAgICAvLyAtIGZpbmRNU0JTZXQoMCkgPT4gMFxuICAgICAgICAvLyAtIGZpbmRNU0JTZXQoMSkgPT4gMVxuICAgICAgICAvLyAtIGZpbmRNU0JTZXQoMjU1KSA9PiA4XG4gICAgICAgIHN0YXRpYyBmaW5kTVNCU2V0KHZhbHVlIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHJldHVybiAzMiAtIEludGVnZXIubnVtYmVyT2ZMZWFkaW5nWmVyb3ModmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIC8vIENhbGN1bGF0ZSBCQ0ggKEJvc2UtQ2hhdWRodXJpLUhvY3F1ZW5naGVtKSBjb2RlIGZvciBcInZhbHVlXCIgdXNpbmcgcG9seW5vbWlhbCBcInBvbHlcIi4gVGhlIEJDSFxuICAgICAgICAvLyBjb2RlIGlzIHVzZWQgZm9yIGVuY29kaW5nIHR5cGUgaW5mb3JtYXRpb24gYW5kIHZlcnNpb24gaW5mb3JtYXRpb24uXG4gICAgICAgIC8vIEV4YW1wbGU6IENhbGN1bGF0aW9uIG9mIHZlcnNpb24gaW5mb3JtYXRpb24gb2YgNy5cbiAgICAgICAgLy8gZih4KSBpcyBjcmVhdGVkIGZyb20gNy5cbiAgICAgICAgLy8gICAtIDcgPSAwMDAxMTEgaW4gNiBiaXRzXG4gICAgICAgIC8vICAgLSBmKHgpID0geF4yICsgeF4xICsgeF4wXG4gICAgICAgIC8vIGcoeCkgaXMgZ2l2ZW4gYnkgdGhlIHN0YW5kYXJkIChwLiA2NylcbiAgICAgICAgLy8gICAtIGcoeCkgPSB4XjEyICsgeF4xMSArIHheMTAgKyB4XjkgKyB4XjggKyB4XjUgKyB4XjIgKyAxXG4gICAgICAgIC8vIE11bHRpcGx5IGYoeCkgYnkgeF4oMTggLSA2KVxuICAgICAgICAvLyAgIC0gZicoeCkgPSBmKHgpICogeF4oMTggLSA2KVxuICAgICAgICAvLyAgIC0gZicoeCkgPSB4XjE0ICsgeF4xMyArIHheMTJcbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSByZW1haW5kZXIgb2YgZicoeCkgLyBnKHgpXG4gICAgICAgIC8vICAgICAgICAgeF4yXG4gICAgICAgIC8vICAgICAgICAgX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19cbiAgICAgICAgLy8gICBnKHgpICl4XjE0ICsgeF4xMyArIHheMTJcbiAgICAgICAgLy8gICAgICAgICB4XjE0ICsgeF4xMyArIHheMTIgKyB4XjExICsgeF4xMCArIHheNyArIHheNCArIHheMlxuICAgICAgICAvLyAgICAgICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgIC8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeF4xMSArIHheMTAgKyB4XjcgKyB4XjQgKyB4XjJcbiAgICAgICAgLy9cbiAgICAgICAgLy8gVGhlIHJlbWFpbmRlciBpcyB4XjExICsgeF4xMCArIHheNyArIHheNCArIHheMlxuICAgICAgICAvLyBFbmNvZGUgaXQgaW4gYmluYXJ5OiAxMTAwMTAwMTAxMDBcbiAgICAgICAgLy8gVGhlIHJldHVybiB2YWx1ZSBpcyAweGM5NCAoMTEwMCAxMDAxIDAxMDApXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFNpbmNlIGFsbCBjb2VmZmljaWVudHMgaW4gdGhlIHBvbHlub21pYWxzIGFyZSAxIG9yIDAsIHdlIGNhbiBkbyB0aGUgY2FsY3VsYXRpb24gYnkgYml0XG4gICAgICAgIC8vIG9wZXJhdGlvbnMuIFdlIGRvbid0IGNhcmUgaWYgY29lZmZpY2llbnRzIGFyZSBwb3NpdGl2ZSBvciBuZWdhdGl2ZS5cbiAgICAgICAgc3RhdGljIGNhbGN1bGF0ZUJDSENvZGUodmFsdWUgLyppbnQqLywgcG9seSAvKmludCovKSB7XG4gICAgICAgICAgICBpZiAocG9seSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJzAgcG9seW5vbWlhbCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSWYgcG9seSBpcyBcIjEgMTExMSAwMDEwIDAxMDFcIiAodmVyc2lvbiBpbmZvIHBvbHkpLCBtc2JTZXRJblBvbHkgaXMgMTMuIFdlJ2xsIHN1YnRyYWN0IDFcbiAgICAgICAgICAgIC8vIGZyb20gMTMgdG8gbWFrZSBpdCAxMi5cbiAgICAgICAgICAgIGNvbnN0IG1zYlNldEluUG9seSA9IE1hdHJpeFV0aWwuZmluZE1TQlNldChwb2x5KTtcbiAgICAgICAgICAgIHZhbHVlIDw8PSBtc2JTZXRJblBvbHkgLSAxO1xuICAgICAgICAgICAgLy8gRG8gdGhlIGRpdmlzaW9uIGJ1c2luZXNzIHVzaW5nIGV4Y2x1c2l2ZS1vciBvcGVyYXRpb25zLlxuICAgICAgICAgICAgd2hpbGUgKE1hdHJpeFV0aWwuZmluZE1TQlNldCh2YWx1ZSkgPj0gbXNiU2V0SW5Qb2x5KSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgXj0gcG9seSA8PCAoTWF0cml4VXRpbC5maW5kTVNCU2V0KHZhbHVlKSAtIG1zYlNldEluUG9seSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBOb3cgdGhlIFwidmFsdWVcIiBpcyB0aGUgcmVtYWluZGVyIChpLmUuIHRoZSBCQ0ggY29kZSlcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBNYWtlIGJpdCB2ZWN0b3Igb2YgdHlwZSBpbmZvcm1hdGlvbi4gT24gc3VjY2Vzcywgc3RvcmUgdGhlIHJlc3VsdCBpbiBcImJpdHNcIiBhbmQgcmV0dXJuIHRydWUuXG4gICAgICAgIC8vIEVuY29kZSBlcnJvciBjb3JyZWN0aW9uIGxldmVsIGFuZCBtYXNrIHBhdHRlcm4uIFNlZSA4Ljkgb2ZcbiAgICAgICAgLy8gSklTWDA1MTA6MjAwNCAocC40NSkgZm9yIGRldGFpbHMuXG4gICAgICAgIHN0YXRpYyBtYWtlVHlwZUluZm9CaXRzKGVjTGV2ZWwsIG1hc2tQYXR0ZXJuIC8qaW50Ki8sIGJpdHMpIHtcbiAgICAgICAgICAgIGlmICghUVJDb2RlLmlzVmFsaWRNYXNrUGF0dGVybihtYXNrUGF0dGVybikpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKCdJbnZhbGlkIG1hc2sgcGF0dGVybicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgdHlwZUluZm8gPSAoZWNMZXZlbC5nZXRCaXRzKCkgPDwgMykgfCBtYXNrUGF0dGVybjtcbiAgICAgICAgICAgIGJpdHMuYXBwZW5kQml0cyh0eXBlSW5mbywgNSk7XG4gICAgICAgICAgICBjb25zdCBiY2hDb2RlID0gTWF0cml4VXRpbC5jYWxjdWxhdGVCQ0hDb2RlKHR5cGVJbmZvLCBNYXRyaXhVdGlsLlRZUEVfSU5GT19QT0xZKTtcbiAgICAgICAgICAgIGJpdHMuYXBwZW5kQml0cyhiY2hDb2RlLCAxMCk7XG4gICAgICAgICAgICBjb25zdCBtYXNrQml0cyA9IG5ldyBCaXRBcnJheSgpO1xuICAgICAgICAgICAgbWFza0JpdHMuYXBwZW5kQml0cyhNYXRyaXhVdGlsLlRZUEVfSU5GT19NQVNLX1BBVFRFUk4sIDE1KTtcbiAgICAgICAgICAgIGJpdHMueG9yKG1hc2tCaXRzKTtcbiAgICAgICAgICAgIGlmIChiaXRzLmdldFNpemUoKSAhPT0gMTUpIHsgLy8gSnVzdCBpbiBjYXNlLlxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oJ3Nob3VsZCBub3QgaGFwcGVuIGJ1dCB3ZSBnb3Q6ICcgKyBiaXRzLmdldFNpemUoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gTWFrZSBiaXQgdmVjdG9yIG9mIHZlcnNpb24gaW5mb3JtYXRpb24uIE9uIHN1Y2Nlc3MsIHN0b3JlIHRoZSByZXN1bHQgaW4gXCJiaXRzXCIgYW5kIHJldHVybiB0cnVlLlxuICAgICAgICAvLyBTZWUgOC4xMCBvZiBKSVNYMDUxMDoyMDA0IChwLjQ1KSBmb3IgZGV0YWlscy5cbiAgICAgICAgc3RhdGljIG1ha2VWZXJzaW9uSW5mb0JpdHModmVyc2lvbiwgYml0cykge1xuICAgICAgICAgICAgYml0cy5hcHBlbmRCaXRzKHZlcnNpb24uZ2V0VmVyc2lvbk51bWJlcigpLCA2KTtcbiAgICAgICAgICAgIGNvbnN0IGJjaENvZGUgPSBNYXRyaXhVdGlsLmNhbGN1bGF0ZUJDSENvZGUodmVyc2lvbi5nZXRWZXJzaW9uTnVtYmVyKCksIE1hdHJpeFV0aWwuVkVSU0lPTl9JTkZPX1BPTFkpO1xuICAgICAgICAgICAgYml0cy5hcHBlbmRCaXRzKGJjaENvZGUsIDEyKTtcbiAgICAgICAgICAgIGlmIChiaXRzLmdldFNpemUoKSAhPT0gMTgpIHsgLy8gSnVzdCBpbiBjYXNlLlxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oJ3Nob3VsZCBub3QgaGFwcGVuIGJ1dCB3ZSBnb3Q6ICcgKyBiaXRzLmdldFNpemUoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ2hlY2sgaWYgXCJ2YWx1ZVwiIGlzIGVtcHR5LlxuICAgICAgICBzdGF0aWMgaXNFbXB0eSh2YWx1ZSAvKmludCovKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWUgPT09IDI1NTsgLy8gLTFcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZW1iZWRUaW1pbmdQYXR0ZXJucyhtYXRyaXgpIHtcbiAgICAgICAgICAgIC8vIC04IGlzIGZvciBza2lwcGluZyBwb3NpdGlvbiBkZXRlY3Rpb24gcGF0dGVybnMgKDc6IHNpemUpLCBhbmQgdHdvIGhvcml6b250YWwvdmVydGljYWxcbiAgICAgICAgICAgIC8vIHNlcGFyYXRpb24gcGF0dGVybnMgKDE6IHNpemUpLiBUaHVzLCA4ID0gNyArIDEuXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gODsgaSA8IG1hdHJpeC5nZXRXaWR0aCgpIC0gODsgKytpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYml0ID0gKGkgKyAxKSAlIDI7XG4gICAgICAgICAgICAgICAgLy8gSG9yaXpvbnRhbCBsaW5lLlxuICAgICAgICAgICAgICAgIGlmIChNYXRyaXhVdGlsLmlzRW1wdHkobWF0cml4LmdldChpLCA2KSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldE51bWJlcihpLCA2LCBiaXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBWZXJ0aWNhbCBsaW5lLlxuICAgICAgICAgICAgICAgIGlmIChNYXRyaXhVdGlsLmlzRW1wdHkobWF0cml4LmdldCg2LCBpKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldE51bWJlcig2LCBpLCBiaXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBFbWJlZCB0aGUgbG9uZWx5IGRhcmsgZG90IGF0IGxlZnQgYm90dG9tIGNvcm5lci4gSklTWDA1MTA6MjAwNCAocC40NilcbiAgICAgICAgc3RhdGljIGVtYmVkRGFya0RvdEF0TGVmdEJvdHRvbUNvcm5lcihtYXRyaXgpIHtcbiAgICAgICAgICAgIGlmIChtYXRyaXguZ2V0KDgsIG1hdHJpeC5nZXRIZWlnaHQoKSAtIDgpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdyaXRlckV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbWF0cml4LnNldE51bWJlcig4LCBtYXRyaXguZ2V0SGVpZ2h0KCkgLSA4LCAxKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZW1iZWRIb3Jpem9udGFsU2VwYXJhdGlvblBhdHRlcm4oeFN0YXJ0IC8qaW50Ki8sIHlTdGFydCAvKmludCovLCBtYXRyaXgpIHtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgODsgKyt4KSB7XG4gICAgICAgICAgICAgICAgaWYgKCFNYXRyaXhVdGlsLmlzRW1wdHkobWF0cml4LmdldCh4U3RhcnQgKyB4LCB5U3RhcnQpKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1hdHJpeC5zZXROdW1iZXIoeFN0YXJ0ICsgeCwgeVN0YXJ0LCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZW1iZWRWZXJ0aWNhbFNlcGFyYXRpb25QYXR0ZXJuKHhTdGFydCAvKmludCovLCB5U3RhcnQgLyppbnQqLywgbWF0cml4KSB7XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IDc7ICsreSkge1xuICAgICAgICAgICAgICAgIGlmICghTWF0cml4VXRpbC5pc0VtcHR5KG1hdHJpeC5nZXQoeFN0YXJ0LCB5U3RhcnQgKyB5KSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdyaXRlckV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBtYXRyaXguc2V0TnVtYmVyKHhTdGFydCwgeVN0YXJ0ICsgeSwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGVtYmVkUG9zaXRpb25BZGp1c3RtZW50UGF0dGVybih4U3RhcnQgLyppbnQqLywgeVN0YXJ0IC8qaW50Ki8sIG1hdHJpeCkge1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCA1OyArK3kpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXR0ZXJuWSA9IE1hdHJpeFV0aWwuUE9TSVRJT05fQURKVVNUTUVOVF9QQVRURVJOW3ldO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgNTsgKyt4KSB7XG4gICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXROdW1iZXIoeFN0YXJ0ICsgeCwgeVN0YXJ0ICsgeSwgcGF0dGVybllbeF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZW1iZWRQb3NpdGlvbkRldGVjdGlvblBhdHRlcm4oeFN0YXJ0IC8qaW50Ki8sIHlTdGFydCAvKmludCovLCBtYXRyaXgpIHtcbiAgICAgICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgNzsgKyt5KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGF0dGVyblkgPSBNYXRyaXhVdGlsLlBPU0lUSU9OX0RFVEVDVElPTl9QQVRURVJOW3ldO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgNzsgKyt4KSB7XG4gICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXROdW1iZXIoeFN0YXJ0ICsgeCwgeVN0YXJ0ICsgeSwgcGF0dGVybllbeF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBFbWJlZCBwb3NpdGlvbiBkZXRlY3Rpb24gcGF0dGVybnMgYW5kIHN1cnJvdW5kaW5nIHZlcnRpY2FsL2hvcml6b250YWwgc2VwYXJhdG9ycy5cbiAgICAgICAgc3RhdGljIGVtYmVkUG9zaXRpb25EZXRlY3Rpb25QYXR0ZXJuc0FuZFNlcGFyYXRvcnMobWF0cml4KSB7XG4gICAgICAgICAgICAvLyBFbWJlZCB0aHJlZSBiaWcgc3F1YXJlcyBhdCBjb3JuZXJzLlxuICAgICAgICAgICAgY29uc3QgcGRwV2lkdGggPSBNYXRyaXhVdGlsLlBPU0lUSU9OX0RFVEVDVElPTl9QQVRURVJOWzBdLmxlbmd0aDtcbiAgICAgICAgICAgIC8vIExlZnQgdG9wIGNvcm5lci5cbiAgICAgICAgICAgIE1hdHJpeFV0aWwuZW1iZWRQb3NpdGlvbkRldGVjdGlvblBhdHRlcm4oMCwgMCwgbWF0cml4KTtcbiAgICAgICAgICAgIC8vIFJpZ2h0IHRvcCBjb3JuZXIuXG4gICAgICAgICAgICBNYXRyaXhVdGlsLmVtYmVkUG9zaXRpb25EZXRlY3Rpb25QYXR0ZXJuKG1hdHJpeC5nZXRXaWR0aCgpIC0gcGRwV2lkdGgsIDAsIG1hdHJpeCk7XG4gICAgICAgICAgICAvLyBMZWZ0IGJvdHRvbSBjb3JuZXIuXG4gICAgICAgICAgICBNYXRyaXhVdGlsLmVtYmVkUG9zaXRpb25EZXRlY3Rpb25QYXR0ZXJuKDAsIG1hdHJpeC5nZXRXaWR0aCgpIC0gcGRwV2lkdGgsIG1hdHJpeCk7XG4gICAgICAgICAgICAvLyBFbWJlZCBob3Jpem9udGFsIHNlcGFyYXRpb24gcGF0dGVybnMgYXJvdW5kIHRoZSBzcXVhcmVzLlxuICAgICAgICAgICAgY29uc3QgaHNwV2lkdGggPSA4O1xuICAgICAgICAgICAgLy8gTGVmdCB0b3AgY29ybmVyLlxuICAgICAgICAgICAgTWF0cml4VXRpbC5lbWJlZEhvcml6b250YWxTZXBhcmF0aW9uUGF0dGVybigwLCBoc3BXaWR0aCAtIDEsIG1hdHJpeCk7XG4gICAgICAgICAgICAvLyBSaWdodCB0b3AgY29ybmVyLlxuICAgICAgICAgICAgTWF0cml4VXRpbC5lbWJlZEhvcml6b250YWxTZXBhcmF0aW9uUGF0dGVybihtYXRyaXguZ2V0V2lkdGgoKSAtIGhzcFdpZHRoLCBoc3BXaWR0aCAtIDEsIG1hdHJpeCk7XG4gICAgICAgICAgICAvLyBMZWZ0IGJvdHRvbSBjb3JuZXIuXG4gICAgICAgICAgICBNYXRyaXhVdGlsLmVtYmVkSG9yaXpvbnRhbFNlcGFyYXRpb25QYXR0ZXJuKDAsIG1hdHJpeC5nZXRXaWR0aCgpIC0gaHNwV2lkdGgsIG1hdHJpeCk7XG4gICAgICAgICAgICAvLyBFbWJlZCB2ZXJ0aWNhbCBzZXBhcmF0aW9uIHBhdHRlcm5zIGFyb3VuZCB0aGUgc3F1YXJlcy5cbiAgICAgICAgICAgIGNvbnN0IHZzcFNpemUgPSA3O1xuICAgICAgICAgICAgLy8gTGVmdCB0b3AgY29ybmVyLlxuICAgICAgICAgICAgTWF0cml4VXRpbC5lbWJlZFZlcnRpY2FsU2VwYXJhdGlvblBhdHRlcm4odnNwU2l6ZSwgMCwgbWF0cml4KTtcbiAgICAgICAgICAgIC8vIFJpZ2h0IHRvcCBjb3JuZXIuXG4gICAgICAgICAgICBNYXRyaXhVdGlsLmVtYmVkVmVydGljYWxTZXBhcmF0aW9uUGF0dGVybihtYXRyaXguZ2V0SGVpZ2h0KCkgLSB2c3BTaXplIC0gMSwgMCwgbWF0cml4KTtcbiAgICAgICAgICAgIC8vIExlZnQgYm90dG9tIGNvcm5lci5cbiAgICAgICAgICAgIE1hdHJpeFV0aWwuZW1iZWRWZXJ0aWNhbFNlcGFyYXRpb25QYXR0ZXJuKHZzcFNpemUsIG1hdHJpeC5nZXRIZWlnaHQoKSAtIHZzcFNpemUsIG1hdHJpeCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRW1iZWQgcG9zaXRpb24gYWRqdXN0bWVudCBwYXR0ZXJucyBpZiBuZWVkIGJlLlxuICAgICAgICBzdGF0aWMgbWF5YmVFbWJlZFBvc2l0aW9uQWRqdXN0bWVudFBhdHRlcm5zKHZlcnNpb24sIG1hdHJpeCkge1xuICAgICAgICAgICAgaWYgKHZlcnNpb24uZ2V0VmVyc2lvbk51bWJlcigpIDwgMikgeyAvLyBUaGUgcGF0dGVybnMgYXBwZWFyIGlmIHZlcnNpb24gPj0gMlxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gdmVyc2lvbi5nZXRWZXJzaW9uTnVtYmVyKCkgLSAxO1xuICAgICAgICAgICAgY29uc3QgY29vcmRpbmF0ZXMgPSBNYXRyaXhVdGlsLlBPU0lUSU9OX0FESlVTVE1FTlRfUEFUVEVSTl9DT09SRElOQVRFX1RBQkxFW2luZGV4XTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBsZW5ndGggPSBjb29yZGluYXRlcy5sZW5ndGg7IGkgIT09IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgeSA9IGNvb3JkaW5hdGVzW2ldO1xuICAgICAgICAgICAgICAgIGlmICh5ID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogIT09IGxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB4ID0gY29vcmRpbmF0ZXNbal07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoeCA+PSAwICYmIE1hdHJpeFV0aWwuaXNFbXB0eShtYXRyaXguZ2V0KHgsIHkpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBjZWxsIGlzIHVuc2V0LCB3ZSBlbWJlZCB0aGUgcG9zaXRpb24gYWRqdXN0bWVudCBwYXR0ZXJuIGhlcmUuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gLTIgaXMgbmVjZXNzYXJ5IHNpbmNlIHRoZSB4L3kgY29vcmRpbmF0ZXMgcG9pbnQgdG8gdGhlIGNlbnRlciBvZiB0aGUgcGF0dGVybiwgbm90IHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxlZnQgdG9wIGNvcm5lci5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBNYXRyaXhVdGlsLmVtYmVkUG9zaXRpb25BZGp1c3RtZW50UGF0dGVybih4IC0gMiwgeSAtIDIsIG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgTWF0cml4VXRpbC5QT1NJVElPTl9ERVRFQ1RJT05fUEFUVEVSTiA9IEFycmF5LmZyb20oW1xuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDEsIDEsIDEsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAwLCAwLCAwLCAwLCAwLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMCwgMSwgMSwgMSwgMCwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDAsIDEsIDEsIDEsIDAsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAwLCAxLCAxLCAxLCAwLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMCwgMCwgMCwgMCwgMCwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDEsIDEsIDEsIDEsIDFdKSxcbiAgICBdKTtcbiAgICBNYXRyaXhVdGlsLlBPU0lUSU9OX0FESlVTVE1FTlRfUEFUVEVSTiA9IEFycmF5LmZyb20oW1xuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDEsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAwLCAwLCAwLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMCwgMSwgMCwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDAsIDAsIDAsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAxLCAxLCAxXSksXG4gICAgXSk7XG4gICAgLy8gRnJvbSBBcHBlbmRpeCBFLiBUYWJsZSAxLCBKSVMwNTEwWDoyMDA0ICg3MTogcCkuIFRoZSB0YWJsZSB3YXMgZG91YmxlLWNoZWNrZWQgYnkga29tYXRzdS5cbiAgICBNYXRyaXhVdGlsLlBPU0lUSU9OX0FESlVTVE1FTlRfUEFUVEVSTl9DT09SRElOQVRFX1RBQkxFID0gQXJyYXkuZnJvbShbXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAxOCwgLTEsIC0xLCAtMSwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMjIsIC0xLCAtMSwgLTEsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDI2LCAtMSwgLTEsIC0xLCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgLTEsIC0xLCAtMSwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzQsIC0xLCAtMSwgLTEsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDIyLCAzOCwgLTEsIC0xLCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAyNCwgNDIsIC0xLCAtMSwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMjYsIDQ2LCAtMSwgLTEsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDI4LCA1MCwgLTEsIC0xLCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTQsIC0xLCAtMSwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzIsIDU4LCAtMSwgLTEsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDM0LCA2MiwgLTEsIC0xLCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAyNiwgNDYsIDY2LCAtMSwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMjYsIDQ4LCA3MCwgLTEsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDI2LCA1MCwgNzQsIC0xLCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTQsIDc4LCAtMSwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIDU2LCA4MiwgLTEsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDMwLCA1OCwgODYsIC0xLCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzNCwgNjIsIDkwLCAtMSwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMjgsIDUwLCA3MiwgOTQsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDI2LCA1MCwgNzQsIDk4LCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTQsIDc4LCAxMDIsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDI4LCA1NCwgODAsIDEwNiwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzIsIDU4LCA4NCwgMTEwLCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTgsIDg2LCAxMTQsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDM0LCA2MiwgOTAsIDExOCwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMjYsIDUwLCA3NCwgOTgsIDEyMiwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTQsIDc4LCAxMDIsIDEyNiwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAyNiwgNTIsIDc4LCAxMDQsIDEzMCwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTYsIDgyLCAxMDgsIDEzNCwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzNCwgNjAsIDg2LCAxMTIsIDEzOCwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTgsIDg2LCAxMTQsIDE0MiwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzNCwgNjIsIDkwLCAxMTgsIDE0NiwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTQsIDc4LCAxMDIsIDEyNiwgMTUwXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMjQsIDUwLCA3NiwgMTAyLCAxMjgsIDE1NF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDI4LCA1NCwgODAsIDEwNiwgMTMyLCAxNThdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzMiwgNTgsIDg0LCAxMTAsIDEzNiwgMTYyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMjYsIDU0LCA4MiwgMTEwLCAxMzgsIDE2Nl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDMwLCA1OCwgODYsIDExNCwgMTQyLCAxNzBdKSxcbiAgICBdKTtcbiAgICAvLyBUeXBlIGluZm8gY2VsbHMgYXQgdGhlIGxlZnQgdG9wIGNvcm5lci5cbiAgICBNYXRyaXhVdGlsLlRZUEVfSU5GT19DT09SRElOQVRFUyA9IEFycmF5LmZyb20oW1xuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzgsIDBdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs4LCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbOCwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzgsIDNdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs4LCA0XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbOCwgNV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzgsIDddKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs4LCA4XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNywgOF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzUsIDhdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs0LCA4XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgOF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDhdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCA4XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMCwgOF0pLFxuICAgIF0pO1xuICAgIC8vIEZyb20gQXBwZW5kaXggRCBpbiBKSVNYMDUxMDoyMDA0IChwLiA2NylcbiAgICBNYXRyaXhVdGlsLlZFUlNJT05fSU5GT19QT0xZID0gMHgxZjI1OyAvLyAxIDExMTEgMDAxMCAwMTAxXG4gICAgLy8gRnJvbSBBcHBlbmRpeCBDIGluIEpJU1gwNTEwOjIwMDQgKHAuNjUpLlxuICAgIE1hdHJpeFV0aWwuVFlQRV9JTkZPX1BPTFkgPSAweDUzNztcbiAgICBNYXRyaXhVdGlsLlRZUEVfSU5GT19NQVNLX1BBVFRFUk4gPSAweDU0MTI7XG5cbiAgICAvKm5hbWVzcGFjZSBjb20uZ29vZ2xlLnp4aW5nLnFyY29kZS5lbmNvZGVyIHsqL1xuICAgIGNsYXNzIEJsb2NrUGFpciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGRhdGFCeXRlcywgZXJyb3JDb3JyZWN0aW9uQnl0ZXMpIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YUJ5dGVzID0gZGF0YUJ5dGVzO1xuICAgICAgICAgICAgdGhpcy5lcnJvckNvcnJlY3Rpb25CeXRlcyA9IGVycm9yQ29ycmVjdGlvbkJ5dGVzO1xuICAgICAgICB9XG4gICAgICAgIGdldERhdGFCeXRlcygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGFCeXRlcztcbiAgICAgICAgfVxuICAgICAgICBnZXRFcnJvckNvcnJlY3Rpb25CeXRlcygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVycm9yQ29ycmVjdGlvbkJ5dGVzO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyppbXBvcnQgamF2YS5pby5VbnN1cHBvcnRlZEVuY29kaW5nRXhjZXB0aW9uOyovXG4gICAgLyppbXBvcnQgamF2YS51dGlsLkFycmF5TGlzdDsqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5Db2xsZWN0aW9uOyovXG4gICAgLyppbXBvcnQgamF2YS51dGlsLk1hcDsqL1xuICAgIC8qKlxuICAgICAqIEBhdXRob3Igc2F0b3J1eEBnb29nbGUuY29tIChTYXRvcnUgVGFrYWJheWFzaGkpIC0gY3JlYXRvclxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pIC0gcG9ydGVkIGZyb20gQysrXG4gICAgICovXG4gICAgY2xhc3MgRW5jb2RlciB7XG4gICAgICAgIC8vIFRZUEVTQ1JJUFRQT1JUOiBjaGFuZ2VkIHRvIFVURjgsIHRoZSBkZWZhdWx0IGZvciBqc1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHsgfVxuICAgICAgICAvLyBUaGUgbWFzayBwZW5hbHR5IGNhbGN1bGF0aW9uIGlzIGNvbXBsaWNhdGVkLiAgU2VlIFRhYmxlIDIxIG9mIEpJU1gwNTEwOjIwMDQgKHAuNDUpIGZvciBkZXRhaWxzLlxuICAgICAgICAvLyBCYXNpY2FsbHkgaXQgYXBwbGllcyBmb3VyIHJ1bGVzIGFuZCBzdW1tYXRlIGFsbCBwZW5hbHRpZXMuXG4gICAgICAgIHN0YXRpYyBjYWxjdWxhdGVNYXNrUGVuYWx0eShtYXRyaXgpIHtcbiAgICAgICAgICAgIHJldHVybiBNYXNrVXRpbC5hcHBseU1hc2tQZW5hbHR5UnVsZTEobWF0cml4KVxuICAgICAgICAgICAgICAgICsgTWFza1V0aWwuYXBwbHlNYXNrUGVuYWx0eVJ1bGUyKG1hdHJpeClcbiAgICAgICAgICAgICAgICArIE1hc2tVdGlsLmFwcGx5TWFza1BlbmFsdHlSdWxlMyhtYXRyaXgpXG4gICAgICAgICAgICAgICAgKyBNYXNrVXRpbC5hcHBseU1hc2tQZW5hbHR5UnVsZTQobWF0cml4KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIGNvbnRlbnQgdGV4dCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIGVjTGV2ZWwgZXJyb3IgY29ycmVjdGlvbiBsZXZlbCB0byB1c2VcbiAgICAgICAgICogQHJldHVybiB7QGxpbmsgUVJDb2RlfSByZXByZXNlbnRpbmcgdGhlIGVuY29kZWQgUVIgY29kZVxuICAgICAgICAgKiBAdGhyb3dzIFdyaXRlckV4Y2VwdGlvbiBpZiBlbmNvZGluZyBjYW4ndCBzdWNjZWVkLCBiZWNhdXNlIG9mIGZvciBleGFtcGxlIGludmFsaWQgY29udGVudFxuICAgICAgICAgKiAgIG9yIGNvbmZpZ3VyYXRpb25cbiAgICAgICAgICovXG4gICAgICAgIC8vIHB1YmxpYyBzdGF0aWMgZW5jb2RlKGNvbnRlbnQ6IHN0cmluZywgZWNMZXZlbDogRXJyb3JDb3JyZWN0aW9uTGV2ZWwpOiBRUkNvZGUgLyp0aHJvd3MgV3JpdGVyRXhjZXB0aW9uKi8ge1xuICAgICAgICAvLyAgIHJldHVybiBlbmNvZGUoY29udGVudCwgZWNMZXZlbCwgbnVsbClcbiAgICAgICAgLy8gfVxuICAgICAgICBzdGF0aWMgZW5jb2RlKGNvbnRlbnQsIGVjTGV2ZWwsIGhpbnRzID0gbnVsbCkge1xuICAgICAgICAgICAgLy8gRGV0ZXJtaW5lIHdoYXQgY2hhcmFjdGVyIGVuY29kaW5nIGhhcyBiZWVuIHNwZWNpZmllZCBieSB0aGUgY2FsbGVyLCBpZiBhbnlcbiAgICAgICAgICAgIGxldCBlbmNvZGluZyA9IEVuY29kZXIuREVGQVVMVF9CWVRFX01PREVfRU5DT0RJTkc7XG4gICAgICAgICAgICBjb25zdCBoYXNFbmNvZGluZ0hpbnQgPSBoaW50cyAhPT0gbnVsbCAmJiB1bmRlZmluZWQgIT09IGhpbnRzLmdldChFbmNvZGVIaW50VHlwZSQxLkNIQVJBQ1RFUl9TRVQpO1xuICAgICAgICAgICAgaWYgKGhhc0VuY29kaW5nSGludCkge1xuICAgICAgICAgICAgICAgIGVuY29kaW5nID0gaGludHMuZ2V0KEVuY29kZUhpbnRUeXBlJDEuQ0hBUkFDVEVSX1NFVCkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFBpY2sgYW4gZW5jb2RpbmcgbW9kZSBhcHByb3ByaWF0ZSBmb3IgdGhlIGNvbnRlbnQuIE5vdGUgdGhhdCB0aGlzIHdpbGwgbm90IGF0dGVtcHQgdG8gdXNlXG4gICAgICAgICAgICAvLyBtdWx0aXBsZSBtb2RlcyAvIHNlZ21lbnRzIGV2ZW4gaWYgdGhhdCB3ZXJlIG1vcmUgZWZmaWNpZW50LiBUd291bGQgYmUgbmljZS5cbiAgICAgICAgICAgIGNvbnN0IG1vZGUgPSB0aGlzLmNob29zZU1vZGUoY29udGVudCwgZW5jb2RpbmcpO1xuICAgICAgICAgICAgLy8gVGhpcyB3aWxsIHN0b3JlIHRoZSBoZWFkZXIgaW5mb3JtYXRpb24sIGxpa2UgbW9kZSBhbmRcbiAgICAgICAgICAgIC8vIGxlbmd0aCwgYXMgd2VsbCBhcyBcImhlYWRlclwiIHNlZ21lbnRzIGxpa2UgYW4gRUNJIHNlZ21lbnQuXG4gICAgICAgICAgICBjb25zdCBoZWFkZXJCaXRzID0gbmV3IEJpdEFycmF5KCk7XG4gICAgICAgICAgICAvLyBBcHBlbmQgRUNJIHNlZ21lbnQgaWYgYXBwbGljYWJsZVxuICAgICAgICAgICAgaWYgKG1vZGUgPT09IE1vZGUkMS5CWVRFICYmIChoYXNFbmNvZGluZ0hpbnQgfHwgRW5jb2Rlci5ERUZBVUxUX0JZVEVfTU9ERV9FTkNPRElORyAhPT0gZW5jb2RpbmcpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZWNpID0gQ2hhcmFjdGVyU2V0RUNJLmdldENoYXJhY3RlclNldEVDSUJ5TmFtZShlbmNvZGluZyk7XG4gICAgICAgICAgICAgICAgaWYgKGVjaSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYXBwZW5kRUNJKGVjaSwgaGVhZGVyQml0cyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gKFdpdGggRUNJIGluIHBsYWNlLCkgV3JpdGUgdGhlIG1vZGUgbWFya2VyXG4gICAgICAgICAgICB0aGlzLmFwcGVuZE1vZGVJbmZvKG1vZGUsIGhlYWRlckJpdHMpO1xuICAgICAgICAgICAgLy8gQ29sbGVjdCBkYXRhIHdpdGhpbiB0aGUgbWFpbiBzZWdtZW50LCBzZXBhcmF0ZWx5LCB0byBjb3VudCBpdHMgc2l6ZSBpZiBuZWVkZWQuIERvbid0IGFkZCBpdCB0b1xuICAgICAgICAgICAgLy8gbWFpbiBwYXlsb2FkIHlldC5cbiAgICAgICAgICAgIGNvbnN0IGRhdGFCaXRzID0gbmV3IEJpdEFycmF5KCk7XG4gICAgICAgICAgICB0aGlzLmFwcGVuZEJ5dGVzKGNvbnRlbnQsIG1vZGUsIGRhdGFCaXRzLCBlbmNvZGluZyk7XG4gICAgICAgICAgICBsZXQgdmVyc2lvbjtcbiAgICAgICAgICAgIGlmIChoaW50cyAhPT0gbnVsbCAmJiB1bmRlZmluZWQgIT09IGhpbnRzLmdldChFbmNvZGVIaW50VHlwZSQxLlFSX1ZFUlNJT04pKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdmVyc2lvbk51bWJlciA9IE51bWJlci5wYXJzZUludChoaW50cy5nZXQoRW5jb2RlSGludFR5cGUkMS5RUl9WRVJTSU9OKS50b1N0cmluZygpLCAxMCk7XG4gICAgICAgICAgICAgICAgdmVyc2lvbiA9IFZlcnNpb24kMS5nZXRWZXJzaW9uRm9yTnVtYmVyKHZlcnNpb25OdW1iZXIpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGJpdHNOZWVkZWQgPSB0aGlzLmNhbGN1bGF0ZUJpdHNOZWVkZWQobW9kZSwgaGVhZGVyQml0cywgZGF0YUJpdHMsIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aWxsRml0KGJpdHNOZWVkZWQsIHZlcnNpb24sIGVjTGV2ZWwpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oJ0RhdGEgdG9vIGJpZyBmb3IgcmVxdWVzdGVkIHZlcnNpb24nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB2ZXJzaW9uID0gdGhpcy5yZWNvbW1lbmRWZXJzaW9uKGVjTGV2ZWwsIG1vZGUsIGhlYWRlckJpdHMsIGRhdGFCaXRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGhlYWRlckFuZERhdGFCaXRzID0gbmV3IEJpdEFycmF5KCk7XG4gICAgICAgICAgICBoZWFkZXJBbmREYXRhQml0cy5hcHBlbmRCaXRBcnJheShoZWFkZXJCaXRzKTtcbiAgICAgICAgICAgIC8vIEZpbmQgXCJsZW5ndGhcIiBvZiBtYWluIHNlZ21lbnQgYW5kIHdyaXRlIGl0XG4gICAgICAgICAgICBjb25zdCBudW1MZXR0ZXJzID0gbW9kZSA9PT0gTW9kZSQxLkJZVEUgPyBkYXRhQml0cy5nZXRTaXplSW5CeXRlcygpIDogY29udGVudC5sZW5ndGg7XG4gICAgICAgICAgICB0aGlzLmFwcGVuZExlbmd0aEluZm8obnVtTGV0dGVycywgdmVyc2lvbiwgbW9kZSwgaGVhZGVyQW5kRGF0YUJpdHMpO1xuICAgICAgICAgICAgLy8gUHV0IGRhdGEgdG9nZXRoZXIgaW50byB0aGUgb3ZlcmFsbCBwYXlsb2FkXG4gICAgICAgICAgICBoZWFkZXJBbmREYXRhQml0cy5hcHBlbmRCaXRBcnJheShkYXRhQml0cyk7XG4gICAgICAgICAgICBjb25zdCBlY0Jsb2NrcyA9IHZlcnNpb24uZ2V0RUNCbG9ja3NGb3JMZXZlbChlY0xldmVsKTtcbiAgICAgICAgICAgIGNvbnN0IG51bURhdGFCeXRlcyA9IHZlcnNpb24uZ2V0VG90YWxDb2Rld29yZHMoKSAtIGVjQmxvY2tzLmdldFRvdGFsRUNDb2Rld29yZHMoKTtcbiAgICAgICAgICAgIC8vIFRlcm1pbmF0ZSB0aGUgYml0cyBwcm9wZXJseS5cbiAgICAgICAgICAgIHRoaXMudGVybWluYXRlQml0cyhudW1EYXRhQnl0ZXMsIGhlYWRlckFuZERhdGFCaXRzKTtcbiAgICAgICAgICAgIC8vIEludGVybGVhdmUgZGF0YSBiaXRzIHdpdGggZXJyb3IgY29ycmVjdGlvbiBjb2RlLlxuICAgICAgICAgICAgY29uc3QgZmluYWxCaXRzID0gdGhpcy5pbnRlcmxlYXZlV2l0aEVDQnl0ZXMoaGVhZGVyQW5kRGF0YUJpdHMsIHZlcnNpb24uZ2V0VG90YWxDb2Rld29yZHMoKSwgbnVtRGF0YUJ5dGVzLCBlY0Jsb2Nrcy5nZXROdW1CbG9ja3MoKSk7XG4gICAgICAgICAgICBjb25zdCBxckNvZGUgPSBuZXcgUVJDb2RlKCk7XG4gICAgICAgICAgICBxckNvZGUuc2V0RUNMZXZlbChlY0xldmVsKTtcbiAgICAgICAgICAgIHFyQ29kZS5zZXRNb2RlKG1vZGUpO1xuICAgICAgICAgICAgcXJDb2RlLnNldFZlcnNpb24odmVyc2lvbik7XG4gICAgICAgICAgICAvLyAgQ2hvb3NlIHRoZSBtYXNrIHBhdHRlcm4gYW5kIHNldCB0byBcInFyQ29kZVwiLlxuICAgICAgICAgICAgY29uc3QgZGltZW5zaW9uID0gdmVyc2lvbi5nZXREaW1lbnNpb25Gb3JWZXJzaW9uKCk7XG4gICAgICAgICAgICBjb25zdCBtYXRyaXggPSBuZXcgQnl0ZU1hdHJpeChkaW1lbnNpb24sIGRpbWVuc2lvbik7XG4gICAgICAgICAgICBjb25zdCBtYXNrUGF0dGVybiA9IHRoaXMuY2hvb3NlTWFza1BhdHRlcm4oZmluYWxCaXRzLCBlY0xldmVsLCB2ZXJzaW9uLCBtYXRyaXgpO1xuICAgICAgICAgICAgcXJDb2RlLnNldE1hc2tQYXR0ZXJuKG1hc2tQYXR0ZXJuKTtcbiAgICAgICAgICAgIC8vIEJ1aWxkIHRoZSBtYXRyaXggYW5kIHNldCBpdCB0byBcInFyQ29kZVwiLlxuICAgICAgICAgICAgTWF0cml4VXRpbC5idWlsZE1hdHJpeChmaW5hbEJpdHMsIGVjTGV2ZWwsIHZlcnNpb24sIG1hc2tQYXR0ZXJuLCBtYXRyaXgpO1xuICAgICAgICAgICAgcXJDb2RlLnNldE1hdHJpeChtYXRyaXgpO1xuICAgICAgICAgICAgcmV0dXJuIHFyQ29kZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjaWRlcyB0aGUgc21hbGxlc3QgdmVyc2lvbiBvZiBRUiBjb2RlIHRoYXQgd2lsbCBjb250YWluIGFsbCBvZiB0aGUgcHJvdmlkZWQgZGF0YS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHRocm93cyBXcml0ZXJFeGNlcHRpb24gaWYgdGhlIGRhdGEgY2Fubm90IGZpdCBpbiBhbnkgdmVyc2lvblxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIHJlY29tbWVuZFZlcnNpb24oZWNMZXZlbCwgbW9kZSwgaGVhZGVyQml0cywgZGF0YUJpdHMpIHtcbiAgICAgICAgICAgIC8vIEhhcmQgcGFydDogbmVlZCB0byBrbm93IHZlcnNpb24gdG8ga25vdyBob3cgbWFueSBiaXRzIGxlbmd0aCB0YWtlcy4gQnV0IG5lZWQgdG8ga25vdyBob3cgbWFueVxuICAgICAgICAgICAgLy8gYml0cyBpdCB0YWtlcyB0byBrbm93IHZlcnNpb24uIEZpcnN0IHdlIHRha2UgYSBndWVzcyBhdCB2ZXJzaW9uIGJ5IGFzc3VtaW5nIHZlcnNpb24gd2lsbCBiZVxuICAgICAgICAgICAgLy8gdGhlIG1pbmltdW0sIDE6XG4gICAgICAgICAgICBjb25zdCBwcm92aXNpb25hbEJpdHNOZWVkZWQgPSB0aGlzLmNhbGN1bGF0ZUJpdHNOZWVkZWQobW9kZSwgaGVhZGVyQml0cywgZGF0YUJpdHMsIFZlcnNpb24kMS5nZXRWZXJzaW9uRm9yTnVtYmVyKDEpKTtcbiAgICAgICAgICAgIGNvbnN0IHByb3Zpc2lvbmFsVmVyc2lvbiA9IHRoaXMuY2hvb3NlVmVyc2lvbihwcm92aXNpb25hbEJpdHNOZWVkZWQsIGVjTGV2ZWwpO1xuICAgICAgICAgICAgLy8gVXNlIHRoYXQgZ3Vlc3MgdG8gY2FsY3VsYXRlIHRoZSByaWdodCB2ZXJzaW9uLiBJIGFtIHN0aWxsIG5vdCBzdXJlIHRoaXMgd29ya3MgaW4gMTAwJSBvZiBjYXNlcy5cbiAgICAgICAgICAgIGNvbnN0IGJpdHNOZWVkZWQgPSB0aGlzLmNhbGN1bGF0ZUJpdHNOZWVkZWQobW9kZSwgaGVhZGVyQml0cywgZGF0YUJpdHMsIHByb3Zpc2lvbmFsVmVyc2lvbik7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jaG9vc2VWZXJzaW9uKGJpdHNOZWVkZWQsIGVjTGV2ZWwpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBjYWxjdWxhdGVCaXRzTmVlZGVkKG1vZGUsIGhlYWRlckJpdHMsIGRhdGFCaXRzLCB2ZXJzaW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gaGVhZGVyQml0cy5nZXRTaXplKCkgKyBtb2RlLmdldENoYXJhY3RlckNvdW50Qml0cyh2ZXJzaW9uKSArIGRhdGFCaXRzLmdldFNpemUoKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB0aGUgY29kZSBwb2ludCBvZiB0aGUgdGFibGUgdXNlZCBpbiBhbHBoYW51bWVyaWMgbW9kZSBvclxuICAgICAgICAgKiAgLTEgaWYgdGhlcmUgaXMgbm8gY29ycmVzcG9uZGluZyBjb2RlIGluIHRoZSB0YWJsZS5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBnZXRBbHBoYW51bWVyaWNDb2RlKGNvZGUgLyppbnQqLykge1xuICAgICAgICAgICAgaWYgKGNvZGUgPCBFbmNvZGVyLkFMUEhBTlVNRVJJQ19UQUJMRS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRW5jb2Rlci5BTFBIQU5VTUVSSUNfVEFCTEVbY29kZV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgIH1cbiAgICAgICAgLy8gcHVibGljIHN0YXRpYyBjaG9vc2VNb2RlKGNvbnRlbnQ6IHN0cmluZyk6IE1vZGUge1xuICAgICAgICAvLyAgIHJldHVybiBjaG9vc2VNb2RlKGNvbnRlbnQsIG51bGwpO1xuICAgICAgICAvLyB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDaG9vc2UgdGhlIGJlc3QgbW9kZSBieSBleGFtaW5pbmcgdGhlIGNvbnRlbnQuIE5vdGUgdGhhdCAnZW5jb2RpbmcnIGlzIHVzZWQgYXMgYSBoaW50O1xuICAgICAgICAgKiBpZiBpdCBpcyBTaGlmdF9KSVMsIGFuZCB0aGUgaW5wdXQgaXMgb25seSBkb3VibGUtYnl0ZSBLYW5qaSwgdGhlbiB3ZSByZXR1cm4ge0BsaW5rIE1vZGUjS0FOSkl9LlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGNob29zZU1vZGUoY29udGVudCwgZW5jb2RpbmcgPSBudWxsKSB7XG4gICAgICAgICAgICBpZiAoQ2hhcmFjdGVyU2V0RUNJLlNKSVMuZ2V0TmFtZSgpID09PSBlbmNvZGluZyAmJiB0aGlzLmlzT25seURvdWJsZUJ5dGVLYW5qaShjb250ZW50KSkge1xuICAgICAgICAgICAgICAgIC8vIENob29zZSBLYW5qaSBtb2RlIGlmIGFsbCBpbnB1dCBhcmUgZG91YmxlLWJ5dGUgY2hhcmFjdGVyc1xuICAgICAgICAgICAgICAgIHJldHVybiBNb2RlJDEuS0FOSkk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgaGFzTnVtZXJpYyA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGhhc0FscGhhbnVtZXJpYyA9IGZhbHNlO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGxlbmd0aCA9IGNvbnRlbnQubGVuZ3RoOyBpIDwgbGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjID0gY29udGVudC5jaGFyQXQoaSk7XG4gICAgICAgICAgICAgICAgaWYgKEVuY29kZXIuaXNEaWdpdChjKSkge1xuICAgICAgICAgICAgICAgICAgICBoYXNOdW1lcmljID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5nZXRBbHBoYW51bWVyaWNDb2RlKGMuY2hhckNvZGVBdCgwKSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc0FscGhhbnVtZXJpYyA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gTW9kZSQxLkJZVEU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGhhc0FscGhhbnVtZXJpYykge1xuICAgICAgICAgICAgICAgIHJldHVybiBNb2RlJDEuQUxQSEFOVU1FUklDO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGhhc051bWVyaWMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTW9kZSQxLk5VTUVSSUM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gTW9kZSQxLkJZVEU7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGlzT25seURvdWJsZUJ5dGVLYW5qaShjb250ZW50KSB7XG4gICAgICAgICAgICBsZXQgYnl0ZXM7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGJ5dGVzID0gU3RyaW5nRW5jb2RpbmcuZW5jb2RlKGNvbnRlbnQsIENoYXJhY3RlclNldEVDSS5TSklTKTsgLy8gY29udGVudC5nZXRCeXRlcyhcIlNoaWZ0X0pJU1wiKSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChpZ25vcmVkIC8qOiBVbnN1cHBvcnRlZEVuY29kaW5nRXhjZXB0aW9uKi8pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBsZW5ndGggPSBieXRlcy5sZW5ndGg7XG4gICAgICAgICAgICBpZiAobGVuZ3RoICUgMiAhPT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBieXRlMSA9IGJ5dGVzW2ldICYgMHhGRjtcbiAgICAgICAgICAgICAgICBpZiAoKGJ5dGUxIDwgMHg4MSB8fCBieXRlMSA+IDB4OUYpICYmIChieXRlMSA8IDB4RTAgfHwgYnl0ZTEgPiAweEVCKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGNob29zZU1hc2tQYXR0ZXJuKGJpdHMsIGVjTGV2ZWwsIHZlcnNpb24sIG1hdHJpeCkge1xuICAgICAgICAgICAgbGV0IG1pblBlbmFsdHkgPSBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUjsgLy8gTG93ZXIgcGVuYWx0eSBpcyBiZXR0ZXIuXG4gICAgICAgICAgICBsZXQgYmVzdE1hc2tQYXR0ZXJuID0gLTE7XG4gICAgICAgICAgICAvLyBXZSB0cnkgYWxsIG1hc2sgcGF0dGVybnMgdG8gY2hvb3NlIHRoZSBiZXN0IG9uZS5cbiAgICAgICAgICAgIGZvciAobGV0IG1hc2tQYXR0ZXJuID0gMDsgbWFza1BhdHRlcm4gPCBRUkNvZGUuTlVNX01BU0tfUEFUVEVSTlM7IG1hc2tQYXR0ZXJuKyspIHtcbiAgICAgICAgICAgICAgICBNYXRyaXhVdGlsLmJ1aWxkTWF0cml4KGJpdHMsIGVjTGV2ZWwsIHZlcnNpb24sIG1hc2tQYXR0ZXJuLCBtYXRyaXgpO1xuICAgICAgICAgICAgICAgIGxldCBwZW5hbHR5ID0gdGhpcy5jYWxjdWxhdGVNYXNrUGVuYWx0eShtYXRyaXgpO1xuICAgICAgICAgICAgICAgIGlmIChwZW5hbHR5IDwgbWluUGVuYWx0eSkge1xuICAgICAgICAgICAgICAgICAgICBtaW5QZW5hbHR5ID0gcGVuYWx0eTtcbiAgICAgICAgICAgICAgICAgICAgYmVzdE1hc2tQYXR0ZXJuID0gbWFza1BhdHRlcm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGJlc3RNYXNrUGF0dGVybjtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgY2hvb3NlVmVyc2lvbihudW1JbnB1dEJpdHMgLyppbnQqLywgZWNMZXZlbCkge1xuICAgICAgICAgICAgZm9yIChsZXQgdmVyc2lvbk51bSA9IDE7IHZlcnNpb25OdW0gPD0gNDA7IHZlcnNpb25OdW0rKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZlcnNpb24gPSBWZXJzaW9uJDEuZ2V0VmVyc2lvbkZvck51bWJlcih2ZXJzaW9uTnVtKTtcbiAgICAgICAgICAgICAgICBpZiAoRW5jb2Rlci53aWxsRml0KG51bUlucHV0Qml0cywgdmVyc2lvbiwgZWNMZXZlbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZlcnNpb247XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IFdyaXRlckV4Y2VwdGlvbignRGF0YSB0b28gYmlnJyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gdHJ1ZSBpZiB0aGUgbnVtYmVyIG9mIGlucHV0IGJpdHMgd2lsbCBmaXQgaW4gYSBjb2RlIHdpdGggdGhlIHNwZWNpZmllZCB2ZXJzaW9uIGFuZFxuICAgICAgICAgKiBlcnJvciBjb3JyZWN0aW9uIGxldmVsLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIHdpbGxGaXQobnVtSW5wdXRCaXRzIC8qaW50Ki8sIHZlcnNpb24sIGVjTGV2ZWwpIHtcbiAgICAgICAgICAgIC8vIEluIHRoZSBmb2xsb3dpbmcgY29tbWVudHMsIHdlIHVzZSBudW1iZXJzIG9mIFZlcnNpb24gNy1ILlxuICAgICAgICAgICAgLy8gbnVtQnl0ZXMgPSAxOTZcbiAgICAgICAgICAgIGNvbnN0IG51bUJ5dGVzID0gdmVyc2lvbi5nZXRUb3RhbENvZGV3b3JkcygpO1xuICAgICAgICAgICAgLy8gZ2V0TnVtRUNCeXRlcyA9IDEzMFxuICAgICAgICAgICAgY29uc3QgZWNCbG9ja3MgPSB2ZXJzaW9uLmdldEVDQmxvY2tzRm9yTGV2ZWwoZWNMZXZlbCk7XG4gICAgICAgICAgICBjb25zdCBudW1FY0J5dGVzID0gZWNCbG9ja3MuZ2V0VG90YWxFQ0NvZGV3b3JkcygpO1xuICAgICAgICAgICAgLy8gZ2V0TnVtRGF0YUJ5dGVzID0gMTk2IC0gMTMwID0gNjZcbiAgICAgICAgICAgIGNvbnN0IG51bURhdGFCeXRlcyA9IG51bUJ5dGVzIC0gbnVtRWNCeXRlcztcbiAgICAgICAgICAgIGNvbnN0IHRvdGFsSW5wdXRCeXRlcyA9IChudW1JbnB1dEJpdHMgKyA3KSAvIDg7XG4gICAgICAgICAgICByZXR1cm4gbnVtRGF0YUJ5dGVzID49IHRvdGFsSW5wdXRCeXRlcztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogVGVybWluYXRlIGJpdHMgYXMgZGVzY3JpYmVkIGluIDguNC44IGFuZCA4LjQuOSBvZiBKSVNYMDUxMDoyMDA0IChwLjI0KS5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyB0ZXJtaW5hdGVCaXRzKG51bURhdGFCeXRlcyAvKmludCovLCBiaXRzKSB7XG4gICAgICAgICAgICBjb25zdCBjYXBhY2l0eSA9IG51bURhdGFCeXRlcyAqIDg7XG4gICAgICAgICAgICBpZiAoYml0cy5nZXRTaXplKCkgPiBjYXBhY2l0eSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oJ2RhdGEgYml0cyBjYW5ub3QgZml0IGluIHRoZSBRUiBDb2RlJyArIGJpdHMuZ2V0U2l6ZSgpICsgJyA+ICcgK1xuICAgICAgICAgICAgICAgICAgICBjYXBhY2l0eSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDQgJiYgYml0cy5nZXRTaXplKCkgPCBjYXBhY2l0eTsgKytpKSB7XG4gICAgICAgICAgICAgICAgYml0cy5hcHBlbmRCaXQoZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQXBwZW5kIHRlcm1pbmF0aW9uIGJpdHMuIFNlZSA4LjQuOCBvZiBKSVNYMDUxMDoyMDA0IChwLjI0KSBmb3IgZGV0YWlscy5cbiAgICAgICAgICAgIC8vIElmIHRoZSBsYXN0IGJ5dGUgaXNuJ3QgOC1iaXQgYWxpZ25lZCwgd2UnbGwgYWRkIHBhZGRpbmcgYml0cy5cbiAgICAgICAgICAgIGNvbnN0IG51bUJpdHNJbkxhc3RCeXRlID0gYml0cy5nZXRTaXplKCkgJiAweDA3O1xuICAgICAgICAgICAgaWYgKG51bUJpdHNJbkxhc3RCeXRlID4gMCkge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBudW1CaXRzSW5MYXN0Qnl0ZTsgaSA8IDg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBiaXRzLmFwcGVuZEJpdChmYWxzZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSWYgd2UgaGF2ZSBtb3JlIHNwYWNlLCB3ZSdsbCBmaWxsIHRoZSBzcGFjZSB3aXRoIHBhZGRpbmcgcGF0dGVybnMgZGVmaW5lZCBpbiA4LjQuOSAocC4yNCkuXG4gICAgICAgICAgICBjb25zdCBudW1QYWRkaW5nQnl0ZXMgPSBudW1EYXRhQnl0ZXMgLSBiaXRzLmdldFNpemVJbkJ5dGVzKCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bVBhZGRpbmdCeXRlczsgKytpKSB7XG4gICAgICAgICAgICAgICAgYml0cy5hcHBlbmRCaXRzKChpICYgMHgwMSkgPT09IDAgPyAweEVDIDogMHgxMSwgOCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYml0cy5nZXRTaXplKCkgIT09IGNhcGFjaXR5KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdyaXRlckV4Y2VwdGlvbignQml0cyBzaXplIGRvZXMgbm90IGVxdWFsIGNhcGFjaXR5Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdldCBudW1iZXIgb2YgZGF0YSBieXRlcyBhbmQgbnVtYmVyIG9mIGVycm9yIGNvcnJlY3Rpb24gYnl0ZXMgZm9yIGJsb2NrIGlkIFwiYmxvY2tJRFwiLiBTdG9yZVxuICAgICAgICAgKiB0aGUgcmVzdWx0IGluIFwibnVtRGF0YUJ5dGVzSW5CbG9ja1wiLCBhbmQgXCJudW1FQ0J5dGVzSW5CbG9ja1wiLiBTZWUgdGFibGUgMTIgaW4gOC41LjEgb2ZcbiAgICAgICAgICogSklTWDA1MTA6MjAwNCAocC4zMClcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBnZXROdW1EYXRhQnl0ZXNBbmROdW1FQ0J5dGVzRm9yQmxvY2tJRChudW1Ub3RhbEJ5dGVzIC8qaW50Ki8sIG51bURhdGFCeXRlcyAvKmludCovLCBudW1SU0Jsb2NrcyAvKmludCovLCBibG9ja0lEIC8qaW50Ki8sIG51bURhdGFCeXRlc0luQmxvY2ssIG51bUVDQnl0ZXNJbkJsb2NrKSB7XG4gICAgICAgICAgICBpZiAoYmxvY2tJRCA+PSBudW1SU0Jsb2Nrcykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oJ0Jsb2NrIElEIHRvbyBsYXJnZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gbnVtUnNCbG9ja3NJbkdyb3VwMiA9IDE5NiAlIDUgPSAxXG4gICAgICAgICAgICBjb25zdCBudW1Sc0Jsb2Nrc0luR3JvdXAyID0gbnVtVG90YWxCeXRlcyAlIG51bVJTQmxvY2tzO1xuICAgICAgICAgICAgLy8gbnVtUnNCbG9ja3NJbkdyb3VwMSA9IDUgLSAxID0gNFxuICAgICAgICAgICAgY29uc3QgbnVtUnNCbG9ja3NJbkdyb3VwMSA9IG51bVJTQmxvY2tzIC0gbnVtUnNCbG9ja3NJbkdyb3VwMjtcbiAgICAgICAgICAgIC8vIG51bVRvdGFsQnl0ZXNJbkdyb3VwMSA9IDE5NiAvIDUgPSAzOVxuICAgICAgICAgICAgY29uc3QgbnVtVG90YWxCeXRlc0luR3JvdXAxID0gTWF0aC5mbG9vcihudW1Ub3RhbEJ5dGVzIC8gbnVtUlNCbG9ja3MpO1xuICAgICAgICAgICAgLy8gbnVtVG90YWxCeXRlc0luR3JvdXAyID0gMzkgKyAxID0gNDBcbiAgICAgICAgICAgIGNvbnN0IG51bVRvdGFsQnl0ZXNJbkdyb3VwMiA9IG51bVRvdGFsQnl0ZXNJbkdyb3VwMSArIDE7XG4gICAgICAgICAgICAvLyBudW1EYXRhQnl0ZXNJbkdyb3VwMSA9IDY2IC8gNSA9IDEzXG4gICAgICAgICAgICBjb25zdCBudW1EYXRhQnl0ZXNJbkdyb3VwMSA9IE1hdGguZmxvb3IobnVtRGF0YUJ5dGVzIC8gbnVtUlNCbG9ja3MpO1xuICAgICAgICAgICAgLy8gbnVtRGF0YUJ5dGVzSW5Hcm91cDIgPSAxMyArIDEgPSAxNFxuICAgICAgICAgICAgY29uc3QgbnVtRGF0YUJ5dGVzSW5Hcm91cDIgPSBudW1EYXRhQnl0ZXNJbkdyb3VwMSArIDE7XG4gICAgICAgICAgICAvLyBudW1FY0J5dGVzSW5Hcm91cDEgPSAzOSAtIDEzID0gMjZcbiAgICAgICAgICAgIGNvbnN0IG51bUVjQnl0ZXNJbkdyb3VwMSA9IG51bVRvdGFsQnl0ZXNJbkdyb3VwMSAtIG51bURhdGFCeXRlc0luR3JvdXAxO1xuICAgICAgICAgICAgLy8gbnVtRWNCeXRlc0luR3JvdXAyID0gNDAgLSAxNCA9IDI2XG4gICAgICAgICAgICBjb25zdCBudW1FY0J5dGVzSW5Hcm91cDIgPSBudW1Ub3RhbEJ5dGVzSW5Hcm91cDIgLSBudW1EYXRhQnl0ZXNJbkdyb3VwMjtcbiAgICAgICAgICAgIC8vIFNhbml0eSBjaGVja3MuXG4gICAgICAgICAgICAvLyAyNiA9IDI2XG4gICAgICAgICAgICBpZiAobnVtRWNCeXRlc0luR3JvdXAxICE9PSBudW1FY0J5dGVzSW5Hcm91cDIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKCdFQyBieXRlcyBtaXNtYXRjaCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gNSA9IDQgKyAxLlxuICAgICAgICAgICAgaWYgKG51bVJTQmxvY2tzICE9PSBudW1Sc0Jsb2Nrc0luR3JvdXAxICsgbnVtUnNCbG9ja3NJbkdyb3VwMikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oJ1JTIGJsb2NrcyBtaXNtYXRjaCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gMTk2ID0gKDEzICsgMjYpICogNCArICgxNCArIDI2KSAqIDFcbiAgICAgICAgICAgIGlmIChudW1Ub3RhbEJ5dGVzICE9PVxuICAgICAgICAgICAgICAgICgobnVtRGF0YUJ5dGVzSW5Hcm91cDEgKyBudW1FY0J5dGVzSW5Hcm91cDEpICpcbiAgICAgICAgICAgICAgICAgICAgbnVtUnNCbG9ja3NJbkdyb3VwMSkgK1xuICAgICAgICAgICAgICAgICAgICAoKG51bURhdGFCeXRlc0luR3JvdXAyICsgbnVtRWNCeXRlc0luR3JvdXAyKSAqXG4gICAgICAgICAgICAgICAgICAgICAgICBudW1Sc0Jsb2Nrc0luR3JvdXAyKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oJ1RvdGFsIGJ5dGVzIG1pc21hdGNoJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYmxvY2tJRCA8IG51bVJzQmxvY2tzSW5Hcm91cDEpIHtcbiAgICAgICAgICAgICAgICBudW1EYXRhQnl0ZXNJbkJsb2NrWzBdID0gbnVtRGF0YUJ5dGVzSW5Hcm91cDE7XG4gICAgICAgICAgICAgICAgbnVtRUNCeXRlc0luQmxvY2tbMF0gPSBudW1FY0J5dGVzSW5Hcm91cDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBudW1EYXRhQnl0ZXNJbkJsb2NrWzBdID0gbnVtRGF0YUJ5dGVzSW5Hcm91cDI7XG4gICAgICAgICAgICAgICAgbnVtRUNCeXRlc0luQmxvY2tbMF0gPSBudW1FY0J5dGVzSW5Hcm91cDI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEludGVybGVhdmUgXCJiaXRzXCIgd2l0aCBjb3JyZXNwb25kaW5nIGVycm9yIGNvcnJlY3Rpb24gYnl0ZXMuIE9uIHN1Y2Nlc3MsIHN0b3JlIHRoZSByZXN1bHQgaW5cbiAgICAgICAgICogXCJyZXN1bHRcIi4gVGhlIGludGVybGVhdmUgcnVsZSBpcyBjb21wbGljYXRlZC4gU2VlIDguNiBvZiBKSVNYMDUxMDoyMDA0IChwLjM3KSBmb3IgZGV0YWlscy5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBpbnRlcmxlYXZlV2l0aEVDQnl0ZXMoYml0cywgbnVtVG90YWxCeXRlcyAvKmludCovLCBudW1EYXRhQnl0ZXMgLyppbnQqLywgbnVtUlNCbG9ja3MgLyppbnQqLykge1xuICAgICAgICAgICAgLy8gXCJiaXRzXCIgbXVzdCBoYXZlIFwiZ2V0TnVtRGF0YUJ5dGVzXCIgYnl0ZXMgb2YgZGF0YS5cbiAgICAgICAgICAgIGlmIChiaXRzLmdldFNpemVJbkJ5dGVzKCkgIT09IG51bURhdGFCeXRlcykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oJ051bWJlciBvZiBiaXRzIGFuZCBkYXRhIGJ5dGVzIGRvZXMgbm90IG1hdGNoJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBTdGVwIDEuICBEaXZpZGUgZGF0YSBieXRlcyBpbnRvIGJsb2NrcyBhbmQgZ2VuZXJhdGUgZXJyb3IgY29ycmVjdGlvbiBieXRlcyBmb3IgdGhlbS4gV2UnbGxcbiAgICAgICAgICAgIC8vIHN0b3JlIHRoZSBkaXZpZGVkIGRhdGEgYnl0ZXMgYmxvY2tzIGFuZCBlcnJvciBjb3JyZWN0aW9uIGJ5dGVzIGJsb2NrcyBpbnRvIFwiYmxvY2tzXCIuXG4gICAgICAgICAgICBsZXQgZGF0YUJ5dGVzT2Zmc2V0ID0gMDtcbiAgICAgICAgICAgIGxldCBtYXhOdW1EYXRhQnl0ZXMgPSAwO1xuICAgICAgICAgICAgbGV0IG1heE51bUVjQnl0ZXMgPSAwO1xuICAgICAgICAgICAgLy8gU2luY2UsIHdlIGtub3cgdGhlIG51bWJlciBvZiByZWVkc29sbW9uIGJsb2Nrcywgd2UgY2FuIGluaXRpYWxpemUgdGhlIHZlY3RvciB3aXRoIHRoZSBudW1iZXIuXG4gICAgICAgICAgICBjb25zdCBibG9ja3MgPSBuZXcgQXJyYXkoKTsgLy8gbmV3IEFycmF5PEJsb2NrUGFpcj4obnVtUlNCbG9ja3MpXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bVJTQmxvY2tzOyArK2kpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBudW1EYXRhQnl0ZXNJbkJsb2NrID0gbmV3IEludDMyQXJyYXkoMSk7XG4gICAgICAgICAgICAgICAgY29uc3QgbnVtRWNCeXRlc0luQmxvY2sgPSBuZXcgSW50MzJBcnJheSgxKTtcbiAgICAgICAgICAgICAgICBFbmNvZGVyLmdldE51bURhdGFCeXRlc0FuZE51bUVDQnl0ZXNGb3JCbG9ja0lEKG51bVRvdGFsQnl0ZXMsIG51bURhdGFCeXRlcywgbnVtUlNCbG9ja3MsIGksIG51bURhdGFCeXRlc0luQmxvY2ssIG51bUVjQnl0ZXNJbkJsb2NrKTtcbiAgICAgICAgICAgICAgICBjb25zdCBzaXplID0gbnVtRGF0YUJ5dGVzSW5CbG9ja1swXTtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhQnl0ZXMgPSBuZXcgVWludDhBcnJheShzaXplKTtcbiAgICAgICAgICAgICAgICBiaXRzLnRvQnl0ZXMoOCAqIGRhdGFCeXRlc09mZnNldCwgZGF0YUJ5dGVzLCAwLCBzaXplKTtcbiAgICAgICAgICAgICAgICBjb25zdCBlY0J5dGVzID0gRW5jb2Rlci5nZW5lcmF0ZUVDQnl0ZXMoZGF0YUJ5dGVzLCBudW1FY0J5dGVzSW5CbG9ja1swXSk7XG4gICAgICAgICAgICAgICAgYmxvY2tzLnB1c2gobmV3IEJsb2NrUGFpcihkYXRhQnl0ZXMsIGVjQnl0ZXMpKTtcbiAgICAgICAgICAgICAgICBtYXhOdW1EYXRhQnl0ZXMgPSBNYXRoLm1heChtYXhOdW1EYXRhQnl0ZXMsIHNpemUpO1xuICAgICAgICAgICAgICAgIG1heE51bUVjQnl0ZXMgPSBNYXRoLm1heChtYXhOdW1FY0J5dGVzLCBlY0J5dGVzLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgZGF0YUJ5dGVzT2Zmc2V0ICs9IG51bURhdGFCeXRlc0luQmxvY2tbMF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobnVtRGF0YUJ5dGVzICE9PSBkYXRhQnl0ZXNPZmZzZXQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKCdEYXRhIGJ5dGVzIGRvZXMgbm90IG1hdGNoIG9mZnNldCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IEJpdEFycmF5KCk7XG4gICAgICAgICAgICAvLyBGaXJzdCwgcGxhY2UgZGF0YSBibG9ja3MuXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1heE51bURhdGFCeXRlczsgKytpKSB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBibG9jayBvZiBibG9ja3MpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGF0YUJ5dGVzID0gYmxvY2suZ2V0RGF0YUJ5dGVzKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpIDwgZGF0YUJ5dGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZEJpdHMoZGF0YUJ5dGVzW2ldLCA4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFRoZW4sIHBsYWNlIGVycm9yIGNvcnJlY3Rpb24gYmxvY2tzLlxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXhOdW1FY0J5dGVzOyArK2kpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGJsb2NrIG9mIGJsb2Nrcykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBlY0J5dGVzID0gYmxvY2suZ2V0RXJyb3JDb3JyZWN0aW9uQnl0ZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkgPCBlY0J5dGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZEJpdHMoZWNCeXRlc1tpXSwgOCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobnVtVG90YWxCeXRlcyAhPT0gcmVzdWx0LmdldFNpemVJbkJ5dGVzKCkpIHsgLy8gU2hvdWxkIGJlIHNhbWUuXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdyaXRlckV4Y2VwdGlvbignSW50ZXJsZWF2aW5nIGVycm9yOiAnICsgbnVtVG90YWxCeXRlcyArICcgYW5kICcgK1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQuZ2V0U2l6ZUluQnl0ZXMoKSArICcgZGlmZmVyLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZ2VuZXJhdGVFQ0J5dGVzKGRhdGFCeXRlcywgbnVtRWNCeXRlc0luQmxvY2sgLyppbnQqLykge1xuICAgICAgICAgICAgY29uc3QgbnVtRGF0YUJ5dGVzID0gZGF0YUJ5dGVzLmxlbmd0aDtcbiAgICAgICAgICAgIGNvbnN0IHRvRW5jb2RlID0gbmV3IEludDMyQXJyYXkobnVtRGF0YUJ5dGVzICsgbnVtRWNCeXRlc0luQmxvY2spOyAvLyBpbnRbbnVtRGF0YUJ5dGVzICsgbnVtRWNCeXRlc0luQmxvY2tdXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bURhdGFCeXRlczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdG9FbmNvZGVbaV0gPSBkYXRhQnl0ZXNbaV0gJiAweEZGO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbmV3IFJlZWRTb2xvbW9uRW5jb2RlcihHZW5lcmljR0YuUVJfQ09ERV9GSUVMRF8yNTYpLmVuY29kZSh0b0VuY29kZSwgbnVtRWNCeXRlc0luQmxvY2spO1xuICAgICAgICAgICAgY29uc3QgZWNCeXRlcyA9IG5ldyBVaW50OEFycmF5KG51bUVjQnl0ZXNJbkJsb2NrKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtRWNCeXRlc0luQmxvY2s7IGkrKykge1xuICAgICAgICAgICAgICAgIGVjQnl0ZXNbaV0gPSAvKihieXRlKSAqLyB0b0VuY29kZVtudW1EYXRhQnl0ZXMgKyBpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBlY0J5dGVzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBcHBlbmQgbW9kZSBpbmZvLiBPbiBzdWNjZXNzLCBzdG9yZSB0aGUgcmVzdWx0IGluIFwiYml0c1wiLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGFwcGVuZE1vZGVJbmZvKG1vZGUsIGJpdHMpIHtcbiAgICAgICAgICAgIGJpdHMuYXBwZW5kQml0cyhtb2RlLmdldEJpdHMoKSwgNCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEFwcGVuZCBsZW5ndGggaW5mby4gT24gc3VjY2Vzcywgc3RvcmUgdGhlIHJlc3VsdCBpbiBcImJpdHNcIi5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBhcHBlbmRMZW5ndGhJbmZvKG51bUxldHRlcnMgLyppbnQqLywgdmVyc2lvbiwgbW9kZSwgYml0cykge1xuICAgICAgICAgICAgY29uc3QgbnVtQml0cyA9IG1vZGUuZ2V0Q2hhcmFjdGVyQ291bnRCaXRzKHZlcnNpb24pO1xuICAgICAgICAgICAgaWYgKG51bUxldHRlcnMgPj0gKDEgPDwgbnVtQml0cykpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKG51bUxldHRlcnMgKyAnIGlzIGJpZ2dlciB0aGFuICcgKyAoKDEgPDwgbnVtQml0cykgLSAxKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBiaXRzLmFwcGVuZEJpdHMobnVtTGV0dGVycywgbnVtQml0cyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEFwcGVuZCBcImJ5dGVzXCIgaW4gXCJtb2RlXCIgbW9kZSAoZW5jb2RpbmcpIGludG8gXCJiaXRzXCIuIE9uIHN1Y2Nlc3MsIHN0b3JlIHRoZSByZXN1bHQgaW4gXCJiaXRzXCIuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgYXBwZW5kQnl0ZXMoY29udGVudCwgbW9kZSwgYml0cywgZW5jb2RpbmcpIHtcbiAgICAgICAgICAgIHN3aXRjaCAobW9kZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgTW9kZSQxLk5VTUVSSUM6XG4gICAgICAgICAgICAgICAgICAgIEVuY29kZXIuYXBwZW5kTnVtZXJpY0J5dGVzKGNvbnRlbnQsIGJpdHMpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIE1vZGUkMS5BTFBIQU5VTUVSSUM6XG4gICAgICAgICAgICAgICAgICAgIEVuY29kZXIuYXBwZW5kQWxwaGFudW1lcmljQnl0ZXMoY29udGVudCwgYml0cyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgTW9kZSQxLkJZVEU6XG4gICAgICAgICAgICAgICAgICAgIEVuY29kZXIuYXBwZW5kOEJpdEJ5dGVzKGNvbnRlbnQsIGJpdHMsIGVuY29kaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBNb2RlJDEuS0FOSkk6XG4gICAgICAgICAgICAgICAgICAgIEVuY29kZXIuYXBwZW5kS2FuamlCeXRlcyhjb250ZW50LCBiaXRzKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdyaXRlckV4Y2VwdGlvbignSW52YWxpZCBtb2RlOiAnICsgbW9kZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdldERpZ2l0KHNpbmdsZUNoYXJhY3Rlcikge1xuICAgICAgICAgICAgcmV0dXJuIHNpbmdsZUNoYXJhY3Rlci5jaGFyQ29kZUF0KDApIC0gNDg7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGlzRGlnaXQoc2luZ2xlQ2hhcmFjdGVyKSB7XG4gICAgICAgICAgICBjb25zdCBjbiA9IEVuY29kZXIuZ2V0RGlnaXQoc2luZ2xlQ2hhcmFjdGVyKTtcbiAgICAgICAgICAgIHJldHVybiBjbiA+PSAwICYmIGNuIDw9IDk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGFwcGVuZE51bWVyaWNCeXRlcyhjb250ZW50LCBiaXRzKSB7XG4gICAgICAgICAgICBjb25zdCBsZW5ndGggPSBjb250ZW50Lmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBpID0gMDtcbiAgICAgICAgICAgIHdoaWxlIChpIDwgbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbnVtMSA9IEVuY29kZXIuZ2V0RGlnaXQoY29udGVudC5jaGFyQXQoaSkpO1xuICAgICAgICAgICAgICAgIGlmIChpICsgMiA8IGxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBFbmNvZGUgdGhyZWUgbnVtZXJpYyBsZXR0ZXJzIGluIHRlbiBiaXRzLlxuICAgICAgICAgICAgICAgICAgICBjb25zdCBudW0yID0gRW5jb2Rlci5nZXREaWdpdChjb250ZW50LmNoYXJBdChpICsgMSkpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBudW0zID0gRW5jb2Rlci5nZXREaWdpdChjb250ZW50LmNoYXJBdChpICsgMikpO1xuICAgICAgICAgICAgICAgICAgICBiaXRzLmFwcGVuZEJpdHMobnVtMSAqIDEwMCArIG51bTIgKiAxMCArIG51bTMsIDEwKTtcbiAgICAgICAgICAgICAgICAgICAgaSArPSAzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChpICsgMSA8IGxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBFbmNvZGUgdHdvIG51bWVyaWMgbGV0dGVycyBpbiBzZXZlbiBiaXRzLlxuICAgICAgICAgICAgICAgICAgICBjb25zdCBudW0yID0gRW5jb2Rlci5nZXREaWdpdChjb250ZW50LmNoYXJBdChpICsgMSkpO1xuICAgICAgICAgICAgICAgICAgICBiaXRzLmFwcGVuZEJpdHMobnVtMSAqIDEwICsgbnVtMiwgNyk7XG4gICAgICAgICAgICAgICAgICAgIGkgKz0gMjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEVuY29kZSBvbmUgbnVtZXJpYyBsZXR0ZXIgaW4gZm91ciBiaXRzLlxuICAgICAgICAgICAgICAgICAgICBiaXRzLmFwcGVuZEJpdHMobnVtMSwgNCk7XG4gICAgICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGFwcGVuZEFscGhhbnVtZXJpY0J5dGVzKGNvbnRlbnQsIGJpdHMpIHtcbiAgICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IGNvbnRlbnQubGVuZ3RoO1xuICAgICAgICAgICAgbGV0IGkgPSAwO1xuICAgICAgICAgICAgd2hpbGUgKGkgPCBsZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb2RlMSA9IEVuY29kZXIuZ2V0QWxwaGFudW1lcmljQ29kZShjb250ZW50LmNoYXJDb2RlQXQoaSkpO1xuICAgICAgICAgICAgICAgIGlmIChjb2RlMSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdyaXRlckV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoaSArIDEgPCBsZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29kZTIgPSBFbmNvZGVyLmdldEFscGhhbnVtZXJpY0NvZGUoY29udGVudC5jaGFyQ29kZUF0KGkgKyAxKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb2RlMiA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBFbmNvZGUgdHdvIGFscGhhbnVtZXJpYyBsZXR0ZXJzIGluIDExIGJpdHMuXG4gICAgICAgICAgICAgICAgICAgIGJpdHMuYXBwZW5kQml0cyhjb2RlMSAqIDQ1ICsgY29kZTIsIDExKTtcbiAgICAgICAgICAgICAgICAgICAgaSArPSAyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRW5jb2RlIG9uZSBhbHBoYW51bWVyaWMgbGV0dGVyIGluIHNpeCBiaXRzLlxuICAgICAgICAgICAgICAgICAgICBiaXRzLmFwcGVuZEJpdHMoY29kZTEsIDYpO1xuICAgICAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBhcHBlbmQ4Qml0Qnl0ZXMoY29udGVudCwgYml0cywgZW5jb2RpbmcpIHtcbiAgICAgICAgICAgIGxldCBieXRlcztcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYnl0ZXMgPSBTdHJpbmdFbmNvZGluZy5lbmNvZGUoY29udGVudCwgZW5jb2RpbmcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKHVlZSAvKjogVW5zdXBwb3J0ZWRFbmNvZGluZ0V4Y2VwdGlvbiovKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdyaXRlckV4Y2VwdGlvbih1ZWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGxlbmd0aCA9IGJ5dGVzLmxlbmd0aDsgaSAhPT0gbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBiID0gYnl0ZXNbaV07XG4gICAgICAgICAgICAgICAgYml0cy5hcHBlbmRCaXRzKGIsIDgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAdGhyb3dzIFdyaXRlckV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGFwcGVuZEthbmppQnl0ZXMoY29udGVudCwgYml0cykge1xuICAgICAgICAgICAgbGV0IGJ5dGVzO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBieXRlcyA9IFN0cmluZ0VuY29kaW5nLmVuY29kZShjb250ZW50LCBDaGFyYWN0ZXJTZXRFQ0kuU0pJUyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAodWVlIC8qOiBVbnN1cHBvcnRlZEVuY29kaW5nRXhjZXB0aW9uKi8pIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKHVlZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBsZW5ndGggPSBieXRlcy5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAyKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYnl0ZTEgPSBieXRlc1tpXSAmIDB4RkY7XG4gICAgICAgICAgICAgICAgY29uc3QgYnl0ZTIgPSBieXRlc1tpICsgMV0gJiAweEZGO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvZGUgPSAoKGJ5dGUxIDw8IDgpICYgMHhGRkZGRkZGRikgfCBieXRlMjtcbiAgICAgICAgICAgICAgICBsZXQgc3VidHJhY3RlZCA9IC0xO1xuICAgICAgICAgICAgICAgIGlmIChjb2RlID49IDB4ODE0MCAmJiBjb2RlIDw9IDB4OWZmYykge1xuICAgICAgICAgICAgICAgICAgICBzdWJ0cmFjdGVkID0gY29kZSAtIDB4ODE0MDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoY29kZSA+PSAweGUwNDAgJiYgY29kZSA8PSAweGViYmYpIHtcbiAgICAgICAgICAgICAgICAgICAgc3VidHJhY3RlZCA9IGNvZGUgLSAweGMxNDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChzdWJ0cmFjdGVkID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKCdJbnZhbGlkIGJ5dGUgc2VxdWVuY2UnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgZW5jb2RlZCA9ICgoc3VidHJhY3RlZCA+PiA4KSAqIDB4YzApICsgKHN1YnRyYWN0ZWQgJiAweGZmKTtcbiAgICAgICAgICAgICAgICBiaXRzLmFwcGVuZEJpdHMoZW5jb2RlZCwgMTMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBhcHBlbmRFQ0koZWNpLCBiaXRzKSB7XG4gICAgICAgICAgICBiaXRzLmFwcGVuZEJpdHMoTW9kZSQxLkVDSS5nZXRCaXRzKCksIDQpO1xuICAgICAgICAgICAgLy8gVGhpcyBpcyBjb3JyZWN0IGZvciB2YWx1ZXMgdXAgdG8gMTI3LCB3aGljaCBpcyBhbGwgd2UgbmVlZCBub3cuXG4gICAgICAgICAgICBiaXRzLmFwcGVuZEJpdHMoZWNpLmdldFZhbHVlKCksIDgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIFRoZSBvcmlnaW5hbCB0YWJsZSBpcyBkZWZpbmVkIGluIHRoZSB0YWJsZSA1IG9mIEpJU1gwNTEwOjIwMDQgKHAuMTkpLlxuICAgIEVuY29kZXIuQUxQSEFOVU1FUklDX1RBQkxFID0gSW50MzJBcnJheS5mcm9tKFtcbiAgICAgICAgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsXG4gICAgICAgIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLFxuICAgICAgICAzNiwgLTEsIC0xLCAtMSwgMzcsIDM4LCAtMSwgLTEsIC0xLCAtMSwgMzksIDQwLCAtMSwgNDEsIDQyLCA0MyxcbiAgICAgICAgMCwgMSwgMiwgMywgNCwgNSwgNiwgNywgOCwgOSwgNDQsIC0xLCAtMSwgLTEsIC0xLCAtMSxcbiAgICAgICAgLTEsIDEwLCAxMSwgMTIsIDEzLCAxNCwgMTUsIDE2LCAxNywgMTgsIDE5LCAyMCwgMjEsIDIyLCAyMywgMjQsXG4gICAgICAgIDI1LCAyNiwgMjcsIDI4LCAyOSwgMzAsIDMxLCAzMiwgMzMsIDM0LCAzNSwgLTEsIC0xLCAtMSwgLTEsIC0xLFxuICAgIF0pO1xuICAgIEVuY29kZXIuREVGQVVMVF9CWVRFX01PREVfRU5DT0RJTkcgPSBDaGFyYWN0ZXJTZXRFQ0kuVVRGOC5nZXROYW1lKCk7IC8vIFwiSVNPLTg4NTktMVwiXG5cbiAgICAvKipcbiAgICAgKiBAZGVwcmVjYXRlZCBNb3ZpbmcgdG8gQHp4aW5nL2Jyb3dzZXJcbiAgICAgKi9cbiAgICBjbGFzcyBCcm93c2VyUVJDb2RlU3ZnV3JpdGVyIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdyaXRlcyBhbmQgcmVuZGVycyBhIFFSQ29kZSBTVkcgZWxlbWVudC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGNvbnRlbnRzXG4gICAgICAgICAqIEBwYXJhbSB3aWR0aFxuICAgICAgICAgKiBAcGFyYW0gaGVpZ2h0XG4gICAgICAgICAqIEBwYXJhbSBoaW50c1xuICAgICAgICAgKi9cbiAgICAgICAgd3JpdGUoY29udGVudHMsIHdpZHRoLCBoZWlnaHQsIGhpbnRzID0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKGNvbnRlbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ0ZvdW5kIGVtcHR5IGNvbnRlbnRzJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBpZiAoZm9ybWF0ICE9IEJhcmNvZGVGb3JtYXQuUVJfQ09ERSkge1xuICAgICAgICAgICAgLy8gICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKFwiQ2FuIG9ubHkgZW5jb2RlIFFSX0NPREUsIGJ1dCBnb3QgXCIgKyBmb3JtYXQpXG4gICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICBpZiAod2lkdGggPCAwIHx8IGhlaWdodCA8IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdSZXF1ZXN0ZWQgZGltZW5zaW9ucyBhcmUgdG9vIHNtYWxsOiAnICsgd2lkdGggKyAneCcgKyBoZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGVycm9yQ29ycmVjdGlvbkxldmVsID0gRXJyb3JDb3JyZWN0aW9uTGV2ZWwuTDtcbiAgICAgICAgICAgIGxldCBxdWlldFpvbmUgPSBCcm93c2VyUVJDb2RlU3ZnV3JpdGVyLlFVSUVUX1pPTkVfU0laRTtcbiAgICAgICAgICAgIGlmIChoaW50cyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGlmICh1bmRlZmluZWQgIT09IGhpbnRzLmdldChFbmNvZGVIaW50VHlwZSQxLkVSUk9SX0NPUlJFQ1RJT04pKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yQ29ycmVjdGlvbkxldmVsID0gRXJyb3JDb3JyZWN0aW9uTGV2ZWwuZnJvbVN0cmluZyhoaW50cy5nZXQoRW5jb2RlSGludFR5cGUkMS5FUlJPUl9DT1JSRUNUSU9OKS50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCAhPT0gaGludHMuZ2V0KEVuY29kZUhpbnRUeXBlJDEuTUFSR0lOKSkge1xuICAgICAgICAgICAgICAgICAgICBxdWlldFpvbmUgPSBOdW1iZXIucGFyc2VJbnQoaGludHMuZ2V0KEVuY29kZUhpbnRUeXBlJDEuTUFSR0lOKS50b1N0cmluZygpLCAxMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgY29kZSA9IEVuY29kZXIuZW5jb2RlKGNvbnRlbnRzLCBlcnJvckNvcnJlY3Rpb25MZXZlbCwgaGludHMpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVuZGVyUmVzdWx0KGNvZGUsIHdpZHRoLCBoZWlnaHQsIHF1aWV0Wm9uZSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJlbmRlcnMgdGhlIHJlc3VsdCBhbmQgdGhlbiBhcHBlbmRzIGl0IHRvIHRoZSBET00uXG4gICAgICAgICAqL1xuICAgICAgICB3cml0ZVRvRG9tKGNvbnRhaW5lckVsZW1lbnQsIGNvbnRlbnRzLCB3aWR0aCwgaGVpZ2h0LCBoaW50cyA9IG51bGwpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY29udGFpbmVyRWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBjb250YWluZXJFbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcihjb250YWluZXJFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHN2Z0VsZW1lbnQgPSB0aGlzLndyaXRlKGNvbnRlbnRzLCB3aWR0aCwgaGVpZ2h0LCBoaW50cyk7XG4gICAgICAgICAgICBpZiAoY29udGFpbmVyRWxlbWVudClcbiAgICAgICAgICAgICAgICBjb250YWluZXJFbGVtZW50LmFwcGVuZENoaWxkKHN2Z0VsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBOb3RlIHRoYXQgdGhlIGlucHV0IG1hdHJpeCB1c2VzIDAgPT0gd2hpdGUsIDEgPT0gYmxhY2suXG4gICAgICAgICAqIFRoZSBvdXRwdXQgbWF0cml4IHVzZXMgMCA9PSBibGFjaywgMjU1ID09IHdoaXRlIChpLmUuIGFuIDggYml0IGdyZXlzY2FsZSBiaXRtYXApLlxuICAgICAgICAgKi9cbiAgICAgICAgcmVuZGVyUmVzdWx0KGNvZGUsIHdpZHRoIC8qaW50Ki8sIGhlaWdodCAvKmludCovLCBxdWlldFpvbmUgLyppbnQqLykge1xuICAgICAgICAgICAgY29uc3QgaW5wdXQgPSBjb2RlLmdldE1hdHJpeCgpO1xuICAgICAgICAgICAgaWYgKGlucHV0ID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgaW5wdXRXaWR0aCA9IGlucHV0LmdldFdpZHRoKCk7XG4gICAgICAgICAgICBjb25zdCBpbnB1dEhlaWdodCA9IGlucHV0LmdldEhlaWdodCgpO1xuICAgICAgICAgICAgY29uc3QgcXJXaWR0aCA9IGlucHV0V2lkdGggKyAocXVpZXRab25lICogMik7XG4gICAgICAgICAgICBjb25zdCBxckhlaWdodCA9IGlucHV0SGVpZ2h0ICsgKHF1aWV0Wm9uZSAqIDIpO1xuICAgICAgICAgICAgY29uc3Qgb3V0cHV0V2lkdGggPSBNYXRoLm1heCh3aWR0aCwgcXJXaWR0aCk7XG4gICAgICAgICAgICBjb25zdCBvdXRwdXRIZWlnaHQgPSBNYXRoLm1heChoZWlnaHQsIHFySGVpZ2h0KTtcbiAgICAgICAgICAgIGNvbnN0IG11bHRpcGxlID0gTWF0aC5taW4oTWF0aC5mbG9vcihvdXRwdXRXaWR0aCAvIHFyV2lkdGgpLCBNYXRoLmZsb29yKG91dHB1dEhlaWdodCAvIHFySGVpZ2h0KSk7XG4gICAgICAgICAgICAvLyBQYWRkaW5nIGluY2x1ZGVzIGJvdGggdGhlIHF1aWV0IHpvbmUgYW5kIHRoZSBleHRyYSB3aGl0ZSBwaXhlbHMgdG8gYWNjb21tb2RhdGUgdGhlIHJlcXVlc3RlZFxuICAgICAgICAgICAgLy8gZGltZW5zaW9ucy4gRm9yIGV4YW1wbGUsIGlmIGlucHV0IGlzIDI1eDI1IHRoZSBRUiB3aWxsIGJlIDMzeDMzIGluY2x1ZGluZyB0aGUgcXVpZXQgem9uZS5cbiAgICAgICAgICAgIC8vIElmIHRoZSByZXF1ZXN0ZWQgc2l6ZSBpcyAyMDB4MTYwLCB0aGUgbXVsdGlwbGUgd2lsbCBiZSA0LCBmb3IgYSBRUiBvZiAxMzJ4MTMyLiBUaGVzZSB3aWxsXG4gICAgICAgICAgICAvLyBoYW5kbGUgYWxsIHRoZSBwYWRkaW5nIGZyb20gMTAweDEwMCAodGhlIGFjdHVhbCBRUikgdXAgdG8gMjAweDE2MC5cbiAgICAgICAgICAgIGNvbnN0IGxlZnRQYWRkaW5nID0gTWF0aC5mbG9vcigob3V0cHV0V2lkdGggLSAoaW5wdXRXaWR0aCAqIG11bHRpcGxlKSkgLyAyKTtcbiAgICAgICAgICAgIGNvbnN0IHRvcFBhZGRpbmcgPSBNYXRoLmZsb29yKChvdXRwdXRIZWlnaHQgLSAoaW5wdXRIZWlnaHQgKiBtdWx0aXBsZSkpIC8gMik7XG4gICAgICAgICAgICBjb25zdCBzdmdFbGVtZW50ID0gdGhpcy5jcmVhdGVTVkdFbGVtZW50KG91dHB1dFdpZHRoLCBvdXRwdXRIZWlnaHQpO1xuICAgICAgICAgICAgZm9yIChsZXQgaW5wdXRZID0gMCwgb3V0cHV0WSA9IHRvcFBhZGRpbmc7IGlucHV0WSA8IGlucHV0SGVpZ2h0OyBpbnB1dFkrKywgb3V0cHV0WSArPSBtdWx0aXBsZSkge1xuICAgICAgICAgICAgICAgIC8vIFdyaXRlIHRoZSBjb250ZW50cyBvZiB0aGlzIHJvdyBvZiB0aGUgYmFyY29kZVxuICAgICAgICAgICAgICAgIGZvciAobGV0IGlucHV0WCA9IDAsIG91dHB1dFggPSBsZWZ0UGFkZGluZzsgaW5wdXRYIDwgaW5wdXRXaWR0aDsgaW5wdXRYKyssIG91dHB1dFggKz0gbXVsdGlwbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0LmdldChpbnB1dFgsIGlucHV0WSkgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN2Z1JlY3RFbGVtZW50ID0gdGhpcy5jcmVhdGVTdmdSZWN0RWxlbWVudChvdXRwdXRYLCBvdXRwdXRZLCBtdWx0aXBsZSwgbXVsdGlwbGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3ZnRWxlbWVudC5hcHBlbmRDaGlsZChzdmdSZWN0RWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc3ZnRWxlbWVudDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIFNWRyBlbGVtZW50LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gdyBTVkcncyB3aWR0aCBhdHRyaWJ1dGVcbiAgICAgICAgICogQHBhcmFtIGggU1ZHJ3MgaGVpZ2h0IGF0dHJpYnV0ZVxuICAgICAgICAgKi9cbiAgICAgICAgY3JlYXRlU1ZHRWxlbWVudCh3LCBoKSB7XG4gICAgICAgICAgICBjb25zdCBzdmdFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKEJyb3dzZXJRUkNvZGVTdmdXcml0ZXIuU1ZHX05TLCAnc3ZnJyk7XG4gICAgICAgICAgICBzdmdFbGVtZW50LnNldEF0dHJpYnV0ZU5TKG51bGwsICdoZWlnaHQnLCB3LnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgc3ZnRWxlbWVudC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAnd2lkdGgnLCBoLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgcmV0dXJuIHN2Z0VsZW1lbnQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBTVkcgcmVjdCBlbGVtZW50LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0geCBFbGVtZW50J3MgeCBjb29yZGluYXRlXG4gICAgICAgICAqIEBwYXJhbSB5IEVsZW1lbnQncyB5IGNvb3JkaW5hdGVcbiAgICAgICAgICogQHBhcmFtIHcgRWxlbWVudCdzIHdpZHRoIGF0dHJpYnV0ZVxuICAgICAgICAgKiBAcGFyYW0gaCBFbGVtZW50J3MgaGVpZ2h0IGF0dHJpYnV0ZVxuICAgICAgICAgKi9cbiAgICAgICAgY3JlYXRlU3ZnUmVjdEVsZW1lbnQoeCwgeSwgdywgaCkge1xuICAgICAgICAgICAgY29uc3QgcmVjdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhCcm93c2VyUVJDb2RlU3ZnV3JpdGVyLlNWR19OUywgJ3JlY3QnKTtcbiAgICAgICAgICAgIHJlY3Quc2V0QXR0cmlidXRlTlMobnVsbCwgJ3gnLCB4LnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgcmVjdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAneScsIHkudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICByZWN0LnNldEF0dHJpYnV0ZU5TKG51bGwsICdoZWlnaHQnLCB3LnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgcmVjdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAnd2lkdGgnLCBoLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgcmVjdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAnZmlsbCcsICcjMDAwMDAwJyk7XG4gICAgICAgICAgICByZXR1cm4gcmVjdDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBCcm93c2VyUVJDb2RlU3ZnV3JpdGVyLlFVSUVUX1pPTkVfU0laRSA9IDQ7XG4gICAgLyoqXG4gICAgICogU1ZHIG1hcmt1cCBOYW1lU3BhY2VcbiAgICAgKi9cbiAgICBCcm93c2VyUVJDb2RlU3ZnV3JpdGVyLlNWR19OUyA9ICdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Zyc7XG5cbiAgICAvKmltcG9ydCBqYXZhLnV0aWwuTWFwOyovXG4gICAgLyoqXG4gICAgICogVGhpcyBvYmplY3QgcmVuZGVycyBhIFFSIENvZGUgYXMgYSBCaXRNYXRyaXggMkQgYXJyYXkgb2YgZ3JleXNjYWxlIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pXG4gICAgICovXG4gICAgY2xhc3MgUVJDb2RlV3JpdGVyIHtcbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICAvLyBwdWJsaWMgZW5jb2RlKGNvbnRlbnRzOiBzdHJpbmcsIGZvcm1hdDogQmFyY29kZUZvcm1hdCwgd2lkdGg6IG51bWJlciAvKmludCovLCBoZWlnaHQ6IG51bWJlciAvKmludCovKTogQml0TWF0cml4XG4gICAgICAgIC8vICAgICAvKnRocm93cyBXcml0ZXJFeGNlcHRpb24gKi8ge1xuICAgICAgICAvLyAgIHJldHVybiBlbmNvZGUoY29udGVudHMsIGZvcm1hdCwgd2lkdGgsIGhlaWdodCwgbnVsbClcbiAgICAgICAgLy8gfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGVuY29kZShjb250ZW50cywgZm9ybWF0LCB3aWR0aCAvKmludCovLCBoZWlnaHQgLyppbnQqLywgaGludHMpIHtcbiAgICAgICAgICAgIGlmIChjb250ZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdGb3VuZCBlbXB0eSBjb250ZW50cycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZvcm1hdCAhPT0gQmFyY29kZUZvcm1hdCQxLlFSX0NPREUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdDYW4gb25seSBlbmNvZGUgUVJfQ09ERSwgYnV0IGdvdCAnICsgZm9ybWF0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh3aWR0aCA8IDAgfHwgaGVpZ2h0IDwgMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oYFJlcXVlc3RlZCBkaW1lbnNpb25zIGFyZSB0b28gc21hbGw6ICR7d2lkdGh9eCR7aGVpZ2h0fWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGVycm9yQ29ycmVjdGlvbkxldmVsID0gRXJyb3JDb3JyZWN0aW9uTGV2ZWwuTDtcbiAgICAgICAgICAgIGxldCBxdWlldFpvbmUgPSBRUkNvZGVXcml0ZXIuUVVJRVRfWk9ORV9TSVpFO1xuICAgICAgICAgICAgaWYgKGhpbnRzICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCAhPT0gaGludHMuZ2V0KEVuY29kZUhpbnRUeXBlJDEuRVJST1JfQ09SUkVDVElPTikpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JDb3JyZWN0aW9uTGV2ZWwgPSBFcnJvckNvcnJlY3Rpb25MZXZlbC5mcm9tU3RyaW5nKGhpbnRzLmdldChFbmNvZGVIaW50VHlwZSQxLkVSUk9SX0NPUlJFQ1RJT04pLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodW5kZWZpbmVkICE9PSBoaW50cy5nZXQoRW5jb2RlSGludFR5cGUkMS5NQVJHSU4pKSB7XG4gICAgICAgICAgICAgICAgICAgIHF1aWV0Wm9uZSA9IE51bWJlci5wYXJzZUludChoaW50cy5nZXQoRW5jb2RlSGludFR5cGUkMS5NQVJHSU4pLnRvU3RyaW5nKCksIDEwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBjb2RlID0gRW5jb2Rlci5lbmNvZGUoY29udGVudHMsIGVycm9yQ29ycmVjdGlvbkxldmVsLCBoaW50cyk7XG4gICAgICAgICAgICByZXR1cm4gUVJDb2RlV3JpdGVyLnJlbmRlclJlc3VsdChjb2RlLCB3aWR0aCwgaGVpZ2h0LCBxdWlldFpvbmUpO1xuICAgICAgICB9XG4gICAgICAgIC8vIE5vdGUgdGhhdCB0aGUgaW5wdXQgbWF0cml4IHVzZXMgMCA9PSB3aGl0ZSwgMSA9PSBibGFjaywgd2hpbGUgdGhlIG91dHB1dCBtYXRyaXggdXNlc1xuICAgICAgICAvLyAwID09IGJsYWNrLCAyNTUgPT0gd2hpdGUgKGkuZS4gYW4gOCBiaXQgZ3JleXNjYWxlIGJpdG1hcCkuXG4gICAgICAgIHN0YXRpYyByZW5kZXJSZXN1bHQoY29kZSwgd2lkdGggLyppbnQqLywgaGVpZ2h0IC8qaW50Ki8sIHF1aWV0Wm9uZSAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBpbnB1dCA9IGNvZGUuZ2V0TWF0cml4KCk7XG4gICAgICAgICAgICBpZiAoaW5wdXQgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBpbnB1dFdpZHRoID0gaW5wdXQuZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGNvbnN0IGlucHV0SGVpZ2h0ID0gaW5wdXQuZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICBjb25zdCBxcldpZHRoID0gaW5wdXRXaWR0aCArIChxdWlldFpvbmUgKiAyKTtcbiAgICAgICAgICAgIGNvbnN0IHFySGVpZ2h0ID0gaW5wdXRIZWlnaHQgKyAocXVpZXRab25lICogMik7XG4gICAgICAgICAgICBjb25zdCBvdXRwdXRXaWR0aCA9IE1hdGgubWF4KHdpZHRoLCBxcldpZHRoKTtcbiAgICAgICAgICAgIGNvbnN0IG91dHB1dEhlaWdodCA9IE1hdGgubWF4KGhlaWdodCwgcXJIZWlnaHQpO1xuICAgICAgICAgICAgY29uc3QgbXVsdGlwbGUgPSBNYXRoLm1pbihNYXRoLmZsb29yKG91dHB1dFdpZHRoIC8gcXJXaWR0aCksIE1hdGguZmxvb3Iob3V0cHV0SGVpZ2h0IC8gcXJIZWlnaHQpKTtcbiAgICAgICAgICAgIC8vIFBhZGRpbmcgaW5jbHVkZXMgYm90aCB0aGUgcXVpZXQgem9uZSBhbmQgdGhlIGV4dHJhIHdoaXRlIHBpeGVscyB0byBhY2NvbW1vZGF0ZSB0aGUgcmVxdWVzdGVkXG4gICAgICAgICAgICAvLyBkaW1lbnNpb25zLiBGb3IgZXhhbXBsZSwgaWYgaW5wdXQgaXMgMjV4MjUgdGhlIFFSIHdpbGwgYmUgMzN4MzMgaW5jbHVkaW5nIHRoZSBxdWlldCB6b25lLlxuICAgICAgICAgICAgLy8gSWYgdGhlIHJlcXVlc3RlZCBzaXplIGlzIDIwMHgxNjAsIHRoZSBtdWx0aXBsZSB3aWxsIGJlIDQsIGZvciBhIFFSIG9mIDEzMngxMzIuIFRoZXNlIHdpbGxcbiAgICAgICAgICAgIC8vIGhhbmRsZSBhbGwgdGhlIHBhZGRpbmcgZnJvbSAxMDB4MTAwICh0aGUgYWN0dWFsIFFSKSB1cCB0byAyMDB4MTYwLlxuICAgICAgICAgICAgY29uc3QgbGVmdFBhZGRpbmcgPSBNYXRoLmZsb29yKChvdXRwdXRXaWR0aCAtIChpbnB1dFdpZHRoICogbXVsdGlwbGUpKSAvIDIpO1xuICAgICAgICAgICAgY29uc3QgdG9wUGFkZGluZyA9IE1hdGguZmxvb3IoKG91dHB1dEhlaWdodCAtIChpbnB1dEhlaWdodCAqIG11bHRpcGxlKSkgLyAyKTtcbiAgICAgICAgICAgIGNvbnN0IG91dHB1dCA9IG5ldyBCaXRNYXRyaXgob3V0cHV0V2lkdGgsIG91dHB1dEhlaWdodCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpbnB1dFkgPSAwLCBvdXRwdXRZID0gdG9wUGFkZGluZzsgaW5wdXRZIDwgaW5wdXRIZWlnaHQ7IGlucHV0WSsrLCBvdXRwdXRZICs9IG11bHRpcGxlKSB7XG4gICAgICAgICAgICAgICAgLy8gV3JpdGUgdGhlIGNvbnRlbnRzIG9mIHRoaXMgcm93IG9mIHRoZSBiYXJjb2RlXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaW5wdXRYID0gMCwgb3V0cHV0WCA9IGxlZnRQYWRkaW5nOyBpbnB1dFggPCBpbnB1dFdpZHRoOyBpbnB1dFgrKywgb3V0cHV0WCArPSBtdWx0aXBsZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXQuZ2V0KGlucHV0WCwgaW5wdXRZKSA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnNldFJlZ2lvbihvdXRwdXRYLCBvdXRwdXRZLCBtdWx0aXBsZSwgbXVsdGlwbGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dHB1dDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBRUkNvZGVXcml0ZXIuUVVJRVRfWk9ORV9TSVpFID0gNDtcblxuICAgIC8qaW1wb3J0IGphdmEudXRpbC5NYXA7Ki9cbiAgICAvKipcbiAgICAgKiBUaGlzIGlzIGEgZmFjdG9yeSBjbGFzcyB3aGljaCBmaW5kcyB0aGUgYXBwcm9wcmlhdGUgV3JpdGVyIHN1YmNsYXNzIGZvciB0aGUgQmFyY29kZUZvcm1hdFxuICAgICAqIHJlcXVlc3RlZCBhbmQgZW5jb2RlcyB0aGUgYmFyY29kZSB3aXRoIHRoZSBzdXBwbGllZCBjb250ZW50cy5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pXG4gICAgICovXG4gICAgY2xhc3MgTXVsdGlGb3JtYXRXcml0ZXIge1xuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIC8vIHB1YmxpYyBlbmNvZGUoY29udGVudHM6IHN0cmluZyxcbiAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0OiBCYXJjb2RlRm9ybWF0LFxuICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogbnVtYmVyIC8qaW50Ki8sXG4gICAgICAgIC8vICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogbnVtYmVyIC8qaW50Ki8pOiBCaXRNYXRyaXggLyp0aHJvd3MgV3JpdGVyRXhjZXB0aW9uICovIHtcbiAgICAgICAgLy8gICByZXR1cm4gZW5jb2RlKGNvbnRlbnRzLCBmb3JtYXQsIHdpZHRoLCBoZWlnaHQsIG51bGwpXG4gICAgICAgIC8vIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBlbmNvZGUoY29udGVudHMsIGZvcm1hdCwgd2lkdGggLyppbnQqLywgaGVpZ2h0IC8qaW50Ki8sIGhpbnRzKSB7XG4gICAgICAgICAgICBsZXQgd3JpdGVyO1xuICAgICAgICAgICAgc3dpdGNoIChmb3JtYXQpIHtcbiAgICAgICAgICAgICAgICAvLyBjYXNlIEJhcmNvZGVGb3JtYXQuRUFOXzg6XG4gICAgICAgICAgICAgICAgLy8gICB3cml0ZXIgPSBuZXcgRUFOOFdyaXRlcigpXG4gICAgICAgICAgICAgICAgLy8gICBicmVha1xuICAgICAgICAgICAgICAgIC8vIGNhc2UgQmFyY29kZUZvcm1hdC5VUENfRTpcbiAgICAgICAgICAgICAgICAvLyAgIHdyaXRlciA9IG5ldyBVUENFV3JpdGVyKClcbiAgICAgICAgICAgICAgICAvLyAgIGJyZWFrXG4gICAgICAgICAgICAgICAgLy8gY2FzZSBCYXJjb2RlRm9ybWF0LkVBTl8xMzpcbiAgICAgICAgICAgICAgICAvLyAgIHdyaXRlciA9IG5ldyBFQU4xM1dyaXRlcigpXG4gICAgICAgICAgICAgICAgLy8gICBicmVha1xuICAgICAgICAgICAgICAgIC8vIGNhc2UgQmFyY29kZUZvcm1hdC5VUENfQTpcbiAgICAgICAgICAgICAgICAvLyAgIHdyaXRlciA9IG5ldyBVUENBV3JpdGVyKClcbiAgICAgICAgICAgICAgICAvLyAgIGJyZWFrXG4gICAgICAgICAgICAgICAgY2FzZSBCYXJjb2RlRm9ybWF0JDEuUVJfQ09ERTpcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVyID0gbmV3IFFSQ29kZVdyaXRlcigpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAvLyBjYXNlIEJhcmNvZGVGb3JtYXQuQ09ERV8zOTpcbiAgICAgICAgICAgICAgICAvLyAgIHdyaXRlciA9IG5ldyBDb2RlMzlXcml0ZXIoKVxuICAgICAgICAgICAgICAgIC8vICAgYnJlYWtcbiAgICAgICAgICAgICAgICAvLyBjYXNlIEJhcmNvZGVGb3JtYXQuQ09ERV85MzpcbiAgICAgICAgICAgICAgICAvLyAgIHdyaXRlciA9IG5ldyBDb2RlOTNXcml0ZXIoKVxuICAgICAgICAgICAgICAgIC8vICAgYnJlYWtcbiAgICAgICAgICAgICAgICAvLyBjYXNlIEJhcmNvZGVGb3JtYXQuQ09ERV8xMjg6XG4gICAgICAgICAgICAgICAgLy8gICB3cml0ZXIgPSBuZXcgQ29kZTEyOFdyaXRlcigpXG4gICAgICAgICAgICAgICAgLy8gICBicmVha1xuICAgICAgICAgICAgICAgIC8vIGNhc2UgQmFyY29kZUZvcm1hdC5JVEY6XG4gICAgICAgICAgICAgICAgLy8gICB3cml0ZXIgPSBuZXcgSVRGV3JpdGVyKClcbiAgICAgICAgICAgICAgICAvLyAgIGJyZWFrXG4gICAgICAgICAgICAgICAgLy8gY2FzZSBCYXJjb2RlRm9ybWF0LlBERl80MTc6XG4gICAgICAgICAgICAgICAgLy8gICB3cml0ZXIgPSBuZXcgUERGNDE3V3JpdGVyKClcbiAgICAgICAgICAgICAgICAvLyAgIGJyZWFrXG4gICAgICAgICAgICAgICAgLy8gY2FzZSBCYXJjb2RlRm9ybWF0LkNPREFCQVI6XG4gICAgICAgICAgICAgICAgLy8gICB3cml0ZXIgPSBuZXcgQ29kYUJhcldyaXRlcigpXG4gICAgICAgICAgICAgICAgLy8gICBicmVha1xuICAgICAgICAgICAgICAgIC8vIGNhc2UgQmFyY29kZUZvcm1hdC5EQVRBX01BVFJJWDpcbiAgICAgICAgICAgICAgICAvLyAgIHdyaXRlciA9IG5ldyBEYXRhTWF0cml4V3JpdGVyKClcbiAgICAgICAgICAgICAgICAvLyAgIGJyZWFrXG4gICAgICAgICAgICAgICAgLy8gY2FzZSBCYXJjb2RlRm9ybWF0LkFaVEVDOlxuICAgICAgICAgICAgICAgIC8vICAgd3JpdGVyID0gbmV3IEF6dGVjV3JpdGVyKClcbiAgICAgICAgICAgICAgICAvLyAgIGJyZWFrXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignTm8gZW5jb2RlciBhdmFpbGFibGUgZm9yIGZvcm1hdCAnICsgZm9ybWF0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB3cml0ZXIuZW5jb2RlKGNvbnRlbnRzLCBmb3JtYXQsIHdpZHRoLCBoZWlnaHQsIGhpbnRzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDkgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogVGhpcyBvYmplY3QgZXh0ZW5kcyBMdW1pbmFuY2VTb3VyY2UgYXJvdW5kIGFuIGFycmF5IG9mIFlVViBkYXRhIHJldHVybmVkIGZyb20gdGhlIGNhbWVyYSBkcml2ZXIsXG4gICAgICogd2l0aCB0aGUgb3B0aW9uIHRvIGNyb3AgdG8gYSByZWN0YW5nbGUgd2l0aGluIHRoZSBmdWxsIGRhdGEuIFRoaXMgY2FuIGJlIHVzZWQgdG8gZXhjbHVkZVxuICAgICAqIHN1cGVyZmx1b3VzIHBpeGVscyBhcm91bmQgdGhlIHBlcmltZXRlciBhbmQgc3BlZWQgdXAgZGVjb2RpbmcuXG4gICAgICpcbiAgICAgKiBJdCB3b3JrcyBmb3IgYW55IHBpeGVsIGZvcm1hdCB3aGVyZSB0aGUgWSBjaGFubmVsIGlzIHBsYW5hciBhbmQgYXBwZWFycyBmaXJzdCwgaW5jbHVkaW5nXG4gICAgICogWUNiQ3JfNDIwX1NQIGFuZCBZQ2JDcl80MjJfU1AuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIGRzd2l0a2luQGdvb2dsZS5jb20gKERhbmllbCBTd2l0a2luKVxuICAgICAqL1xuICAgIGNsYXNzIFBsYW5hcllVVkx1bWluYW5jZVNvdXJjZSBleHRlbmRzIEx1bWluYW5jZVNvdXJjZSB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHl1dkRhdGEsIGRhdGFXaWR0aCAvKmludCovLCBkYXRhSGVpZ2h0IC8qaW50Ki8sIGxlZnQgLyppbnQqLywgdG9wIC8qaW50Ki8sIHdpZHRoIC8qaW50Ki8sIGhlaWdodCAvKmludCovLCByZXZlcnNlSG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgc3VwZXIod2lkdGgsIGhlaWdodCk7XG4gICAgICAgICAgICB0aGlzLnl1dkRhdGEgPSB5dXZEYXRhO1xuICAgICAgICAgICAgdGhpcy5kYXRhV2lkdGggPSBkYXRhV2lkdGg7XG4gICAgICAgICAgICB0aGlzLmRhdGFIZWlnaHQgPSBkYXRhSGVpZ2h0O1xuICAgICAgICAgICAgdGhpcy5sZWZ0ID0gbGVmdDtcbiAgICAgICAgICAgIHRoaXMudG9wID0gdG9wO1xuICAgICAgICAgICAgaWYgKGxlZnQgKyB3aWR0aCA+IGRhdGFXaWR0aCB8fCB0b3AgKyBoZWlnaHQgPiBkYXRhSGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignQ3JvcCByZWN0YW5nbGUgZG9lcyBub3QgZml0IHdpdGhpbiBpbWFnZSBkYXRhLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJldmVyc2VIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXZlcnNlSG9yaXpvbnRhbCh3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGdldFJvdyh5IC8qaW50Ki8sIHJvdykge1xuICAgICAgICAgICAgaWYgKHkgPCAwIHx8IHkgPj0gdGhpcy5nZXRIZWlnaHQoKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ1JlcXVlc3RlZCByb3cgaXMgb3V0c2lkZSB0aGUgaW1hZ2U6ICcgKyB5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgaWYgKHJvdyA9PT0gbnVsbCB8fCByb3cgPT09IHVuZGVmaW5lZCB8fCByb3cubGVuZ3RoIDwgd2lkdGgpIHtcbiAgICAgICAgICAgICAgICByb3cgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkod2lkdGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gKHkgKyB0aGlzLnRvcCkgKiB0aGlzLmRhdGFXaWR0aCArIHRoaXMubGVmdDtcbiAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkodGhpcy55dXZEYXRhLCBvZmZzZXQsIHJvdywgMCwgd2lkdGgpO1xuICAgICAgICAgICAgcmV0dXJuIHJvdztcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGdldE1hdHJpeCgpIHtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIC8vIElmIHRoZSBjYWxsZXIgYXNrcyBmb3IgdGhlIGVudGlyZSB1bmRlcmx5aW5nIGltYWdlLCBzYXZlIHRoZSBjb3B5IGFuZCBnaXZlIHRoZW0gdGhlXG4gICAgICAgICAgICAvLyBvcmlnaW5hbCBkYXRhLiBUaGUgZG9jcyBzcGVjaWZpY2FsbHkgd2FybiB0aGF0IHJlc3VsdC5sZW5ndGggbXVzdCBiZSBpZ25vcmVkLlxuICAgICAgICAgICAgaWYgKHdpZHRoID09PSB0aGlzLmRhdGFXaWR0aCAmJiBoZWlnaHQgPT09IHRoaXMuZGF0YUhlaWdodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnl1dkRhdGE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBhcmVhID0gd2lkdGggKiBoZWlnaHQ7XG4gICAgICAgICAgICBjb25zdCBtYXRyaXggPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoYXJlYSk7XG4gICAgICAgICAgICBsZXQgaW5wdXRPZmZzZXQgPSB0aGlzLnRvcCAqIHRoaXMuZGF0YVdpZHRoICsgdGhpcy5sZWZ0O1xuICAgICAgICAgICAgLy8gSWYgdGhlIHdpZHRoIG1hdGNoZXMgdGhlIGZ1bGwgd2lkdGggb2YgdGhlIHVuZGVybHlpbmcgZGF0YSwgcGVyZm9ybSBhIHNpbmdsZSBjb3B5LlxuICAgICAgICAgICAgaWYgKHdpZHRoID09PSB0aGlzLmRhdGFXaWR0aCkge1xuICAgICAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkodGhpcy55dXZEYXRhLCBpbnB1dE9mZnNldCwgbWF0cml4LCAwLCBhcmVhKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWF0cml4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGNvcHkgb25lIGNyb3BwZWQgcm93IGF0IGEgdGltZS5cbiAgICAgICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgaGVpZ2h0OyB5KyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBvdXRwdXRPZmZzZXQgPSB5ICogd2lkdGg7XG4gICAgICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weSh0aGlzLnl1dkRhdGEsIGlucHV0T2Zmc2V0LCBtYXRyaXgsIG91dHB1dE9mZnNldCwgd2lkdGgpO1xuICAgICAgICAgICAgICAgIGlucHV0T2Zmc2V0ICs9IHRoaXMuZGF0YVdpZHRoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1hdHJpeDtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGlzQ3JvcFN1cHBvcnRlZCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgY3JvcChsZWZ0IC8qaW50Ki8sIHRvcCAvKmludCovLCB3aWR0aCAvKmludCovLCBoZWlnaHQgLyppbnQqLykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQbGFuYXJZVVZMdW1pbmFuY2VTb3VyY2UodGhpcy55dXZEYXRhLCB0aGlzLmRhdGFXaWR0aCwgdGhpcy5kYXRhSGVpZ2h0LCB0aGlzLmxlZnQgKyBsZWZ0LCB0aGlzLnRvcCArIHRvcCwgd2lkdGgsIGhlaWdodCwgZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIHJlbmRlclRodW1ibmFpbCgpIHtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy5nZXRXaWR0aCgpIC8gUGxhbmFyWVVWTHVtaW5hbmNlU291cmNlLlRIVU1CTkFJTF9TQ0FMRV9GQUNUT1I7XG4gICAgICAgICAgICBjb25zdCBoZWlnaHQgPSB0aGlzLmdldEhlaWdodCgpIC8gUGxhbmFyWVVWTHVtaW5hbmNlU291cmNlLlRIVU1CTkFJTF9TQ0FMRV9GQUNUT1I7XG4gICAgICAgICAgICBjb25zdCBwaXhlbHMgPSBuZXcgSW50MzJBcnJheSh3aWR0aCAqIGhlaWdodCk7XG4gICAgICAgICAgICBjb25zdCB5dXYgPSB0aGlzLnl1dkRhdGE7XG4gICAgICAgICAgICBsZXQgaW5wdXRPZmZzZXQgPSB0aGlzLnRvcCAqIHRoaXMuZGF0YVdpZHRoICsgdGhpcy5sZWZ0O1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IG91dHB1dE9mZnNldCA9IHkgKiB3aWR0aDtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IHdpZHRoOyB4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZ3JleSA9IHl1dltpbnB1dE9mZnNldCArIHggKiBQbGFuYXJZVVZMdW1pbmFuY2VTb3VyY2UuVEhVTUJOQUlMX1NDQUxFX0ZBQ1RPUl0gJiAweGZmO1xuICAgICAgICAgICAgICAgICAgICBwaXhlbHNbb3V0cHV0T2Zmc2V0ICsgeF0gPSAweEZGMDAwMDAwIHwgKGdyZXkgKiAweDAwMDEwMTAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaW5wdXRPZmZzZXQgKz0gdGhpcy5kYXRhV2lkdGggKiBQbGFuYXJZVVZMdW1pbmFuY2VTb3VyY2UuVEhVTUJOQUlMX1NDQUxFX0ZBQ1RPUjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBwaXhlbHM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gd2lkdGggb2YgaW1hZ2UgZnJvbSB7QGxpbmsgI3JlbmRlclRodW1ibmFpbCgpfVxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0VGh1bWJuYWlsV2lkdGgoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRXaWR0aCgpIC8gUGxhbmFyWVVWTHVtaW5hbmNlU291cmNlLlRIVU1CTkFJTF9TQ0FMRV9GQUNUT1I7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gaGVpZ2h0IG9mIGltYWdlIGZyb20ge0BsaW5rICNyZW5kZXJUaHVtYm5haWwoKX1cbiAgICAgICAgICovXG4gICAgICAgIGdldFRodW1ibmFpbEhlaWdodCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldEhlaWdodCgpIC8gUGxhbmFyWVVWTHVtaW5hbmNlU291cmNlLlRIVU1CTkFJTF9TQ0FMRV9GQUNUT1I7XG4gICAgICAgIH1cbiAgICAgICAgcmV2ZXJzZUhvcml6b250YWwod2lkdGggLyppbnQqLywgaGVpZ2h0IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IHl1dkRhdGEgPSB0aGlzLnl1dkRhdGE7XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMCwgcm93U3RhcnQgPSB0aGlzLnRvcCAqIHRoaXMuZGF0YVdpZHRoICsgdGhpcy5sZWZ0OyB5IDwgaGVpZ2h0OyB5KyssIHJvd1N0YXJ0ICs9IHRoaXMuZGF0YVdpZHRoKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbWlkZGxlID0gcm93U3RhcnQgKyB3aWR0aCAvIDI7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeDEgPSByb3dTdGFydCwgeDIgPSByb3dTdGFydCArIHdpZHRoIC0gMTsgeDEgPCBtaWRkbGU7IHgxKyssIHgyLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGVtcCA9IHl1dkRhdGFbeDFdO1xuICAgICAgICAgICAgICAgICAgICB5dXZEYXRhW3gxXSA9IHl1dkRhdGFbeDJdO1xuICAgICAgICAgICAgICAgICAgICB5dXZEYXRhW3gyXSA9IHRlbXA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGludmVydCgpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgSW52ZXJ0ZWRMdW1pbmFuY2VTb3VyY2UodGhpcyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgUGxhbmFyWVVWTHVtaW5hbmNlU291cmNlLlRIVU1CTkFJTF9TQ0FMRV9GQUNUT1IgPSAyO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwOSBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiBUaGlzIGNsYXNzIGlzIHVzZWQgdG8gaGVscCBkZWNvZGUgaW1hZ2VzIGZyb20gZmlsZXMgd2hpY2ggYXJyaXZlIGFzIFJHQiBkYXRhIGZyb21cbiAgICAgKiBhbiBBUkdCIHBpeGVsIGFycmF5LiBJdCBkb2VzIG5vdCBzdXBwb3J0IHJvdGF0aW9uLlxuICAgICAqXG4gICAgICogQGF1dGhvciBkc3dpdGtpbkBnb29nbGUuY29tIChEYW5pZWwgU3dpdGtpbilcbiAgICAgKiBAYXV0aG9yIEJldGFtaW5vc1xuICAgICAqL1xuICAgIGNsYXNzIFJHQkx1bWluYW5jZVNvdXJjZSBleHRlbmRzIEx1bWluYW5jZVNvdXJjZSB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGx1bWluYW5jZXMsIHdpZHRoIC8qaW50Ki8sIGhlaWdodCAvKmludCovLCBkYXRhV2lkdGggLyppbnQqLywgZGF0YUhlaWdodCAvKmludCovLCBsZWZ0IC8qaW50Ki8sIHRvcCAvKmludCovKSB7XG4gICAgICAgICAgICBzdXBlcih3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgICAgIHRoaXMuZGF0YVdpZHRoID0gZGF0YVdpZHRoO1xuICAgICAgICAgICAgdGhpcy5kYXRhSGVpZ2h0ID0gZGF0YUhlaWdodDtcbiAgICAgICAgICAgIHRoaXMubGVmdCA9IGxlZnQ7XG4gICAgICAgICAgICB0aGlzLnRvcCA9IHRvcDtcbiAgICAgICAgICAgIGlmIChsdW1pbmFuY2VzLkJZVEVTX1BFUl9FTEVNRU5UID09PSA0KSB7IC8vIEludDMyQXJyYXlcbiAgICAgICAgICAgICAgICBjb25zdCBzaXplID0gd2lkdGggKiBoZWlnaHQ7XG4gICAgICAgICAgICAgICAgY29uc3QgbHVtaW5hbmNlc1VpbnQ4QXJyYXkgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoc2l6ZSk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgb2Zmc2V0ID0gMDsgb2Zmc2V0IDwgc2l6ZTsgb2Zmc2V0KyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGl4ZWwgPSBsdW1pbmFuY2VzW29mZnNldF07XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHIgPSAocGl4ZWwgPj4gMTYpICYgMHhmZjsgLy8gcmVkXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGcyID0gKHBpeGVsID4+IDcpICYgMHgxZmU7IC8vIDIgKiBncmVlblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBiID0gcGl4ZWwgJiAweGZmOyAvLyBibHVlXG4gICAgICAgICAgICAgICAgICAgIC8vIENhbGN1bGF0ZSBncmVlbi1mYXZvdXJpbmcgYXZlcmFnZSBjaGVhcGx5XG4gICAgICAgICAgICAgICAgICAgIGx1bWluYW5jZXNVaW50OEFycmF5W29mZnNldF0gPSAvKihieXRlKSAqLyAoKHIgKyBnMiArIGIpIC8gNCkgJiAweEZGO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmx1bWluYW5jZXMgPSBsdW1pbmFuY2VzVWludDhBcnJheTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMubHVtaW5hbmNlcyA9IGx1bWluYW5jZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodW5kZWZpbmVkID09PSBkYXRhV2lkdGgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGFXaWR0aCA9IHdpZHRoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCA9PT0gZGF0YUhlaWdodCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0YUhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IGxlZnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxlZnQgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCA9PT0gdG9wKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50b3AgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMubGVmdCArIHdpZHRoID4gdGhpcy5kYXRhV2lkdGggfHwgdGhpcy50b3AgKyBoZWlnaHQgPiB0aGlzLmRhdGFIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdDcm9wIHJlY3RhbmdsZSBkb2VzIG5vdCBmaXQgd2l0aGluIGltYWdlIGRhdGEuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBnZXRSb3coeSAvKmludCovLCByb3cpIHtcbiAgICAgICAgICAgIGlmICh5IDwgMCB8fCB5ID49IHRoaXMuZ2V0SGVpZ2h0KCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdSZXF1ZXN0ZWQgcm93IGlzIG91dHNpZGUgdGhlIGltYWdlOiAnICsgeSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMuZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGlmIChyb3cgPT09IG51bGwgfHwgcm93ID09PSB1bmRlZmluZWQgfHwgcm93Lmxlbmd0aCA8IHdpZHRoKSB7XG4gICAgICAgICAgICAgICAgcm93ID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHdpZHRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9ICh5ICsgdGhpcy50b3ApICogdGhpcy5kYXRhV2lkdGggKyB0aGlzLmxlZnQ7XG4gICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KHRoaXMubHVtaW5hbmNlcywgb2Zmc2V0LCByb3csIDAsIHdpZHRoKTtcbiAgICAgICAgICAgIHJldHVybiByb3c7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBnZXRNYXRyaXgoKSB7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMuZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICAvLyBJZiB0aGUgY2FsbGVyIGFza3MgZm9yIHRoZSBlbnRpcmUgdW5kZXJseWluZyBpbWFnZSwgc2F2ZSB0aGUgY29weSBhbmQgZ2l2ZSB0aGVtIHRoZVxuICAgICAgICAgICAgLy8gb3JpZ2luYWwgZGF0YS4gVGhlIGRvY3Mgc3BlY2lmaWNhbGx5IHdhcm4gdGhhdCByZXN1bHQubGVuZ3RoIG11c3QgYmUgaWdub3JlZC5cbiAgICAgICAgICAgIGlmICh3aWR0aCA9PT0gdGhpcy5kYXRhV2lkdGggJiYgaGVpZ2h0ID09PSB0aGlzLmRhdGFIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5sdW1pbmFuY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYXJlYSA9IHdpZHRoICogaGVpZ2h0O1xuICAgICAgICAgICAgY29uc3QgbWF0cml4ID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KGFyZWEpO1xuICAgICAgICAgICAgbGV0IGlucHV0T2Zmc2V0ID0gdGhpcy50b3AgKiB0aGlzLmRhdGFXaWR0aCArIHRoaXMubGVmdDtcbiAgICAgICAgICAgIC8vIElmIHRoZSB3aWR0aCBtYXRjaGVzIHRoZSBmdWxsIHdpZHRoIG9mIHRoZSB1bmRlcmx5aW5nIGRhdGEsIHBlcmZvcm0gYSBzaW5nbGUgY29weS5cbiAgICAgICAgICAgIGlmICh3aWR0aCA9PT0gdGhpcy5kYXRhV2lkdGgpIHtcbiAgICAgICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KHRoaXMubHVtaW5hbmNlcywgaW5wdXRPZmZzZXQsIG1hdHJpeCwgMCwgYXJlYSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hdHJpeDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE90aGVyd2lzZSBjb3B5IG9uZSBjcm9wcGVkIHJvdyBhdCBhIHRpbWUuXG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgb3V0cHV0T2Zmc2V0ID0geSAqIHdpZHRoO1xuICAgICAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkodGhpcy5sdW1pbmFuY2VzLCBpbnB1dE9mZnNldCwgbWF0cml4LCBvdXRwdXRPZmZzZXQsIHdpZHRoKTtcbiAgICAgICAgICAgICAgICBpbnB1dE9mZnNldCArPSB0aGlzLmRhdGFXaWR0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtYXRyaXg7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBpc0Nyb3BTdXBwb3J0ZWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGNyb3AobGVmdCAvKmludCovLCB0b3AgLyppbnQqLywgd2lkdGggLyppbnQqLywgaGVpZ2h0IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUkdCTHVtaW5hbmNlU291cmNlKHRoaXMubHVtaW5hbmNlcywgd2lkdGgsIGhlaWdodCwgdGhpcy5kYXRhV2lkdGgsIHRoaXMuZGF0YUhlaWdodCwgdGhpcy5sZWZ0ICsgbGVmdCwgdGhpcy50b3AgKyB0b3ApO1xuICAgICAgICB9XG4gICAgICAgIGludmVydCgpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgSW52ZXJ0ZWRMdW1pbmFuY2VTb3VyY2UodGhpcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBKdXN0IHRvIG1ha2UgYSBzaG9ydGN1dCBiZXR3ZWVuIEphdmEgY29kZSBhbmQgVFMgY29kZS5cbiAgICAgKi9cbiAgICBjbGFzcyBDaGFyc2V0IGV4dGVuZHMgQ2hhcmFjdGVyU2V0RUNJIHtcbiAgICAgICAgc3RhdGljIGZvck5hbWUobmFtZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q2hhcmFjdGVyU2V0RUNJQnlOYW1lKG5hbWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSnVzdCB0byBtYWtlIGEgc2hvcnRjdXQgYmV0d2VlbiBKYXZhIGNvZGUgYW5kIFRTIGNvZGUuXG4gICAgICovXG4gICAgY2xhc3MgU3RhbmRhcmRDaGFyc2V0cyB7XG4gICAgfVxuICAgIFN0YW5kYXJkQ2hhcnNldHMuSVNPXzg4NTlfMSA9IENoYXJhY3RlclNldEVDSS5JU084ODU5XzE7XG5cbiAgICAvKlxuICAgICogQ29weXJpZ2h0IDIwMTMgWlhpbmcgYXV0aG9yc1xuICAgICpcbiAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAqXG4gICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICpcbiAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgKi9cbiAgICAvKipcbiAgICAgKiBBenRlYyAyRCBjb2RlIHJlcHJlc2VudGF0aW9uXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFJ1c3RhbSBBYmR1bGxhZXZcbiAgICAgKi9cbiAgICAvKnB1YmxpYyBmaW5hbCovIGNsYXNzIEF6dGVjQ29kZSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHtAY29kZSB0cnVlfSBpZiBjb21wYWN0IGluc3RlYWQgb2YgZnVsbCBtb2RlXG4gICAgICAgICAqL1xuICAgICAgICBpc0NvbXBhY3QoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb21wYWN0O1xuICAgICAgICB9XG4gICAgICAgIHNldENvbXBhY3QoY29tcGFjdCkge1xuICAgICAgICAgICAgdGhpcy5jb21wYWN0ID0gY29tcGFjdDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBzaXplIGluIHBpeGVscyAod2lkdGggYW5kIGhlaWdodClcbiAgICAgICAgICovXG4gICAgICAgIGdldFNpemUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zaXplO1xuICAgICAgICB9XG4gICAgICAgIHNldFNpemUoc2l6ZSkge1xuICAgICAgICAgICAgdGhpcy5zaXplID0gc2l6ZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBudW1iZXIgb2YgbGV2ZWxzXG4gICAgICAgICAqL1xuICAgICAgICBnZXRMYXllcnMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sYXllcnM7XG4gICAgICAgIH1cbiAgICAgICAgc2V0TGF5ZXJzKGxheWVycykge1xuICAgICAgICAgICAgdGhpcy5sYXllcnMgPSBsYXllcnM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gbnVtYmVyIG9mIGRhdGEgY29kZXdvcmRzXG4gICAgICAgICAqL1xuICAgICAgICBnZXRDb2RlV29yZHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2RlV29yZHM7XG4gICAgICAgIH1cbiAgICAgICAgc2V0Q29kZVdvcmRzKGNvZGVXb3Jkcykge1xuICAgICAgICAgICAgdGhpcy5jb2RlV29yZHMgPSBjb2RlV29yZHM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gdGhlIHN5bWJvbCBpbWFnZVxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0TWF0cml4KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubWF0cml4O1xuICAgICAgICB9XG4gICAgICAgIHNldE1hdHJpeChtYXRyaXgpIHtcbiAgICAgICAgICAgIHRoaXMubWF0cml4ID0gbWF0cml4O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xhc3MgQ29sbGVjdGlvbnMge1xuICAgICAgICAvKipcbiAgICAgICAgICogVGhlIHNpbmdsZXRvbkxpc3QoVCkgbWV0aG9kIGlzIHVzZWQgdG8gcmV0dXJuIGFuIGltbXV0YWJsZSBsaXN0IGNvbnRhaW5pbmcgb25seSB0aGUgc3BlY2lmaWVkIG9iamVjdC5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBzaW5nbGV0b25MaXN0KGl0ZW0pIHtcbiAgICAgICAgICAgIHJldHVybiBbaXRlbV07XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoZSBtaW4oQ29sbGVjdGlvbjw/IGV4dGVuZHMgVD4sIENvbXBhcmF0b3I8PyBzdXBlciBUPikgbWV0aG9kIGlzIHVzZWQgdG8gcmV0dXJuIHRoZSBtaW5pbXVtIGVsZW1lbnQgb2YgdGhlIGdpdmVuIGNvbGxlY3Rpb24sIGFjY29yZGluZyB0byB0aGUgb3JkZXIgaW5kdWNlZCBieSB0aGUgc3BlY2lmaWVkIGNvbXBhcmF0b3IuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgbWluKGNvbGxlY3Rpb24sIGNvbXBhcmF0b3IpIHtcbiAgICAgICAgICAgIHJldHVybiBjb2xsZWN0aW9uLnNvcnQoY29tcGFyYXRvcilbMF07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICogQ29weXJpZ2h0IDIwMTMgWlhpbmcgYXV0aG9yc1xuICAgICpcbiAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAqXG4gICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICpcbiAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgKi9cbiAgICBjbGFzcyBUb2tlbiB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHByZXZpb3VzKSB7XG4gICAgICAgICAgICB0aGlzLnByZXZpb3VzID0gcHJldmlvdXM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0UHJldmlvdXMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wcmV2aW91cztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgKiBDb3B5cmlnaHQgMjAxMyBaWGluZyBhdXRob3JzXG4gICAgKlxuICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICpcbiAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgKlxuICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAqL1xuICAgIC8qZmluYWwqLyBjbGFzcyBTaW1wbGVUb2tlbiBleHRlbmRzIFRva2VuIHtcbiAgICAgICAgY29uc3RydWN0b3IocHJldmlvdXMsIHZhbHVlLCBiaXRDb3VudCkge1xuICAgICAgICAgICAgc3VwZXIocHJldmlvdXMpO1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgdGhpcy5iaXRDb3VudCA9IGJpdENvdW50O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAT3ZlcnJpZGVcbiAgICAgICAgICovXG4gICAgICAgIGFwcGVuZFRvKGJpdEFycmF5LCB0ZXh0KSB7XG4gICAgICAgICAgICBiaXRBcnJheS5hcHBlbmRCaXRzKHRoaXMudmFsdWUsIHRoaXMuYml0Q291bnQpO1xuICAgICAgICB9XG4gICAgICAgIGFkZCh2YWx1ZSwgYml0Q291bnQpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU2ltcGxlVG9rZW4odGhpcywgdmFsdWUsIGJpdENvdW50KTtcbiAgICAgICAgfVxuICAgICAgICBhZGRCaW5hcnlTaGlmdChzdGFydCwgYnl0ZUNvdW50KSB7XG4gICAgICAgICAgICAvLyBuby1vcCBjYW4ndCBiaW5hcnkgc2hpZnQgYSBzaW1wbGUgdG9rZW5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignYWRkQmluYXJ5U2hpZnQgb24gU2ltcGxlVG9rZW4sIHRoaXMgc2ltcGx5IHJldHVybnMgYSBjb3B5IG9mIHRoaXMgdG9rZW4nKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU2ltcGxlVG9rZW4odGhpcywgc3RhcnQsIGJ5dGVDb3VudCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBPdmVycmlkZVxuICAgICAgICAgKi9cbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSB0aGlzLnZhbHVlICYgKCgxIDw8IHRoaXMuYml0Q291bnQpIC0gMSk7XG4gICAgICAgICAgICB2YWx1ZSB8PSAxIDw8IHRoaXMuYml0Q291bnQ7XG4gICAgICAgICAgICByZXR1cm4gJzwnICsgSW50ZWdlci50b0JpbmFyeVN0cmluZyh2YWx1ZSB8ICgxIDw8IHRoaXMuYml0Q291bnQpKS5zdWJzdHJpbmcoMSkgKyAnPic7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICogQ29weXJpZ2h0IDIwMTMgWlhpbmcgYXV0aG9yc1xuICAgICpcbiAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAqXG4gICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICpcbiAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgKi9cbiAgICAvKmZpbmFsKi8gY2xhc3MgQmluYXJ5U2hpZnRUb2tlbiBleHRlbmRzIFNpbXBsZVRva2VuIHtcbiAgICAgICAgY29uc3RydWN0b3IocHJldmlvdXMsIGJpbmFyeVNoaWZ0U3RhcnQsIGJpbmFyeVNoaWZ0Qnl0ZUNvdW50KSB7XG4gICAgICAgICAgICBzdXBlcihwcmV2aW91cywgMCwgMCk7XG4gICAgICAgICAgICB0aGlzLmJpbmFyeVNoaWZ0U3RhcnQgPSBiaW5hcnlTaGlmdFN0YXJ0O1xuICAgICAgICAgICAgdGhpcy5iaW5hcnlTaGlmdEJ5dGVDb3VudCA9IGJpbmFyeVNoaWZ0Qnl0ZUNvdW50O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAT3ZlcnJpZGVcbiAgICAgICAgICovXG4gICAgICAgIGFwcGVuZFRvKGJpdEFycmF5LCB0ZXh0KSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuYmluYXJ5U2hpZnRCeXRlQ291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChpID09PSAwIHx8IChpID09PSAzMSAmJiB0aGlzLmJpbmFyeVNoaWZ0Qnl0ZUNvdW50IDw9IDYyKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBXZSBuZWVkIGEgaGVhZGVyIGJlZm9yZSB0aGUgZmlyc3QgY2hhcmFjdGVyLCBhbmQgYmVmb3JlXG4gICAgICAgICAgICAgICAgICAgIC8vIGNoYXJhY3RlciAzMSB3aGVuIHRoZSB0b3RhbCBieXRlIGNvZGUgaXMgPD0gNjJcbiAgICAgICAgICAgICAgICAgICAgYml0QXJyYXkuYXBwZW5kQml0cygzMSwgNSk7IC8vIEJJTkFSWV9TSElGVFxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5iaW5hcnlTaGlmdEJ5dGVDb3VudCA+IDYyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBiaXRBcnJheS5hcHBlbmRCaXRzKHRoaXMuYmluYXJ5U2hpZnRCeXRlQ291bnQgLSAzMSwgMTYpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIDEgPD0gYmluYXJ5U2hpZnRCeXRlQ29kZSA8PSA2MlxuICAgICAgICAgICAgICAgICAgICAgICAgYml0QXJyYXkuYXBwZW5kQml0cyhNYXRoLm1pbih0aGlzLmJpbmFyeVNoaWZ0Qnl0ZUNvdW50LCAzMSksIDUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gMzIgPD0gYmluYXJ5U2hpZnRDb3VudCA8PSA2MiBhbmQgaSA9PSAzMVxuICAgICAgICAgICAgICAgICAgICAgICAgYml0QXJyYXkuYXBwZW5kQml0cyh0aGlzLmJpbmFyeVNoaWZ0Qnl0ZUNvdW50IC0gMzEsIDUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJpdEFycmF5LmFwcGVuZEJpdHModGV4dFt0aGlzLmJpbmFyeVNoaWZ0U3RhcnQgKyBpXSwgOCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYWRkQmluYXJ5U2hpZnQoc3RhcnQsIGJ5dGVDb3VudCkge1xuICAgICAgICAgICAgLy8gaW50IGJpdENvdW50ID0gKGJ5dGVDb3VudCAqIDgpICsgKGJ5dGVDb3VudCA8PSAzMSA/IDEwIDogYnl0ZUNvdW50IDw9IDYyID8gMjAgOiAyMSk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEJpbmFyeVNoaWZ0VG9rZW4odGhpcywgc3RhcnQsIGJ5dGVDb3VudCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBPdmVycmlkZVxuICAgICAgICAgKi9cbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICByZXR1cm4gJzwnICsgdGhpcy5iaW5hcnlTaGlmdFN0YXJ0ICsgJzo6JyArICh0aGlzLmJpbmFyeVNoaWZ0U3RhcnQgKyB0aGlzLmJpbmFyeVNoaWZ0Qnl0ZUNvdW50IC0gMSkgKyAnPic7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhZGRCaW5hcnlTaGlmdCh0b2tlbiwgc3RhcnQsIGJ5dGVDb3VudCkge1xuICAgICAgICAvLyBpbnQgYml0Q291bnQgPSAoYnl0ZUNvdW50ICogOCkgKyAoYnl0ZUNvdW50IDw9IDMxID8gMTAgOiBieXRlQ291bnQgPD0gNjIgPyAyMCA6IDIxKTtcbiAgICAgICAgcmV0dXJuIG5ldyBCaW5hcnlTaGlmdFRva2VuKHRva2VuLCBzdGFydCwgYnl0ZUNvdW50KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gYWRkKHRva2VuLCB2YWx1ZSwgYml0Q291bnQpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBTaW1wbGVUb2tlbih0b2tlbiwgdmFsdWUsIGJpdENvdW50KTtcbiAgICB9XG5cbiAgICBjb25zdCAvKmZpbmFsKi8gTU9ERV9OQU1FUyA9IFtcbiAgICAgICAgJ1VQUEVSJyxcbiAgICAgICAgJ0xPV0VSJyxcbiAgICAgICAgJ0RJR0lUJyxcbiAgICAgICAgJ01JWEVEJyxcbiAgICAgICAgJ1BVTkNUJ1xuICAgIF07XG4gICAgY29uc3QgLypmaW5hbCovIE1PREVfVVBQRVIgPSAwOyAvLyA1IGJpdHNcbiAgICBjb25zdCAvKmZpbmFsKi8gTU9ERV9MT1dFUiA9IDE7IC8vIDUgYml0c1xuICAgIGNvbnN0IC8qZmluYWwqLyBNT0RFX0RJR0lUID0gMjsgLy8gNCBiaXRzXG4gICAgY29uc3QgLypmaW5hbCovIE1PREVfTUlYRUQgPSAzOyAvLyA1IGJpdHNcbiAgICBjb25zdCAvKmZpbmFsKi8gTU9ERV9QVU5DVCA9IDQ7IC8vIDUgYml0c1xuICAgIGNvbnN0IEVNUFRZX1RPS0VOID0gbmV3IFNpbXBsZVRva2VuKG51bGwsIDAsIDApO1xuXG4gICAgLy8gVGhlIExhdGNoIFRhYmxlIHNob3dzLCBmb3IgZWFjaCBwYWlyIG9mIE1vZGVzLCB0aGUgb3B0aW1hbCBtZXRob2QgZm9yXG4gICAgLy8gZ2V0dGluZyBmcm9tIG9uZSBtb2RlIHRvIGFub3RoZXIuICBJbiB0aGUgd29yc3QgcG9zc2libGUgY2FzZSwgdGhpcyBjYW5cbiAgICAvLyBiZSB1cCB0byAxNCBiaXRzLiAgSW4gdGhlIGJlc3QgcG9zc2libGUgY2FzZSwgd2UgYXJlIGFscmVhZHkgdGhlcmUhXG4gICAgLy8gVGhlIGhpZ2ggaGFsZi13b3JkIG9mIGVhY2ggZW50cnkgZ2l2ZXMgdGhlIG51bWJlciBvZiBiaXRzLlxuICAgIC8vIFRoZSBsb3cgaGFsZi13b3JkIG9mIGVhY2ggZW50cnkgYXJlIHRoZSBhY3R1YWwgYml0cyBuZWNlc3NhcnkgdG8gY2hhbmdlXG4gICAgY29uc3QgTEFUQ0hfVEFCTEUgPSBbXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbXG4gICAgICAgICAgICAwLFxuICAgICAgICAgICAgKDUgPDwgMTYpICsgMjgsXG4gICAgICAgICAgICAoNSA8PCAxNikgKyAzMCxcbiAgICAgICAgICAgICg1IDw8IDE2KSArIDI5LFxuICAgICAgICAgICAgKDEwIDw8IDE2KSArICgyOSA8PCA1KSArIDMwIC8vIFVQUEVSIC0+IE1JWEVEIC0+IFBVTkNUXG4gICAgICAgIF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oW1xuICAgICAgICAgICAgKDkgPDwgMTYpICsgKDMwIDw8IDQpICsgMTQsXG4gICAgICAgICAgICAwLFxuICAgICAgICAgICAgKDUgPDwgMTYpICsgMzAsXG4gICAgICAgICAgICAoNSA8PCAxNikgKyAyOSxcbiAgICAgICAgICAgICgxMCA8PCAxNikgKyAoMjkgPDwgNSkgKyAzMCAvLyBMT1dFUiAtPiBNSVhFRCAtPiBQVU5DVFxuICAgICAgICBdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFtcbiAgICAgICAgICAgICg0IDw8IDE2KSArIDE0LFxuICAgICAgICAgICAgKDkgPDwgMTYpICsgKDE0IDw8IDUpICsgMjgsXG4gICAgICAgICAgICAwLFxuICAgICAgICAgICAgKDkgPDwgMTYpICsgKDE0IDw8IDUpICsgMjksXG4gICAgICAgICAgICAoMTQgPDwgMTYpICsgKDE0IDw8IDEwKSArICgyOSA8PCA1KSArIDMwXG4gICAgICAgICAgICAvLyBESUdJVCAtPiBVUFBFUiAtPiBNSVhFRCAtPiBQVU5DVFxuICAgICAgICBdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFtcbiAgICAgICAgICAgICg1IDw8IDE2KSArIDI5LFxuICAgICAgICAgICAgKDUgPDwgMTYpICsgMjgsXG4gICAgICAgICAgICAoMTAgPDwgMTYpICsgKDI5IDw8IDUpICsgMzAsXG4gICAgICAgICAgICAwLFxuICAgICAgICAgICAgKDUgPDwgMTYpICsgMzAgLy8gTUlYRUQgLT4gUFVOQ1RcbiAgICAgICAgXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbXG4gICAgICAgICAgICAoNSA8PCAxNikgKyAzMSxcbiAgICAgICAgICAgICgxMCA8PCAxNikgKyAoMzEgPDwgNSkgKyAyOCxcbiAgICAgICAgICAgICgxMCA8PCAxNikgKyAoMzEgPDwgNSkgKyAzMCxcbiAgICAgICAgICAgICgxMCA8PCAxNikgKyAoMzEgPDwgNSkgKyAyOSxcbiAgICAgICAgICAgIDBcbiAgICAgICAgXSlcbiAgICBdO1xuXG4gICAgZnVuY3Rpb24gc3RhdGljX1NISUZUX1RBQkxFKFNISUZUX1RBQkxFKSB7XG4gICAgICAgIGZvciAobGV0IHRhYmxlIC8qSW50MzJBcnJheSovIG9mIFNISUZUX1RBQkxFKSB7XG4gICAgICAgICAgICBBcnJheXMuZmlsbCh0YWJsZSwgLTEpO1xuICAgICAgICB9XG4gICAgICAgIFNISUZUX1RBQkxFW01PREVfVVBQRVJdW01PREVfUFVOQ1RdID0gMDtcbiAgICAgICAgU0hJRlRfVEFCTEVbTU9ERV9MT1dFUl1bTU9ERV9QVU5DVF0gPSAwO1xuICAgICAgICBTSElGVF9UQUJMRVtNT0RFX0xPV0VSXVtNT0RFX1VQUEVSXSA9IDI4O1xuICAgICAgICBTSElGVF9UQUJMRVtNT0RFX01JWEVEXVtNT0RFX1BVTkNUXSA9IDA7XG4gICAgICAgIFNISUZUX1RBQkxFW01PREVfRElHSVRdW01PREVfUFVOQ1RdID0gMDtcbiAgICAgICAgU0hJRlRfVEFCTEVbTU9ERV9ESUdJVF1bTU9ERV9VUFBFUl0gPSAxNTtcbiAgICAgICAgcmV0dXJuIFNISUZUX1RBQkxFO1xuICAgIH1cbiAgICBjb25zdCAvKmZpbmFsKi8gU0hJRlRfVEFCTEUgPSBzdGF0aWNfU0hJRlRfVEFCTEUoQXJyYXlzLmNyZWF0ZUludDMyQXJyYXkoNiwgNikpOyAvLyBtb2RlIHNoaWZ0IGNvZGVzLCBwZXIgdGFibGVcblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMTMgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogU3RhdGUgcmVwcmVzZW50cyBhbGwgaW5mb3JtYXRpb24gYWJvdXQgYSBzZXF1ZW5jZSBuZWNlc3NhcnkgdG8gZ2VuZXJhdGUgdGhlIGN1cnJlbnQgb3V0cHV0LlxuICAgICAqIE5vdGUgdGhhdCBhIHN0YXRlIGlzIGltbXV0YWJsZS5cbiAgICAgKi9cbiAgICAvKmZpbmFsKi8gY2xhc3MgU3RhdGUge1xuICAgICAgICBjb25zdHJ1Y3Rvcih0b2tlbiwgbW9kZSwgYmluYXJ5Qnl0ZXMsIGJpdENvdW50KSB7XG4gICAgICAgICAgICB0aGlzLnRva2VuID0gdG9rZW47XG4gICAgICAgICAgICB0aGlzLm1vZGUgPSBtb2RlO1xuICAgICAgICAgICAgdGhpcy5iaW5hcnlTaGlmdEJ5dGVDb3VudCA9IGJpbmFyeUJ5dGVzO1xuICAgICAgICAgICAgdGhpcy5iaXRDb3VudCA9IGJpdENvdW50O1xuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHdlIG1hdGNoIHRoZSB0b2tlblxuICAgICAgICAgICAgLy8gaW50IGJpbmFyeVNoaWZ0Qml0Q291bnQgPSAoYmluYXJ5U2hpZnRCeXRlQ291bnQgKiA4KSArXG4gICAgICAgICAgICAvLyAgICAoYmluYXJ5U2hpZnRCeXRlQ291bnQgPT09IDAgPyAwIDpcbiAgICAgICAgICAgIC8vICAgICBiaW5hcnlTaGlmdEJ5dGVDb3VudCA8PSAzMSA/IDEwIDpcbiAgICAgICAgICAgIC8vICAgICBiaW5hcnlTaGlmdEJ5dGVDb3VudCA8PSA2MiA/IDIwIDogMjEpO1xuICAgICAgICAgICAgLy8gYXNzZXJ0IHRoaXMuYml0Q291bnQgPT09IHRva2VuLmdldFRvdGFsQml0Q291bnQoKSArIGJpbmFyeVNoaWZ0Qml0Q291bnQ7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0TW9kZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1vZGU7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0VG9rZW4oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50b2tlbjtcbiAgICAgICAgfVxuICAgICAgICBnZXRCaW5hcnlTaGlmdEJ5dGVDb3VudCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJpbmFyeVNoaWZ0Qnl0ZUNvdW50O1xuICAgICAgICB9XG4gICAgICAgIGdldEJpdENvdW50KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYml0Q291bnQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IHN0YXRlIHJlcHJlc2VudGluZyB0aGlzIHN0YXRlIHdpdGggYSBsYXRjaCB0byBhIChub3RcbiAgICAgICAgLy8gbmVjZXNzYXJ5IGRpZmZlcmVudCkgbW9kZSwgYW5kIHRoZW4gYSBjb2RlLlxuICAgICAgICBsYXRjaEFuZEFwcGVuZChtb2RlLCB2YWx1ZSkge1xuICAgICAgICAgICAgLy8gYXNzZXJ0IGJpbmFyeVNoaWZ0Qnl0ZUNvdW50ID09PSAwO1xuICAgICAgICAgICAgbGV0IGJpdENvdW50ID0gdGhpcy5iaXRDb3VudDtcbiAgICAgICAgICAgIGxldCB0b2tlbiA9IHRoaXMudG9rZW47XG4gICAgICAgICAgICBpZiAobW9kZSAhPT0gdGhpcy5tb2RlKSB7XG4gICAgICAgICAgICAgICAgbGV0IGxhdGNoID0gTEFUQ0hfVEFCTEVbdGhpcy5tb2RlXVttb2RlXTtcbiAgICAgICAgICAgICAgICB0b2tlbiA9IGFkZCh0b2tlbiwgbGF0Y2ggJiAweGZmZmYsIGxhdGNoID4+IDE2KTtcbiAgICAgICAgICAgICAgICBiaXRDb3VudCArPSBsYXRjaCA+PiAxNjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBsYXRjaE1vZGVCaXRDb3VudCA9IG1vZGUgPT09IE1PREVfRElHSVQgPyA0IDogNTtcbiAgICAgICAgICAgIHRva2VuID0gYWRkKHRva2VuLCB2YWx1ZSwgbGF0Y2hNb2RlQml0Q291bnQpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBTdGF0ZSh0b2tlbiwgbW9kZSwgMCwgYml0Q291bnQgKyBsYXRjaE1vZGVCaXRDb3VudCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IHN0YXRlIHJlcHJlc2VudGluZyB0aGlzIHN0YXRlLCB3aXRoIGEgdGVtcG9yYXJ5IHNoaWZ0XG4gICAgICAgIC8vIHRvIGEgZGlmZmVyZW50IG1vZGUgdG8gb3V0cHV0IGEgc2luZ2xlIHZhbHVlLlxuICAgICAgICBzaGlmdEFuZEFwcGVuZChtb2RlLCB2YWx1ZSkge1xuICAgICAgICAgICAgLy8gYXNzZXJ0IGJpbmFyeVNoaWZ0Qnl0ZUNvdW50ID09PSAwICYmIHRoaXMubW9kZSAhPT0gbW9kZTtcbiAgICAgICAgICAgIGxldCB0b2tlbiA9IHRoaXMudG9rZW47XG4gICAgICAgICAgICBsZXQgdGhpc01vZGVCaXRDb3VudCA9IHRoaXMubW9kZSA9PT0gTU9ERV9ESUdJVCA/IDQgOiA1O1xuICAgICAgICAgICAgLy8gU2hpZnRzIGV4aXN0IG9ubHkgdG8gVVBQRVIgYW5kIFBVTkNULCBib3RoIHdpdGggdG9rZW5zIHNpemUgNS5cbiAgICAgICAgICAgIHRva2VuID0gYWRkKHRva2VuLCBTSElGVF9UQUJMRVt0aGlzLm1vZGVdW21vZGVdLCB0aGlzTW9kZUJpdENvdW50KTtcbiAgICAgICAgICAgIHRva2VuID0gYWRkKHRva2VuLCB2YWx1ZSwgNSk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFN0YXRlKHRva2VuLCB0aGlzLm1vZGUsIDAsIHRoaXMuYml0Q291bnQgKyB0aGlzTW9kZUJpdENvdW50ICsgNSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IHN0YXRlIHJlcHJlc2VudGluZyB0aGlzIHN0YXRlLCBidXQgYW4gYWRkaXRpb25hbCBjaGFyYWN0ZXJcbiAgICAgICAgLy8gb3V0cHV0IGluIEJpbmFyeSBTaGlmdCBtb2RlLlxuICAgICAgICBhZGRCaW5hcnlTaGlmdENoYXIoaW5kZXgpIHtcbiAgICAgICAgICAgIGxldCB0b2tlbiA9IHRoaXMudG9rZW47XG4gICAgICAgICAgICBsZXQgbW9kZSA9IHRoaXMubW9kZTtcbiAgICAgICAgICAgIGxldCBiaXRDb3VudCA9IHRoaXMuYml0Q291bnQ7XG4gICAgICAgICAgICBpZiAodGhpcy5tb2RlID09PSBNT0RFX1BVTkNUIHx8IHRoaXMubW9kZSA9PT0gTU9ERV9ESUdJVCkge1xuICAgICAgICAgICAgICAgIC8vIGFzc2VydCBiaW5hcnlTaGlmdEJ5dGVDb3VudCA9PT0gMDtcbiAgICAgICAgICAgICAgICBsZXQgbGF0Y2ggPSBMQVRDSF9UQUJMRVttb2RlXVtNT0RFX1VQUEVSXTtcbiAgICAgICAgICAgICAgICB0b2tlbiA9IGFkZCh0b2tlbiwgbGF0Y2ggJiAweGZmZmYsIGxhdGNoID4+IDE2KTtcbiAgICAgICAgICAgICAgICBiaXRDb3VudCArPSBsYXRjaCA+PiAxNjtcbiAgICAgICAgICAgICAgICBtb2RlID0gTU9ERV9VUFBFUjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBkZWx0YUJpdENvdW50ID0gdGhpcy5iaW5hcnlTaGlmdEJ5dGVDb3VudCA9PT0gMCB8fCB0aGlzLmJpbmFyeVNoaWZ0Qnl0ZUNvdW50ID09PSAzMVxuICAgICAgICAgICAgICAgID8gMThcbiAgICAgICAgICAgICAgICA6IHRoaXMuYmluYXJ5U2hpZnRCeXRlQ291bnQgPT09IDYyXG4gICAgICAgICAgICAgICAgICAgID8gOVxuICAgICAgICAgICAgICAgICAgICA6IDg7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gbmV3IFN0YXRlKHRva2VuLCBtb2RlLCB0aGlzLmJpbmFyeVNoaWZ0Qnl0ZUNvdW50ICsgMSwgYml0Q291bnQgKyBkZWx0YUJpdENvdW50KTtcbiAgICAgICAgICAgIGlmIChyZXN1bHQuYmluYXJ5U2hpZnRCeXRlQ291bnQgPT09IDIwNDcgKyAzMSkge1xuICAgICAgICAgICAgICAgIC8vIFRoZSBzdHJpbmcgaXMgYXMgbG9uZyBhcyBpdCdzIGFsbG93ZWQgdG8gYmUuICBXZSBzaG91bGQgZW5kIGl0LlxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5lbmRCaW5hcnlTaGlmdChpbmRleCArIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICAvLyBDcmVhdGUgdGhlIHN0YXRlIGlkZW50aWNhbCB0byB0aGlzIG9uZSwgYnV0IHdlIGFyZSBubyBsb25nZXIgaW5cbiAgICAgICAgLy8gQmluYXJ5IFNoaWZ0IG1vZGUuXG4gICAgICAgIGVuZEJpbmFyeVNoaWZ0KGluZGV4KSB7XG4gICAgICAgICAgICBpZiAodGhpcy5iaW5hcnlTaGlmdEJ5dGVDb3VudCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHRva2VuID0gdGhpcy50b2tlbjtcbiAgICAgICAgICAgIHRva2VuID0gYWRkQmluYXJ5U2hpZnQodG9rZW4sIGluZGV4IC0gdGhpcy5iaW5hcnlTaGlmdEJ5dGVDb3VudCwgdGhpcy5iaW5hcnlTaGlmdEJ5dGVDb3VudCk7XG4gICAgICAgICAgICAvLyBhc3NlcnQgdG9rZW4uZ2V0VG90YWxCaXRDb3VudCgpID09PSB0aGlzLmJpdENvdW50O1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBTdGF0ZSh0b2tlbiwgdGhpcy5tb2RlLCAwLCB0aGlzLmJpdENvdW50KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBSZXR1cm5zIHRydWUgaWYgXCJ0aGlzXCIgc3RhdGUgaXMgYmV0dGVyIChlcXVhbDogb3IpIHRvIGJlIGluIHRoYW4gXCJ0aGF0XCJcbiAgICAgICAgLy8gc3RhdGUgdW5kZXIgYWxsIHBvc3NpYmxlIGNpcmN1bXN0YW5jZXMuXG4gICAgICAgIGlzQmV0dGVyVGhhbk9yRXF1YWxUbyhvdGhlcikge1xuICAgICAgICAgICAgbGV0IG5ld01vZGVCaXRDb3VudCA9IHRoaXMuYml0Q291bnQgKyAoTEFUQ0hfVEFCTEVbdGhpcy5tb2RlXVtvdGhlci5tb2RlXSA+PiAxNik7XG4gICAgICAgICAgICBpZiAodGhpcy5iaW5hcnlTaGlmdEJ5dGVDb3VudCA8IG90aGVyLmJpbmFyeVNoaWZ0Qnl0ZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgLy8gYWRkIGFkZGl0aW9uYWwgQi9TIGVuY29kaW5nIGNvc3Qgb2Ygb3RoZXIsIGlmIGFueVxuICAgICAgICAgICAgICAgIG5ld01vZGVCaXRDb3VudCArPVxuICAgICAgICAgICAgICAgICAgICBTdGF0ZS5jYWxjdWxhdGVCaW5hcnlTaGlmdENvc3Qob3RoZXIpIC1cbiAgICAgICAgICAgICAgICAgICAgICAgIFN0YXRlLmNhbGN1bGF0ZUJpbmFyeVNoaWZ0Q29zdCh0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuYmluYXJ5U2hpZnRCeXRlQ291bnQgPiBvdGhlci5iaW5hcnlTaGlmdEJ5dGVDb3VudCAmJlxuICAgICAgICAgICAgICAgIG90aGVyLmJpbmFyeVNoaWZ0Qnl0ZUNvdW50ID4gMCkge1xuICAgICAgICAgICAgICAgIC8vIG1heGltdW0gcG9zc2libGUgYWRkaXRpb25hbCBjb3N0IChpdDogaClcbiAgICAgICAgICAgICAgICBuZXdNb2RlQml0Q291bnQgKz0gMTA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3TW9kZUJpdENvdW50IDw9IG90aGVyLmJpdENvdW50O1xuICAgICAgICB9XG4gICAgICAgIHRvQml0QXJyYXkodGV4dCkge1xuICAgICAgICAgICAgLy8gUmV2ZXJzZSB0aGUgdG9rZW5zLCBzbyB0aGF0IHRoZXkgYXJlIGluIHRoZSBvcmRlciB0aGF0IHRoZXkgc2hvdWxkXG4gICAgICAgICAgICAvLyBiZSBvdXRwdXRcbiAgICAgICAgICAgIGxldCBzeW1ib2xzID0gW107XG4gICAgICAgICAgICBmb3IgKGxldCB0b2tlbiA9IHRoaXMuZW5kQmluYXJ5U2hpZnQodGV4dC5sZW5ndGgpLnRva2VuOyB0b2tlbiAhPT0gbnVsbDsgdG9rZW4gPSB0b2tlbi5nZXRQcmV2aW91cygpKSB7XG4gICAgICAgICAgICAgICAgc3ltYm9scy51bnNoaWZ0KHRva2VuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBiaXRBcnJheSA9IG5ldyBCaXRBcnJheSgpO1xuICAgICAgICAgICAgLy8gQWRkIGVhY2ggdG9rZW4gdG8gdGhlIHJlc3VsdC5cbiAgICAgICAgICAgIGZvciAoY29uc3Qgc3ltYm9sIG9mIHN5bWJvbHMpIHtcbiAgICAgICAgICAgICAgICBzeW1ib2wuYXBwZW5kVG8oYml0QXJyYXksIHRleHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gYXNzZXJ0IGJpdEFycmF5LmdldFNpemUoKSA9PT0gdGhpcy5iaXRDb3VudDtcbiAgICAgICAgICAgIHJldHVybiBiaXRBcnJheTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQE92ZXJyaWRlXG4gICAgICAgICAqL1xuICAgICAgICB0b1N0cmluZygpIHtcbiAgICAgICAgICAgIHJldHVybiBTdHJpbmdVdGlscy5mb3JtYXQoJyVzIGJpdHM9JWQgYnl0ZXM9JWQnLCBNT0RFX05BTUVTW3RoaXMubW9kZV0sIHRoaXMuYml0Q291bnQsIHRoaXMuYmluYXJ5U2hpZnRCeXRlQ291bnQpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBjYWxjdWxhdGVCaW5hcnlTaGlmdENvc3Qoc3RhdGUpIHtcbiAgICAgICAgICAgIGlmIChzdGF0ZS5iaW5hcnlTaGlmdEJ5dGVDb3VudCA+IDYyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDIxOyAvLyBCL1Mgd2l0aCBleHRlbmRlZCBsZW5ndGhcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzdGF0ZS5iaW5hcnlTaGlmdEJ5dGVDb3VudCA+IDMxKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDIwOyAvLyB0d28gQi9TXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RhdGUuYmluYXJ5U2hpZnRCeXRlQ291bnQgPiAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDEwOyAvLyBvbmUgQi9TXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBTdGF0ZS5JTklUSUFMX1NUQVRFID0gbmV3IFN0YXRlKEVNUFRZX1RPS0VOLCBNT0RFX1VQUEVSLCAwLCAwKTtcblxuICAgIGZ1bmN0aW9uIHN0YXRpY19DSEFSX01BUChDSEFSX01BUCkge1xuICAgICAgICBjb25zdCBzcGFjZUNoYXJDb2RlID0gU3RyaW5nVXRpbHMuZ2V0Q2hhckNvZGUoJyAnKTtcbiAgICAgICAgY29uc3QgcG9pbnRDaGFyQ29kZSA9IFN0cmluZ1V0aWxzLmdldENoYXJDb2RlKCcuJyk7XG4gICAgICAgIGNvbnN0IGNvbW1hQ2hhckNvZGUgPSBTdHJpbmdVdGlscy5nZXRDaGFyQ29kZSgnLCcpO1xuICAgICAgICBDSEFSX01BUFtNT0RFX1VQUEVSXVtzcGFjZUNoYXJDb2RlXSA9IDE7XG4gICAgICAgIGNvbnN0IHpVcHBlckNoYXJDb2RlID0gU3RyaW5nVXRpbHMuZ2V0Q2hhckNvZGUoJ1onKTtcbiAgICAgICAgY29uc3QgYVVwcGVyQ2hhckNvZGUgPSBTdHJpbmdVdGlscy5nZXRDaGFyQ29kZSgnQScpO1xuICAgICAgICBmb3IgKGxldCBjID0gYVVwcGVyQ2hhckNvZGU7IGMgPD0gelVwcGVyQ2hhckNvZGU7IGMrKykge1xuICAgICAgICAgICAgQ0hBUl9NQVBbTU9ERV9VUFBFUl1bY10gPSBjIC0gYVVwcGVyQ2hhckNvZGUgKyAyO1xuICAgICAgICB9XG4gICAgICAgIENIQVJfTUFQW01PREVfTE9XRVJdW3NwYWNlQ2hhckNvZGVdID0gMTtcbiAgICAgICAgY29uc3Qgekxvd2VyQ2hhckNvZGUgPSBTdHJpbmdVdGlscy5nZXRDaGFyQ29kZSgneicpO1xuICAgICAgICBjb25zdCBhTG93ZXJDaGFyQ29kZSA9IFN0cmluZ1V0aWxzLmdldENoYXJDb2RlKCdhJyk7XG4gICAgICAgIGZvciAobGV0IGMgPSBhTG93ZXJDaGFyQ29kZTsgYyA8PSB6TG93ZXJDaGFyQ29kZTsgYysrKSB7XG4gICAgICAgICAgICBDSEFSX01BUFtNT0RFX0xPV0VSXVtjXSA9IGMgLSBhTG93ZXJDaGFyQ29kZSArIDI7XG4gICAgICAgIH1cbiAgICAgICAgQ0hBUl9NQVBbTU9ERV9ESUdJVF1bc3BhY2VDaGFyQ29kZV0gPSAxO1xuICAgICAgICBjb25zdCBuaW5lQ2hhckNvZGUgPSBTdHJpbmdVdGlscy5nZXRDaGFyQ29kZSgnOScpO1xuICAgICAgICBjb25zdCB6ZXJvQ2hhckNvZGUgPSBTdHJpbmdVdGlscy5nZXRDaGFyQ29kZSgnMCcpO1xuICAgICAgICBmb3IgKGxldCBjID0gemVyb0NoYXJDb2RlOyBjIDw9IG5pbmVDaGFyQ29kZTsgYysrKSB7XG4gICAgICAgICAgICBDSEFSX01BUFtNT0RFX0RJR0lUXVtjXSA9IGMgLSB6ZXJvQ2hhckNvZGUgKyAyO1xuICAgICAgICB9XG4gICAgICAgIENIQVJfTUFQW01PREVfRElHSVRdW2NvbW1hQ2hhckNvZGVdID0gMTI7XG4gICAgICAgIENIQVJfTUFQW01PREVfRElHSVRdW3BvaW50Q2hhckNvZGVdID0gMTM7XG4gICAgICAgIGNvbnN0IG1peGVkVGFibGUgPSBbXG4gICAgICAgICAgICAnXFx4MDAnLFxuICAgICAgICAgICAgJyAnLFxuICAgICAgICAgICAgJ1xceDAxJyxcbiAgICAgICAgICAgICdcXHgwMicsXG4gICAgICAgICAgICAnXFx4MDMnLFxuICAgICAgICAgICAgJ1xceDA0JyxcbiAgICAgICAgICAgICdcXHgwNScsXG4gICAgICAgICAgICAnXFx4MDYnLFxuICAgICAgICAgICAgJ1xceDA3JyxcbiAgICAgICAgICAgICdcXGInLFxuICAgICAgICAgICAgJ1xcdCcsXG4gICAgICAgICAgICAnXFxuJyxcbiAgICAgICAgICAgICdcXHgwYicsXG4gICAgICAgICAgICAnXFxmJyxcbiAgICAgICAgICAgICdcXHInLFxuICAgICAgICAgICAgJ1xceDFiJyxcbiAgICAgICAgICAgICdcXHgxYycsXG4gICAgICAgICAgICAnXFx4MWQnLFxuICAgICAgICAgICAgJ1xceDFlJyxcbiAgICAgICAgICAgICdcXHgxZicsXG4gICAgICAgICAgICAnQCcsXG4gICAgICAgICAgICAnXFxcXCcsXG4gICAgICAgICAgICAnXicsXG4gICAgICAgICAgICAnXycsXG4gICAgICAgICAgICAnYCcsXG4gICAgICAgICAgICAnfCcsXG4gICAgICAgICAgICAnficsXG4gICAgICAgICAgICAnXFx4N2YnXG4gICAgICAgIF07XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbWl4ZWRUYWJsZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgQ0hBUl9NQVBbTU9ERV9NSVhFRF1bU3RyaW5nVXRpbHMuZ2V0Q2hhckNvZGUobWl4ZWRUYWJsZVtpXSldID0gaTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwdW5jdFRhYmxlID0gW1xuICAgICAgICAgICAgJ1xceDAwJyxcbiAgICAgICAgICAgICdcXHInLFxuICAgICAgICAgICAgJ1xceDAwJyxcbiAgICAgICAgICAgICdcXHgwMCcsXG4gICAgICAgICAgICAnXFx4MDAnLFxuICAgICAgICAgICAgJ1xceDAwJyxcbiAgICAgICAgICAgICchJyxcbiAgICAgICAgICAgICdcXCcnLFxuICAgICAgICAgICAgJyMnLFxuICAgICAgICAgICAgJyQnLFxuICAgICAgICAgICAgJyUnLFxuICAgICAgICAgICAgJyYnLFxuICAgICAgICAgICAgJ1xcJycsXG4gICAgICAgICAgICAnKCcsXG4gICAgICAgICAgICAnKScsXG4gICAgICAgICAgICAnKicsXG4gICAgICAgICAgICAnKycsXG4gICAgICAgICAgICAnLCcsXG4gICAgICAgICAgICAnLScsXG4gICAgICAgICAgICAnLicsXG4gICAgICAgICAgICAnLycsXG4gICAgICAgICAgICAnOicsXG4gICAgICAgICAgICAnOycsXG4gICAgICAgICAgICAnPCcsXG4gICAgICAgICAgICAnPScsXG4gICAgICAgICAgICAnPicsXG4gICAgICAgICAgICAnPycsXG4gICAgICAgICAgICAnWycsXG4gICAgICAgICAgICAnXScsXG4gICAgICAgICAgICAneycsXG4gICAgICAgICAgICAnfSdcbiAgICAgICAgXTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwdW5jdFRhYmxlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoU3RyaW5nVXRpbHMuZ2V0Q2hhckNvZGUocHVuY3RUYWJsZVtpXSkgPiAwKSB7XG4gICAgICAgICAgICAgICAgQ0hBUl9NQVBbTU9ERV9QVU5DVF1bU3RyaW5nVXRpbHMuZ2V0Q2hhckNvZGUocHVuY3RUYWJsZVtpXSldID0gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gQ0hBUl9NQVA7XG4gICAgfVxuICAgIGNvbnN0IENIQVJfTUFQID0gc3RhdGljX0NIQVJfTUFQKEFycmF5cy5jcmVhdGVJbnQzMkFycmF5KDUsIDI1NikpO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAxMyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiBUaGlzIHByb2R1Y2VzIG5lYXJseSBvcHRpbWFsIGVuY29kaW5ncyBvZiB0ZXh0IGludG8gdGhlIGZpcnN0LWxldmVsIG9mXG4gICAgICogZW5jb2RpbmcgdXNlZCBieSBBenRlYyBjb2RlLlxuICAgICAqXG4gICAgICogSXQgdXNlcyBhIGR5bmFtaWMgYWxnb3JpdGhtLiAgRm9yIGVhY2ggcHJlZml4IG9mIHRoZSBzdHJpbmcsIGl0IGRldGVybWluZXNcbiAgICAgKiBhIHNldCBvZiBlbmNvZGluZ3MgdGhhdCBjb3VsZCBsZWFkIHRvIHRoaXMgcHJlZml4LiAgV2UgcmVwZWF0ZWRseSBhZGQgYVxuICAgICAqIGNoYXJhY3RlciBhbmQgZ2VuZXJhdGUgYSBuZXcgc2V0IG9mIG9wdGltYWwgZW5jb2RpbmdzIHVudGlsIHdlIGhhdmUgcmVhZFxuICAgICAqIHRocm91Z2ggdGhlIGVudGlyZSBpbnB1dC5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgRnJhbmsgWWVsbGluXG4gICAgICogQGF1dGhvciBSdXN0YW0gQWJkdWxsYWV2XG4gICAgICovXG4gICAgLypwdWJsaWMgZmluYWwqLyBjbGFzcyBIaWdoTGV2ZWxFbmNvZGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IodGV4dCkge1xuICAgICAgICAgICAgdGhpcy50ZXh0ID0gdGV4dDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB0ZXh0IHJlcHJlc2VudGVkIGJ5IHRoaXMgZW5jb2RlciBlbmNvZGVkIGFzIGEge0BsaW5rIEJpdEFycmF5fVxuICAgICAgICAgKi9cbiAgICAgICAgZW5jb2RlKCkge1xuICAgICAgICAgICAgY29uc3Qgc3BhY2VDaGFyQ29kZSA9IFN0cmluZ1V0aWxzLmdldENoYXJDb2RlKCcgJyk7XG4gICAgICAgICAgICBjb25zdCBsaW5lQnJlYWtDaGFyQ29kZSA9IFN0cmluZ1V0aWxzLmdldENoYXJDb2RlKCdcXG4nKTtcbiAgICAgICAgICAgIGxldCBzdGF0ZXMgPSBDb2xsZWN0aW9ucy5zaW5nbGV0b25MaXN0KFN0YXRlLklOSVRJQUxfU1RBVEUpO1xuICAgICAgICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHRoaXMudGV4dC5sZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgICAgICAgICBsZXQgcGFpckNvZGU7XG4gICAgICAgICAgICAgICAgbGV0IG5leHRDaGFyID0gaW5kZXggKyAxIDwgdGhpcy50ZXh0Lmxlbmd0aCA/IHRoaXMudGV4dFtpbmRleCArIDFdIDogMDtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMudGV4dFtpbmRleF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBTdHJpbmdVdGlscy5nZXRDaGFyQ29kZSgnXFxyJyk6XG4gICAgICAgICAgICAgICAgICAgICAgICBwYWlyQ29kZSA9IG5leHRDaGFyID09PSBsaW5lQnJlYWtDaGFyQ29kZSA/IDIgOiAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgU3RyaW5nVXRpbHMuZ2V0Q2hhckNvZGUoJy4nKTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhaXJDb2RlID0gbmV4dENoYXIgPT09IHNwYWNlQ2hhckNvZGUgPyAzIDogMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFN0cmluZ1V0aWxzLmdldENoYXJDb2RlKCcsJyk6XG4gICAgICAgICAgICAgICAgICAgICAgICBwYWlyQ29kZSA9IG5leHRDaGFyID09PSBzcGFjZUNoYXJDb2RlID8gNCA6IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBTdHJpbmdVdGlscy5nZXRDaGFyQ29kZSgnOicpOlxuICAgICAgICAgICAgICAgICAgICAgICAgcGFpckNvZGUgPSBuZXh0Q2hhciA9PT0gc3BhY2VDaGFyQ29kZSA/IDUgOiAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBwYWlyQ29kZSA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChwYWlyQ29kZSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gV2UgaGF2ZSBvbmUgb2YgdGhlIGZvdXIgc3BlY2lhbCBQVU5DVCBwYWlycy4gIFRyZWF0IHRoZW0gc3BlY2lhbGx5LlxuICAgICAgICAgICAgICAgICAgICAvLyBHZXQgYSBuZXcgc2V0IG9mIHN0YXRlcyBmb3IgdGhlIHR3byBuZXcgY2hhcmFjdGVycy5cbiAgICAgICAgICAgICAgICAgICAgc3RhdGVzID0gSGlnaExldmVsRW5jb2Rlci51cGRhdGVTdGF0ZUxpc3RGb3JQYWlyKHN0YXRlcywgaW5kZXgsIHBhaXJDb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXgrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEdldCBhIG5ldyBzZXQgb2Ygc3RhdGVzIGZvciB0aGUgbmV3IGNoYXJhY3Rlci5cbiAgICAgICAgICAgICAgICAgICAgc3RhdGVzID0gdGhpcy51cGRhdGVTdGF0ZUxpc3RGb3JDaGFyKHN0YXRlcywgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFdlIGFyZSBsZWZ0IHdpdGggYSBzZXQgb2Ygc3RhdGVzLiAgRmluZCB0aGUgc2hvcnRlc3Qgb25lLlxuICAgICAgICAgICAgY29uc3QgbWluU3RhdGUgPSBDb2xsZWN0aW9ucy5taW4oc3RhdGVzLCAoYSwgYikgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBhLmdldEJpdENvdW50KCkgLSBiLmdldEJpdENvdW50KCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vIENvbnZlcnQgaXQgdG8gYSBiaXQgYXJyYXksIGFuZCByZXR1cm4uXG4gICAgICAgICAgICByZXR1cm4gbWluU3RhdGUudG9CaXRBcnJheSh0aGlzLnRleHQpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFdlIHVwZGF0ZSBhIHNldCBvZiBzdGF0ZXMgZm9yIGEgbmV3IGNoYXJhY3RlciBieSB1cGRhdGluZyBlYWNoIHN0YXRlXG4gICAgICAgIC8vIGZvciB0aGUgbmV3IGNoYXJhY3RlciwgbWVyZ2luZyB0aGUgcmVzdWx0cywgYW5kIHRoZW4gcmVtb3ZpbmcgdGhlXG4gICAgICAgIC8vIG5vbi1vcHRpbWFsIHN0YXRlcy5cbiAgICAgICAgdXBkYXRlU3RhdGVMaXN0Rm9yQ2hhcihzdGF0ZXMsIGluZGV4KSB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgIGZvciAobGV0IHN0YXRlIC8qU3RhdGUqLyBvZiBzdGF0ZXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVN0YXRlRm9yQ2hhcihzdGF0ZSwgaW5kZXgsIHJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gSGlnaExldmVsRW5jb2Rlci5zaW1wbGlmeVN0YXRlcyhyZXN1bHQpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFJldHVybiBhIHNldCBvZiBzdGF0ZXMgdGhhdCByZXByZXNlbnQgdGhlIHBvc3NpYmxlIHdheXMgb2YgdXBkYXRpbmcgdGhpc1xuICAgICAgICAvLyBzdGF0ZSBmb3IgdGhlIG5leHQgY2hhcmFjdGVyLiAgVGhlIHJlc3VsdGluZyBzZXQgb2Ygc3RhdGVzIGFyZSBhZGRlZCB0b1xuICAgICAgICAvLyB0aGUgXCJyZXN1bHRcIiBsaXN0LlxuICAgICAgICB1cGRhdGVTdGF0ZUZvckNoYXIoc3RhdGUsIGluZGV4LCByZXN1bHQpIHtcbiAgICAgICAgICAgIGxldCBjaCA9ICh0aGlzLnRleHRbaW5kZXhdICYgMHhmZik7XG4gICAgICAgICAgICBsZXQgY2hhckluQ3VycmVudFRhYmxlID0gQ0hBUl9NQVBbc3RhdGUuZ2V0TW9kZSgpXVtjaF0gPiAwO1xuICAgICAgICAgICAgbGV0IHN0YXRlTm9CaW5hcnkgPSBudWxsO1xuICAgICAgICAgICAgZm9yIChsZXQgbW9kZSAvKmludCovID0gMDsgbW9kZSA8PSBNT0RFX1BVTkNUOyBtb2RlKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgY2hhckluTW9kZSA9IENIQVJfTUFQW21vZGVdW2NoXTtcbiAgICAgICAgICAgICAgICBpZiAoY2hhckluTW9kZSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXRlTm9CaW5hcnkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25seSBjcmVhdGUgc3RhdGVOb0JpbmFyeSB0aGUgZmlyc3QgdGltZSBpdCdzIHJlcXVpcmVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVOb0JpbmFyeSA9IHN0YXRlLmVuZEJpbmFyeVNoaWZ0KGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBUcnkgZ2VuZXJhdGluZyB0aGUgY2hhcmFjdGVyIGJ5IGxhdGNoaW5nIHRvIGl0cyBtb2RlXG4gICAgICAgICAgICAgICAgICAgIGlmICghY2hhckluQ3VycmVudFRhYmxlIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICBtb2RlID09PSBzdGF0ZS5nZXRNb2RlKCkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vZGUgPT09IE1PREVfRElHSVQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBjaGFyYWN0ZXIgaXMgaW4gdGhlIGN1cnJlbnQgdGFibGUsIHdlIGRvbid0IHdhbnQgdG8gbGF0Y2ggdG9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFueSBvdGhlciBtb2RlIGV4Y2VwdCBwb3NzaWJseSBkaWdpdCAod2hpY2ggdXNlcyBvbmx5IDQgYml0cykuICBBbnlcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG90aGVyIGxhdGNoIHdvdWxkIGJlIGVxdWFsbHkgc3VjY2Vzc2Z1bCAqYWZ0ZXIqIHRoaXMgY2hhcmFjdGVyLCBhbmRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNvIHdvdWxkbid0IHNhdmUgYW55IGJpdHMuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsYXRjaFN0YXRlID0gc3RhdGVOb0JpbmFyeS5sYXRjaEFuZEFwcGVuZChtb2RlLCBjaGFySW5Nb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKGxhdGNoU3RhdGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIFRyeSBnZW5lcmF0aW5nIHRoZSBjaGFyYWN0ZXIgYnkgc3dpdGNoaW5nIHRvIGl0cyBtb2RlLlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNoYXJJbkN1cnJlbnRUYWJsZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgU0hJRlRfVEFCTEVbc3RhdGUuZ2V0TW9kZSgpXVttb2RlXSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJdCBuZXZlciBtYWtlcyBzZW5zZSB0byB0ZW1wb3JhcmlseSBzaGlmdCB0byBhbm90aGVyIG1vZGUgaWYgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjaGFyYWN0ZXIgZXhpc3RzIGluIHRoZSBjdXJyZW50IG1vZGUuICBUaGF0IGNhbiBuZXZlciBzYXZlIGJpdHMuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzaGlmdFN0YXRlID0gc3RhdGVOb0JpbmFyeS5zaGlmdEFuZEFwcGVuZChtb2RlLCBjaGFySW5Nb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKHNoaWZ0U3RhdGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0YXRlLmdldEJpbmFyeVNoaWZ0Qnl0ZUNvdW50KCkgPiAwIHx8XG4gICAgICAgICAgICAgICAgQ0hBUl9NQVBbc3RhdGUuZ2V0TW9kZSgpXVtjaF0gPT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyBJdCdzIG5ldmVyIHdvcnRod2hpbGUgdG8gZ28gaW50byBiaW5hcnkgc2hpZnQgbW9kZSBpZiB5b3UncmUgbm90IGFscmVhZHlcbiAgICAgICAgICAgICAgICAvLyBpbiBiaW5hcnkgc2hpZnQgbW9kZSwgYW5kIHRoZSBjaGFyYWN0ZXIgZXhpc3RzIGluIHlvdXIgY3VycmVudCBtb2RlLlxuICAgICAgICAgICAgICAgIC8vIFRoYXQgY2FuIG5ldmVyIHNhdmUgYml0cyBvdmVyIGp1c3Qgb3V0cHV0dGluZyB0aGUgY2hhciBpbiB0aGUgY3VycmVudCBtb2RlLlxuICAgICAgICAgICAgICAgIGxldCBiaW5hcnlTdGF0ZSA9IHN0YXRlLmFkZEJpbmFyeVNoaWZ0Q2hhcihpbmRleCk7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goYmluYXJ5U3RhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyB1cGRhdGVTdGF0ZUxpc3RGb3JQYWlyKHN0YXRlcywgaW5kZXgsIHBhaXJDb2RlKSB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgIGZvciAobGV0IHN0YXRlIC8qU3RhdGUqLyBvZiBzdGF0ZXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVN0YXRlRm9yUGFpcihzdGF0ZSwgaW5kZXgsIHBhaXJDb2RlLCByZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2ltcGxpZnlTdGF0ZXMocmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgdXBkYXRlU3RhdGVGb3JQYWlyKHN0YXRlLCBpbmRleCwgcGFpckNvZGUsIHJlc3VsdCkge1xuICAgICAgICAgICAgbGV0IHN0YXRlTm9CaW5hcnkgPSBzdGF0ZS5lbmRCaW5hcnlTaGlmdChpbmRleCk7XG4gICAgICAgICAgICAvLyBQb3NzaWJpbGl0eSAxLiAgTGF0Y2ggdG8gQy5NT0RFX1BVTkNULCBhbmQgdGhlbiBhcHBlbmQgdGhpcyBjb2RlXG4gICAgICAgICAgICByZXN1bHQucHVzaChzdGF0ZU5vQmluYXJ5LmxhdGNoQW5kQXBwZW5kKE1PREVfUFVOQ1QsIHBhaXJDb2RlKSk7XG4gICAgICAgICAgICBpZiAoc3RhdGUuZ2V0TW9kZSgpICE9PSBNT0RFX1BVTkNUKSB7XG4gICAgICAgICAgICAgICAgLy8gUG9zc2liaWxpdHkgMi4gIFNoaWZ0IHRvIEMuTU9ERV9QVU5DVCwgYW5kIHRoZW4gYXBwZW5kIHRoaXMgY29kZS5cbiAgICAgICAgICAgICAgICAvLyBFdmVyeSBzdGF0ZSBleGNlcHQgQy5NT0RFX1BVTkNUIChoYW5kbGVkIGFib3ZlKSBjYW4gc2hpZnRcbiAgICAgICAgICAgICAgICByZXN1bHQucHVzaChzdGF0ZU5vQmluYXJ5LnNoaWZ0QW5kQXBwZW5kKE1PREVfUFVOQ1QsIHBhaXJDb2RlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocGFpckNvZGUgPT09IDMgfHwgcGFpckNvZGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAvLyBib3RoIGNoYXJhY3RlcnMgYXJlIGluIERJR0lUUy4gIFNvbWV0aW1lcyBiZXR0ZXIgdG8ganVzdCBhZGQgdHdvIGRpZ2l0c1xuICAgICAgICAgICAgICAgIGxldCBkaWdpdFN0YXRlID0gc3RhdGVOb0JpbmFyeVxuICAgICAgICAgICAgICAgICAgICAubGF0Y2hBbmRBcHBlbmQoTU9ERV9ESUdJVCwgMTYgLSBwYWlyQ29kZSkgLy8gcGVyaW9kIG9yIGNvbW1hIGluIERJR0lUXG4gICAgICAgICAgICAgICAgICAgIC5sYXRjaEFuZEFwcGVuZChNT0RFX0RJR0lULCAxKTsgLy8gc3BhY2UgaW4gRElHSVRcbiAgICAgICAgICAgICAgICByZXN1bHQucHVzaChkaWdpdFN0YXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzdGF0ZS5nZXRCaW5hcnlTaGlmdEJ5dGVDb3VudCgpID4gMCkge1xuICAgICAgICAgICAgICAgIC8vIEl0IG9ubHkgbWFrZXMgc2Vuc2UgdG8gZG8gdGhlIGNoYXJhY3RlcnMgYXMgYmluYXJ5IGlmIHdlJ3JlIGFscmVhZHlcbiAgICAgICAgICAgICAgICAvLyBpbiBiaW5hcnkgbW9kZS5cbiAgICAgICAgICAgICAgICBsZXQgYmluYXJ5U3RhdGUgPSBzdGF0ZVxuICAgICAgICAgICAgICAgICAgICAuYWRkQmluYXJ5U2hpZnRDaGFyKGluZGV4KVxuICAgICAgICAgICAgICAgICAgICAuYWRkQmluYXJ5U2hpZnRDaGFyKGluZGV4ICsgMSk7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goYmluYXJ5U3RhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBzaW1wbGlmeVN0YXRlcyhzdGF0ZXMpIHtcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgbmV3U3RhdGUgb2Ygc3RhdGVzKSB7XG4gICAgICAgICAgICAgICAgbGV0IGFkZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBvbGRTdGF0ZSBvZiByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9sZFN0YXRlLmlzQmV0dGVyVGhhbk9yRXF1YWxUbyhuZXdTdGF0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld1N0YXRlLmlzQmV0dGVyVGhhbk9yRXF1YWxUbyhvbGRTdGF0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZXJhdG9yLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LmZpbHRlcih4ID0+IHggIT09IG9sZFN0YXRlKTsgLy8gcmVtb3ZlIG9sZCBzdGF0ZVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChhZGQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2gobmV3U3RhdGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDEzIFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8vIHBhY2thZ2UgY29tLmdvb2dsZS56eGluZy5henRlYy5lbmNvZGVyO1xuICAgIC8vIGltcG9ydCBjb20uZ29vZ2xlLnp4aW5nLmNvbW1vbi5CaXRBcnJheTtcbiAgICAvLyBpbXBvcnQgY29tLmdvb2dsZS56eGluZy5jb21tb24uQml0TWF0cml4O1xuICAgIC8vIGltcG9ydCBjb20uZ29vZ2xlLnp4aW5nLmNvbW1vbi5yZWVkc29sb21vbi5HZW5lcmljR0Y7XG4gICAgLy8gaW1wb3J0IGNvbS5nb29nbGUuenhpbmcuY29tbW9uLnJlZWRzb2xvbW9uLlJlZWRTb2xvbW9uRW5jb2RlcjtcbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZXMgQXp0ZWMgMkQgYmFyY29kZXMuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFJ1c3RhbSBBYmR1bGxhZXZcbiAgICAgKi9cbiAgICAvKnB1YmxpYyBmaW5hbCovIGNsYXNzIEVuY29kZXIkMSB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbmNvZGVzIHRoZSBnaXZlbiBiaW5hcnkgY29udGVudCBhcyBhbiBBenRlYyBzeW1ib2xcbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGRhdGEgaW5wdXQgZGF0YSBzdHJpbmdcbiAgICAgICAgICogQHJldHVybiBBenRlYyBzeW1ib2wgbWF0cml4IHdpdGggbWV0YWRhdGFcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBlbmNvZGVCeXRlcyhkYXRhKSB7XG4gICAgICAgICAgICByZXR1cm4gRW5jb2RlciQxLmVuY29kZShkYXRhLCBFbmNvZGVyJDEuREVGQVVMVF9FQ19QRVJDRU5ULCBFbmNvZGVyJDEuREVGQVVMVF9BWlRFQ19MQVlFUlMpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbmNvZGVzIHRoZSBnaXZlbiBiaW5hcnkgY29udGVudCBhcyBhbiBBenRlYyBzeW1ib2xcbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGRhdGEgaW5wdXQgZGF0YSBzdHJpbmdcbiAgICAgICAgICogQHBhcmFtIG1pbkVDQ1BlcmNlbnQgbWluaW1hbCBwZXJjZW50YWdlIG9mIGVycm9yIGNoZWNrIHdvcmRzIChBY2NvcmRpbmcgdG8gSVNPL0lFQyAyNDc3ODoyMDA4LFxuICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgICBhIG1pbmltdW0gb2YgMjMlICsgMyB3b3JkcyBpcyByZWNvbW1lbmRlZClcbiAgICAgICAgICogQHBhcmFtIHVzZXJTcGVjaWZpZWRMYXllcnMgaWYgbm9uLXplcm8sIGEgdXNlci1zcGVjaWZpZWQgdmFsdWUgZm9yIHRoZSBudW1iZXIgb2YgbGF5ZXJzXG4gICAgICAgICAqIEByZXR1cm4gQXp0ZWMgc3ltYm9sIG1hdHJpeCB3aXRoIG1ldGFkYXRhXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZW5jb2RlKGRhdGEsIG1pbkVDQ1BlcmNlbnQsIHVzZXJTcGVjaWZpZWRMYXllcnMpIHtcbiAgICAgICAgICAgIC8vIEhpZ2gtbGV2ZWwgZW5jb2RlXG4gICAgICAgICAgICBsZXQgYml0cyA9IG5ldyBIaWdoTGV2ZWxFbmNvZGVyKGRhdGEpLmVuY29kZSgpO1xuICAgICAgICAgICAgLy8gc3R1ZmYgYml0cyBhbmQgY2hvb3NlIHN5bWJvbCBzaXplXG4gICAgICAgICAgICBsZXQgZWNjQml0cyA9IEludGVnZXIudHJ1bmNEaXZpc2lvbigoYml0cy5nZXRTaXplKCkgKiBtaW5FQ0NQZXJjZW50KSwgMTAwKSArIDExO1xuICAgICAgICAgICAgbGV0IHRvdGFsU2l6ZUJpdHMgPSBiaXRzLmdldFNpemUoKSArIGVjY0JpdHM7XG4gICAgICAgICAgICBsZXQgY29tcGFjdDtcbiAgICAgICAgICAgIGxldCBsYXllcnM7XG4gICAgICAgICAgICBsZXQgdG90YWxCaXRzSW5MYXllcjtcbiAgICAgICAgICAgIGxldCB3b3JkU2l6ZTtcbiAgICAgICAgICAgIGxldCBzdHVmZmVkQml0cztcbiAgICAgICAgICAgIGlmICh1c2VyU3BlY2lmaWVkTGF5ZXJzICE9PSBFbmNvZGVyJDEuREVGQVVMVF9BWlRFQ19MQVlFUlMpIHtcbiAgICAgICAgICAgICAgICBjb21wYWN0ID0gdXNlclNwZWNpZmllZExheWVycyA8IDA7XG4gICAgICAgICAgICAgICAgbGF5ZXJzID0gTWF0aC5hYnModXNlclNwZWNpZmllZExheWVycyk7XG4gICAgICAgICAgICAgICAgaWYgKGxheWVycyA+IChjb21wYWN0ID8gRW5jb2RlciQxLk1BWF9OQl9CSVRTX0NPTVBBQ1QgOiBFbmNvZGVyJDEuTUFYX05CX0JJVFMpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oU3RyaW5nVXRpbHMuZm9ybWF0KCdJbGxlZ2FsIHZhbHVlICVzIGZvciBsYXllcnMnLCB1c2VyU3BlY2lmaWVkTGF5ZXJzKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRvdGFsQml0c0luTGF5ZXIgPSBFbmNvZGVyJDEudG90YWxCaXRzSW5MYXllcihsYXllcnMsIGNvbXBhY3QpO1xuICAgICAgICAgICAgICAgIHdvcmRTaXplID0gRW5jb2RlciQxLldPUkRfU0laRVtsYXllcnNdO1xuICAgICAgICAgICAgICAgIGxldCB1c2FibGVCaXRzSW5MYXllcnMgPSB0b3RhbEJpdHNJbkxheWVyIC0gKHRvdGFsQml0c0luTGF5ZXIgJSB3b3JkU2l6ZSk7XG4gICAgICAgICAgICAgICAgc3R1ZmZlZEJpdHMgPSBFbmNvZGVyJDEuc3R1ZmZCaXRzKGJpdHMsIHdvcmRTaXplKTtcbiAgICAgICAgICAgICAgICBpZiAoc3R1ZmZlZEJpdHMuZ2V0U2l6ZSgpICsgZWNjQml0cyA+IHVzYWJsZUJpdHNJbkxheWVycykge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdEYXRhIHRvIGxhcmdlIGZvciB1c2VyIHNwZWNpZmllZCBsYXllcicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY29tcGFjdCAmJiBzdHVmZmVkQml0cy5nZXRTaXplKCkgPiB3b3JkU2l6ZSAqIDY0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENvbXBhY3QgZm9ybWF0IG9ubHkgYWxsb3dzIDY0IGRhdGEgd29yZHMsIHRob3VnaCBDNCBjYW4gaG9sZCBtb3JlIHdvcmRzIHRoYW4gdGhhdFxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdEYXRhIHRvIGxhcmdlIGZvciB1c2VyIHNwZWNpZmllZCBsYXllcicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHdvcmRTaXplID0gMDtcbiAgICAgICAgICAgICAgICBzdHVmZmVkQml0cyA9IG51bGw7XG4gICAgICAgICAgICAgICAgLy8gV2UgbG9vayBhdCB0aGUgcG9zc2libGUgdGFibGUgc2l6ZXMgaW4gdGhlIG9yZGVyIENvbXBhY3QxLCBDb21wYWN0MiwgQ29tcGFjdDMsXG4gICAgICAgICAgICAgICAgLy8gQ29tcGFjdDQsIE5vcm1hbDQsLi4uICBOb3JtYWwoaSkgZm9yIGkgPCA0IGlzbid0IHR5cGljYWxseSB1c2VkIHNpbmNlIENvbXBhY3QoaSsxKVxuICAgICAgICAgICAgICAgIC8vIGlzIHRoZSBzYW1lIHNpemUsIGJ1dCBoYXMgbW9yZSBkYXRhLlxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkgPiBFbmNvZGVyJDEuTUFYX05CX0JJVFMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ0RhdGEgdG9vIGxhcmdlIGZvciBhbiBBenRlYyBjb2RlJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY29tcGFjdCA9IGkgPD0gMztcbiAgICAgICAgICAgICAgICAgICAgbGF5ZXJzID0gY29tcGFjdCA/IGkgKyAxIDogaTtcbiAgICAgICAgICAgICAgICAgICAgdG90YWxCaXRzSW5MYXllciA9IEVuY29kZXIkMS50b3RhbEJpdHNJbkxheWVyKGxheWVycywgY29tcGFjdCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0b3RhbFNpemVCaXRzID4gdG90YWxCaXRzSW5MYXllcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gW1JlXXN0dWZmIHRoZSBiaXRzIGlmIHRoaXMgaXMgdGhlIGZpcnN0IG9wcG9ydHVuaXR5LCBvciBpZiB0aGVcbiAgICAgICAgICAgICAgICAgICAgLy8gd29yZFNpemUgaGFzIGNoYW5nZWRcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0dWZmZWRCaXRzID09IG51bGwgfHwgd29yZFNpemUgIT09IEVuY29kZXIkMS5XT1JEX1NJWkVbbGF5ZXJzXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgd29yZFNpemUgPSBFbmNvZGVyJDEuV09SRF9TSVpFW2xheWVyc107XG4gICAgICAgICAgICAgICAgICAgICAgICBzdHVmZmVkQml0cyA9IEVuY29kZXIkMS5zdHVmZkJpdHMoYml0cywgd29yZFNpemUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGxldCB1c2FibGVCaXRzSW5MYXllcnMgPSB0b3RhbEJpdHNJbkxheWVyIC0gKHRvdGFsQml0c0luTGF5ZXIgJSB3b3JkU2l6ZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb21wYWN0ICYmIHN0dWZmZWRCaXRzLmdldFNpemUoKSA+IHdvcmRTaXplICogNjQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIENvbXBhY3QgZm9ybWF0IG9ubHkgYWxsb3dzIDY0IGRhdGEgd29yZHMsIHRob3VnaCBDNCBjYW4gaG9sZCBtb3JlIHdvcmRzIHRoYW4gdGhhdFxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0dWZmZWRCaXRzLmdldFNpemUoKSArIGVjY0JpdHMgPD0gdXNhYmxlQml0c0luTGF5ZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBtZXNzYWdlQml0cyA9IEVuY29kZXIkMS5nZW5lcmF0ZUNoZWNrV29yZHMoc3R1ZmZlZEJpdHMsIHRvdGFsQml0c0luTGF5ZXIsIHdvcmRTaXplKTtcbiAgICAgICAgICAgIC8vIGdlbmVyYXRlIG1vZGUgbWVzc2FnZVxuICAgICAgICAgICAgbGV0IG1lc3NhZ2VTaXplSW5Xb3JkcyA9IHN0dWZmZWRCaXRzLmdldFNpemUoKSAvIHdvcmRTaXplO1xuICAgICAgICAgICAgbGV0IG1vZGVNZXNzYWdlID0gRW5jb2RlciQxLmdlbmVyYXRlTW9kZU1lc3NhZ2UoY29tcGFjdCwgbGF5ZXJzLCBtZXNzYWdlU2l6ZUluV29yZHMpO1xuICAgICAgICAgICAgLy8gYWxsb2NhdGUgc3ltYm9sXG4gICAgICAgICAgICBsZXQgYmFzZU1hdHJpeFNpemUgPSAoY29tcGFjdCA/IDExIDogMTQpICsgbGF5ZXJzICogNDsgLy8gbm90IGluY2x1ZGluZyBhbGlnbm1lbnQgbGluZXNcbiAgICAgICAgICAgIGxldCBhbGlnbm1lbnRNYXAgPSBuZXcgSW50MzJBcnJheShiYXNlTWF0cml4U2l6ZSk7XG4gICAgICAgICAgICBsZXQgbWF0cml4U2l6ZTtcbiAgICAgICAgICAgIGlmIChjb21wYWN0KSB7XG4gICAgICAgICAgICAgICAgLy8gbm8gYWxpZ25tZW50IG1hcmtzIGluIGNvbXBhY3QgbW9kZSwgYWxpZ25tZW50TWFwIGlzIGEgbm8tb3BcbiAgICAgICAgICAgICAgICBtYXRyaXhTaXplID0gYmFzZU1hdHJpeFNpemU7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMDsgaSA8IGFsaWdubWVudE1hcC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBhbGlnbm1lbnRNYXBbaV0gPSBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG1hdHJpeFNpemUgPSBiYXNlTWF0cml4U2l6ZSArIDEgKyAyICogSW50ZWdlci50cnVuY0RpdmlzaW9uKChJbnRlZ2VyLnRydW5jRGl2aXNpb24oYmFzZU1hdHJpeFNpemUsIDIpIC0gMSksIDE1KTtcbiAgICAgICAgICAgICAgICBsZXQgb3JpZ0NlbnRlciA9IEludGVnZXIudHJ1bmNEaXZpc2lvbihiYXNlTWF0cml4U2l6ZSwgMik7XG4gICAgICAgICAgICAgICAgbGV0IGNlbnRlciA9IEludGVnZXIudHJ1bmNEaXZpc2lvbihtYXRyaXhTaXplLCAyKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAwOyBpIDwgb3JpZ0NlbnRlcjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBuZXdPZmZzZXQgPSBpICsgSW50ZWdlci50cnVuY0RpdmlzaW9uKGksIDE1KTtcbiAgICAgICAgICAgICAgICAgICAgYWxpZ25tZW50TWFwW29yaWdDZW50ZXIgLSBpIC0gMV0gPSBjZW50ZXIgLSBuZXdPZmZzZXQgLSAxO1xuICAgICAgICAgICAgICAgICAgICBhbGlnbm1lbnRNYXBbb3JpZ0NlbnRlciArIGldID0gY2VudGVyICsgbmV3T2Zmc2V0ICsgMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgbWF0cml4ID0gbmV3IEJpdE1hdHJpeChtYXRyaXhTaXplKTtcbiAgICAgICAgICAgIC8vIGRyYXcgZGF0YSBiaXRzXG4gICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAwLCByb3dPZmZzZXQgPSAwOyBpIDwgbGF5ZXJzOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgcm93U2l6ZSA9IChsYXllcnMgLSBpKSAqIDQgKyAoY29tcGFjdCA/IDkgOiAxMik7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiAvKmludCovID0gMDsgaiA8IHJvd1NpemU7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgY29sdW1uT2Zmc2V0ID0gaiAqIDI7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGsgLyppbnQqLyA9IDA7IGsgPCAyOyBrKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlQml0cy5nZXQocm93T2Zmc2V0ICsgY29sdW1uT2Zmc2V0ICsgaykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KGFsaWdubWVudE1hcFtpICogMiArIGtdLCBhbGlnbm1lbnRNYXBbaSAqIDIgKyBqXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobWVzc2FnZUJpdHMuZ2V0KHJvd09mZnNldCArIHJvd1NpemUgKiAyICsgY29sdW1uT2Zmc2V0ICsgaykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KGFsaWdubWVudE1hcFtpICogMiArIGpdLCBhbGlnbm1lbnRNYXBbYmFzZU1hdHJpeFNpemUgLSAxIC0gaSAqIDIgLSBrXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobWVzc2FnZUJpdHMuZ2V0KHJvd09mZnNldCArIHJvd1NpemUgKiA0ICsgY29sdW1uT2Zmc2V0ICsgaykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KGFsaWdubWVudE1hcFtiYXNlTWF0cml4U2l6ZSAtIDEgLSBpICogMiAtIGtdLCBhbGlnbm1lbnRNYXBbYmFzZU1hdHJpeFNpemUgLSAxIC0gaSAqIDIgLSBqXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobWVzc2FnZUJpdHMuZ2V0KHJvd09mZnNldCArIHJvd1NpemUgKiA2ICsgY29sdW1uT2Zmc2V0ICsgaykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KGFsaWdubWVudE1hcFtiYXNlTWF0cml4U2l6ZSAtIDEgLSBpICogMiAtIGpdLCBhbGlnbm1lbnRNYXBbaSAqIDIgKyBrXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcm93T2Zmc2V0ICs9IHJvd1NpemUgKiA4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZHJhdyBtb2RlIG1lc3NhZ2VcbiAgICAgICAgICAgIEVuY29kZXIkMS5kcmF3TW9kZU1lc3NhZ2UobWF0cml4LCBjb21wYWN0LCBtYXRyaXhTaXplLCBtb2RlTWVzc2FnZSk7XG4gICAgICAgICAgICAvLyBkcmF3IGFsaWdubWVudCBtYXJrc1xuICAgICAgICAgICAgaWYgKGNvbXBhY3QpIHtcbiAgICAgICAgICAgICAgICBFbmNvZGVyJDEuZHJhd0J1bGxzRXllKG1hdHJpeCwgSW50ZWdlci50cnVuY0RpdmlzaW9uKG1hdHJpeFNpemUsIDIpLCA1KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIEVuY29kZXIkMS5kcmF3QnVsbHNFeWUobWF0cml4LCBJbnRlZ2VyLnRydW5jRGl2aXNpb24obWF0cml4U2l6ZSwgMiksIDcpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDAsIGogPSAwOyBpIDwgSW50ZWdlci50cnVuY0RpdmlzaW9uKGJhc2VNYXRyaXhTaXplLCAyKSAtIDE7IGkgKz0gMTUsIGogKz0gMTYpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgayAvKmludCovID0gSW50ZWdlci50cnVuY0RpdmlzaW9uKG1hdHJpeFNpemUsIDIpICYgMTsgayA8IG1hdHJpeFNpemU7IGsgKz0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChJbnRlZ2VyLnRydW5jRGl2aXNpb24obWF0cml4U2l6ZSwgMikgLSBqLCBrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXQoSW50ZWdlci50cnVuY0RpdmlzaW9uKG1hdHJpeFNpemUsIDIpICsgaiwgayk7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KGssIEludGVnZXIudHJ1bmNEaXZpc2lvbihtYXRyaXhTaXplLCAyKSAtIGopO1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChrLCBJbnRlZ2VyLnRydW5jRGl2aXNpb24obWF0cml4U2l6ZSwgMikgKyBqKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBhenRlYyA9IG5ldyBBenRlY0NvZGUoKTtcbiAgICAgICAgICAgIGF6dGVjLnNldENvbXBhY3QoY29tcGFjdCk7XG4gICAgICAgICAgICBhenRlYy5zZXRTaXplKG1hdHJpeFNpemUpO1xuICAgICAgICAgICAgYXp0ZWMuc2V0TGF5ZXJzKGxheWVycyk7XG4gICAgICAgICAgICBhenRlYy5zZXRDb2RlV29yZHMobWVzc2FnZVNpemVJbldvcmRzKTtcbiAgICAgICAgICAgIGF6dGVjLnNldE1hdHJpeChtYXRyaXgpO1xuICAgICAgICAgICAgcmV0dXJuIGF6dGVjO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBkcmF3QnVsbHNFeWUobWF0cml4LCBjZW50ZXIsIHNpemUpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCBzaXplOyBpICs9IDIpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqIC8qaW50Ki8gPSBjZW50ZXIgLSBpOyBqIDw9IGNlbnRlciArIGk7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KGosIGNlbnRlciAtIGkpO1xuICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KGosIGNlbnRlciArIGkpO1xuICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KGNlbnRlciAtIGksIGopO1xuICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KGNlbnRlciArIGksIGopO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1hdHJpeC5zZXQoY2VudGVyIC0gc2l6ZSwgY2VudGVyIC0gc2l6ZSk7XG4gICAgICAgICAgICBtYXRyaXguc2V0KGNlbnRlciAtIHNpemUgKyAxLCBjZW50ZXIgLSBzaXplKTtcbiAgICAgICAgICAgIG1hdHJpeC5zZXQoY2VudGVyIC0gc2l6ZSwgY2VudGVyIC0gc2l6ZSArIDEpO1xuICAgICAgICAgICAgbWF0cml4LnNldChjZW50ZXIgKyBzaXplLCBjZW50ZXIgLSBzaXplKTtcbiAgICAgICAgICAgIG1hdHJpeC5zZXQoY2VudGVyICsgc2l6ZSwgY2VudGVyIC0gc2l6ZSArIDEpO1xuICAgICAgICAgICAgbWF0cml4LnNldChjZW50ZXIgKyBzaXplLCBjZW50ZXIgKyBzaXplIC0gMSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdlbmVyYXRlTW9kZU1lc3NhZ2UoY29tcGFjdCwgbGF5ZXJzLCBtZXNzYWdlU2l6ZUluV29yZHMpIHtcbiAgICAgICAgICAgIGxldCBtb2RlTWVzc2FnZSA9IG5ldyBCaXRBcnJheSgpO1xuICAgICAgICAgICAgaWYgKGNvbXBhY3QpIHtcbiAgICAgICAgICAgICAgICBtb2RlTWVzc2FnZS5hcHBlbmRCaXRzKGxheWVycyAtIDEsIDIpO1xuICAgICAgICAgICAgICAgIG1vZGVNZXNzYWdlLmFwcGVuZEJpdHMobWVzc2FnZVNpemVJbldvcmRzIC0gMSwgNik7XG4gICAgICAgICAgICAgICAgbW9kZU1lc3NhZ2UgPSBFbmNvZGVyJDEuZ2VuZXJhdGVDaGVja1dvcmRzKG1vZGVNZXNzYWdlLCAyOCwgNCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBtb2RlTWVzc2FnZS5hcHBlbmRCaXRzKGxheWVycyAtIDEsIDUpO1xuICAgICAgICAgICAgICAgIG1vZGVNZXNzYWdlLmFwcGVuZEJpdHMobWVzc2FnZVNpemVJbldvcmRzIC0gMSwgMTEpO1xuICAgICAgICAgICAgICAgIG1vZGVNZXNzYWdlID0gRW5jb2RlciQxLmdlbmVyYXRlQ2hlY2tXb3Jkcyhtb2RlTWVzc2FnZSwgNDAsIDQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1vZGVNZXNzYWdlO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBkcmF3TW9kZU1lc3NhZ2UobWF0cml4LCBjb21wYWN0LCBtYXRyaXhTaXplLCBtb2RlTWVzc2FnZSkge1xuICAgICAgICAgICAgbGV0IGNlbnRlciA9IEludGVnZXIudHJ1bmNEaXZpc2lvbihtYXRyaXhTaXplLCAyKTtcbiAgICAgICAgICAgIGlmIChjb21wYWN0KSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMDsgaSA8IDc7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgb2Zmc2V0ID0gY2VudGVyIC0gMyArIGk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtb2RlTWVzc2FnZS5nZXQoaSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXQob2Zmc2V0LCBjZW50ZXIgLSA1KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobW9kZU1lc3NhZ2UuZ2V0KGkgKyA3KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChjZW50ZXIgKyA1LCBvZmZzZXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChtb2RlTWVzc2FnZS5nZXQoMjAgLSBpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChvZmZzZXQsIGNlbnRlciArIDUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChtb2RlTWVzc2FnZS5nZXQoMjcgLSBpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChjZW50ZXIgLSA1LCBvZmZzZXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMDsgaSA8IDEwOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG9mZnNldCA9IGNlbnRlciAtIDUgKyBpICsgSW50ZWdlci50cnVuY0RpdmlzaW9uKGksIDUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobW9kZU1lc3NhZ2UuZ2V0KGkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KG9mZnNldCwgY2VudGVyIC0gNyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1vZGVNZXNzYWdlLmdldChpICsgMTApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KGNlbnRlciArIDcsIG9mZnNldCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1vZGVNZXNzYWdlLmdldCgyOSAtIGkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KG9mZnNldCwgY2VudGVyICsgNyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1vZGVNZXNzYWdlLmdldCgzOSAtIGkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KGNlbnRlciAtIDcsIG9mZnNldCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdlbmVyYXRlQ2hlY2tXb3JkcyhiaXRBcnJheSwgdG90YWxCaXRzLCB3b3JkU2l6ZSkge1xuICAgICAgICAgICAgLy8gYml0QXJyYXkgaXMgZ3VhcmFudGVlZCB0byBiZSBhIG11bHRpcGxlIG9mIHRoZSB3b3JkU2l6ZSwgc28gbm8gcGFkZGluZyBuZWVkZWRcbiAgICAgICAgICAgIGxldCBtZXNzYWdlU2l6ZUluV29yZHMgPSBiaXRBcnJheS5nZXRTaXplKCkgLyB3b3JkU2l6ZTtcbiAgICAgICAgICAgIGxldCBycyA9IG5ldyBSZWVkU29sb21vbkVuY29kZXIoRW5jb2RlciQxLmdldEdGKHdvcmRTaXplKSk7XG4gICAgICAgICAgICBsZXQgdG90YWxXb3JkcyA9IEludGVnZXIudHJ1bmNEaXZpc2lvbih0b3RhbEJpdHMsIHdvcmRTaXplKTtcbiAgICAgICAgICAgIGxldCBtZXNzYWdlV29yZHMgPSBFbmNvZGVyJDEuYml0c1RvV29yZHMoYml0QXJyYXksIHdvcmRTaXplLCB0b3RhbFdvcmRzKTtcbiAgICAgICAgICAgIHJzLmVuY29kZShtZXNzYWdlV29yZHMsIHRvdGFsV29yZHMgLSBtZXNzYWdlU2l6ZUluV29yZHMpO1xuICAgICAgICAgICAgbGV0IHN0YXJ0UGFkID0gdG90YWxCaXRzICUgd29yZFNpemU7XG4gICAgICAgICAgICBsZXQgbWVzc2FnZUJpdHMgPSBuZXcgQml0QXJyYXkoKTtcbiAgICAgICAgICAgIG1lc3NhZ2VCaXRzLmFwcGVuZEJpdHMoMCwgc3RhcnRQYWQpO1xuICAgICAgICAgICAgZm9yIChjb25zdCBtZXNzYWdlV29yZCAvKjogaW50Ki8gb2YgQXJyYXkuZnJvbShtZXNzYWdlV29yZHMpKSB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZUJpdHMuYXBwZW5kQml0cyhtZXNzYWdlV29yZCwgd29yZFNpemUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2VCaXRzO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBiaXRzVG9Xb3JkcyhzdHVmZmVkQml0cywgd29yZFNpemUsIHRvdGFsV29yZHMpIHtcbiAgICAgICAgICAgIGxldCBtZXNzYWdlID0gbmV3IEludDMyQXJyYXkodG90YWxXb3Jkcyk7XG4gICAgICAgICAgICBsZXQgaTtcbiAgICAgICAgICAgIGxldCBuO1xuICAgICAgICAgICAgZm9yIChpID0gMCwgbiA9IHN0dWZmZWRCaXRzLmdldFNpemUoKSAvIHdvcmRTaXplOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IHZhbHVlID0gMDtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqIC8qaW50Ki8gPSAwOyBqIDwgd29yZFNpemU7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSB8PSBzdHVmZmVkQml0cy5nZXQoaSAqIHdvcmRTaXplICsgaikgPyAoMSA8PCB3b3JkU2l6ZSAtIGogLSAxKSA6IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1lc3NhZ2VbaV0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXRHRih3b3JkU2l6ZSkge1xuICAgICAgICAgICAgc3dpdGNoICh3b3JkU2l6ZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEdlbmVyaWNHRi5BWlRFQ19QQVJBTTtcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBHZW5lcmljR0YuQVpURUNfREFUQV82O1xuICAgICAgICAgICAgICAgIGNhc2UgODpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEdlbmVyaWNHRi5BWlRFQ19EQVRBXzg7XG4gICAgICAgICAgICAgICAgY2FzZSAxMDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEdlbmVyaWNHRi5BWlRFQ19EQVRBXzEwO1xuICAgICAgICAgICAgICAgIGNhc2UgMTI6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBHZW5lcmljR0YuQVpURUNfREFUQV8xMjtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdVbnN1cHBvcnRlZCB3b3JkIHNpemUgJyArIHdvcmRTaXplKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgc3R1ZmZCaXRzKGJpdHMsIHdvcmRTaXplKSB7XG4gICAgICAgICAgICBsZXQgb3V0ID0gbmV3IEJpdEFycmF5KCk7XG4gICAgICAgICAgICBsZXQgbiA9IGJpdHMuZ2V0U2l6ZSgpO1xuICAgICAgICAgICAgbGV0IG1hc2sgPSAoMSA8PCB3b3JkU2l6ZSkgLSAyO1xuICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMDsgaSA8IG47IGkgKz0gd29yZFNpemUpIHtcbiAgICAgICAgICAgICAgICBsZXQgd29yZCA9IDA7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiAvKmludCovID0gMDsgaiA8IHdvcmRTaXplOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkgKyBqID49IG4gfHwgYml0cy5nZXQoaSArIGopKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3b3JkIHw9IDEgPDwgKHdvcmRTaXplIC0gMSAtIGopO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICgod29yZCAmIG1hc2spID09PSBtYXNrKSB7XG4gICAgICAgICAgICAgICAgICAgIG91dC5hcHBlbmRCaXRzKHdvcmQgJiBtYXNrLCB3b3JkU2l6ZSk7XG4gICAgICAgICAgICAgICAgICAgIGktLTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoKHdvcmQgJiBtYXNrKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBvdXQuYXBwZW5kQml0cyh3b3JkIHwgMSwgd29yZFNpemUpO1xuICAgICAgICAgICAgICAgICAgICBpLS07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBvdXQuYXBwZW5kQml0cyh3b3JkLCB3b3JkU2l6ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgdG90YWxCaXRzSW5MYXllcihsYXllcnMsIGNvbXBhY3QpIHtcbiAgICAgICAgICAgIHJldHVybiAoKGNvbXBhY3QgPyA4OCA6IDExMikgKyAxNiAqIGxheWVycykgKiBsYXllcnM7XG4gICAgICAgIH1cbiAgICB9XG4gICAgRW5jb2RlciQxLkRFRkFVTFRfRUNfUEVSQ0VOVCA9IDMzOyAvLyBkZWZhdWx0IG1pbmltYWwgcGVyY2VudGFnZSBvZiBlcnJvciBjaGVjayB3b3Jkc1xuICAgIEVuY29kZXIkMS5ERUZBVUxUX0FaVEVDX0xBWUVSUyA9IDA7XG4gICAgRW5jb2RlciQxLk1BWF9OQl9CSVRTID0gMzI7XG4gICAgRW5jb2RlciQxLk1BWF9OQl9CSVRTX0NPTVBBQ1QgPSA0O1xuICAgIEVuY29kZXIkMS5XT1JEX1NJWkUgPSBJbnQzMkFycmF5LmZyb20oW1xuICAgICAgICA0LCA2LCA2LCA4LCA4LCA4LCA4LCA4LCA4LCAxMCwgMTAsIDEwLCAxMCwgMTAsIDEwLCAxMCwgMTAsIDEwLCAxMCwgMTAsIDEwLCAxMCwgMTAsXG4gICAgICAgIDEyLCAxMiwgMTIsIDEyLCAxMiwgMTIsIDEyLCAxMiwgMTIsIDEyXG4gICAgXSk7XG5cbiAgICAvKlxuICAgICogQ29weXJpZ2h0IDIwMTMgWlhpbmcgYXV0aG9yc1xuICAgICpcbiAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAqXG4gICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICpcbiAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgKi9cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIGFuIEF6dGVjIGNvZGUgYXMgYSB7QGxpbmsgQml0TWF0cml4fS5cbiAgICAgKi9cbiAgICAvKnB1YmxpYyBmaW5hbCovIGNsYXNzIEF6dGVjV3JpdGVyIHtcbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIGVuY29kZShjb250ZW50cywgZm9ybWF0LCB3aWR0aCwgaGVpZ2h0KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lbmNvZGVXaXRoSGludHMoY29udGVudHMsIGZvcm1hdCwgd2lkdGgsIGhlaWdodCwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIGVuY29kZVdpdGhIaW50cyhjb250ZW50cywgZm9ybWF0LCB3aWR0aCwgaGVpZ2h0LCBoaW50cykge1xuICAgICAgICAgICAgbGV0IGNoYXJzZXQgPSBTdGFuZGFyZENoYXJzZXRzLklTT184ODU5XzE7XG4gICAgICAgICAgICBsZXQgZWNjUGVyY2VudCA9IEVuY29kZXIkMS5ERUZBVUxUX0VDX1BFUkNFTlQ7XG4gICAgICAgICAgICBsZXQgbGF5ZXJzID0gRW5jb2RlciQxLkRFRkFVTFRfQVpURUNfTEFZRVJTO1xuICAgICAgICAgICAgaWYgKGhpbnRzICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAoaGludHMuaGFzKEVuY29kZUhpbnRUeXBlJDEuQ0hBUkFDVEVSX1NFVCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hhcnNldCA9IENoYXJzZXQuZm9yTmFtZShoaW50cy5nZXQoRW5jb2RlSGludFR5cGUkMS5DSEFSQUNURVJfU0VUKS50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGhpbnRzLmhhcyhFbmNvZGVIaW50VHlwZSQxLkVSUk9SX0NPUlJFQ1RJT04pKSB7XG4gICAgICAgICAgICAgICAgICAgIGVjY1BlcmNlbnQgPSBJbnRlZ2VyLnBhcnNlSW50KGhpbnRzLmdldChFbmNvZGVIaW50VHlwZSQxLkVSUk9SX0NPUlJFQ1RJT04pLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoaGludHMuaGFzKEVuY29kZUhpbnRUeXBlJDEuQVpURUNfTEFZRVJTKSkge1xuICAgICAgICAgICAgICAgICAgICBsYXllcnMgPSBJbnRlZ2VyLnBhcnNlSW50KGhpbnRzLmdldChFbmNvZGVIaW50VHlwZSQxLkFaVEVDX0xBWUVSUykudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIEF6dGVjV3JpdGVyLmVuY29kZUxheWVycyhjb250ZW50cywgZm9ybWF0LCB3aWR0aCwgaGVpZ2h0LCBjaGFyc2V0LCBlY2NQZXJjZW50LCBsYXllcnMpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBlbmNvZGVMYXllcnMoY29udGVudHMsIGZvcm1hdCwgd2lkdGgsIGhlaWdodCwgY2hhcnNldCwgZWNjUGVyY2VudCwgbGF5ZXJzKSB7XG4gICAgICAgICAgICBpZiAoZm9ybWF0ICE9PSBCYXJjb2RlRm9ybWF0JDEuQVpURUMpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdDYW4gb25seSBlbmNvZGUgQVpURUMsIGJ1dCBnb3QgJyArIGZvcm1hdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgYXp0ZWMgPSBFbmNvZGVyJDEuZW5jb2RlKFN0cmluZ1V0aWxzLmdldEJ5dGVzKGNvbnRlbnRzLCBjaGFyc2V0KSwgZWNjUGVyY2VudCwgbGF5ZXJzKTtcbiAgICAgICAgICAgIHJldHVybiBBenRlY1dyaXRlci5yZW5kZXJSZXN1bHQoYXp0ZWMsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyByZW5kZXJSZXN1bHQoY29kZSwgd2lkdGgsIGhlaWdodCkge1xuICAgICAgICAgICAgbGV0IGlucHV0ID0gY29kZS5nZXRNYXRyaXgoKTtcbiAgICAgICAgICAgIGlmIChpbnB1dCA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGlucHV0V2lkdGggPSBpbnB1dC5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgbGV0IGlucHV0SGVpZ2h0ID0gaW5wdXQuZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICBsZXQgb3V0cHV0V2lkdGggPSBNYXRoLm1heCh3aWR0aCwgaW5wdXRXaWR0aCk7XG4gICAgICAgICAgICBsZXQgb3V0cHV0SGVpZ2h0ID0gTWF0aC5tYXgoaGVpZ2h0LCBpbnB1dEhlaWdodCk7XG4gICAgICAgICAgICBsZXQgbXVsdGlwbGUgPSBNYXRoLm1pbihvdXRwdXRXaWR0aCAvIGlucHV0V2lkdGgsIG91dHB1dEhlaWdodCAvIGlucHV0SGVpZ2h0KTtcbiAgICAgICAgICAgIGxldCBsZWZ0UGFkZGluZyA9IChvdXRwdXRXaWR0aCAtIChpbnB1dFdpZHRoICogbXVsdGlwbGUpKSAvIDI7XG4gICAgICAgICAgICBsZXQgdG9wUGFkZGluZyA9IChvdXRwdXRIZWlnaHQgLSAoaW5wdXRIZWlnaHQgKiBtdWx0aXBsZSkpIC8gMjtcbiAgICAgICAgICAgIGxldCBvdXRwdXQgPSBuZXcgQml0TWF0cml4KG91dHB1dFdpZHRoLCBvdXRwdXRIZWlnaHQpO1xuICAgICAgICAgICAgZm9yIChsZXQgaW5wdXRZIC8qaW50Ki8gPSAwLCBvdXRwdXRZID0gdG9wUGFkZGluZzsgaW5wdXRZIDwgaW5wdXRIZWlnaHQ7IGlucHV0WSsrLCBvdXRwdXRZICs9IG11bHRpcGxlKSB7XG4gICAgICAgICAgICAgICAgLy8gV3JpdGUgdGhlIGNvbnRlbnRzIG9mIHRoaXMgcm93IG9mIHRoZSBiYXJjb2RlXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaW5wdXRYIC8qaW50Ki8gPSAwLCBvdXRwdXRYID0gbGVmdFBhZGRpbmc7IGlucHV0WCA8IGlucHV0V2lkdGg7IGlucHV0WCsrLCBvdXRwdXRYICs9IG11bHRpcGxlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dC5nZXQoaW5wdXRYLCBpbnB1dFkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQuc2V0UmVnaW9uKG91dHB1dFgsIG91dHB1dFksIG11bHRpcGxlLCBtdWx0aXBsZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3V0cHV0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZXhwb3J0cy5BYnN0cmFjdEV4cGFuZGVkRGVjb2RlciA9IEFic3RyYWN0RXhwYW5kZWREZWNvZGVyO1xuICAgIGV4cG9ydHMuQXJndW1lbnRFeGNlcHRpb24gPSBBcmd1bWVudEV4Y2VwdGlvbjtcbiAgICBleHBvcnRzLkFyaXRobWV0aWNFeGNlcHRpb24gPSBBcml0aG1ldGljRXhjZXB0aW9uO1xuICAgIGV4cG9ydHMuQXp0ZWNDb2RlID0gQXp0ZWNDb2RlO1xuICAgIGV4cG9ydHMuQXp0ZWNDb2RlUmVhZGVyID0gQXp0ZWNSZWFkZXI7XG4gICAgZXhwb3J0cy5BenRlY0NvZGVXcml0ZXIgPSBBenRlY1dyaXRlcjtcbiAgICBleHBvcnRzLkF6dGVjRGVjb2RlciA9IERlY29kZXI7XG4gICAgZXhwb3J0cy5BenRlY0RldGVjdG9yID0gRGV0ZWN0b3I7XG4gICAgZXhwb3J0cy5BenRlY0RldGVjdG9yUmVzdWx0ID0gQXp0ZWNEZXRlY3RvclJlc3VsdDtcbiAgICBleHBvcnRzLkF6dGVjRW5jb2RlciA9IEVuY29kZXIkMTtcbiAgICBleHBvcnRzLkF6dGVjSGlnaExldmVsRW5jb2RlciA9IEhpZ2hMZXZlbEVuY29kZXI7XG4gICAgZXhwb3J0cy5BenRlY1BvaW50ID0gUG9pbnQ7XG4gICAgZXhwb3J0cy5CYXJjb2RlRm9ybWF0ID0gQmFyY29kZUZvcm1hdCQxO1xuICAgIGV4cG9ydHMuQmluYXJpemVyID0gQmluYXJpemVyO1xuICAgIGV4cG9ydHMuQmluYXJ5Qml0bWFwID0gQmluYXJ5Qml0bWFwO1xuICAgIGV4cG9ydHMuQml0QXJyYXkgPSBCaXRBcnJheTtcbiAgICBleHBvcnRzLkJpdE1hdHJpeCA9IEJpdE1hdHJpeDtcbiAgICBleHBvcnRzLkJpdFNvdXJjZSA9IEJpdFNvdXJjZTtcbiAgICBleHBvcnRzLkJyb3dzZXJBenRlY0NvZGVSZWFkZXIgPSBCcm93c2VyQXp0ZWNDb2RlUmVhZGVyO1xuICAgIGV4cG9ydHMuQnJvd3NlckJhcmNvZGVSZWFkZXIgPSBCcm93c2VyQmFyY29kZVJlYWRlcjtcbiAgICBleHBvcnRzLkJyb3dzZXJDb2RlUmVhZGVyID0gQnJvd3NlckNvZGVSZWFkZXI7XG4gICAgZXhwb3J0cy5Ccm93c2VyRGF0YW1hdHJpeENvZGVSZWFkZXIgPSBCcm93c2VyRGF0YW1hdHJpeENvZGVSZWFkZXI7XG4gICAgZXhwb3J0cy5Ccm93c2VyTXVsdGlGb3JtYXRSZWFkZXIgPSBCcm93c2VyTXVsdGlGb3JtYXRSZWFkZXI7XG4gICAgZXhwb3J0cy5Ccm93c2VyUERGNDE3UmVhZGVyID0gQnJvd3NlclBERjQxN1JlYWRlcjtcbiAgICBleHBvcnRzLkJyb3dzZXJRUkNvZGVSZWFkZXIgPSBCcm93c2VyUVJDb2RlUmVhZGVyO1xuICAgIGV4cG9ydHMuQnJvd3NlclFSQ29kZVN2Z1dyaXRlciA9IEJyb3dzZXJRUkNvZGVTdmdXcml0ZXI7XG4gICAgZXhwb3J0cy5DaGFyYWN0ZXJTZXRFQ0kgPSBDaGFyYWN0ZXJTZXRFQ0k7XG4gICAgZXhwb3J0cy5DaGVja3N1bUV4Y2VwdGlvbiA9IENoZWNrc3VtRXhjZXB0aW9uO1xuICAgIGV4cG9ydHMuQ29kZTEyOFJlYWRlciA9IENvZGUxMjhSZWFkZXI7XG4gICAgZXhwb3J0cy5Db2RlMzlSZWFkZXIgPSBDb2RlMzlSZWFkZXI7XG4gICAgZXhwb3J0cy5EYXRhTWF0cml4RGVjb2RlZEJpdFN0cmVhbVBhcnNlciA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXI7XG4gICAgZXhwb3J0cy5EYXRhTWF0cml4UmVhZGVyID0gRGF0YU1hdHJpeFJlYWRlcjtcbiAgICBleHBvcnRzLkRlY29kZUhpbnRUeXBlID0gRGVjb2RlSGludFR5cGUkMTtcbiAgICBleHBvcnRzLkRlY29kZXJSZXN1bHQgPSBEZWNvZGVyUmVzdWx0O1xuICAgIGV4cG9ydHMuRGVmYXVsdEdyaWRTYW1wbGVyID0gRGVmYXVsdEdyaWRTYW1wbGVyO1xuICAgIGV4cG9ydHMuRGV0ZWN0b3JSZXN1bHQgPSBEZXRlY3RvclJlc3VsdDtcbiAgICBleHBvcnRzLkVBTjEzUmVhZGVyID0gRUFOMTNSZWFkZXI7XG4gICAgZXhwb3J0cy5FbmNvZGVIaW50VHlwZSA9IEVuY29kZUhpbnRUeXBlJDE7XG4gICAgZXhwb3J0cy5FeGNlcHRpb24gPSBFeGNlcHRpb247XG4gICAgZXhwb3J0cy5Gb3JtYXRFeGNlcHRpb24gPSBGb3JtYXRFeGNlcHRpb247XG4gICAgZXhwb3J0cy5HZW5lcmljR0YgPSBHZW5lcmljR0Y7XG4gICAgZXhwb3J0cy5HZW5lcmljR0ZQb2x5ID0gR2VuZXJpY0dGUG9seTtcbiAgICBleHBvcnRzLkdsb2JhbEhpc3RvZ3JhbUJpbmFyaXplciA9IEdsb2JhbEhpc3RvZ3JhbUJpbmFyaXplcjtcbiAgICBleHBvcnRzLkdyaWRTYW1wbGVyID0gR3JpZFNhbXBsZXI7XG4gICAgZXhwb3J0cy5HcmlkU2FtcGxlckluc3RhbmNlID0gR3JpZFNhbXBsZXJJbnN0YW5jZTtcbiAgICBleHBvcnRzLkhUTUxDYW52YXNFbGVtZW50THVtaW5hbmNlU291cmNlID0gSFRNTENhbnZhc0VsZW1lbnRMdW1pbmFuY2VTb3VyY2U7XG4gICAgZXhwb3J0cy5IeWJyaWRCaW5hcml6ZXIgPSBIeWJyaWRCaW5hcml6ZXI7XG4gICAgZXhwb3J0cy5JVEZSZWFkZXIgPSBJVEZSZWFkZXI7XG4gICAgZXhwb3J0cy5JbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24gPSBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb247XG4gICAgZXhwb3J0cy5JbGxlZ2FsU3RhdGVFeGNlcHRpb24gPSBJbGxlZ2FsU3RhdGVFeGNlcHRpb247XG4gICAgZXhwb3J0cy5JbnZlcnRlZEx1bWluYW5jZVNvdXJjZSA9IEludmVydGVkTHVtaW5hbmNlU291cmNlO1xuICAgIGV4cG9ydHMuTHVtaW5hbmNlU291cmNlID0gTHVtaW5hbmNlU291cmNlO1xuICAgIGV4cG9ydHMuTWF0aFV0aWxzID0gTWF0aFV0aWxzO1xuICAgIGV4cG9ydHMuTXVsdGlGb3JtYXRPbmVEUmVhZGVyID0gTXVsdGlGb3JtYXRPbmVEUmVhZGVyO1xuICAgIGV4cG9ydHMuTXVsdGlGb3JtYXRSZWFkZXIgPSBNdWx0aUZvcm1hdFJlYWRlcjtcbiAgICBleHBvcnRzLk11bHRpRm9ybWF0V3JpdGVyID0gTXVsdGlGb3JtYXRXcml0ZXI7XG4gICAgZXhwb3J0cy5Ob3RGb3VuZEV4Y2VwdGlvbiA9IE5vdEZvdW5kRXhjZXB0aW9uO1xuICAgIGV4cG9ydHMuT25lRFJlYWRlciA9IE9uZURSZWFkZXI7XG4gICAgZXhwb3J0cy5QREY0MTdEZWNvZGVkQml0U3RyZWFtUGFyc2VyID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyO1xuICAgIGV4cG9ydHMuUERGNDE3RGVjb2RlckVycm9yQ29ycmVjdGlvbiA9IEVycm9yQ29ycmVjdGlvbjtcbiAgICBleHBvcnRzLlBERjQxN1JlYWRlciA9IFBERjQxN1JlYWRlcjtcbiAgICBleHBvcnRzLlBERjQxN1Jlc3VsdE1ldGFkYXRhID0gUERGNDE3UmVzdWx0TWV0YWRhdGE7XG4gICAgZXhwb3J0cy5QZXJzcGVjdGl2ZVRyYW5zZm9ybSA9IFBlcnNwZWN0aXZlVHJhbnNmb3JtO1xuICAgIGV4cG9ydHMuUGxhbmFyWVVWTHVtaW5hbmNlU291cmNlID0gUGxhbmFyWVVWTHVtaW5hbmNlU291cmNlO1xuICAgIGV4cG9ydHMuUVJDb2RlQnl0ZU1hdHJpeCA9IEJ5dGVNYXRyaXg7XG4gICAgZXhwb3J0cy5RUkNvZGVEYXRhTWFzayA9IERhdGFNYXNrO1xuICAgIGV4cG9ydHMuUVJDb2RlRGVjb2RlZEJpdFN0cmVhbVBhcnNlciA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMTtcbiAgICBleHBvcnRzLlFSQ29kZURlY29kZXJFcnJvckNvcnJlY3Rpb25MZXZlbCA9IEVycm9yQ29ycmVjdGlvbkxldmVsO1xuICAgIGV4cG9ydHMuUVJDb2RlRGVjb2RlckZvcm1hdEluZm9ybWF0aW9uID0gRm9ybWF0SW5mb3JtYXRpb247XG4gICAgZXhwb3J0cy5RUkNvZGVFbmNvZGVyID0gRW5jb2RlcjtcbiAgICBleHBvcnRzLlFSQ29kZUVuY29kZXJRUkNvZGUgPSBRUkNvZGU7XG4gICAgZXhwb3J0cy5RUkNvZGVNYXNrVXRpbCA9IE1hc2tVdGlsO1xuICAgIGV4cG9ydHMuUVJDb2RlTWF0cml4VXRpbCA9IE1hdHJpeFV0aWw7XG4gICAgZXhwb3J0cy5RUkNvZGVNb2RlID0gTW9kZSQxO1xuICAgIGV4cG9ydHMuUVJDb2RlUmVhZGVyID0gUVJDb2RlUmVhZGVyO1xuICAgIGV4cG9ydHMuUVJDb2RlVmVyc2lvbiA9IFZlcnNpb24kMTtcbiAgICBleHBvcnRzLlFSQ29kZVdyaXRlciA9IFFSQ29kZVdyaXRlcjtcbiAgICBleHBvcnRzLlJHQkx1bWluYW5jZVNvdXJjZSA9IFJHQkx1bWluYW5jZVNvdXJjZTtcbiAgICBleHBvcnRzLlJTUzE0UmVhZGVyID0gUlNTMTRSZWFkZXI7XG4gICAgZXhwb3J0cy5SU1NFeHBhbmRlZFJlYWRlciA9IFJTU0V4cGFuZGVkUmVhZGVyO1xuICAgIGV4cG9ydHMuUmVhZGVyRXhjZXB0aW9uID0gUmVhZGVyRXhjZXB0aW9uO1xuICAgIGV4cG9ydHMuUmVlZFNvbG9tb25EZWNvZGVyID0gUmVlZFNvbG9tb25EZWNvZGVyO1xuICAgIGV4cG9ydHMuUmVlZFNvbG9tb25FbmNvZGVyID0gUmVlZFNvbG9tb25FbmNvZGVyO1xuICAgIGV4cG9ydHMuUmVlZFNvbG9tb25FeGNlcHRpb24gPSBSZWVkU29sb21vbkV4Y2VwdGlvbjtcbiAgICBleHBvcnRzLlJlc3VsdCA9IFJlc3VsdDtcbiAgICBleHBvcnRzLlJlc3VsdE1ldGFkYXRhVHlwZSA9IFJlc3VsdE1ldGFkYXRhVHlwZSQxO1xuICAgIGV4cG9ydHMuUmVzdWx0UG9pbnQgPSBSZXN1bHRQb2ludDtcbiAgICBleHBvcnRzLlN0cmluZ1V0aWxzID0gU3RyaW5nVXRpbHM7XG4gICAgZXhwb3J0cy5VbnN1cHBvcnRlZE9wZXJhdGlvbkV4Y2VwdGlvbiA9IFVuc3VwcG9ydGVkT3BlcmF0aW9uRXhjZXB0aW9uO1xuICAgIGV4cG9ydHMuVmlkZW9JbnB1dERldmljZSA9IFZpZGVvSW5wdXREZXZpY2U7XG4gICAgZXhwb3J0cy5XaGl0ZVJlY3RhbmdsZURldGVjdG9yID0gV2hpdGVSZWN0YW5nbGVEZXRlY3RvcjtcbiAgICBleHBvcnRzLldyaXRlckV4Y2VwdGlvbiA9IFdyaXRlckV4Y2VwdGlvbjtcbiAgICBleHBvcnRzLlpYaW5nQXJyYXlzID0gQXJyYXlzO1xuICAgIGV4cG9ydHMuWlhpbmdDaGFyc2V0ID0gQ2hhcnNldDtcbiAgICBleHBvcnRzLlpYaW5nSW50ZWdlciA9IEludGVnZXI7XG4gICAgZXhwb3J0cy5aWGluZ1N0YW5kYXJkQ2hhcnNldHMgPSBTdGFuZGFyZENoYXJzZXRzO1xuICAgIGV4cG9ydHMuWlhpbmdTdHJpbmdCdWlsZGVyID0gU3RyaW5nQnVpbGRlcjtcbiAgICBleHBvcnRzLlpYaW5nU3RyaW5nRW5jb2RpbmcgPSBTdHJpbmdFbmNvZGluZztcbiAgICBleHBvcnRzLlpYaW5nU3lzdGVtID0gU3lzdGVtO1xuICAgIGV4cG9ydHMuY3JlYXRlQWJzdHJhY3RFeHBhbmRlZERlY29kZXIgPSBjcmVhdGVEZWNvZGVyO1xuXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///817\n")},645:(__unused_webpack_module,exports)=>{eval("/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */\nexports.read = function (buffer, offset, isLE, mLen, nBytes) {\n  var e, m\n  var eLen = (nBytes * 8) - mLen - 1\n  var eMax = (1 << eLen) - 1\n  var eBias = eMax >> 1\n  var nBits = -7\n  var i = isLE ? (nBytes - 1) : 0\n  var d = isLE ? -1 : 1\n  var s = buffer[offset + i]\n\n  i += d\n\n  e = s & ((1 << (-nBits)) - 1)\n  s >>= (-nBits)\n  nBits += eLen\n  for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {}\n\n  m = e & ((1 << (-nBits)) - 1)\n  e >>= (-nBits)\n  nBits += mLen\n  for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {}\n\n  if (e === 0) {\n    e = 1 - eBias\n  } else if (e === eMax) {\n    return m ? NaN : ((s ? -1 : 1) * Infinity)\n  } else {\n    m = m + Math.pow(2, mLen)\n    e = e - eBias\n  }\n  return (s ? -1 : 1) * m * Math.pow(2, e - mLen)\n}\n\nexports.write = function (buffer, value, offset, isLE, mLen, nBytes) {\n  var e, m, c\n  var eLen = (nBytes * 8) - mLen - 1\n  var eMax = (1 << eLen) - 1\n  var eBias = eMax >> 1\n  var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)\n  var i = isLE ? 0 : (nBytes - 1)\n  var d = isLE ? 1 : -1\n  var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0\n\n  value = Math.abs(value)\n\n  if (isNaN(value) || value === Infinity) {\n    m = isNaN(value) ? 1 : 0\n    e = eMax\n  } else {\n    e = Math.floor(Math.log(value) / Math.LN2)\n    if (value * (c = Math.pow(2, -e)) < 1) {\n      e--\n      c *= 2\n    }\n    if (e + eBias >= 1) {\n      value += rt / c\n    } else {\n      value += rt * Math.pow(2, 1 - eBias)\n    }\n    if (value * c >= 2) {\n      e++\n      c /= 2\n    }\n\n    if (e + eBias >= eMax) {\n      m = 0\n      e = eMax\n    } else if (e + eBias >= 1) {\n      m = ((value * c) - 1) * Math.pow(2, mLen)\n      e = e + eBias\n    } else {\n      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)\n      e = 0\n    }\n  }\n\n  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}\n\n  e = (e << mLen) | m\n  eLen += mLen\n  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}\n\n  buffer[offset + i - d] |= s * 128\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNjQ1LmpzIiwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2llZWU3NTQvaW5kZXguanM/OTE1MiJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiEgaWVlZTc1NC4gQlNELTMtQ2xhdXNlIExpY2Vuc2UuIEZlcm9zcyBBYm91a2hhZGlqZWggPGh0dHBzOi8vZmVyb3NzLm9yZy9vcGVuc291cmNlPiAqL1xuZXhwb3J0cy5yZWFkID0gZnVuY3Rpb24gKGJ1ZmZlciwgb2Zmc2V0LCBpc0xFLCBtTGVuLCBuQnl0ZXMpIHtcbiAgdmFyIGUsIG1cbiAgdmFyIGVMZW4gPSAobkJ5dGVzICogOCkgLSBtTGVuIC0gMVxuICB2YXIgZU1heCA9ICgxIDw8IGVMZW4pIC0gMVxuICB2YXIgZUJpYXMgPSBlTWF4ID4+IDFcbiAgdmFyIG5CaXRzID0gLTdcbiAgdmFyIGkgPSBpc0xFID8gKG5CeXRlcyAtIDEpIDogMFxuICB2YXIgZCA9IGlzTEUgPyAtMSA6IDFcbiAgdmFyIHMgPSBidWZmZXJbb2Zmc2V0ICsgaV1cblxuICBpICs9IGRcblxuICBlID0gcyAmICgoMSA8PCAoLW5CaXRzKSkgLSAxKVxuICBzID4+PSAoLW5CaXRzKVxuICBuQml0cyArPSBlTGVuXG4gIGZvciAoOyBuQml0cyA+IDA7IGUgPSAoZSAqIDI1NikgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCkge31cblxuICBtID0gZSAmICgoMSA8PCAoLW5CaXRzKSkgLSAxKVxuICBlID4+PSAoLW5CaXRzKVxuICBuQml0cyArPSBtTGVuXG4gIGZvciAoOyBuQml0cyA+IDA7IG0gPSAobSAqIDI1NikgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCkge31cblxuICBpZiAoZSA9PT0gMCkge1xuICAgIGUgPSAxIC0gZUJpYXNcbiAgfSBlbHNlIGlmIChlID09PSBlTWF4KSB7XG4gICAgcmV0dXJuIG0gPyBOYU4gOiAoKHMgPyAtMSA6IDEpICogSW5maW5pdHkpXG4gIH0gZWxzZSB7XG4gICAgbSA9IG0gKyBNYXRoLnBvdygyLCBtTGVuKVxuICAgIGUgPSBlIC0gZUJpYXNcbiAgfVxuICByZXR1cm4gKHMgPyAtMSA6IDEpICogbSAqIE1hdGgucG93KDIsIGUgLSBtTGVuKVxufVxuXG5leHBvcnRzLndyaXRlID0gZnVuY3Rpb24gKGJ1ZmZlciwgdmFsdWUsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtLCBjXG4gIHZhciBlTGVuID0gKG5CeXRlcyAqIDgpIC0gbUxlbiAtIDFcbiAgdmFyIGVNYXggPSAoMSA8PCBlTGVuKSAtIDFcbiAgdmFyIGVCaWFzID0gZU1heCA+PiAxXG4gIHZhciBydCA9IChtTGVuID09PSAyMyA/IE1hdGgucG93KDIsIC0yNCkgLSBNYXRoLnBvdygyLCAtNzcpIDogMClcbiAgdmFyIGkgPSBpc0xFID8gMCA6IChuQnl0ZXMgLSAxKVxuICB2YXIgZCA9IGlzTEUgPyAxIDogLTFcbiAgdmFyIHMgPSB2YWx1ZSA8IDAgfHwgKHZhbHVlID09PSAwICYmIDEgLyB2YWx1ZSA8IDApID8gMSA6IDBcblxuICB2YWx1ZSA9IE1hdGguYWJzKHZhbHVlKVxuXG4gIGlmIChpc05hTih2YWx1ZSkgfHwgdmFsdWUgPT09IEluZmluaXR5KSB7XG4gICAgbSA9IGlzTmFOKHZhbHVlKSA/IDEgOiAwXG4gICAgZSA9IGVNYXhcbiAgfSBlbHNlIHtcbiAgICBlID0gTWF0aC5mbG9vcihNYXRoLmxvZyh2YWx1ZSkgLyBNYXRoLkxOMilcbiAgICBpZiAodmFsdWUgKiAoYyA9IE1hdGgucG93KDIsIC1lKSkgPCAxKSB7XG4gICAgICBlLS1cbiAgICAgIGMgKj0gMlxuICAgIH1cbiAgICBpZiAoZSArIGVCaWFzID49IDEpIHtcbiAgICAgIHZhbHVlICs9IHJ0IC8gY1xuICAgIH0gZWxzZSB7XG4gICAgICB2YWx1ZSArPSBydCAqIE1hdGgucG93KDIsIDEgLSBlQmlhcylcbiAgICB9XG4gICAgaWYgKHZhbHVlICogYyA+PSAyKSB7XG4gICAgICBlKytcbiAgICAgIGMgLz0gMlxuICAgIH1cblxuICAgIGlmIChlICsgZUJpYXMgPj0gZU1heCkge1xuICAgICAgbSA9IDBcbiAgICAgIGUgPSBlTWF4XG4gICAgfSBlbHNlIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgbSA9ICgodmFsdWUgKiBjKSAtIDEpICogTWF0aC5wb3coMiwgbUxlbilcbiAgICAgIGUgPSBlICsgZUJpYXNcbiAgICB9IGVsc2Uge1xuICAgICAgbSA9IHZhbHVlICogTWF0aC5wb3coMiwgZUJpYXMgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pXG4gICAgICBlID0gMFxuICAgIH1cbiAgfVxuXG4gIGZvciAoOyBtTGVuID49IDg7IGJ1ZmZlcltvZmZzZXQgKyBpXSA9IG0gJiAweGZmLCBpICs9IGQsIG0gLz0gMjU2LCBtTGVuIC09IDgpIHt9XG5cbiAgZSA9IChlIDw8IG1MZW4pIHwgbVxuICBlTGVuICs9IG1MZW5cbiAgZm9yICg7IGVMZW4gPiAwOyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBlICYgMHhmZiwgaSArPSBkLCBlIC89IDI1NiwgZUxlbiAtPSA4KSB7fVxuXG4gIGJ1ZmZlcltvZmZzZXQgKyBpIC0gZF0gfD0gcyAqIDEyOFxufVxuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///645\n")}},__webpack_module_cache__={};function __webpack_require__(g){var I=__webpack_module_cache__[g];if(void 0!==I)return I.exports;var C=__webpack_module_cache__[g]={exports:{}};return __webpack_modules__[g].call(C.exports,C,C.exports,__webpack_require__),C.exports}__webpack_require__.d=(g,I)=>{for(var C in I)__webpack_require__.o(I,C)&&!__webpack_require__.o(g,C)&&Object.defineProperty(g,C,{enumerable:!0,get:I[C]})},__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(g){if("object"==typeof window)return window}}(),__webpack_require__.o=(g,I)=>Object.prototype.hasOwnProperty.call(g,I),__webpack_require__.r=g=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(g,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(g,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__(244);lib=__webpack_exports__})();
\ No newline at end of file
+/*
+ * ATTENTION: An "eval-source-map" devtool has been used.
+ * This devtool is neither made for production nor for readable output files.
+ * It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
+ * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
+ * or disable the default devtool with "devtool: false".
+ * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
+ */
+var lib;
+/******/ (() => { // webpackBootstrap
+/******/ 	var __webpack_modules__ = ({
+
+/***/ "./src/js/main.js":
+/*!************************!*\
+  !*** ./src/js/main.js ***!
+  \************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   addItemByTag: () => (/* binding */ addItemByTag),\n/* harmony export */   addItemImage: () => (/* binding */ addItemImage),\n/* harmony export */   addItemScan: () => (/* binding */ addItemScan),\n/* harmony export */   checkinItems: () => (/* binding */ checkinItems),\n/* harmony export */   checkoutByTag: () => (/* binding */ checkoutByTag),\n/* harmony export */   checkoutItem: () => (/* binding */ checkoutItem),\n/* harmony export */   decreaseItemCount: () => (/* binding */ decreaseItemCount),\n/* harmony export */   increaseItemCount: () => (/* binding */ increaseItemCount),\n/* harmony export */   loadStorages: () => (/* binding */ loadStorages),\n/* harmony export */   onPageLoad: () => (/* binding */ onPageLoad),\n/* harmony export */   onTagInputChanged: () => (/* binding */ onTagInputChanged),\n/* harmony export */   onTagTextUpdate: () => (/* binding */ onTagTextUpdate),\n/* harmony export */   scanReceiver: () => (/* binding */ scanReceiver),\n/* harmony export */   stopScanningItem: () => (/* binding */ stopScanningItem)\n/* harmony export */ });\n/* harmony import */ var html5_qrcode__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! html5-qrcode */ \"./node_modules/html5-qrcode/esm/index.js\");\n/* harmony import */ var _noble_curves_ed448__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @noble/curves/ed448 */ \"./node_modules/@noble/curves/esm/ed448.js\");\n/* harmony import */ var buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! buffer */ \"./node_modules/buffer/index.js\");\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }, _typeof(obj); }\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }\nfunction _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : \"undefined\" != typeof Symbol && arr[Symbol.iterator] || arr[\"@@iterator\"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i[\"return\"] && (_r = _i[\"return\"](), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return exports; }; var exports = {}, Op = Object.prototype, hasOwn = Op.hasOwnProperty, defineProperty = Object.defineProperty || function (obj, key, desc) { obj[key] = desc.value; }, $Symbol = \"function\" == typeof Symbol ? Symbol : {}, iteratorSymbol = $Symbol.iterator || \"@@iterator\", asyncIteratorSymbol = $Symbol.asyncIterator || \"@@asyncIterator\", toStringTagSymbol = $Symbol.toStringTag || \"@@toStringTag\"; function define(obj, key, value) { return Object.defineProperty(obj, key, { value: value, enumerable: !0, configurable: !0, writable: !0 }), obj[key]; } try { define({}, \"\"); } catch (err) { define = function define(obj, key, value) { return obj[key] = value; }; } function wrap(innerFn, outerFn, self, tryLocsList) { var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator, generator = Object.create(protoGenerator.prototype), context = new Context(tryLocsList || []); return defineProperty(generator, \"_invoke\", { value: makeInvokeMethod(innerFn, self, context) }), generator; } function tryCatch(fn, obj, arg) { try { return { type: \"normal\", arg: fn.call(obj, arg) }; } catch (err) { return { type: \"throw\", arg: err }; } } exports.wrap = wrap; var ContinueSentinel = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var IteratorPrototype = {}; define(IteratorPrototype, iteratorSymbol, function () { return this; }); var getProto = Object.getPrototypeOf, NativeIteratorPrototype = getProto && getProto(getProto(values([]))); NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype); var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype); function defineIteratorMethods(prototype) { [\"next\", \"throw\", \"return\"].forEach(function (method) { define(prototype, method, function (arg) { return this._invoke(method, arg); }); }); } function AsyncIterator(generator, PromiseImpl) { function invoke(method, arg, resolve, reject) { var record = tryCatch(generator[method], generator, arg); if (\"throw\" !== record.type) { var result = record.arg, value = result.value; return value && \"object\" == _typeof(value) && hasOwn.call(value, \"__await\") ? PromiseImpl.resolve(value.__await).then(function (value) { invoke(\"next\", value, resolve, reject); }, function (err) { invoke(\"throw\", err, resolve, reject); }) : PromiseImpl.resolve(value).then(function (unwrapped) { result.value = unwrapped, resolve(result); }, function (error) { return invoke(\"throw\", error, resolve, reject); }); } reject(record.arg); } var previousPromise; defineProperty(this, \"_invoke\", { value: function value(method, arg) { function callInvokeWithMethodAndArg() { return new PromiseImpl(function (resolve, reject) { invoke(method, arg, resolve, reject); }); } return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(innerFn, self, context) { var state = \"suspendedStart\"; return function (method, arg) { if (\"executing\" === state) throw new Error(\"Generator is already running\"); if (\"completed\" === state) { if (\"throw\" === method) throw arg; return doneResult(); } for (context.method = method, context.arg = arg;;) { var delegate = context.delegate; if (delegate) { var delegateResult = maybeInvokeDelegate(delegate, context); if (delegateResult) { if (delegateResult === ContinueSentinel) continue; return delegateResult; } } if (\"next\" === context.method) context.sent = context._sent = context.arg;else if (\"throw\" === context.method) { if (\"suspendedStart\" === state) throw state = \"completed\", context.arg; context.dispatchException(context.arg); } else \"return\" === context.method && context.abrupt(\"return\", context.arg); state = \"executing\"; var record = tryCatch(innerFn, self, context); if (\"normal\" === record.type) { if (state = context.done ? \"completed\" : \"suspendedYield\", record.arg === ContinueSentinel) continue; return { value: record.arg, done: context.done }; } \"throw\" === record.type && (state = \"completed\", context.method = \"throw\", context.arg = record.arg); } }; } function maybeInvokeDelegate(delegate, context) { var methodName = context.method, method = delegate.iterator[methodName]; if (undefined === method) return context.delegate = null, \"throw\" === methodName && delegate.iterator[\"return\"] && (context.method = \"return\", context.arg = undefined, maybeInvokeDelegate(delegate, context), \"throw\" === context.method) || \"return\" !== methodName && (context.method = \"throw\", context.arg = new TypeError(\"The iterator does not provide a '\" + methodName + \"' method\")), ContinueSentinel; var record = tryCatch(method, delegate.iterator, context.arg); if (\"throw\" === record.type) return context.method = \"throw\", context.arg = record.arg, context.delegate = null, ContinueSentinel; var info = record.arg; return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, \"return\" !== context.method && (context.method = \"next\", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = \"throw\", context.arg = new TypeError(\"iterator result is not an object\"), context.delegate = null, ContinueSentinel); } function pushTryEntry(locs) { var entry = { tryLoc: locs[0] }; 1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry); } function resetTryEntry(entry) { var record = entry.completion || {}; record.type = \"normal\", delete record.arg, entry.completion = record; } function Context(tryLocsList) { this.tryEntries = [{ tryLoc: \"root\" }], tryLocsList.forEach(pushTryEntry, this), this.reset(!0); } function values(iterable) { if (iterable) { var iteratorMethod = iterable[iteratorSymbol]; if (iteratorMethod) return iteratorMethod.call(iterable); if (\"function\" == typeof iterable.next) return iterable; if (!isNaN(iterable.length)) { var i = -1, next = function next() { for (; ++i < iterable.length;) if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next; return next.value = undefined, next.done = !0, next; }; return next.next = next; } } return { next: doneResult }; } function doneResult() { return { value: undefined, done: !0 }; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, defineProperty(Gp, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), defineProperty(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, \"GeneratorFunction\"), exports.isGeneratorFunction = function (genFun) { var ctor = \"function\" == typeof genFun && genFun.constructor; return !!ctor && (ctor === GeneratorFunction || \"GeneratorFunction\" === (ctor.displayName || ctor.name)); }, exports.mark = function (genFun) { return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, \"GeneratorFunction\")), genFun.prototype = Object.create(Gp), genFun; }, exports.awrap = function (arg) { return { __await: arg }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () { return this; }), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) { void 0 === PromiseImpl && (PromiseImpl = Promise); var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl); return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) { return result.done ? result.value : iter.next(); }); }, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, \"Generator\"), define(Gp, iteratorSymbol, function () { return this; }), define(Gp, \"toString\", function () { return \"[object Generator]\"; }), exports.keys = function (val) { var object = Object(val), keys = []; for (var key in object) keys.push(key); return keys.reverse(), function next() { for (; keys.length;) { var key = keys.pop(); if (key in object) return next.value = key, next.done = !1, next; } return next.done = !0, next; }; }, exports.values = values, Context.prototype = { constructor: Context, reset: function reset(skipTempReset) { if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = undefined, this.tryEntries.forEach(resetTryEntry), !skipTempReset) for (var name in this) \"t\" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+name.slice(1)) && (this[name] = undefined); }, stop: function stop() { this.done = !0; var rootRecord = this.tryEntries[0].completion; if (\"throw\" === rootRecord.type) throw rootRecord.arg; return this.rval; }, dispatchException: function dispatchException(exception) { if (this.done) throw exception; var context = this; function handle(loc, caught) { return record.type = \"throw\", record.arg = exception, context.next = loc, caught && (context.method = \"next\", context.arg = undefined), !!caught; } for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i], record = entry.completion; if (\"root\" === entry.tryLoc) return handle(\"end\"); if (entry.tryLoc <= this.prev) { var hasCatch = hasOwn.call(entry, \"catchLoc\"), hasFinally = hasOwn.call(entry, \"finallyLoc\"); if (hasCatch && hasFinally) { if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0); if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc); } else if (hasCatch) { if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0); } else { if (!hasFinally) throw new Error(\"try statement without catch or finally\"); if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc); } } } }, abrupt: function abrupt(type, arg) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.tryLoc <= this.prev && hasOwn.call(entry, \"finallyLoc\") && this.prev < entry.finallyLoc) { var finallyEntry = entry; break; } } finallyEntry && (\"break\" === type || \"continue\" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null); var record = finallyEntry ? finallyEntry.completion : {}; return record.type = type, record.arg = arg, finallyEntry ? (this.method = \"next\", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record); }, complete: function complete(record, afterLoc) { if (\"throw\" === record.type) throw record.arg; return \"break\" === record.type || \"continue\" === record.type ? this.next = record.arg : \"return\" === record.type ? (this.rval = this.arg = record.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel; }, finish: function finish(finallyLoc) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel; } }, \"catch\": function _catch(tryLoc) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.tryLoc === tryLoc) { var record = entry.completion; if (\"throw\" === record.type) { var thrown = record.arg; resetTryEntry(entry); } return thrown; } } throw new Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(iterable, resultName, nextLoc) { return this.delegate = { iterator: values(iterable), resultName: resultName, nextLoc: nextLoc }, \"next\" === this.method && (this.arg = undefined), ContinueSentinel; } }, exports; }\nfunction asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }\nfunction _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"next\", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"throw\", err); } _next(undefined); }); }; }\n\n\n\nvar currentlyAddingItemByTag = new Map();\nvar received_items = {};\nvar config;\nvar scanner = new html5_qrcode__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScanner(\"reader\", {\n  fps: 10,\n  qrbox: {\n    width: 250,\n    height: 250\n  },\n  showTorchButtonIfSupported: true,\n  formatsToSupport: [html5_qrcode__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.QR_CODE],\n  //there are many other types of codes on the labels we do not want\n  rememberLastUsedCamera: true\n});\nvar scanner_audio = new Audio(\"/beep.wav\");\nscanner_audio.load();\nvar toastDiv = document.getElementById(\"bottomToast\");\n\n/*\n * Helper functions\n */\nfunction htoa(h) {\n  return Uint8Array.from(buffer__WEBPACK_IMPORTED_MODULE_2__.Buffer.from(h, \"hex\"));\n}\nfunction toast(title, message) {\n  toastDiv.children[0].children[0].innerHTML = title;\n  toastDiv.children[1].innerHTML = message;\n  toastDiv.classList.remove(\"hide\");\n  toastDiv.classList.add(\"show\");\n  toastDiv.classList.add(\"showing\");\n  setTimeout(function () {\n    toastDiv.classList.remove(\"show\");\n    toastDiv.classList.remove(\"showing\");\n    toastDiv.classList.add(\"hide\");\n  }, 3000);\n}\nfunction fetchWithAuth(_x, _x2) {\n  return _fetchWithAuth.apply(this, arguments);\n}\nfunction _fetchWithAuth() {\n  _fetchWithAuth = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(input, init) {\n    var response;\n    return _regeneratorRuntime().wrap(function _callee$(_context) {\n      while (1) switch (_context.prev = _context.next) {\n        case 0:\n          if (init == undefined || init == null) {\n            init = {};\n          }\n          if (init[\"headers\"] == null) {\n            init[\"headers\"] = {};\n          }\n          if (window.sessionStorage.getItem(\"access_token\")) {\n            _context.next = 5;\n            break;\n          }\n          _context.next = 5;\n          return login();\n        case 5:\n          init[\"headers\"][\"Authorization\"] = \"Bearer \" + window.sessionStorage.getItem(\"access_token\");\n          _context.next = 8;\n          return fetch(input, init);\n        case 8:\n          response = _context.sent;\n        case 9:\n          if (!(response.status == 401)) {\n            _context.next = 19;\n            break;\n          }\n          console.log(\"Fetch with auth failed for\", input);\n          _context.next = 13;\n          return login();\n        case 13:\n          init[\"headers\"][\"Authorization\"] = \"Bearer \" + window.sessionStorage.getItem(\"access_token\");\n          _context.next = 16;\n          return fetch(input, init);\n        case 16:\n          response = _context.sent;\n          _context.next = 9;\n          break;\n        case 19:\n          return _context.abrupt(\"return\", response);\n        case 20:\n        case \"end\":\n          return _context.stop();\n      }\n    }, _callee);\n  }));\n  return _fetchWithAuth.apply(this, arguments);\n}\nfunction checkResponseForError(_x3, _x4) {\n  return _checkResponseForError.apply(this, arguments);\n}\nfunction _checkResponseForError() {\n  _checkResponseForError = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(response, message) {\n    var content;\n    return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n      while (1) switch (_context2.prev = _context2.next) {\n        case 0:\n          if (!(response.status !== 200)) {\n            _context2.next = 7;\n            break;\n          }\n          _context2.next = 3;\n          return response.text();\n        case 3:\n          content = _context2.sent;\n          console.log(\"Got Response Error:\", message, response);\n          alert(message + \"; Status: \" + response.status + \"; Content: \" + content);\n          return _context2.abrupt(\"return\", false);\n        case 7:\n          return _context2.abrupt(\"return\", true);\n        case 8:\n        case \"end\":\n          return _context2.stop();\n      }\n    }, _callee2);\n  }));\n  return _checkResponseForError.apply(this, arguments);\n}\nfunction getConfig() {\n  return _getConfig.apply(this, arguments);\n}\nfunction _getConfig() {\n  _getConfig = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {\n    var config_request;\n    return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n      while (1) switch (_context3.prev = _context3.next) {\n        case 0:\n          if (!(config == undefined)) {\n            _context3.next = 12;\n            break;\n          }\n          _context3.next = 3;\n          return fetch(\"config.json\");\n        case 3:\n          config_request = _context3.sent;\n          console.log(\"Loading config\");\n          _context3.next = 7;\n          return checkResponseForError(config_request, \"Could not load config\");\n        case 7:\n          if (!_context3.sent) {\n            _context3.next = 12;\n            break;\n          }\n          _context3.next = 10;\n          return config_request.json();\n        case 10:\n          config = _context3.sent;\n          console.log(\"Loaded config\");\n        case 12:\n        case \"end\":\n          return _context3.stop();\n      }\n    }, _callee3);\n  }));\n  return _getConfig.apply(this, arguments);\n}\nfunction login(_x5) {\n  return _login.apply(this, arguments);\n}\nfunction _login() {\n  _login = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(passwordToTry) {\n    var loginSuccess, password, form, response, result;\n    return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n      while (1) switch (_context4.prev = _context4.next) {\n        case 0:\n          console.log(\"Performing login\");\n          loginSuccess = false;\n        case 2:\n          if (passwordToTry !== undefined) {\n            console.log(\"Using password to try from parameter\");\n            password = passwordToTry;\n            passwordToTry = undefined;\n          } else {\n            console.log(\"Prompting user for shared secret.\");\n            password = prompt(\"provide the shared secret\");\n          }\n          form = new FormData();\n          form.append(\"grant_type\", \"password\");\n          form.append(\"username\", \"worker\");\n          form.append(\"password\", password);\n          console.log(\"Requesting token.\");\n          _context4.next = 10;\n          return fetch(config.backend_url + \"/token\", {\n            method: \"POST\",\n            body: form\n          });\n        case 10:\n          response = _context4.sent;\n          _context4.next = 13;\n          return checkResponseForError(response, \"Login failed\");\n        case 13:\n          if (!_context4.sent) {\n            _context4.next = 20;\n            break;\n          }\n          _context4.next = 16;\n          return response.json();\n        case 16:\n          result = _context4.sent;\n          console.log(\"Got token\");\n          window.sessionStorage.setItem(\"access_token\", result.access_token);\n          loginSuccess = true;\n        case 20:\n          if (!loginSuccess) {\n            _context4.next = 2;\n            break;\n          }\n        case 21:\n        case \"end\":\n          return _context4.stop();\n      }\n    }, _callee4);\n  }));\n  return _login.apply(this, arguments);\n}\nfunction updateItemsView() {\n  console.log(\"Updating items view\");\n  var items = document.querySelector(\"#items\");\n  items.innerHTML = \"\";\n  for (var item in received_items) {\n    var li = document.createElement(\"li\");\n    console.log(item);\n    console.log(received_items[item]);\n    li.innerHTML = \"<div id=\\\"item_\" + received_items[item].item.uuid + \"\\\" class=\\\"alert alert-success\\\" role=\\\"alert\\\">\" + received_items[item].item.tag + \" (\" + received_items[item].item.addressee + \", \" + received_items[item].item.team + \")\" + \"&emsp;<span class=\\\"badge badge-light\\\">\" + received_items[item].num + \"</span>\" + \"&emsp;<button class=\\\"btn btn-primary\\\" onclick=\\\"lib.increaseItemCount('\" + received_items[item].item.uuid + \"')\\\">+</button>\" + \"&emsp;<button class=\\\"btn btn-primary\\\" onclick=\\\"lib.decreaseItemCount('\" + received_items[item].item.uuid + \"')\\\">-</button></div>\";\n    items.appendChild(li);\n  }\n}\n\n/*\n * various add Items functions\n */\n\nfunction onTagTextUpdate(_x6) {\n  return _onTagTextUpdate.apply(this, arguments);\n}\nfunction _onTagTextUpdate() {\n  _onTagTextUpdate = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(element) {\n    return _regeneratorRuntime().wrap(function _callee5$(_context5) {\n      while (1) switch (_context5.prev = _context5.next) {\n        case 0:\n          if (!(element.value.length == 0)) {\n            _context5.next = 5;\n            break;\n          }\n          element.setCustomValidity(\"\");\n          element.classList.remove(\"is-invalid\");\n          _context5.next = 12;\n          break;\n        case 5:\n          if (!(element.value.length != 6)) {\n            _context5.next = 11;\n            break;\n          }\n          element.setCustomValidity(\"Code must be 6 chars long.\");\n          element.classList.add(\"is-invalid\");\n          return _context5.abrupt(\"return\");\n        case 11:\n          tagEntered(element);\n        case 12:\n        case \"end\":\n          return _context5.stop();\n      }\n    }, _callee5);\n  }));\n  return _onTagTextUpdate.apply(this, arguments);\n}\nfunction onTagInputChanged(_x7) {\n  return _onTagInputChanged.apply(this, arguments);\n}\nfunction _onTagInputChanged() {\n  _onTagInputChanged = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(element) {\n    return _regeneratorRuntime().wrap(function _callee6$(_context6) {\n      while (1) switch (_context6.prev = _context6.next) {\n        case 0:\n          // Element lost focus or user pressed enter\n          if (element.value.length == 6) {\n            tagEntered(element);\n          } else {\n            element.reportValidity();\n          }\n        case 1:\n        case \"end\":\n          return _context6.stop();\n      }\n    }, _callee6);\n  }));\n  return _onTagInputChanged.apply(this, arguments);\n}\nfunction tagEntered(_x8) {\n  return _tagEntered.apply(this, arguments);\n}\nfunction _tagEntered() {\n  _tagEntered = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(element) {\n    var tag, succ;\n    return _regeneratorRuntime().wrap(function _callee7$(_context7) {\n      while (1) switch (_context7.prev = _context7.next) {\n        case 0:\n          tag = element.value;\n          console.log(\"Tag Entered\", tag);\n          if (!currentlyAddingItemByTag.has(tag)) {\n            _context7.next = 4;\n            break;\n          }\n          return _context7.abrupt(\"return\");\n        case 4:\n          currentlyAddingItemByTag.set(tag, \"\");\n          _context7.next = 7;\n          return addItemByTag(element.value);\n        case 7:\n          succ = _context7.sent;\n          if (succ) {\n            element.classList.remove(\"is-invalid\");\n            element.value = \"\";\n            element.setCustomValidity(\"\");\n          } else {\n            element.setCustomValidity(\"Unknown item\");\n            element.classList.add(\"is-invalid\");\n          }\n          element.reportValidity();\n          currentlyAddingItemByTag[\"delete\"](tag);\n        case 11:\n        case \"end\":\n          return _context7.stop();\n      }\n    }, _callee7);\n  }));\n  return _tagEntered.apply(this, arguments);\n}\nfunction addItemByTag(_x9) {\n  return _addItemByTag.apply(this, arguments);\n}\nfunction _addItemByTag() {\n  _addItemByTag = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(tag) {\n    var response, tracking_item;\n    return _regeneratorRuntime().wrap(function _callee8$(_context8) {\n      while (1) switch (_context8.prev = _context8.next) {\n        case 0:\n          if (!(tag.length != 6)) {\n            _context8.next = 2;\n            break;\n          }\n          throw \"Internal Error: Tag not length 6.\";\n        case 2:\n          tag = tag.toLowerCase();\n          console.log(\"Trying to add item by tag:\", tag);\n          _context8.next = 6;\n          return fetchWithAuth(config.backend_url + \"/tag/\" + tag);\n        case 6:\n          response = _context8.sent;\n          if (!(response.status == 200)) {\n            _context8.next = 18;\n            break;\n          }\n          _context8.next = 10;\n          return response.json();\n        case 10:\n          tracking_item = _context8.sent;\n          if (tracking_item.uuid in received_items) {\n            received_items[tracking_item.uuid].num += 1;\n          } else {\n            received_items[tracking_item.uuid] = {\n              \"num\": 1,\n              \"item\": tracking_item\n            };\n          }\n          updateItemsView();\n          scanner_audio.play();\n          console.log(\"Added item by tag\");\n          return _context8.abrupt(\"return\", true);\n        case 18:\n          if (!(response.status == 404)) {\n            _context8.next = 23;\n            break;\n          }\n          console.log(\"Item not found\");\n          return _context8.abrupt(\"return\", false);\n        case 23:\n          checkResponseForError(response, \"Failed to get item from backend\");\n          return _context8.abrupt(\"return\", false);\n        case 25:\n        case \"end\":\n          return _context8.stop();\n      }\n    }, _callee8);\n  }));\n  return _addItemByTag.apply(this, arguments);\n}\nfunction handleQrError(_x10, _x11) {\n  return _handleQrError.apply(this, arguments);\n}\nfunction _handleQrError() {\n  _handleQrError = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee9(msg, err) {\n    return _regeneratorRuntime().wrap(function _callee9$(_context9) {\n      while (1) switch (_context9.prev = _context9.next) {\n        case 0:\n          return _context9.abrupt(\"return\");\n        case 1:\n        case \"end\":\n          return _context9.stop();\n      }\n    }, _callee9);\n  }));\n  return _handleQrError.apply(this, arguments);\n}\nfunction debounceScanner() {\n  if (scanner.getState() != html5_qrcode__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScannerState.SCANNING) {\n    return;\n  }\n  scanner.pause(false);\n  setTimeout(function () {\n    if (scanner.getState() == html5_qrcode__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScannerState.PAUSED) {\n      scanner.resume();\n    }\n  }, 1000);\n}\nfunction handleItemScanResult(_x12) {\n  return _handleItemScanResult.apply(this, arguments);\n}\nfunction _handleItemScanResult() {\n  _handleItemScanResult = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee10(item_uuid) {\n    var response, tracking_item;\n    return _regeneratorRuntime().wrap(function _callee10$(_context10) {\n      while (1) switch (_context10.prev = _context10.next) {\n        case 0:\n          debounceScanner();\n          if (!(item_uuid.length == 36)) {\n            _context10.next = 27;\n            break;\n          }\n          console.log(\"Trying to add item by uuid (scanned)\");\n          if (!(item_uuid in received_items)) {\n            _context10.next = 10;\n            break;\n          }\n          received_items[item_uuid].num += 1;\n          console.log(\"Increased count of existing item uuid\");\n          updateItemsView();\n          scanner_audio.play();\n          _context10.next = 25;\n          break;\n        case 10:\n          received_items[item_uuid] = {\n            \"num\": 1,\n            \"item\": null\n          };\n          _context10.next = 13;\n          return fetchWithAuth(config.backend_url + \"/item/\" + item_uuid);\n        case 13:\n          response = _context10.sent;\n          if (!(response.status == 200)) {\n            _context10.next = 24;\n            break;\n          }\n          _context10.next = 17;\n          return response.json();\n        case 17:\n          tracking_item = _context10.sent;\n          received_items[item_uuid] = {\n            \"num\": 1,\n            \"item\": tracking_item\n          };\n          updateItemsView();\n          scanner_audio.play();\n          console.log(\"Added item by uuid.\");\n          _context10.next = 25;\n          break;\n        case 24:\n          if (response.status == 404) {\n            alert(\"Item not found\");\n            console.log(\"Item not found\");\n          } else {\n            checkResponseForError(response, \"Failed to get item from backend\");\n          }\n        case 25:\n          _context10.next = 28;\n          break;\n        case 27:\n          alert(\"QR Code is not a bgp checkin code.\");\n        case 28:\n        case \"end\":\n          return _context10.stop();\n      }\n    }, _callee10);\n  }));\n  return _handleItemScanResult.apply(this, arguments);\n}\nfunction addItemScan() {\n  return _addItemScan.apply(this, arguments);\n}\nfunction _addItemScan() {\n  _addItemScan = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee11() {\n    return _regeneratorRuntime().wrap(function _callee11$(_context11) {\n      while (1) switch (_context11.prev = _context11.next) {\n        case 0:\n          console.log(\"Starting scanner\");\n          scanner.render(handleItemScanResult, handleQrError);\n          document.getElementById(\"startScan\").style.display = \"none\";\n          document.getElementById(\"stopScan\").style.display = \"inline-block\";\n        case 4:\n        case \"end\":\n          return _context11.stop();\n      }\n    }, _callee11);\n  }));\n  return _addItemScan.apply(this, arguments);\n}\nfunction stopScanningItem() {\n  return _stopScanningItem.apply(this, arguments);\n}\nfunction _stopScanningItem() {\n  _stopScanningItem = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee12() {\n    return _regeneratorRuntime().wrap(function _callee12$(_context12) {\n      while (1) switch (_context12.prev = _context12.next) {\n        case 0:\n          console.log(\"Stopping scanner\");\n          scanner.clear();\n          document.getElementById(\"startScan\").style.display = \"inline-block\";\n          document.getElementById(\"stopScan\").style.display = \"none\";\n        case 4:\n        case \"end\":\n          return _context12.stop();\n      }\n    }, _callee12);\n  }));\n  return _stopScanningItem.apply(this, arguments);\n}\nfunction addItemImage(_x13) {\n  return _addItemImage.apply(this, arguments);\n}\nfunction _addItemImage() {\n  _addItemImage = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee13(e) {\n    var form, response, tracking_item;\n    return _regeneratorRuntime().wrap(function _callee13$(_context13) {\n      while (1) switch (_context13.prev = _context13.next) {\n        case 0:\n          console.log(\"Adding item  by image\");\n          form = new FormData();\n          form.append(\"image\", e.files[0]);\n          _context13.next = 5;\n          return fetchWithAuth(config.backend_url + \"/item/register\", {\n            method: \"POST\",\n            body: form\n          });\n        case 5:\n          response = _context13.sent;\n          _context13.next = 8;\n          return checkResponseForError(response, \"Failed to save item\");\n        case 8:\n          if (!_context13.sent) {\n            _context13.next = 16;\n            break;\n          }\n          _context13.next = 11;\n          return response.json();\n        case 11:\n          tracking_item = _context13.sent;\n          received_items[tracking_item.uuid] = {\n            \"num\": 1,\n            \"item\": tracking_item\n          };\n          updateItemsView();\n          scanner_audio.play();\n          console.log(\"Added item by image.\");\n        case 16:\n        case \"end\":\n          return _context13.stop();\n      }\n    }, _callee13);\n  }));\n  return _addItemImage.apply(this, arguments);\n}\nfunction decreaseItemCount(_x14) {\n  return _decreaseItemCount.apply(this, arguments);\n}\nfunction _decreaseItemCount() {\n  _decreaseItemCount = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee14(uuid) {\n    return _regeneratorRuntime().wrap(function _callee14$(_context14) {\n      while (1) switch (_context14.prev = _context14.next) {\n        case 0:\n          if (!(received_items[uuid] == null)) {\n            _context14.next = 3;\n            break;\n          }\n          console.log(\"Trying to decrease item count of unknown item\", uuid);\n          return _context14.abrupt(\"return\");\n        case 3:\n          console.log(\"Decreasing item count of\", uuid);\n          received_items[uuid][\"num\"]--;\n          if (received_items[uuid][\"num\"] <= 0) {\n            delete received_items[uuid];\n          }\n          updateItemsView();\n        case 7:\n        case \"end\":\n          return _context14.stop();\n      }\n    }, _callee14);\n  }));\n  return _decreaseItemCount.apply(this, arguments);\n}\nfunction increaseItemCount(_x15) {\n  return _increaseItemCount.apply(this, arguments);\n}\n\n/*\n * Checkin the selected items\n */\nfunction _increaseItemCount() {\n  _increaseItemCount = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee15(uuid) {\n    return _regeneratorRuntime().wrap(function _callee15$(_context15) {\n      while (1) switch (_context15.prev = _context15.next) {\n        case 0:\n          if (!(received_items[uuid] == null)) {\n            _context15.next = 3;\n            break;\n          }\n          console.log(\"Trying to increase item count of unknown item\", uuid);\n          return _context15.abrupt(\"return\");\n        case 3:\n          console.log(\"Increasing item count of\", uuid);\n          received_items[uuid][\"num\"]++;\n          updateItemsView();\n        case 6:\n        case \"end\":\n          return _context15.stop();\n      }\n    }, _callee15);\n  }));\n  return _increaseItemCount.apply(this, arguments);\n}\nfunction checkinItems() {\n  return _checkinItems.apply(this, arguments);\n}\nfunction _checkinItems() {\n  _checkinItems = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee16() {\n    var successfullCount, item, response, tracking_item;\n    return _regeneratorRuntime().wrap(function _callee16$(_context16) {\n      while (1) switch (_context16.prev = _context16.next) {\n        case 0:\n          console.log(\"Checking in items\");\n          successfullCount = 0;\n          _context16.t0 = _regeneratorRuntime().keys(received_items);\n        case 3:\n          if ((_context16.t1 = _context16.t0()).done) {\n            _context16.next = 18;\n            break;\n          }\n          item = _context16.t1.value;\n          _context16.next = 7;\n          return fetchWithAuth(config.backend_url + \"/checkin\", {\n            method: \"POST\",\n            headers: {\n              \"Content-Type\": \"application/json\"\n            },\n            body: JSON.stringify({\n              \"item_uuid\": received_items[item].item.uuid,\n              \"storage_name\": document.querySelector(\"#storage_select\").value,\n              \"amount\": received_items[item].num\n            })\n          });\n        case 7:\n          response = _context16.sent;\n          _context16.next = 10;\n          return checkResponseForError(response, \"Failed to checkin item \" + received_items[item].item.tag);\n        case 10:\n          if (!_context16.sent) {\n            _context16.next = 16;\n            break;\n          }\n          _context16.next = 13;\n          return response.json();\n        case 13:\n          tracking_item = _context16.sent;\n          // eslint-disable-line no-unused-vars\n          delete received_items[tracking_item.uuid];\n          successfullCount++;\n        case 16:\n          _context16.next = 3;\n          break;\n        case 18:\n          toast(\"Check-In successfull.\", \"The check-in of \" + successfullCount + \" items completed succesfully.\");\n          updateItemsView();\n        case 20:\n        case \"end\":\n          return _context16.stop();\n      }\n    }, _callee16);\n  }));\n  return _checkinItems.apply(this, arguments);\n}\nfunction updateCheckoutItem(tracking_item) {\n  document.querySelector(\"#uuid\").innerHTML = tracking_item.uuid;\n  document.querySelector(\"#tag\").innerHTML = tracking_item.tag;\n  document.querySelector(\"#storage\").innerHTML = tracking_item.storage;\n  document.querySelector(\"#addressee\").innerHTML = tracking_item.addressee;\n  document.querySelector(\"#team\").innerHTML = tracking_item.team;\n}\nfunction checkoutItem() {\n  return _checkoutItem.apply(this, arguments);\n}\nfunction _checkoutItem() {\n  _checkoutItem = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee17() {\n    var confirmed, response;\n    return _regeneratorRuntime().wrap(function _callee17$(_context17) {\n      while (1) switch (_context17.prev = _context17.next) {\n        case 0:\n          confirmed = confirm(\"Did you make sure the recipient is really the right person?\");\n          if (confirmed) {\n            _context17.next = 4;\n            break;\n          }\n          console.log(\"Recipient confirmation denied.\");\n          return _context17.abrupt(\"return\");\n        case 4:\n          _context17.next = 6;\n          return fetchWithAuth(config.backend_url + \"/checkout/\" + document.querySelector(\"#uuid\").innerHTML);\n        case 6:\n          response = _context17.sent;\n        case 7:\n        case \"end\":\n          return _context17.stop();\n      }\n    }, _callee17);\n  }));\n  return _checkoutItem.apply(this, arguments);\n}\nfunction onRecevierScanSuccess(_x16) {\n  return _onRecevierScanSuccess.apply(this, arguments);\n}\nfunction _onRecevierScanSuccess() {\n  _onRecevierScanSuccess = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee18(scannedCode) {\n    var _scannedCode$split, _scannedCode$split2, uuid, signature, response, tracking_item;\n    return _regeneratorRuntime().wrap(function _callee18$(_context18) {\n      while (1) switch (_context18.prev = _context18.next) {\n        case 0:\n          debounceScanner();\n          _scannedCode$split = scannedCode.split(\"/\"), _scannedCode$split2 = _slicedToArray(_scannedCode$split, 2), uuid = _scannedCode$split2[0], signature = _scannedCode$split2[1];\n          console.log(\"Receiver scan success\");\n          scanner_audio.play();\n          _context18.next = 6;\n          return getConfig();\n        case 6:\n          _context18.next = 8;\n          return fetch(config.backend_url + \"/item/\" + uuid, {\n            headers: {}\n          });\n        case 8:\n          response = _context18.sent;\n          if (!(response.status == 200)) {\n            _context18.next = 26;\n            break;\n          }\n          _context18.next = 12;\n          return response.json();\n        case 12:\n          tracking_item = _context18.sent;\n          if (!_noble_curves_ed448__WEBPACK_IMPORTED_MODULE_1__.ed448.verify(htoa(signature), new TextEncoder().encode(tracking_item.uuid), htoa(tracking_item.verification))) {\n            _context18.next = 22;\n            break;\n          }\n          if (!(tracking_item.storage == undefined || tracking_item.storage == null || tracking_item.storage.length == 0)) {\n            _context18.next = 18;\n            break;\n          }\n          alert(\"Item not yet received.\");\n          console.log(\"Item not yet received.\");\n          return _context18.abrupt(\"return\");\n        case 18:\n          updateCheckoutItem(tracking_item);\n          console.log(\"Receiver verify success\");\n          _context18.next = 24;\n          break;\n        case 22:\n          alert(\"Could not verify signature.\");\n          console.log(\"Could not verify signature.\");\n        case 24:\n          _context18.next = 27;\n          break;\n        case 26:\n          if (response.status == 404) {\n            alert(\"Item not found.\");\n          } else {\n            checkResponseForError(response, \"Failed to get item from backend.\");\n          }\n        case 27:\n        case \"end\":\n          return _context18.stop();\n      }\n    }, _callee18);\n  }));\n  return _onRecevierScanSuccess.apply(this, arguments);\n}\nfunction scanReceiver() {\n  return _scanReceiver.apply(this, arguments);\n}\nfunction _scanReceiver() {\n  _scanReceiver = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee19() {\n    return _regeneratorRuntime().wrap(function _callee19$(_context19) {\n      while (1) switch (_context19.prev = _context19.next) {\n        case 0:\n          console.log(\"Scanning receiver.\");\n          scanner.render(onRecevierScanSuccess, handleQrError);\n        case 2:\n        case \"end\":\n          return _context19.stop();\n      }\n    }, _callee19);\n  }));\n  return _scanReceiver.apply(this, arguments);\n}\nfunction loadStorages(_x17) {\n  return _loadStorages.apply(this, arguments);\n}\nfunction _loadStorages() {\n  _loadStorages = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee20(selectedStorage) {\n    var response, storages, select, i, option;\n    return _regeneratorRuntime().wrap(function _callee20$(_context20) {\n      while (1) switch (_context20.prev = _context20.next) {\n        case 0:\n          console.log(\"Retrieving storages\");\n          _context20.next = 3;\n          return fetchWithAuth(config.backend_url + \"/storages\");\n        case 3:\n          response = _context20.sent;\n          _context20.next = 6;\n          return checkResponseForError(response, \"Failed to load storages.\");\n        case 6:\n          if (!_context20.sent) {\n            _context20.next = 13;\n            break;\n          }\n          _context20.next = 9;\n          return response.json();\n        case 9:\n          storages = _context20.sent;\n          select = document.querySelector(\"#storage_select\");\n          console.log(\"Got storages\");\n          for (i in storages) {\n            option = document.createElement(\"option\");\n            option.textContent = storages[i].name;\n            option.value = storages[i].name;\n            select.appendChild(option);\n            if (selectedStorage == storages[i].name) {\n              select.value = selectedStorage;\n            }\n          }\n        case 13:\n        case \"end\":\n          return _context20.stop();\n      }\n    }, _callee20);\n  }));\n  return _loadStorages.apply(this, arguments);\n}\nfunction onPageLoad(_x18) {\n  return _onPageLoad.apply(this, arguments);\n}\nfunction _onPageLoad() {\n  _onPageLoad = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee21(doloadStorages) {\n    var pw;\n    return _regeneratorRuntime().wrap(function _callee21$(_context21) {\n      while (1) switch (_context21.prev = _context21.next) {\n        case 0:\n          _context21.next = 2;\n          return getConfig();\n        case 2:\n          pw = window.location.hash.substring(1);\n          if (!(pw.length > 1)) {\n            _context21.next = 8;\n            break;\n          }\n          _context21.next = 6;\n          return login(pw);\n        case 6:\n          _context21.next = 10;\n          break;\n        case 8:\n          _context21.next = 10;\n          return login();\n        case 10:\n          if (doloadStorages) {\n            loadStorages(document.location.search.substring(1));\n          }\n        case 11:\n        case \"end\":\n          return _context21.stop();\n      }\n    }, _callee21);\n  }));\n  return _onPageLoad.apply(this, arguments);\n}\nfunction checkoutByTag() {\n  return _checkoutByTag.apply(this, arguments);\n}\nfunction _checkoutByTag() {\n  _checkoutByTag = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee22() {\n    var el, response, tracking_item;\n    return _regeneratorRuntime().wrap(function _callee22$(_context22) {\n      while (1) switch (_context22.prev = _context22.next) {\n        case 0:\n          console.log(\"Checkout by tag\");\n          el = document.getElementById(\"checkoutByTag\");\n          if (!(el.value.length != 6)) {\n            _context22.next = 6;\n            break;\n          }\n          alert(\"Not a BGP tag!\");\n          console.log(\"Not a BGP tag\");\n          return _context22.abrupt(\"return\");\n        case 6:\n          _context22.next = 8;\n          return fetchWithAuth(config.backend_url + \"/tag/\" + el.value);\n        case 8:\n          response = _context22.sent;\n          if (!(response.status == 200)) {\n            _context22.next = 21;\n            break;\n          }\n          _context22.next = 12;\n          return response.json();\n        case 12:\n          tracking_item = _context22.sent;\n          if (!(tracking_item.storage == undefined || tracking_item.storage == null || tracking_item.storage.length == 0)) {\n            _context22.next = 17;\n            break;\n          }\n          alert(\"Item not yet received.\");\n          console.log(\"Item not yet received.\");\n          return _context22.abrupt(\"return\");\n        case 17:\n          console.log(\"Checkout item by tag success.\");\n          updateCheckoutItem(tracking_item);\n          _context22.next = 22;\n          break;\n        case 21:\n          if (response.status == 404) {\n            console.log(\"Item not found\");\n            alert(\"Item not found!\");\n          } else {\n            checkResponseForError(response, \"Failed to get item from backend\");\n          }\n        case 22:\n        case \"end\":\n          return _context22.stop();\n      }\n    }, _callee22);\n  }));\n  return _checkoutByTag.apply(this, arguments);\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvanMvbWFpbi5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL3NyYy9qcy9tYWluLmpzPzAwM2EiXSwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gX3R5cGVvZihvYmopIHsgXCJAYmFiZWwvaGVscGVycyAtIHR5cGVvZlwiOyByZXR1cm4gX3R5cGVvZiA9IFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgU3ltYm9sICYmIFwic3ltYm9sXCIgPT0gdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA/IGZ1bmN0aW9uIChvYmopIHsgcmV0dXJuIHR5cGVvZiBvYmo7IH0gOiBmdW5jdGlvbiAob2JqKSB7IHJldHVybiBvYmogJiYgXCJmdW5jdGlvblwiID09IHR5cGVvZiBTeW1ib2wgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgJiYgb2JqICE9PSBTeW1ib2wucHJvdG90eXBlID8gXCJzeW1ib2xcIiA6IHR5cGVvZiBvYmo7IH0sIF90eXBlb2Yob2JqKTsgfVxuZnVuY3Rpb24gX3NsaWNlZFRvQXJyYXkoYXJyLCBpKSB7IHJldHVybiBfYXJyYXlXaXRoSG9sZXMoYXJyKSB8fCBfaXRlcmFibGVUb0FycmF5TGltaXQoYXJyLCBpKSB8fCBfdW5zdXBwb3J0ZWRJdGVyYWJsZVRvQXJyYXkoYXJyLCBpKSB8fCBfbm9uSXRlcmFibGVSZXN0KCk7IH1cbmZ1bmN0aW9uIF9ub25JdGVyYWJsZVJlc3QoKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIGF0dGVtcHQgdG8gZGVzdHJ1Y3R1cmUgbm9uLWl0ZXJhYmxlIGluc3RhbmNlLlxcbkluIG9yZGVyIHRvIGJlIGl0ZXJhYmxlLCBub24tYXJyYXkgb2JqZWN0cyBtdXN0IGhhdmUgYSBbU3ltYm9sLml0ZXJhdG9yXSgpIG1ldGhvZC5cIik7IH1cbmZ1bmN0aW9uIF91bnN1cHBvcnRlZEl0ZXJhYmxlVG9BcnJheShvLCBtaW5MZW4pIHsgaWYgKCFvKSByZXR1cm47IGlmICh0eXBlb2YgbyA9PT0gXCJzdHJpbmdcIikgcmV0dXJuIF9hcnJheUxpa2VUb0FycmF5KG8sIG1pbkxlbik7IHZhciBuID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG8pLnNsaWNlKDgsIC0xKTsgaWYgKG4gPT09IFwiT2JqZWN0XCIgJiYgby5jb25zdHJ1Y3RvcikgbiA9IG8uY29uc3RydWN0b3IubmFtZTsgaWYgKG4gPT09IFwiTWFwXCIgfHwgbiA9PT0gXCJTZXRcIikgcmV0dXJuIEFycmF5LmZyb20obyk7IGlmIChuID09PSBcIkFyZ3VtZW50c1wiIHx8IC9eKD86VWl8SSludCg/Ojh8MTZ8MzIpKD86Q2xhbXBlZCk/QXJyYXkkLy50ZXN0KG4pKSByZXR1cm4gX2FycmF5TGlrZVRvQXJyYXkobywgbWluTGVuKTsgfVxuZnVuY3Rpb24gX2FycmF5TGlrZVRvQXJyYXkoYXJyLCBsZW4pIHsgaWYgKGxlbiA9PSBudWxsIHx8IGxlbiA+IGFyci5sZW5ndGgpIGxlbiA9IGFyci5sZW5ndGg7IGZvciAodmFyIGkgPSAwLCBhcnIyID0gbmV3IEFycmF5KGxlbik7IGkgPCBsZW47IGkrKykgYXJyMltpXSA9IGFycltpXTsgcmV0dXJuIGFycjI7IH1cbmZ1bmN0aW9uIF9pdGVyYWJsZVRvQXJyYXlMaW1pdChhcnIsIGkpIHsgdmFyIF9pID0gbnVsbCA9PSBhcnIgPyBudWxsIDogXCJ1bmRlZmluZWRcIiAhPSB0eXBlb2YgU3ltYm9sICYmIGFycltTeW1ib2wuaXRlcmF0b3JdIHx8IGFycltcIkBAaXRlcmF0b3JcIl07IGlmIChudWxsICE9IF9pKSB7IHZhciBfcywgX2UsIF94LCBfciwgX2FyciA9IFtdLCBfbiA9ICEwLCBfZCA9ICExOyB0cnkgeyBpZiAoX3ggPSAoX2kgPSBfaS5jYWxsKGFycikpLm5leHQsIDAgPT09IGkpIHsgaWYgKE9iamVjdChfaSkgIT09IF9pKSByZXR1cm47IF9uID0gITE7IH0gZWxzZSBmb3IgKDsgIShfbiA9IChfcyA9IF94LmNhbGwoX2kpKS5kb25lKSAmJiAoX2Fyci5wdXNoKF9zLnZhbHVlKSwgX2Fyci5sZW5ndGggIT09IGkpOyBfbiA9ICEwKTsgfSBjYXRjaCAoZXJyKSB7IF9kID0gITAsIF9lID0gZXJyOyB9IGZpbmFsbHkgeyB0cnkgeyBpZiAoIV9uICYmIG51bGwgIT0gX2lbXCJyZXR1cm5cIl0gJiYgKF9yID0gX2lbXCJyZXR1cm5cIl0oKSwgT2JqZWN0KF9yKSAhPT0gX3IpKSByZXR1cm47IH0gZmluYWxseSB7IGlmIChfZCkgdGhyb3cgX2U7IH0gfSByZXR1cm4gX2FycjsgfSB9XG5mdW5jdGlvbiBfYXJyYXlXaXRoSG9sZXMoYXJyKSB7IGlmIChBcnJheS5pc0FycmF5KGFycikpIHJldHVybiBhcnI7IH1cbmZ1bmN0aW9uIF9yZWdlbmVyYXRvclJ1bnRpbWUoKSB7IFwidXNlIHN0cmljdFwiOyAvKiEgcmVnZW5lcmF0b3ItcnVudGltZSAtLSBDb3B5cmlnaHQgKGMpIDIwMTQtcHJlc2VudCwgRmFjZWJvb2ssIEluYy4gLS0gbGljZW5zZSAoTUlUKTogaHR0cHM6Ly9naXRodWIuY29tL2ZhY2Vib29rL3JlZ2VuZXJhdG9yL2Jsb2IvbWFpbi9MSUNFTlNFICovIF9yZWdlbmVyYXRvclJ1bnRpbWUgPSBmdW5jdGlvbiBfcmVnZW5lcmF0b3JSdW50aW1lKCkgeyByZXR1cm4gZXhwb3J0czsgfTsgdmFyIGV4cG9ydHMgPSB7fSwgT3AgPSBPYmplY3QucHJvdG90eXBlLCBoYXNPd24gPSBPcC5oYXNPd25Qcm9wZXJ0eSwgZGVmaW5lUHJvcGVydHkgPSBPYmplY3QuZGVmaW5lUHJvcGVydHkgfHwgZnVuY3Rpb24gKG9iaiwga2V5LCBkZXNjKSB7IG9ialtrZXldID0gZGVzYy52YWx1ZTsgfSwgJFN5bWJvbCA9IFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgU3ltYm9sID8gU3ltYm9sIDoge30sIGl0ZXJhdG9yU3ltYm9sID0gJFN5bWJvbC5pdGVyYXRvciB8fCBcIkBAaXRlcmF0b3JcIiwgYXN5bmNJdGVyYXRvclN5bWJvbCA9ICRTeW1ib2wuYXN5bmNJdGVyYXRvciB8fCBcIkBAYXN5bmNJdGVyYXRvclwiLCB0b1N0cmluZ1RhZ1N5bWJvbCA9ICRTeW1ib2wudG9TdHJpbmdUYWcgfHwgXCJAQHRvU3RyaW5nVGFnXCI7IGZ1bmN0aW9uIGRlZmluZShvYmosIGtleSwgdmFsdWUpIHsgcmV0dXJuIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIGtleSwgeyB2YWx1ZTogdmFsdWUsIGVudW1lcmFibGU6ICEwLCBjb25maWd1cmFibGU6ICEwLCB3cml0YWJsZTogITAgfSksIG9ialtrZXldOyB9IHRyeSB7IGRlZmluZSh7fSwgXCJcIik7IH0gY2F0Y2ggKGVycikgeyBkZWZpbmUgPSBmdW5jdGlvbiBkZWZpbmUob2JqLCBrZXksIHZhbHVlKSB7IHJldHVybiBvYmpba2V5XSA9IHZhbHVlOyB9OyB9IGZ1bmN0aW9uIHdyYXAoaW5uZXJGbiwgb3V0ZXJGbiwgc2VsZiwgdHJ5TG9jc0xpc3QpIHsgdmFyIHByb3RvR2VuZXJhdG9yID0gb3V0ZXJGbiAmJiBvdXRlckZuLnByb3RvdHlwZSBpbnN0YW5jZW9mIEdlbmVyYXRvciA/IG91dGVyRm4gOiBHZW5lcmF0b3IsIGdlbmVyYXRvciA9IE9iamVjdC5jcmVhdGUocHJvdG9HZW5lcmF0b3IucHJvdG90eXBlKSwgY29udGV4dCA9IG5ldyBDb250ZXh0KHRyeUxvY3NMaXN0IHx8IFtdKTsgcmV0dXJuIGRlZmluZVByb3BlcnR5KGdlbmVyYXRvciwgXCJfaW52b2tlXCIsIHsgdmFsdWU6IG1ha2VJbnZva2VNZXRob2QoaW5uZXJGbiwgc2VsZiwgY29udGV4dCkgfSksIGdlbmVyYXRvcjsgfSBmdW5jdGlvbiB0cnlDYXRjaChmbiwgb2JqLCBhcmcpIHsgdHJ5IHsgcmV0dXJuIHsgdHlwZTogXCJub3JtYWxcIiwgYXJnOiBmbi5jYWxsKG9iaiwgYXJnKSB9OyB9IGNhdGNoIChlcnIpIHsgcmV0dXJuIHsgdHlwZTogXCJ0aHJvd1wiLCBhcmc6IGVyciB9OyB9IH0gZXhwb3J0cy53cmFwID0gd3JhcDsgdmFyIENvbnRpbnVlU2VudGluZWwgPSB7fTsgZnVuY3Rpb24gR2VuZXJhdG9yKCkge30gZnVuY3Rpb24gR2VuZXJhdG9yRnVuY3Rpb24oKSB7fSBmdW5jdGlvbiBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZSgpIHt9IHZhciBJdGVyYXRvclByb3RvdHlwZSA9IHt9OyBkZWZpbmUoSXRlcmF0b3JQcm90b3R5cGUsIGl0ZXJhdG9yU3ltYm9sLCBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9KTsgdmFyIGdldFByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mLCBOYXRpdmVJdGVyYXRvclByb3RvdHlwZSA9IGdldFByb3RvICYmIGdldFByb3RvKGdldFByb3RvKHZhbHVlcyhbXSkpKTsgTmF0aXZlSXRlcmF0b3JQcm90b3R5cGUgJiYgTmF0aXZlSXRlcmF0b3JQcm90b3R5cGUgIT09IE9wICYmIGhhc093bi5jYWxsKE5hdGl2ZUl0ZXJhdG9yUHJvdG90eXBlLCBpdGVyYXRvclN5bWJvbCkgJiYgKEl0ZXJhdG9yUHJvdG90eXBlID0gTmF0aXZlSXRlcmF0b3JQcm90b3R5cGUpOyB2YXIgR3AgPSBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZS5wcm90b3R5cGUgPSBHZW5lcmF0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShJdGVyYXRvclByb3RvdHlwZSk7IGZ1bmN0aW9uIGRlZmluZUl0ZXJhdG9yTWV0aG9kcyhwcm90b3R5cGUpIHsgW1wibmV4dFwiLCBcInRocm93XCIsIFwicmV0dXJuXCJdLmZvckVhY2goZnVuY3Rpb24gKG1ldGhvZCkgeyBkZWZpbmUocHJvdG90eXBlLCBtZXRob2QsIGZ1bmN0aW9uIChhcmcpIHsgcmV0dXJuIHRoaXMuX2ludm9rZShtZXRob2QsIGFyZyk7IH0pOyB9KTsgfSBmdW5jdGlvbiBBc3luY0l0ZXJhdG9yKGdlbmVyYXRvciwgUHJvbWlzZUltcGwpIHsgZnVuY3Rpb24gaW52b2tlKG1ldGhvZCwgYXJnLCByZXNvbHZlLCByZWplY3QpIHsgdmFyIHJlY29yZCA9IHRyeUNhdGNoKGdlbmVyYXRvclttZXRob2RdLCBnZW5lcmF0b3IsIGFyZyk7IGlmIChcInRocm93XCIgIT09IHJlY29yZC50eXBlKSB7IHZhciByZXN1bHQgPSByZWNvcmQuYXJnLCB2YWx1ZSA9IHJlc3VsdC52YWx1ZTsgcmV0dXJuIHZhbHVlICYmIFwib2JqZWN0XCIgPT0gX3R5cGVvZih2YWx1ZSkgJiYgaGFzT3duLmNhbGwodmFsdWUsIFwiX19hd2FpdFwiKSA/IFByb21pc2VJbXBsLnJlc29sdmUodmFsdWUuX19hd2FpdCkudGhlbihmdW5jdGlvbiAodmFsdWUpIHsgaW52b2tlKFwibmV4dFwiLCB2YWx1ZSwgcmVzb2x2ZSwgcmVqZWN0KTsgfSwgZnVuY3Rpb24gKGVycikgeyBpbnZva2UoXCJ0aHJvd1wiLCBlcnIsIHJlc29sdmUsIHJlamVjdCk7IH0pIDogUHJvbWlzZUltcGwucmVzb2x2ZSh2YWx1ZSkudGhlbihmdW5jdGlvbiAodW53cmFwcGVkKSB7IHJlc3VsdC52YWx1ZSA9IHVud3JhcHBlZCwgcmVzb2x2ZShyZXN1bHQpOyB9LCBmdW5jdGlvbiAoZXJyb3IpIHsgcmV0dXJuIGludm9rZShcInRocm93XCIsIGVycm9yLCByZXNvbHZlLCByZWplY3QpOyB9KTsgfSByZWplY3QocmVjb3JkLmFyZyk7IH0gdmFyIHByZXZpb3VzUHJvbWlzZTsgZGVmaW5lUHJvcGVydHkodGhpcywgXCJfaW52b2tlXCIsIHsgdmFsdWU6IGZ1bmN0aW9uIHZhbHVlKG1ldGhvZCwgYXJnKSB7IGZ1bmN0aW9uIGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnKCkgeyByZXR1cm4gbmV3IFByb21pc2VJbXBsKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsgaW52b2tlKG1ldGhvZCwgYXJnLCByZXNvbHZlLCByZWplY3QpOyB9KTsgfSByZXR1cm4gcHJldmlvdXNQcm9taXNlID0gcHJldmlvdXNQcm9taXNlID8gcHJldmlvdXNQcm9taXNlLnRoZW4oY2FsbEludm9rZVdpdGhNZXRob2RBbmRBcmcsIGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnKSA6IGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnKCk7IH0gfSk7IH0gZnVuY3Rpb24gbWFrZUludm9rZU1ldGhvZChpbm5lckZuLCBzZWxmLCBjb250ZXh0KSB7IHZhciBzdGF0ZSA9IFwic3VzcGVuZGVkU3RhcnRcIjsgcmV0dXJuIGZ1bmN0aW9uIChtZXRob2QsIGFyZykgeyBpZiAoXCJleGVjdXRpbmdcIiA9PT0gc3RhdGUpIHRocm93IG5ldyBFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IHJ1bm5pbmdcIik7IGlmIChcImNvbXBsZXRlZFwiID09PSBzdGF0ZSkgeyBpZiAoXCJ0aHJvd1wiID09PSBtZXRob2QpIHRocm93IGFyZzsgcmV0dXJuIGRvbmVSZXN1bHQoKTsgfSBmb3IgKGNvbnRleHQubWV0aG9kID0gbWV0aG9kLCBjb250ZXh0LmFyZyA9IGFyZzs7KSB7IHZhciBkZWxlZ2F0ZSA9IGNvbnRleHQuZGVsZWdhdGU7IGlmIChkZWxlZ2F0ZSkgeyB2YXIgZGVsZWdhdGVSZXN1bHQgPSBtYXliZUludm9rZURlbGVnYXRlKGRlbGVnYXRlLCBjb250ZXh0KTsgaWYgKGRlbGVnYXRlUmVzdWx0KSB7IGlmIChkZWxlZ2F0ZVJlc3VsdCA9PT0gQ29udGludWVTZW50aW5lbCkgY29udGludWU7IHJldHVybiBkZWxlZ2F0ZVJlc3VsdDsgfSB9IGlmIChcIm5leHRcIiA9PT0gY29udGV4dC5tZXRob2QpIGNvbnRleHQuc2VudCA9IGNvbnRleHQuX3NlbnQgPSBjb250ZXh0LmFyZztlbHNlIGlmIChcInRocm93XCIgPT09IGNvbnRleHQubWV0aG9kKSB7IGlmIChcInN1c3BlbmRlZFN0YXJ0XCIgPT09IHN0YXRlKSB0aHJvdyBzdGF0ZSA9IFwiY29tcGxldGVkXCIsIGNvbnRleHQuYXJnOyBjb250ZXh0LmRpc3BhdGNoRXhjZXB0aW9uKGNvbnRleHQuYXJnKTsgfSBlbHNlIFwicmV0dXJuXCIgPT09IGNvbnRleHQubWV0aG9kICYmIGNvbnRleHQuYWJydXB0KFwicmV0dXJuXCIsIGNvbnRleHQuYXJnKTsgc3RhdGUgPSBcImV4ZWN1dGluZ1wiOyB2YXIgcmVjb3JkID0gdHJ5Q2F0Y2goaW5uZXJGbiwgc2VsZiwgY29udGV4dCk7IGlmIChcIm5vcm1hbFwiID09PSByZWNvcmQudHlwZSkgeyBpZiAoc3RhdGUgPSBjb250ZXh0LmRvbmUgPyBcImNvbXBsZXRlZFwiIDogXCJzdXNwZW5kZWRZaWVsZFwiLCByZWNvcmQuYXJnID09PSBDb250aW51ZVNlbnRpbmVsKSBjb250aW51ZTsgcmV0dXJuIHsgdmFsdWU6IHJlY29yZC5hcmcsIGRvbmU6IGNvbnRleHQuZG9uZSB9OyB9IFwidGhyb3dcIiA9PT0gcmVjb3JkLnR5cGUgJiYgKHN0YXRlID0gXCJjb21wbGV0ZWRcIiwgY29udGV4dC5tZXRob2QgPSBcInRocm93XCIsIGNvbnRleHQuYXJnID0gcmVjb3JkLmFyZyk7IH0gfTsgfSBmdW5jdGlvbiBtYXliZUludm9rZURlbGVnYXRlKGRlbGVnYXRlLCBjb250ZXh0KSB7IHZhciBtZXRob2ROYW1lID0gY29udGV4dC5tZXRob2QsIG1ldGhvZCA9IGRlbGVnYXRlLml0ZXJhdG9yW21ldGhvZE5hbWVdOyBpZiAodW5kZWZpbmVkID09PSBtZXRob2QpIHJldHVybiBjb250ZXh0LmRlbGVnYXRlID0gbnVsbCwgXCJ0aHJvd1wiID09PSBtZXRob2ROYW1lICYmIGRlbGVnYXRlLml0ZXJhdG9yW1wicmV0dXJuXCJdICYmIChjb250ZXh0Lm1ldGhvZCA9IFwicmV0dXJuXCIsIGNvbnRleHQuYXJnID0gdW5kZWZpbmVkLCBtYXliZUludm9rZURlbGVnYXRlKGRlbGVnYXRlLCBjb250ZXh0KSwgXCJ0aHJvd1wiID09PSBjb250ZXh0Lm1ldGhvZCkgfHwgXCJyZXR1cm5cIiAhPT0gbWV0aG9kTmFtZSAmJiAoY29udGV4dC5tZXRob2QgPSBcInRocm93XCIsIGNvbnRleHQuYXJnID0gbmV3IFR5cGVFcnJvcihcIlRoZSBpdGVyYXRvciBkb2VzIG5vdCBwcm92aWRlIGEgJ1wiICsgbWV0aG9kTmFtZSArIFwiJyBtZXRob2RcIikpLCBDb250aW51ZVNlbnRpbmVsOyB2YXIgcmVjb3JkID0gdHJ5Q2F0Y2gobWV0aG9kLCBkZWxlZ2F0ZS5pdGVyYXRvciwgY29udGV4dC5hcmcpOyBpZiAoXCJ0aHJvd1wiID09PSByZWNvcmQudHlwZSkgcmV0dXJuIGNvbnRleHQubWV0aG9kID0gXCJ0aHJvd1wiLCBjb250ZXh0LmFyZyA9IHJlY29yZC5hcmcsIGNvbnRleHQuZGVsZWdhdGUgPSBudWxsLCBDb250aW51ZVNlbnRpbmVsOyB2YXIgaW5mbyA9IHJlY29yZC5hcmc7IHJldHVybiBpbmZvID8gaW5mby5kb25lID8gKGNvbnRleHRbZGVsZWdhdGUucmVzdWx0TmFtZV0gPSBpbmZvLnZhbHVlLCBjb250ZXh0Lm5leHQgPSBkZWxlZ2F0ZS5uZXh0TG9jLCBcInJldHVyblwiICE9PSBjb250ZXh0Lm1ldGhvZCAmJiAoY29udGV4dC5tZXRob2QgPSBcIm5leHRcIiwgY29udGV4dC5hcmcgPSB1bmRlZmluZWQpLCBjb250ZXh0LmRlbGVnYXRlID0gbnVsbCwgQ29udGludWVTZW50aW5lbCkgOiBpbmZvIDogKGNvbnRleHQubWV0aG9kID0gXCJ0aHJvd1wiLCBjb250ZXh0LmFyZyA9IG5ldyBUeXBlRXJyb3IoXCJpdGVyYXRvciByZXN1bHQgaXMgbm90IGFuIG9iamVjdFwiKSwgY29udGV4dC5kZWxlZ2F0ZSA9IG51bGwsIENvbnRpbnVlU2VudGluZWwpOyB9IGZ1bmN0aW9uIHB1c2hUcnlFbnRyeShsb2NzKSB7IHZhciBlbnRyeSA9IHsgdHJ5TG9jOiBsb2NzWzBdIH07IDEgaW4gbG9jcyAmJiAoZW50cnkuY2F0Y2hMb2MgPSBsb2NzWzFdKSwgMiBpbiBsb2NzICYmIChlbnRyeS5maW5hbGx5TG9jID0gbG9jc1syXSwgZW50cnkuYWZ0ZXJMb2MgPSBsb2NzWzNdKSwgdGhpcy50cnlFbnRyaWVzLnB1c2goZW50cnkpOyB9IGZ1bmN0aW9uIHJlc2V0VHJ5RW50cnkoZW50cnkpIHsgdmFyIHJlY29yZCA9IGVudHJ5LmNvbXBsZXRpb24gfHwge307IHJlY29yZC50eXBlID0gXCJub3JtYWxcIiwgZGVsZXRlIHJlY29yZC5hcmcsIGVudHJ5LmNvbXBsZXRpb24gPSByZWNvcmQ7IH0gZnVuY3Rpb24gQ29udGV4dCh0cnlMb2NzTGlzdCkgeyB0aGlzLnRyeUVudHJpZXMgPSBbeyB0cnlMb2M6IFwicm9vdFwiIH1dLCB0cnlMb2NzTGlzdC5mb3JFYWNoKHB1c2hUcnlFbnRyeSwgdGhpcyksIHRoaXMucmVzZXQoITApOyB9IGZ1bmN0aW9uIHZhbHVlcyhpdGVyYWJsZSkgeyBpZiAoaXRlcmFibGUpIHsgdmFyIGl0ZXJhdG9yTWV0aG9kID0gaXRlcmFibGVbaXRlcmF0b3JTeW1ib2xdOyBpZiAoaXRlcmF0b3JNZXRob2QpIHJldHVybiBpdGVyYXRvck1ldGhvZC5jYWxsKGl0ZXJhYmxlKTsgaWYgKFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgaXRlcmFibGUubmV4dCkgcmV0dXJuIGl0ZXJhYmxlOyBpZiAoIWlzTmFOKGl0ZXJhYmxlLmxlbmd0aCkpIHsgdmFyIGkgPSAtMSwgbmV4dCA9IGZ1bmN0aW9uIG5leHQoKSB7IGZvciAoOyArK2kgPCBpdGVyYWJsZS5sZW5ndGg7KSBpZiAoaGFzT3duLmNhbGwoaXRlcmFibGUsIGkpKSByZXR1cm4gbmV4dC52YWx1ZSA9IGl0ZXJhYmxlW2ldLCBuZXh0LmRvbmUgPSAhMSwgbmV4dDsgcmV0dXJuIG5leHQudmFsdWUgPSB1bmRlZmluZWQsIG5leHQuZG9uZSA9ICEwLCBuZXh0OyB9OyByZXR1cm4gbmV4dC5uZXh0ID0gbmV4dDsgfSB9IHJldHVybiB7IG5leHQ6IGRvbmVSZXN1bHQgfTsgfSBmdW5jdGlvbiBkb25lUmVzdWx0KCkgeyByZXR1cm4geyB2YWx1ZTogdW5kZWZpbmVkLCBkb25lOiAhMCB9OyB9IHJldHVybiBHZW5lcmF0b3JGdW5jdGlvbi5wcm90b3R5cGUgPSBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZSwgZGVmaW5lUHJvcGVydHkoR3AsIFwiY29uc3RydWN0b3JcIiwgeyB2YWx1ZTogR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUsIGNvbmZpZ3VyYWJsZTogITAgfSksIGRlZmluZVByb3BlcnR5KEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlLCBcImNvbnN0cnVjdG9yXCIsIHsgdmFsdWU6IEdlbmVyYXRvckZ1bmN0aW9uLCBjb25maWd1cmFibGU6ICEwIH0pLCBHZW5lcmF0b3JGdW5jdGlvbi5kaXNwbGF5TmFtZSA9IGRlZmluZShHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZSwgdG9TdHJpbmdUYWdTeW1ib2wsIFwiR2VuZXJhdG9yRnVuY3Rpb25cIiksIGV4cG9ydHMuaXNHZW5lcmF0b3JGdW5jdGlvbiA9IGZ1bmN0aW9uIChnZW5GdW4pIHsgdmFyIGN0b3IgPSBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIGdlbkZ1biAmJiBnZW5GdW4uY29uc3RydWN0b3I7IHJldHVybiAhIWN0b3IgJiYgKGN0b3IgPT09IEdlbmVyYXRvckZ1bmN0aW9uIHx8IFwiR2VuZXJhdG9yRnVuY3Rpb25cIiA9PT0gKGN0b3IuZGlzcGxheU5hbWUgfHwgY3Rvci5uYW1lKSk7IH0sIGV4cG9ydHMubWFyayA9IGZ1bmN0aW9uIChnZW5GdW4pIHsgcmV0dXJuIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihnZW5GdW4sIEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlKSA6IChnZW5GdW4uX19wcm90b19fID0gR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUsIGRlZmluZShnZW5GdW4sIHRvU3RyaW5nVGFnU3ltYm9sLCBcIkdlbmVyYXRvckZ1bmN0aW9uXCIpKSwgZ2VuRnVuLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoR3ApLCBnZW5GdW47IH0sIGV4cG9ydHMuYXdyYXAgPSBmdW5jdGlvbiAoYXJnKSB7IHJldHVybiB7IF9fYXdhaXQ6IGFyZyB9OyB9LCBkZWZpbmVJdGVyYXRvck1ldGhvZHMoQXN5bmNJdGVyYXRvci5wcm90b3R5cGUpLCBkZWZpbmUoQXN5bmNJdGVyYXRvci5wcm90b3R5cGUsIGFzeW5jSXRlcmF0b3JTeW1ib2wsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0pLCBleHBvcnRzLkFzeW5jSXRlcmF0b3IgPSBBc3luY0l0ZXJhdG9yLCBleHBvcnRzLmFzeW5jID0gZnVuY3Rpb24gKGlubmVyRm4sIG91dGVyRm4sIHNlbGYsIHRyeUxvY3NMaXN0LCBQcm9taXNlSW1wbCkgeyB2b2lkIDAgPT09IFByb21pc2VJbXBsICYmIChQcm9taXNlSW1wbCA9IFByb21pc2UpOyB2YXIgaXRlciA9IG5ldyBBc3luY0l0ZXJhdG9yKHdyYXAoaW5uZXJGbiwgb3V0ZXJGbiwgc2VsZiwgdHJ5TG9jc0xpc3QpLCBQcm9taXNlSW1wbCk7IHJldHVybiBleHBvcnRzLmlzR2VuZXJhdG9yRnVuY3Rpb24ob3V0ZXJGbikgPyBpdGVyIDogaXRlci5uZXh0KCkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7IHJldHVybiByZXN1bHQuZG9uZSA/IHJlc3VsdC52YWx1ZSA6IGl0ZXIubmV4dCgpOyB9KTsgfSwgZGVmaW5lSXRlcmF0b3JNZXRob2RzKEdwKSwgZGVmaW5lKEdwLCB0b1N0cmluZ1RhZ1N5bWJvbCwgXCJHZW5lcmF0b3JcIiksIGRlZmluZShHcCwgaXRlcmF0b3JTeW1ib2wsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0pLCBkZWZpbmUoR3AsIFwidG9TdHJpbmdcIiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gXCJbb2JqZWN0IEdlbmVyYXRvcl1cIjsgfSksIGV4cG9ydHMua2V5cyA9IGZ1bmN0aW9uICh2YWwpIHsgdmFyIG9iamVjdCA9IE9iamVjdCh2YWwpLCBrZXlzID0gW107IGZvciAodmFyIGtleSBpbiBvYmplY3QpIGtleXMucHVzaChrZXkpOyByZXR1cm4ga2V5cy5yZXZlcnNlKCksIGZ1bmN0aW9uIG5leHQoKSB7IGZvciAoOyBrZXlzLmxlbmd0aDspIHsgdmFyIGtleSA9IGtleXMucG9wKCk7IGlmIChrZXkgaW4gb2JqZWN0KSByZXR1cm4gbmV4dC52YWx1ZSA9IGtleSwgbmV4dC5kb25lID0gITEsIG5leHQ7IH0gcmV0dXJuIG5leHQuZG9uZSA9ICEwLCBuZXh0OyB9OyB9LCBleHBvcnRzLnZhbHVlcyA9IHZhbHVlcywgQ29udGV4dC5wcm90b3R5cGUgPSB7IGNvbnN0cnVjdG9yOiBDb250ZXh0LCByZXNldDogZnVuY3Rpb24gcmVzZXQoc2tpcFRlbXBSZXNldCkgeyBpZiAodGhpcy5wcmV2ID0gMCwgdGhpcy5uZXh0ID0gMCwgdGhpcy5zZW50ID0gdGhpcy5fc2VudCA9IHVuZGVmaW5lZCwgdGhpcy5kb25lID0gITEsIHRoaXMuZGVsZWdhdGUgPSBudWxsLCB0aGlzLm1ldGhvZCA9IFwibmV4dFwiLCB0aGlzLmFyZyA9IHVuZGVmaW5lZCwgdGhpcy50cnlFbnRyaWVzLmZvckVhY2gocmVzZXRUcnlFbnRyeSksICFza2lwVGVtcFJlc2V0KSBmb3IgKHZhciBuYW1lIGluIHRoaXMpIFwidFwiID09PSBuYW1lLmNoYXJBdCgwKSAmJiBoYXNPd24uY2FsbCh0aGlzLCBuYW1lKSAmJiAhaXNOYU4oK25hbWUuc2xpY2UoMSkpICYmICh0aGlzW25hbWVdID0gdW5kZWZpbmVkKTsgfSwgc3RvcDogZnVuY3Rpb24gc3RvcCgpIHsgdGhpcy5kb25lID0gITA7IHZhciByb290UmVjb3JkID0gdGhpcy50cnlFbnRyaWVzWzBdLmNvbXBsZXRpb247IGlmIChcInRocm93XCIgPT09IHJvb3RSZWNvcmQudHlwZSkgdGhyb3cgcm9vdFJlY29yZC5hcmc7IHJldHVybiB0aGlzLnJ2YWw7IH0sIGRpc3BhdGNoRXhjZXB0aW9uOiBmdW5jdGlvbiBkaXNwYXRjaEV4Y2VwdGlvbihleGNlcHRpb24pIHsgaWYgKHRoaXMuZG9uZSkgdGhyb3cgZXhjZXB0aW9uOyB2YXIgY29udGV4dCA9IHRoaXM7IGZ1bmN0aW9uIGhhbmRsZShsb2MsIGNhdWdodCkgeyByZXR1cm4gcmVjb3JkLnR5cGUgPSBcInRocm93XCIsIHJlY29yZC5hcmcgPSBleGNlcHRpb24sIGNvbnRleHQubmV4dCA9IGxvYywgY2F1Z2h0ICYmIChjb250ZXh0Lm1ldGhvZCA9IFwibmV4dFwiLCBjb250ZXh0LmFyZyA9IHVuZGVmaW5lZCksICEhY2F1Z2h0OyB9IGZvciAodmFyIGkgPSB0aGlzLnRyeUVudHJpZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHsgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldLCByZWNvcmQgPSBlbnRyeS5jb21wbGV0aW9uOyBpZiAoXCJyb290XCIgPT09IGVudHJ5LnRyeUxvYykgcmV0dXJuIGhhbmRsZShcImVuZFwiKTsgaWYgKGVudHJ5LnRyeUxvYyA8PSB0aGlzLnByZXYpIHsgdmFyIGhhc0NhdGNoID0gaGFzT3duLmNhbGwoZW50cnksIFwiY2F0Y2hMb2NcIiksIGhhc0ZpbmFsbHkgPSBoYXNPd24uY2FsbChlbnRyeSwgXCJmaW5hbGx5TG9jXCIpOyBpZiAoaGFzQ2F0Y2ggJiYgaGFzRmluYWxseSkgeyBpZiAodGhpcy5wcmV2IDwgZW50cnkuY2F0Y2hMb2MpIHJldHVybiBoYW5kbGUoZW50cnkuY2F0Y2hMb2MsICEwKTsgaWYgKHRoaXMucHJldiA8IGVudHJ5LmZpbmFsbHlMb2MpIHJldHVybiBoYW5kbGUoZW50cnkuZmluYWxseUxvYyk7IH0gZWxzZSBpZiAoaGFzQ2F0Y2gpIHsgaWYgKHRoaXMucHJldiA8IGVudHJ5LmNhdGNoTG9jKSByZXR1cm4gaGFuZGxlKGVudHJ5LmNhdGNoTG9jLCAhMCk7IH0gZWxzZSB7IGlmICghaGFzRmluYWxseSkgdGhyb3cgbmV3IEVycm9yKFwidHJ5IHN0YXRlbWVudCB3aXRob3V0IGNhdGNoIG9yIGZpbmFsbHlcIik7IGlmICh0aGlzLnByZXYgPCBlbnRyeS5maW5hbGx5TG9jKSByZXR1cm4gaGFuZGxlKGVudHJ5LmZpbmFsbHlMb2MpOyB9IH0gfSB9LCBhYnJ1cHQ6IGZ1bmN0aW9uIGFicnVwdCh0eXBlLCBhcmcpIHsgZm9yICh2YXIgaSA9IHRoaXMudHJ5RW50cmllcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgeyB2YXIgZW50cnkgPSB0aGlzLnRyeUVudHJpZXNbaV07IGlmIChlbnRyeS50cnlMb2MgPD0gdGhpcy5wcmV2ICYmIGhhc093bi5jYWxsKGVudHJ5LCBcImZpbmFsbHlMb2NcIikgJiYgdGhpcy5wcmV2IDwgZW50cnkuZmluYWxseUxvYykgeyB2YXIgZmluYWxseUVudHJ5ID0gZW50cnk7IGJyZWFrOyB9IH0gZmluYWxseUVudHJ5ICYmIChcImJyZWFrXCIgPT09IHR5cGUgfHwgXCJjb250aW51ZVwiID09PSB0eXBlKSAmJiBmaW5hbGx5RW50cnkudHJ5TG9jIDw9IGFyZyAmJiBhcmcgPD0gZmluYWxseUVudHJ5LmZpbmFsbHlMb2MgJiYgKGZpbmFsbHlFbnRyeSA9IG51bGwpOyB2YXIgcmVjb3JkID0gZmluYWxseUVudHJ5ID8gZmluYWxseUVudHJ5LmNvbXBsZXRpb24gOiB7fTsgcmV0dXJuIHJlY29yZC50eXBlID0gdHlwZSwgcmVjb3JkLmFyZyA9IGFyZywgZmluYWxseUVudHJ5ID8gKHRoaXMubWV0aG9kID0gXCJuZXh0XCIsIHRoaXMubmV4dCA9IGZpbmFsbHlFbnRyeS5maW5hbGx5TG9jLCBDb250aW51ZVNlbnRpbmVsKSA6IHRoaXMuY29tcGxldGUocmVjb3JkKTsgfSwgY29tcGxldGU6IGZ1bmN0aW9uIGNvbXBsZXRlKHJlY29yZCwgYWZ0ZXJMb2MpIHsgaWYgKFwidGhyb3dcIiA9PT0gcmVjb3JkLnR5cGUpIHRocm93IHJlY29yZC5hcmc7IHJldHVybiBcImJyZWFrXCIgPT09IHJlY29yZC50eXBlIHx8IFwiY29udGludWVcIiA9PT0gcmVjb3JkLnR5cGUgPyB0aGlzLm5leHQgPSByZWNvcmQuYXJnIDogXCJyZXR1cm5cIiA9PT0gcmVjb3JkLnR5cGUgPyAodGhpcy5ydmFsID0gdGhpcy5hcmcgPSByZWNvcmQuYXJnLCB0aGlzLm1ldGhvZCA9IFwicmV0dXJuXCIsIHRoaXMubmV4dCA9IFwiZW5kXCIpIDogXCJub3JtYWxcIiA9PT0gcmVjb3JkLnR5cGUgJiYgYWZ0ZXJMb2MgJiYgKHRoaXMubmV4dCA9IGFmdGVyTG9jKSwgQ29udGludWVTZW50aW5lbDsgfSwgZmluaXNoOiBmdW5jdGlvbiBmaW5pc2goZmluYWxseUxvYykgeyBmb3IgKHZhciBpID0gdGhpcy50cnlFbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7IHZhciBlbnRyeSA9IHRoaXMudHJ5RW50cmllc1tpXTsgaWYgKGVudHJ5LmZpbmFsbHlMb2MgPT09IGZpbmFsbHlMb2MpIHJldHVybiB0aGlzLmNvbXBsZXRlKGVudHJ5LmNvbXBsZXRpb24sIGVudHJ5LmFmdGVyTG9jKSwgcmVzZXRUcnlFbnRyeShlbnRyeSksIENvbnRpbnVlU2VudGluZWw7IH0gfSwgXCJjYXRjaFwiOiBmdW5jdGlvbiBfY2F0Y2godHJ5TG9jKSB7IGZvciAodmFyIGkgPSB0aGlzLnRyeUVudHJpZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHsgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldOyBpZiAoZW50cnkudHJ5TG9jID09PSB0cnlMb2MpIHsgdmFyIHJlY29yZCA9IGVudHJ5LmNvbXBsZXRpb247IGlmIChcInRocm93XCIgPT09IHJlY29yZC50eXBlKSB7IHZhciB0aHJvd24gPSByZWNvcmQuYXJnOyByZXNldFRyeUVudHJ5KGVudHJ5KTsgfSByZXR1cm4gdGhyb3duOyB9IH0gdGhyb3cgbmV3IEVycm9yKFwiaWxsZWdhbCBjYXRjaCBhdHRlbXB0XCIpOyB9LCBkZWxlZ2F0ZVlpZWxkOiBmdW5jdGlvbiBkZWxlZ2F0ZVlpZWxkKGl0ZXJhYmxlLCByZXN1bHROYW1lLCBuZXh0TG9jKSB7IHJldHVybiB0aGlzLmRlbGVnYXRlID0geyBpdGVyYXRvcjogdmFsdWVzKGl0ZXJhYmxlKSwgcmVzdWx0TmFtZTogcmVzdWx0TmFtZSwgbmV4dExvYzogbmV4dExvYyB9LCBcIm5leHRcIiA9PT0gdGhpcy5tZXRob2QgJiYgKHRoaXMuYXJnID0gdW5kZWZpbmVkKSwgQ29udGludWVTZW50aW5lbDsgfSB9LCBleHBvcnRzOyB9XG5mdW5jdGlvbiBhc3luY0dlbmVyYXRvclN0ZXAoZ2VuLCByZXNvbHZlLCByZWplY3QsIF9uZXh0LCBfdGhyb3csIGtleSwgYXJnKSB7IHRyeSB7IHZhciBpbmZvID0gZ2VuW2tleV0oYXJnKTsgdmFyIHZhbHVlID0gaW5mby52YWx1ZTsgfSBjYXRjaCAoZXJyb3IpIHsgcmVqZWN0KGVycm9yKTsgcmV0dXJuOyB9IGlmIChpbmZvLmRvbmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0gZWxzZSB7IFByb21pc2UucmVzb2x2ZSh2YWx1ZSkudGhlbihfbmV4dCwgX3Rocm93KTsgfSB9XG5mdW5jdGlvbiBfYXN5bmNUb0dlbmVyYXRvcihmbikgeyByZXR1cm4gZnVuY3Rpb24gKCkgeyB2YXIgc2VsZiA9IHRoaXMsIGFyZ3MgPSBhcmd1bWVudHM7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7IHZhciBnZW4gPSBmbi5hcHBseShzZWxmLCBhcmdzKTsgZnVuY3Rpb24gX25leHQodmFsdWUpIHsgYXN5bmNHZW5lcmF0b3JTdGVwKGdlbiwgcmVzb2x2ZSwgcmVqZWN0LCBfbmV4dCwgX3Rocm93LCBcIm5leHRcIiwgdmFsdWUpOyB9IGZ1bmN0aW9uIF90aHJvdyhlcnIpIHsgYXN5bmNHZW5lcmF0b3JTdGVwKGdlbiwgcmVzb2x2ZSwgcmVqZWN0LCBfbmV4dCwgX3Rocm93LCBcInRocm93XCIsIGVycik7IH0gX25leHQodW5kZWZpbmVkKTsgfSk7IH07IH1cbmltcG9ydCB7IEh0bWw1UXJjb2RlU2Nhbm5lciwgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUsIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyB9IGZyb20gXCJodG1sNS1xcmNvZGVcIjtcbmltcG9ydCB7IGVkNDQ4IH0gZnJvbSBcIkBub2JsZS9jdXJ2ZXMvZWQ0NDhcIjtcbmltcG9ydCB7IEJ1ZmZlciB9IGZyb20gXCJidWZmZXJcIjtcbnZhciBjdXJyZW50bHlBZGRpbmdJdGVtQnlUYWcgPSBuZXcgTWFwKCk7XG52YXIgcmVjZWl2ZWRfaXRlbXMgPSB7fTtcbnZhciBjb25maWc7XG52YXIgc2Nhbm5lciA9IG5ldyBIdG1sNVFyY29kZVNjYW5uZXIoXCJyZWFkZXJcIiwge1xuICBmcHM6IDEwLFxuICBxcmJveDoge1xuICAgIHdpZHRoOiAyNTAsXG4gICAgaGVpZ2h0OiAyNTBcbiAgfSxcbiAgc2hvd1RvcmNoQnV0dG9uSWZTdXBwb3J0ZWQ6IHRydWUsXG4gIGZvcm1hdHNUb1N1cHBvcnQ6IFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUVJfQ09ERV0sXG4gIC8vdGhlcmUgYXJlIG1hbnkgb3RoZXIgdHlwZXMgb2YgY29kZXMgb24gdGhlIGxhYmVscyB3ZSBkbyBub3Qgd2FudFxuICByZW1lbWJlckxhc3RVc2VkQ2FtZXJhOiB0cnVlXG59KTtcbnZhciBzY2FubmVyX2F1ZGlvID0gbmV3IEF1ZGlvKFwiL2JlZXAud2F2XCIpO1xuc2Nhbm5lcl9hdWRpby5sb2FkKCk7XG52YXIgdG9hc3REaXYgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcImJvdHRvbVRvYXN0XCIpO1xuXG4vKlxuICogSGVscGVyIGZ1bmN0aW9uc1xuICovXG5mdW5jdGlvbiBodG9hKGgpIHtcbiAgcmV0dXJuIFVpbnQ4QXJyYXkuZnJvbShCdWZmZXIuZnJvbShoLCBcImhleFwiKSk7XG59XG5mdW5jdGlvbiB0b2FzdCh0aXRsZSwgbWVzc2FnZSkge1xuICB0b2FzdERpdi5jaGlsZHJlblswXS5jaGlsZHJlblswXS5pbm5lckhUTUwgPSB0aXRsZTtcbiAgdG9hc3REaXYuY2hpbGRyZW5bMV0uaW5uZXJIVE1MID0gbWVzc2FnZTtcbiAgdG9hc3REaXYuY2xhc3NMaXN0LnJlbW92ZShcImhpZGVcIik7XG4gIHRvYXN0RGl2LmNsYXNzTGlzdC5hZGQoXCJzaG93XCIpO1xuICB0b2FzdERpdi5jbGFzc0xpc3QuYWRkKFwic2hvd2luZ1wiKTtcbiAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgdG9hc3REaXYuY2xhc3NMaXN0LnJlbW92ZShcInNob3dcIik7XG4gICAgdG9hc3REaXYuY2xhc3NMaXN0LnJlbW92ZShcInNob3dpbmdcIik7XG4gICAgdG9hc3REaXYuY2xhc3NMaXN0LmFkZChcImhpZGVcIik7XG4gIH0sIDMwMDApO1xufVxuZnVuY3Rpb24gZmV0Y2hXaXRoQXV0aChfeCwgX3gyKSB7XG4gIHJldHVybiBfZmV0Y2hXaXRoQXV0aC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2ZldGNoV2l0aEF1dGgoKSB7XG4gIF9mZXRjaFdpdGhBdXRoID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlKGlucHV0LCBpbml0KSB7XG4gICAgdmFyIHJlc3BvbnNlO1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlJChfY29udGV4dCkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQucHJldiA9IF9jb250ZXh0Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGlmIChpbml0ID09IHVuZGVmaW5lZCB8fCBpbml0ID09IG51bGwpIHtcbiAgICAgICAgICAgIGluaXQgPSB7fTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGluaXRbXCJoZWFkZXJzXCJdID09IG51bGwpIHtcbiAgICAgICAgICAgIGluaXRbXCJoZWFkZXJzXCJdID0ge307XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh3aW5kb3cuc2Vzc2lvblN0b3JhZ2UuZ2V0SXRlbShcImFjY2Vzc190b2tlblwiKSkge1xuICAgICAgICAgICAgX2NvbnRleHQubmV4dCA9IDU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgX2NvbnRleHQubmV4dCA9IDU7XG4gICAgICAgICAgcmV0dXJuIGxvZ2luKCk7XG4gICAgICAgIGNhc2UgNTpcbiAgICAgICAgICBpbml0W1wiaGVhZGVyc1wiXVtcIkF1dGhvcml6YXRpb25cIl0gPSBcIkJlYXJlciBcIiArIHdpbmRvdy5zZXNzaW9uU3RvcmFnZS5nZXRJdGVtKFwiYWNjZXNzX3Rva2VuXCIpO1xuICAgICAgICAgIF9jb250ZXh0Lm5leHQgPSA4O1xuICAgICAgICAgIHJldHVybiBmZXRjaChpbnB1dCwgaW5pdCk7XG4gICAgICAgIGNhc2UgODpcbiAgICAgICAgICByZXNwb25zZSA9IF9jb250ZXh0LnNlbnQ7XG4gICAgICAgIGNhc2UgOTpcbiAgICAgICAgICBpZiAoIShyZXNwb25zZS5zdGF0dXMgPT0gNDAxKSkge1xuICAgICAgICAgICAgX2NvbnRleHQubmV4dCA9IDE5O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiRmV0Y2ggd2l0aCBhdXRoIGZhaWxlZCBmb3JcIiwgaW5wdXQpO1xuICAgICAgICAgIF9jb250ZXh0Lm5leHQgPSAxMztcbiAgICAgICAgICByZXR1cm4gbG9naW4oKTtcbiAgICAgICAgY2FzZSAxMzpcbiAgICAgICAgICBpbml0W1wiaGVhZGVyc1wiXVtcIkF1dGhvcml6YXRpb25cIl0gPSBcIkJlYXJlciBcIiArIHdpbmRvdy5zZXNzaW9uU3RvcmFnZS5nZXRJdGVtKFwiYWNjZXNzX3Rva2VuXCIpO1xuICAgICAgICAgIF9jb250ZXh0Lm5leHQgPSAxNjtcbiAgICAgICAgICByZXR1cm4gZmV0Y2goaW5wdXQsIGluaXQpO1xuICAgICAgICBjYXNlIDE2OlxuICAgICAgICAgIHJlc3BvbnNlID0gX2NvbnRleHQuc2VudDtcbiAgICAgICAgICBfY29udGV4dC5uZXh0ID0gOTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAxOTpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQuYWJydXB0KFwicmV0dXJuXCIsIHJlc3BvbnNlKTtcbiAgICAgICAgY2FzZSAyMDpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dC5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZSk7XG4gIH0pKTtcbiAgcmV0dXJuIF9mZXRjaFdpdGhBdXRoLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBjaGVja1Jlc3BvbnNlRm9yRXJyb3IoX3gzLCBfeDQpIHtcbiAgcmV0dXJuIF9jaGVja1Jlc3BvbnNlRm9yRXJyb3IuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9jaGVja1Jlc3BvbnNlRm9yRXJyb3IoKSB7XG4gIF9jaGVja1Jlc3BvbnNlRm9yRXJyb3IgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUyKHJlc3BvbnNlLCBtZXNzYWdlKSB7XG4gICAgdmFyIGNvbnRlbnQ7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUyJChfY29udGV4dDIpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0Mi5wcmV2ID0gX2NvbnRleHQyLm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGlmICghKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSkge1xuICAgICAgICAgICAgX2NvbnRleHQyLm5leHQgPSA3O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0Mi5uZXh0ID0gMztcbiAgICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgY29udGVudCA9IF9jb250ZXh0Mi5zZW50O1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiR290IFJlc3BvbnNlIEVycm9yOlwiLCBtZXNzYWdlLCByZXNwb25zZSk7XG4gICAgICAgICAgYWxlcnQobWVzc2FnZSArIFwiOyBTdGF0dXM6IFwiICsgcmVzcG9uc2Uuc3RhdHVzICsgXCI7IENvbnRlbnQ6IFwiICsgY29udGVudCk7XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0Mi5hYnJ1cHQoXCJyZXR1cm5cIiwgZmFsc2UpO1xuICAgICAgICBjYXNlIDc6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0Mi5hYnJ1cHQoXCJyZXR1cm5cIiwgdHJ1ZSk7XG4gICAgICAgIGNhc2UgODpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDIuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUyKTtcbiAgfSkpO1xuICByZXR1cm4gX2NoZWNrUmVzcG9uc2VGb3JFcnJvci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gZ2V0Q29uZmlnKCkge1xuICByZXR1cm4gX2dldENvbmZpZy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2dldENvbmZpZygpIHtcbiAgX2dldENvbmZpZyA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTMoKSB7XG4gICAgdmFyIGNvbmZpZ19yZXF1ZXN0O1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMyQoX2NvbnRleHQzKSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDMucHJldiA9IF9jb250ZXh0My5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBpZiAoIShjb25maWcgPT0gdW5kZWZpbmVkKSkge1xuICAgICAgICAgICAgX2NvbnRleHQzLm5leHQgPSAxMjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dDMubmV4dCA9IDM7XG4gICAgICAgICAgcmV0dXJuIGZldGNoKFwiY29uZmlnLmpzb25cIik7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICBjb25maWdfcmVxdWVzdCA9IF9jb250ZXh0My5zZW50O1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiTG9hZGluZyBjb25maWdcIik7XG4gICAgICAgICAgX2NvbnRleHQzLm5leHQgPSA3O1xuICAgICAgICAgIHJldHVybiBjaGVja1Jlc3BvbnNlRm9yRXJyb3IoY29uZmlnX3JlcXVlc3QsIFwiQ291bGQgbm90IGxvYWQgY29uZmlnXCIpO1xuICAgICAgICBjYXNlIDc6XG4gICAgICAgICAgaWYgKCFfY29udGV4dDMuc2VudCkge1xuICAgICAgICAgICAgX2NvbnRleHQzLm5leHQgPSAxMjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dDMubmV4dCA9IDEwO1xuICAgICAgICAgIHJldHVybiBjb25maWdfcmVxdWVzdC5qc29uKCk7XG4gICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgY29uZmlnID0gX2NvbnRleHQzLnNlbnQ7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJMb2FkZWQgY29uZmlnXCIpO1xuICAgICAgICBjYXNlIDEyOlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0My5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTMpO1xuICB9KSk7XG4gIHJldHVybiBfZ2V0Q29uZmlnLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBsb2dpbihfeDUpIHtcbiAgcmV0dXJuIF9sb2dpbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2xvZ2luKCkge1xuICBfbG9naW4gPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWU0KHBhc3N3b3JkVG9UcnkpIHtcbiAgICB2YXIgbG9naW5TdWNjZXNzLCBwYXNzd29yZCwgZm9ybSwgcmVzcG9uc2UsIHJlc3VsdDtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTQkKF9jb250ZXh0NCkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQ0LnByZXYgPSBfY29udGV4dDQubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgY29uc29sZS5sb2coXCJQZXJmb3JtaW5nIGxvZ2luXCIpO1xuICAgICAgICAgIGxvZ2luU3VjY2VzcyA9IGZhbHNlO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgaWYgKHBhc3N3b3JkVG9UcnkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCJVc2luZyBwYXNzd29yZCB0byB0cnkgZnJvbSBwYXJhbWV0ZXJcIik7XG4gICAgICAgICAgICBwYXNzd29yZCA9IHBhc3N3b3JkVG9Ucnk7XG4gICAgICAgICAgICBwYXNzd29yZFRvVHJ5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIlByb21wdGluZyB1c2VyIGZvciBzaGFyZWQgc2VjcmV0LlwiKTtcbiAgICAgICAgICAgIHBhc3N3b3JkID0gcHJvbXB0KFwicHJvdmlkZSB0aGUgc2hhcmVkIHNlY3JldFwiKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZm9ybSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgIGZvcm0uYXBwZW5kKFwiZ3JhbnRfdHlwZVwiLCBcInBhc3N3b3JkXCIpO1xuICAgICAgICAgIGZvcm0uYXBwZW5kKFwidXNlcm5hbWVcIiwgXCJ3b3JrZXJcIik7XG4gICAgICAgICAgZm9ybS5hcHBlbmQoXCJwYXNzd29yZFwiLCBwYXNzd29yZCk7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJSZXF1ZXN0aW5nIHRva2VuLlwiKTtcbiAgICAgICAgICBfY29udGV4dDQubmV4dCA9IDEwO1xuICAgICAgICAgIHJldHVybiBmZXRjaChjb25maWcuYmFja2VuZF91cmwgKyBcIi90b2tlblwiLCB7XG4gICAgICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICAgICAgYm9keTogZm9ybVxuICAgICAgICAgIH0pO1xuICAgICAgICBjYXNlIDEwOlxuICAgICAgICAgIHJlc3BvbnNlID0gX2NvbnRleHQ0LnNlbnQ7XG4gICAgICAgICAgX2NvbnRleHQ0Lm5leHQgPSAxMztcbiAgICAgICAgICByZXR1cm4gY2hlY2tSZXNwb25zZUZvckVycm9yKHJlc3BvbnNlLCBcIkxvZ2luIGZhaWxlZFwiKTtcbiAgICAgICAgY2FzZSAxMzpcbiAgICAgICAgICBpZiAoIV9jb250ZXh0NC5zZW50KSB7XG4gICAgICAgICAgICBfY29udGV4dDQubmV4dCA9IDIwO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0NC5uZXh0ID0gMTY7XG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgY2FzZSAxNjpcbiAgICAgICAgICByZXN1bHQgPSBfY29udGV4dDQuc2VudDtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkdvdCB0b2tlblwiKTtcbiAgICAgICAgICB3aW5kb3cuc2Vzc2lvblN0b3JhZ2Uuc2V0SXRlbShcImFjY2Vzc190b2tlblwiLCByZXN1bHQuYWNjZXNzX3Rva2VuKTtcbiAgICAgICAgICBsb2dpblN1Y2Nlc3MgPSB0cnVlO1xuICAgICAgICBjYXNlIDIwOlxuICAgICAgICAgIGlmICghbG9naW5TdWNjZXNzKSB7XG4gICAgICAgICAgICBfY29udGV4dDQubmV4dCA9IDI7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIGNhc2UgMjE6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ0LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlNCk7XG4gIH0pKTtcbiAgcmV0dXJuIF9sb2dpbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gdXBkYXRlSXRlbXNWaWV3KCkge1xuICBjb25zb2xlLmxvZyhcIlVwZGF0aW5nIGl0ZW1zIHZpZXdcIik7XG4gIHZhciBpdGVtcyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjaXRlbXNcIik7XG4gIGl0ZW1zLmlubmVySFRNTCA9IFwiXCI7XG4gIGZvciAodmFyIGl0ZW0gaW4gcmVjZWl2ZWRfaXRlbXMpIHtcbiAgICB2YXIgbGkgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwibGlcIik7XG4gICAgY29uc29sZS5sb2coaXRlbSk7XG4gICAgY29uc29sZS5sb2cocmVjZWl2ZWRfaXRlbXNbaXRlbV0pO1xuICAgIGxpLmlubmVySFRNTCA9IFwiPGRpdiBpZD1cXFwiaXRlbV9cIiArIHJlY2VpdmVkX2l0ZW1zW2l0ZW1dLml0ZW0udXVpZCArIFwiXFxcIiBjbGFzcz1cXFwiYWxlcnQgYWxlcnQtc3VjY2Vzc1xcXCIgcm9sZT1cXFwiYWxlcnRcXFwiPlwiICsgcmVjZWl2ZWRfaXRlbXNbaXRlbV0uaXRlbS50YWcgKyBcIiAoXCIgKyByZWNlaXZlZF9pdGVtc1tpdGVtXS5pdGVtLmFkZHJlc3NlZSArIFwiLCBcIiArIHJlY2VpdmVkX2l0ZW1zW2l0ZW1dLml0ZW0udGVhbSArIFwiKVwiICsgXCImZW1zcDs8c3BhbiBjbGFzcz1cXFwiYmFkZ2UgYmFkZ2UtbGlnaHRcXFwiPlwiICsgcmVjZWl2ZWRfaXRlbXNbaXRlbV0ubnVtICsgXCI8L3NwYW4+XCIgKyBcIiZlbXNwOzxidXR0b24gY2xhc3M9XFxcImJ0biBidG4tcHJpbWFyeVxcXCIgb25jbGljaz1cXFwibGliLmluY3JlYXNlSXRlbUNvdW50KCdcIiArIHJlY2VpdmVkX2l0ZW1zW2l0ZW1dLml0ZW0udXVpZCArIFwiJylcXFwiPis8L2J1dHRvbj5cIiArIFwiJmVtc3A7PGJ1dHRvbiBjbGFzcz1cXFwiYnRuIGJ0bi1wcmltYXJ5XFxcIiBvbmNsaWNrPVxcXCJsaWIuZGVjcmVhc2VJdGVtQ291bnQoJ1wiICsgcmVjZWl2ZWRfaXRlbXNbaXRlbV0uaXRlbS51dWlkICsgXCInKVxcXCI+LTwvYnV0dG9uPjwvZGl2PlwiO1xuICAgIGl0ZW1zLmFwcGVuZENoaWxkKGxpKTtcbiAgfVxufVxuXG4vKlxuICogdmFyaW91cyBhZGQgSXRlbXMgZnVuY3Rpb25zXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG9uVGFnVGV4dFVwZGF0ZShfeDYpIHtcbiAgcmV0dXJuIF9vblRhZ1RleHRVcGRhdGUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9vblRhZ1RleHRVcGRhdGUoKSB7XG4gIF9vblRhZ1RleHRVcGRhdGUgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWU1KGVsZW1lbnQpIHtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTUkKF9jb250ZXh0NSkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQ1LnByZXYgPSBfY29udGV4dDUubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgaWYgKCEoZWxlbWVudC52YWx1ZS5sZW5ndGggPT0gMCkpIHtcbiAgICAgICAgICAgIF9jb250ZXh0NS5uZXh0ID0gNTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbGVtZW50LnNldEN1c3RvbVZhbGlkaXR5KFwiXCIpO1xuICAgICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShcImlzLWludmFsaWRcIik7XG4gICAgICAgICAgX2NvbnRleHQ1Lm5leHQgPSAxMjtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSA1OlxuICAgICAgICAgIGlmICghKGVsZW1lbnQudmFsdWUubGVuZ3RoICE9IDYpKSB7XG4gICAgICAgICAgICBfY29udGV4dDUubmV4dCA9IDExO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsZW1lbnQuc2V0Q3VzdG9tVmFsaWRpdHkoXCJDb2RlIG11c3QgYmUgNiBjaGFycyBsb25nLlwiKTtcbiAgICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5hZGQoXCJpcy1pbnZhbGlkXCIpO1xuICAgICAgICAgIHJldHVybiBfY29udGV4dDUuYWJydXB0KFwicmV0dXJuXCIpO1xuICAgICAgICBjYXNlIDExOlxuICAgICAgICAgIHRhZ0VudGVyZWQoZWxlbWVudCk7XG4gICAgICAgIGNhc2UgMTI6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ1LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlNSk7XG4gIH0pKTtcbiAgcmV0dXJuIF9vblRhZ1RleHRVcGRhdGUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBvblRhZ0lucHV0Q2hhbmdlZChfeDcpIHtcbiAgcmV0dXJuIF9vblRhZ0lucHV0Q2hhbmdlZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX29uVGFnSW5wdXRDaGFuZ2VkKCkge1xuICBfb25UYWdJbnB1dENoYW5nZWQgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWU2KGVsZW1lbnQpIHtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTYkKF9jb250ZXh0Nikge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQ2LnByZXYgPSBfY29udGV4dDYubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgLy8gRWxlbWVudCBsb3N0IGZvY3VzIG9yIHVzZXIgcHJlc3NlZCBlbnRlclxuICAgICAgICAgIGlmIChlbGVtZW50LnZhbHVlLmxlbmd0aCA9PSA2KSB7XG4gICAgICAgICAgICB0YWdFbnRlcmVkKGVsZW1lbnQpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbGVtZW50LnJlcG9ydFZhbGlkaXR5KCk7XG4gICAgICAgICAgfVxuICAgICAgICBjYXNlIDE6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ2LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlNik7XG4gIH0pKTtcbiAgcmV0dXJuIF9vblRhZ0lucHV0Q2hhbmdlZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gdGFnRW50ZXJlZChfeDgpIHtcbiAgcmV0dXJuIF90YWdFbnRlcmVkLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfdGFnRW50ZXJlZCgpIHtcbiAgX3RhZ0VudGVyZWQgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWU3KGVsZW1lbnQpIHtcbiAgICB2YXIgdGFnLCBzdWNjO1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlNyQoX2NvbnRleHQ3KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDcucHJldiA9IF9jb250ZXh0Ny5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICB0YWcgPSBlbGVtZW50LnZhbHVlO1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiVGFnIEVudGVyZWRcIiwgdGFnKTtcbiAgICAgICAgICBpZiAoIWN1cnJlbnRseUFkZGluZ0l0ZW1CeVRhZy5oYXModGFnKSkge1xuICAgICAgICAgICAgX2NvbnRleHQ3Lm5leHQgPSA0O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBfY29udGV4dDcuYWJydXB0KFwicmV0dXJuXCIpO1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgY3VycmVudGx5QWRkaW5nSXRlbUJ5VGFnLnNldCh0YWcsIFwiXCIpO1xuICAgICAgICAgIF9jb250ZXh0Ny5uZXh0ID0gNztcbiAgICAgICAgICByZXR1cm4gYWRkSXRlbUJ5VGFnKGVsZW1lbnQudmFsdWUpO1xuICAgICAgICBjYXNlIDc6XG4gICAgICAgICAgc3VjYyA9IF9jb250ZXh0Ny5zZW50O1xuICAgICAgICAgIGlmIChzdWNjKSB7XG4gICAgICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoXCJpcy1pbnZhbGlkXCIpO1xuICAgICAgICAgICAgZWxlbWVudC52YWx1ZSA9IFwiXCI7XG4gICAgICAgICAgICBlbGVtZW50LnNldEN1c3RvbVZhbGlkaXR5KFwiXCIpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbGVtZW50LnNldEN1c3RvbVZhbGlkaXR5KFwiVW5rbm93biBpdGVtXCIpO1xuICAgICAgICAgICAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKFwiaXMtaW52YWxpZFwiKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxlbWVudC5yZXBvcnRWYWxpZGl0eSgpO1xuICAgICAgICAgIGN1cnJlbnRseUFkZGluZ0l0ZW1CeVRhZ1tcImRlbGV0ZVwiXSh0YWcpO1xuICAgICAgICBjYXNlIDExOlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0Ny5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTcpO1xuICB9KSk7XG4gIHJldHVybiBfdGFnRW50ZXJlZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGFkZEl0ZW1CeVRhZyhfeDkpIHtcbiAgcmV0dXJuIF9hZGRJdGVtQnlUYWcuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9hZGRJdGVtQnlUYWcoKSB7XG4gIF9hZGRJdGVtQnlUYWcgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWU4KHRhZykge1xuICAgIHZhciByZXNwb25zZSwgdHJhY2tpbmdfaXRlbTtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTgkKF9jb250ZXh0OCkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQ4LnByZXYgPSBfY29udGV4dDgubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgaWYgKCEodGFnLmxlbmd0aCAhPSA2KSkge1xuICAgICAgICAgICAgX2NvbnRleHQ4Lm5leHQgPSAyO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRocm93IFwiSW50ZXJuYWwgRXJyb3I6IFRhZyBub3QgbGVuZ3RoIDYuXCI7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICB0YWcgPSB0YWcudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIlRyeWluZyB0byBhZGQgaXRlbSBieSB0YWc6XCIsIHRhZyk7XG4gICAgICAgICAgX2NvbnRleHQ4Lm5leHQgPSA2O1xuICAgICAgICAgIHJldHVybiBmZXRjaFdpdGhBdXRoKGNvbmZpZy5iYWNrZW5kX3VybCArIFwiL3RhZy9cIiArIHRhZyk7XG4gICAgICAgIGNhc2UgNjpcbiAgICAgICAgICByZXNwb25zZSA9IF9jb250ZXh0OC5zZW50O1xuICAgICAgICAgIGlmICghKHJlc3BvbnNlLnN0YXR1cyA9PSAyMDApKSB7XG4gICAgICAgICAgICBfY29udGV4dDgubmV4dCA9IDE4O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0OC5uZXh0ID0gMTA7XG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgY2FzZSAxMDpcbiAgICAgICAgICB0cmFja2luZ19pdGVtID0gX2NvbnRleHQ4LnNlbnQ7XG4gICAgICAgICAgaWYgKHRyYWNraW5nX2l0ZW0udXVpZCBpbiByZWNlaXZlZF9pdGVtcykge1xuICAgICAgICAgICAgcmVjZWl2ZWRfaXRlbXNbdHJhY2tpbmdfaXRlbS51dWlkXS5udW0gKz0gMTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVjZWl2ZWRfaXRlbXNbdHJhY2tpbmdfaXRlbS51dWlkXSA9IHtcbiAgICAgICAgICAgICAgXCJudW1cIjogMSxcbiAgICAgICAgICAgICAgXCJpdGVtXCI6IHRyYWNraW5nX2l0ZW1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICAgIHVwZGF0ZUl0ZW1zVmlldygpO1xuICAgICAgICAgIHNjYW5uZXJfYXVkaW8ucGxheSgpO1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiQWRkZWQgaXRlbSBieSB0YWdcIik7XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0OC5hYnJ1cHQoXCJyZXR1cm5cIiwgdHJ1ZSk7XG4gICAgICAgIGNhc2UgMTg6XG4gICAgICAgICAgaWYgKCEocmVzcG9uc2Uuc3RhdHVzID09IDQwNCkpIHtcbiAgICAgICAgICAgIF9jb250ZXh0OC5uZXh0ID0gMjM7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc29sZS5sb2coXCJJdGVtIG5vdCBmb3VuZFwiKTtcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ4LmFicnVwdChcInJldHVyblwiLCBmYWxzZSk7XG4gICAgICAgIGNhc2UgMjM6XG4gICAgICAgICAgY2hlY2tSZXNwb25zZUZvckVycm9yKHJlc3BvbnNlLCBcIkZhaWxlZCB0byBnZXQgaXRlbSBmcm9tIGJhY2tlbmRcIik7XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0OC5hYnJ1cHQoXCJyZXR1cm5cIiwgZmFsc2UpO1xuICAgICAgICBjYXNlIDI1OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0OC5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTgpO1xuICB9KSk7XG4gIHJldHVybiBfYWRkSXRlbUJ5VGFnLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBoYW5kbGVRckVycm9yKF94MTAsIF94MTEpIHtcbiAgcmV0dXJuIF9oYW5kbGVRckVycm9yLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfaGFuZGxlUXJFcnJvcigpIHtcbiAgX2hhbmRsZVFyRXJyb3IgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWU5KG1zZywgZXJyKSB7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWU5JChfY29udGV4dDkpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0OS5wcmV2ID0gX2NvbnRleHQ5Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDkuYWJydXB0KFwicmV0dXJuXCIpO1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ5LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlOSk7XG4gIH0pKTtcbiAgcmV0dXJuIF9oYW5kbGVRckVycm9yLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBkZWJvdW5jZVNjYW5uZXIoKSB7XG4gIGlmIChzY2FubmVyLmdldFN0YXRlKCkgIT0gSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuU0NBTk5JTkcpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgc2Nhbm5lci5wYXVzZShmYWxzZSk7XG4gIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgIGlmIChzY2FubmVyLmdldFN0YXRlKCkgPT0gSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICBzY2FubmVyLnJlc3VtZSgpO1xuICAgIH1cbiAgfSwgMTAwMCk7XG59XG5mdW5jdGlvbiBoYW5kbGVJdGVtU2NhblJlc3VsdChfeDEyKSB7XG4gIHJldHVybiBfaGFuZGxlSXRlbVNjYW5SZXN1bHQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9oYW5kbGVJdGVtU2NhblJlc3VsdCgpIHtcbiAgX2hhbmRsZUl0ZW1TY2FuUmVzdWx0ID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMTAoaXRlbV91dWlkKSB7XG4gICAgdmFyIHJlc3BvbnNlLCB0cmFja2luZ19pdGVtO1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMTAkKF9jb250ZXh0MTApIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MTAucHJldiA9IF9jb250ZXh0MTAubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgZGVib3VuY2VTY2FubmVyKCk7XG4gICAgICAgICAgaWYgKCEoaXRlbV91dWlkLmxlbmd0aCA9PSAzNikpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTAubmV4dCA9IDI3O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiVHJ5aW5nIHRvIGFkZCBpdGVtIGJ5IHV1aWQgKHNjYW5uZWQpXCIpO1xuICAgICAgICAgIGlmICghKGl0ZW1fdXVpZCBpbiByZWNlaXZlZF9pdGVtcykpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTAubmV4dCA9IDEwO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlY2VpdmVkX2l0ZW1zW2l0ZW1fdXVpZF0ubnVtICs9IDE7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJJbmNyZWFzZWQgY291bnQgb2YgZXhpc3RpbmcgaXRlbSB1dWlkXCIpO1xuICAgICAgICAgIHVwZGF0ZUl0ZW1zVmlldygpO1xuICAgICAgICAgIHNjYW5uZXJfYXVkaW8ucGxheSgpO1xuICAgICAgICAgIF9jb250ZXh0MTAubmV4dCA9IDI1O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDEwOlxuICAgICAgICAgIHJlY2VpdmVkX2l0ZW1zW2l0ZW1fdXVpZF0gPSB7XG4gICAgICAgICAgICBcIm51bVwiOiAxLFxuICAgICAgICAgICAgXCJpdGVtXCI6IG51bGxcbiAgICAgICAgICB9O1xuICAgICAgICAgIF9jb250ZXh0MTAubmV4dCA9IDEzO1xuICAgICAgICAgIHJldHVybiBmZXRjaFdpdGhBdXRoKGNvbmZpZy5iYWNrZW5kX3VybCArIFwiL2l0ZW0vXCIgKyBpdGVtX3V1aWQpO1xuICAgICAgICBjYXNlIDEzOlxuICAgICAgICAgIHJlc3BvbnNlID0gX2NvbnRleHQxMC5zZW50O1xuICAgICAgICAgIGlmICghKHJlc3BvbnNlLnN0YXR1cyA9PSAyMDApKSB7XG4gICAgICAgICAgICBfY29udGV4dDEwLm5leHQgPSAyNDtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dDEwLm5leHQgPSAxNztcbiAgICAgICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuICAgICAgICBjYXNlIDE3OlxuICAgICAgICAgIHRyYWNraW5nX2l0ZW0gPSBfY29udGV4dDEwLnNlbnQ7XG4gICAgICAgICAgcmVjZWl2ZWRfaXRlbXNbaXRlbV91dWlkXSA9IHtcbiAgICAgICAgICAgIFwibnVtXCI6IDEsXG4gICAgICAgICAgICBcIml0ZW1cIjogdHJhY2tpbmdfaXRlbVxuICAgICAgICAgIH07XG4gICAgICAgICAgdXBkYXRlSXRlbXNWaWV3KCk7XG4gICAgICAgICAgc2Nhbm5lcl9hdWRpby5wbGF5KCk7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJBZGRlZCBpdGVtIGJ5IHV1aWQuXCIpO1xuICAgICAgICAgIF9jb250ZXh0MTAubmV4dCA9IDI1O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDI0OlxuICAgICAgICAgIGlmIChyZXNwb25zZS5zdGF0dXMgPT0gNDA0KSB7XG4gICAgICAgICAgICBhbGVydChcIkl0ZW0gbm90IGZvdW5kXCIpO1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCJJdGVtIG5vdCBmb3VuZFwiKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2hlY2tSZXNwb25zZUZvckVycm9yKHJlc3BvbnNlLCBcIkZhaWxlZCB0byBnZXQgaXRlbSBmcm9tIGJhY2tlbmRcIik7XG4gICAgICAgICAgfVxuICAgICAgICBjYXNlIDI1OlxuICAgICAgICAgIF9jb250ZXh0MTAubmV4dCA9IDI4O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDI3OlxuICAgICAgICAgIGFsZXJ0KFwiUVIgQ29kZSBpcyBub3QgYSBiZ3AgY2hlY2tpbiBjb2RlLlwiKTtcbiAgICAgICAgY2FzZSAyODpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDEwLnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMTApO1xuICB9KSk7XG4gIHJldHVybiBfaGFuZGxlSXRlbVNjYW5SZXN1bHQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBhZGRJdGVtU2NhbigpIHtcbiAgcmV0dXJuIF9hZGRJdGVtU2Nhbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2FkZEl0ZW1TY2FuKCkge1xuICBfYWRkSXRlbVNjYW4gPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUxMSgpIHtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTExJChfY29udGV4dDExKSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDExLnByZXYgPSBfY29udGV4dDExLm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiU3RhcnRpbmcgc2Nhbm5lclwiKTtcbiAgICAgICAgICBzY2FubmVyLnJlbmRlcihoYW5kbGVJdGVtU2NhblJlc3VsdCwgaGFuZGxlUXJFcnJvcik7XG4gICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJzdGFydFNjYW5cIikuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwic3RvcFNjYW5cIikuc3R5bGUuZGlzcGxheSA9IFwiaW5saW5lLWJsb2NrXCI7XG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDExLnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMTEpO1xuICB9KSk7XG4gIHJldHVybiBfYWRkSXRlbVNjYW4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBzdG9wU2Nhbm5pbmdJdGVtKCkge1xuICByZXR1cm4gX3N0b3BTY2FubmluZ0l0ZW0uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9zdG9wU2Nhbm5pbmdJdGVtKCkge1xuICBfc3RvcFNjYW5uaW5nSXRlbSA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTEyKCkge1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMTIkKF9jb250ZXh0MTIpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MTIucHJldiA9IF9jb250ZXh0MTIubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgY29uc29sZS5sb2coXCJTdG9wcGluZyBzY2FubmVyXCIpO1xuICAgICAgICAgIHNjYW5uZXIuY2xlYXIoKTtcbiAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInN0YXJ0U2NhblwiKS5zdHlsZS5kaXNwbGF5ID0gXCJpbmxpbmUtYmxvY2tcIjtcbiAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInN0b3BTY2FuXCIpLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTIuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUxMik7XG4gIH0pKTtcbiAgcmV0dXJuIF9zdG9wU2Nhbm5pbmdJdGVtLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5leHBvcnQgZnVuY3Rpb24gYWRkSXRlbUltYWdlKF94MTMpIHtcbiAgcmV0dXJuIF9hZGRJdGVtSW1hZ2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9hZGRJdGVtSW1hZ2UoKSB7XG4gIF9hZGRJdGVtSW1hZ2UgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUxMyhlKSB7XG4gICAgdmFyIGZvcm0sIHJlc3BvbnNlLCB0cmFja2luZ19pdGVtO1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMTMkKF9jb250ZXh0MTMpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MTMucHJldiA9IF9jb250ZXh0MTMubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgY29uc29sZS5sb2coXCJBZGRpbmcgaXRlbSAgYnkgaW1hZ2VcIik7XG4gICAgICAgICAgZm9ybSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgIGZvcm0uYXBwZW5kKFwiaW1hZ2VcIiwgZS5maWxlc1swXSk7XG4gICAgICAgICAgX2NvbnRleHQxMy5uZXh0ID0gNTtcbiAgICAgICAgICByZXR1cm4gZmV0Y2hXaXRoQXV0aChjb25maWcuYmFja2VuZF91cmwgKyBcIi9pdGVtL3JlZ2lzdGVyXCIsIHtcbiAgICAgICAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICAgICAgICBib2R5OiBmb3JtXG4gICAgICAgICAgfSk7XG4gICAgICAgIGNhc2UgNTpcbiAgICAgICAgICByZXNwb25zZSA9IF9jb250ZXh0MTMuc2VudDtcbiAgICAgICAgICBfY29udGV4dDEzLm5leHQgPSA4O1xuICAgICAgICAgIHJldHVybiBjaGVja1Jlc3BvbnNlRm9yRXJyb3IocmVzcG9uc2UsIFwiRmFpbGVkIHRvIHNhdmUgaXRlbVwiKTtcbiAgICAgICAgY2FzZSA4OlxuICAgICAgICAgIGlmICghX2NvbnRleHQxMy5zZW50KSB7XG4gICAgICAgICAgICBfY29udGV4dDEzLm5leHQgPSAxNjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dDEzLm5leHQgPSAxMTtcbiAgICAgICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuICAgICAgICBjYXNlIDExOlxuICAgICAgICAgIHRyYWNraW5nX2l0ZW0gPSBfY29udGV4dDEzLnNlbnQ7XG4gICAgICAgICAgcmVjZWl2ZWRfaXRlbXNbdHJhY2tpbmdfaXRlbS51dWlkXSA9IHtcbiAgICAgICAgICAgIFwibnVtXCI6IDEsXG4gICAgICAgICAgICBcIml0ZW1cIjogdHJhY2tpbmdfaXRlbVxuICAgICAgICAgIH07XG4gICAgICAgICAgdXBkYXRlSXRlbXNWaWV3KCk7XG4gICAgICAgICAgc2Nhbm5lcl9hdWRpby5wbGF5KCk7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJBZGRlZCBpdGVtIGJ5IGltYWdlLlwiKTtcbiAgICAgICAgY2FzZSAxNjpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDEzLnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMTMpO1xuICB9KSk7XG4gIHJldHVybiBfYWRkSXRlbUltYWdlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5leHBvcnQgZnVuY3Rpb24gZGVjcmVhc2VJdGVtQ291bnQoX3gxNCkge1xuICByZXR1cm4gX2RlY3JlYXNlSXRlbUNvdW50LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfZGVjcmVhc2VJdGVtQ291bnQoKSB7XG4gIF9kZWNyZWFzZUl0ZW1Db3VudCA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTE0KHV1aWQpIHtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTE0JChfY29udGV4dDE0KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDE0LnByZXYgPSBfY29udGV4dDE0Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGlmICghKHJlY2VpdmVkX2l0ZW1zW3V1aWRdID09IG51bGwpKSB7XG4gICAgICAgICAgICBfY29udGV4dDE0Lm5leHQgPSAzO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiVHJ5aW5nIHRvIGRlY3JlYXNlIGl0ZW0gY291bnQgb2YgdW5rbm93biBpdGVtXCIsIHV1aWQpO1xuICAgICAgICAgIHJldHVybiBfY29udGV4dDE0LmFicnVwdChcInJldHVyblwiKTtcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiRGVjcmVhc2luZyBpdGVtIGNvdW50IG9mXCIsIHV1aWQpO1xuICAgICAgICAgIHJlY2VpdmVkX2l0ZW1zW3V1aWRdW1wibnVtXCJdLS07XG4gICAgICAgICAgaWYgKHJlY2VpdmVkX2l0ZW1zW3V1aWRdW1wibnVtXCJdIDw9IDApIHtcbiAgICAgICAgICAgIGRlbGV0ZSByZWNlaXZlZF9pdGVtc1t1dWlkXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdXBkYXRlSXRlbXNWaWV3KCk7XG4gICAgICAgIGNhc2UgNzpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDE0LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMTQpO1xuICB9KSk7XG4gIHJldHVybiBfZGVjcmVhc2VJdGVtQ291bnQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBpbmNyZWFzZUl0ZW1Db3VudChfeDE1KSB7XG4gIHJldHVybiBfaW5jcmVhc2VJdGVtQ291bnQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cblxuLypcbiAqIENoZWNraW4gdGhlIHNlbGVjdGVkIGl0ZW1zXG4gKi9cbmZ1bmN0aW9uIF9pbmNyZWFzZUl0ZW1Db3VudCgpIHtcbiAgX2luY3JlYXNlSXRlbUNvdW50ID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMTUodXVpZCkge1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMTUkKF9jb250ZXh0MTUpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MTUucHJldiA9IF9jb250ZXh0MTUubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgaWYgKCEocmVjZWl2ZWRfaXRlbXNbdXVpZF0gPT0gbnVsbCkpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTUubmV4dCA9IDM7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc29sZS5sb2coXCJUcnlpbmcgdG8gaW5jcmVhc2UgaXRlbSBjb3VudCBvZiB1bmtub3duIGl0ZW1cIiwgdXVpZCk7XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTUuYWJydXB0KFwicmV0dXJuXCIpO1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgY29uc29sZS5sb2coXCJJbmNyZWFzaW5nIGl0ZW0gY291bnQgb2ZcIiwgdXVpZCk7XG4gICAgICAgICAgcmVjZWl2ZWRfaXRlbXNbdXVpZF1bXCJudW1cIl0rKztcbiAgICAgICAgICB1cGRhdGVJdGVtc1ZpZXcoKTtcbiAgICAgICAgY2FzZSA2OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTUuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUxNSk7XG4gIH0pKTtcbiAgcmV0dXJuIF9pbmNyZWFzZUl0ZW1Db3VudC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGNoZWNraW5JdGVtcygpIHtcbiAgcmV0dXJuIF9jaGVja2luSXRlbXMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9jaGVja2luSXRlbXMoKSB7XG4gIF9jaGVja2luSXRlbXMgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUxNigpIHtcbiAgICB2YXIgc3VjY2Vzc2Z1bGxDb3VudCwgaXRlbSwgcmVzcG9uc2UsIHRyYWNraW5nX2l0ZW07XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUxNiQoX2NvbnRleHQxNikge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQxNi5wcmV2ID0gX2NvbnRleHQxNi5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkNoZWNraW5nIGluIGl0ZW1zXCIpO1xuICAgICAgICAgIHN1Y2Nlc3NmdWxsQ291bnQgPSAwO1xuICAgICAgICAgIF9jb250ZXh0MTYudDAgPSBfcmVnZW5lcmF0b3JSdW50aW1lKCkua2V5cyhyZWNlaXZlZF9pdGVtcyk7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICBpZiAoKF9jb250ZXh0MTYudDEgPSBfY29udGV4dDE2LnQwKCkpLmRvbmUpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTYubmV4dCA9IDE4O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGl0ZW0gPSBfY29udGV4dDE2LnQxLnZhbHVlO1xuICAgICAgICAgIF9jb250ZXh0MTYubmV4dCA9IDc7XG4gICAgICAgICAgcmV0dXJuIGZldGNoV2l0aEF1dGgoY29uZmlnLmJhY2tlbmRfdXJsICsgXCIvY2hlY2tpblwiLCB7XG4gICAgICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgXCJpdGVtX3V1aWRcIjogcmVjZWl2ZWRfaXRlbXNbaXRlbV0uaXRlbS51dWlkLFxuICAgICAgICAgICAgICBcInN0b3JhZ2VfbmFtZVwiOiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3N0b3JhZ2Vfc2VsZWN0XCIpLnZhbHVlLFxuICAgICAgICAgICAgICBcImFtb3VudFwiOiByZWNlaXZlZF9pdGVtc1tpdGVtXS5udW1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgfSk7XG4gICAgICAgIGNhc2UgNzpcbiAgICAgICAgICByZXNwb25zZSA9IF9jb250ZXh0MTYuc2VudDtcbiAgICAgICAgICBfY29udGV4dDE2Lm5leHQgPSAxMDtcbiAgICAgICAgICByZXR1cm4gY2hlY2tSZXNwb25zZUZvckVycm9yKHJlc3BvbnNlLCBcIkZhaWxlZCB0byBjaGVja2luIGl0ZW0gXCIgKyByZWNlaXZlZF9pdGVtc1tpdGVtXS5pdGVtLnRhZyk7XG4gICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgaWYgKCFfY29udGV4dDE2LnNlbnQpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTYubmV4dCA9IDE2O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0MTYubmV4dCA9IDEzO1xuICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgIGNhc2UgMTM6XG4gICAgICAgICAgdHJhY2tpbmdfaXRlbSA9IF9jb250ZXh0MTYuc2VudDtcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gICAgICAgICAgZGVsZXRlIHJlY2VpdmVkX2l0ZW1zW3RyYWNraW5nX2l0ZW0udXVpZF07XG4gICAgICAgICAgc3VjY2Vzc2Z1bGxDb3VudCsrO1xuICAgICAgICBjYXNlIDE2OlxuICAgICAgICAgIF9jb250ZXh0MTYubmV4dCA9IDM7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMTg6XG4gICAgICAgICAgdG9hc3QoXCJDaGVjay1JbiBzdWNjZXNzZnVsbC5cIiwgXCJUaGUgY2hlY2staW4gb2YgXCIgKyBzdWNjZXNzZnVsbENvdW50ICsgXCIgaXRlbXMgY29tcGxldGVkIHN1Y2Nlc2Z1bGx5LlwiKTtcbiAgICAgICAgICB1cGRhdGVJdGVtc1ZpZXcoKTtcbiAgICAgICAgY2FzZSAyMDpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDE2LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMTYpO1xuICB9KSk7XG4gIHJldHVybiBfY2hlY2tpbkl0ZW1zLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiB1cGRhdGVDaGVja291dEl0ZW0odHJhY2tpbmdfaXRlbSkge1xuICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3V1aWRcIikuaW5uZXJIVE1MID0gdHJhY2tpbmdfaXRlbS51dWlkO1xuICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3RhZ1wiKS5pbm5lckhUTUwgPSB0cmFja2luZ19pdGVtLnRhZztcbiAgZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNzdG9yYWdlXCIpLmlubmVySFRNTCA9IHRyYWNraW5nX2l0ZW0uc3RvcmFnZTtcbiAgZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNhZGRyZXNzZWVcIikuaW5uZXJIVE1MID0gdHJhY2tpbmdfaXRlbS5hZGRyZXNzZWU7XG4gIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjdGVhbVwiKS5pbm5lckhUTUwgPSB0cmFja2luZ19pdGVtLnRlYW07XG59XG5leHBvcnQgZnVuY3Rpb24gY2hlY2tvdXRJdGVtKCkge1xuICByZXR1cm4gX2NoZWNrb3V0SXRlbS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2NoZWNrb3V0SXRlbSgpIHtcbiAgX2NoZWNrb3V0SXRlbSA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTE3KCkge1xuICAgIHZhciBjb25maXJtZWQsIHJlc3BvbnNlO1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMTckKF9jb250ZXh0MTcpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MTcucHJldiA9IF9jb250ZXh0MTcubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgY29uZmlybWVkID0gY29uZmlybShcIkRpZCB5b3UgbWFrZSBzdXJlIHRoZSByZWNpcGllbnQgaXMgcmVhbGx5IHRoZSByaWdodCBwZXJzb24/XCIpO1xuICAgICAgICAgIGlmIChjb25maXJtZWQpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTcubmV4dCA9IDQ7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc29sZS5sb2coXCJSZWNpcGllbnQgY29uZmlybWF0aW9uIGRlbmllZC5cIik7XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTcuYWJydXB0KFwicmV0dXJuXCIpO1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgX2NvbnRleHQxNy5uZXh0ID0gNjtcbiAgICAgICAgICByZXR1cm4gZmV0Y2hXaXRoQXV0aChjb25maWcuYmFja2VuZF91cmwgKyBcIi9jaGVja291dC9cIiArIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjdXVpZFwiKS5pbm5lckhUTUwpO1xuICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgcmVzcG9uc2UgPSBfY29udGV4dDE3LnNlbnQ7XG4gICAgICAgIGNhc2UgNzpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDE3LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMTcpO1xuICB9KSk7XG4gIHJldHVybiBfY2hlY2tvdXRJdGVtLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBvblJlY2V2aWVyU2NhblN1Y2Nlc3MoX3gxNikge1xuICByZXR1cm4gX29uUmVjZXZpZXJTY2FuU3VjY2Vzcy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX29uUmVjZXZpZXJTY2FuU3VjY2VzcygpIHtcbiAgX29uUmVjZXZpZXJTY2FuU3VjY2VzcyA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTE4KHNjYW5uZWRDb2RlKSB7XG4gICAgdmFyIF9zY2FubmVkQ29kZSRzcGxpdCwgX3NjYW5uZWRDb2RlJHNwbGl0MiwgdXVpZCwgc2lnbmF0dXJlLCByZXNwb25zZSwgdHJhY2tpbmdfaXRlbTtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTE4JChfY29udGV4dDE4KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDE4LnByZXYgPSBfY29udGV4dDE4Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGRlYm91bmNlU2Nhbm5lcigpO1xuICAgICAgICAgIF9zY2FubmVkQ29kZSRzcGxpdCA9IHNjYW5uZWRDb2RlLnNwbGl0KFwiL1wiKSwgX3NjYW5uZWRDb2RlJHNwbGl0MiA9IF9zbGljZWRUb0FycmF5KF9zY2FubmVkQ29kZSRzcGxpdCwgMiksIHV1aWQgPSBfc2Nhbm5lZENvZGUkc3BsaXQyWzBdLCBzaWduYXR1cmUgPSBfc2Nhbm5lZENvZGUkc3BsaXQyWzFdO1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiUmVjZWl2ZXIgc2NhbiBzdWNjZXNzXCIpO1xuICAgICAgICAgIHNjYW5uZXJfYXVkaW8ucGxheSgpO1xuICAgICAgICAgIF9jb250ZXh0MTgubmV4dCA9IDY7XG4gICAgICAgICAgcmV0dXJuIGdldENvbmZpZygpO1xuICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgX2NvbnRleHQxOC5uZXh0ID0gODtcbiAgICAgICAgICByZXR1cm4gZmV0Y2goY29uZmlnLmJhY2tlbmRfdXJsICsgXCIvaXRlbS9cIiArIHV1aWQsIHtcbiAgICAgICAgICAgIGhlYWRlcnM6IHt9XG4gICAgICAgICAgfSk7XG4gICAgICAgIGNhc2UgODpcbiAgICAgICAgICByZXNwb25zZSA9IF9jb250ZXh0MTguc2VudDtcbiAgICAgICAgICBpZiAoIShyZXNwb25zZS5zdGF0dXMgPT0gMjAwKSkge1xuICAgICAgICAgICAgX2NvbnRleHQxOC5uZXh0ID0gMjY7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgX2NvbnRleHQxOC5uZXh0ID0gMTI7XG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgY2FzZSAxMjpcbiAgICAgICAgICB0cmFja2luZ19pdGVtID0gX2NvbnRleHQxOC5zZW50O1xuICAgICAgICAgIGlmICghZWQ0NDgudmVyaWZ5KGh0b2Eoc2lnbmF0dXJlKSwgbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHRyYWNraW5nX2l0ZW0udXVpZCksIGh0b2EodHJhY2tpbmdfaXRlbS52ZXJpZmljYXRpb24pKSkge1xuICAgICAgICAgICAgX2NvbnRleHQxOC5uZXh0ID0gMjI7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCEodHJhY2tpbmdfaXRlbS5zdG9yYWdlID09IHVuZGVmaW5lZCB8fCB0cmFja2luZ19pdGVtLnN0b3JhZ2UgPT0gbnVsbCB8fCB0cmFja2luZ19pdGVtLnN0b3JhZ2UubGVuZ3RoID09IDApKSB7XG4gICAgICAgICAgICBfY29udGV4dDE4Lm5leHQgPSAxODtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBhbGVydChcIkl0ZW0gbm90IHlldCByZWNlaXZlZC5cIik7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJJdGVtIG5vdCB5ZXQgcmVjZWl2ZWQuXCIpO1xuICAgICAgICAgIHJldHVybiBfY29udGV4dDE4LmFicnVwdChcInJldHVyblwiKTtcbiAgICAgICAgY2FzZSAxODpcbiAgICAgICAgICB1cGRhdGVDaGVja291dEl0ZW0odHJhY2tpbmdfaXRlbSk7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJSZWNlaXZlciB2ZXJpZnkgc3VjY2Vzc1wiKTtcbiAgICAgICAgICBfY29udGV4dDE4Lm5leHQgPSAyNDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAyMjpcbiAgICAgICAgICBhbGVydChcIkNvdWxkIG5vdCB2ZXJpZnkgc2lnbmF0dXJlLlwiKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkNvdWxkIG5vdCB2ZXJpZnkgc2lnbmF0dXJlLlwiKTtcbiAgICAgICAgY2FzZSAyNDpcbiAgICAgICAgICBfY29udGV4dDE4Lm5leHQgPSAyNztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAyNjpcbiAgICAgICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09IDQwNCkge1xuICAgICAgICAgICAgYWxlcnQoXCJJdGVtIG5vdCBmb3VuZC5cIik7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNoZWNrUmVzcG9uc2VGb3JFcnJvcihyZXNwb25zZSwgXCJGYWlsZWQgdG8gZ2V0IGl0ZW0gZnJvbSBiYWNrZW5kLlwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIGNhc2UgMjc6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQxOC5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTE4KTtcbiAgfSkpO1xuICByZXR1cm4gX29uUmVjZXZpZXJTY2FuU3VjY2Vzcy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHNjYW5SZWNlaXZlcigpIHtcbiAgcmV0dXJuIF9zY2FuUmVjZWl2ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9zY2FuUmVjZWl2ZXIoKSB7XG4gIF9zY2FuUmVjZWl2ZXIgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUxOSgpIHtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTE5JChfY29udGV4dDE5KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDE5LnByZXYgPSBfY29udGV4dDE5Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiU2Nhbm5pbmcgcmVjZWl2ZXIuXCIpO1xuICAgICAgICAgIHNjYW5uZXIucmVuZGVyKG9uUmVjZXZpZXJTY2FuU3VjY2VzcywgaGFuZGxlUXJFcnJvcik7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDE5LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMTkpO1xuICB9KSk7XG4gIHJldHVybiBfc2NhblJlY2VpdmVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5leHBvcnQgZnVuY3Rpb24gbG9hZFN0b3JhZ2VzKF94MTcpIHtcbiAgcmV0dXJuIF9sb2FkU3RvcmFnZXMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9sb2FkU3RvcmFnZXMoKSB7XG4gIF9sb2FkU3RvcmFnZXMgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUyMChzZWxlY3RlZFN0b3JhZ2UpIHtcbiAgICB2YXIgcmVzcG9uc2UsIHN0b3JhZ2VzLCBzZWxlY3QsIGksIG9wdGlvbjtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTIwJChfY29udGV4dDIwKSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDIwLnByZXYgPSBfY29udGV4dDIwLm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiUmV0cmlldmluZyBzdG9yYWdlc1wiKTtcbiAgICAgICAgICBfY29udGV4dDIwLm5leHQgPSAzO1xuICAgICAgICAgIHJldHVybiBmZXRjaFdpdGhBdXRoKGNvbmZpZy5iYWNrZW5kX3VybCArIFwiL3N0b3JhZ2VzXCIpO1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgcmVzcG9uc2UgPSBfY29udGV4dDIwLnNlbnQ7XG4gICAgICAgICAgX2NvbnRleHQyMC5uZXh0ID0gNjtcbiAgICAgICAgICByZXR1cm4gY2hlY2tSZXNwb25zZUZvckVycm9yKHJlc3BvbnNlLCBcIkZhaWxlZCB0byBsb2FkIHN0b3JhZ2VzLlwiKTtcbiAgICAgICAgY2FzZSA2OlxuICAgICAgICAgIGlmICghX2NvbnRleHQyMC5zZW50KSB7XG4gICAgICAgICAgICBfY29udGV4dDIwLm5leHQgPSAxMztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dDIwLm5leHQgPSA5O1xuICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgIGNhc2UgOTpcbiAgICAgICAgICBzdG9yYWdlcyA9IF9jb250ZXh0MjAuc2VudDtcbiAgICAgICAgICBzZWxlY3QgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3N0b3JhZ2Vfc2VsZWN0XCIpO1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiR290IHN0b3JhZ2VzXCIpO1xuICAgICAgICAgIGZvciAoaSBpbiBzdG9yYWdlcykge1xuICAgICAgICAgICAgb3B0aW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcIm9wdGlvblwiKTtcbiAgICAgICAgICAgIG9wdGlvbi50ZXh0Q29udGVudCA9IHN0b3JhZ2VzW2ldLm5hbWU7XG4gICAgICAgICAgICBvcHRpb24udmFsdWUgPSBzdG9yYWdlc1tpXS5uYW1lO1xuICAgICAgICAgICAgc2VsZWN0LmFwcGVuZENoaWxkKG9wdGlvbik7XG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWRTdG9yYWdlID09IHN0b3JhZ2VzW2ldLm5hbWUpIHtcbiAgICAgICAgICAgICAgc2VsZWN0LnZhbHVlID0gc2VsZWN0ZWRTdG9yYWdlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgY2FzZSAxMzpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDIwLnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMjApO1xuICB9KSk7XG4gIHJldHVybiBfbG9hZFN0b3JhZ2VzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5leHBvcnQgZnVuY3Rpb24gb25QYWdlTG9hZChfeDE4KSB7XG4gIHJldHVybiBfb25QYWdlTG9hZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX29uUGFnZUxvYWQoKSB7XG4gIF9vblBhZ2VMb2FkID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMjEoZG9sb2FkU3RvcmFnZXMpIHtcbiAgICB2YXIgcHc7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUyMSQoX2NvbnRleHQyMSkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQyMS5wcmV2ID0gX2NvbnRleHQyMS5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBfY29udGV4dDIxLm5leHQgPSAyO1xuICAgICAgICAgIHJldHVybiBnZXRDb25maWcoKTtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHB3ID0gd2luZG93LmxvY2F0aW9uLmhhc2guc3Vic3RyaW5nKDEpO1xuICAgICAgICAgIGlmICghKHB3Lmxlbmd0aCA+IDEpKSB7XG4gICAgICAgICAgICBfY29udGV4dDIxLm5leHQgPSA4O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0MjEubmV4dCA9IDY7XG4gICAgICAgICAgcmV0dXJuIGxvZ2luKHB3KTtcbiAgICAgICAgY2FzZSA2OlxuICAgICAgICAgIF9jb250ZXh0MjEubmV4dCA9IDEwO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDg6XG4gICAgICAgICAgX2NvbnRleHQyMS5uZXh0ID0gMTA7XG4gICAgICAgICAgcmV0dXJuIGxvZ2luKCk7XG4gICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgaWYgKGRvbG9hZFN0b3JhZ2VzKSB7XG4gICAgICAgICAgICBsb2FkU3RvcmFnZXMoZG9jdW1lbnQubG9jYXRpb24uc2VhcmNoLnN1YnN0cmluZygxKSk7XG4gICAgICAgICAgfVxuICAgICAgICBjYXNlIDExOlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MjEuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUyMSk7XG4gIH0pKTtcbiAgcmV0dXJuIF9vblBhZ2VMb2FkLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5leHBvcnQgZnVuY3Rpb24gY2hlY2tvdXRCeVRhZygpIHtcbiAgcmV0dXJuIF9jaGVja291dEJ5VGFnLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfY2hlY2tvdXRCeVRhZygpIHtcbiAgX2NoZWNrb3V0QnlUYWcgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUyMigpIHtcbiAgICB2YXIgZWwsIHJlc3BvbnNlLCB0cmFja2luZ19pdGVtO1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMjIkKF9jb250ZXh0MjIpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MjIucHJldiA9IF9jb250ZXh0MjIubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgY29uc29sZS5sb2coXCJDaGVja291dCBieSB0YWdcIik7XG4gICAgICAgICAgZWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcImNoZWNrb3V0QnlUYWdcIik7XG4gICAgICAgICAgaWYgKCEoZWwudmFsdWUubGVuZ3RoICE9IDYpKSB7XG4gICAgICAgICAgICBfY29udGV4dDIyLm5leHQgPSA2O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGFsZXJ0KFwiTm90IGEgQkdQIHRhZyFcIik7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJOb3QgYSBCR1AgdGFnXCIpO1xuICAgICAgICAgIHJldHVybiBfY29udGV4dDIyLmFicnVwdChcInJldHVyblwiKTtcbiAgICAgICAgY2FzZSA2OlxuICAgICAgICAgIF9jb250ZXh0MjIubmV4dCA9IDg7XG4gICAgICAgICAgcmV0dXJuIGZldGNoV2l0aEF1dGgoY29uZmlnLmJhY2tlbmRfdXJsICsgXCIvdGFnL1wiICsgZWwudmFsdWUpO1xuICAgICAgICBjYXNlIDg6XG4gICAgICAgICAgcmVzcG9uc2UgPSBfY29udGV4dDIyLnNlbnQ7XG4gICAgICAgICAgaWYgKCEocmVzcG9uc2Uuc3RhdHVzID09IDIwMCkpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MjIubmV4dCA9IDIxO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0MjIubmV4dCA9IDEyO1xuICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgIGNhc2UgMTI6XG4gICAgICAgICAgdHJhY2tpbmdfaXRlbSA9IF9jb250ZXh0MjIuc2VudDtcbiAgICAgICAgICBpZiAoISh0cmFja2luZ19pdGVtLnN0b3JhZ2UgPT0gdW5kZWZpbmVkIHx8IHRyYWNraW5nX2l0ZW0uc3RvcmFnZSA9PSBudWxsIHx8IHRyYWNraW5nX2l0ZW0uc3RvcmFnZS5sZW5ndGggPT0gMCkpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MjIubmV4dCA9IDE3O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGFsZXJ0KFwiSXRlbSBub3QgeWV0IHJlY2VpdmVkLlwiKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkl0ZW0gbm90IHlldCByZWNlaXZlZC5cIik7XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MjIuYWJydXB0KFwicmV0dXJuXCIpO1xuICAgICAgICBjYXNlIDE3OlxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiQ2hlY2tvdXQgaXRlbSBieSB0YWcgc3VjY2Vzcy5cIik7XG4gICAgICAgICAgdXBkYXRlQ2hlY2tvdXRJdGVtKHRyYWNraW5nX2l0ZW0pO1xuICAgICAgICAgIF9jb250ZXh0MjIubmV4dCA9IDIyO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDIxOlxuICAgICAgICAgIGlmIChyZXNwb25zZS5zdGF0dXMgPT0gNDA0KSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkl0ZW0gbm90IGZvdW5kXCIpO1xuICAgICAgICAgICAgYWxlcnQoXCJJdGVtIG5vdCBmb3VuZCFcIik7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNoZWNrUmVzcG9uc2VGb3JFcnJvcihyZXNwb25zZSwgXCJGYWlsZWQgdG8gZ2V0IGl0ZW0gZnJvbSBiYWNrZW5kXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgY2FzZSAyMjpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDIyLnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMjIpO1xuICB9KSk7XG4gIHJldHVybiBfY2hlY2tvdXRCeVRhZy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufSJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/js/main.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/base64-js/index.js":
+/*!*****************************************!*\
+  !*** ./node_modules/base64-js/index.js ***!
+  \*****************************************/
+/***/ ((__unused_webpack_module, exports) => {
+
+"use strict";
+eval("\n\nexports.byteLength = byteLength\nexports.toByteArray = toByteArray\nexports.fromByteArray = fromByteArray\n\nvar lookup = []\nvar revLookup = []\nvar Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array\n\nvar code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nfor (var i = 0, len = code.length; i < len; ++i) {\n  lookup[i] = code[i]\n  revLookup[code.charCodeAt(i)] = i\n}\n\n// Support decoding URL-safe base64 strings, as Node.js does.\n// See: https://en.wikipedia.org/wiki/Base64#URL_applications\nrevLookup['-'.charCodeAt(0)] = 62\nrevLookup['_'.charCodeAt(0)] = 63\n\nfunction getLens (b64) {\n  var len = b64.length\n\n  if (len % 4 > 0) {\n    throw new Error('Invalid string. Length must be a multiple of 4')\n  }\n\n  // Trim off extra bytes after placeholder bytes are found\n  // See: https://github.com/beatgammit/base64-js/issues/42\n  var validLen = b64.indexOf('=')\n  if (validLen === -1) validLen = len\n\n  var placeHoldersLen = validLen === len\n    ? 0\n    : 4 - (validLen % 4)\n\n  return [validLen, placeHoldersLen]\n}\n\n// base64 is 4/3 + up to two characters of the original data\nfunction byteLength (b64) {\n  var lens = getLens(b64)\n  var validLen = lens[0]\n  var placeHoldersLen = lens[1]\n  return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction _byteLength (b64, validLen, placeHoldersLen) {\n  return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction toByteArray (b64) {\n  var tmp\n  var lens = getLens(b64)\n  var validLen = lens[0]\n  var placeHoldersLen = lens[1]\n\n  var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))\n\n  var curByte = 0\n\n  // if there are placeholders, only get up to the last complete 4 chars\n  var len = placeHoldersLen > 0\n    ? validLen - 4\n    : validLen\n\n  var i\n  for (i = 0; i < len; i += 4) {\n    tmp =\n      (revLookup[b64.charCodeAt(i)] << 18) |\n      (revLookup[b64.charCodeAt(i + 1)] << 12) |\n      (revLookup[b64.charCodeAt(i + 2)] << 6) |\n      revLookup[b64.charCodeAt(i + 3)]\n    arr[curByte++] = (tmp >> 16) & 0xFF\n    arr[curByte++] = (tmp >> 8) & 0xFF\n    arr[curByte++] = tmp & 0xFF\n  }\n\n  if (placeHoldersLen === 2) {\n    tmp =\n      (revLookup[b64.charCodeAt(i)] << 2) |\n      (revLookup[b64.charCodeAt(i + 1)] >> 4)\n    arr[curByte++] = tmp & 0xFF\n  }\n\n  if (placeHoldersLen === 1) {\n    tmp =\n      (revLookup[b64.charCodeAt(i)] << 10) |\n      (revLookup[b64.charCodeAt(i + 1)] << 4) |\n      (revLookup[b64.charCodeAt(i + 2)] >> 2)\n    arr[curByte++] = (tmp >> 8) & 0xFF\n    arr[curByte++] = tmp & 0xFF\n  }\n\n  return arr\n}\n\nfunction tripletToBase64 (num) {\n  return lookup[num >> 18 & 0x3F] +\n    lookup[num >> 12 & 0x3F] +\n    lookup[num >> 6 & 0x3F] +\n    lookup[num & 0x3F]\n}\n\nfunction encodeChunk (uint8, start, end) {\n  var tmp\n  var output = []\n  for (var i = start; i < end; i += 3) {\n    tmp =\n      ((uint8[i] << 16) & 0xFF0000) +\n      ((uint8[i + 1] << 8) & 0xFF00) +\n      (uint8[i + 2] & 0xFF)\n    output.push(tripletToBase64(tmp))\n  }\n  return output.join('')\n}\n\nfunction fromByteArray (uint8) {\n  var tmp\n  var len = uint8.length\n  var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes\n  var parts = []\n  var maxChunkLength = 16383 // must be multiple of 3\n\n  // go through the array every three bytes, we'll deal with trailing stuff later\n  for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {\n    parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))\n  }\n\n  // pad the end with zeros, but make sure to not forget the extra bytes\n  if (extraBytes === 1) {\n    tmp = uint8[len - 1]\n    parts.push(\n      lookup[tmp >> 2] +\n      lookup[(tmp << 4) & 0x3F] +\n      '=='\n    )\n  } else if (extraBytes === 2) {\n    tmp = (uint8[len - 2] << 8) + uint8[len - 1]\n    parts.push(\n      lookup[tmp >> 10] +\n      lookup[(tmp >> 4) & 0x3F] +\n      lookup[(tmp << 2) & 0x3F] +\n      '='\n    )\n  }\n\n  return parts.join('')\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYmFzZTY0LWpzL2luZGV4LmpzLmpzIiwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9iYXNlNjQtanMvaW5kZXguanM/MWZiNSJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCdcblxuZXhwb3J0cy5ieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aFxuZXhwb3J0cy50b0J5dGVBcnJheSA9IHRvQnl0ZUFycmF5XG5leHBvcnRzLmZyb21CeXRlQXJyYXkgPSBmcm9tQnl0ZUFycmF5XG5cbnZhciBsb29rdXAgPSBbXVxudmFyIHJldkxvb2t1cCA9IFtdXG52YXIgQXJyID0gdHlwZW9mIFVpbnQ4QXJyYXkgIT09ICd1bmRlZmluZWQnID8gVWludDhBcnJheSA6IEFycmF5XG5cbnZhciBjb2RlID0gJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8nXG5mb3IgKHZhciBpID0gMCwgbGVuID0gY29kZS5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xuICBsb29rdXBbaV0gPSBjb2RlW2ldXG4gIHJldkxvb2t1cFtjb2RlLmNoYXJDb2RlQXQoaSldID0gaVxufVxuXG4vLyBTdXBwb3J0IGRlY29kaW5nIFVSTC1zYWZlIGJhc2U2NCBzdHJpbmdzLCBhcyBOb2RlLmpzIGRvZXMuXG4vLyBTZWU6IGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Jhc2U2NCNVUkxfYXBwbGljYXRpb25zXG5yZXZMb29rdXBbJy0nLmNoYXJDb2RlQXQoMCldID0gNjJcbnJldkxvb2t1cFsnXycuY2hhckNvZGVBdCgwKV0gPSA2M1xuXG5mdW5jdGlvbiBnZXRMZW5zIChiNjQpIHtcbiAgdmFyIGxlbiA9IGI2NC5sZW5ndGhcblxuICBpZiAobGVuICUgNCA+IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc3RyaW5nLiBMZW5ndGggbXVzdCBiZSBhIG11bHRpcGxlIG9mIDQnKVxuICB9XG5cbiAgLy8gVHJpbSBvZmYgZXh0cmEgYnl0ZXMgYWZ0ZXIgcGxhY2Vob2xkZXIgYnl0ZXMgYXJlIGZvdW5kXG4gIC8vIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL2JlYXRnYW1taXQvYmFzZTY0LWpzL2lzc3Vlcy80MlxuICB2YXIgdmFsaWRMZW4gPSBiNjQuaW5kZXhPZignPScpXG4gIGlmICh2YWxpZExlbiA9PT0gLTEpIHZhbGlkTGVuID0gbGVuXG5cbiAgdmFyIHBsYWNlSG9sZGVyc0xlbiA9IHZhbGlkTGVuID09PSBsZW5cbiAgICA/IDBcbiAgICA6IDQgLSAodmFsaWRMZW4gJSA0KVxuXG4gIHJldHVybiBbdmFsaWRMZW4sIHBsYWNlSG9sZGVyc0xlbl1cbn1cblxuLy8gYmFzZTY0IGlzIDQvMyArIHVwIHRvIHR3byBjaGFyYWN0ZXJzIG9mIHRoZSBvcmlnaW5hbCBkYXRhXG5mdW5jdGlvbiBieXRlTGVuZ3RoIChiNjQpIHtcbiAgdmFyIGxlbnMgPSBnZXRMZW5zKGI2NClcbiAgdmFyIHZhbGlkTGVuID0gbGVuc1swXVxuICB2YXIgcGxhY2VIb2xkZXJzTGVuID0gbGVuc1sxXVxuICByZXR1cm4gKCh2YWxpZExlbiArIHBsYWNlSG9sZGVyc0xlbikgKiAzIC8gNCkgLSBwbGFjZUhvbGRlcnNMZW5cbn1cblxuZnVuY3Rpb24gX2J5dGVMZW5ndGggKGI2NCwgdmFsaWRMZW4sIHBsYWNlSG9sZGVyc0xlbikge1xuICByZXR1cm4gKCh2YWxpZExlbiArIHBsYWNlSG9sZGVyc0xlbikgKiAzIC8gNCkgLSBwbGFjZUhvbGRlcnNMZW5cbn1cblxuZnVuY3Rpb24gdG9CeXRlQXJyYXkgKGI2NCkge1xuICB2YXIgdG1wXG4gIHZhciBsZW5zID0gZ2V0TGVucyhiNjQpXG4gIHZhciB2YWxpZExlbiA9IGxlbnNbMF1cbiAgdmFyIHBsYWNlSG9sZGVyc0xlbiA9IGxlbnNbMV1cblxuICB2YXIgYXJyID0gbmV3IEFycihfYnl0ZUxlbmd0aChiNjQsIHZhbGlkTGVuLCBwbGFjZUhvbGRlcnNMZW4pKVxuXG4gIHZhciBjdXJCeXRlID0gMFxuXG4gIC8vIGlmIHRoZXJlIGFyZSBwbGFjZWhvbGRlcnMsIG9ubHkgZ2V0IHVwIHRvIHRoZSBsYXN0IGNvbXBsZXRlIDQgY2hhcnNcbiAgdmFyIGxlbiA9IHBsYWNlSG9sZGVyc0xlbiA+IDBcbiAgICA/IHZhbGlkTGVuIC0gNFxuICAgIDogdmFsaWRMZW5cblxuICB2YXIgaVxuICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpICs9IDQpIHtcbiAgICB0bXAgPVxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpKV0gPDwgMTgpIHxcbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDEpXSA8PCAxMikgfFxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMildIDw8IDYpIHxcbiAgICAgIHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMyldXG4gICAgYXJyW2N1ckJ5dGUrK10gPSAodG1wID4+IDE2KSAmIDB4RkZcbiAgICBhcnJbY3VyQnl0ZSsrXSA9ICh0bXAgPj4gOCkgJiAweEZGXG4gICAgYXJyW2N1ckJ5dGUrK10gPSB0bXAgJiAweEZGXG4gIH1cblxuICBpZiAocGxhY2VIb2xkZXJzTGVuID09PSAyKSB7XG4gICAgdG1wID1cbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSldIDw8IDIpIHxcbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDEpXSA+PiA0KVxuICAgIGFycltjdXJCeXRlKytdID0gdG1wICYgMHhGRlxuICB9XG5cbiAgaWYgKHBsYWNlSG9sZGVyc0xlbiA9PT0gMSkge1xuICAgIHRtcCA9XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkpXSA8PCAxMCkgfFxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMSldIDw8IDQpIHxcbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDIpXSA+PiAyKVxuICAgIGFycltjdXJCeXRlKytdID0gKHRtcCA+PiA4KSAmIDB4RkZcbiAgICBhcnJbY3VyQnl0ZSsrXSA9IHRtcCAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBhcnJcbn1cblxuZnVuY3Rpb24gdHJpcGxldFRvQmFzZTY0IChudW0pIHtcbiAgcmV0dXJuIGxvb2t1cFtudW0gPj4gMTggJiAweDNGXSArXG4gICAgbG9va3VwW251bSA+PiAxMiAmIDB4M0ZdICtcbiAgICBsb29rdXBbbnVtID4+IDYgJiAweDNGXSArXG4gICAgbG9va3VwW251bSAmIDB4M0ZdXG59XG5cbmZ1bmN0aW9uIGVuY29kZUNodW5rICh1aW50OCwgc3RhcnQsIGVuZCkge1xuICB2YXIgdG1wXG4gIHZhciBvdXRwdXQgPSBbXVxuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkgKz0gMykge1xuICAgIHRtcCA9XG4gICAgICAoKHVpbnQ4W2ldIDw8IDE2KSAmIDB4RkYwMDAwKSArXG4gICAgICAoKHVpbnQ4W2kgKyAxXSA8PCA4KSAmIDB4RkYwMCkgK1xuICAgICAgKHVpbnQ4W2kgKyAyXSAmIDB4RkYpXG4gICAgb3V0cHV0LnB1c2godHJpcGxldFRvQmFzZTY0KHRtcCkpXG4gIH1cbiAgcmV0dXJuIG91dHB1dC5qb2luKCcnKVxufVxuXG5mdW5jdGlvbiBmcm9tQnl0ZUFycmF5ICh1aW50OCkge1xuICB2YXIgdG1wXG4gIHZhciBsZW4gPSB1aW50OC5sZW5ndGhcbiAgdmFyIGV4dHJhQnl0ZXMgPSBsZW4gJSAzIC8vIGlmIHdlIGhhdmUgMSBieXRlIGxlZnQsIHBhZCAyIGJ5dGVzXG4gIHZhciBwYXJ0cyA9IFtdXG4gIHZhciBtYXhDaHVua0xlbmd0aCA9IDE2MzgzIC8vIG11c3QgYmUgbXVsdGlwbGUgb2YgM1xuXG4gIC8vIGdvIHRocm91Z2ggdGhlIGFycmF5IGV2ZXJ5IHRocmVlIGJ5dGVzLCB3ZSdsbCBkZWFsIHdpdGggdHJhaWxpbmcgc3R1ZmYgbGF0ZXJcbiAgZm9yICh2YXIgaSA9IDAsIGxlbjIgPSBsZW4gLSBleHRyYUJ5dGVzOyBpIDwgbGVuMjsgaSArPSBtYXhDaHVua0xlbmd0aCkge1xuICAgIHBhcnRzLnB1c2goZW5jb2RlQ2h1bmsodWludDgsIGksIChpICsgbWF4Q2h1bmtMZW5ndGgpID4gbGVuMiA/IGxlbjIgOiAoaSArIG1heENodW5rTGVuZ3RoKSkpXG4gIH1cblxuICAvLyBwYWQgdGhlIGVuZCB3aXRoIHplcm9zLCBidXQgbWFrZSBzdXJlIHRvIG5vdCBmb3JnZXQgdGhlIGV4dHJhIGJ5dGVzXG4gIGlmIChleHRyYUJ5dGVzID09PSAxKSB7XG4gICAgdG1wID0gdWludDhbbGVuIC0gMV1cbiAgICBwYXJ0cy5wdXNoKFxuICAgICAgbG9va3VwW3RtcCA+PiAyXSArXG4gICAgICBsb29rdXBbKHRtcCA8PCA0KSAmIDB4M0ZdICtcbiAgICAgICc9PSdcbiAgICApXG4gIH0gZWxzZSBpZiAoZXh0cmFCeXRlcyA9PT0gMikge1xuICAgIHRtcCA9ICh1aW50OFtsZW4gLSAyXSA8PCA4KSArIHVpbnQ4W2xlbiAtIDFdXG4gICAgcGFydHMucHVzaChcbiAgICAgIGxvb2t1cFt0bXAgPj4gMTBdICtcbiAgICAgIGxvb2t1cFsodG1wID4+IDQpICYgMHgzRl0gK1xuICAgICAgbG9va3VwWyh0bXAgPDwgMikgJiAweDNGXSArXG4gICAgICAnPSdcbiAgICApXG4gIH1cblxuICByZXR1cm4gcGFydHMuam9pbignJylcbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/base64-js/index.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/buffer/index.js":
+/*!**************************************!*\
+  !*** ./node_modules/buffer/index.js ***!
+  \**************************************/
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
+
+"use strict";
+eval("/*!\n * The buffer module from node.js, for the browser.\n *\n * @author   Feross Aboukhadijeh <https://feross.org>\n * @license  MIT\n */\n/* eslint-disable no-proto */\n\n\n\nconst base64 = __webpack_require__(/*! base64-js */ \"./node_modules/base64-js/index.js\")\nconst ieee754 = __webpack_require__(/*! ieee754 */ \"./node_modules/ieee754/index.js\")\nconst customInspectSymbol =\n  (typeof Symbol === 'function' && typeof Symbol['for'] === 'function') // eslint-disable-line dot-notation\n    ? Symbol['for']('nodejs.util.inspect.custom') // eslint-disable-line dot-notation\n    : null\n\nexports.Buffer = Buffer\nexports.SlowBuffer = SlowBuffer\nexports.INSPECT_MAX_BYTES = 50\n\nconst K_MAX_LENGTH = 0x7fffffff\nexports.kMaxLength = K_MAX_LENGTH\n\n/**\n * If `Buffer.TYPED_ARRAY_SUPPORT`:\n *   === true    Use Uint8Array implementation (fastest)\n *   === false   Print warning and recommend using `buffer` v4.x which has an Object\n *               implementation (most compatible, even IE6)\n *\n * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,\n * Opera 11.6+, iOS 4.2+.\n *\n * We report that the browser does not support typed arrays if the are not subclassable\n * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array`\n * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support\n * for __proto__ and has a buggy typed array implementation.\n */\nBuffer.TYPED_ARRAY_SUPPORT = typedArraySupport()\n\nif (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' &&\n    typeof console.error === 'function') {\n  console.error(\n    'This browser lacks typed array (Uint8Array) support which is required by ' +\n    '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.'\n  )\n}\n\nfunction typedArraySupport () {\n  // Can typed array instances can be augmented?\n  try {\n    const arr = new Uint8Array(1)\n    const proto = { foo: function () { return 42 } }\n    Object.setPrototypeOf(proto, Uint8Array.prototype)\n    Object.setPrototypeOf(arr, proto)\n    return arr.foo() === 42\n  } catch (e) {\n    return false\n  }\n}\n\nObject.defineProperty(Buffer.prototype, 'parent', {\n  enumerable: true,\n  get: function () {\n    if (!Buffer.isBuffer(this)) return undefined\n    return this.buffer\n  }\n})\n\nObject.defineProperty(Buffer.prototype, 'offset', {\n  enumerable: true,\n  get: function () {\n    if (!Buffer.isBuffer(this)) return undefined\n    return this.byteOffset\n  }\n})\n\nfunction createBuffer (length) {\n  if (length > K_MAX_LENGTH) {\n    throw new RangeError('The value \"' + length + '\" is invalid for option \"size\"')\n  }\n  // Return an augmented `Uint8Array` instance\n  const buf = new Uint8Array(length)\n  Object.setPrototypeOf(buf, Buffer.prototype)\n  return buf\n}\n\n/**\n * The Buffer constructor returns instances of `Uint8Array` that have their\n * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of\n * `Uint8Array`, so the returned instances will have all the node `Buffer` methods\n * and the `Uint8Array` methods. Square bracket notation works as expected -- it\n * returns a single octet.\n *\n * The `Uint8Array` prototype remains unmodified.\n */\n\nfunction Buffer (arg, encodingOrOffset, length) {\n  // Common case.\n  if (typeof arg === 'number') {\n    if (typeof encodingOrOffset === 'string') {\n      throw new TypeError(\n        'The \"string\" argument must be of type string. Received type number'\n      )\n    }\n    return allocUnsafe(arg)\n  }\n  return from(arg, encodingOrOffset, length)\n}\n\nBuffer.poolSize = 8192 // not used by this implementation\n\nfunction from (value, encodingOrOffset, length) {\n  if (typeof value === 'string') {\n    return fromString(value, encodingOrOffset)\n  }\n\n  if (ArrayBuffer.isView(value)) {\n    return fromArrayView(value)\n  }\n\n  if (value == null) {\n    throw new TypeError(\n      'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' +\n      'or Array-like Object. Received type ' + (typeof value)\n    )\n  }\n\n  if (isInstance(value, ArrayBuffer) ||\n      (value && isInstance(value.buffer, ArrayBuffer))) {\n    return fromArrayBuffer(value, encodingOrOffset, length)\n  }\n\n  if (typeof SharedArrayBuffer !== 'undefined' &&\n      (isInstance(value, SharedArrayBuffer) ||\n      (value && isInstance(value.buffer, SharedArrayBuffer)))) {\n    return fromArrayBuffer(value, encodingOrOffset, length)\n  }\n\n  if (typeof value === 'number') {\n    throw new TypeError(\n      'The \"value\" argument must not be of type number. Received type number'\n    )\n  }\n\n  const valueOf = value.valueOf && value.valueOf()\n  if (valueOf != null && valueOf !== value) {\n    return Buffer.from(valueOf, encodingOrOffset, length)\n  }\n\n  const b = fromObject(value)\n  if (b) return b\n\n  if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null &&\n      typeof value[Symbol.toPrimitive] === 'function') {\n    return Buffer.from(value[Symbol.toPrimitive]('string'), encodingOrOffset, length)\n  }\n\n  throw new TypeError(\n    'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' +\n    'or Array-like Object. Received type ' + (typeof value)\n  )\n}\n\n/**\n * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError\n * if value is a number.\n * Buffer.from(str[, encoding])\n * Buffer.from(array)\n * Buffer.from(buffer)\n * Buffer.from(arrayBuffer[, byteOffset[, length]])\n **/\nBuffer.from = function (value, encodingOrOffset, length) {\n  return from(value, encodingOrOffset, length)\n}\n\n// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug:\n// https://github.com/feross/buffer/pull/148\nObject.setPrototypeOf(Buffer.prototype, Uint8Array.prototype)\nObject.setPrototypeOf(Buffer, Uint8Array)\n\nfunction assertSize (size) {\n  if (typeof size !== 'number') {\n    throw new TypeError('\"size\" argument must be of type number')\n  } else if (size < 0) {\n    throw new RangeError('The value \"' + size + '\" is invalid for option \"size\"')\n  }\n}\n\nfunction alloc (size, fill, encoding) {\n  assertSize(size)\n  if (size <= 0) {\n    return createBuffer(size)\n  }\n  if (fill !== undefined) {\n    // Only pay attention to encoding if it's a string. This\n    // prevents accidentally sending in a number that would\n    // be interpreted as a start offset.\n    return typeof encoding === 'string'\n      ? createBuffer(size).fill(fill, encoding)\n      : createBuffer(size).fill(fill)\n  }\n  return createBuffer(size)\n}\n\n/**\n * Creates a new filled Buffer instance.\n * alloc(size[, fill[, encoding]])\n **/\nBuffer.alloc = function (size, fill, encoding) {\n  return alloc(size, fill, encoding)\n}\n\nfunction allocUnsafe (size) {\n  assertSize(size)\n  return createBuffer(size < 0 ? 0 : checked(size) | 0)\n}\n\n/**\n * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.\n * */\nBuffer.allocUnsafe = function (size) {\n  return allocUnsafe(size)\n}\n/**\n * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.\n */\nBuffer.allocUnsafeSlow = function (size) {\n  return allocUnsafe(size)\n}\n\nfunction fromString (string, encoding) {\n  if (typeof encoding !== 'string' || encoding === '') {\n    encoding = 'utf8'\n  }\n\n  if (!Buffer.isEncoding(encoding)) {\n    throw new TypeError('Unknown encoding: ' + encoding)\n  }\n\n  const length = byteLength(string, encoding) | 0\n  let buf = createBuffer(length)\n\n  const actual = buf.write(string, encoding)\n\n  if (actual !== length) {\n    // Writing a hex string, for example, that contains invalid characters will\n    // cause everything after the first invalid character to be ignored. (e.g.\n    // 'abxxcd' will be treated as 'ab')\n    buf = buf.slice(0, actual)\n  }\n\n  return buf\n}\n\nfunction fromArrayLike (array) {\n  const length = array.length < 0 ? 0 : checked(array.length) | 0\n  const buf = createBuffer(length)\n  for (let i = 0; i < length; i += 1) {\n    buf[i] = array[i] & 255\n  }\n  return buf\n}\n\nfunction fromArrayView (arrayView) {\n  if (isInstance(arrayView, Uint8Array)) {\n    const copy = new Uint8Array(arrayView)\n    return fromArrayBuffer(copy.buffer, copy.byteOffset, copy.byteLength)\n  }\n  return fromArrayLike(arrayView)\n}\n\nfunction fromArrayBuffer (array, byteOffset, length) {\n  if (byteOffset < 0 || array.byteLength < byteOffset) {\n    throw new RangeError('\"offset\" is outside of buffer bounds')\n  }\n\n  if (array.byteLength < byteOffset + (length || 0)) {\n    throw new RangeError('\"length\" is outside of buffer bounds')\n  }\n\n  let buf\n  if (byteOffset === undefined && length === undefined) {\n    buf = new Uint8Array(array)\n  } else if (length === undefined) {\n    buf = new Uint8Array(array, byteOffset)\n  } else {\n    buf = new Uint8Array(array, byteOffset, length)\n  }\n\n  // Return an augmented `Uint8Array` instance\n  Object.setPrototypeOf(buf, Buffer.prototype)\n\n  return buf\n}\n\nfunction fromObject (obj) {\n  if (Buffer.isBuffer(obj)) {\n    const len = checked(obj.length) | 0\n    const buf = createBuffer(len)\n\n    if (buf.length === 0) {\n      return buf\n    }\n\n    obj.copy(buf, 0, 0, len)\n    return buf\n  }\n\n  if (obj.length !== undefined) {\n    if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) {\n      return createBuffer(0)\n    }\n    return fromArrayLike(obj)\n  }\n\n  if (obj.type === 'Buffer' && Array.isArray(obj.data)) {\n    return fromArrayLike(obj.data)\n  }\n}\n\nfunction checked (length) {\n  // Note: cannot use `length < K_MAX_LENGTH` here because that fails when\n  // length is NaN (which is otherwise coerced to zero.)\n  if (length >= K_MAX_LENGTH) {\n    throw new RangeError('Attempt to allocate Buffer larger than maximum ' +\n                         'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes')\n  }\n  return length | 0\n}\n\nfunction SlowBuffer (length) {\n  if (+length != length) { // eslint-disable-line eqeqeq\n    length = 0\n  }\n  return Buffer.alloc(+length)\n}\n\nBuffer.isBuffer = function isBuffer (b) {\n  return b != null && b._isBuffer === true &&\n    b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false\n}\n\nBuffer.compare = function compare (a, b) {\n  if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength)\n  if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength)\n  if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {\n    throw new TypeError(\n      'The \"buf1\", \"buf2\" arguments must be one of type Buffer or Uint8Array'\n    )\n  }\n\n  if (a === b) return 0\n\n  let x = a.length\n  let y = b.length\n\n  for (let i = 0, len = Math.min(x, y); i < len; ++i) {\n    if (a[i] !== b[i]) {\n      x = a[i]\n      y = b[i]\n      break\n    }\n  }\n\n  if (x < y) return -1\n  if (y < x) return 1\n  return 0\n}\n\nBuffer.isEncoding = function isEncoding (encoding) {\n  switch (String(encoding).toLowerCase()) {\n    case 'hex':\n    case 'utf8':\n    case 'utf-8':\n    case 'ascii':\n    case 'latin1':\n    case 'binary':\n    case 'base64':\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n      return true\n    default:\n      return false\n  }\n}\n\nBuffer.concat = function concat (list, length) {\n  if (!Array.isArray(list)) {\n    throw new TypeError('\"list\" argument must be an Array of Buffers')\n  }\n\n  if (list.length === 0) {\n    return Buffer.alloc(0)\n  }\n\n  let i\n  if (length === undefined) {\n    length = 0\n    for (i = 0; i < list.length; ++i) {\n      length += list[i].length\n    }\n  }\n\n  const buffer = Buffer.allocUnsafe(length)\n  let pos = 0\n  for (i = 0; i < list.length; ++i) {\n    let buf = list[i]\n    if (isInstance(buf, Uint8Array)) {\n      if (pos + buf.length > buffer.length) {\n        if (!Buffer.isBuffer(buf)) buf = Buffer.from(buf)\n        buf.copy(buffer, pos)\n      } else {\n        Uint8Array.prototype.set.call(\n          buffer,\n          buf,\n          pos\n        )\n      }\n    } else if (!Buffer.isBuffer(buf)) {\n      throw new TypeError('\"list\" argument must be an Array of Buffers')\n    } else {\n      buf.copy(buffer, pos)\n    }\n    pos += buf.length\n  }\n  return buffer\n}\n\nfunction byteLength (string, encoding) {\n  if (Buffer.isBuffer(string)) {\n    return string.length\n  }\n  if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) {\n    return string.byteLength\n  }\n  if (typeof string !== 'string') {\n    throw new TypeError(\n      'The \"string\" argument must be one of type string, Buffer, or ArrayBuffer. ' +\n      'Received type ' + typeof string\n    )\n  }\n\n  const len = string.length\n  const mustMatch = (arguments.length > 2 && arguments[2] === true)\n  if (!mustMatch && len === 0) return 0\n\n  // Use a for loop to avoid recursion\n  let loweredCase = false\n  for (;;) {\n    switch (encoding) {\n      case 'ascii':\n      case 'latin1':\n      case 'binary':\n        return len\n      case 'utf8':\n      case 'utf-8':\n        return utf8ToBytes(string).length\n      case 'ucs2':\n      case 'ucs-2':\n      case 'utf16le':\n      case 'utf-16le':\n        return len * 2\n      case 'hex':\n        return len >>> 1\n      case 'base64':\n        return base64ToBytes(string).length\n      default:\n        if (loweredCase) {\n          return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8\n        }\n        encoding = ('' + encoding).toLowerCase()\n        loweredCase = true\n    }\n  }\n}\nBuffer.byteLength = byteLength\n\nfunction slowToString (encoding, start, end) {\n  let loweredCase = false\n\n  // No need to verify that \"this.length <= MAX_UINT32\" since it's a read-only\n  // property of a typed array.\n\n  // This behaves neither like String nor Uint8Array in that we set start/end\n  // to their upper/lower bounds if the value passed is out of range.\n  // undefined is handled specially as per ECMA-262 6th Edition,\n  // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.\n  if (start === undefined || start < 0) {\n    start = 0\n  }\n  // Return early if start > this.length. Done here to prevent potential uint32\n  // coercion fail below.\n  if (start > this.length) {\n    return ''\n  }\n\n  if (end === undefined || end > this.length) {\n    end = this.length\n  }\n\n  if (end <= 0) {\n    return ''\n  }\n\n  // Force coercion to uint32. This will also coerce falsey/NaN values to 0.\n  end >>>= 0\n  start >>>= 0\n\n  if (end <= start) {\n    return ''\n  }\n\n  if (!encoding) encoding = 'utf8'\n\n  while (true) {\n    switch (encoding) {\n      case 'hex':\n        return hexSlice(this, start, end)\n\n      case 'utf8':\n      case 'utf-8':\n        return utf8Slice(this, start, end)\n\n      case 'ascii':\n        return asciiSlice(this, start, end)\n\n      case 'latin1':\n      case 'binary':\n        return latin1Slice(this, start, end)\n\n      case 'base64':\n        return base64Slice(this, start, end)\n\n      case 'ucs2':\n      case 'ucs-2':\n      case 'utf16le':\n      case 'utf-16le':\n        return utf16leSlice(this, start, end)\n\n      default:\n        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)\n        encoding = (encoding + '').toLowerCase()\n        loweredCase = true\n    }\n  }\n}\n\n// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package)\n// to detect a Buffer instance. It's not possible to use `instanceof Buffer`\n// reliably in a browserify context because there could be multiple different\n// copies of the 'buffer' package in use. This method works even for Buffer\n// instances that were created from another copy of the `buffer` package.\n// See: https://github.com/feross/buffer/issues/154\nBuffer.prototype._isBuffer = true\n\nfunction swap (b, n, m) {\n  const i = b[n]\n  b[n] = b[m]\n  b[m] = i\n}\n\nBuffer.prototype.swap16 = function swap16 () {\n  const len = this.length\n  if (len % 2 !== 0) {\n    throw new RangeError('Buffer size must be a multiple of 16-bits')\n  }\n  for (let i = 0; i < len; i += 2) {\n    swap(this, i, i + 1)\n  }\n  return this\n}\n\nBuffer.prototype.swap32 = function swap32 () {\n  const len = this.length\n  if (len % 4 !== 0) {\n    throw new RangeError('Buffer size must be a multiple of 32-bits')\n  }\n  for (let i = 0; i < len; i += 4) {\n    swap(this, i, i + 3)\n    swap(this, i + 1, i + 2)\n  }\n  return this\n}\n\nBuffer.prototype.swap64 = function swap64 () {\n  const len = this.length\n  if (len % 8 !== 0) {\n    throw new RangeError('Buffer size must be a multiple of 64-bits')\n  }\n  for (let i = 0; i < len; i += 8) {\n    swap(this, i, i + 7)\n    swap(this, i + 1, i + 6)\n    swap(this, i + 2, i + 5)\n    swap(this, i + 3, i + 4)\n  }\n  return this\n}\n\nBuffer.prototype.toString = function toString () {\n  const length = this.length\n  if (length === 0) return ''\n  if (arguments.length === 0) return utf8Slice(this, 0, length)\n  return slowToString.apply(this, arguments)\n}\n\nBuffer.prototype.toLocaleString = Buffer.prototype.toString\n\nBuffer.prototype.equals = function equals (b) {\n  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')\n  if (this === b) return true\n  return Buffer.compare(this, b) === 0\n}\n\nBuffer.prototype.inspect = function inspect () {\n  let str = ''\n  const max = exports.INSPECT_MAX_BYTES\n  str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim()\n  if (this.length > max) str += ' ... '\n  return '<Buffer ' + str + '>'\n}\nif (customInspectSymbol) {\n  Buffer.prototype[customInspectSymbol] = Buffer.prototype.inspect\n}\n\nBuffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {\n  if (isInstance(target, Uint8Array)) {\n    target = Buffer.from(target, target.offset, target.byteLength)\n  }\n  if (!Buffer.isBuffer(target)) {\n    throw new TypeError(\n      'The \"target\" argument must be one of type Buffer or Uint8Array. ' +\n      'Received type ' + (typeof target)\n    )\n  }\n\n  if (start === undefined) {\n    start = 0\n  }\n  if (end === undefined) {\n    end = target ? target.length : 0\n  }\n  if (thisStart === undefined) {\n    thisStart = 0\n  }\n  if (thisEnd === undefined) {\n    thisEnd = this.length\n  }\n\n  if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {\n    throw new RangeError('out of range index')\n  }\n\n  if (thisStart >= thisEnd && start >= end) {\n    return 0\n  }\n  if (thisStart >= thisEnd) {\n    return -1\n  }\n  if (start >= end) {\n    return 1\n  }\n\n  start >>>= 0\n  end >>>= 0\n  thisStart >>>= 0\n  thisEnd >>>= 0\n\n  if (this === target) return 0\n\n  let x = thisEnd - thisStart\n  let y = end - start\n  const len = Math.min(x, y)\n\n  const thisCopy = this.slice(thisStart, thisEnd)\n  const targetCopy = target.slice(start, end)\n\n  for (let i = 0; i < len; ++i) {\n    if (thisCopy[i] !== targetCopy[i]) {\n      x = thisCopy[i]\n      y = targetCopy[i]\n      break\n    }\n  }\n\n  if (x < y) return -1\n  if (y < x) return 1\n  return 0\n}\n\n// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,\n// OR the last index of `val` in `buffer` at offset <= `byteOffset`.\n//\n// Arguments:\n// - buffer - a Buffer to search\n// - val - a string, Buffer, or number\n// - byteOffset - an index into `buffer`; will be clamped to an int32\n// - encoding - an optional encoding, relevant is val is a string\n// - dir - true for indexOf, false for lastIndexOf\nfunction bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {\n  // Empty buffer means no match\n  if (buffer.length === 0) return -1\n\n  // Normalize byteOffset\n  if (typeof byteOffset === 'string') {\n    encoding = byteOffset\n    byteOffset = 0\n  } else if (byteOffset > 0x7fffffff) {\n    byteOffset = 0x7fffffff\n  } else if (byteOffset < -0x80000000) {\n    byteOffset = -0x80000000\n  }\n  byteOffset = +byteOffset // Coerce to Number.\n  if (numberIsNaN(byteOffset)) {\n    // byteOffset: it it's undefined, null, NaN, \"foo\", etc, search whole buffer\n    byteOffset = dir ? 0 : (buffer.length - 1)\n  }\n\n  // Normalize byteOffset: negative offsets start from the end of the buffer\n  if (byteOffset < 0) byteOffset = buffer.length + byteOffset\n  if (byteOffset >= buffer.length) {\n    if (dir) return -1\n    else byteOffset = buffer.length - 1\n  } else if (byteOffset < 0) {\n    if (dir) byteOffset = 0\n    else return -1\n  }\n\n  // Normalize val\n  if (typeof val === 'string') {\n    val = Buffer.from(val, encoding)\n  }\n\n  // Finally, search either indexOf (if dir is true) or lastIndexOf\n  if (Buffer.isBuffer(val)) {\n    // Special case: looking for empty string/buffer always fails\n    if (val.length === 0) {\n      return -1\n    }\n    return arrayIndexOf(buffer, val, byteOffset, encoding, dir)\n  } else if (typeof val === 'number') {\n    val = val & 0xFF // Search for a byte value [0-255]\n    if (typeof Uint8Array.prototype.indexOf === 'function') {\n      if (dir) {\n        return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)\n      } else {\n        return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)\n      }\n    }\n    return arrayIndexOf(buffer, [val], byteOffset, encoding, dir)\n  }\n\n  throw new TypeError('val must be string, number or Buffer')\n}\n\nfunction arrayIndexOf (arr, val, byteOffset, encoding, dir) {\n  let indexSize = 1\n  let arrLength = arr.length\n  let valLength = val.length\n\n  if (encoding !== undefined) {\n    encoding = String(encoding).toLowerCase()\n    if (encoding === 'ucs2' || encoding === 'ucs-2' ||\n        encoding === 'utf16le' || encoding === 'utf-16le') {\n      if (arr.length < 2 || val.length < 2) {\n        return -1\n      }\n      indexSize = 2\n      arrLength /= 2\n      valLength /= 2\n      byteOffset /= 2\n    }\n  }\n\n  function read (buf, i) {\n    if (indexSize === 1) {\n      return buf[i]\n    } else {\n      return buf.readUInt16BE(i * indexSize)\n    }\n  }\n\n  let i\n  if (dir) {\n    let foundIndex = -1\n    for (i = byteOffset; i < arrLength; i++) {\n      if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {\n        if (foundIndex === -1) foundIndex = i\n        if (i - foundIndex + 1 === valLength) return foundIndex * indexSize\n      } else {\n        if (foundIndex !== -1) i -= i - foundIndex\n        foundIndex = -1\n      }\n    }\n  } else {\n    if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength\n    for (i = byteOffset; i >= 0; i--) {\n      let found = true\n      for (let j = 0; j < valLength; j++) {\n        if (read(arr, i + j) !== read(val, j)) {\n          found = false\n          break\n        }\n      }\n      if (found) return i\n    }\n  }\n\n  return -1\n}\n\nBuffer.prototype.includes = function includes (val, byteOffset, encoding) {\n  return this.indexOf(val, byteOffset, encoding) !== -1\n}\n\nBuffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {\n  return bidirectionalIndexOf(this, val, byteOffset, encoding, true)\n}\n\nBuffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {\n  return bidirectionalIndexOf(this, val, byteOffset, encoding, false)\n}\n\nfunction hexWrite (buf, string, offset, length) {\n  offset = Number(offset) || 0\n  const remaining = buf.length - offset\n  if (!length) {\n    length = remaining\n  } else {\n    length = Number(length)\n    if (length > remaining) {\n      length = remaining\n    }\n  }\n\n  const strLen = string.length\n\n  if (length > strLen / 2) {\n    length = strLen / 2\n  }\n  let i\n  for (i = 0; i < length; ++i) {\n    const parsed = parseInt(string.substr(i * 2, 2), 16)\n    if (numberIsNaN(parsed)) return i\n    buf[offset + i] = parsed\n  }\n  return i\n}\n\nfunction utf8Write (buf, string, offset, length) {\n  return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)\n}\n\nfunction asciiWrite (buf, string, offset, length) {\n  return blitBuffer(asciiToBytes(string), buf, offset, length)\n}\n\nfunction base64Write (buf, string, offset, length) {\n  return blitBuffer(base64ToBytes(string), buf, offset, length)\n}\n\nfunction ucs2Write (buf, string, offset, length) {\n  return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)\n}\n\nBuffer.prototype.write = function write (string, offset, length, encoding) {\n  // Buffer#write(string)\n  if (offset === undefined) {\n    encoding = 'utf8'\n    length = this.length\n    offset = 0\n  // Buffer#write(string, encoding)\n  } else if (length === undefined && typeof offset === 'string') {\n    encoding = offset\n    length = this.length\n    offset = 0\n  // Buffer#write(string, offset[, length][, encoding])\n  } else if (isFinite(offset)) {\n    offset = offset >>> 0\n    if (isFinite(length)) {\n      length = length >>> 0\n      if (encoding === undefined) encoding = 'utf8'\n    } else {\n      encoding = length\n      length = undefined\n    }\n  } else {\n    throw new Error(\n      'Buffer.write(string, encoding, offset[, length]) is no longer supported'\n    )\n  }\n\n  const remaining = this.length - offset\n  if (length === undefined || length > remaining) length = remaining\n\n  if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {\n    throw new RangeError('Attempt to write outside buffer bounds')\n  }\n\n  if (!encoding) encoding = 'utf8'\n\n  let loweredCase = false\n  for (;;) {\n    switch (encoding) {\n      case 'hex':\n        return hexWrite(this, string, offset, length)\n\n      case 'utf8':\n      case 'utf-8':\n        return utf8Write(this, string, offset, length)\n\n      case 'ascii':\n      case 'latin1':\n      case 'binary':\n        return asciiWrite(this, string, offset, length)\n\n      case 'base64':\n        // Warning: maxLength not taken into account in base64Write\n        return base64Write(this, string, offset, length)\n\n      case 'ucs2':\n      case 'ucs-2':\n      case 'utf16le':\n      case 'utf-16le':\n        return ucs2Write(this, string, offset, length)\n\n      default:\n        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)\n        encoding = ('' + encoding).toLowerCase()\n        loweredCase = true\n    }\n  }\n}\n\nBuffer.prototype.toJSON = function toJSON () {\n  return {\n    type: 'Buffer',\n    data: Array.prototype.slice.call(this._arr || this, 0)\n  }\n}\n\nfunction base64Slice (buf, start, end) {\n  if (start === 0 && end === buf.length) {\n    return base64.fromByteArray(buf)\n  } else {\n    return base64.fromByteArray(buf.slice(start, end))\n  }\n}\n\nfunction utf8Slice (buf, start, end) {\n  end = Math.min(buf.length, end)\n  const res = []\n\n  let i = start\n  while (i < end) {\n    const firstByte = buf[i]\n    let codePoint = null\n    let bytesPerSequence = (firstByte > 0xEF)\n      ? 4\n      : (firstByte > 0xDF)\n          ? 3\n          : (firstByte > 0xBF)\n              ? 2\n              : 1\n\n    if (i + bytesPerSequence <= end) {\n      let secondByte, thirdByte, fourthByte, tempCodePoint\n\n      switch (bytesPerSequence) {\n        case 1:\n          if (firstByte < 0x80) {\n            codePoint = firstByte\n          }\n          break\n        case 2:\n          secondByte = buf[i + 1]\n          if ((secondByte & 0xC0) === 0x80) {\n            tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)\n            if (tempCodePoint > 0x7F) {\n              codePoint = tempCodePoint\n            }\n          }\n          break\n        case 3:\n          secondByte = buf[i + 1]\n          thirdByte = buf[i + 2]\n          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {\n            tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)\n            if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {\n              codePoint = tempCodePoint\n            }\n          }\n          break\n        case 4:\n          secondByte = buf[i + 1]\n          thirdByte = buf[i + 2]\n          fourthByte = buf[i + 3]\n          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {\n            tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)\n            if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {\n              codePoint = tempCodePoint\n            }\n          }\n      }\n    }\n\n    if (codePoint === null) {\n      // we did not generate a valid codePoint so insert a\n      // replacement char (U+FFFD) and advance only 1 byte\n      codePoint = 0xFFFD\n      bytesPerSequence = 1\n    } else if (codePoint > 0xFFFF) {\n      // encode to utf16 (surrogate pair dance)\n      codePoint -= 0x10000\n      res.push(codePoint >>> 10 & 0x3FF | 0xD800)\n      codePoint = 0xDC00 | codePoint & 0x3FF\n    }\n\n    res.push(codePoint)\n    i += bytesPerSequence\n  }\n\n  return decodeCodePointsArray(res)\n}\n\n// Based on http://stackoverflow.com/a/22747272/680742, the browser with\n// the lowest limit is Chrome, with 0x10000 args.\n// We go 1 magnitude less, for safety\nconst MAX_ARGUMENTS_LENGTH = 0x1000\n\nfunction decodeCodePointsArray (codePoints) {\n  const len = codePoints.length\n  if (len <= MAX_ARGUMENTS_LENGTH) {\n    return String.fromCharCode.apply(String, codePoints) // avoid extra slice()\n  }\n\n  // Decode in chunks to avoid \"call stack size exceeded\".\n  let res = ''\n  let i = 0\n  while (i < len) {\n    res += String.fromCharCode.apply(\n      String,\n      codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)\n    )\n  }\n  return res\n}\n\nfunction asciiSlice (buf, start, end) {\n  let ret = ''\n  end = Math.min(buf.length, end)\n\n  for (let i = start; i < end; ++i) {\n    ret += String.fromCharCode(buf[i] & 0x7F)\n  }\n  return ret\n}\n\nfunction latin1Slice (buf, start, end) {\n  let ret = ''\n  end = Math.min(buf.length, end)\n\n  for (let i = start; i < end; ++i) {\n    ret += String.fromCharCode(buf[i])\n  }\n  return ret\n}\n\nfunction hexSlice (buf, start, end) {\n  const len = buf.length\n\n  if (!start || start < 0) start = 0\n  if (!end || end < 0 || end > len) end = len\n\n  let out = ''\n  for (let i = start; i < end; ++i) {\n    out += hexSliceLookupTable[buf[i]]\n  }\n  return out\n}\n\nfunction utf16leSlice (buf, start, end) {\n  const bytes = buf.slice(start, end)\n  let res = ''\n  // If bytes.length is odd, the last 8 bits must be ignored (same as node.js)\n  for (let i = 0; i < bytes.length - 1; i += 2) {\n    res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256))\n  }\n  return res\n}\n\nBuffer.prototype.slice = function slice (start, end) {\n  const len = this.length\n  start = ~~start\n  end = end === undefined ? len : ~~end\n\n  if (start < 0) {\n    start += len\n    if (start < 0) start = 0\n  } else if (start > len) {\n    start = len\n  }\n\n  if (end < 0) {\n    end += len\n    if (end < 0) end = 0\n  } else if (end > len) {\n    end = len\n  }\n\n  if (end < start) end = start\n\n  const newBuf = this.subarray(start, end)\n  // Return an augmented `Uint8Array` instance\n  Object.setPrototypeOf(newBuf, Buffer.prototype)\n\n  return newBuf\n}\n\n/*\n * Need to make sure that buffer isn't trying to write out of bounds.\n */\nfunction checkOffset (offset, ext, length) {\n  if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')\n  if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')\n}\n\nBuffer.prototype.readUintLE =\nBuffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {\n  offset = offset >>> 0\n  byteLength = byteLength >>> 0\n  if (!noAssert) checkOffset(offset, byteLength, this.length)\n\n  let val = this[offset]\n  let mul = 1\n  let i = 0\n  while (++i < byteLength && (mul *= 0x100)) {\n    val += this[offset + i] * mul\n  }\n\n  return val\n}\n\nBuffer.prototype.readUintBE =\nBuffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {\n  offset = offset >>> 0\n  byteLength = byteLength >>> 0\n  if (!noAssert) {\n    checkOffset(offset, byteLength, this.length)\n  }\n\n  let val = this[offset + --byteLength]\n  let mul = 1\n  while (byteLength > 0 && (mul *= 0x100)) {\n    val += this[offset + --byteLength] * mul\n  }\n\n  return val\n}\n\nBuffer.prototype.readUint8 =\nBuffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 1, this.length)\n  return this[offset]\n}\n\nBuffer.prototype.readUint16LE =\nBuffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 2, this.length)\n  return this[offset] | (this[offset + 1] << 8)\n}\n\nBuffer.prototype.readUint16BE =\nBuffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 2, this.length)\n  return (this[offset] << 8) | this[offset + 1]\n}\n\nBuffer.prototype.readUint32LE =\nBuffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 4, this.length)\n\n  return ((this[offset]) |\n      (this[offset + 1] << 8) |\n      (this[offset + 2] << 16)) +\n      (this[offset + 3] * 0x1000000)\n}\n\nBuffer.prototype.readUint32BE =\nBuffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 4, this.length)\n\n  return (this[offset] * 0x1000000) +\n    ((this[offset + 1] << 16) |\n    (this[offset + 2] << 8) |\n    this[offset + 3])\n}\n\nBuffer.prototype.readBigUInt64LE = defineBigIntMethod(function readBigUInt64LE (offset) {\n  offset = offset >>> 0\n  validateNumber(offset, 'offset')\n  const first = this[offset]\n  const last = this[offset + 7]\n  if (first === undefined || last === undefined) {\n    boundsError(offset, this.length - 8)\n  }\n\n  const lo = first +\n    this[++offset] * 2 ** 8 +\n    this[++offset] * 2 ** 16 +\n    this[++offset] * 2 ** 24\n\n  const hi = this[++offset] +\n    this[++offset] * 2 ** 8 +\n    this[++offset] * 2 ** 16 +\n    last * 2 ** 24\n\n  return BigInt(lo) + (BigInt(hi) << BigInt(32))\n})\n\nBuffer.prototype.readBigUInt64BE = defineBigIntMethod(function readBigUInt64BE (offset) {\n  offset = offset >>> 0\n  validateNumber(offset, 'offset')\n  const first = this[offset]\n  const last = this[offset + 7]\n  if (first === undefined || last === undefined) {\n    boundsError(offset, this.length - 8)\n  }\n\n  const hi = first * 2 ** 24 +\n    this[++offset] * 2 ** 16 +\n    this[++offset] * 2 ** 8 +\n    this[++offset]\n\n  const lo = this[++offset] * 2 ** 24 +\n    this[++offset] * 2 ** 16 +\n    this[++offset] * 2 ** 8 +\n    last\n\n  return (BigInt(hi) << BigInt(32)) + BigInt(lo)\n})\n\nBuffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {\n  offset = offset >>> 0\n  byteLength = byteLength >>> 0\n  if (!noAssert) checkOffset(offset, byteLength, this.length)\n\n  let val = this[offset]\n  let mul = 1\n  let i = 0\n  while (++i < byteLength && (mul *= 0x100)) {\n    val += this[offset + i] * mul\n  }\n  mul *= 0x80\n\n  if (val >= mul) val -= Math.pow(2, 8 * byteLength)\n\n  return val\n}\n\nBuffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {\n  offset = offset >>> 0\n  byteLength = byteLength >>> 0\n  if (!noAssert) checkOffset(offset, byteLength, this.length)\n\n  let i = byteLength\n  let mul = 1\n  let val = this[offset + --i]\n  while (i > 0 && (mul *= 0x100)) {\n    val += this[offset + --i] * mul\n  }\n  mul *= 0x80\n\n  if (val >= mul) val -= Math.pow(2, 8 * byteLength)\n\n  return val\n}\n\nBuffer.prototype.readInt8 = function readInt8 (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 1, this.length)\n  if (!(this[offset] & 0x80)) return (this[offset])\n  return ((0xff - this[offset] + 1) * -1)\n}\n\nBuffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 2, this.length)\n  const val = this[offset] | (this[offset + 1] << 8)\n  return (val & 0x8000) ? val | 0xFFFF0000 : val\n}\n\nBuffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 2, this.length)\n  const val = this[offset + 1] | (this[offset] << 8)\n  return (val & 0x8000) ? val | 0xFFFF0000 : val\n}\n\nBuffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 4, this.length)\n\n  return (this[offset]) |\n    (this[offset + 1] << 8) |\n    (this[offset + 2] << 16) |\n    (this[offset + 3] << 24)\n}\n\nBuffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 4, this.length)\n\n  return (this[offset] << 24) |\n    (this[offset + 1] << 16) |\n    (this[offset + 2] << 8) |\n    (this[offset + 3])\n}\n\nBuffer.prototype.readBigInt64LE = defineBigIntMethod(function readBigInt64LE (offset) {\n  offset = offset >>> 0\n  validateNumber(offset, 'offset')\n  const first = this[offset]\n  const last = this[offset + 7]\n  if (first === undefined || last === undefined) {\n    boundsError(offset, this.length - 8)\n  }\n\n  const val = this[offset + 4] +\n    this[offset + 5] * 2 ** 8 +\n    this[offset + 6] * 2 ** 16 +\n    (last << 24) // Overflow\n\n  return (BigInt(val) << BigInt(32)) +\n    BigInt(first +\n    this[++offset] * 2 ** 8 +\n    this[++offset] * 2 ** 16 +\n    this[++offset] * 2 ** 24)\n})\n\nBuffer.prototype.readBigInt64BE = defineBigIntMethod(function readBigInt64BE (offset) {\n  offset = offset >>> 0\n  validateNumber(offset, 'offset')\n  const first = this[offset]\n  const last = this[offset + 7]\n  if (first === undefined || last === undefined) {\n    boundsError(offset, this.length - 8)\n  }\n\n  const val = (first << 24) + // Overflow\n    this[++offset] * 2 ** 16 +\n    this[++offset] * 2 ** 8 +\n    this[++offset]\n\n  return (BigInt(val) << BigInt(32)) +\n    BigInt(this[++offset] * 2 ** 24 +\n    this[++offset] * 2 ** 16 +\n    this[++offset] * 2 ** 8 +\n    last)\n})\n\nBuffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 4, this.length)\n  return ieee754.read(this, offset, true, 23, 4)\n}\n\nBuffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 4, this.length)\n  return ieee754.read(this, offset, false, 23, 4)\n}\n\nBuffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 8, this.length)\n  return ieee754.read(this, offset, true, 52, 8)\n}\n\nBuffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {\n  offset = offset >>> 0\n  if (!noAssert) checkOffset(offset, 8, this.length)\n  return ieee754.read(this, offset, false, 52, 8)\n}\n\nfunction checkInt (buf, value, offset, ext, max, min) {\n  if (!Buffer.isBuffer(buf)) throw new TypeError('\"buffer\" argument must be a Buffer instance')\n  if (value > max || value < min) throw new RangeError('\"value\" argument is out of bounds')\n  if (offset + ext > buf.length) throw new RangeError('Index out of range')\n}\n\nBuffer.prototype.writeUintLE =\nBuffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  byteLength = byteLength >>> 0\n  if (!noAssert) {\n    const maxBytes = Math.pow(2, 8 * byteLength) - 1\n    checkInt(this, value, offset, byteLength, maxBytes, 0)\n  }\n\n  let mul = 1\n  let i = 0\n  this[offset] = value & 0xFF\n  while (++i < byteLength && (mul *= 0x100)) {\n    this[offset + i] = (value / mul) & 0xFF\n  }\n\n  return offset + byteLength\n}\n\nBuffer.prototype.writeUintBE =\nBuffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  byteLength = byteLength >>> 0\n  if (!noAssert) {\n    const maxBytes = Math.pow(2, 8 * byteLength) - 1\n    checkInt(this, value, offset, byteLength, maxBytes, 0)\n  }\n\n  let i = byteLength - 1\n  let mul = 1\n  this[offset + i] = value & 0xFF\n  while (--i >= 0 && (mul *= 0x100)) {\n    this[offset + i] = (value / mul) & 0xFF\n  }\n\n  return offset + byteLength\n}\n\nBuffer.prototype.writeUint8 =\nBuffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)\n  this[offset] = (value & 0xff)\n  return offset + 1\n}\n\nBuffer.prototype.writeUint16LE =\nBuffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)\n  this[offset] = (value & 0xff)\n  this[offset + 1] = (value >>> 8)\n  return offset + 2\n}\n\nBuffer.prototype.writeUint16BE =\nBuffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)\n  this[offset] = (value >>> 8)\n  this[offset + 1] = (value & 0xff)\n  return offset + 2\n}\n\nBuffer.prototype.writeUint32LE =\nBuffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)\n  this[offset + 3] = (value >>> 24)\n  this[offset + 2] = (value >>> 16)\n  this[offset + 1] = (value >>> 8)\n  this[offset] = (value & 0xff)\n  return offset + 4\n}\n\nBuffer.prototype.writeUint32BE =\nBuffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)\n  this[offset] = (value >>> 24)\n  this[offset + 1] = (value >>> 16)\n  this[offset + 2] = (value >>> 8)\n  this[offset + 3] = (value & 0xff)\n  return offset + 4\n}\n\nfunction wrtBigUInt64LE (buf, value, offset, min, max) {\n  checkIntBI(value, min, max, buf, offset, 7)\n\n  let lo = Number(value & BigInt(0xffffffff))\n  buf[offset++] = lo\n  lo = lo >> 8\n  buf[offset++] = lo\n  lo = lo >> 8\n  buf[offset++] = lo\n  lo = lo >> 8\n  buf[offset++] = lo\n  let hi = Number(value >> BigInt(32) & BigInt(0xffffffff))\n  buf[offset++] = hi\n  hi = hi >> 8\n  buf[offset++] = hi\n  hi = hi >> 8\n  buf[offset++] = hi\n  hi = hi >> 8\n  buf[offset++] = hi\n  return offset\n}\n\nfunction wrtBigUInt64BE (buf, value, offset, min, max) {\n  checkIntBI(value, min, max, buf, offset, 7)\n\n  let lo = Number(value & BigInt(0xffffffff))\n  buf[offset + 7] = lo\n  lo = lo >> 8\n  buf[offset + 6] = lo\n  lo = lo >> 8\n  buf[offset + 5] = lo\n  lo = lo >> 8\n  buf[offset + 4] = lo\n  let hi = Number(value >> BigInt(32) & BigInt(0xffffffff))\n  buf[offset + 3] = hi\n  hi = hi >> 8\n  buf[offset + 2] = hi\n  hi = hi >> 8\n  buf[offset + 1] = hi\n  hi = hi >> 8\n  buf[offset] = hi\n  return offset + 8\n}\n\nBuffer.prototype.writeBigUInt64LE = defineBigIntMethod(function writeBigUInt64LE (value, offset = 0) {\n  return wrtBigUInt64LE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff'))\n})\n\nBuffer.prototype.writeBigUInt64BE = defineBigIntMethod(function writeBigUInt64BE (value, offset = 0) {\n  return wrtBigUInt64BE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff'))\n})\n\nBuffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) {\n    const limit = Math.pow(2, (8 * byteLength) - 1)\n\n    checkInt(this, value, offset, byteLength, limit - 1, -limit)\n  }\n\n  let i = 0\n  let mul = 1\n  let sub = 0\n  this[offset] = value & 0xFF\n  while (++i < byteLength && (mul *= 0x100)) {\n    if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {\n      sub = 1\n    }\n    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF\n  }\n\n  return offset + byteLength\n}\n\nBuffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) {\n    const limit = Math.pow(2, (8 * byteLength) - 1)\n\n    checkInt(this, value, offset, byteLength, limit - 1, -limit)\n  }\n\n  let i = byteLength - 1\n  let mul = 1\n  let sub = 0\n  this[offset + i] = value & 0xFF\n  while (--i >= 0 && (mul *= 0x100)) {\n    if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {\n      sub = 1\n    }\n    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF\n  }\n\n  return offset + byteLength\n}\n\nBuffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)\n  if (value < 0) value = 0xff + value + 1\n  this[offset] = (value & 0xff)\n  return offset + 1\n}\n\nBuffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)\n  this[offset] = (value & 0xff)\n  this[offset + 1] = (value >>> 8)\n  return offset + 2\n}\n\nBuffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)\n  this[offset] = (value >>> 8)\n  this[offset + 1] = (value & 0xff)\n  return offset + 2\n}\n\nBuffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)\n  this[offset] = (value & 0xff)\n  this[offset + 1] = (value >>> 8)\n  this[offset + 2] = (value >>> 16)\n  this[offset + 3] = (value >>> 24)\n  return offset + 4\n}\n\nBuffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)\n  if (value < 0) value = 0xffffffff + value + 1\n  this[offset] = (value >>> 24)\n  this[offset + 1] = (value >>> 16)\n  this[offset + 2] = (value >>> 8)\n  this[offset + 3] = (value & 0xff)\n  return offset + 4\n}\n\nBuffer.prototype.writeBigInt64LE = defineBigIntMethod(function writeBigInt64LE (value, offset = 0) {\n  return wrtBigUInt64LE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff'))\n})\n\nBuffer.prototype.writeBigInt64BE = defineBigIntMethod(function writeBigInt64BE (value, offset = 0) {\n  return wrtBigUInt64BE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff'))\n})\n\nfunction checkIEEE754 (buf, value, offset, ext, max, min) {\n  if (offset + ext > buf.length) throw new RangeError('Index out of range')\n  if (offset < 0) throw new RangeError('Index out of range')\n}\n\nfunction writeFloat (buf, value, offset, littleEndian, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) {\n    checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)\n  }\n  ieee754.write(buf, value, offset, littleEndian, 23, 4)\n  return offset + 4\n}\n\nBuffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {\n  return writeFloat(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {\n  return writeFloat(this, value, offset, false, noAssert)\n}\n\nfunction writeDouble (buf, value, offset, littleEndian, noAssert) {\n  value = +value\n  offset = offset >>> 0\n  if (!noAssert) {\n    checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)\n  }\n  ieee754.write(buf, value, offset, littleEndian, 52, 8)\n  return offset + 8\n}\n\nBuffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {\n  return writeDouble(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {\n  return writeDouble(this, value, offset, false, noAssert)\n}\n\n// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)\nBuffer.prototype.copy = function copy (target, targetStart, start, end) {\n  if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer')\n  if (!start) start = 0\n  if (!end && end !== 0) end = this.length\n  if (targetStart >= target.length) targetStart = target.length\n  if (!targetStart) targetStart = 0\n  if (end > 0 && end < start) end = start\n\n  // Copy 0 bytes; we're done\n  if (end === start) return 0\n  if (target.length === 0 || this.length === 0) return 0\n\n  // Fatal error conditions\n  if (targetStart < 0) {\n    throw new RangeError('targetStart out of bounds')\n  }\n  if (start < 0 || start >= this.length) throw new RangeError('Index out of range')\n  if (end < 0) throw new RangeError('sourceEnd out of bounds')\n\n  // Are we oob?\n  if (end > this.length) end = this.length\n  if (target.length - targetStart < end - start) {\n    end = target.length - targetStart + start\n  }\n\n  const len = end - start\n\n  if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') {\n    // Use built-in when available, missing from IE11\n    this.copyWithin(targetStart, start, end)\n  } else {\n    Uint8Array.prototype.set.call(\n      target,\n      this.subarray(start, end),\n      targetStart\n    )\n  }\n\n  return len\n}\n\n// Usage:\n//    buffer.fill(number[, offset[, end]])\n//    buffer.fill(buffer[, offset[, end]])\n//    buffer.fill(string[, offset[, end]][, encoding])\nBuffer.prototype.fill = function fill (val, start, end, encoding) {\n  // Handle string cases:\n  if (typeof val === 'string') {\n    if (typeof start === 'string') {\n      encoding = start\n      start = 0\n      end = this.length\n    } else if (typeof end === 'string') {\n      encoding = end\n      end = this.length\n    }\n    if (encoding !== undefined && typeof encoding !== 'string') {\n      throw new TypeError('encoding must be a string')\n    }\n    if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {\n      throw new TypeError('Unknown encoding: ' + encoding)\n    }\n    if (val.length === 1) {\n      const code = val.charCodeAt(0)\n      if ((encoding === 'utf8' && code < 128) ||\n          encoding === 'latin1') {\n        // Fast path: If `val` fits into a single byte, use that numeric value.\n        val = code\n      }\n    }\n  } else if (typeof val === 'number') {\n    val = val & 255\n  } else if (typeof val === 'boolean') {\n    val = Number(val)\n  }\n\n  // Invalid ranges are not set to a default, so can range check early.\n  if (start < 0 || this.length < start || this.length < end) {\n    throw new RangeError('Out of range index')\n  }\n\n  if (end <= start) {\n    return this\n  }\n\n  start = start >>> 0\n  end = end === undefined ? this.length : end >>> 0\n\n  if (!val) val = 0\n\n  let i\n  if (typeof val === 'number') {\n    for (i = start; i < end; ++i) {\n      this[i] = val\n    }\n  } else {\n    const bytes = Buffer.isBuffer(val)\n      ? val\n      : Buffer.from(val, encoding)\n    const len = bytes.length\n    if (len === 0) {\n      throw new TypeError('The value \"' + val +\n        '\" is invalid for argument \"value\"')\n    }\n    for (i = 0; i < end - start; ++i) {\n      this[i + start] = bytes[i % len]\n    }\n  }\n\n  return this\n}\n\n// CUSTOM ERRORS\n// =============\n\n// Simplified versions from Node, changed for Buffer-only usage\nconst errors = {}\nfunction E (sym, getMessage, Base) {\n  errors[sym] = class NodeError extends Base {\n    constructor () {\n      super()\n\n      Object.defineProperty(this, 'message', {\n        value: getMessage.apply(this, arguments),\n        writable: true,\n        configurable: true\n      })\n\n      // Add the error code to the name to include it in the stack trace.\n      this.name = `${this.name} [${sym}]`\n      // Access the stack to generate the error message including the error code\n      // from the name.\n      this.stack // eslint-disable-line no-unused-expressions\n      // Reset the name to the actual name.\n      delete this.name\n    }\n\n    get code () {\n      return sym\n    }\n\n    set code (value) {\n      Object.defineProperty(this, 'code', {\n        configurable: true,\n        enumerable: true,\n        value,\n        writable: true\n      })\n    }\n\n    toString () {\n      return `${this.name} [${sym}]: ${this.message}`\n    }\n  }\n}\n\nE('ERR_BUFFER_OUT_OF_BOUNDS',\n  function (name) {\n    if (name) {\n      return `${name} is outside of buffer bounds`\n    }\n\n    return 'Attempt to access memory outside buffer bounds'\n  }, RangeError)\nE('ERR_INVALID_ARG_TYPE',\n  function (name, actual) {\n    return `The \"${name}\" argument must be of type number. Received type ${typeof actual}`\n  }, TypeError)\nE('ERR_OUT_OF_RANGE',\n  function (str, range, input) {\n    let msg = `The value of \"${str}\" is out of range.`\n    let received = input\n    if (Number.isInteger(input) && Math.abs(input) > 2 ** 32) {\n      received = addNumericalSeparator(String(input))\n    } else if (typeof input === 'bigint') {\n      received = String(input)\n      if (input > BigInt(2) ** BigInt(32) || input < -(BigInt(2) ** BigInt(32))) {\n        received = addNumericalSeparator(received)\n      }\n      received += 'n'\n    }\n    msg += ` It must be ${range}. Received ${received}`\n    return msg\n  }, RangeError)\n\nfunction addNumericalSeparator (val) {\n  let res = ''\n  let i = val.length\n  const start = val[0] === '-' ? 1 : 0\n  for (; i >= start + 4; i -= 3) {\n    res = `_${val.slice(i - 3, i)}${res}`\n  }\n  return `${val.slice(0, i)}${res}`\n}\n\n// CHECK FUNCTIONS\n// ===============\n\nfunction checkBounds (buf, offset, byteLength) {\n  validateNumber(offset, 'offset')\n  if (buf[offset] === undefined || buf[offset + byteLength] === undefined) {\n    boundsError(offset, buf.length - (byteLength + 1))\n  }\n}\n\nfunction checkIntBI (value, min, max, buf, offset, byteLength) {\n  if (value > max || value < min) {\n    const n = typeof min === 'bigint' ? 'n' : ''\n    let range\n    if (byteLength > 3) {\n      if (min === 0 || min === BigInt(0)) {\n        range = `>= 0${n} and < 2${n} ** ${(byteLength + 1) * 8}${n}`\n      } else {\n        range = `>= -(2${n} ** ${(byteLength + 1) * 8 - 1}${n}) and < 2 ** ` +\n                `${(byteLength + 1) * 8 - 1}${n}`\n      }\n    } else {\n      range = `>= ${min}${n} and <= ${max}${n}`\n    }\n    throw new errors.ERR_OUT_OF_RANGE('value', range, value)\n  }\n  checkBounds(buf, offset, byteLength)\n}\n\nfunction validateNumber (value, name) {\n  if (typeof value !== 'number') {\n    throw new errors.ERR_INVALID_ARG_TYPE(name, 'number', value)\n  }\n}\n\nfunction boundsError (value, length, type) {\n  if (Math.floor(value) !== value) {\n    validateNumber(value, type)\n    throw new errors.ERR_OUT_OF_RANGE(type || 'offset', 'an integer', value)\n  }\n\n  if (length < 0) {\n    throw new errors.ERR_BUFFER_OUT_OF_BOUNDS()\n  }\n\n  throw new errors.ERR_OUT_OF_RANGE(type || 'offset',\n                                    `>= ${type ? 1 : 0} and <= ${length}`,\n                                    value)\n}\n\n// HELPER FUNCTIONS\n// ================\n\nconst INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g\n\nfunction base64clean (str) {\n  // Node takes equal signs as end of the Base64 encoding\n  str = str.split('=')[0]\n  // Node strips out invalid characters like \\n and \\t from the string, base64-js does not\n  str = str.trim().replace(INVALID_BASE64_RE, '')\n  // Node converts strings with length < 2 to ''\n  if (str.length < 2) return ''\n  // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not\n  while (str.length % 4 !== 0) {\n    str = str + '='\n  }\n  return str\n}\n\nfunction utf8ToBytes (string, units) {\n  units = units || Infinity\n  let codePoint\n  const length = string.length\n  let leadSurrogate = null\n  const bytes = []\n\n  for (let i = 0; i < length; ++i) {\n    codePoint = string.charCodeAt(i)\n\n    // is surrogate component\n    if (codePoint > 0xD7FF && codePoint < 0xE000) {\n      // last char was a lead\n      if (!leadSurrogate) {\n        // no lead yet\n        if (codePoint > 0xDBFF) {\n          // unexpected trail\n          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n          continue\n        } else if (i + 1 === length) {\n          // unpaired lead\n          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n          continue\n        }\n\n        // valid lead\n        leadSurrogate = codePoint\n\n        continue\n      }\n\n      // 2 leads in a row\n      if (codePoint < 0xDC00) {\n        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n        leadSurrogate = codePoint\n        continue\n      }\n\n      // valid surrogate pair\n      codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000\n    } else if (leadSurrogate) {\n      // valid bmp char, but last char was a lead\n      if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n    }\n\n    leadSurrogate = null\n\n    // encode utf8\n    if (codePoint < 0x80) {\n      if ((units -= 1) < 0) break\n      bytes.push(codePoint)\n    } else if (codePoint < 0x800) {\n      if ((units -= 2) < 0) break\n      bytes.push(\n        codePoint >> 0x6 | 0xC0,\n        codePoint & 0x3F | 0x80\n      )\n    } else if (codePoint < 0x10000) {\n      if ((units -= 3) < 0) break\n      bytes.push(\n        codePoint >> 0xC | 0xE0,\n        codePoint >> 0x6 & 0x3F | 0x80,\n        codePoint & 0x3F | 0x80\n      )\n    } else if (codePoint < 0x110000) {\n      if ((units -= 4) < 0) break\n      bytes.push(\n        codePoint >> 0x12 | 0xF0,\n        codePoint >> 0xC & 0x3F | 0x80,\n        codePoint >> 0x6 & 0x3F | 0x80,\n        codePoint & 0x3F | 0x80\n      )\n    } else {\n      throw new Error('Invalid code point')\n    }\n  }\n\n  return bytes\n}\n\nfunction asciiToBytes (str) {\n  const byteArray = []\n  for (let i = 0; i < str.length; ++i) {\n    // Node's code seems to be doing this and not & 0x7F..\n    byteArray.push(str.charCodeAt(i) & 0xFF)\n  }\n  return byteArray\n}\n\nfunction utf16leToBytes (str, units) {\n  let c, hi, lo\n  const byteArray = []\n  for (let i = 0; i < str.length; ++i) {\n    if ((units -= 2) < 0) break\n\n    c = str.charCodeAt(i)\n    hi = c >> 8\n    lo = c % 256\n    byteArray.push(lo)\n    byteArray.push(hi)\n  }\n\n  return byteArray\n}\n\nfunction base64ToBytes (str) {\n  return base64.toByteArray(base64clean(str))\n}\n\nfunction blitBuffer (src, dst, offset, length) {\n  let i\n  for (i = 0; i < length; ++i) {\n    if ((i + offset >= dst.length) || (i >= src.length)) break\n    dst[i + offset] = src[i]\n  }\n  return i\n}\n\n// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass\n// the `instanceof` check but they should be treated as of that type.\n// See: https://github.com/feross/buffer/issues/166\nfunction isInstance (obj, type) {\n  return obj instanceof type ||\n    (obj != null && obj.constructor != null && obj.constructor.name != null &&\n      obj.constructor.name === type.name)\n}\nfunction numberIsNaN (obj) {\n  // For IE11 support\n  return obj !== obj // eslint-disable-line no-self-compare\n}\n\n// Create lookup table for `toString('hex')`\n// See: https://github.com/feross/buffer/issues/219\nconst hexSliceLookupTable = (function () {\n  const alphabet = '0123456789abcdef'\n  const table = new Array(256)\n  for (let i = 0; i < 16; ++i) {\n    const i16 = i * 16\n    for (let j = 0; j < 16; ++j) {\n      table[i16 + j] = alphabet[i] + alphabet[j]\n    }\n  }\n  return table\n})()\n\n// Return not function with Error if BigInt not supported\nfunction defineBigIntMethod (fn) {\n  return typeof BigInt === 'undefined' ? BufferBigIntNotDefined : fn\n}\n\nfunction BufferBigIntNotDefined () {\n  throw new Error('BigInt not supported')\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYnVmZmVyL2luZGV4LmpzLmpzIiwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9idWZmZXIvaW5kZXguanM/YjYzOSJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAqIFRoZSBidWZmZXIgbW9kdWxlIGZyb20gbm9kZS5qcywgZm9yIHRoZSBicm93c2VyLlxuICpcbiAqIEBhdXRob3IgICBGZXJvc3MgQWJvdWtoYWRpamVoIDxodHRwczovL2Zlcm9zcy5vcmc+XG4gKiBAbGljZW5zZSAgTUlUXG4gKi9cbi8qIGVzbGludC1kaXNhYmxlIG5vLXByb3RvICovXG5cbid1c2Ugc3RyaWN0J1xuXG5jb25zdCBiYXNlNjQgPSByZXF1aXJlKCdiYXNlNjQtanMnKVxuY29uc3QgaWVlZTc1NCA9IHJlcXVpcmUoJ2llZWU3NTQnKVxuY29uc3QgY3VzdG9tSW5zcGVjdFN5bWJvbCA9XG4gICh0eXBlb2YgU3ltYm9sID09PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBTeW1ib2xbJ2ZvciddID09PSAnZnVuY3Rpb24nKSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGRvdC1ub3RhdGlvblxuICAgID8gU3ltYm9sWydmb3InXSgnbm9kZWpzLnV0aWwuaW5zcGVjdC5jdXN0b20nKSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGRvdC1ub3RhdGlvblxuICAgIDogbnVsbFxuXG5leHBvcnRzLkJ1ZmZlciA9IEJ1ZmZlclxuZXhwb3J0cy5TbG93QnVmZmVyID0gU2xvd0J1ZmZlclxuZXhwb3J0cy5JTlNQRUNUX01BWF9CWVRFUyA9IDUwXG5cbmNvbnN0IEtfTUFYX0xFTkdUSCA9IDB4N2ZmZmZmZmZcbmV4cG9ydHMua01heExlbmd0aCA9IEtfTUFYX0xFTkdUSFxuXG4vKipcbiAqIElmIGBCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVGA6XG4gKiAgID09PSB0cnVlICAgIFVzZSBVaW50OEFycmF5IGltcGxlbWVudGF0aW9uIChmYXN0ZXN0KVxuICogICA9PT0gZmFsc2UgICBQcmludCB3YXJuaW5nIGFuZCByZWNvbW1lbmQgdXNpbmcgYGJ1ZmZlcmAgdjQueCB3aGljaCBoYXMgYW4gT2JqZWN0XG4gKiAgICAgICAgICAgICAgIGltcGxlbWVudGF0aW9uIChtb3N0IGNvbXBhdGlibGUsIGV2ZW4gSUU2KVxuICpcbiAqIEJyb3dzZXJzIHRoYXQgc3VwcG9ydCB0eXBlZCBhcnJheXMgYXJlIElFIDEwKywgRmlyZWZveCA0KywgQ2hyb21lIDcrLCBTYWZhcmkgNS4xKyxcbiAqIE9wZXJhIDExLjYrLCBpT1MgNC4yKy5cbiAqXG4gKiBXZSByZXBvcnQgdGhhdCB0aGUgYnJvd3NlciBkb2VzIG5vdCBzdXBwb3J0IHR5cGVkIGFycmF5cyBpZiB0aGUgYXJlIG5vdCBzdWJjbGFzc2FibGVcbiAqIHVzaW5nIF9fcHJvdG9fXy4gRmlyZWZveCA0LTI5IGxhY2tzIHN1cHBvcnQgZm9yIGFkZGluZyBuZXcgcHJvcGVydGllcyB0byBgVWludDhBcnJheWBcbiAqIChTZWU6IGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTY5NTQzOCkuIElFIDEwIGxhY2tzIHN1cHBvcnRcbiAqIGZvciBfX3Byb3RvX18gYW5kIGhhcyBhIGJ1Z2d5IHR5cGVkIGFycmF5IGltcGxlbWVudGF0aW9uLlxuICovXG5CdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCA9IHR5cGVkQXJyYXlTdXBwb3J0KClcblxuaWYgKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCAmJiB0eXBlb2YgY29uc29sZSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICB0eXBlb2YgY29uc29sZS5lcnJvciA9PT0gJ2Z1bmN0aW9uJykge1xuICBjb25zb2xlLmVycm9yKFxuICAgICdUaGlzIGJyb3dzZXIgbGFja3MgdHlwZWQgYXJyYXkgKFVpbnQ4QXJyYXkpIHN1cHBvcnQgd2hpY2ggaXMgcmVxdWlyZWQgYnkgJyArXG4gICAgJ2BidWZmZXJgIHY1LnguIFVzZSBgYnVmZmVyYCB2NC54IGlmIHlvdSByZXF1aXJlIG9sZCBicm93c2VyIHN1cHBvcnQuJ1xuICApXG59XG5cbmZ1bmN0aW9uIHR5cGVkQXJyYXlTdXBwb3J0ICgpIHtcbiAgLy8gQ2FuIHR5cGVkIGFycmF5IGluc3RhbmNlcyBjYW4gYmUgYXVnbWVudGVkP1xuICB0cnkge1xuICAgIGNvbnN0IGFyciA9IG5ldyBVaW50OEFycmF5KDEpXG4gICAgY29uc3QgcHJvdG8gPSB7IGZvbzogZnVuY3Rpb24gKCkgeyByZXR1cm4gNDIgfSB9XG4gICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKHByb3RvLCBVaW50OEFycmF5LnByb3RvdHlwZSlcbiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YoYXJyLCBwcm90bylcbiAgICByZXR1cm4gYXJyLmZvbygpID09PSA0MlxuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbn1cblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KEJ1ZmZlci5wcm90b3R5cGUsICdwYXJlbnQnLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gKCkge1xuICAgIGlmICghQnVmZmVyLmlzQnVmZmVyKHRoaXMpKSByZXR1cm4gdW5kZWZpbmVkXG4gICAgcmV0dXJuIHRoaXMuYnVmZmVyXG4gIH1cbn0pXG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShCdWZmZXIucHJvdG90eXBlLCAnb2Zmc2V0Jywge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcih0aGlzKSkgcmV0dXJuIHVuZGVmaW5lZFxuICAgIHJldHVybiB0aGlzLmJ5dGVPZmZzZXRcbiAgfVxufSlcblxuZnVuY3Rpb24gY3JlYXRlQnVmZmVyIChsZW5ndGgpIHtcbiAgaWYgKGxlbmd0aCA+IEtfTUFYX0xFTkdUSCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdUaGUgdmFsdWUgXCInICsgbGVuZ3RoICsgJ1wiIGlzIGludmFsaWQgZm9yIG9wdGlvbiBcInNpemVcIicpXG4gIH1cbiAgLy8gUmV0dXJuIGFuIGF1Z21lbnRlZCBgVWludDhBcnJheWAgaW5zdGFuY2VcbiAgY29uc3QgYnVmID0gbmV3IFVpbnQ4QXJyYXkobGVuZ3RoKVxuICBPYmplY3Quc2V0UHJvdG90eXBlT2YoYnVmLCBCdWZmZXIucHJvdG90eXBlKVxuICByZXR1cm4gYnVmXG59XG5cbi8qKlxuICogVGhlIEJ1ZmZlciBjb25zdHJ1Y3RvciByZXR1cm5zIGluc3RhbmNlcyBvZiBgVWludDhBcnJheWAgdGhhdCBoYXZlIHRoZWlyXG4gKiBwcm90b3R5cGUgY2hhbmdlZCB0byBgQnVmZmVyLnByb3RvdHlwZWAuIEZ1cnRoZXJtb3JlLCBgQnVmZmVyYCBpcyBhIHN1YmNsYXNzIG9mXG4gKiBgVWludDhBcnJheWAsIHNvIHRoZSByZXR1cm5lZCBpbnN0YW5jZXMgd2lsbCBoYXZlIGFsbCB0aGUgbm9kZSBgQnVmZmVyYCBtZXRob2RzXG4gKiBhbmQgdGhlIGBVaW50OEFycmF5YCBtZXRob2RzLiBTcXVhcmUgYnJhY2tldCBub3RhdGlvbiB3b3JrcyBhcyBleHBlY3RlZCAtLSBpdFxuICogcmV0dXJucyBhIHNpbmdsZSBvY3RldC5cbiAqXG4gKiBUaGUgYFVpbnQ4QXJyYXlgIHByb3RvdHlwZSByZW1haW5zIHVubW9kaWZpZWQuXG4gKi9cblxuZnVuY3Rpb24gQnVmZmVyIChhcmcsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aCkge1xuICAvLyBDb21tb24gY2FzZS5cbiAgaWYgKHR5cGVvZiBhcmcgPT09ICdudW1iZXInKSB7XG4gICAgaWYgKHR5cGVvZiBlbmNvZGluZ09yT2Zmc2V0ID09PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICAgJ1RoZSBcInN0cmluZ1wiIGFyZ3VtZW50IG11c3QgYmUgb2YgdHlwZSBzdHJpbmcuIFJlY2VpdmVkIHR5cGUgbnVtYmVyJ1xuICAgICAgKVxuICAgIH1cbiAgICByZXR1cm4gYWxsb2NVbnNhZmUoYXJnKVxuICB9XG4gIHJldHVybiBmcm9tKGFyZywgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKVxufVxuXG5CdWZmZXIucG9vbFNpemUgPSA4MTkyIC8vIG5vdCB1c2VkIGJ5IHRoaXMgaW1wbGVtZW50YXRpb25cblxuZnVuY3Rpb24gZnJvbSAodmFsdWUsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aCkge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBmcm9tU3RyaW5nKHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0KVxuICB9XG5cbiAgaWYgKEFycmF5QnVmZmVyLmlzVmlldyh2YWx1ZSkpIHtcbiAgICByZXR1cm4gZnJvbUFycmF5Vmlldyh2YWx1ZSlcbiAgfVxuXG4gIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdUaGUgZmlyc3QgYXJndW1lbnQgbXVzdCBiZSBvbmUgb2YgdHlwZSBzdHJpbmcsIEJ1ZmZlciwgQXJyYXlCdWZmZXIsIEFycmF5LCAnICtcbiAgICAgICdvciBBcnJheS1saWtlIE9iamVjdC4gUmVjZWl2ZWQgdHlwZSAnICsgKHR5cGVvZiB2YWx1ZSlcbiAgICApXG4gIH1cblxuICBpZiAoaXNJbnN0YW5jZSh2YWx1ZSwgQXJyYXlCdWZmZXIpIHx8XG4gICAgICAodmFsdWUgJiYgaXNJbnN0YW5jZSh2YWx1ZS5idWZmZXIsIEFycmF5QnVmZmVyKSkpIHtcbiAgICByZXR1cm4gZnJvbUFycmF5QnVmZmVyKHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpXG4gIH1cblxuICBpZiAodHlwZW9mIFNoYXJlZEFycmF5QnVmZmVyICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgKGlzSW5zdGFuY2UodmFsdWUsIFNoYXJlZEFycmF5QnVmZmVyKSB8fFxuICAgICAgKHZhbHVlICYmIGlzSW5zdGFuY2UodmFsdWUuYnVmZmVyLCBTaGFyZWRBcnJheUJ1ZmZlcikpKSkge1xuICAgIHJldHVybiBmcm9tQXJyYXlCdWZmZXIodmFsdWUsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aClcbiAgfVxuXG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdUaGUgXCJ2YWx1ZVwiIGFyZ3VtZW50IG11c3Qgbm90IGJlIG9mIHR5cGUgbnVtYmVyLiBSZWNlaXZlZCB0eXBlIG51bWJlcidcbiAgICApXG4gIH1cblxuICBjb25zdCB2YWx1ZU9mID0gdmFsdWUudmFsdWVPZiAmJiB2YWx1ZS52YWx1ZU9mKClcbiAgaWYgKHZhbHVlT2YgIT0gbnVsbCAmJiB2YWx1ZU9mICE9PSB2YWx1ZSkge1xuICAgIHJldHVybiBCdWZmZXIuZnJvbSh2YWx1ZU9mLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpXG4gIH1cblxuICBjb25zdCBiID0gZnJvbU9iamVjdCh2YWx1ZSlcbiAgaWYgKGIpIHJldHVybiBiXG5cbiAgaWYgKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1ByaW1pdGl2ZSAhPSBudWxsICYmXG4gICAgICB0eXBlb2YgdmFsdWVbU3ltYm9sLnRvUHJpbWl0aXZlXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBCdWZmZXIuZnJvbSh2YWx1ZVtTeW1ib2wudG9QcmltaXRpdmVdKCdzdHJpbmcnKSwgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKVxuICB9XG5cbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAnVGhlIGZpcnN0IGFyZ3VtZW50IG11c3QgYmUgb25lIG9mIHR5cGUgc3RyaW5nLCBCdWZmZXIsIEFycmF5QnVmZmVyLCBBcnJheSwgJyArXG4gICAgJ29yIEFycmF5LWxpa2UgT2JqZWN0LiBSZWNlaXZlZCB0eXBlICcgKyAodHlwZW9mIHZhbHVlKVxuICApXG59XG5cbi8qKlxuICogRnVuY3Rpb25hbGx5IGVxdWl2YWxlbnQgdG8gQnVmZmVyKGFyZywgZW5jb2RpbmcpIGJ1dCB0aHJvd3MgYSBUeXBlRXJyb3JcbiAqIGlmIHZhbHVlIGlzIGEgbnVtYmVyLlxuICogQnVmZmVyLmZyb20oc3RyWywgZW5jb2RpbmddKVxuICogQnVmZmVyLmZyb20oYXJyYXkpXG4gKiBCdWZmZXIuZnJvbShidWZmZXIpXG4gKiBCdWZmZXIuZnJvbShhcnJheUJ1ZmZlclssIGJ5dGVPZmZzZXRbLCBsZW5ndGhdXSlcbiAqKi9cbkJ1ZmZlci5mcm9tID0gZnVuY3Rpb24gKHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGZyb20odmFsdWUsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aClcbn1cblxuLy8gTm90ZTogQ2hhbmdlIHByb3RvdHlwZSAqYWZ0ZXIqIEJ1ZmZlci5mcm9tIGlzIGRlZmluZWQgdG8gd29ya2Fyb3VuZCBDaHJvbWUgYnVnOlxuLy8gaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXIvcHVsbC8xNDhcbk9iamVjdC5zZXRQcm90b3R5cGVPZihCdWZmZXIucHJvdG90eXBlLCBVaW50OEFycmF5LnByb3RvdHlwZSlcbk9iamVjdC5zZXRQcm90b3R5cGVPZihCdWZmZXIsIFVpbnQ4QXJyYXkpXG5cbmZ1bmN0aW9uIGFzc2VydFNpemUgKHNpemUpIHtcbiAgaWYgKHR5cGVvZiBzaXplICE9PSAnbnVtYmVyJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wic2l6ZVwiIGFyZ3VtZW50IG11c3QgYmUgb2YgdHlwZSBudW1iZXInKVxuICB9IGVsc2UgaWYgKHNpemUgPCAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1RoZSB2YWx1ZSBcIicgKyBzaXplICsgJ1wiIGlzIGludmFsaWQgZm9yIG9wdGlvbiBcInNpemVcIicpXG4gIH1cbn1cblxuZnVuY3Rpb24gYWxsb2MgKHNpemUsIGZpbGwsIGVuY29kaW5nKSB7XG4gIGFzc2VydFNpemUoc2l6ZSlcbiAgaWYgKHNpemUgPD0gMCkge1xuICAgIHJldHVybiBjcmVhdGVCdWZmZXIoc2l6ZSlcbiAgfVxuICBpZiAoZmlsbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgLy8gT25seSBwYXkgYXR0ZW50aW9uIHRvIGVuY29kaW5nIGlmIGl0J3MgYSBzdHJpbmcuIFRoaXNcbiAgICAvLyBwcmV2ZW50cyBhY2NpZGVudGFsbHkgc2VuZGluZyBpbiBhIG51bWJlciB0aGF0IHdvdWxkXG4gICAgLy8gYmUgaW50ZXJwcmV0ZWQgYXMgYSBzdGFydCBvZmZzZXQuXG4gICAgcmV0dXJuIHR5cGVvZiBlbmNvZGluZyA9PT0gJ3N0cmluZydcbiAgICAgID8gY3JlYXRlQnVmZmVyKHNpemUpLmZpbGwoZmlsbCwgZW5jb2RpbmcpXG4gICAgICA6IGNyZWF0ZUJ1ZmZlcihzaXplKS5maWxsKGZpbGwpXG4gIH1cbiAgcmV0dXJuIGNyZWF0ZUJ1ZmZlcihzaXplKVxufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgZmlsbGVkIEJ1ZmZlciBpbnN0YW5jZS5cbiAqIGFsbG9jKHNpemVbLCBmaWxsWywgZW5jb2RpbmddXSlcbiAqKi9cbkJ1ZmZlci5hbGxvYyA9IGZ1bmN0aW9uIChzaXplLCBmaWxsLCBlbmNvZGluZykge1xuICByZXR1cm4gYWxsb2Moc2l6ZSwgZmlsbCwgZW5jb2RpbmcpXG59XG5cbmZ1bmN0aW9uIGFsbG9jVW5zYWZlIChzaXplKSB7XG4gIGFzc2VydFNpemUoc2l6ZSlcbiAgcmV0dXJuIGNyZWF0ZUJ1ZmZlcihzaXplIDwgMCA/IDAgOiBjaGVja2VkKHNpemUpIHwgMClcbn1cblxuLyoqXG4gKiBFcXVpdmFsZW50IHRvIEJ1ZmZlcihudW0pLCBieSBkZWZhdWx0IGNyZWF0ZXMgYSBub24temVyby1maWxsZWQgQnVmZmVyIGluc3RhbmNlLlxuICogKi9cbkJ1ZmZlci5hbGxvY1Vuc2FmZSA9IGZ1bmN0aW9uIChzaXplKSB7XG4gIHJldHVybiBhbGxvY1Vuc2FmZShzaXplKVxufVxuLyoqXG4gKiBFcXVpdmFsZW50IHRvIFNsb3dCdWZmZXIobnVtKSwgYnkgZGVmYXVsdCBjcmVhdGVzIGEgbm9uLXplcm8tZmlsbGVkIEJ1ZmZlciBpbnN0YW5jZS5cbiAqL1xuQnVmZmVyLmFsbG9jVW5zYWZlU2xvdyA9IGZ1bmN0aW9uIChzaXplKSB7XG4gIHJldHVybiBhbGxvY1Vuc2FmZShzaXplKVxufVxuXG5mdW5jdGlvbiBmcm9tU3RyaW5nIChzdHJpbmcsIGVuY29kaW5nKSB7XG4gIGlmICh0eXBlb2YgZW5jb2RpbmcgIT09ICdzdHJpbmcnIHx8IGVuY29kaW5nID09PSAnJykge1xuICAgIGVuY29kaW5nID0gJ3V0ZjgnXG4gIH1cblxuICBpZiAoIUJ1ZmZlci5pc0VuY29kaW5nKGVuY29kaW5nKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBlbmNvZGluZylcbiAgfVxuXG4gIGNvbnN0IGxlbmd0aCA9IGJ5dGVMZW5ndGgoc3RyaW5nLCBlbmNvZGluZykgfCAwXG4gIGxldCBidWYgPSBjcmVhdGVCdWZmZXIobGVuZ3RoKVxuXG4gIGNvbnN0IGFjdHVhbCA9IGJ1Zi53cml0ZShzdHJpbmcsIGVuY29kaW5nKVxuXG4gIGlmIChhY3R1YWwgIT09IGxlbmd0aCkge1xuICAgIC8vIFdyaXRpbmcgYSBoZXggc3RyaW5nLCBmb3IgZXhhbXBsZSwgdGhhdCBjb250YWlucyBpbnZhbGlkIGNoYXJhY3RlcnMgd2lsbFxuICAgIC8vIGNhdXNlIGV2ZXJ5dGhpbmcgYWZ0ZXIgdGhlIGZpcnN0IGludmFsaWQgY2hhcmFjdGVyIHRvIGJlIGlnbm9yZWQuIChlLmcuXG4gICAgLy8gJ2FieHhjZCcgd2lsbCBiZSB0cmVhdGVkIGFzICdhYicpXG4gICAgYnVmID0gYnVmLnNsaWNlKDAsIGFjdHVhbClcbiAgfVxuXG4gIHJldHVybiBidWZcbn1cblxuZnVuY3Rpb24gZnJvbUFycmF5TGlrZSAoYXJyYXkpIHtcbiAgY29uc3QgbGVuZ3RoID0gYXJyYXkubGVuZ3RoIDwgMCA/IDAgOiBjaGVja2VkKGFycmF5Lmxlbmd0aCkgfCAwXG4gIGNvbnN0IGJ1ZiA9IGNyZWF0ZUJ1ZmZlcihsZW5ndGgpXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDEpIHtcbiAgICBidWZbaV0gPSBhcnJheVtpXSAmIDI1NVxuICB9XG4gIHJldHVybiBidWZcbn1cblxuZnVuY3Rpb24gZnJvbUFycmF5VmlldyAoYXJyYXlWaWV3KSB7XG4gIGlmIChpc0luc3RhbmNlKGFycmF5VmlldywgVWludDhBcnJheSkpIHtcbiAgICBjb25zdCBjb3B5ID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXlWaWV3KVxuICAgIHJldHVybiBmcm9tQXJyYXlCdWZmZXIoY29weS5idWZmZXIsIGNvcHkuYnl0ZU9mZnNldCwgY29weS5ieXRlTGVuZ3RoKVxuICB9XG4gIHJldHVybiBmcm9tQXJyYXlMaWtlKGFycmF5Vmlldylcbn1cblxuZnVuY3Rpb24gZnJvbUFycmF5QnVmZmVyIChhcnJheSwgYnl0ZU9mZnNldCwgbGVuZ3RoKSB7XG4gIGlmIChieXRlT2Zmc2V0IDwgMCB8fCBhcnJheS5ieXRlTGVuZ3RoIDwgYnl0ZU9mZnNldCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdcIm9mZnNldFwiIGlzIG91dHNpZGUgb2YgYnVmZmVyIGJvdW5kcycpXG4gIH1cblxuICBpZiAoYXJyYXkuYnl0ZUxlbmd0aCA8IGJ5dGVPZmZzZXQgKyAobGVuZ3RoIHx8IDApKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1wibGVuZ3RoXCIgaXMgb3V0c2lkZSBvZiBidWZmZXIgYm91bmRzJylcbiAgfVxuXG4gIGxldCBidWZcbiAgaWYgKGJ5dGVPZmZzZXQgPT09IHVuZGVmaW5lZCAmJiBsZW5ndGggPT09IHVuZGVmaW5lZCkge1xuICAgIGJ1ZiA9IG5ldyBVaW50OEFycmF5KGFycmF5KVxuICB9IGVsc2UgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgYnVmID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXksIGJ5dGVPZmZzZXQpXG4gIH0gZWxzZSB7XG4gICAgYnVmID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXksIGJ5dGVPZmZzZXQsIGxlbmd0aClcbiAgfVxuXG4gIC8vIFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlXG4gIE9iamVjdC5zZXRQcm90b3R5cGVPZihidWYsIEJ1ZmZlci5wcm90b3R5cGUpXG5cbiAgcmV0dXJuIGJ1ZlxufVxuXG5mdW5jdGlvbiBmcm9tT2JqZWN0IChvYmopIHtcbiAgaWYgKEJ1ZmZlci5pc0J1ZmZlcihvYmopKSB7XG4gICAgY29uc3QgbGVuID0gY2hlY2tlZChvYmoubGVuZ3RoKSB8IDBcbiAgICBjb25zdCBidWYgPSBjcmVhdGVCdWZmZXIobGVuKVxuXG4gICAgaWYgKGJ1Zi5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBidWZcbiAgICB9XG5cbiAgICBvYmouY29weShidWYsIDAsIDAsIGxlbilcbiAgICByZXR1cm4gYnVmXG4gIH1cblxuICBpZiAob2JqLmxlbmd0aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgaWYgKHR5cGVvZiBvYmoubGVuZ3RoICE9PSAnbnVtYmVyJyB8fCBudW1iZXJJc05hTihvYmoubGVuZ3RoKSkge1xuICAgICAgcmV0dXJuIGNyZWF0ZUJ1ZmZlcigwKVxuICAgIH1cbiAgICByZXR1cm4gZnJvbUFycmF5TGlrZShvYmopXG4gIH1cblxuICBpZiAob2JqLnR5cGUgPT09ICdCdWZmZXInICYmIEFycmF5LmlzQXJyYXkob2JqLmRhdGEpKSB7XG4gICAgcmV0dXJuIGZyb21BcnJheUxpa2Uob2JqLmRhdGEpXG4gIH1cbn1cblxuZnVuY3Rpb24gY2hlY2tlZCAobGVuZ3RoKSB7XG4gIC8vIE5vdGU6IGNhbm5vdCB1c2UgYGxlbmd0aCA8IEtfTUFYX0xFTkdUSGAgaGVyZSBiZWNhdXNlIHRoYXQgZmFpbHMgd2hlblxuICAvLyBsZW5ndGggaXMgTmFOICh3aGljaCBpcyBvdGhlcndpc2UgY29lcmNlZCB0byB6ZXJvLilcbiAgaWYgKGxlbmd0aCA+PSBLX01BWF9MRU5HVEgpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignQXR0ZW1wdCB0byBhbGxvY2F0ZSBCdWZmZXIgbGFyZ2VyIHRoYW4gbWF4aW11bSAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAnc2l6ZTogMHgnICsgS19NQVhfTEVOR1RILnRvU3RyaW5nKDE2KSArICcgYnl0ZXMnKVxuICB9XG4gIHJldHVybiBsZW5ndGggfCAwXG59XG5cbmZ1bmN0aW9uIFNsb3dCdWZmZXIgKGxlbmd0aCkge1xuICBpZiAoK2xlbmd0aCAhPSBsZW5ndGgpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBlcWVxZXFcbiAgICBsZW5ndGggPSAwXG4gIH1cbiAgcmV0dXJuIEJ1ZmZlci5hbGxvYygrbGVuZ3RoKVxufVxuXG5CdWZmZXIuaXNCdWZmZXIgPSBmdW5jdGlvbiBpc0J1ZmZlciAoYikge1xuICByZXR1cm4gYiAhPSBudWxsICYmIGIuX2lzQnVmZmVyID09PSB0cnVlICYmXG4gICAgYiAhPT0gQnVmZmVyLnByb3RvdHlwZSAvLyBzbyBCdWZmZXIuaXNCdWZmZXIoQnVmZmVyLnByb3RvdHlwZSkgd2lsbCBiZSBmYWxzZVxufVxuXG5CdWZmZXIuY29tcGFyZSA9IGZ1bmN0aW9uIGNvbXBhcmUgKGEsIGIpIHtcbiAgaWYgKGlzSW5zdGFuY2UoYSwgVWludDhBcnJheSkpIGEgPSBCdWZmZXIuZnJvbShhLCBhLm9mZnNldCwgYS5ieXRlTGVuZ3RoKVxuICBpZiAoaXNJbnN0YW5jZShiLCBVaW50OEFycmF5KSkgYiA9IEJ1ZmZlci5mcm9tKGIsIGIub2Zmc2V0LCBiLmJ5dGVMZW5ndGgpXG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGEpIHx8ICFCdWZmZXIuaXNCdWZmZXIoYikpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ1RoZSBcImJ1ZjFcIiwgXCJidWYyXCIgYXJndW1lbnRzIG11c3QgYmUgb25lIG9mIHR5cGUgQnVmZmVyIG9yIFVpbnQ4QXJyYXknXG4gICAgKVxuICB9XG5cbiAgaWYgKGEgPT09IGIpIHJldHVybiAwXG5cbiAgbGV0IHggPSBhLmxlbmd0aFxuICBsZXQgeSA9IGIubGVuZ3RoXG5cbiAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IE1hdGgubWluKHgsIHkpOyBpIDwgbGVuOyArK2kpIHtcbiAgICBpZiAoYVtpXSAhPT0gYltpXSkge1xuICAgICAgeCA9IGFbaV1cbiAgICAgIHkgPSBiW2ldXG4gICAgICBicmVha1xuICAgIH1cbiAgfVxuXG4gIGlmICh4IDwgeSkgcmV0dXJuIC0xXG4gIGlmICh5IDwgeCkgcmV0dXJuIDFcbiAgcmV0dXJuIDBcbn1cblxuQnVmZmVyLmlzRW5jb2RpbmcgPSBmdW5jdGlvbiBpc0VuY29kaW5nIChlbmNvZGluZykge1xuICBzd2l0Y2ggKFN0cmluZyhlbmNvZGluZykudG9Mb3dlckNhc2UoKSkge1xuICAgIGNhc2UgJ2hleCc6XG4gICAgY2FzZSAndXRmOCc6XG4gICAgY2FzZSAndXRmLTgnOlxuICAgIGNhc2UgJ2FzY2lpJzpcbiAgICBjYXNlICdsYXRpbjEnOlxuICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgY2FzZSAnYmFzZTY0JzpcbiAgICBjYXNlICd1Y3MyJzpcbiAgICBjYXNlICd1Y3MtMic6XG4gICAgY2FzZSAndXRmMTZsZSc6XG4gICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgcmV0dXJuIHRydWVcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGZhbHNlXG4gIH1cbn1cblxuQnVmZmVyLmNvbmNhdCA9IGZ1bmN0aW9uIGNvbmNhdCAobGlzdCwgbGVuZ3RoKSB7XG4gIGlmICghQXJyYXkuaXNBcnJheShsaXN0KSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdFwiIGFyZ3VtZW50IG11c3QgYmUgYW4gQXJyYXkgb2YgQnVmZmVycycpXG4gIH1cblxuICBpZiAobGlzdC5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gQnVmZmVyLmFsbG9jKDApXG4gIH1cblxuICBsZXQgaVxuICBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQpIHtcbiAgICBsZW5ndGggPSAwXG4gICAgZm9yIChpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyArK2kpIHtcbiAgICAgIGxlbmd0aCArPSBsaXN0W2ldLmxlbmd0aFxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5hbGxvY1Vuc2FmZShsZW5ndGgpXG4gIGxldCBwb3MgPSAwXG4gIGZvciAoaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgKytpKSB7XG4gICAgbGV0IGJ1ZiA9IGxpc3RbaV1cbiAgICBpZiAoaXNJbnN0YW5jZShidWYsIFVpbnQ4QXJyYXkpKSB7XG4gICAgICBpZiAocG9zICsgYnVmLmxlbmd0aCA+IGJ1ZmZlci5sZW5ndGgpIHtcbiAgICAgICAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYnVmKSkgYnVmID0gQnVmZmVyLmZyb20oYnVmKVxuICAgICAgICBidWYuY29weShidWZmZXIsIHBvcylcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIFVpbnQ4QXJyYXkucHJvdG90eXBlLnNldC5jYWxsKFxuICAgICAgICAgIGJ1ZmZlcixcbiAgICAgICAgICBidWYsXG4gICAgICAgICAgcG9zXG4gICAgICAgIClcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYnVmKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0XCIgYXJndW1lbnQgbXVzdCBiZSBhbiBBcnJheSBvZiBCdWZmZXJzJylcbiAgICB9IGVsc2Uge1xuICAgICAgYnVmLmNvcHkoYnVmZmVyLCBwb3MpXG4gICAgfVxuICAgIHBvcyArPSBidWYubGVuZ3RoXG4gIH1cbiAgcmV0dXJuIGJ1ZmZlclxufVxuXG5mdW5jdGlvbiBieXRlTGVuZ3RoIChzdHJpbmcsIGVuY29kaW5nKSB7XG4gIGlmIChCdWZmZXIuaXNCdWZmZXIoc3RyaW5nKSkge1xuICAgIHJldHVybiBzdHJpbmcubGVuZ3RoXG4gIH1cbiAgaWYgKEFycmF5QnVmZmVyLmlzVmlldyhzdHJpbmcpIHx8IGlzSW5zdGFuY2Uoc3RyaW5nLCBBcnJheUJ1ZmZlcikpIHtcbiAgICByZXR1cm4gc3RyaW5nLmJ5dGVMZW5ndGhcbiAgfVxuICBpZiAodHlwZW9mIHN0cmluZyAhPT0gJ3N0cmluZycpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ1RoZSBcInN0cmluZ1wiIGFyZ3VtZW50IG11c3QgYmUgb25lIG9mIHR5cGUgc3RyaW5nLCBCdWZmZXIsIG9yIEFycmF5QnVmZmVyLiAnICtcbiAgICAgICdSZWNlaXZlZCB0eXBlICcgKyB0eXBlb2Ygc3RyaW5nXG4gICAgKVxuICB9XG5cbiAgY29uc3QgbGVuID0gc3RyaW5nLmxlbmd0aFxuICBjb25zdCBtdXN0TWF0Y2ggPSAoYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdID09PSB0cnVlKVxuICBpZiAoIW11c3RNYXRjaCAmJiBsZW4gPT09IDApIHJldHVybiAwXG5cbiAgLy8gVXNlIGEgZm9yIGxvb3AgdG8gYXZvaWQgcmVjdXJzaW9uXG4gIGxldCBsb3dlcmVkQ2FzZSA9IGZhbHNlXG4gIGZvciAoOzspIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdhc2NpaSc6XG4gICAgICBjYXNlICdsYXRpbjEnOlxuICAgICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgICAgcmV0dXJuIGxlblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICAgIHJldHVybiB1dGY4VG9CeXRlcyhzdHJpbmcpLmxlbmd0aFxuICAgICAgY2FzZSAndWNzMic6XG4gICAgICBjYXNlICd1Y3MtMic6XG4gICAgICBjYXNlICd1dGYxNmxlJzpcbiAgICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgICAgcmV0dXJuIGxlbiAqIDJcbiAgICAgIGNhc2UgJ2hleCc6XG4gICAgICAgIHJldHVybiBsZW4gPj4+IDFcbiAgICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICAgIHJldHVybiBiYXNlNjRUb0J5dGVzKHN0cmluZykubGVuZ3RoXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBpZiAobG93ZXJlZENhc2UpIHtcbiAgICAgICAgICByZXR1cm4gbXVzdE1hdGNoID8gLTEgOiB1dGY4VG9CeXRlcyhzdHJpbmcpLmxlbmd0aCAvLyBhc3N1bWUgdXRmOFxuICAgICAgICB9XG4gICAgICAgIGVuY29kaW5nID0gKCcnICsgZW5jb2RpbmcpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5CdWZmZXIuYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGhcblxuZnVuY3Rpb24gc2xvd1RvU3RyaW5nIChlbmNvZGluZywgc3RhcnQsIGVuZCkge1xuICBsZXQgbG93ZXJlZENhc2UgPSBmYWxzZVxuXG4gIC8vIE5vIG5lZWQgdG8gdmVyaWZ5IHRoYXQgXCJ0aGlzLmxlbmd0aCA8PSBNQVhfVUlOVDMyXCIgc2luY2UgaXQncyBhIHJlYWQtb25seVxuICAvLyBwcm9wZXJ0eSBvZiBhIHR5cGVkIGFycmF5LlxuXG4gIC8vIFRoaXMgYmVoYXZlcyBuZWl0aGVyIGxpa2UgU3RyaW5nIG5vciBVaW50OEFycmF5IGluIHRoYXQgd2Ugc2V0IHN0YXJ0L2VuZFxuICAvLyB0byB0aGVpciB1cHBlci9sb3dlciBib3VuZHMgaWYgdGhlIHZhbHVlIHBhc3NlZCBpcyBvdXQgb2YgcmFuZ2UuXG4gIC8vIHVuZGVmaW5lZCBpcyBoYW5kbGVkIHNwZWNpYWxseSBhcyBwZXIgRUNNQS0yNjIgNnRoIEVkaXRpb24sXG4gIC8vIFNlY3Rpb24gMTMuMy4zLjcgUnVudGltZSBTZW1hbnRpY3M6IEtleWVkQmluZGluZ0luaXRpYWxpemF0aW9uLlxuICBpZiAoc3RhcnQgPT09IHVuZGVmaW5lZCB8fCBzdGFydCA8IDApIHtcbiAgICBzdGFydCA9IDBcbiAgfVxuICAvLyBSZXR1cm4gZWFybHkgaWYgc3RhcnQgPiB0aGlzLmxlbmd0aC4gRG9uZSBoZXJlIHRvIHByZXZlbnQgcG90ZW50aWFsIHVpbnQzMlxuICAvLyBjb2VyY2lvbiBmYWlsIGJlbG93LlxuICBpZiAoc3RhcnQgPiB0aGlzLmxlbmd0aCkge1xuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgaWYgKGVuZCA9PT0gdW5kZWZpbmVkIHx8IGVuZCA+IHRoaXMubGVuZ3RoKSB7XG4gICAgZW5kID0gdGhpcy5sZW5ndGhcbiAgfVxuXG4gIGlmIChlbmQgPD0gMCkge1xuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgLy8gRm9yY2UgY29lcmNpb24gdG8gdWludDMyLiBUaGlzIHdpbGwgYWxzbyBjb2VyY2UgZmFsc2V5L05hTiB2YWx1ZXMgdG8gMC5cbiAgZW5kID4+Pj0gMFxuICBzdGFydCA+Pj49IDBcblxuICBpZiAoZW5kIDw9IHN0YXJ0KSB7XG4gICAgcmV0dXJuICcnXG4gIH1cblxuICBpZiAoIWVuY29kaW5nKSBlbmNvZGluZyA9ICd1dGY4J1xuXG4gIHdoaWxlICh0cnVlKSB7XG4gICAgc3dpdGNoIChlbmNvZGluZykge1xuICAgICAgY2FzZSAnaGV4JzpcbiAgICAgICAgcmV0dXJuIGhleFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgY2FzZSAndXRmLTgnOlxuICAgICAgICByZXR1cm4gdXRmOFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgICAgcmV0dXJuIGFzY2lpU2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnbGF0aW4xJzpcbiAgICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICAgIHJldHVybiBsYXRpbjFTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgICByZXR1cm4gYmFzZTY0U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAndWNzMic6XG4gICAgICBjYXNlICd1Y3MtMic6XG4gICAgICBjYXNlICd1dGYxNmxlJzpcbiAgICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgICAgcmV0dXJuIHV0ZjE2bGVTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBpZiAobG93ZXJlZENhc2UpIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBlbmNvZGluZylcbiAgICAgICAgZW5jb2RpbmcgPSAoZW5jb2RpbmcgKyAnJykudG9Mb3dlckNhc2UoKVxuICAgICAgICBsb3dlcmVkQ2FzZSA9IHRydWVcbiAgICB9XG4gIH1cbn1cblxuLy8gVGhpcyBwcm9wZXJ0eSBpcyB1c2VkIGJ5IGBCdWZmZXIuaXNCdWZmZXJgIChhbmQgdGhlIGBpcy1idWZmZXJgIG5wbSBwYWNrYWdlKVxuLy8gdG8gZGV0ZWN0IGEgQnVmZmVyIGluc3RhbmNlLiBJdCdzIG5vdCBwb3NzaWJsZSB0byB1c2UgYGluc3RhbmNlb2YgQnVmZmVyYFxuLy8gcmVsaWFibHkgaW4gYSBicm93c2VyaWZ5IGNvbnRleHQgYmVjYXVzZSB0aGVyZSBjb3VsZCBiZSBtdWx0aXBsZSBkaWZmZXJlbnRcbi8vIGNvcGllcyBvZiB0aGUgJ2J1ZmZlcicgcGFja2FnZSBpbiB1c2UuIFRoaXMgbWV0aG9kIHdvcmtzIGV2ZW4gZm9yIEJ1ZmZlclxuLy8gaW5zdGFuY2VzIHRoYXQgd2VyZSBjcmVhdGVkIGZyb20gYW5vdGhlciBjb3B5IG9mIHRoZSBgYnVmZmVyYCBwYWNrYWdlLlxuLy8gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlci9pc3N1ZXMvMTU0XG5CdWZmZXIucHJvdG90eXBlLl9pc0J1ZmZlciA9IHRydWVcblxuZnVuY3Rpb24gc3dhcCAoYiwgbiwgbSkge1xuICBjb25zdCBpID0gYltuXVxuICBiW25dID0gYlttXVxuICBiW21dID0gaVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnN3YXAxNiA9IGZ1bmN0aW9uIHN3YXAxNiAoKSB7XG4gIGNvbnN0IGxlbiA9IHRoaXMubGVuZ3RoXG4gIGlmIChsZW4gJSAyICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0J1ZmZlciBzaXplIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAxNi1iaXRzJylcbiAgfVxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSArPSAyKSB7XG4gICAgc3dhcCh0aGlzLCBpLCBpICsgMSlcbiAgfVxuICByZXR1cm4gdGhpc1xufVxuXG5CdWZmZXIucHJvdG90eXBlLnN3YXAzMiA9IGZ1bmN0aW9uIHN3YXAzMiAoKSB7XG4gIGNvbnN0IGxlbiA9IHRoaXMubGVuZ3RoXG4gIGlmIChsZW4gJSA0ICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0J1ZmZlciBzaXplIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAzMi1iaXRzJylcbiAgfVxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSArPSA0KSB7XG4gICAgc3dhcCh0aGlzLCBpLCBpICsgMylcbiAgICBzd2FwKHRoaXMsIGkgKyAxLCBpICsgMilcbiAgfVxuICByZXR1cm4gdGhpc1xufVxuXG5CdWZmZXIucHJvdG90eXBlLnN3YXA2NCA9IGZ1bmN0aW9uIHN3YXA2NCAoKSB7XG4gIGNvbnN0IGxlbiA9IHRoaXMubGVuZ3RoXG4gIGlmIChsZW4gJSA4ICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0J1ZmZlciBzaXplIG11c3QgYmUgYSBtdWx0aXBsZSBvZiA2NC1iaXRzJylcbiAgfVxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSArPSA4KSB7XG4gICAgc3dhcCh0aGlzLCBpLCBpICsgNylcbiAgICBzd2FwKHRoaXMsIGkgKyAxLCBpICsgNilcbiAgICBzd2FwKHRoaXMsIGkgKyAyLCBpICsgNSlcbiAgICBzd2FwKHRoaXMsIGkgKyAzLCBpICsgNClcbiAgfVxuICByZXR1cm4gdGhpc1xufVxuXG5CdWZmZXIucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcgKCkge1xuICBjb25zdCBsZW5ndGggPSB0aGlzLmxlbmd0aFxuICBpZiAobGVuZ3RoID09PSAwKSByZXR1cm4gJydcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHJldHVybiB1dGY4U2xpY2UodGhpcywgMCwgbGVuZ3RoKVxuICByZXR1cm4gc2xvd1RvU3RyaW5nLmFwcGx5KHRoaXMsIGFyZ3VtZW50cylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS50b0xvY2FsZVN0cmluZyA9IEJ1ZmZlci5wcm90b3R5cGUudG9TdHJpbmdcblxuQnVmZmVyLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbiBlcXVhbHMgKGIpIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYikpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXInKVxuICBpZiAodGhpcyA9PT0gYikgcmV0dXJuIHRydWVcbiAgcmV0dXJuIEJ1ZmZlci5jb21wYXJlKHRoaXMsIGIpID09PSAwXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuaW5zcGVjdCA9IGZ1bmN0aW9uIGluc3BlY3QgKCkge1xuICBsZXQgc3RyID0gJydcbiAgY29uc3QgbWF4ID0gZXhwb3J0cy5JTlNQRUNUX01BWF9CWVRFU1xuICBzdHIgPSB0aGlzLnRvU3RyaW5nKCdoZXgnLCAwLCBtYXgpLnJlcGxhY2UoLyguezJ9KS9nLCAnJDEgJykudHJpbSgpXG4gIGlmICh0aGlzLmxlbmd0aCA+IG1heCkgc3RyICs9ICcgLi4uICdcbiAgcmV0dXJuICc8QnVmZmVyICcgKyBzdHIgKyAnPidcbn1cbmlmIChjdXN0b21JbnNwZWN0U3ltYm9sKSB7XG4gIEJ1ZmZlci5wcm90b3R5cGVbY3VzdG9tSW5zcGVjdFN5bWJvbF0gPSBCdWZmZXIucHJvdG90eXBlLmluc3BlY3Rcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5jb21wYXJlID0gZnVuY3Rpb24gY29tcGFyZSAodGFyZ2V0LCBzdGFydCwgZW5kLCB0aGlzU3RhcnQsIHRoaXNFbmQpIHtcbiAgaWYgKGlzSW5zdGFuY2UodGFyZ2V0LCBVaW50OEFycmF5KSkge1xuICAgIHRhcmdldCA9IEJ1ZmZlci5mcm9tKHRhcmdldCwgdGFyZ2V0Lm9mZnNldCwgdGFyZ2V0LmJ5dGVMZW5ndGgpXG4gIH1cbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIodGFyZ2V0KSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnVGhlIFwidGFyZ2V0XCIgYXJndW1lbnQgbXVzdCBiZSBvbmUgb2YgdHlwZSBCdWZmZXIgb3IgVWludDhBcnJheS4gJyArXG4gICAgICAnUmVjZWl2ZWQgdHlwZSAnICsgKHR5cGVvZiB0YXJnZXQpXG4gICAgKVxuICB9XG5cbiAgaWYgKHN0YXJ0ID09PSB1bmRlZmluZWQpIHtcbiAgICBzdGFydCA9IDBcbiAgfVxuICBpZiAoZW5kID09PSB1bmRlZmluZWQpIHtcbiAgICBlbmQgPSB0YXJnZXQgPyB0YXJnZXQubGVuZ3RoIDogMFxuICB9XG4gIGlmICh0aGlzU3RhcnQgPT09IHVuZGVmaW5lZCkge1xuICAgIHRoaXNTdGFydCA9IDBcbiAgfVxuICBpZiAodGhpc0VuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhpc0VuZCA9IHRoaXMubGVuZ3RoXG4gIH1cblxuICBpZiAoc3RhcnQgPCAwIHx8IGVuZCA+IHRhcmdldC5sZW5ndGggfHwgdGhpc1N0YXJ0IDwgMCB8fCB0aGlzRW5kID4gdGhpcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignb3V0IG9mIHJhbmdlIGluZGV4JylcbiAgfVxuXG4gIGlmICh0aGlzU3RhcnQgPj0gdGhpc0VuZCAmJiBzdGFydCA+PSBlbmQpIHtcbiAgICByZXR1cm4gMFxuICB9XG4gIGlmICh0aGlzU3RhcnQgPj0gdGhpc0VuZCkge1xuICAgIHJldHVybiAtMVxuICB9XG4gIGlmIChzdGFydCA+PSBlbmQpIHtcbiAgICByZXR1cm4gMVxuICB9XG5cbiAgc3RhcnQgPj4+PSAwXG4gIGVuZCA+Pj49IDBcbiAgdGhpc1N0YXJ0ID4+Pj0gMFxuICB0aGlzRW5kID4+Pj0gMFxuXG4gIGlmICh0aGlzID09PSB0YXJnZXQpIHJldHVybiAwXG5cbiAgbGV0IHggPSB0aGlzRW5kIC0gdGhpc1N0YXJ0XG4gIGxldCB5ID0gZW5kIC0gc3RhcnRcbiAgY29uc3QgbGVuID0gTWF0aC5taW4oeCwgeSlcblxuICBjb25zdCB0aGlzQ29weSA9IHRoaXMuc2xpY2UodGhpc1N0YXJ0LCB0aGlzRW5kKVxuICBjb25zdCB0YXJnZXRDb3B5ID0gdGFyZ2V0LnNsaWNlKHN0YXJ0LCBlbmQpXG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47ICsraSkge1xuICAgIGlmICh0aGlzQ29weVtpXSAhPT0gdGFyZ2V0Q29weVtpXSkge1xuICAgICAgeCA9IHRoaXNDb3B5W2ldXG4gICAgICB5ID0gdGFyZ2V0Q29weVtpXVxuICAgICAgYnJlYWtcbiAgICB9XG4gIH1cblxuICBpZiAoeCA8IHkpIHJldHVybiAtMVxuICBpZiAoeSA8IHgpIHJldHVybiAxXG4gIHJldHVybiAwXG59XG5cbi8vIEZpbmRzIGVpdGhlciB0aGUgZmlyc3QgaW5kZXggb2YgYHZhbGAgaW4gYGJ1ZmZlcmAgYXQgb2Zmc2V0ID49IGBieXRlT2Zmc2V0YCxcbi8vIE9SIHRoZSBsYXN0IGluZGV4IG9mIGB2YWxgIGluIGBidWZmZXJgIGF0IG9mZnNldCA8PSBgYnl0ZU9mZnNldGAuXG4vL1xuLy8gQXJndW1lbnRzOlxuLy8gLSBidWZmZXIgLSBhIEJ1ZmZlciB0byBzZWFyY2hcbi8vIC0gdmFsIC0gYSBzdHJpbmcsIEJ1ZmZlciwgb3IgbnVtYmVyXG4vLyAtIGJ5dGVPZmZzZXQgLSBhbiBpbmRleCBpbnRvIGBidWZmZXJgOyB3aWxsIGJlIGNsYW1wZWQgdG8gYW4gaW50MzJcbi8vIC0gZW5jb2RpbmcgLSBhbiBvcHRpb25hbCBlbmNvZGluZywgcmVsZXZhbnQgaXMgdmFsIGlzIGEgc3RyaW5nXG4vLyAtIGRpciAtIHRydWUgZm9yIGluZGV4T2YsIGZhbHNlIGZvciBsYXN0SW5kZXhPZlxuZnVuY3Rpb24gYmlkaXJlY3Rpb25hbEluZGV4T2YgKGJ1ZmZlciwgdmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZywgZGlyKSB7XG4gIC8vIEVtcHR5IGJ1ZmZlciBtZWFucyBubyBtYXRjaFxuICBpZiAoYnVmZmVyLmxlbmd0aCA9PT0gMCkgcmV0dXJuIC0xXG5cbiAgLy8gTm9ybWFsaXplIGJ5dGVPZmZzZXRcbiAgaWYgKHR5cGVvZiBieXRlT2Zmc2V0ID09PSAnc3RyaW5nJykge1xuICAgIGVuY29kaW5nID0gYnl0ZU9mZnNldFxuICAgIGJ5dGVPZmZzZXQgPSAwXG4gIH0gZWxzZSBpZiAoYnl0ZU9mZnNldCA+IDB4N2ZmZmZmZmYpIHtcbiAgICBieXRlT2Zmc2V0ID0gMHg3ZmZmZmZmZlxuICB9IGVsc2UgaWYgKGJ5dGVPZmZzZXQgPCAtMHg4MDAwMDAwMCkge1xuICAgIGJ5dGVPZmZzZXQgPSAtMHg4MDAwMDAwMFxuICB9XG4gIGJ5dGVPZmZzZXQgPSArYnl0ZU9mZnNldCAvLyBDb2VyY2UgdG8gTnVtYmVyLlxuICBpZiAobnVtYmVySXNOYU4oYnl0ZU9mZnNldCkpIHtcbiAgICAvLyBieXRlT2Zmc2V0OiBpdCBpdCdzIHVuZGVmaW5lZCwgbnVsbCwgTmFOLCBcImZvb1wiLCBldGMsIHNlYXJjaCB3aG9sZSBidWZmZXJcbiAgICBieXRlT2Zmc2V0ID0gZGlyID8gMCA6IChidWZmZXIubGVuZ3RoIC0gMSlcbiAgfVxuXG4gIC8vIE5vcm1hbGl6ZSBieXRlT2Zmc2V0OiBuZWdhdGl2ZSBvZmZzZXRzIHN0YXJ0IGZyb20gdGhlIGVuZCBvZiB0aGUgYnVmZmVyXG4gIGlmIChieXRlT2Zmc2V0IDwgMCkgYnl0ZU9mZnNldCA9IGJ1ZmZlci5sZW5ndGggKyBieXRlT2Zmc2V0XG4gIGlmIChieXRlT2Zmc2V0ID49IGJ1ZmZlci5sZW5ndGgpIHtcbiAgICBpZiAoZGlyKSByZXR1cm4gLTFcbiAgICBlbHNlIGJ5dGVPZmZzZXQgPSBidWZmZXIubGVuZ3RoIC0gMVxuICB9IGVsc2UgaWYgKGJ5dGVPZmZzZXQgPCAwKSB7XG4gICAgaWYgKGRpcikgYnl0ZU9mZnNldCA9IDBcbiAgICBlbHNlIHJldHVybiAtMVxuICB9XG5cbiAgLy8gTm9ybWFsaXplIHZhbFxuICBpZiAodHlwZW9mIHZhbCA9PT0gJ3N0cmluZycpIHtcbiAgICB2YWwgPSBCdWZmZXIuZnJvbSh2YWwsIGVuY29kaW5nKVxuICB9XG5cbiAgLy8gRmluYWxseSwgc2VhcmNoIGVpdGhlciBpbmRleE9mIChpZiBkaXIgaXMgdHJ1ZSkgb3IgbGFzdEluZGV4T2ZcbiAgaWYgKEJ1ZmZlci5pc0J1ZmZlcih2YWwpKSB7XG4gICAgLy8gU3BlY2lhbCBjYXNlOiBsb29raW5nIGZvciBlbXB0eSBzdHJpbmcvYnVmZmVyIGFsd2F5cyBmYWlsc1xuICAgIGlmICh2YWwubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gLTFcbiAgICB9XG4gICAgcmV0dXJuIGFycmF5SW5kZXhPZihidWZmZXIsIHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcsIGRpcilcbiAgfSBlbHNlIGlmICh0eXBlb2YgdmFsID09PSAnbnVtYmVyJykge1xuICAgIHZhbCA9IHZhbCAmIDB4RkYgLy8gU2VhcmNoIGZvciBhIGJ5dGUgdmFsdWUgWzAtMjU1XVxuICAgIGlmICh0eXBlb2YgVWludDhBcnJheS5wcm90b3R5cGUuaW5kZXhPZiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgaWYgKGRpcikge1xuICAgICAgICByZXR1cm4gVWludDhBcnJheS5wcm90b3R5cGUuaW5kZXhPZi5jYWxsKGJ1ZmZlciwgdmFsLCBieXRlT2Zmc2V0KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFVpbnQ4QXJyYXkucHJvdG90eXBlLmxhc3RJbmRleE9mLmNhbGwoYnVmZmVyLCB2YWwsIGJ5dGVPZmZzZXQpXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBhcnJheUluZGV4T2YoYnVmZmVyLCBbdmFsXSwgYnl0ZU9mZnNldCwgZW5jb2RpbmcsIGRpcilcbiAgfVxuXG4gIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ZhbCBtdXN0IGJlIHN0cmluZywgbnVtYmVyIG9yIEJ1ZmZlcicpXG59XG5cbmZ1bmN0aW9uIGFycmF5SW5kZXhPZiAoYXJyLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBkaXIpIHtcbiAgbGV0IGluZGV4U2l6ZSA9IDFcbiAgbGV0IGFyckxlbmd0aCA9IGFyci5sZW5ndGhcbiAgbGV0IHZhbExlbmd0aCA9IHZhbC5sZW5ndGhcblxuICBpZiAoZW5jb2RpbmcgIT09IHVuZGVmaW5lZCkge1xuICAgIGVuY29kaW5nID0gU3RyaW5nKGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpXG4gICAgaWYgKGVuY29kaW5nID09PSAndWNzMicgfHwgZW5jb2RpbmcgPT09ICd1Y3MtMicgfHxcbiAgICAgICAgZW5jb2RpbmcgPT09ICd1dGYxNmxlJyB8fCBlbmNvZGluZyA9PT0gJ3V0Zi0xNmxlJykge1xuICAgICAgaWYgKGFyci5sZW5ndGggPCAyIHx8IHZhbC5sZW5ndGggPCAyKSB7XG4gICAgICAgIHJldHVybiAtMVxuICAgICAgfVxuICAgICAgaW5kZXhTaXplID0gMlxuICAgICAgYXJyTGVuZ3RoIC89IDJcbiAgICAgIHZhbExlbmd0aCAvPSAyXG4gICAgICBieXRlT2Zmc2V0IC89IDJcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiByZWFkIChidWYsIGkpIHtcbiAgICBpZiAoaW5kZXhTaXplID09PSAxKSB7XG4gICAgICByZXR1cm4gYnVmW2ldXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBidWYucmVhZFVJbnQxNkJFKGkgKiBpbmRleFNpemUpXG4gICAgfVxuICB9XG5cbiAgbGV0IGlcbiAgaWYgKGRpcikge1xuICAgIGxldCBmb3VuZEluZGV4ID0gLTFcbiAgICBmb3IgKGkgPSBieXRlT2Zmc2V0OyBpIDwgYXJyTGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChyZWFkKGFyciwgaSkgPT09IHJlYWQodmFsLCBmb3VuZEluZGV4ID09PSAtMSA/IDAgOiBpIC0gZm91bmRJbmRleCkpIHtcbiAgICAgICAgaWYgKGZvdW5kSW5kZXggPT09IC0xKSBmb3VuZEluZGV4ID0gaVxuICAgICAgICBpZiAoaSAtIGZvdW5kSW5kZXggKyAxID09PSB2YWxMZW5ndGgpIHJldHVybiBmb3VuZEluZGV4ICogaW5kZXhTaXplXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoZm91bmRJbmRleCAhPT0gLTEpIGkgLT0gaSAtIGZvdW5kSW5kZXhcbiAgICAgICAgZm91bmRJbmRleCA9IC0xXG4gICAgICB9XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChieXRlT2Zmc2V0ICsgdmFsTGVuZ3RoID4gYXJyTGVuZ3RoKSBieXRlT2Zmc2V0ID0gYXJyTGVuZ3RoIC0gdmFsTGVuZ3RoXG4gICAgZm9yIChpID0gYnl0ZU9mZnNldDsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIGxldCBmb3VuZCA9IHRydWVcbiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdmFsTGVuZ3RoOyBqKyspIHtcbiAgICAgICAgaWYgKHJlYWQoYXJyLCBpICsgaikgIT09IHJlYWQodmFsLCBqKSkge1xuICAgICAgICAgIGZvdW5kID0gZmFsc2VcbiAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZm91bmQpIHJldHVybiBpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIC0xXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuaW5jbHVkZXMgPSBmdW5jdGlvbiBpbmNsdWRlcyAodmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZykge1xuICByZXR1cm4gdGhpcy5pbmRleE9mKHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcpICE9PSAtMVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluZGV4T2YgPSBmdW5jdGlvbiBpbmRleE9mICh2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nKSB7XG4gIHJldHVybiBiaWRpcmVjdGlvbmFsSW5kZXhPZih0aGlzLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCB0cnVlKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmxhc3RJbmRleE9mID0gZnVuY3Rpb24gbGFzdEluZGV4T2YgKHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcpIHtcbiAgcmV0dXJuIGJpZGlyZWN0aW9uYWxJbmRleE9mKHRoaXMsIHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcsIGZhbHNlKVxufVxuXG5mdW5jdGlvbiBoZXhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIG9mZnNldCA9IE51bWJlcihvZmZzZXQpIHx8IDBcbiAgY29uc3QgcmVtYWluaW5nID0gYnVmLmxlbmd0aCAtIG9mZnNldFxuICBpZiAoIWxlbmd0aCkge1xuICAgIGxlbmd0aCA9IHJlbWFpbmluZ1xuICB9IGVsc2Uge1xuICAgIGxlbmd0aCA9IE51bWJlcihsZW5ndGgpXG4gICAgaWYgKGxlbmd0aCA+IHJlbWFpbmluZykge1xuICAgICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gICAgfVxuICB9XG5cbiAgY29uc3Qgc3RyTGVuID0gc3RyaW5nLmxlbmd0aFxuXG4gIGlmIChsZW5ndGggPiBzdHJMZW4gLyAyKSB7XG4gICAgbGVuZ3RoID0gc3RyTGVuIC8gMlxuICB9XG4gIGxldCBpXG4gIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkge1xuICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlSW50KHN0cmluZy5zdWJzdHIoaSAqIDIsIDIpLCAxNilcbiAgICBpZiAobnVtYmVySXNOYU4ocGFyc2VkKSkgcmV0dXJuIGlcbiAgICBidWZbb2Zmc2V0ICsgaV0gPSBwYXJzZWRcbiAgfVxuICByZXR1cm4gaVxufVxuXG5mdW5jdGlvbiB1dGY4V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcih1dGY4VG9CeXRlcyhzdHJpbmcsIGJ1Zi5sZW5ndGggLSBvZmZzZXQpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiBhc2NpaVdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIoYXNjaWlUb0J5dGVzKHN0cmluZyksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGJhc2U2NFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIoYmFzZTY0VG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiB1Y3MyV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcih1dGYxNmxlVG9CeXRlcyhzdHJpbmcsIGJ1Zi5sZW5ndGggLSBvZmZzZXQpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlID0gZnVuY3Rpb24gd3JpdGUgKHN0cmluZywgb2Zmc2V0LCBsZW5ndGgsIGVuY29kaW5nKSB7XG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcpXG4gIGlmIChvZmZzZXQgPT09IHVuZGVmaW5lZCkge1xuICAgIGVuY29kaW5nID0gJ3V0ZjgnXG4gICAgbGVuZ3RoID0gdGhpcy5sZW5ndGhcbiAgICBvZmZzZXQgPSAwXG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcsIGVuY29kaW5nKVxuICB9IGVsc2UgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkICYmIHR5cGVvZiBvZmZzZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgZW5jb2RpbmcgPSBvZmZzZXRcbiAgICBsZW5ndGggPSB0aGlzLmxlbmd0aFxuICAgIG9mZnNldCA9IDBcbiAgLy8gQnVmZmVyI3dyaXRlKHN0cmluZywgb2Zmc2V0WywgbGVuZ3RoXVssIGVuY29kaW5nXSlcbiAgfSBlbHNlIGlmIChpc0Zpbml0ZShvZmZzZXQpKSB7XG4gICAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gICAgaWYgKGlzRmluaXRlKGxlbmd0aCkpIHtcbiAgICAgIGxlbmd0aCA9IGxlbmd0aCA+Pj4gMFxuICAgICAgaWYgKGVuY29kaW5nID09PSB1bmRlZmluZWQpIGVuY29kaW5nID0gJ3V0ZjgnXG4gICAgfSBlbHNlIHtcbiAgICAgIGVuY29kaW5nID0gbGVuZ3RoXG4gICAgICBsZW5ndGggPSB1bmRlZmluZWRcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgJ0J1ZmZlci53cml0ZShzdHJpbmcsIGVuY29kaW5nLCBvZmZzZXRbLCBsZW5ndGhdKSBpcyBubyBsb25nZXIgc3VwcG9ydGVkJ1xuICAgIClcbiAgfVxuXG4gIGNvbnN0IHJlbWFpbmluZyA9IHRoaXMubGVuZ3RoIC0gb2Zmc2V0XG4gIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCB8fCBsZW5ndGggPiByZW1haW5pbmcpIGxlbmd0aCA9IHJlbWFpbmluZ1xuXG4gIGlmICgoc3RyaW5nLmxlbmd0aCA+IDAgJiYgKGxlbmd0aCA8IDAgfHwgb2Zmc2V0IDwgMCkpIHx8IG9mZnNldCA+IHRoaXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0F0dGVtcHQgdG8gd3JpdGUgb3V0c2lkZSBidWZmZXIgYm91bmRzJylcbiAgfVxuXG4gIGlmICghZW5jb2RpbmcpIGVuY29kaW5nID0gJ3V0ZjgnXG5cbiAgbGV0IGxvd2VyZWRDYXNlID0gZmFsc2VcbiAgZm9yICg7Oykge1xuICAgIHN3aXRjaCAoZW5jb2RpbmcpIHtcbiAgICAgIGNhc2UgJ2hleCc6XG4gICAgICAgIHJldHVybiBoZXhXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICd1dGY4JzpcbiAgICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgICAgcmV0dXJuIHV0ZjhXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICdhc2NpaSc6XG4gICAgICBjYXNlICdsYXRpbjEnOlxuICAgICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgICAgcmV0dXJuIGFzY2lpV3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgLy8gV2FybmluZzogbWF4TGVuZ3RoIG5vdCB0YWtlbiBpbnRvIGFjY291bnQgaW4gYmFzZTY0V3JpdGVcbiAgICAgICAgcmV0dXJuIGJhc2U2NFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiB1Y3MyV3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gICAgICAgIGVuY29kaW5nID0gKCcnICsgZW5jb2RpbmcpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OICgpIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAnQnVmZmVyJyxcbiAgICBkYXRhOiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCh0aGlzLl9hcnIgfHwgdGhpcywgMClcbiAgfVxufVxuXG5mdW5jdGlvbiBiYXNlNjRTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGlmIChzdGFydCA9PT0gMCAmJiBlbmQgPT09IGJ1Zi5sZW5ndGgpIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmKVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBiYXNlNjQuZnJvbUJ5dGVBcnJheShidWYuc2xpY2Uoc3RhcnQsIGVuZCkpXG4gIH1cbn1cblxuZnVuY3Rpb24gdXRmOFNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuICBjb25zdCByZXMgPSBbXVxuXG4gIGxldCBpID0gc3RhcnRcbiAgd2hpbGUgKGkgPCBlbmQpIHtcbiAgICBjb25zdCBmaXJzdEJ5dGUgPSBidWZbaV1cbiAgICBsZXQgY29kZVBvaW50ID0gbnVsbFxuICAgIGxldCBieXRlc1BlclNlcXVlbmNlID0gKGZpcnN0Qnl0ZSA+IDB4RUYpXG4gICAgICA/IDRcbiAgICAgIDogKGZpcnN0Qnl0ZSA+IDB4REYpXG4gICAgICAgICAgPyAzXG4gICAgICAgICAgOiAoZmlyc3RCeXRlID4gMHhCRilcbiAgICAgICAgICAgICAgPyAyXG4gICAgICAgICAgICAgIDogMVxuXG4gICAgaWYgKGkgKyBieXRlc1BlclNlcXVlbmNlIDw9IGVuZCkge1xuICAgICAgbGV0IHNlY29uZEJ5dGUsIHRoaXJkQnl0ZSwgZm91cnRoQnl0ZSwgdGVtcENvZGVQb2ludFxuXG4gICAgICBzd2l0Y2ggKGJ5dGVzUGVyU2VxdWVuY2UpIHtcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgIGlmIChmaXJzdEJ5dGUgPCAweDgwKSB7XG4gICAgICAgICAgICBjb2RlUG9pbnQgPSBmaXJzdEJ5dGVcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgaWYgKChzZWNvbmRCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgIHRlbXBDb2RlUG9pbnQgPSAoZmlyc3RCeXRlICYgMHgxRikgPDwgMHg2IHwgKHNlY29uZEJ5dGUgJiAweDNGKVxuICAgICAgICAgICAgaWYgKHRlbXBDb2RlUG9pbnQgPiAweDdGKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgdGhpcmRCeXRlID0gYnVmW2kgKyAyXVxuICAgICAgICAgIGlmICgoc2Vjb25kQnl0ZSAmIDB4QzApID09PSAweDgwICYmICh0aGlyZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCkge1xuICAgICAgICAgICAgdGVtcENvZGVQb2ludCA9IChmaXJzdEJ5dGUgJiAweEYpIDw8IDB4QyB8IChzZWNvbmRCeXRlICYgMHgzRikgPDwgMHg2IHwgKHRoaXJkQnl0ZSAmIDB4M0YpXG4gICAgICAgICAgICBpZiAodGVtcENvZGVQb2ludCA+IDB4N0ZGICYmICh0ZW1wQ29kZVBvaW50IDwgMHhEODAwIHx8IHRlbXBDb2RlUG9pbnQgPiAweERGRkYpKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgdGhpcmRCeXRlID0gYnVmW2kgKyAyXVxuICAgICAgICAgIGZvdXJ0aEJ5dGUgPSBidWZbaSArIDNdXG4gICAgICAgICAgaWYgKChzZWNvbmRCeXRlICYgMHhDMCkgPT09IDB4ODAgJiYgKHRoaXJkQnl0ZSAmIDB4QzApID09PSAweDgwICYmIChmb3VydGhCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgIHRlbXBDb2RlUG9pbnQgPSAoZmlyc3RCeXRlICYgMHhGKSA8PCAweDEyIHwgKHNlY29uZEJ5dGUgJiAweDNGKSA8PCAweEMgfCAodGhpcmRCeXRlICYgMHgzRikgPDwgMHg2IHwgKGZvdXJ0aEJ5dGUgJiAweDNGKVxuICAgICAgICAgICAgaWYgKHRlbXBDb2RlUG9pbnQgPiAweEZGRkYgJiYgdGVtcENvZGVQb2ludCA8IDB4MTEwMDAwKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNvZGVQb2ludCA9PT0gbnVsbCkge1xuICAgICAgLy8gd2UgZGlkIG5vdCBnZW5lcmF0ZSBhIHZhbGlkIGNvZGVQb2ludCBzbyBpbnNlcnQgYVxuICAgICAgLy8gcmVwbGFjZW1lbnQgY2hhciAoVStGRkZEKSBhbmQgYWR2YW5jZSBvbmx5IDEgYnl0ZVxuICAgICAgY29kZVBvaW50ID0gMHhGRkZEXG4gICAgICBieXRlc1BlclNlcXVlbmNlID0gMVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50ID4gMHhGRkZGKSB7XG4gICAgICAvLyBlbmNvZGUgdG8gdXRmMTYgKHN1cnJvZ2F0ZSBwYWlyIGRhbmNlKVxuICAgICAgY29kZVBvaW50IC09IDB4MTAwMDBcbiAgICAgIHJlcy5wdXNoKGNvZGVQb2ludCA+Pj4gMTAgJiAweDNGRiB8IDB4RDgwMClcbiAgICAgIGNvZGVQb2ludCA9IDB4REMwMCB8IGNvZGVQb2ludCAmIDB4M0ZGXG4gICAgfVxuXG4gICAgcmVzLnB1c2goY29kZVBvaW50KVxuICAgIGkgKz0gYnl0ZXNQZXJTZXF1ZW5jZVxuICB9XG5cbiAgcmV0dXJuIGRlY29kZUNvZGVQb2ludHNBcnJheShyZXMpXG59XG5cbi8vIEJhc2VkIG9uIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzIyNzQ3MjcyLzY4MDc0MiwgdGhlIGJyb3dzZXIgd2l0aFxuLy8gdGhlIGxvd2VzdCBsaW1pdCBpcyBDaHJvbWUsIHdpdGggMHgxMDAwMCBhcmdzLlxuLy8gV2UgZ28gMSBtYWduaXR1ZGUgbGVzcywgZm9yIHNhZmV0eVxuY29uc3QgTUFYX0FSR1VNRU5UU19MRU5HVEggPSAweDEwMDBcblxuZnVuY3Rpb24gZGVjb2RlQ29kZVBvaW50c0FycmF5IChjb2RlUG9pbnRzKSB7XG4gIGNvbnN0IGxlbiA9IGNvZGVQb2ludHMubGVuZ3RoXG4gIGlmIChsZW4gPD0gTUFYX0FSR1VNRU5UU19MRU5HVEgpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShTdHJpbmcsIGNvZGVQb2ludHMpIC8vIGF2b2lkIGV4dHJhIHNsaWNlKClcbiAgfVxuXG4gIC8vIERlY29kZSBpbiBjaHVua3MgdG8gYXZvaWQgXCJjYWxsIHN0YWNrIHNpemUgZXhjZWVkZWRcIi5cbiAgbGV0IHJlcyA9ICcnXG4gIGxldCBpID0gMFxuICB3aGlsZSAoaSA8IGxlbikge1xuICAgIHJlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KFxuICAgICAgU3RyaW5nLFxuICAgICAgY29kZVBvaW50cy5zbGljZShpLCBpICs9IE1BWF9BUkdVTUVOVFNfTEVOR1RIKVxuICAgIClcbiAgfVxuICByZXR1cm4gcmVzXG59XG5cbmZ1bmN0aW9uIGFzY2lpU2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICBsZXQgcmV0ID0gJydcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuXG4gIGZvciAobGV0IGkgPSBzdGFydDsgaSA8IGVuZDsgKytpKSB7XG4gICAgcmV0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnVmW2ldICYgMHg3RilcbiAgfVxuICByZXR1cm4gcmV0XG59XG5cbmZ1bmN0aW9uIGxhdGluMVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgbGV0IHJldCA9ICcnXG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcblxuICBmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSkge1xuICAgIHJldCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ1ZltpXSlcbiAgfVxuICByZXR1cm4gcmV0XG59XG5cbmZ1bmN0aW9uIGhleFNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgY29uc3QgbGVuID0gYnVmLmxlbmd0aFxuXG4gIGlmICghc3RhcnQgfHwgc3RhcnQgPCAwKSBzdGFydCA9IDBcbiAgaWYgKCFlbmQgfHwgZW5kIDwgMCB8fCBlbmQgPiBsZW4pIGVuZCA9IGxlblxuXG4gIGxldCBvdXQgPSAnJ1xuICBmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSkge1xuICAgIG91dCArPSBoZXhTbGljZUxvb2t1cFRhYmxlW2J1ZltpXV1cbiAgfVxuICByZXR1cm4gb3V0XG59XG5cbmZ1bmN0aW9uIHV0ZjE2bGVTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGNvbnN0IGJ5dGVzID0gYnVmLnNsaWNlKHN0YXJ0LCBlbmQpXG4gIGxldCByZXMgPSAnJ1xuICAvLyBJZiBieXRlcy5sZW5ndGggaXMgb2RkLCB0aGUgbGFzdCA4IGJpdHMgbXVzdCBiZSBpZ25vcmVkIChzYW1lIGFzIG5vZGUuanMpXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoIC0gMTsgaSArPSAyKSB7XG4gICAgcmVzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnl0ZXNbaV0gKyAoYnl0ZXNbaSArIDFdICogMjU2KSlcbiAgfVxuICByZXR1cm4gcmVzXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuc2xpY2UgPSBmdW5jdGlvbiBzbGljZSAoc3RhcnQsIGVuZCkge1xuICBjb25zdCBsZW4gPSB0aGlzLmxlbmd0aFxuICBzdGFydCA9IH5+c3RhcnRcbiAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyBsZW4gOiB+fmVuZFxuXG4gIGlmIChzdGFydCA8IDApIHtcbiAgICBzdGFydCArPSBsZW5cbiAgICBpZiAoc3RhcnQgPCAwKSBzdGFydCA9IDBcbiAgfSBlbHNlIGlmIChzdGFydCA+IGxlbikge1xuICAgIHN0YXJ0ID0gbGVuXG4gIH1cblxuICBpZiAoZW5kIDwgMCkge1xuICAgIGVuZCArPSBsZW5cbiAgICBpZiAoZW5kIDwgMCkgZW5kID0gMFxuICB9IGVsc2UgaWYgKGVuZCA+IGxlbikge1xuICAgIGVuZCA9IGxlblxuICB9XG5cbiAgaWYgKGVuZCA8IHN0YXJ0KSBlbmQgPSBzdGFydFxuXG4gIGNvbnN0IG5ld0J1ZiA9IHRoaXMuc3ViYXJyYXkoc3RhcnQsIGVuZClcbiAgLy8gUmV0dXJuIGFuIGF1Z21lbnRlZCBgVWludDhBcnJheWAgaW5zdGFuY2VcbiAgT2JqZWN0LnNldFByb3RvdHlwZU9mKG5ld0J1ZiwgQnVmZmVyLnByb3RvdHlwZSlcblxuICByZXR1cm4gbmV3QnVmXG59XG5cbi8qXG4gKiBOZWVkIHRvIG1ha2Ugc3VyZSB0aGF0IGJ1ZmZlciBpc24ndCB0cnlpbmcgdG8gd3JpdGUgb3V0IG9mIGJvdW5kcy5cbiAqL1xuZnVuY3Rpb24gY2hlY2tPZmZzZXQgKG9mZnNldCwgZXh0LCBsZW5ndGgpIHtcbiAgaWYgKChvZmZzZXQgJSAxKSAhPT0gMCB8fCBvZmZzZXQgPCAwKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignb2Zmc2V0IGlzIG5vdCB1aW50JylcbiAgaWYgKG9mZnNldCArIGV4dCA+IGxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1RyeWluZyB0byBhY2Nlc3MgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVaW50TEUgPVxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludExFID0gZnVuY3Rpb24gcmVhZFVJbnRMRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICBsZXQgdmFsID0gdGhpc1tvZmZzZXRdXG4gIGxldCBtdWwgPSAxXG4gIGxldCBpID0gMFxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIGldICogbXVsXG4gIH1cblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVpbnRCRSA9XG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50QkUgPSBmdW5jdGlvbiByZWFkVUludEJFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcbiAgfVxuXG4gIGxldCB2YWwgPSB0aGlzW29mZnNldCArIC0tYnl0ZUxlbmd0aF1cbiAgbGV0IG11bCA9IDFcbiAgd2hpbGUgKGJ5dGVMZW5ndGggPiAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgLS1ieXRlTGVuZ3RoXSAqIG11bFxuICB9XG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVaW50OCA9XG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50OCA9IGZ1bmN0aW9uIHJlYWRVSW50OCAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAxLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIHRoaXNbb2Zmc2V0XVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVaW50MTZMRSA9XG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MTZMRSA9IGZ1bmN0aW9uIHJlYWRVSW50MTZMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIHRoaXNbb2Zmc2V0XSB8ICh0aGlzW29mZnNldCArIDFdIDw8IDgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVpbnQxNkJFID1cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQxNkJFID0gZnVuY3Rpb24gcmVhZFVJbnQxNkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSA8PCA4KSB8IHRoaXNbb2Zmc2V0ICsgMV1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVWludDMyTEUgPVxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDMyTEUgPSBmdW5jdGlvbiByZWFkVUludDMyTEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICgodGhpc1tvZmZzZXRdKSB8XG4gICAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KSB8XG4gICAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCAxNikpICtcbiAgICAgICh0aGlzW29mZnNldCArIDNdICogMHgxMDAwMDAwKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVaW50MzJCRSA9XG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MzJCRSA9IGZ1bmN0aW9uIHJlYWRVSW50MzJCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSAqIDB4MTAwMDAwMCkgK1xuICAgICgodGhpc1tvZmZzZXQgKyAxXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDgpIHxcbiAgICB0aGlzW29mZnNldCArIDNdKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRCaWdVSW50NjRMRSA9IGRlZmluZUJpZ0ludE1ldGhvZChmdW5jdGlvbiByZWFkQmlnVUludDY0TEUgKG9mZnNldCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgdmFsaWRhdGVOdW1iZXIob2Zmc2V0LCAnb2Zmc2V0JylcbiAgY29uc3QgZmlyc3QgPSB0aGlzW29mZnNldF1cbiAgY29uc3QgbGFzdCA9IHRoaXNbb2Zmc2V0ICsgN11cbiAgaWYgKGZpcnN0ID09PSB1bmRlZmluZWQgfHwgbGFzdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgYm91bmRzRXJyb3Iob2Zmc2V0LCB0aGlzLmxlbmd0aCAtIDgpXG4gIH1cblxuICBjb25zdCBsbyA9IGZpcnN0ICtcbiAgICB0aGlzWysrb2Zmc2V0XSAqIDIgKiogOCArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDE2ICtcbiAgICB0aGlzWysrb2Zmc2V0XSAqIDIgKiogMjRcblxuICBjb25zdCBoaSA9IHRoaXNbKytvZmZzZXRdICtcbiAgICB0aGlzWysrb2Zmc2V0XSAqIDIgKiogOCArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDE2ICtcbiAgICBsYXN0ICogMiAqKiAyNFxuXG4gIHJldHVybiBCaWdJbnQobG8pICsgKEJpZ0ludChoaSkgPDwgQmlnSW50KDMyKSlcbn0pXG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEJpZ1VJbnQ2NEJFID0gZGVmaW5lQmlnSW50TWV0aG9kKGZ1bmN0aW9uIHJlYWRCaWdVSW50NjRCRSAob2Zmc2V0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICB2YWxpZGF0ZU51bWJlcihvZmZzZXQsICdvZmZzZXQnKVxuICBjb25zdCBmaXJzdCA9IHRoaXNbb2Zmc2V0XVxuICBjb25zdCBsYXN0ID0gdGhpc1tvZmZzZXQgKyA3XVxuICBpZiAoZmlyc3QgPT09IHVuZGVmaW5lZCB8fCBsYXN0ID09PSB1bmRlZmluZWQpIHtcbiAgICBib3VuZHNFcnJvcihvZmZzZXQsIHRoaXMubGVuZ3RoIC0gOClcbiAgfVxuXG4gIGNvbnN0IGhpID0gZmlyc3QgKiAyICoqIDI0ICtcbiAgICB0aGlzWysrb2Zmc2V0XSAqIDIgKiogMTYgK1xuICAgIHRoaXNbKytvZmZzZXRdICogMiAqKiA4ICtcbiAgICB0aGlzWysrb2Zmc2V0XVxuXG4gIGNvbnN0IGxvID0gdGhpc1srK29mZnNldF0gKiAyICoqIDI0ICtcbiAgICB0aGlzWysrb2Zmc2V0XSAqIDIgKiogMTYgK1xuICAgIHRoaXNbKytvZmZzZXRdICogMiAqKiA4ICtcbiAgICBsYXN0XG5cbiAgcmV0dXJuIChCaWdJbnQoaGkpIDw8IEJpZ0ludCgzMikpICsgQmlnSW50KGxvKVxufSlcblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50TEUgPSBmdW5jdGlvbiByZWFkSW50TEUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgbGV0IHZhbCA9IHRoaXNbb2Zmc2V0XVxuICBsZXQgbXVsID0gMVxuICBsZXQgaSA9IDBcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyBpXSAqIG11bFxuICB9XG4gIG11bCAqPSAweDgwXG5cbiAgaWYgKHZhbCA+PSBtdWwpIHZhbCAtPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aClcblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludEJFID0gZnVuY3Rpb24gcmVhZEludEJFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuXG4gIGxldCBpID0gYnl0ZUxlbmd0aFxuICBsZXQgbXVsID0gMVxuICBsZXQgdmFsID0gdGhpc1tvZmZzZXQgKyAtLWldXG4gIHdoaWxlIChpID4gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIC0taV0gKiBtdWxcbiAgfVxuICBtdWwgKj0gMHg4MFxuXG4gIGlmICh2YWwgPj0gbXVsKSB2YWwgLT0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpXG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQ4ID0gZnVuY3Rpb24gcmVhZEludDggKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMSwgdGhpcy5sZW5ndGgpXG4gIGlmICghKHRoaXNbb2Zmc2V0XSAmIDB4ODApKSByZXR1cm4gKHRoaXNbb2Zmc2V0XSlcbiAgcmV0dXJuICgoMHhmZiAtIHRoaXNbb2Zmc2V0XSArIDEpICogLTEpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDE2TEUgPSBmdW5jdGlvbiByZWFkSW50MTZMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgY29uc3QgdmFsID0gdGhpc1tvZmZzZXRdIHwgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOClcbiAgcmV0dXJuICh2YWwgJiAweDgwMDApID8gdmFsIHwgMHhGRkZGMDAwMCA6IHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQxNkJFID0gZnVuY3Rpb24gcmVhZEludDE2QkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIGNvbnN0IHZhbCA9IHRoaXNbb2Zmc2V0ICsgMV0gfCAodGhpc1tvZmZzZXRdIDw8IDgpXG4gIHJldHVybiAodmFsICYgMHg4MDAwKSA/IHZhbCB8IDB4RkZGRjAwMDAgOiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MzJMRSA9IGZ1bmN0aW9uIHJlYWRJbnQzMkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuXG4gIHJldHVybiAodGhpc1tvZmZzZXRdKSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOCkgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDE2KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgM10gPDwgMjQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDMyQkUgPSBmdW5jdGlvbiByZWFkSW50MzJCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSA8PCAyNCkgfFxuICAgICh0aGlzW29mZnNldCArIDFdIDw8IDE2KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgOCkgfFxuICAgICh0aGlzW29mZnNldCArIDNdKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRCaWdJbnQ2NExFID0gZGVmaW5lQmlnSW50TWV0aG9kKGZ1bmN0aW9uIHJlYWRCaWdJbnQ2NExFIChvZmZzZXQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIHZhbGlkYXRlTnVtYmVyKG9mZnNldCwgJ29mZnNldCcpXG4gIGNvbnN0IGZpcnN0ID0gdGhpc1tvZmZzZXRdXG4gIGNvbnN0IGxhc3QgPSB0aGlzW29mZnNldCArIDddXG4gIGlmIChmaXJzdCA9PT0gdW5kZWZpbmVkIHx8IGxhc3QgPT09IHVuZGVmaW5lZCkge1xuICAgIGJvdW5kc0Vycm9yKG9mZnNldCwgdGhpcy5sZW5ndGggLSA4KVxuICB9XG5cbiAgY29uc3QgdmFsID0gdGhpc1tvZmZzZXQgKyA0XSArXG4gICAgdGhpc1tvZmZzZXQgKyA1XSAqIDIgKiogOCArXG4gICAgdGhpc1tvZmZzZXQgKyA2XSAqIDIgKiogMTYgK1xuICAgIChsYXN0IDw8IDI0KSAvLyBPdmVyZmxvd1xuXG4gIHJldHVybiAoQmlnSW50KHZhbCkgPDwgQmlnSW50KDMyKSkgK1xuICAgIEJpZ0ludChmaXJzdCArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDggK1xuICAgIHRoaXNbKytvZmZzZXRdICogMiAqKiAxNiArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDI0KVxufSlcblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkQmlnSW50NjRCRSA9IGRlZmluZUJpZ0ludE1ldGhvZChmdW5jdGlvbiByZWFkQmlnSW50NjRCRSAob2Zmc2V0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICB2YWxpZGF0ZU51bWJlcihvZmZzZXQsICdvZmZzZXQnKVxuICBjb25zdCBmaXJzdCA9IHRoaXNbb2Zmc2V0XVxuICBjb25zdCBsYXN0ID0gdGhpc1tvZmZzZXQgKyA3XVxuICBpZiAoZmlyc3QgPT09IHVuZGVmaW5lZCB8fCBsYXN0ID09PSB1bmRlZmluZWQpIHtcbiAgICBib3VuZHNFcnJvcihvZmZzZXQsIHRoaXMubGVuZ3RoIC0gOClcbiAgfVxuXG4gIGNvbnN0IHZhbCA9IChmaXJzdCA8PCAyNCkgKyAvLyBPdmVyZmxvd1xuICAgIHRoaXNbKytvZmZzZXRdICogMiAqKiAxNiArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDggK1xuICAgIHRoaXNbKytvZmZzZXRdXG5cbiAgcmV0dXJuIChCaWdJbnQodmFsKSA8PCBCaWdJbnQoMzIpKSArXG4gICAgQmlnSW50KHRoaXNbKytvZmZzZXRdICogMiAqKiAyNCArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDE2ICtcbiAgICB0aGlzWysrb2Zmc2V0XSAqIDIgKiogOCArXG4gICAgbGFzdClcbn0pXG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEZsb2F0TEUgPSBmdW5jdGlvbiByZWFkRmxvYXRMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIHRydWUsIDIzLCA0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRGbG9hdEJFID0gZnVuY3Rpb24gcmVhZEZsb2F0QkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCBmYWxzZSwgMjMsIDQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZERvdWJsZUxFID0gZnVuY3Rpb24gcmVhZERvdWJsZUxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDgsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgdHJ1ZSwgNTIsIDgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZERvdWJsZUJFID0gZnVuY3Rpb24gcmVhZERvdWJsZUJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDgsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgZmFsc2UsIDUyLCA4KVxufVxuXG5mdW5jdGlvbiBjaGVja0ludCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBleHQsIG1heCwgbWluKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGJ1ZikpIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiYnVmZmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIEJ1ZmZlciBpbnN0YW5jZScpXG4gIGlmICh2YWx1ZSA+IG1heCB8fCB2YWx1ZSA8IG1pbikgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1widmFsdWVcIiBhcmd1bWVudCBpcyBvdXQgb2YgYm91bmRzJylcbiAgaWYgKG9mZnNldCArIGV4dCA+IGJ1Zi5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbmRleCBvdXQgb2YgcmFuZ2UnKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVWludExFID1cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50TEUgPSBmdW5jdGlvbiB3cml0ZVVJbnRMRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjb25zdCBtYXhCeXRlcyA9IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKSAtIDFcbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBtYXhCeXRlcywgMClcbiAgfVxuXG4gIGxldCBtdWwgPSAxXG4gIGxldCBpID0gMFxuICB0aGlzW29mZnNldF0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB0aGlzW29mZnNldCArIGldID0gKHZhbHVlIC8gbXVsKSAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVaW50QkUgPVxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnRCRSA9IGZ1bmN0aW9uIHdyaXRlVUludEJFICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGNvbnN0IG1heEJ5dGVzID0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpIC0gMVxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG1heEJ5dGVzLCAwKVxuICB9XG5cbiAgbGV0IGkgPSBieXRlTGVuZ3RoIC0gMVxuICBsZXQgbXVsID0gMVxuICB0aGlzW29mZnNldCArIGldID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgtLWkgPj0gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAodmFsdWUgLyBtdWwpICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVpbnQ4ID1cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50OCA9IGZ1bmN0aW9uIHdyaXRlVUludDggKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAxLCAweGZmLCAwKVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICByZXR1cm4gb2Zmc2V0ICsgMVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVWludDE2TEUgPVxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkxFID0gZnVuY3Rpb24gd3JpdGVVSW50MTZMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4ZmZmZiwgMClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVpbnQxNkJFID1cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MTZCRSA9IGZ1bmN0aW9uIHdyaXRlVUludDE2QkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweGZmZmYsIDApXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gOClcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVaW50MzJMRSA9XG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDMyTEUgPSBmdW5jdGlvbiB3cml0ZVVJbnQzMkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgNCwgMHhmZmZmZmZmZiwgMClcbiAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSA+Pj4gMjQpXG4gIHRoaXNbb2Zmc2V0ICsgMl0gPSAodmFsdWUgPj4+IDE2KVxuICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVWludDMyQkUgPVxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkJFID0gZnVuY3Rpb24gd3JpdGVVSW50MzJCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4ZmZmZmZmZmYsIDApXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gMjQpXG4gIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDE2KVxuICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiA4KVxuICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuZnVuY3Rpb24gd3J0QmlnVUludDY0TEUgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbWluLCBtYXgpIHtcbiAgY2hlY2tJbnRCSSh2YWx1ZSwgbWluLCBtYXgsIGJ1Ziwgb2Zmc2V0LCA3KVxuXG4gIGxldCBsbyA9IE51bWJlcih2YWx1ZSAmIEJpZ0ludCgweGZmZmZmZmZmKSlcbiAgYnVmW29mZnNldCsrXSA9IGxvXG4gIGxvID0gbG8gPj4gOFxuICBidWZbb2Zmc2V0KytdID0gbG9cbiAgbG8gPSBsbyA+PiA4XG4gIGJ1ZltvZmZzZXQrK10gPSBsb1xuICBsbyA9IGxvID4+IDhcbiAgYnVmW29mZnNldCsrXSA9IGxvXG4gIGxldCBoaSA9IE51bWJlcih2YWx1ZSA+PiBCaWdJbnQoMzIpICYgQmlnSW50KDB4ZmZmZmZmZmYpKVxuICBidWZbb2Zmc2V0KytdID0gaGlcbiAgaGkgPSBoaSA+PiA4XG4gIGJ1ZltvZmZzZXQrK10gPSBoaVxuICBoaSA9IGhpID4+IDhcbiAgYnVmW29mZnNldCsrXSA9IGhpXG4gIGhpID0gaGkgPj4gOFxuICBidWZbb2Zmc2V0KytdID0gaGlcbiAgcmV0dXJuIG9mZnNldFxufVxuXG5mdW5jdGlvbiB3cnRCaWdVSW50NjRCRSAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBtaW4sIG1heCkge1xuICBjaGVja0ludEJJKHZhbHVlLCBtaW4sIG1heCwgYnVmLCBvZmZzZXQsIDcpXG5cbiAgbGV0IGxvID0gTnVtYmVyKHZhbHVlICYgQmlnSW50KDB4ZmZmZmZmZmYpKVxuICBidWZbb2Zmc2V0ICsgN10gPSBsb1xuICBsbyA9IGxvID4+IDhcbiAgYnVmW29mZnNldCArIDZdID0gbG9cbiAgbG8gPSBsbyA+PiA4XG4gIGJ1ZltvZmZzZXQgKyA1XSA9IGxvXG4gIGxvID0gbG8gPj4gOFxuICBidWZbb2Zmc2V0ICsgNF0gPSBsb1xuICBsZXQgaGkgPSBOdW1iZXIodmFsdWUgPj4gQmlnSW50KDMyKSAmIEJpZ0ludCgweGZmZmZmZmZmKSlcbiAgYnVmW29mZnNldCArIDNdID0gaGlcbiAgaGkgPSBoaSA+PiA4XG4gIGJ1ZltvZmZzZXQgKyAyXSA9IGhpXG4gIGhpID0gaGkgPj4gOFxuICBidWZbb2Zmc2V0ICsgMV0gPSBoaVxuICBoaSA9IGhpID4+IDhcbiAgYnVmW29mZnNldF0gPSBoaVxuICByZXR1cm4gb2Zmc2V0ICsgOFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlQmlnVUludDY0TEUgPSBkZWZpbmVCaWdJbnRNZXRob2QoZnVuY3Rpb24gd3JpdGVCaWdVSW50NjRMRSAodmFsdWUsIG9mZnNldCA9IDApIHtcbiAgcmV0dXJuIHdydEJpZ1VJbnQ2NExFKHRoaXMsIHZhbHVlLCBvZmZzZXQsIEJpZ0ludCgwKSwgQmlnSW50KCcweGZmZmZmZmZmZmZmZmZmZmYnKSlcbn0pXG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVCaWdVSW50NjRCRSA9IGRlZmluZUJpZ0ludE1ldGhvZChmdW5jdGlvbiB3cml0ZUJpZ1VJbnQ2NEJFICh2YWx1ZSwgb2Zmc2V0ID0gMCkge1xuICByZXR1cm4gd3J0QmlnVUludDY0QkUodGhpcywgdmFsdWUsIG9mZnNldCwgQmlnSW50KDApLCBCaWdJbnQoJzB4ZmZmZmZmZmZmZmZmZmZmZicpKVxufSlcblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludExFID0gZnVuY3Rpb24gd3JpdGVJbnRMRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjb25zdCBsaW1pdCA9IE1hdGgucG93KDIsICg4ICogYnl0ZUxlbmd0aCkgLSAxKVxuXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbGltaXQgLSAxLCAtbGltaXQpXG4gIH1cblxuICBsZXQgaSA9IDBcbiAgbGV0IG11bCA9IDFcbiAgbGV0IHN1YiA9IDBcbiAgdGhpc1tvZmZzZXRdID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgaWYgKHZhbHVlIDwgMCAmJiBzdWIgPT09IDAgJiYgdGhpc1tvZmZzZXQgKyBpIC0gMV0gIT09IDApIHtcbiAgICAgIHN1YiA9IDFcbiAgICB9XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICgodmFsdWUgLyBtdWwpID4+IDApIC0gc3ViICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludEJFID0gZnVuY3Rpb24gd3JpdGVJbnRCRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjb25zdCBsaW1pdCA9IE1hdGgucG93KDIsICg4ICogYnl0ZUxlbmd0aCkgLSAxKVxuXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbGltaXQgLSAxLCAtbGltaXQpXG4gIH1cblxuICBsZXQgaSA9IGJ5dGVMZW5ndGggLSAxXG4gIGxldCBtdWwgPSAxXG4gIGxldCBzdWIgPSAwXG4gIHRoaXNbb2Zmc2V0ICsgaV0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKC0taSA+PSAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgaWYgKHZhbHVlIDwgMCAmJiBzdWIgPT09IDAgJiYgdGhpc1tvZmZzZXQgKyBpICsgMV0gIT09IDApIHtcbiAgICAgIHN1YiA9IDFcbiAgICB9XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICgodmFsdWUgLyBtdWwpID4+IDApIC0gc3ViICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDggPSBmdW5jdGlvbiB3cml0ZUludDggKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAxLCAweDdmLCAtMHg4MClcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmICsgdmFsdWUgKyAxXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyAxXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNkxFID0gZnVuY3Rpb24gd3JpdGVJbnQxNkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMiwgMHg3ZmZmLCAtMHg4MDAwKVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MTZCRSA9IGZ1bmN0aW9uIHdyaXRlSW50MTZCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4N2ZmZiwgLTB4ODAwMClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiA4KVxuICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDMyTEUgPSBmdW5jdGlvbiB3cml0ZUludDMyTEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweDdmZmZmZmZmLCAtMHg4MDAwMDAwMClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgPj4+IDI0KVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MzJCRSA9IGZ1bmN0aW9uIHdyaXRlSW50MzJCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4N2ZmZmZmZmYsIC0weDgwMDAwMDAwKVxuICBpZiAodmFsdWUgPCAwKSB2YWx1ZSA9IDB4ZmZmZmZmZmYgKyB2YWx1ZSArIDFcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiAyNClcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gIHRoaXNbb2Zmc2V0ICsgMl0gPSAodmFsdWUgPj4+IDgpXG4gIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgJiAweGZmKVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlQmlnSW50NjRMRSA9IGRlZmluZUJpZ0ludE1ldGhvZChmdW5jdGlvbiB3cml0ZUJpZ0ludDY0TEUgKHZhbHVlLCBvZmZzZXQgPSAwKSB7XG4gIHJldHVybiB3cnRCaWdVSW50NjRMRSh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAtQmlnSW50KCcweDgwMDAwMDAwMDAwMDAwMDAnKSwgQmlnSW50KCcweDdmZmZmZmZmZmZmZmZmZmYnKSlcbn0pXG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVCaWdJbnQ2NEJFID0gZGVmaW5lQmlnSW50TWV0aG9kKGZ1bmN0aW9uIHdyaXRlQmlnSW50NjRCRSAodmFsdWUsIG9mZnNldCA9IDApIHtcbiAgcmV0dXJuIHdydEJpZ1VJbnQ2NEJFKHRoaXMsIHZhbHVlLCBvZmZzZXQsIC1CaWdJbnQoJzB4ODAwMDAwMDAwMDAwMDAwMCcpLCBCaWdJbnQoJzB4N2ZmZmZmZmZmZmZmZmZmZicpKVxufSlcblxuZnVuY3Rpb24gY2hlY2tJRUVFNzU0IChidWYsIHZhbHVlLCBvZmZzZXQsIGV4dCwgbWF4LCBtaW4pIHtcbiAgaWYgKG9mZnNldCArIGV4dCA+IGJ1Zi5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbmRleCBvdXQgb2YgcmFuZ2UnKVxuICBpZiAob2Zmc2V0IDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0luZGV4IG91dCBvZiByYW5nZScpXG59XG5cbmZ1bmN0aW9uIHdyaXRlRmxvYXQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGNoZWNrSUVFRTc1NChidWYsIHZhbHVlLCBvZmZzZXQsIDQsIDMuNDAyODIzNDY2Mzg1Mjg4NmUrMzgsIC0zLjQwMjgyMzQ2NjM4NTI4ODZlKzM4KVxuICB9XG4gIGllZWU3NTQud3JpdGUoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIDIzLCA0KVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRmxvYXRMRSA9IGZ1bmN0aW9uIHdyaXRlRmxvYXRMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRmxvYXQodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVGbG9hdEJFID0gZnVuY3Rpb24gd3JpdGVGbG9hdEJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVGbG9hdCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbmZ1bmN0aW9uIHdyaXRlRG91YmxlIChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjaGVja0lFRUU3NTQoYnVmLCB2YWx1ZSwgb2Zmc2V0LCA4LCAxLjc5NzY5MzEzNDg2MjMxNTdFKzMwOCwgLTEuNzk3NjkzMTM0ODYyMzE1N0UrMzA4KVxuICB9XG4gIGllZWU3NTQud3JpdGUoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIDUyLCA4KVxuICByZXR1cm4gb2Zmc2V0ICsgOFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlTEUgPSBmdW5jdGlvbiB3cml0ZURvdWJsZUxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVEb3VibGUodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVEb3VibGVCRSA9IGZ1bmN0aW9uIHdyaXRlRG91YmxlQkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZURvdWJsZSh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbi8vIGNvcHkodGFyZ2V0QnVmZmVyLCB0YXJnZXRTdGFydD0wLCBzb3VyY2VTdGFydD0wLCBzb3VyY2VFbmQ9YnVmZmVyLmxlbmd0aClcbkJ1ZmZlci5wcm90b3R5cGUuY29weSA9IGZ1bmN0aW9uIGNvcHkgKHRhcmdldCwgdGFyZ2V0U3RhcnQsIHN0YXJ0LCBlbmQpIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIodGFyZ2V0KSkgdGhyb3cgbmV3IFR5cGVFcnJvcignYXJndW1lbnQgc2hvdWxkIGJlIGEgQnVmZmVyJylcbiAgaWYgKCFzdGFydCkgc3RhcnQgPSAwXG4gIGlmICghZW5kICYmIGVuZCAhPT0gMCkgZW5kID0gdGhpcy5sZW5ndGhcbiAgaWYgKHRhcmdldFN0YXJ0ID49IHRhcmdldC5sZW5ndGgpIHRhcmdldFN0YXJ0ID0gdGFyZ2V0Lmxlbmd0aFxuICBpZiAoIXRhcmdldFN0YXJ0KSB0YXJnZXRTdGFydCA9IDBcbiAgaWYgKGVuZCA+IDAgJiYgZW5kIDwgc3RhcnQpIGVuZCA9IHN0YXJ0XG5cbiAgLy8gQ29weSAwIGJ5dGVzOyB3ZSdyZSBkb25lXG4gIGlmIChlbmQgPT09IHN0YXJ0KSByZXR1cm4gMFxuICBpZiAodGFyZ2V0Lmxlbmd0aCA9PT0gMCB8fCB0aGlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIDBcblxuICAvLyBGYXRhbCBlcnJvciBjb25kaXRpb25zXG4gIGlmICh0YXJnZXRTdGFydCA8IDApIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcigndGFyZ2V0U3RhcnQgb3V0IG9mIGJvdW5kcycpXG4gIH1cbiAgaWYgKHN0YXJ0IDwgMCB8fCBzdGFydCA+PSB0aGlzLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0luZGV4IG91dCBvZiByYW5nZScpXG4gIGlmIChlbmQgPCAwKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignc291cmNlRW5kIG91dCBvZiBib3VuZHMnKVxuXG4gIC8vIEFyZSB3ZSBvb2I/XG4gIGlmIChlbmQgPiB0aGlzLmxlbmd0aCkgZW5kID0gdGhpcy5sZW5ndGhcbiAgaWYgKHRhcmdldC5sZW5ndGggLSB0YXJnZXRTdGFydCA8IGVuZCAtIHN0YXJ0KSB7XG4gICAgZW5kID0gdGFyZ2V0Lmxlbmd0aCAtIHRhcmdldFN0YXJ0ICsgc3RhcnRcbiAgfVxuXG4gIGNvbnN0IGxlbiA9IGVuZCAtIHN0YXJ0XG5cbiAgaWYgKHRoaXMgPT09IHRhcmdldCAmJiB0eXBlb2YgVWludDhBcnJheS5wcm90b3R5cGUuY29weVdpdGhpbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIC8vIFVzZSBidWlsdC1pbiB3aGVuIGF2YWlsYWJsZSwgbWlzc2luZyBmcm9tIElFMTFcbiAgICB0aGlzLmNvcHlXaXRoaW4odGFyZ2V0U3RhcnQsIHN0YXJ0LCBlbmQpXG4gIH0gZWxzZSB7XG4gICAgVWludDhBcnJheS5wcm90b3R5cGUuc2V0LmNhbGwoXG4gICAgICB0YXJnZXQsXG4gICAgICB0aGlzLnN1YmFycmF5KHN0YXJ0LCBlbmQpLFxuICAgICAgdGFyZ2V0U3RhcnRcbiAgICApXG4gIH1cblxuICByZXR1cm4gbGVuXG59XG5cbi8vIFVzYWdlOlxuLy8gICAgYnVmZmVyLmZpbGwobnVtYmVyWywgb2Zmc2V0WywgZW5kXV0pXG4vLyAgICBidWZmZXIuZmlsbChidWZmZXJbLCBvZmZzZXRbLCBlbmRdXSlcbi8vICAgIGJ1ZmZlci5maWxsKHN0cmluZ1ssIG9mZnNldFssIGVuZF1dWywgZW5jb2RpbmddKVxuQnVmZmVyLnByb3RvdHlwZS5maWxsID0gZnVuY3Rpb24gZmlsbCAodmFsLCBzdGFydCwgZW5kLCBlbmNvZGluZykge1xuICAvLyBIYW5kbGUgc3RyaW5nIGNhc2VzOlxuICBpZiAodHlwZW9mIHZhbCA9PT0gJ3N0cmluZycpIHtcbiAgICBpZiAodHlwZW9mIHN0YXJ0ID09PSAnc3RyaW5nJykge1xuICAgICAgZW5jb2RpbmcgPSBzdGFydFxuICAgICAgc3RhcnQgPSAwXG4gICAgICBlbmQgPSB0aGlzLmxlbmd0aFxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGVuZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGVuY29kaW5nID0gZW5kXG4gICAgICBlbmQgPSB0aGlzLmxlbmd0aFxuICAgIH1cbiAgICBpZiAoZW5jb2RpbmcgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgZW5jb2RpbmcgIT09ICdzdHJpbmcnKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdlbmNvZGluZyBtdXN0IGJlIGEgc3RyaW5nJylcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBlbmNvZGluZyA9PT0gJ3N0cmluZycgJiYgIUJ1ZmZlci5pc0VuY29kaW5nKGVuY29kaW5nKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBlbmNvZGluZzogJyArIGVuY29kaW5nKVxuICAgIH1cbiAgICBpZiAodmFsLmxlbmd0aCA9PT0gMSkge1xuICAgICAgY29uc3QgY29kZSA9IHZhbC5jaGFyQ29kZUF0KDApXG4gICAgICBpZiAoKGVuY29kaW5nID09PSAndXRmOCcgJiYgY29kZSA8IDEyOCkgfHxcbiAgICAgICAgICBlbmNvZGluZyA9PT0gJ2xhdGluMScpIHtcbiAgICAgICAgLy8gRmFzdCBwYXRoOiBJZiBgdmFsYCBmaXRzIGludG8gYSBzaW5nbGUgYnl0ZSwgdXNlIHRoYXQgbnVtZXJpYyB2YWx1ZS5cbiAgICAgICAgdmFsID0gY29kZVxuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIGlmICh0eXBlb2YgdmFsID09PSAnbnVtYmVyJykge1xuICAgIHZhbCA9IHZhbCAmIDI1NVxuICB9IGVsc2UgaWYgKHR5cGVvZiB2YWwgPT09ICdib29sZWFuJykge1xuICAgIHZhbCA9IE51bWJlcih2YWwpXG4gIH1cblxuICAvLyBJbnZhbGlkIHJhbmdlcyBhcmUgbm90IHNldCB0byBhIGRlZmF1bHQsIHNvIGNhbiByYW5nZSBjaGVjayBlYXJseS5cbiAgaWYgKHN0YXJ0IDwgMCB8fCB0aGlzLmxlbmd0aCA8IHN0YXJ0IHx8IHRoaXMubGVuZ3RoIDwgZW5kKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ091dCBvZiByYW5nZSBpbmRleCcpXG4gIH1cblxuICBpZiAoZW5kIDw9IHN0YXJ0KSB7XG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIHN0YXJ0ID0gc3RhcnQgPj4+IDBcbiAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyB0aGlzLmxlbmd0aCA6IGVuZCA+Pj4gMFxuXG4gIGlmICghdmFsKSB2YWwgPSAwXG5cbiAgbGV0IGlcbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdudW1iZXInKSB7XG4gICAgZm9yIChpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSkge1xuICAgICAgdGhpc1tpXSA9IHZhbFxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBjb25zdCBieXRlcyA9IEJ1ZmZlci5pc0J1ZmZlcih2YWwpXG4gICAgICA/IHZhbFxuICAgICAgOiBCdWZmZXIuZnJvbSh2YWwsIGVuY29kaW5nKVxuICAgIGNvbnN0IGxlbiA9IGJ5dGVzLmxlbmd0aFxuICAgIGlmIChsZW4gPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1RoZSB2YWx1ZSBcIicgKyB2YWwgK1xuICAgICAgICAnXCIgaXMgaW52YWxpZCBmb3IgYXJndW1lbnQgXCJ2YWx1ZVwiJylcbiAgICB9XG4gICAgZm9yIChpID0gMDsgaSA8IGVuZCAtIHN0YXJ0OyArK2kpIHtcbiAgICAgIHRoaXNbaSArIHN0YXJ0XSA9IGJ5dGVzW2kgJSBsZW5dXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoaXNcbn1cblxuLy8gQ1VTVE9NIEVSUk9SU1xuLy8gPT09PT09PT09PT09PVxuXG4vLyBTaW1wbGlmaWVkIHZlcnNpb25zIGZyb20gTm9kZSwgY2hhbmdlZCBmb3IgQnVmZmVyLW9ubHkgdXNhZ2VcbmNvbnN0IGVycm9ycyA9IHt9XG5mdW5jdGlvbiBFIChzeW0sIGdldE1lc3NhZ2UsIEJhc2UpIHtcbiAgZXJyb3JzW3N5bV0gPSBjbGFzcyBOb2RlRXJyb3IgZXh0ZW5kcyBCYXNlIHtcbiAgICBjb25zdHJ1Y3RvciAoKSB7XG4gICAgICBzdXBlcigpXG5cbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnbWVzc2FnZScsIHtcbiAgICAgICAgdmFsdWU6IGdldE1lc3NhZ2UuYXBwbHkodGhpcywgYXJndW1lbnRzKSxcbiAgICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgfSlcblxuICAgICAgLy8gQWRkIHRoZSBlcnJvciBjb2RlIHRvIHRoZSBuYW1lIHRvIGluY2x1ZGUgaXQgaW4gdGhlIHN0YWNrIHRyYWNlLlxuICAgICAgdGhpcy5uYW1lID0gYCR7dGhpcy5uYW1lfSBbJHtzeW19XWBcbiAgICAgIC8vIEFjY2VzcyB0aGUgc3RhY2sgdG8gZ2VuZXJhdGUgdGhlIGVycm9yIG1lc3NhZ2UgaW5jbHVkaW5nIHRoZSBlcnJvciBjb2RlXG4gICAgICAvLyBmcm9tIHRoZSBuYW1lLlxuICAgICAgdGhpcy5zdGFjayAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC1leHByZXNzaW9uc1xuICAgICAgLy8gUmVzZXQgdGhlIG5hbWUgdG8gdGhlIGFjdHVhbCBuYW1lLlxuICAgICAgZGVsZXRlIHRoaXMubmFtZVxuICAgIH1cblxuICAgIGdldCBjb2RlICgpIHtcbiAgICAgIHJldHVybiBzeW1cbiAgICB9XG5cbiAgICBzZXQgY29kZSAodmFsdWUpIHtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnY29kZScsIHtcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICB2YWx1ZSxcbiAgICAgICAgd3JpdGFibGU6IHRydWVcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgdG9TdHJpbmcgKCkge1xuICAgICAgcmV0dXJuIGAke3RoaXMubmFtZX0gWyR7c3ltfV06ICR7dGhpcy5tZXNzYWdlfWBcbiAgICB9XG4gIH1cbn1cblxuRSgnRVJSX0JVRkZFUl9PVVRfT0ZfQk9VTkRTJyxcbiAgZnVuY3Rpb24gKG5hbWUpIHtcbiAgICBpZiAobmFtZSkge1xuICAgICAgcmV0dXJuIGAke25hbWV9IGlzIG91dHNpZGUgb2YgYnVmZmVyIGJvdW5kc2BcbiAgICB9XG5cbiAgICByZXR1cm4gJ0F0dGVtcHQgdG8gYWNjZXNzIG1lbW9yeSBvdXRzaWRlIGJ1ZmZlciBib3VuZHMnXG4gIH0sIFJhbmdlRXJyb3IpXG5FKCdFUlJfSU5WQUxJRF9BUkdfVFlQRScsXG4gIGZ1bmN0aW9uIChuYW1lLCBhY3R1YWwpIHtcbiAgICByZXR1cm4gYFRoZSBcIiR7bmFtZX1cIiBhcmd1bWVudCBtdXN0IGJlIG9mIHR5cGUgbnVtYmVyLiBSZWNlaXZlZCB0eXBlICR7dHlwZW9mIGFjdHVhbH1gXG4gIH0sIFR5cGVFcnJvcilcbkUoJ0VSUl9PVVRfT0ZfUkFOR0UnLFxuICBmdW5jdGlvbiAoc3RyLCByYW5nZSwgaW5wdXQpIHtcbiAgICBsZXQgbXNnID0gYFRoZSB2YWx1ZSBvZiBcIiR7c3RyfVwiIGlzIG91dCBvZiByYW5nZS5gXG4gICAgbGV0IHJlY2VpdmVkID0gaW5wdXRcbiAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihpbnB1dCkgJiYgTWF0aC5hYnMoaW5wdXQpID4gMiAqKiAzMikge1xuICAgICAgcmVjZWl2ZWQgPSBhZGROdW1lcmljYWxTZXBhcmF0b3IoU3RyaW5nKGlucHV0KSlcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ2JpZ2ludCcpIHtcbiAgICAgIHJlY2VpdmVkID0gU3RyaW5nKGlucHV0KVxuICAgICAgaWYgKGlucHV0ID4gQmlnSW50KDIpICoqIEJpZ0ludCgzMikgfHwgaW5wdXQgPCAtKEJpZ0ludCgyKSAqKiBCaWdJbnQoMzIpKSkge1xuICAgICAgICByZWNlaXZlZCA9IGFkZE51bWVyaWNhbFNlcGFyYXRvcihyZWNlaXZlZClcbiAgICAgIH1cbiAgICAgIHJlY2VpdmVkICs9ICduJ1xuICAgIH1cbiAgICBtc2cgKz0gYCBJdCBtdXN0IGJlICR7cmFuZ2V9LiBSZWNlaXZlZCAke3JlY2VpdmVkfWBcbiAgICByZXR1cm4gbXNnXG4gIH0sIFJhbmdlRXJyb3IpXG5cbmZ1bmN0aW9uIGFkZE51bWVyaWNhbFNlcGFyYXRvciAodmFsKSB7XG4gIGxldCByZXMgPSAnJ1xuICBsZXQgaSA9IHZhbC5sZW5ndGhcbiAgY29uc3Qgc3RhcnQgPSB2YWxbMF0gPT09ICctJyA/IDEgOiAwXG4gIGZvciAoOyBpID49IHN0YXJ0ICsgNDsgaSAtPSAzKSB7XG4gICAgcmVzID0gYF8ke3ZhbC5zbGljZShpIC0gMywgaSl9JHtyZXN9YFxuICB9XG4gIHJldHVybiBgJHt2YWwuc2xpY2UoMCwgaSl9JHtyZXN9YFxufVxuXG4vLyBDSEVDSyBGVU5DVElPTlNcbi8vID09PT09PT09PT09PT09PVxuXG5mdW5jdGlvbiBjaGVja0JvdW5kcyAoYnVmLCBvZmZzZXQsIGJ5dGVMZW5ndGgpIHtcbiAgdmFsaWRhdGVOdW1iZXIob2Zmc2V0LCAnb2Zmc2V0JylcbiAgaWYgKGJ1ZltvZmZzZXRdID09PSB1bmRlZmluZWQgfHwgYnVmW29mZnNldCArIGJ5dGVMZW5ndGhdID09PSB1bmRlZmluZWQpIHtcbiAgICBib3VuZHNFcnJvcihvZmZzZXQsIGJ1Zi5sZW5ndGggLSAoYnl0ZUxlbmd0aCArIDEpKVxuICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrSW50QkkgKHZhbHVlLCBtaW4sIG1heCwgYnVmLCBvZmZzZXQsIGJ5dGVMZW5ndGgpIHtcbiAgaWYgKHZhbHVlID4gbWF4IHx8IHZhbHVlIDwgbWluKSB7XG4gICAgY29uc3QgbiA9IHR5cGVvZiBtaW4gPT09ICdiaWdpbnQnID8gJ24nIDogJydcbiAgICBsZXQgcmFuZ2VcbiAgICBpZiAoYnl0ZUxlbmd0aCA+IDMpIHtcbiAgICAgIGlmIChtaW4gPT09IDAgfHwgbWluID09PSBCaWdJbnQoMCkpIHtcbiAgICAgICAgcmFuZ2UgPSBgPj0gMCR7bn0gYW5kIDwgMiR7bn0gKiogJHsoYnl0ZUxlbmd0aCArIDEpICogOH0ke259YFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmFuZ2UgPSBgPj0gLSgyJHtufSAqKiAkeyhieXRlTGVuZ3RoICsgMSkgKiA4IC0gMX0ke259KSBhbmQgPCAyICoqIGAgK1xuICAgICAgICAgICAgICAgIGAkeyhieXRlTGVuZ3RoICsgMSkgKiA4IC0gMX0ke259YFxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByYW5nZSA9IGA+PSAke21pbn0ke259IGFuZCA8PSAke21heH0ke259YFxuICAgIH1cbiAgICB0aHJvdyBuZXcgZXJyb3JzLkVSUl9PVVRfT0ZfUkFOR0UoJ3ZhbHVlJywgcmFuZ2UsIHZhbHVlKVxuICB9XG4gIGNoZWNrQm91bmRzKGJ1Ziwgb2Zmc2V0LCBieXRlTGVuZ3RoKVxufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZU51bWJlciAodmFsdWUsIG5hbWUpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ251bWJlcicpIHtcbiAgICB0aHJvdyBuZXcgZXJyb3JzLkVSUl9JTlZBTElEX0FSR19UWVBFKG5hbWUsICdudW1iZXInLCB2YWx1ZSlcbiAgfVxufVxuXG5mdW5jdGlvbiBib3VuZHNFcnJvciAodmFsdWUsIGxlbmd0aCwgdHlwZSkge1xuICBpZiAoTWF0aC5mbG9vcih2YWx1ZSkgIT09IHZhbHVlKSB7XG4gICAgdmFsaWRhdGVOdW1iZXIodmFsdWUsIHR5cGUpXG4gICAgdGhyb3cgbmV3IGVycm9ycy5FUlJfT1VUX09GX1JBTkdFKHR5cGUgfHwgJ29mZnNldCcsICdhbiBpbnRlZ2VyJywgdmFsdWUpXG4gIH1cblxuICBpZiAobGVuZ3RoIDwgMCkge1xuICAgIHRocm93IG5ldyBlcnJvcnMuRVJSX0JVRkZFUl9PVVRfT0ZfQk9VTkRTKClcbiAgfVxuXG4gIHRocm93IG5ldyBlcnJvcnMuRVJSX09VVF9PRl9SQU5HRSh0eXBlIHx8ICdvZmZzZXQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYD49ICR7dHlwZSA/IDEgOiAwfSBhbmQgPD0gJHtsZW5ndGh9YCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlKVxufVxuXG4vLyBIRUxQRVIgRlVOQ1RJT05TXG4vLyA9PT09PT09PT09PT09PT09XG5cbmNvbnN0IElOVkFMSURfQkFTRTY0X1JFID0gL1teKy8wLTlBLVphLXotX10vZ1xuXG5mdW5jdGlvbiBiYXNlNjRjbGVhbiAoc3RyKSB7XG4gIC8vIE5vZGUgdGFrZXMgZXF1YWwgc2lnbnMgYXMgZW5kIG9mIHRoZSBCYXNlNjQgZW5jb2RpbmdcbiAgc3RyID0gc3RyLnNwbGl0KCc9JylbMF1cbiAgLy8gTm9kZSBzdHJpcHMgb3V0IGludmFsaWQgY2hhcmFjdGVycyBsaWtlIFxcbiBhbmQgXFx0IGZyb20gdGhlIHN0cmluZywgYmFzZTY0LWpzIGRvZXMgbm90XG4gIHN0ciA9IHN0ci50cmltKCkucmVwbGFjZShJTlZBTElEX0JBU0U2NF9SRSwgJycpXG4gIC8vIE5vZGUgY29udmVydHMgc3RyaW5ncyB3aXRoIGxlbmd0aCA8IDIgdG8gJydcbiAgaWYgKHN0ci5sZW5ndGggPCAyKSByZXR1cm4gJydcbiAgLy8gTm9kZSBhbGxvd3MgZm9yIG5vbi1wYWRkZWQgYmFzZTY0IHN0cmluZ3MgKG1pc3NpbmcgdHJhaWxpbmcgPT09KSwgYmFzZTY0LWpzIGRvZXMgbm90XG4gIHdoaWxlIChzdHIubGVuZ3RoICUgNCAhPT0gMCkge1xuICAgIHN0ciA9IHN0ciArICc9J1xuICB9XG4gIHJldHVybiBzdHJcbn1cblxuZnVuY3Rpb24gdXRmOFRvQnl0ZXMgKHN0cmluZywgdW5pdHMpIHtcbiAgdW5pdHMgPSB1bml0cyB8fCBJbmZpbml0eVxuICBsZXQgY29kZVBvaW50XG4gIGNvbnN0IGxlbmd0aCA9IHN0cmluZy5sZW5ndGhcbiAgbGV0IGxlYWRTdXJyb2dhdGUgPSBudWxsXG4gIGNvbnN0IGJ5dGVzID0gW11cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7XG4gICAgY29kZVBvaW50ID0gc3RyaW5nLmNoYXJDb2RlQXQoaSlcblxuICAgIC8vIGlzIHN1cnJvZ2F0ZSBjb21wb25lbnRcbiAgICBpZiAoY29kZVBvaW50ID4gMHhEN0ZGICYmIGNvZGVQb2ludCA8IDB4RTAwMCkge1xuICAgICAgLy8gbGFzdCBjaGFyIHdhcyBhIGxlYWRcbiAgICAgIGlmICghbGVhZFN1cnJvZ2F0ZSkge1xuICAgICAgICAvLyBubyBsZWFkIHlldFxuICAgICAgICBpZiAoY29kZVBvaW50ID4gMHhEQkZGKSB7XG4gICAgICAgICAgLy8gdW5leHBlY3RlZCB0cmFpbFxuICAgICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH0gZWxzZSBpZiAoaSArIDEgPT09IGxlbmd0aCkge1xuICAgICAgICAgIC8vIHVucGFpcmVkIGxlYWRcbiAgICAgICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gdmFsaWQgbGVhZFxuICAgICAgICBsZWFkU3Vycm9nYXRlID0gY29kZVBvaW50XG5cbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgLy8gMiBsZWFkcyBpbiBhIHJvd1xuICAgICAgaWYgKGNvZGVQb2ludCA8IDB4REMwMCkge1xuICAgICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgICAgbGVhZFN1cnJvZ2F0ZSA9IGNvZGVQb2ludFxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICAvLyB2YWxpZCBzdXJyb2dhdGUgcGFpclxuICAgICAgY29kZVBvaW50ID0gKGxlYWRTdXJyb2dhdGUgLSAweEQ4MDAgPDwgMTAgfCBjb2RlUG9pbnQgLSAweERDMDApICsgMHgxMDAwMFxuICAgIH0gZWxzZSBpZiAobGVhZFN1cnJvZ2F0ZSkge1xuICAgICAgLy8gdmFsaWQgYm1wIGNoYXIsIGJ1dCBsYXN0IGNoYXIgd2FzIGEgbGVhZFxuICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgfVxuXG4gICAgbGVhZFN1cnJvZ2F0ZSA9IG51bGxcblxuICAgIC8vIGVuY29kZSB1dGY4XG4gICAgaWYgKGNvZGVQb2ludCA8IDB4ODApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gMSkgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChjb2RlUG9pbnQpXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDgwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAyKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHg2IHwgMHhDMCxcbiAgICAgICAgY29kZVBvaW50ICYgMHgzRiB8IDB4ODBcbiAgICAgIClcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA8IDB4MTAwMDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gMykgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4QyB8IDB4RTAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDYgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ICYgMHgzRiB8IDB4ODBcbiAgICAgIClcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA8IDB4MTEwMDAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDQpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDEyIHwgMHhGMCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4QyAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHg2ICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBjb2RlIHBvaW50JylcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYnl0ZXNcbn1cblxuZnVuY3Rpb24gYXNjaWlUb0J5dGVzIChzdHIpIHtcbiAgY29uc3QgYnl0ZUFycmF5ID0gW11cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyArK2kpIHtcbiAgICAvLyBOb2RlJ3MgY29kZSBzZWVtcyB0byBiZSBkb2luZyB0aGlzIGFuZCBub3QgJiAweDdGLi5cbiAgICBieXRlQXJyYXkucHVzaChzdHIuY2hhckNvZGVBdChpKSAmIDB4RkYpXG4gIH1cbiAgcmV0dXJuIGJ5dGVBcnJheVxufVxuXG5mdW5jdGlvbiB1dGYxNmxlVG9CeXRlcyAoc3RyLCB1bml0cykge1xuICBsZXQgYywgaGksIGxvXG4gIGNvbnN0IGJ5dGVBcnJheSA9IFtdXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgKytpKSB7XG4gICAgaWYgKCh1bml0cyAtPSAyKSA8IDApIGJyZWFrXG5cbiAgICBjID0gc3RyLmNoYXJDb2RlQXQoaSlcbiAgICBoaSA9IGMgPj4gOFxuICAgIGxvID0gYyAlIDI1NlxuICAgIGJ5dGVBcnJheS5wdXNoKGxvKVxuICAgIGJ5dGVBcnJheS5wdXNoKGhpKVxuICB9XG5cbiAgcmV0dXJuIGJ5dGVBcnJheVxufVxuXG5mdW5jdGlvbiBiYXNlNjRUb0J5dGVzIChzdHIpIHtcbiAgcmV0dXJuIGJhc2U2NC50b0J5dGVBcnJheShiYXNlNjRjbGVhbihzdHIpKVxufVxuXG5mdW5jdGlvbiBibGl0QnVmZmVyIChzcmMsIGRzdCwgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgbGV0IGlcbiAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7XG4gICAgaWYgKChpICsgb2Zmc2V0ID49IGRzdC5sZW5ndGgpIHx8IChpID49IHNyYy5sZW5ndGgpKSBicmVha1xuICAgIGRzdFtpICsgb2Zmc2V0XSA9IHNyY1tpXVxuICB9XG4gIHJldHVybiBpXG59XG5cbi8vIEFycmF5QnVmZmVyIG9yIFVpbnQ4QXJyYXkgb2JqZWN0cyBmcm9tIG90aGVyIGNvbnRleHRzIChpLmUuIGlmcmFtZXMpIGRvIG5vdCBwYXNzXG4vLyB0aGUgYGluc3RhbmNlb2ZgIGNoZWNrIGJ1dCB0aGV5IHNob3VsZCBiZSB0cmVhdGVkIGFzIG9mIHRoYXQgdHlwZS5cbi8vIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXIvaXNzdWVzLzE2NlxuZnVuY3Rpb24gaXNJbnN0YW5jZSAob2JqLCB0eXBlKSB7XG4gIHJldHVybiBvYmogaW5zdGFuY2VvZiB0eXBlIHx8XG4gICAgKG9iaiAhPSBudWxsICYmIG9iai5jb25zdHJ1Y3RvciAhPSBudWxsICYmIG9iai5jb25zdHJ1Y3Rvci5uYW1lICE9IG51bGwgJiZcbiAgICAgIG9iai5jb25zdHJ1Y3Rvci5uYW1lID09PSB0eXBlLm5hbWUpXG59XG5mdW5jdGlvbiBudW1iZXJJc05hTiAob2JqKSB7XG4gIC8vIEZvciBJRTExIHN1cHBvcnRcbiAgcmV0dXJuIG9iaiAhPT0gb2JqIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tc2VsZi1jb21wYXJlXG59XG5cbi8vIENyZWF0ZSBsb29rdXAgdGFibGUgZm9yIGB0b1N0cmluZygnaGV4JylgXG4vLyBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyL2lzc3Vlcy8yMTlcbmNvbnN0IGhleFNsaWNlTG9va3VwVGFibGUgPSAoZnVuY3Rpb24gKCkge1xuICBjb25zdCBhbHBoYWJldCA9ICcwMTIzNDU2Nzg5YWJjZGVmJ1xuICBjb25zdCB0YWJsZSA9IG5ldyBBcnJheSgyNTYpXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgMTY7ICsraSkge1xuICAgIGNvbnN0IGkxNiA9IGkgKiAxNlxuICAgIGZvciAobGV0IGogPSAwOyBqIDwgMTY7ICsraikge1xuICAgICAgdGFibGVbaTE2ICsgal0gPSBhbHBoYWJldFtpXSArIGFscGhhYmV0W2pdXG4gICAgfVxuICB9XG4gIHJldHVybiB0YWJsZVxufSkoKVxuXG4vLyBSZXR1cm4gbm90IGZ1bmN0aW9uIHdpdGggRXJyb3IgaWYgQmlnSW50IG5vdCBzdXBwb3J0ZWRcbmZ1bmN0aW9uIGRlZmluZUJpZ0ludE1ldGhvZCAoZm4pIHtcbiAgcmV0dXJuIHR5cGVvZiBCaWdJbnQgPT09ICd1bmRlZmluZWQnID8gQnVmZmVyQmlnSW50Tm90RGVmaW5lZCA6IGZuXG59XG5cbmZ1bmN0aW9uIEJ1ZmZlckJpZ0ludE5vdERlZmluZWQgKCkge1xuICB0aHJvdyBuZXcgRXJyb3IoJ0JpZ0ludCBub3Qgc3VwcG9ydGVkJylcbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/buffer/index.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/camera/core-impl.js":
+/*!***********************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/camera/core-impl.js ***!
+  \***********************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   CameraImpl: () => (/* binding */ CameraImpl)\n/* harmony export */ });\nvar __extends = (undefined && undefined.__extends) || (function () {\n    var extendStatics = function (d, b) {\n        extendStatics = Object.setPrototypeOf ||\n            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n        return extendStatics(d, b);\n    };\n    return function (d, b) {\n        if (typeof b !== \"function\" && b !== null)\n            throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\n        extendStatics(d, b);\n        function __() { this.constructor = d; }\n        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n    };\n})();\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar __generator = (undefined && undefined.__generator) || function (thisArg, body) {\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n    return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n    function verb(n) { return function (v) { return step([n, v]); }; }\n    function step(op) {\n        if (f) throw new TypeError(\"Generator is already executing.\");\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\n            if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n            if (y = 0, t) op = [op[0] & 2, t.value];\n            switch (op[0]) {\n                case 0: case 1: t = op; break;\n                case 4: _.label++; return { value: op[1], done: false };\n                case 5: _.label++; y = op[1]; op = [0]; continue;\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\n                default:\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                    if (t[2]) _.ops.pop();\n                    _.trys.pop(); continue;\n            }\n            op = body.call(thisArg, _);\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n    }\n};\nvar AbstractCameraCapability = (function () {\n    function AbstractCameraCapability(name, track) {\n        this.name = name;\n        this.track = track;\n    }\n    AbstractCameraCapability.prototype.isSupported = function () {\n        if (!this.track.getCapabilities) {\n            return false;\n        }\n        return this.name in this.track.getCapabilities();\n    };\n    AbstractCameraCapability.prototype.apply = function (value) {\n        var constraint = {};\n        constraint[this.name] = value;\n        var constraints = { advanced: [constraint] };\n        return this.track.applyConstraints(constraints);\n    };\n    AbstractCameraCapability.prototype.value = function () {\n        var settings = this.track.getSettings();\n        if (this.name in settings) {\n            var settingValue = settings[this.name];\n            return settingValue;\n        }\n        return null;\n    };\n    return AbstractCameraCapability;\n}());\nvar AbstractRangeCameraCapability = (function (_super) {\n    __extends(AbstractRangeCameraCapability, _super);\n    function AbstractRangeCameraCapability(name, track) {\n        return _super.call(this, name, track) || this;\n    }\n    AbstractRangeCameraCapability.prototype.min = function () {\n        return this.getCapabilities().min;\n    };\n    AbstractRangeCameraCapability.prototype.max = function () {\n        return this.getCapabilities().max;\n    };\n    AbstractRangeCameraCapability.prototype.step = function () {\n        return this.getCapabilities().step;\n    };\n    AbstractRangeCameraCapability.prototype.apply = function (value) {\n        var constraint = {};\n        constraint[this.name] = value;\n        var constraints = { advanced: [constraint] };\n        return this.track.applyConstraints(constraints);\n    };\n    AbstractRangeCameraCapability.prototype.getCapabilities = function () {\n        this.failIfNotSupported();\n        var capabilities = this.track.getCapabilities();\n        var capability = capabilities[this.name];\n        return {\n            min: capability.min,\n            max: capability.max,\n            step: capability.step,\n        };\n    };\n    AbstractRangeCameraCapability.prototype.failIfNotSupported = function () {\n        if (!this.isSupported()) {\n            throw new Error(\"\".concat(this.name, \" capability not supported\"));\n        }\n    };\n    return AbstractRangeCameraCapability;\n}(AbstractCameraCapability));\nvar ZoomFeatureImpl = (function (_super) {\n    __extends(ZoomFeatureImpl, _super);\n    function ZoomFeatureImpl(track) {\n        return _super.call(this, \"zoom\", track) || this;\n    }\n    return ZoomFeatureImpl;\n}(AbstractRangeCameraCapability));\nvar TorchFeatureImpl = (function (_super) {\n    __extends(TorchFeatureImpl, _super);\n    function TorchFeatureImpl(track) {\n        return _super.call(this, \"torch\", track) || this;\n    }\n    return TorchFeatureImpl;\n}(AbstractCameraCapability));\nvar CameraCapabilitiesImpl = (function () {\n    function CameraCapabilitiesImpl(track) {\n        this.track = track;\n    }\n    CameraCapabilitiesImpl.prototype.zoomFeature = function () {\n        return new ZoomFeatureImpl(this.track);\n    };\n    CameraCapabilitiesImpl.prototype.torchFeature = function () {\n        return new TorchFeatureImpl(this.track);\n    };\n    return CameraCapabilitiesImpl;\n}());\nvar RenderedCameraImpl = (function () {\n    function RenderedCameraImpl(parentElement, mediaStream, callbacks) {\n        this.isClosed = false;\n        this.parentElement = parentElement;\n        this.mediaStream = mediaStream;\n        this.callbacks = callbacks;\n        this.surface = this.createVideoElement(this.parentElement.clientWidth);\n        parentElement.append(this.surface);\n    }\n    RenderedCameraImpl.prototype.createVideoElement = function (width) {\n        var videoElement = document.createElement(\"video\");\n        videoElement.style.width = \"\".concat(width, \"px\");\n        videoElement.style.display = \"block\";\n        videoElement.muted = true;\n        videoElement.setAttribute(\"muted\", \"true\");\n        videoElement.playsInline = true;\n        return videoElement;\n    };\n    RenderedCameraImpl.prototype.setupSurface = function () {\n        var _this = this;\n        this.surface.onabort = function () {\n            throw \"RenderedCameraImpl video surface onabort() called\";\n        };\n        this.surface.onerror = function () {\n            throw \"RenderedCameraImpl video surface onerror() called\";\n        };\n        var onVideoStart = function () {\n            var videoWidth = _this.surface.clientWidth;\n            var videoHeight = _this.surface.clientHeight;\n            _this.callbacks.onRenderSurfaceReady(videoWidth, videoHeight);\n            _this.surface.removeEventListener(\"playing\", onVideoStart);\n        };\n        this.surface.addEventListener(\"playing\", onVideoStart);\n        this.surface.srcObject = this.mediaStream;\n        this.surface.play();\n    };\n    RenderedCameraImpl.create = function (parentElement, mediaStream, options, callbacks) {\n        return __awaiter(this, void 0, void 0, function () {\n            var renderedCamera, aspectRatioConstraint;\n            return __generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0:\n                        renderedCamera = new RenderedCameraImpl(parentElement, mediaStream, callbacks);\n                        if (!options.aspectRatio) return [3, 2];\n                        aspectRatioConstraint = {\n                            aspectRatio: options.aspectRatio\n                        };\n                        return [4, renderedCamera.getFirstTrackOrFail().applyConstraints(aspectRatioConstraint)];\n                    case 1:\n                        _a.sent();\n                        _a.label = 2;\n                    case 2:\n                        renderedCamera.setupSurface();\n                        return [2, renderedCamera];\n                }\n            });\n        });\n    };\n    RenderedCameraImpl.prototype.failIfClosed = function () {\n        if (this.isClosed) {\n            throw \"The RenderedCamera has already been closed.\";\n        }\n    };\n    RenderedCameraImpl.prototype.getFirstTrackOrFail = function () {\n        this.failIfClosed();\n        if (this.mediaStream.getVideoTracks().length === 0) {\n            throw \"No video tracks found\";\n        }\n        return this.mediaStream.getVideoTracks()[0];\n    };\n    RenderedCameraImpl.prototype.pause = function () {\n        this.failIfClosed();\n        this.surface.pause();\n    };\n    RenderedCameraImpl.prototype.resume = function (onResumeCallback) {\n        this.failIfClosed();\n        var $this = this;\n        var onVideoResume = function () {\n            setTimeout(onResumeCallback, 200);\n            $this.surface.removeEventListener(\"playing\", onVideoResume);\n        };\n        this.surface.addEventListener(\"playing\", onVideoResume);\n        this.surface.play();\n    };\n    RenderedCameraImpl.prototype.isPaused = function () {\n        this.failIfClosed();\n        return this.surface.paused;\n    };\n    RenderedCameraImpl.prototype.getSurface = function () {\n        this.failIfClosed();\n        return this.surface;\n    };\n    RenderedCameraImpl.prototype.getRunningTrackCapabilities = function () {\n        return this.getFirstTrackOrFail().getCapabilities();\n    };\n    RenderedCameraImpl.prototype.getRunningTrackSettings = function () {\n        return this.getFirstTrackOrFail().getSettings();\n    };\n    RenderedCameraImpl.prototype.applyVideoConstraints = function (constraints) {\n        return __awaiter(this, void 0, void 0, function () {\n            return __generator(this, function (_a) {\n                if (\"aspectRatio\" in constraints) {\n                    throw \"Changing 'aspectRatio' in run-time is not yet supported.\";\n                }\n                return [2, this.getFirstTrackOrFail().applyConstraints(constraints)];\n            });\n        });\n    };\n    RenderedCameraImpl.prototype.close = function () {\n        if (this.isClosed) {\n            return Promise.resolve();\n        }\n        var $this = this;\n        return new Promise(function (resolve, _) {\n            var tracks = $this.mediaStream.getVideoTracks();\n            var tracksToClose = tracks.length;\n            var tracksClosed = 0;\n            $this.mediaStream.getVideoTracks().forEach(function (videoTrack) {\n                $this.mediaStream.removeTrack(videoTrack);\n                videoTrack.stop();\n                ++tracksClosed;\n                if (tracksClosed >= tracksToClose) {\n                    $this.isClosed = true;\n                    $this.parentElement.removeChild($this.surface);\n                    resolve();\n                }\n            });\n        });\n    };\n    RenderedCameraImpl.prototype.getCapabilities = function () {\n        return new CameraCapabilitiesImpl(this.getFirstTrackOrFail());\n    };\n    return RenderedCameraImpl;\n}());\nvar CameraImpl = (function () {\n    function CameraImpl(mediaStream) {\n        this.mediaStream = mediaStream;\n    }\n    CameraImpl.prototype.render = function (parentElement, options, callbacks) {\n        return __awaiter(this, void 0, void 0, function () {\n            return __generator(this, function (_a) {\n                return [2, RenderedCameraImpl.create(parentElement, this.mediaStream, options, callbacks)];\n            });\n        });\n    };\n    CameraImpl.create = function (videoConstraints) {\n        return __awaiter(this, void 0, void 0, function () {\n            var constraints, mediaStream;\n            return __generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0:\n                        if (!navigator.mediaDevices) {\n                            throw \"navigator.mediaDevices not supported\";\n                        }\n                        constraints = {\n                            audio: false,\n                            video: videoConstraints\n                        };\n                        return [4, navigator.mediaDevices.getUserMedia(constraints)];\n                    case 1:\n                        mediaStream = _a.sent();\n                        return [2, new CameraImpl(mediaStream)];\n                }\n            });\n        });\n    };\n    return CameraImpl;\n}());\n\n//# sourceMappingURL=core-impl.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9jYW1lcmEvY29yZS1pbXBsLmpzLmpzIiwibWFwcGluZ3MiOiI7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vY2FtZXJhL2NvcmUtaW1wbC5qcz9iNzZiIl0sInNvdXJjZXNDb250ZW50IjpbInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19hd2FpdGVyID0gKHRoaXMgJiYgdGhpcy5fX2F3YWl0ZXIpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcbiAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH1cbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xuICAgIH0pO1xufTtcbnZhciBfX2dlbmVyYXRvciA9ICh0aGlzICYmIHRoaXMuX19nZW5lcmF0b3IpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBib2R5KSB7XG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZztcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cbiAgICBmdW5jdGlvbiBzdGVwKG9wKSB7XG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcbiAgICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHtcbiAgICAgICAgICAgIGlmIChmID0gMSwgeSAmJiAodCA9IG9wWzBdICYgMiA/IHlbXCJyZXR1cm5cIl0gOiBvcFswXSA/IHlbXCJ0aHJvd1wiXSB8fCAoKHQgPSB5W1wicmV0dXJuXCJdKSAmJiB0LmNhbGwoeSksIDApIDogeS5uZXh0KSAmJiAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKSByZXR1cm4gdDtcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xuICAgIH1cbn07XG52YXIgQWJzdHJhY3RDYW1lcmFDYXBhYmlsaXR5ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBBYnN0cmFjdENhbWVyYUNhcGFiaWxpdHkobmFtZSwgdHJhY2spIHtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy50cmFjayA9IHRyYWNrO1xuICAgIH1cbiAgICBBYnN0cmFjdENhbWVyYUNhcGFiaWxpdHkucHJvdG90eXBlLmlzU3VwcG9ydGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMudHJhY2suZ2V0Q2FwYWJpbGl0aWVzKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMubmFtZSBpbiB0aGlzLnRyYWNrLmdldENhcGFiaWxpdGllcygpO1xuICAgIH07XG4gICAgQWJzdHJhY3RDYW1lcmFDYXBhYmlsaXR5LnByb3RvdHlwZS5hcHBseSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICB2YXIgY29uc3RyYWludCA9IHt9O1xuICAgICAgICBjb25zdHJhaW50W3RoaXMubmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgdmFyIGNvbnN0cmFpbnRzID0geyBhZHZhbmNlZDogW2NvbnN0cmFpbnRdIH07XG4gICAgICAgIHJldHVybiB0aGlzLnRyYWNrLmFwcGx5Q29uc3RyYWludHMoY29uc3RyYWludHMpO1xuICAgIH07XG4gICAgQWJzdHJhY3RDYW1lcmFDYXBhYmlsaXR5LnByb3RvdHlwZS52YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNldHRpbmdzID0gdGhpcy50cmFjay5nZXRTZXR0aW5ncygpO1xuICAgICAgICBpZiAodGhpcy5uYW1lIGluIHNldHRpbmdzKSB7XG4gICAgICAgICAgICB2YXIgc2V0dGluZ1ZhbHVlID0gc2V0dGluZ3NbdGhpcy5uYW1lXTtcbiAgICAgICAgICAgIHJldHVybiBzZXR0aW5nVmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICByZXR1cm4gQWJzdHJhY3RDYW1lcmFDYXBhYmlsaXR5O1xufSgpKTtcbnZhciBBYnN0cmFjdFJhbmdlQ2FtZXJhQ2FwYWJpbGl0eSA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5KG5hbWUsIHRyYWNrKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCBuYW1lLCB0cmFjaykgfHwgdGhpcztcbiAgICB9XG4gICAgQWJzdHJhY3RSYW5nZUNhbWVyYUNhcGFiaWxpdHkucHJvdG90eXBlLm1pbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q2FwYWJpbGl0aWVzKCkubWluO1xuICAgIH07XG4gICAgQWJzdHJhY3RSYW5nZUNhbWVyYUNhcGFiaWxpdHkucHJvdG90eXBlLm1heCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q2FwYWJpbGl0aWVzKCkubWF4O1xuICAgIH07XG4gICAgQWJzdHJhY3RSYW5nZUNhbWVyYUNhcGFiaWxpdHkucHJvdG90eXBlLnN0ZXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENhcGFiaWxpdGllcygpLnN0ZXA7XG4gICAgfTtcbiAgICBBYnN0cmFjdFJhbmdlQ2FtZXJhQ2FwYWJpbGl0eS5wcm90b3R5cGUuYXBwbHkgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgdmFyIGNvbnN0cmFpbnQgPSB7fTtcbiAgICAgICAgY29uc3RyYWludFt0aGlzLm5hbWVdID0gdmFsdWU7XG4gICAgICAgIHZhciBjb25zdHJhaW50cyA9IHsgYWR2YW5jZWQ6IFtjb25zdHJhaW50XSB9O1xuICAgICAgICByZXR1cm4gdGhpcy50cmFjay5hcHBseUNvbnN0cmFpbnRzKGNvbnN0cmFpbnRzKTtcbiAgICB9O1xuICAgIEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5LnByb3RvdHlwZS5nZXRDYXBhYmlsaXRpZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZmFpbElmTm90U3VwcG9ydGVkKCk7XG4gICAgICAgIHZhciBjYXBhYmlsaXRpZXMgPSB0aGlzLnRyYWNrLmdldENhcGFiaWxpdGllcygpO1xuICAgICAgICB2YXIgY2FwYWJpbGl0eSA9IGNhcGFiaWxpdGllc1t0aGlzLm5hbWVdO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbWluOiBjYXBhYmlsaXR5Lm1pbixcbiAgICAgICAgICAgIG1heDogY2FwYWJpbGl0eS5tYXgsXG4gICAgICAgICAgICBzdGVwOiBjYXBhYmlsaXR5LnN0ZXAsXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBBYnN0cmFjdFJhbmdlQ2FtZXJhQ2FwYWJpbGl0eS5wcm90b3R5cGUuZmFpbElmTm90U3VwcG9ydGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuaXNTdXBwb3J0ZWQoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiXCIuY29uY2F0KHRoaXMubmFtZSwgXCIgY2FwYWJpbGl0eSBub3Qgc3VwcG9ydGVkXCIpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5O1xufShBYnN0cmFjdENhbWVyYUNhcGFiaWxpdHkpKTtcbnZhciBab29tRmVhdHVyZUltcGwgPSAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhab29tRmVhdHVyZUltcGwsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gWm9vbUZlYXR1cmVJbXBsKHRyYWNrKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCBcInpvb21cIiwgdHJhY2spIHx8IHRoaXM7XG4gICAgfVxuICAgIHJldHVybiBab29tRmVhdHVyZUltcGw7XG59KEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5KSk7XG52YXIgVG9yY2hGZWF0dXJlSW1wbCA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFRvcmNoRmVhdHVyZUltcGwsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gVG9yY2hGZWF0dXJlSW1wbCh0cmFjaykge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgXCJ0b3JjaFwiLCB0cmFjaykgfHwgdGhpcztcbiAgICB9XG4gICAgcmV0dXJuIFRvcmNoRmVhdHVyZUltcGw7XG59KEFic3RyYWN0Q2FtZXJhQ2FwYWJpbGl0eSkpO1xudmFyIENhbWVyYUNhcGFiaWxpdGllc0ltcGwgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYUNhcGFiaWxpdGllc0ltcGwodHJhY2spIHtcbiAgICAgICAgdGhpcy50cmFjayA9IHRyYWNrO1xuICAgIH1cbiAgICBDYW1lcmFDYXBhYmlsaXRpZXNJbXBsLnByb3RvdHlwZS56b29tRmVhdHVyZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBab29tRmVhdHVyZUltcGwodGhpcy50cmFjayk7XG4gICAgfTtcbiAgICBDYW1lcmFDYXBhYmlsaXRpZXNJbXBsLnByb3RvdHlwZS50b3JjaEZlYXR1cmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBuZXcgVG9yY2hGZWF0dXJlSW1wbCh0aGlzLnRyYWNrKTtcbiAgICB9O1xuICAgIHJldHVybiBDYW1lcmFDYXBhYmlsaXRpZXNJbXBsO1xufSgpKTtcbnZhciBSZW5kZXJlZENhbWVyYUltcGwgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFJlbmRlcmVkQ2FtZXJhSW1wbChwYXJlbnRFbGVtZW50LCBtZWRpYVN0cmVhbSwgY2FsbGJhY2tzKSB7XG4gICAgICAgIHRoaXMuaXNDbG9zZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5wYXJlbnRFbGVtZW50ID0gcGFyZW50RWxlbWVudDtcbiAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IG1lZGlhU3RyZWFtO1xuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IGNhbGxiYWNrcztcbiAgICAgICAgdGhpcy5zdXJmYWNlID0gdGhpcy5jcmVhdGVWaWRlb0VsZW1lbnQodGhpcy5wYXJlbnRFbGVtZW50LmNsaWVudFdpZHRoKTtcbiAgICAgICAgcGFyZW50RWxlbWVudC5hcHBlbmQodGhpcy5zdXJmYWNlKTtcbiAgICB9XG4gICAgUmVuZGVyZWRDYW1lcmFJbXBsLnByb3RvdHlwZS5jcmVhdGVWaWRlb0VsZW1lbnQgPSBmdW5jdGlvbiAod2lkdGgpIHtcbiAgICAgICAgdmFyIHZpZGVvRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJ2aWRlb1wiKTtcbiAgICAgICAgdmlkZW9FbGVtZW50LnN0eWxlLndpZHRoID0gXCJcIi5jb25jYXQod2lkdGgsIFwicHhcIik7XG4gICAgICAgIHZpZGVvRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gXCJibG9ja1wiO1xuICAgICAgICB2aWRlb0VsZW1lbnQubXV0ZWQgPSB0cnVlO1xuICAgICAgICB2aWRlb0VsZW1lbnQuc2V0QXR0cmlidXRlKFwibXV0ZWRcIiwgXCJ0cnVlXCIpO1xuICAgICAgICB2aWRlb0VsZW1lbnQucGxheXNJbmxpbmUgPSB0cnVlO1xuICAgICAgICByZXR1cm4gdmlkZW9FbGVtZW50O1xuICAgIH07XG4gICAgUmVuZGVyZWRDYW1lcmFJbXBsLnByb3RvdHlwZS5zZXR1cFN1cmZhY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuc3VyZmFjZS5vbmFib3J0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhyb3cgXCJSZW5kZXJlZENhbWVyYUltcGwgdmlkZW8gc3VyZmFjZSBvbmFib3J0KCkgY2FsbGVkXCI7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc3VyZmFjZS5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhyb3cgXCJSZW5kZXJlZENhbWVyYUltcGwgdmlkZW8gc3VyZmFjZSBvbmVycm9yKCkgY2FsbGVkXCI7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBvblZpZGVvU3RhcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgdmlkZW9XaWR0aCA9IF90aGlzLnN1cmZhY2UuY2xpZW50V2lkdGg7XG4gICAgICAgICAgICB2YXIgdmlkZW9IZWlnaHQgPSBfdGhpcy5zdXJmYWNlLmNsaWVudEhlaWdodDtcbiAgICAgICAgICAgIF90aGlzLmNhbGxiYWNrcy5vblJlbmRlclN1cmZhY2VSZWFkeSh2aWRlb1dpZHRoLCB2aWRlb0hlaWdodCk7XG4gICAgICAgICAgICBfdGhpcy5zdXJmYWNlLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJwbGF5aW5nXCIsIG9uVmlkZW9TdGFydCk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc3VyZmFjZS5hZGRFdmVudExpc3RlbmVyKFwicGxheWluZ1wiLCBvblZpZGVvU3RhcnQpO1xuICAgICAgICB0aGlzLnN1cmZhY2Uuc3JjT2JqZWN0ID0gdGhpcy5tZWRpYVN0cmVhbTtcbiAgICAgICAgdGhpcy5zdXJmYWNlLnBsYXkoKTtcbiAgICB9O1xuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5jcmVhdGUgPSBmdW5jdGlvbiAocGFyZW50RWxlbWVudCwgbWVkaWFTdHJlYW0sIG9wdGlvbnMsIGNhbGxiYWNrcykge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgcmVuZGVyZWRDYW1lcmEsIGFzcGVjdFJhdGlvQ29uc3RyYWludDtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQ2FtZXJhID0gbmV3IFJlbmRlcmVkQ2FtZXJhSW1wbChwYXJlbnRFbGVtZW50LCBtZWRpYVN0cmVhbSwgY2FsbGJhY2tzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghb3B0aW9ucy5hc3BlY3RSYXRpbykgcmV0dXJuIFszLCAyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFzcGVjdFJhdGlvQ29uc3RyYWludCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3BlY3RSYXRpbzogb3B0aW9ucy5hc3BlY3RSYXRpb1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbNCwgcmVuZGVyZWRDYW1lcmEuZ2V0Rmlyc3RUcmFja09yRmFpbCgpLmFwcGx5Q29uc3RyYWludHMoYXNwZWN0UmF0aW9Db25zdHJhaW50KV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLmxhYmVsID0gMjtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRDYW1lcmEuc2V0dXBTdXJmYWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIsIHJlbmRlcmVkQ2FtZXJhXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmZhaWxJZkNsb3NlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNDbG9zZWQpIHtcbiAgICAgICAgICAgIHRocm93IFwiVGhlIFJlbmRlcmVkQ2FtZXJhIGhhcyBhbHJlYWR5IGJlZW4gY2xvc2VkLlwiO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmdldEZpcnN0VHJhY2tPckZhaWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZmFpbElmQ2xvc2VkKCk7XG4gICAgICAgIGlmICh0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICB0aHJvdyBcIk5vIHZpZGVvIHRyYWNrcyBmb3VuZFwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLnBhdXNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZhaWxJZkNsb3NlZCgpO1xuICAgICAgICB0aGlzLnN1cmZhY2UucGF1c2UoKTtcbiAgICB9O1xuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5wcm90b3R5cGUucmVzdW1lID0gZnVuY3Rpb24gKG9uUmVzdW1lQ2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5mYWlsSWZDbG9zZWQoKTtcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgdmFyIG9uVmlkZW9SZXN1bWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KG9uUmVzdW1lQ2FsbGJhY2ssIDIwMCk7XG4gICAgICAgICAgICAkdGhpcy5zdXJmYWNlLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJwbGF5aW5nXCIsIG9uVmlkZW9SZXN1bWUpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnN1cmZhY2UuYWRkRXZlbnRMaXN0ZW5lcihcInBsYXlpbmdcIiwgb25WaWRlb1Jlc3VtZSk7XG4gICAgICAgIHRoaXMuc3VyZmFjZS5wbGF5KCk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmlzUGF1c2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZhaWxJZkNsb3NlZCgpO1xuICAgICAgICByZXR1cm4gdGhpcy5zdXJmYWNlLnBhdXNlZDtcbiAgICB9O1xuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5wcm90b3R5cGUuZ2V0U3VyZmFjZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5mYWlsSWZDbG9zZWQoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3VyZmFjZTtcbiAgICB9O1xuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5wcm90b3R5cGUuZ2V0UnVubmluZ1RyYWNrQ2FwYWJpbGl0aWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRGaXJzdFRyYWNrT3JGYWlsKCkuZ2V0Q2FwYWJpbGl0aWVzKCk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmdldFJ1bm5pbmdUcmFja1NldHRpbmdzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRGaXJzdFRyYWNrT3JGYWlsKCkuZ2V0U2V0dGluZ3MoKTtcbiAgICB9O1xuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5wcm90b3R5cGUuYXBwbHlWaWRlb0NvbnN0cmFpbnRzID0gZnVuY3Rpb24gKGNvbnN0cmFpbnRzKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBpZiAoXCJhc3BlY3RSYXRpb1wiIGluIGNvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwiQ2hhbmdpbmcgJ2FzcGVjdFJhdGlvJyBpbiBydW4tdGltZSBpcyBub3QgeWV0IHN1cHBvcnRlZC5cIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIFsyLCB0aGlzLmdldEZpcnN0VHJhY2tPckZhaWwoKS5hcHBseUNvbnN0cmFpbnRzKGNvbnN0cmFpbnRzKV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmNsb3NlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pc0Nsb3NlZCkge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgXykge1xuICAgICAgICAgICAgdmFyIHRyYWNrcyA9ICR0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCk7XG4gICAgICAgICAgICB2YXIgdHJhY2tzVG9DbG9zZSA9IHRyYWNrcy5sZW5ndGg7XG4gICAgICAgICAgICB2YXIgdHJhY2tzQ2xvc2VkID0gMDtcbiAgICAgICAgICAgICR0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbiAodmlkZW9UcmFjaykge1xuICAgICAgICAgICAgICAgICR0aGlzLm1lZGlhU3RyZWFtLnJlbW92ZVRyYWNrKHZpZGVvVHJhY2spO1xuICAgICAgICAgICAgICAgIHZpZGVvVHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgICAgICsrdHJhY2tzQ2xvc2VkO1xuICAgICAgICAgICAgICAgIGlmICh0cmFja3NDbG9zZWQgPj0gdHJhY2tzVG9DbG9zZSkge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5pc0Nsb3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICR0aGlzLnBhcmVudEVsZW1lbnQucmVtb3ZlQ2hpbGQoJHRoaXMuc3VyZmFjZSk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmdldENhcGFiaWxpdGllcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDYW1lcmFDYXBhYmlsaXRpZXNJbXBsKHRoaXMuZ2V0Rmlyc3RUcmFja09yRmFpbCgpKTtcbiAgICB9O1xuICAgIHJldHVybiBSZW5kZXJlZENhbWVyYUltcGw7XG59KCkpO1xudmFyIENhbWVyYUltcGwgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYUltcGwobWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IG1lZGlhU3RyZWFtO1xuICAgIH1cbiAgICBDYW1lcmFJbXBsLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocGFyZW50RWxlbWVudCwgb3B0aW9ucywgY2FsbGJhY2tzKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gWzIsIFJlbmRlcmVkQ2FtZXJhSW1wbC5jcmVhdGUocGFyZW50RWxlbWVudCwgdGhpcy5tZWRpYVN0cmVhbSwgb3B0aW9ucywgY2FsbGJhY2tzKV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDYW1lcmFJbXBsLmNyZWF0ZSA9IGZ1bmN0aW9uICh2aWRlb0NvbnN0cmFpbnRzKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjb25zdHJhaW50cywgbWVkaWFTdHJlYW07XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChfYS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW5hdmlnYXRvci5tZWRpYURldmljZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBcIm5hdmlnYXRvci5tZWRpYURldmljZXMgbm90IHN1cHBvcnRlZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiB2aWRlb0NvbnN0cmFpbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFs0LCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cyldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbSA9IF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiwgbmV3IENhbWVyYUltcGwobWVkaWFTdHJlYW0pXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gQ2FtZXJhSW1wbDtcbn0oKSk7XG5leHBvcnQgeyBDYW1lcmFJbXBsIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jb3JlLWltcGwuanMubWFwIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/camera/core-impl.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/camera/factories.js":
+/*!***********************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/camera/factories.js ***!
+  \***********************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   CameraFactory: () => (/* binding */ CameraFactory)\n/* harmony export */ });\n/* harmony import */ var _core_impl__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core-impl */ \"./node_modules/html5-qrcode/esm/camera/core-impl.js\");\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar __generator = (undefined && undefined.__generator) || function (thisArg, body) {\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n    return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n    function verb(n) { return function (v) { return step([n, v]); }; }\n    function step(op) {\n        if (f) throw new TypeError(\"Generator is already executing.\");\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\n            if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n            if (y = 0, t) op = [op[0] & 2, t.value];\n            switch (op[0]) {\n                case 0: case 1: t = op; break;\n                case 4: _.label++; return { value: op[1], done: false };\n                case 5: _.label++; y = op[1]; op = [0]; continue;\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\n                default:\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                    if (t[2]) _.ops.pop();\n                    _.trys.pop(); continue;\n            }\n            op = body.call(thisArg, _);\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n    }\n};\n\nvar CameraFactory = (function () {\n    function CameraFactory() {\n    }\n    CameraFactory.failIfNotSupported = function () {\n        return __awaiter(this, void 0, void 0, function () {\n            return __generator(this, function (_a) {\n                if (!navigator.mediaDevices) {\n                    throw \"navigator.mediaDevices not supported\";\n                }\n                return [2, new CameraFactory()];\n            });\n        });\n    };\n    CameraFactory.prototype.create = function (videoConstraints) {\n        return __awaiter(this, void 0, void 0, function () {\n            return __generator(this, function (_a) {\n                return [2, _core_impl__WEBPACK_IMPORTED_MODULE_0__.CameraImpl.create(videoConstraints)];\n            });\n        });\n    };\n    return CameraFactory;\n}());\n\n//# sourceMappingURL=factories.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9jYW1lcmEvZmFjdG9yaWVzLmpzLmpzIiwibWFwcGluZ3MiOiI7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9jYW1lcmEvZmFjdG9yaWVzLmpzPzdlYzciXSwic291cmNlc0NvbnRlbnQiOlsidmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcbiAgICB9KTtcbn07XG52YXIgX19nZW5lcmF0b3IgPSAodGhpcyAmJiB0aGlzLl9fZ2VuZXJhdG9yKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgYm9keSkge1xuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XG4gICAgICAgIHdoaWxlIChnICYmIChnID0gMCwgb3BbMF0gJiYgKF8gPSAwKSksIF8pIHRyeSB7XG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcbiAgICB9XG59O1xuaW1wb3J0IHsgQ2FtZXJhSW1wbCB9IGZyb20gXCIuL2NvcmUtaW1wbFwiO1xudmFyIENhbWVyYUZhY3RvcnkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYUZhY3RvcnkoKSB7XG4gICAgfVxuICAgIENhbWVyYUZhY3RvcnkuZmFpbElmTm90U3VwcG9ydGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFuYXZpZ2F0b3IubWVkaWFEZXZpY2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwibmF2aWdhdG9yLm1lZGlhRGV2aWNlcyBub3Qgc3VwcG9ydGVkXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBbMiwgbmV3IENhbWVyYUZhY3RvcnkoKV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDYW1lcmFGYWN0b3J5LnByb3RvdHlwZS5jcmVhdGUgPSBmdW5jdGlvbiAodmlkZW9Db25zdHJhaW50cykge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFsyLCBDYW1lcmFJbXBsLmNyZWF0ZSh2aWRlb0NvbnN0cmFpbnRzKV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gQ2FtZXJhRmFjdG9yeTtcbn0oKSk7XG5leHBvcnQgeyBDYW1lcmFGYWN0b3J5IH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1mYWN0b3JpZXMuanMubWFwIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/camera/factories.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/camera/permissions.js":
+/*!*************************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/camera/permissions.js ***!
+  \*************************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   CameraPermissions: () => (/* binding */ CameraPermissions)\n/* harmony export */ });\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar __generator = (undefined && undefined.__generator) || function (thisArg, body) {\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n    return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n    function verb(n) { return function (v) { return step([n, v]); }; }\n    function step(op) {\n        if (f) throw new TypeError(\"Generator is already executing.\");\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\n            if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n            if (y = 0, t) op = [op[0] & 2, t.value];\n            switch (op[0]) {\n                case 0: case 1: t = op; break;\n                case 4: _.label++; return { value: op[1], done: false };\n                case 5: _.label++; y = op[1]; op = [0]; continue;\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\n                default:\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                    if (t[2]) _.ops.pop();\n                    _.trys.pop(); continue;\n            }\n            op = body.call(thisArg, _);\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n    }\n};\nvar CameraPermissions = (function () {\n    function CameraPermissions() {\n    }\n    CameraPermissions.hasPermissions = function () {\n        return __awaiter(this, void 0, void 0, function () {\n            var devices, _i, devices_1, device;\n            return __generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0: return [4, navigator.mediaDevices.enumerateDevices()];\n                    case 1:\n                        devices = _a.sent();\n                        for (_i = 0, devices_1 = devices; _i < devices_1.length; _i++) {\n                            device = devices_1[_i];\n                            if (device.kind === \"videoinput\" && device.label) {\n                                return [2, true];\n                            }\n                        }\n                        return [2, false];\n                }\n            });\n        });\n    };\n    return CameraPermissions;\n}());\n\n//# sourceMappingURL=permissions.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9jYW1lcmEvcGVybWlzc2lvbnMuanMuanMiLCJtYXBwaW5ncyI6Ijs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9jYW1lcmEvcGVybWlzc2lvbnMuanM/NzAwOSJdLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgX19hd2FpdGVyID0gKHRoaXMgJiYgdGhpcy5fX2F3YWl0ZXIpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcbiAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH1cbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xuICAgIH0pO1xufTtcbnZhciBfX2dlbmVyYXRvciA9ICh0aGlzICYmIHRoaXMuX19nZW5lcmF0b3IpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBib2R5KSB7XG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZztcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cbiAgICBmdW5jdGlvbiBzdGVwKG9wKSB7XG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcbiAgICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHtcbiAgICAgICAgICAgIGlmIChmID0gMSwgeSAmJiAodCA9IG9wWzBdICYgMiA/IHlbXCJyZXR1cm5cIl0gOiBvcFswXSA/IHlbXCJ0aHJvd1wiXSB8fCAoKHQgPSB5W1wicmV0dXJuXCJdKSAmJiB0LmNhbGwoeSksIDApIDogeS5uZXh0KSAmJiAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKSByZXR1cm4gdDtcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xuICAgIH1cbn07XG52YXIgQ2FtZXJhUGVybWlzc2lvbnMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYVBlcm1pc3Npb25zKCkge1xuICAgIH1cbiAgICBDYW1lcmFQZXJtaXNzaW9ucy5oYXNQZXJtaXNzaW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGRldmljZXMsIF9pLCBkZXZpY2VzXzEsIGRldmljZTtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDogcmV0dXJuIFs0LCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmVudW1lcmF0ZURldmljZXMoKV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIGRldmljZXMgPSBfYS5zZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKF9pID0gMCwgZGV2aWNlc18xID0gZGV2aWNlczsgX2kgPCBkZXZpY2VzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2aWNlID0gZGV2aWNlc18xW19pXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGV2aWNlLmtpbmQgPT09IFwidmlkZW9pbnB1dFwiICYmIGRldmljZS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIsIHRydWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiwgZmFsc2VdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIHJldHVybiBDYW1lcmFQZXJtaXNzaW9ucztcbn0oKSk7XG5leHBvcnQgeyBDYW1lcmFQZXJtaXNzaW9ucyB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cGVybWlzc2lvbnMuanMubWFwIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/camera/permissions.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/camera/retriever.js":
+/*!***********************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/camera/retriever.js ***!
+  \***********************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   CameraRetriever: () => (/* binding */ CameraRetriever)\n/* harmony export */ });\n/* harmony import */ var _strings__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../strings */ \"./node_modules/html5-qrcode/esm/strings.js\");\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar __generator = (undefined && undefined.__generator) || function (thisArg, body) {\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n    return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n    function verb(n) { return function (v) { return step([n, v]); }; }\n    function step(op) {\n        if (f) throw new TypeError(\"Generator is already executing.\");\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\n            if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n            if (y = 0, t) op = [op[0] & 2, t.value];\n            switch (op[0]) {\n                case 0: case 1: t = op; break;\n                case 4: _.label++; return { value: op[1], done: false };\n                case 5: _.label++; y = op[1]; op = [0]; continue;\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\n                default:\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                    if (t[2]) _.ops.pop();\n                    _.trys.pop(); continue;\n            }\n            op = body.call(thisArg, _);\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n    }\n};\n\nvar CameraRetriever = (function () {\n    function CameraRetriever() {\n    }\n    CameraRetriever.retrieve = function () {\n        if (navigator.mediaDevices) {\n            return CameraRetriever.getCamerasFromMediaDevices();\n        }\n        var mst = MediaStreamTrack;\n        if (MediaStreamTrack && mst.getSources) {\n            return CameraRetriever.getCamerasFromMediaStreamTrack();\n        }\n        return CameraRetriever.rejectWithError();\n    };\n    CameraRetriever.rejectWithError = function () {\n        var errorMessage = _strings__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeStrings.unableToQuerySupportedDevices();\n        if (!CameraRetriever.isHttpsOrLocalhost()) {\n            errorMessage = _strings__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeStrings.insecureContextCameraQueryError();\n        }\n        return Promise.reject(errorMessage);\n    };\n    CameraRetriever.isHttpsOrLocalhost = function () {\n        if (location.protocol === \"https:\") {\n            return true;\n        }\n        var host = location.host.split(\":\")[0];\n        return host === \"127.0.0.1\" || host === \"localhost\";\n    };\n    CameraRetriever.getCamerasFromMediaDevices = function () {\n        return __awaiter(this, void 0, void 0, function () {\n            var closeActiveStreams, mediaStream, devices, results, _i, devices_1, device;\n            return __generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0:\n                        closeActiveStreams = function (stream) {\n                            var tracks = stream.getVideoTracks();\n                            for (var _i = 0, tracks_1 = tracks; _i < tracks_1.length; _i++) {\n                                var track = tracks_1[_i];\n                                track.enabled = false;\n                                track.stop();\n                                stream.removeTrack(track);\n                            }\n                        };\n                        return [4, navigator.mediaDevices.getUserMedia({ audio: false, video: true })];\n                    case 1:\n                        mediaStream = _a.sent();\n                        return [4, navigator.mediaDevices.enumerateDevices()];\n                    case 2:\n                        devices = _a.sent();\n                        results = [];\n                        for (_i = 0, devices_1 = devices; _i < devices_1.length; _i++) {\n                            device = devices_1[_i];\n                            if (device.kind === \"videoinput\") {\n                                results.push({\n                                    id: device.deviceId,\n                                    label: device.label\n                                });\n                            }\n                        }\n                        closeActiveStreams(mediaStream);\n                        return [2, results];\n                }\n            });\n        });\n    };\n    CameraRetriever.getCamerasFromMediaStreamTrack = function () {\n        return new Promise(function (resolve, _) {\n            var callback = function (sourceInfos) {\n                var results = [];\n                for (var _i = 0, sourceInfos_1 = sourceInfos; _i < sourceInfos_1.length; _i++) {\n                    var sourceInfo = sourceInfos_1[_i];\n                    if (sourceInfo.kind === \"video\") {\n                        results.push({\n                            id: sourceInfo.id,\n                            label: sourceInfo.label\n                        });\n                    }\n                }\n                resolve(results);\n            };\n            var mst = MediaStreamTrack;\n            mst.getSources(callback);\n        });\n    };\n    return CameraRetriever;\n}());\n\n//# sourceMappingURL=retriever.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9jYW1lcmEvcmV0cmlldmVyLmpzLmpzIiwibWFwcGluZ3MiOiI7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9jYW1lcmEvcmV0cmlldmVyLmpzPzUzMDIiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcbiAgICB9KTtcbn07XG52YXIgX19nZW5lcmF0b3IgPSAodGhpcyAmJiB0aGlzLl9fZ2VuZXJhdG9yKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgYm9keSkge1xuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XG4gICAgICAgIHdoaWxlIChnICYmIChnID0gMCwgb3BbMF0gJiYgKF8gPSAwKSksIF8pIHRyeSB7XG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcbiAgICB9XG59O1xuaW1wb3J0IHsgSHRtbDVRcmNvZGVTdHJpbmdzIH0gZnJvbSBcIi4uL3N0cmluZ3NcIjtcbnZhciBDYW1lcmFSZXRyaWV2ZXIgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYVJldHJpZXZlcigpIHtcbiAgICB9XG4gICAgQ2FtZXJhUmV0cmlldmVyLnJldHJpZXZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAobmF2aWdhdG9yLm1lZGlhRGV2aWNlcykge1xuICAgICAgICAgICAgcmV0dXJuIENhbWVyYVJldHJpZXZlci5nZXRDYW1lcmFzRnJvbU1lZGlhRGV2aWNlcygpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtc3QgPSBNZWRpYVN0cmVhbVRyYWNrO1xuICAgICAgICBpZiAoTWVkaWFTdHJlYW1UcmFjayAmJiBtc3QuZ2V0U291cmNlcykge1xuICAgICAgICAgICAgcmV0dXJuIENhbWVyYVJldHJpZXZlci5nZXRDYW1lcmFzRnJvbU1lZGlhU3RyZWFtVHJhY2soKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gQ2FtZXJhUmV0cmlldmVyLnJlamVjdFdpdGhFcnJvcigpO1xuICAgIH07XG4gICAgQ2FtZXJhUmV0cmlldmVyLnJlamVjdFdpdGhFcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGVycm9yTWVzc2FnZSA9IEh0bWw1UXJjb2RlU3RyaW5ncy51bmFibGVUb1F1ZXJ5U3VwcG9ydGVkRGV2aWNlcygpO1xuICAgICAgICBpZiAoIUNhbWVyYVJldHJpZXZlci5pc0h0dHBzT3JMb2NhbGhvc3QoKSkge1xuICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gSHRtbDVRcmNvZGVTdHJpbmdzLmluc2VjdXJlQ29udGV4dENhbWVyYVF1ZXJ5RXJyb3IoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyb3JNZXNzYWdlKTtcbiAgICB9O1xuICAgIENhbWVyYVJldHJpZXZlci5pc0h0dHBzT3JMb2NhbGhvc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChsb2NhdGlvbi5wcm90b2NvbCA9PT0gXCJodHRwczpcIikge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGhvc3QgPSBsb2NhdGlvbi5ob3N0LnNwbGl0KFwiOlwiKVswXTtcbiAgICAgICAgcmV0dXJuIGhvc3QgPT09IFwiMTI3LjAuMC4xXCIgfHwgaG9zdCA9PT0gXCJsb2NhbGhvc3RcIjtcbiAgICB9O1xuICAgIENhbWVyYVJldHJpZXZlci5nZXRDYW1lcmFzRnJvbU1lZGlhRGV2aWNlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGNsb3NlQWN0aXZlU3RyZWFtcywgbWVkaWFTdHJlYW0sIGRldmljZXMsIHJlc3VsdHMsIF9pLCBkZXZpY2VzXzEsIGRldmljZTtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsb3NlQWN0aXZlU3RyZWFtcyA9IGZ1bmN0aW9uIChzdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdHJhY2tzID0gc3RyZWFtLmdldFZpZGVvVHJhY2tzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCB0cmFja3NfMSA9IHRyYWNrczsgX2kgPCB0cmFja3NfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRyYWNrID0gdHJhY2tzXzFbX2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5lbmFibGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLnJlbW92ZVRyYWNrKHRyYWNrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFs0LCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7IGF1ZGlvOiBmYWxzZSwgdmlkZW86IHRydWUgfSldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbSA9IF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbNCwgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXZpY2VzID0gX2Euc2VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChfaSA9IDAsIGRldmljZXNfMSA9IGRldmljZXM7IF9pIDwgZGV2aWNlc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldmljZSA9IGRldmljZXNfMVtfaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRldmljZS5raW5kID09PSBcInZpZGVvaW5wdXRcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IGRldmljZS5kZXZpY2VJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2UubGFiZWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY2xvc2VBY3RpdmVTdHJlYW1zKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiwgcmVzdWx0c107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ2FtZXJhUmV0cmlldmVyLmdldENhbWVyYXNGcm9tTWVkaWFTdHJlYW1UcmFjayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCBfKSB7XG4gICAgICAgICAgICB2YXIgY2FsbGJhY2sgPSBmdW5jdGlvbiAoc291cmNlSW5mb3MpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgc291cmNlSW5mb3NfMSA9IHNvdXJjZUluZm9zOyBfaSA8IHNvdXJjZUluZm9zXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzb3VyY2VJbmZvID0gc291cmNlSW5mb3NfMVtfaV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChzb3VyY2VJbmZvLmtpbmQgPT09IFwidmlkZW9cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZDogc291cmNlSW5mby5pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbDogc291cmNlSW5mby5sYWJlbFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShyZXN1bHRzKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIgbXN0ID0gTWVkaWFTdHJlYW1UcmFjaztcbiAgICAgICAgICAgIG1zdC5nZXRTb3VyY2VzKGNhbGxiYWNrKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gQ2FtZXJhUmV0cmlldmVyO1xufSgpKTtcbmV4cG9ydCB7IENhbWVyYVJldHJpZXZlciB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cmV0cmlldmVyLmpzLm1hcCJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/camera/retriever.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/code-decoder.js":
+/*!*******************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/code-decoder.js ***!
+  \*******************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   Html5QrcodeShim: () => (/* binding */ Html5QrcodeShim)\n/* harmony export */ });\n/* harmony import */ var _zxing_html5_qrcode_decoder__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./zxing-html5-qrcode-decoder */ \"./node_modules/html5-qrcode/esm/zxing-html5-qrcode-decoder.js\");\n/* harmony import */ var _native_bar_code_detector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./native-bar-code-detector */ \"./node_modules/html5-qrcode/esm/native-bar-code-detector.js\");\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar __generator = (undefined && undefined.__generator) || function (thisArg, body) {\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n    return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n    function verb(n) { return function (v) { return step([n, v]); }; }\n    function step(op) {\n        if (f) throw new TypeError(\"Generator is already executing.\");\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\n            if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n            if (y = 0, t) op = [op[0] & 2, t.value];\n            switch (op[0]) {\n                case 0: case 1: t = op; break;\n                case 4: _.label++; return { value: op[1], done: false };\n                case 5: _.label++; y = op[1]; op = [0]; continue;\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\n                default:\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                    if (t[2]) _.ops.pop();\n                    _.trys.pop(); continue;\n            }\n            op = body.call(thisArg, _);\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n    }\n};\n\n\nvar Html5QrcodeShim = (function () {\n    function Html5QrcodeShim(requestedFormats, useBarCodeDetectorIfSupported, verbose, logger) {\n        this.EXECUTIONS_TO_REPORT_PERFORMANCE = 100;\n        this.executions = 0;\n        this.executionResults = [];\n        this.wasPrimaryDecoderUsedInLastDecode = false;\n        this.verbose = verbose;\n        if (useBarCodeDetectorIfSupported\n            && _native_bar_code_detector__WEBPACK_IMPORTED_MODULE_1__.BarcodeDetectorDelegate.isSupported()) {\n            this.primaryDecoder = new _native_bar_code_detector__WEBPACK_IMPORTED_MODULE_1__.BarcodeDetectorDelegate(requestedFormats, verbose, logger);\n            this.secondaryDecoder = new _zxing_html5_qrcode_decoder__WEBPACK_IMPORTED_MODULE_0__.ZXingHtml5QrcodeDecoder(requestedFormats, verbose, logger);\n        }\n        else {\n            this.primaryDecoder = new _zxing_html5_qrcode_decoder__WEBPACK_IMPORTED_MODULE_0__.ZXingHtml5QrcodeDecoder(requestedFormats, verbose, logger);\n        }\n    }\n    Html5QrcodeShim.prototype.decodeAsync = function (canvas) {\n        return __awaiter(this, void 0, void 0, function () {\n            var startTime;\n            return __generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0:\n                        startTime = performance.now();\n                        _a.label = 1;\n                    case 1:\n                        _a.trys.push([1, , 3, 4]);\n                        return [4, this.getDecoder().decodeAsync(canvas)];\n                    case 2: return [2, _a.sent()];\n                    case 3:\n                        this.possiblyLogPerformance(startTime);\n                        return [7];\n                    case 4: return [2];\n                }\n            });\n        });\n    };\n    Html5QrcodeShim.prototype.decodeRobustlyAsync = function (canvas) {\n        return __awaiter(this, void 0, void 0, function () {\n            var startTime, error_1;\n            return __generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0:\n                        startTime = performance.now();\n                        _a.label = 1;\n                    case 1:\n                        _a.trys.push([1, 3, 4, 5]);\n                        return [4, this.primaryDecoder.decodeAsync(canvas)];\n                    case 2: return [2, _a.sent()];\n                    case 3:\n                        error_1 = _a.sent();\n                        if (this.secondaryDecoder) {\n                            return [2, this.secondaryDecoder.decodeAsync(canvas)];\n                        }\n                        throw error_1;\n                    case 4:\n                        this.possiblyLogPerformance(startTime);\n                        return [7];\n                    case 5: return [2];\n                }\n            });\n        });\n    };\n    Html5QrcodeShim.prototype.getDecoder = function () {\n        if (!this.secondaryDecoder) {\n            return this.primaryDecoder;\n        }\n        if (this.wasPrimaryDecoderUsedInLastDecode === false) {\n            this.wasPrimaryDecoderUsedInLastDecode = true;\n            return this.primaryDecoder;\n        }\n        this.wasPrimaryDecoderUsedInLastDecode = false;\n        return this.secondaryDecoder;\n    };\n    Html5QrcodeShim.prototype.possiblyLogPerformance = function (startTime) {\n        if (!this.verbose) {\n            return;\n        }\n        var executionTime = performance.now() - startTime;\n        this.executionResults.push(executionTime);\n        this.executions++;\n        this.possiblyFlushPerformanceReport();\n    };\n    Html5QrcodeShim.prototype.possiblyFlushPerformanceReport = function () {\n        if (this.executions < this.EXECUTIONS_TO_REPORT_PERFORMANCE) {\n            return;\n        }\n        var sum = 0;\n        for (var _i = 0, _a = this.executionResults; _i < _a.length; _i++) {\n            var executionTime = _a[_i];\n            sum += executionTime;\n        }\n        var mean = sum / this.executionResults.length;\n        console.log(\"\".concat(mean, \" ms for \").concat(this.executionResults.length, \" last runs.\"));\n        this.executions = 0;\n        this.executionResults = [];\n    };\n    return Html5QrcodeShim;\n}());\n\n//# sourceMappingURL=code-decoder.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9jb2RlLWRlY29kZXIuanMuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vY29kZS1kZWNvZGVyLmpzP2U4MjQiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcbiAgICB9KTtcbn07XG52YXIgX19nZW5lcmF0b3IgPSAodGhpcyAmJiB0aGlzLl9fZ2VuZXJhdG9yKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgYm9keSkge1xuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XG4gICAgICAgIHdoaWxlIChnICYmIChnID0gMCwgb3BbMF0gJiYgKF8gPSAwKSksIF8pIHRyeSB7XG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcbiAgICB9XG59O1xuaW1wb3J0IHsgWlhpbmdIdG1sNVFyY29kZURlY29kZXIgfSBmcm9tIFwiLi96eGluZy1odG1sNS1xcmNvZGUtZGVjb2RlclwiO1xuaW1wb3J0IHsgQmFyY29kZURldGVjdG9yRGVsZWdhdGUgfSBmcm9tIFwiLi9uYXRpdmUtYmFyLWNvZGUtZGV0ZWN0b3JcIjtcbnZhciBIdG1sNVFyY29kZVNoaW0gPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEh0bWw1UXJjb2RlU2hpbShyZXF1ZXN0ZWRGb3JtYXRzLCB1c2VCYXJDb2RlRGV0ZWN0b3JJZlN1cHBvcnRlZCwgdmVyYm9zZSwgbG9nZ2VyKSB7XG4gICAgICAgIHRoaXMuRVhFQ1VUSU9OU19UT19SRVBPUlRfUEVSRk9STUFOQ0UgPSAxMDA7XG4gICAgICAgIHRoaXMuZXhlY3V0aW9ucyA9IDA7XG4gICAgICAgIHRoaXMuZXhlY3V0aW9uUmVzdWx0cyA9IFtdO1xuICAgICAgICB0aGlzLndhc1ByaW1hcnlEZWNvZGVyVXNlZEluTGFzdERlY29kZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLnZlcmJvc2UgPSB2ZXJib3NlO1xuICAgICAgICBpZiAodXNlQmFyQ29kZURldGVjdG9ySWZTdXBwb3J0ZWRcbiAgICAgICAgICAgICYmIEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlLmlzU3VwcG9ydGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMucHJpbWFyeURlY29kZXIgPSBuZXcgQmFyY29kZURldGVjdG9yRGVsZWdhdGUocmVxdWVzdGVkRm9ybWF0cywgdmVyYm9zZSwgbG9nZ2VyKTtcbiAgICAgICAgICAgIHRoaXMuc2Vjb25kYXJ5RGVjb2RlciA9IG5ldyBaWGluZ0h0bWw1UXJjb2RlRGVjb2RlcihyZXF1ZXN0ZWRGb3JtYXRzLCB2ZXJib3NlLCBsb2dnZXIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5wcmltYXJ5RGVjb2RlciA9IG5ldyBaWGluZ0h0bWw1UXJjb2RlRGVjb2RlcihyZXF1ZXN0ZWRGb3JtYXRzLCB2ZXJib3NlLCBsb2dnZXIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIEh0bWw1UXJjb2RlU2hpbS5wcm90b3R5cGUuZGVjb2RlQXN5bmMgPSBmdW5jdGlvbiAoY2FudmFzKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzdGFydFRpbWU7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChfYS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydFRpbWUgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLmxhYmVsID0gMTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgX2EudHJ5cy5wdXNoKFsxLCAsIDMsIDRdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbNCwgdGhpcy5nZXREZWNvZGVyKCkuZGVjb2RlQXN5bmMoY2FudmFzKV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjogcmV0dXJuIFsyLCBfYS5zZW50KCldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBvc3NpYmx5TG9nUGVyZm9ybWFuY2Uoc3RhcnRUaW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbN107XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDogcmV0dXJuIFsyXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNoaW0ucHJvdG90eXBlLmRlY29kZVJvYnVzdGx5QXN5bmMgPSBmdW5jdGlvbiAoY2FudmFzKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzdGFydFRpbWUsIGVycm9yXzE7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChfYS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydFRpbWUgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLmxhYmVsID0gMTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgX2EudHJ5cy5wdXNoKFsxLCAzLCA0LCA1XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQsIHRoaXMucHJpbWFyeURlY29kZXIuZGVjb2RlQXN5bmMoY2FudmFzKV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjogcmV0dXJuIFsyLCBfYS5zZW50KCldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl8xID0gX2Euc2VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2Vjb25kYXJ5RGVjb2Rlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiwgdGhpcy5zZWNvbmRhcnlEZWNvZGVyLmRlY29kZUFzeW5jKGNhbnZhcyldO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyb3JfMTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wb3NzaWJseUxvZ1BlcmZvcm1hbmNlKHN0YXJ0VGltZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzddO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6IHJldHVybiBbMl07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTaGltLnByb3RvdHlwZS5nZXREZWNvZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuc2Vjb25kYXJ5RGVjb2Rlcikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJpbWFyeURlY29kZXI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMud2FzUHJpbWFyeURlY29kZXJVc2VkSW5MYXN0RGVjb2RlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgdGhpcy53YXNQcmltYXJ5RGVjb2RlclVzZWRJbkxhc3REZWNvZGUgPSB0cnVlO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJpbWFyeURlY29kZXI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy53YXNQcmltYXJ5RGVjb2RlclVzZWRJbkxhc3REZWNvZGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2Vjb25kYXJ5RGVjb2RlcjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2hpbS5wcm90b3R5cGUucG9zc2libHlMb2dQZXJmb3JtYW5jZSA9IGZ1bmN0aW9uIChzdGFydFRpbWUpIHtcbiAgICAgICAgaWYgKCF0aGlzLnZlcmJvc2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXhlY3V0aW9uVGltZSA9IHBlcmZvcm1hbmNlLm5vdygpIC0gc3RhcnRUaW1lO1xuICAgICAgICB0aGlzLmV4ZWN1dGlvblJlc3VsdHMucHVzaChleGVjdXRpb25UaW1lKTtcbiAgICAgICAgdGhpcy5leGVjdXRpb25zKys7XG4gICAgICAgIHRoaXMucG9zc2libHlGbHVzaFBlcmZvcm1hbmNlUmVwb3J0KCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNoaW0ucHJvdG90eXBlLnBvc3NpYmx5Rmx1c2hQZXJmb3JtYW5jZVJlcG9ydCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuZXhlY3V0aW9ucyA8IHRoaXMuRVhFQ1VUSU9OU19UT19SRVBPUlRfUEVSRk9STUFOQ0UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc3VtID0gMDtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuZXhlY3V0aW9uUmVzdWx0czsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBleGVjdXRpb25UaW1lID0gX2FbX2ldO1xuICAgICAgICAgICAgc3VtICs9IGV4ZWN1dGlvblRpbWU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1lYW4gPSBzdW0gLyB0aGlzLmV4ZWN1dGlvblJlc3VsdHMubGVuZ3RoO1xuICAgICAgICBjb25zb2xlLmxvZyhcIlwiLmNvbmNhdChtZWFuLCBcIiBtcyBmb3IgXCIpLmNvbmNhdCh0aGlzLmV4ZWN1dGlvblJlc3VsdHMubGVuZ3RoLCBcIiBsYXN0IHJ1bnMuXCIpKTtcbiAgICAgICAgdGhpcy5leGVjdXRpb25zID0gMDtcbiAgICAgICAgdGhpcy5leGVjdXRpb25SZXN1bHRzID0gW107XG4gICAgfTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGVTaGltO1xufSgpKTtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlU2hpbSB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y29kZS1kZWNvZGVyLmpzLm1hcCJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/code-decoder.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/core.js":
+/*!***********************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/core.js ***!
+  \***********************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   BaseLoggger: () => (/* binding */ BaseLoggger),\n/* harmony export */   DecodedTextType: () => (/* binding */ DecodedTextType),\n/* harmony export */   Html5QrcodeConstants: () => (/* binding */ Html5QrcodeConstants),\n/* harmony export */   Html5QrcodeErrorFactory: () => (/* binding */ Html5QrcodeErrorFactory),\n/* harmony export */   Html5QrcodeErrorTypes: () => (/* binding */ Html5QrcodeErrorTypes),\n/* harmony export */   Html5QrcodeResultFactory: () => (/* binding */ Html5QrcodeResultFactory),\n/* harmony export */   Html5QrcodeScanType: () => (/* binding */ Html5QrcodeScanType),\n/* harmony export */   Html5QrcodeSupportedFormats: () => (/* binding */ Html5QrcodeSupportedFormats),\n/* harmony export */   QrcodeResultFormat: () => (/* binding */ QrcodeResultFormat),\n/* harmony export */   clip: () => (/* binding */ clip),\n/* harmony export */   isNullOrUndefined: () => (/* binding */ isNullOrUndefined),\n/* harmony export */   isValidHtml5QrcodeSupportedFormats: () => (/* binding */ isValidHtml5QrcodeSupportedFormats)\n/* harmony export */ });\nvar Html5QrcodeSupportedFormats;\n(function (Html5QrcodeSupportedFormats) {\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"QR_CODE\"] = 0] = \"QR_CODE\";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"AZTEC\"] = 1] = \"AZTEC\";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"CODABAR\"] = 2] = \"CODABAR\";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"CODE_39\"] = 3] = \"CODE_39\";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"CODE_93\"] = 4] = \"CODE_93\";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"CODE_128\"] = 5] = \"CODE_128\";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"DATA_MATRIX\"] = 6] = \"DATA_MATRIX\";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"MAXICODE\"] = 7] = \"MAXICODE\";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"ITF\"] = 8] = \"ITF\";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"EAN_13\"] = 9] = \"EAN_13\";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"EAN_8\"] = 10] = \"EAN_8\";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"PDF_417\"] = 11] = \"PDF_417\";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"RSS_14\"] = 12] = \"RSS_14\";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"RSS_EXPANDED\"] = 13] = \"RSS_EXPANDED\";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"UPC_A\"] = 14] = \"UPC_A\";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"UPC_E\"] = 15] = \"UPC_E\";\n    Html5QrcodeSupportedFormats[Html5QrcodeSupportedFormats[\"UPC_EAN_EXTENSION\"] = 16] = \"UPC_EAN_EXTENSION\";\n})(Html5QrcodeSupportedFormats || (Html5QrcodeSupportedFormats = {}));\nvar html5QrcodeSupportedFormatsTextMap = new Map([\n    [Html5QrcodeSupportedFormats.QR_CODE, \"QR_CODE\"],\n    [Html5QrcodeSupportedFormats.AZTEC, \"AZTEC\"],\n    [Html5QrcodeSupportedFormats.CODABAR, \"CODABAR\"],\n    [Html5QrcodeSupportedFormats.CODE_39, \"CODE_39\"],\n    [Html5QrcodeSupportedFormats.CODE_93, \"CODE_93\"],\n    [Html5QrcodeSupportedFormats.CODE_128, \"CODE_128\"],\n    [Html5QrcodeSupportedFormats.DATA_MATRIX, \"DATA_MATRIX\"],\n    [Html5QrcodeSupportedFormats.MAXICODE, \"MAXICODE\"],\n    [Html5QrcodeSupportedFormats.ITF, \"ITF\"],\n    [Html5QrcodeSupportedFormats.EAN_13, \"EAN_13\"],\n    [Html5QrcodeSupportedFormats.EAN_8, \"EAN_8\"],\n    [Html5QrcodeSupportedFormats.PDF_417, \"PDF_417\"],\n    [Html5QrcodeSupportedFormats.RSS_14, \"RSS_14\"],\n    [Html5QrcodeSupportedFormats.RSS_EXPANDED, \"RSS_EXPANDED\"],\n    [Html5QrcodeSupportedFormats.UPC_A, \"UPC_A\"],\n    [Html5QrcodeSupportedFormats.UPC_E, \"UPC_E\"],\n    [Html5QrcodeSupportedFormats.UPC_EAN_EXTENSION, \"UPC_EAN_EXTENSION\"]\n]);\nvar DecodedTextType;\n(function (DecodedTextType) {\n    DecodedTextType[DecodedTextType[\"UNKNOWN\"] = 0] = \"UNKNOWN\";\n    DecodedTextType[DecodedTextType[\"URL\"] = 1] = \"URL\";\n})(DecodedTextType || (DecodedTextType = {}));\nfunction isValidHtml5QrcodeSupportedFormats(format) {\n    return Object.values(Html5QrcodeSupportedFormats).includes(format);\n}\nvar Html5QrcodeScanType;\n(function (Html5QrcodeScanType) {\n    Html5QrcodeScanType[Html5QrcodeScanType[\"SCAN_TYPE_CAMERA\"] = 0] = \"SCAN_TYPE_CAMERA\";\n    Html5QrcodeScanType[Html5QrcodeScanType[\"SCAN_TYPE_FILE\"] = 1] = \"SCAN_TYPE_FILE\";\n})(Html5QrcodeScanType || (Html5QrcodeScanType = {}));\nvar Html5QrcodeConstants = (function () {\n    function Html5QrcodeConstants() {\n    }\n    Html5QrcodeConstants.GITHUB_PROJECT_URL = \"https://github.com/mebjas/html5-qrcode\";\n    Html5QrcodeConstants.SCAN_DEFAULT_FPS = 2;\n    Html5QrcodeConstants.DEFAULT_DISABLE_FLIP = false;\n    Html5QrcodeConstants.DEFAULT_REMEMBER_LAST_CAMERA_USED = true;\n    Html5QrcodeConstants.DEFAULT_SUPPORTED_SCAN_TYPE = [\n        Html5QrcodeScanType.SCAN_TYPE_CAMERA,\n        Html5QrcodeScanType.SCAN_TYPE_FILE\n    ];\n    return Html5QrcodeConstants;\n}());\n\nvar QrcodeResultFormat = (function () {\n    function QrcodeResultFormat(format, formatName) {\n        this.format = format;\n        this.formatName = formatName;\n    }\n    QrcodeResultFormat.prototype.toString = function () {\n        return this.formatName;\n    };\n    QrcodeResultFormat.create = function (format) {\n        if (!html5QrcodeSupportedFormatsTextMap.has(format)) {\n            throw \"\".concat(format, \" not in html5QrcodeSupportedFormatsTextMap\");\n        }\n        return new QrcodeResultFormat(format, html5QrcodeSupportedFormatsTextMap.get(format));\n    };\n    return QrcodeResultFormat;\n}());\n\nvar Html5QrcodeResultFactory = (function () {\n    function Html5QrcodeResultFactory() {\n    }\n    Html5QrcodeResultFactory.createFromText = function (decodedText) {\n        var qrcodeResult = {\n            text: decodedText\n        };\n        return {\n            decodedText: decodedText,\n            result: qrcodeResult\n        };\n    };\n    Html5QrcodeResultFactory.createFromQrcodeResult = function (qrcodeResult) {\n        return {\n            decodedText: qrcodeResult.text,\n            result: qrcodeResult\n        };\n    };\n    return Html5QrcodeResultFactory;\n}());\n\nvar Html5QrcodeErrorTypes;\n(function (Html5QrcodeErrorTypes) {\n    Html5QrcodeErrorTypes[Html5QrcodeErrorTypes[\"UNKWOWN_ERROR\"] = 0] = \"UNKWOWN_ERROR\";\n    Html5QrcodeErrorTypes[Html5QrcodeErrorTypes[\"IMPLEMENTATION_ERROR\"] = 1] = \"IMPLEMENTATION_ERROR\";\n    Html5QrcodeErrorTypes[Html5QrcodeErrorTypes[\"NO_CODE_FOUND_ERROR\"] = 2] = \"NO_CODE_FOUND_ERROR\";\n})(Html5QrcodeErrorTypes || (Html5QrcodeErrorTypes = {}));\nvar Html5QrcodeErrorFactory = (function () {\n    function Html5QrcodeErrorFactory() {\n    }\n    Html5QrcodeErrorFactory.createFrom = function (error) {\n        return {\n            errorMessage: error,\n            type: Html5QrcodeErrorTypes.UNKWOWN_ERROR\n        };\n    };\n    return Html5QrcodeErrorFactory;\n}());\n\nvar BaseLoggger = (function () {\n    function BaseLoggger(verbose) {\n        this.verbose = verbose;\n    }\n    BaseLoggger.prototype.log = function (message) {\n        if (this.verbose) {\n            console.log(message);\n        }\n    };\n    BaseLoggger.prototype.warn = function (message) {\n        if (this.verbose) {\n            console.warn(message);\n        }\n    };\n    BaseLoggger.prototype.logError = function (message, isExperimental) {\n        if (this.verbose || isExperimental === true) {\n            console.error(message);\n        }\n    };\n    BaseLoggger.prototype.logErrors = function (errors) {\n        if (errors.length === 0) {\n            throw \"Logger#logError called without arguments\";\n        }\n        if (this.verbose) {\n            console.error(errors);\n        }\n    };\n    return BaseLoggger;\n}());\n\nfunction isNullOrUndefined(obj) {\n    return (typeof obj === \"undefined\") || obj === null;\n}\nfunction clip(value, minValue, maxValue) {\n    if (value > maxValue) {\n        return maxValue;\n    }\n    if (value < minValue) {\n        return minValue;\n    }\n    return value;\n}\n//# sourceMappingURL=core.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9jb3JlLmpzLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL2NvcmUuanM/NGIzYiJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgdmFyIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cztcbihmdW5jdGlvbiAoSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzKSB7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIlFSX0NPREVcIl0gPSAwXSA9IFwiUVJfQ09ERVwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJBWlRFQ1wiXSA9IDFdID0gXCJBWlRFQ1wiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJDT0RBQkFSXCJdID0gMl0gPSBcIkNPREFCQVJcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiQ09ERV8zOVwiXSA9IDNdID0gXCJDT0RFXzM5XCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIkNPREVfOTNcIl0gPSA0XSA9IFwiQ09ERV85M1wiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJDT0RFXzEyOFwiXSA9IDVdID0gXCJDT0RFXzEyOFwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJEQVRBX01BVFJJWFwiXSA9IDZdID0gXCJEQVRBX01BVFJJWFwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJNQVhJQ09ERVwiXSA9IDddID0gXCJNQVhJQ09ERVwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJJVEZcIl0gPSA4XSA9IFwiSVRGXCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIkVBTl8xM1wiXSA9IDldID0gXCJFQU5fMTNcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiRUFOXzhcIl0gPSAxMF0gPSBcIkVBTl84XCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIlBERl80MTdcIl0gPSAxMV0gPSBcIlBERl80MTdcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiUlNTXzE0XCJdID0gMTJdID0gXCJSU1NfMTRcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiUlNTX0VYUEFOREVEXCJdID0gMTNdID0gXCJSU1NfRVhQQU5ERURcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiVVBDX0FcIl0gPSAxNF0gPSBcIlVQQ19BXCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIlVQQ19FXCJdID0gMTVdID0gXCJVUENfRVwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJVUENfRUFOX0VYVEVOU0lPTlwiXSA9IDE2XSA9IFwiVVBDX0VBTl9FWFRFTlNJT05cIjtcbn0pKEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyB8fCAoSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzID0ge30pKTtcbnZhciBodG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNUZXh0TWFwID0gbmV3IE1hcChbXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5RUl9DT0RFLCBcIlFSX0NPREVcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5BWlRFQywgXCJBWlRFQ1wiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREFCQVIsIFwiQ09EQUJBUlwiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfMzksIFwiQ09ERV8zOVwiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfOTMsIFwiQ09ERV85M1wiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfMTI4LCBcIkNPREVfMTI4XCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuREFUQV9NQVRSSVgsIFwiREFUQV9NQVRSSVhcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5NQVhJQ09ERSwgXCJNQVhJQ09ERVwiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLklURiwgXCJJVEZcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5FQU5fMTMsIFwiRUFOXzEzXCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuRUFOXzgsIFwiRUFOXzhcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5QREZfNDE3LCBcIlBERl80MTdcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5SU1NfMTQsIFwiUlNTXzE0XCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUlNTX0VYUEFOREVELCBcIlJTU19FWFBBTkRFRFwiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlVQQ19BLCBcIlVQQ19BXCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0UsIFwiVVBDX0VcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5VUENfRUFOX0VYVEVOU0lPTiwgXCJVUENfRUFOX0VYVEVOU0lPTlwiXVxuXSk7XG5leHBvcnQgdmFyIERlY29kZWRUZXh0VHlwZTtcbihmdW5jdGlvbiAoRGVjb2RlZFRleHRUeXBlKSB7XG4gICAgRGVjb2RlZFRleHRUeXBlW0RlY29kZWRUZXh0VHlwZVtcIlVOS05PV05cIl0gPSAwXSA9IFwiVU5LTk9XTlwiO1xuICAgIERlY29kZWRUZXh0VHlwZVtEZWNvZGVkVGV4dFR5cGVbXCJVUkxcIl0gPSAxXSA9IFwiVVJMXCI7XG59KShEZWNvZGVkVGV4dFR5cGUgfHwgKERlY29kZWRUZXh0VHlwZSA9IHt9KSk7XG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyhmb3JtYXQpIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyhIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMpLmluY2x1ZGVzKGZvcm1hdCk7XG59XG5leHBvcnQgdmFyIEh0bWw1UXJjb2RlU2NhblR5cGU7XG4oZnVuY3Rpb24gKEh0bWw1UXJjb2RlU2NhblR5cGUpIHtcbiAgICBIdG1sNVFyY29kZVNjYW5UeXBlW0h0bWw1UXJjb2RlU2NhblR5cGVbXCJTQ0FOX1RZUEVfQ0FNRVJBXCJdID0gMF0gPSBcIlNDQU5fVFlQRV9DQU1FUkFcIjtcbiAgICBIdG1sNVFyY29kZVNjYW5UeXBlW0h0bWw1UXJjb2RlU2NhblR5cGVbXCJTQ0FOX1RZUEVfRklMRVwiXSA9IDFdID0gXCJTQ0FOX1RZUEVfRklMRVwiO1xufSkoSHRtbDVRcmNvZGVTY2FuVHlwZSB8fCAoSHRtbDVRcmNvZGVTY2FuVHlwZSA9IHt9KSk7XG52YXIgSHRtbDVRcmNvZGVDb25zdGFudHMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEh0bWw1UXJjb2RlQ29uc3RhbnRzKCkge1xuICAgIH1cbiAgICBIdG1sNVFyY29kZUNvbnN0YW50cy5HSVRIVUJfUFJPSkVDVF9VUkwgPSBcImh0dHBzOi8vZ2l0aHViLmNvbS9tZWJqYXMvaHRtbDUtcXJjb2RlXCI7XG4gICAgSHRtbDVRcmNvZGVDb25zdGFudHMuU0NBTl9ERUZBVUxUX0ZQUyA9IDI7XG4gICAgSHRtbDVRcmNvZGVDb25zdGFudHMuREVGQVVMVF9ESVNBQkxFX0ZMSVAgPSBmYWxzZTtcbiAgICBIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1JFTUVNQkVSX0xBU1RfQ0FNRVJBX1VTRUQgPSB0cnVlO1xuICAgIEh0bWw1UXJjb2RlQ29uc3RhbnRzLkRFRkFVTFRfU1VQUE9SVEVEX1NDQU5fVFlQRSA9IFtcbiAgICAgICAgSHRtbDVRcmNvZGVTY2FuVHlwZS5TQ0FOX1RZUEVfQ0FNRVJBLFxuICAgICAgICBIdG1sNVFyY29kZVNjYW5UeXBlLlNDQU5fVFlQRV9GSUxFXG4gICAgXTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGVDb25zdGFudHM7XG59KCkpO1xuZXhwb3J0IHsgSHRtbDVRcmNvZGVDb25zdGFudHMgfTtcbnZhciBRcmNvZGVSZXN1bHRGb3JtYXQgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFFyY29kZVJlc3VsdEZvcm1hdChmb3JtYXQsIGZvcm1hdE5hbWUpIHtcbiAgICAgICAgdGhpcy5mb3JtYXQgPSBmb3JtYXQ7XG4gICAgICAgIHRoaXMuZm9ybWF0TmFtZSA9IGZvcm1hdE5hbWU7XG4gICAgfVxuICAgIFFyY29kZVJlc3VsdEZvcm1hdC5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZvcm1hdE5hbWU7XG4gICAgfTtcbiAgICBRcmNvZGVSZXN1bHRGb3JtYXQuY3JlYXRlID0gZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICBpZiAoIWh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1RleHRNYXAuaGFzKGZvcm1hdCkpIHtcbiAgICAgICAgICAgIHRocm93IFwiXCIuY29uY2F0KGZvcm1hdCwgXCIgbm90IGluIGh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1RleHRNYXBcIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBRcmNvZGVSZXN1bHRGb3JtYXQoZm9ybWF0LCBodG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNUZXh0TWFwLmdldChmb3JtYXQpKTtcbiAgICB9O1xuICAgIHJldHVybiBRcmNvZGVSZXN1bHRGb3JtYXQ7XG59KCkpO1xuZXhwb3J0IHsgUXJjb2RlUmVzdWx0Rm9ybWF0IH07XG52YXIgSHRtbDVRcmNvZGVSZXN1bHRGYWN0b3J5ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBIdG1sNVFyY29kZVJlc3VsdEZhY3RvcnkoKSB7XG4gICAgfVxuICAgIEh0bWw1UXJjb2RlUmVzdWx0RmFjdG9yeS5jcmVhdGVGcm9tVGV4dCA9IGZ1bmN0aW9uIChkZWNvZGVkVGV4dCkge1xuICAgICAgICB2YXIgcXJjb2RlUmVzdWx0ID0ge1xuICAgICAgICAgICAgdGV4dDogZGVjb2RlZFRleHRcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGRlY29kZWRUZXh0OiBkZWNvZGVkVGV4dCxcbiAgICAgICAgICAgIHJlc3VsdDogcXJjb2RlUmVzdWx0XG4gICAgICAgIH07XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVJlc3VsdEZhY3RvcnkuY3JlYXRlRnJvbVFyY29kZVJlc3VsdCA9IGZ1bmN0aW9uIChxcmNvZGVSZXN1bHQpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGRlY29kZWRUZXh0OiBxcmNvZGVSZXN1bHQudGV4dCxcbiAgICAgICAgICAgIHJlc3VsdDogcXJjb2RlUmVzdWx0XG4gICAgICAgIH07XG4gICAgfTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGVSZXN1bHRGYWN0b3J5O1xufSgpKTtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlUmVzdWx0RmFjdG9yeSB9O1xuZXhwb3J0IHZhciBIdG1sNVFyY29kZUVycm9yVHlwZXM7XG4oZnVuY3Rpb24gKEh0bWw1UXJjb2RlRXJyb3JUeXBlcykge1xuICAgIEh0bWw1UXJjb2RlRXJyb3JUeXBlc1tIdG1sNVFyY29kZUVycm9yVHlwZXNbXCJVTktXT1dOX0VSUk9SXCJdID0gMF0gPSBcIlVOS1dPV05fRVJST1JcIjtcbiAgICBIdG1sNVFyY29kZUVycm9yVHlwZXNbSHRtbDVRcmNvZGVFcnJvclR5cGVzW1wiSU1QTEVNRU5UQVRJT05fRVJST1JcIl0gPSAxXSA9IFwiSU1QTEVNRU5UQVRJT05fRVJST1JcIjtcbiAgICBIdG1sNVFyY29kZUVycm9yVHlwZXNbSHRtbDVRcmNvZGVFcnJvclR5cGVzW1wiTk9fQ09ERV9GT1VORF9FUlJPUlwiXSA9IDJdID0gXCJOT19DT0RFX0ZPVU5EX0VSUk9SXCI7XG59KShIdG1sNVFyY29kZUVycm9yVHlwZXMgfHwgKEh0bWw1UXJjb2RlRXJyb3JUeXBlcyA9IHt9KSk7XG52YXIgSHRtbDVRcmNvZGVFcnJvckZhY3RvcnkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEh0bWw1UXJjb2RlRXJyb3JGYWN0b3J5KCkge1xuICAgIH1cbiAgICBIdG1sNVFyY29kZUVycm9yRmFjdG9yeS5jcmVhdGVGcm9tID0gZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBlcnJvck1lc3NhZ2U6IGVycm9yLFxuICAgICAgICAgICAgdHlwZTogSHRtbDVRcmNvZGVFcnJvclR5cGVzLlVOS1dPV05fRVJST1JcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIHJldHVybiBIdG1sNVFyY29kZUVycm9yRmFjdG9yeTtcbn0oKSk7XG5leHBvcnQgeyBIdG1sNVFyY29kZUVycm9yRmFjdG9yeSB9O1xudmFyIEJhc2VMb2dnZ2VyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBCYXNlTG9nZ2dlcih2ZXJib3NlKSB7XG4gICAgICAgIHRoaXMudmVyYm9zZSA9IHZlcmJvc2U7XG4gICAgfVxuICAgIEJhc2VMb2dnZ2VyLnByb3RvdHlwZS5sb2cgPSBmdW5jdGlvbiAobWVzc2FnZSkge1xuICAgICAgICBpZiAodGhpcy52ZXJib3NlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQmFzZUxvZ2dnZXIucHJvdG90eXBlLndhcm4gPSBmdW5jdGlvbiAobWVzc2FnZSkge1xuICAgICAgICBpZiAodGhpcy52ZXJib3NlKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEJhc2VMb2dnZ2VyLnByb3RvdHlwZS5sb2dFcnJvciA9IGZ1bmN0aW9uIChtZXNzYWdlLCBpc0V4cGVyaW1lbnRhbCkge1xuICAgICAgICBpZiAodGhpcy52ZXJib3NlIHx8IGlzRXhwZXJpbWVudGFsID09PSB0cnVlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBCYXNlTG9nZ2dlci5wcm90b3R5cGUubG9nRXJyb3JzID0gZnVuY3Rpb24gKGVycm9ycykge1xuICAgICAgICBpZiAoZXJyb3JzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgXCJMb2dnZXIjbG9nRXJyb3IgY2FsbGVkIHdpdGhvdXQgYXJndW1lbnRzXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMudmVyYm9zZSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcnMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gQmFzZUxvZ2dnZXI7XG59KCkpO1xuZXhwb3J0IHsgQmFzZUxvZ2dnZXIgfTtcbmV4cG9ydCBmdW5jdGlvbiBpc051bGxPclVuZGVmaW5lZChvYmopIHtcbiAgICByZXR1cm4gKHR5cGVvZiBvYmogPT09IFwidW5kZWZpbmVkXCIpIHx8IG9iaiA9PT0gbnVsbDtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjbGlwKHZhbHVlLCBtaW5WYWx1ZSwgbWF4VmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPiBtYXhWYWx1ZSkge1xuICAgICAgICByZXR1cm4gbWF4VmFsdWU7XG4gICAgfVxuICAgIGlmICh2YWx1ZSA8IG1pblZhbHVlKSB7XG4gICAgICAgIHJldHVybiBtaW5WYWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y29yZS5qcy5tYXAiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/core.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/html5-qrcode-scanner.js":
+/*!***************************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/html5-qrcode-scanner.js ***!
+  \***************************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   Html5QrcodeScanner: () => (/* binding */ Html5QrcodeScanner)\n/* harmony export */ });\n/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core */ \"./node_modules/html5-qrcode/esm/core.js\");\n/* harmony import */ var _html5_qrcode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./html5-qrcode */ \"./node_modules/html5-qrcode/esm/html5-qrcode.js\");\n/* harmony import */ var _strings__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./strings */ \"./node_modules/html5-qrcode/esm/strings.js\");\n/* harmony import */ var _image_assets__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./image-assets */ \"./node_modules/html5-qrcode/esm/image-assets.js\");\n/* harmony import */ var _storage__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./storage */ \"./node_modules/html5-qrcode/esm/storage.js\");\n/* harmony import */ var _ui__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./ui */ \"./node_modules/html5-qrcode/esm/ui.js\");\n/* harmony import */ var _camera_permissions__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./camera/permissions */ \"./node_modules/html5-qrcode/esm/camera/permissions.js\");\n/* harmony import */ var _ui_scanner_scan_type_selector__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./ui/scanner/scan-type-selector */ \"./node_modules/html5-qrcode/esm/ui/scanner/scan-type-selector.js\");\n/* harmony import */ var _ui_scanner_torch_button__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./ui/scanner/torch-button */ \"./node_modules/html5-qrcode/esm/ui/scanner/torch-button.js\");\n/* harmony import */ var _ui_scanner_file_selection_ui__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./ui/scanner/file-selection-ui */ \"./node_modules/html5-qrcode/esm/ui/scanner/file-selection-ui.js\");\n/* harmony import */ var _ui_scanner_base__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./ui/scanner/base */ \"./node_modules/html5-qrcode/esm/ui/scanner/base.js\");\n/* harmony import */ var _ui_scanner_camera_selection_ui__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./ui/scanner/camera-selection-ui */ \"./node_modules/html5-qrcode/esm/ui/scanner/camera-selection-ui.js\");\n/* harmony import */ var _ui_scanner_camera_zoom_ui__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./ui/scanner/camera-zoom-ui */ \"./node_modules/html5-qrcode/esm/ui/scanner/camera-zoom-ui.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar Html5QrcodeScannerStatus;\n(function (Html5QrcodeScannerStatus) {\n    Html5QrcodeScannerStatus[Html5QrcodeScannerStatus[\"STATUS_DEFAULT\"] = 0] = \"STATUS_DEFAULT\";\n    Html5QrcodeScannerStatus[Html5QrcodeScannerStatus[\"STATUS_SUCCESS\"] = 1] = \"STATUS_SUCCESS\";\n    Html5QrcodeScannerStatus[Html5QrcodeScannerStatus[\"STATUS_WARNING\"] = 2] = \"STATUS_WARNING\";\n    Html5QrcodeScannerStatus[Html5QrcodeScannerStatus[\"STATUS_REQUESTING_PERMISSION\"] = 3] = \"STATUS_REQUESTING_PERMISSION\";\n})(Html5QrcodeScannerStatus || (Html5QrcodeScannerStatus = {}));\nfunction toHtml5QrcodeCameraScanConfig(config) {\n    return {\n        fps: config.fps,\n        qrbox: config.qrbox,\n        aspectRatio: config.aspectRatio,\n        disableFlip: config.disableFlip,\n        videoConstraints: config.videoConstraints\n    };\n}\nfunction toHtml5QrcodeFullConfig(config, verbose) {\n    return {\n        formatsToSupport: config.formatsToSupport,\n        useBarCodeDetectorIfSupported: config.useBarCodeDetectorIfSupported,\n        experimentalFeatures: config.experimentalFeatures,\n        verbose: verbose\n    };\n}\nvar Html5QrcodeScanner = (function () {\n    function Html5QrcodeScanner(elementId, config, verbose) {\n        this.lastMatchFound = null;\n        this.cameraScanImage = null;\n        this.fileScanImage = null;\n        this.fileSelectionUi = null;\n        this.elementId = elementId;\n        this.config = this.createConfig(config);\n        this.verbose = verbose === true;\n        if (!document.getElementById(elementId)) {\n            throw \"HTML Element with id=\".concat(elementId, \" not found\");\n        }\n        this.scanTypeSelector = new _ui_scanner_scan_type_selector__WEBPACK_IMPORTED_MODULE_7__.ScanTypeSelector(this.config.supportedScanTypes);\n        this.currentScanType = this.scanTypeSelector.getDefaultScanType();\n        this.sectionSwapAllowed = true;\n        this.logger = new _core__WEBPACK_IMPORTED_MODULE_0__.BaseLoggger(this.verbose);\n        this.persistedDataManager = new _storage__WEBPACK_IMPORTED_MODULE_4__.PersistedDataManager();\n        if (config.rememberLastUsedCamera !== true) {\n            this.persistedDataManager.reset();\n        }\n    }\n    Html5QrcodeScanner.prototype.render = function (qrCodeSuccessCallback, qrCodeErrorCallback) {\n        var _this = this;\n        this.lastMatchFound = null;\n        this.qrCodeSuccessCallback\n            = function (decodedText, result) {\n                if (qrCodeSuccessCallback) {\n                    qrCodeSuccessCallback(decodedText, result);\n                }\n                else {\n                    if (_this.lastMatchFound === decodedText) {\n                        return;\n                    }\n                    _this.lastMatchFound = decodedText;\n                    _this.setHeaderMessage(_strings__WEBPACK_IMPORTED_MODULE_2__.Html5QrcodeScannerStrings.lastMatch(decodedText), Html5QrcodeScannerStatus.STATUS_SUCCESS);\n                }\n            };\n        this.qrCodeErrorCallback =\n            function (errorMessage, error) {\n                if (qrCodeErrorCallback) {\n                    qrCodeErrorCallback(errorMessage, error);\n                }\n            };\n        var container = document.getElementById(this.elementId);\n        if (!container) {\n            throw \"HTML Element with id=\".concat(this.elementId, \" not found\");\n        }\n        container.innerHTML = \"\";\n        this.createBasicLayout(container);\n        this.html5Qrcode = new _html5_qrcode__WEBPACK_IMPORTED_MODULE_1__.Html5Qrcode(this.getScanRegionId(), toHtml5QrcodeFullConfig(this.config, this.verbose));\n    };\n    Html5QrcodeScanner.prototype.pause = function (shouldPauseVideo) {\n        if ((0,_core__WEBPACK_IMPORTED_MODULE_0__.isNullOrUndefined)(shouldPauseVideo) || shouldPauseVideo !== true) {\n            shouldPauseVideo = false;\n        }\n        this.getHtml5QrcodeOrFail().pause(shouldPauseVideo);\n    };\n    Html5QrcodeScanner.prototype.resume = function () {\n        this.getHtml5QrcodeOrFail().resume();\n    };\n    Html5QrcodeScanner.prototype.getState = function () {\n        return this.getHtml5QrcodeOrFail().getState();\n    };\n    Html5QrcodeScanner.prototype.clear = function () {\n        var _this = this;\n        var emptyHtmlContainer = function () {\n            var mainContainer = document.getElementById(_this.elementId);\n            if (mainContainer) {\n                mainContainer.innerHTML = \"\";\n                _this.resetBasicLayout(mainContainer);\n            }\n        };\n        if (this.html5Qrcode) {\n            return new Promise(function (resolve, reject) {\n                if (!_this.html5Qrcode) {\n                    resolve();\n                    return;\n                }\n                if (_this.html5Qrcode.isScanning) {\n                    _this.html5Qrcode.stop().then(function (_) {\n                        if (!_this.html5Qrcode) {\n                            resolve();\n                            return;\n                        }\n                        _this.html5Qrcode.clear();\n                        emptyHtmlContainer();\n                        resolve();\n                    }).catch(function (error) {\n                        if (_this.verbose) {\n                            _this.logger.logError(\"Unable to stop qrcode scanner\", error);\n                        }\n                        reject(error);\n                    });\n                }\n                else {\n                    _this.html5Qrcode.clear();\n                    emptyHtmlContainer();\n                    resolve();\n                }\n            });\n        }\n        return Promise.resolve();\n    };\n    Html5QrcodeScanner.prototype.getRunningTrackCapabilities = function () {\n        return this.getHtml5QrcodeOrFail().getRunningTrackCapabilities();\n    };\n    Html5QrcodeScanner.prototype.getRunningTrackSettings = function () {\n        return this.getHtml5QrcodeOrFail().getRunningTrackSettings();\n    };\n    Html5QrcodeScanner.prototype.applyVideoConstraints = function (videoConstaints) {\n        return this.getHtml5QrcodeOrFail().applyVideoConstraints(videoConstaints);\n    };\n    Html5QrcodeScanner.prototype.getHtml5QrcodeOrFail = function () {\n        if (!this.html5Qrcode) {\n            throw \"Code scanner not initialized.\";\n        }\n        return this.html5Qrcode;\n    };\n    Html5QrcodeScanner.prototype.createConfig = function (config) {\n        if (config) {\n            if (!config.fps) {\n                config.fps = _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeConstants.SCAN_DEFAULT_FPS;\n            }\n            if (config.rememberLastUsedCamera !== (!_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeConstants.DEFAULT_REMEMBER_LAST_CAMERA_USED)) {\n                config.rememberLastUsedCamera\n                    = _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeConstants.DEFAULT_REMEMBER_LAST_CAMERA_USED;\n            }\n            if (!config.supportedScanTypes) {\n                config.supportedScanTypes\n                    = _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeConstants.DEFAULT_SUPPORTED_SCAN_TYPE;\n            }\n            return config;\n        }\n        return {\n            fps: _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeConstants.SCAN_DEFAULT_FPS,\n            rememberLastUsedCamera: _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeConstants.DEFAULT_REMEMBER_LAST_CAMERA_USED,\n            supportedScanTypes: _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeConstants.DEFAULT_SUPPORTED_SCAN_TYPE\n        };\n    };\n    Html5QrcodeScanner.prototype.createBasicLayout = function (parent) {\n        parent.style.position = \"relative\";\n        parent.style.padding = \"0px\";\n        parent.style.border = \"1px solid silver\";\n        this.createHeader(parent);\n        var qrCodeScanRegion = document.createElement(\"div\");\n        var scanRegionId = this.getScanRegionId();\n        qrCodeScanRegion.id = scanRegionId;\n        qrCodeScanRegion.style.width = \"100%\";\n        qrCodeScanRegion.style.minHeight = \"100px\";\n        qrCodeScanRegion.style.textAlign = \"center\";\n        parent.appendChild(qrCodeScanRegion);\n        if (_ui_scanner_scan_type_selector__WEBPACK_IMPORTED_MODULE_7__.ScanTypeSelector.isCameraScanType(this.currentScanType)) {\n            this.insertCameraScanImageToScanRegion();\n        }\n        else {\n            this.insertFileScanImageToScanRegion();\n        }\n        var qrCodeDashboard = document.createElement(\"div\");\n        var dashboardId = this.getDashboardId();\n        qrCodeDashboard.id = dashboardId;\n        qrCodeDashboard.style.width = \"100%\";\n        parent.appendChild(qrCodeDashboard);\n        this.setupInitialDashboard(qrCodeDashboard);\n    };\n    Html5QrcodeScanner.prototype.resetBasicLayout = function (mainContainer) {\n        mainContainer.style.border = \"none\";\n    };\n    Html5QrcodeScanner.prototype.setupInitialDashboard = function (dashboard) {\n        this.createSection(dashboard);\n        this.createSectionControlPanel();\n        if (this.scanTypeSelector.hasMoreThanOneScanType()) {\n            this.createSectionSwap();\n        }\n    };\n    Html5QrcodeScanner.prototype.createHeader = function (dashboard) {\n        var header = document.createElement(\"div\");\n        header.style.textAlign = \"left\";\n        header.style.margin = \"0px\";\n        dashboard.appendChild(header);\n        var libraryInfo = new _ui__WEBPACK_IMPORTED_MODULE_5__.LibraryInfoContainer();\n        libraryInfo.renderInto(header);\n        var headerMessageContainer = document.createElement(\"div\");\n        headerMessageContainer.id = this.getHeaderMessageContainerId();\n        headerMessageContainer.style.display = \"none\";\n        headerMessageContainer.style.textAlign = \"center\";\n        headerMessageContainer.style.fontSize = \"14px\";\n        headerMessageContainer.style.padding = \"2px 10px\";\n        headerMessageContainer.style.margin = \"4px\";\n        headerMessageContainer.style.borderTop = \"1px solid #f6f6f6\";\n        header.appendChild(headerMessageContainer);\n    };\n    Html5QrcodeScanner.prototype.createSection = function (dashboard) {\n        var section = document.createElement(\"div\");\n        section.id = this.getDashboardSectionId();\n        section.style.width = \"100%\";\n        section.style.padding = \"10px 0px 10px 0px\";\n        section.style.textAlign = \"left\";\n        dashboard.appendChild(section);\n    };\n    Html5QrcodeScanner.prototype.createCameraListUi = function (scpCameraScanRegion, requestPermissionContainer, requestPermissionButton) {\n        var $this = this;\n        $this.showHideScanTypeSwapLink(false);\n        $this.setHeaderMessage(_strings__WEBPACK_IMPORTED_MODULE_2__.Html5QrcodeScannerStrings.cameraPermissionRequesting());\n        var createPermissionButtonIfNotExists = function () {\n            if (!requestPermissionButton) {\n                $this.createPermissionButton(scpCameraScanRegion, requestPermissionContainer);\n            }\n        };\n        _html5_qrcode__WEBPACK_IMPORTED_MODULE_1__.Html5Qrcode.getCameras().then(function (cameras) {\n            $this.persistedDataManager.setHasPermission(true);\n            $this.showHideScanTypeSwapLink(true);\n            $this.resetHeaderMessage();\n            if (cameras && cameras.length > 0) {\n                scpCameraScanRegion.removeChild(requestPermissionContainer);\n                $this.renderCameraSelection(cameras);\n            }\n            else {\n                $this.setHeaderMessage(_strings__WEBPACK_IMPORTED_MODULE_2__.Html5QrcodeScannerStrings.noCameraFound(), Html5QrcodeScannerStatus.STATUS_WARNING);\n                createPermissionButtonIfNotExists();\n            }\n        }).catch(function (error) {\n            $this.persistedDataManager.setHasPermission(false);\n            if (requestPermissionButton) {\n                requestPermissionButton.disabled = false;\n            }\n            else {\n                createPermissionButtonIfNotExists();\n            }\n            $this.setHeaderMessage(error, Html5QrcodeScannerStatus.STATUS_WARNING);\n            $this.showHideScanTypeSwapLink(true);\n        });\n    };\n    Html5QrcodeScanner.prototype.createPermissionButton = function (scpCameraScanRegion, requestPermissionContainer) {\n        var $this = this;\n        var requestPermissionButton = _ui_scanner_base__WEBPACK_IMPORTED_MODULE_10__.BaseUiElementFactory.createElement(\"button\", this.getCameraPermissionButtonId());\n        requestPermissionButton.innerText\n            = _strings__WEBPACK_IMPORTED_MODULE_2__.Html5QrcodeScannerStrings.cameraPermissionTitle();\n        requestPermissionButton.addEventListener(\"click\", function () {\n            requestPermissionButton.disabled = true;\n            $this.createCameraListUi(scpCameraScanRegion, requestPermissionContainer, requestPermissionButton);\n        });\n        requestPermissionContainer.appendChild(requestPermissionButton);\n    };\n    Html5QrcodeScanner.prototype.createPermissionsUi = function (scpCameraScanRegion, requestPermissionContainer) {\n        var $this = this;\n        if (_ui_scanner_scan_type_selector__WEBPACK_IMPORTED_MODULE_7__.ScanTypeSelector.isCameraScanType(this.currentScanType)\n            && this.persistedDataManager.hasCameraPermissions()) {\n            _camera_permissions__WEBPACK_IMPORTED_MODULE_6__.CameraPermissions.hasPermissions().then(function (hasPermissions) {\n                if (hasPermissions) {\n                    $this.createCameraListUi(scpCameraScanRegion, requestPermissionContainer);\n                }\n                else {\n                    $this.persistedDataManager.setHasPermission(false);\n                    $this.createPermissionButton(scpCameraScanRegion, requestPermissionContainer);\n                }\n            }).catch(function (_) {\n                $this.persistedDataManager.setHasPermission(false);\n                $this.createPermissionButton(scpCameraScanRegion, requestPermissionContainer);\n            });\n            return;\n        }\n        this.createPermissionButton(scpCameraScanRegion, requestPermissionContainer);\n    };\n    Html5QrcodeScanner.prototype.createSectionControlPanel = function () {\n        var section = document.getElementById(this.getDashboardSectionId());\n        var sectionControlPanel = document.createElement(\"div\");\n        section.appendChild(sectionControlPanel);\n        var scpCameraScanRegion = document.createElement(\"div\");\n        scpCameraScanRegion.id = this.getDashboardSectionCameraScanRegionId();\n        scpCameraScanRegion.style.display\n            = _ui_scanner_scan_type_selector__WEBPACK_IMPORTED_MODULE_7__.ScanTypeSelector.isCameraScanType(this.currentScanType)\n                ? \"block\" : \"none\";\n        sectionControlPanel.appendChild(scpCameraScanRegion);\n        var requestPermissionContainer = document.createElement(\"div\");\n        requestPermissionContainer.style.textAlign = \"center\";\n        scpCameraScanRegion.appendChild(requestPermissionContainer);\n        if (this.scanTypeSelector.isCameraScanRequired()) {\n            this.createPermissionsUi(scpCameraScanRegion, requestPermissionContainer);\n        }\n        this.renderFileScanUi(sectionControlPanel);\n    };\n    Html5QrcodeScanner.prototype.renderFileScanUi = function (parent) {\n        var showOnRender = _ui_scanner_scan_type_selector__WEBPACK_IMPORTED_MODULE_7__.ScanTypeSelector.isFileScanType(this.currentScanType);\n        var $this = this;\n        var onFileSelected = function (file) {\n            if (!$this.html5Qrcode) {\n                throw \"html5Qrcode not defined\";\n            }\n            if (!_ui_scanner_scan_type_selector__WEBPACK_IMPORTED_MODULE_7__.ScanTypeSelector.isFileScanType($this.currentScanType)) {\n                return;\n            }\n            $this.setHeaderMessage(_strings__WEBPACK_IMPORTED_MODULE_2__.Html5QrcodeScannerStrings.loadingImage());\n            $this.html5Qrcode.scanFileV2(file, true)\n                .then(function (html5qrcodeResult) {\n                $this.resetHeaderMessage();\n                $this.qrCodeSuccessCallback(html5qrcodeResult.decodedText, html5qrcodeResult);\n            })\n                .catch(function (error) {\n                $this.setHeaderMessage(error, Html5QrcodeScannerStatus.STATUS_WARNING);\n                $this.qrCodeErrorCallback(error, _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeErrorFactory.createFrom(error));\n            });\n        };\n        this.fileSelectionUi = _ui_scanner_file_selection_ui__WEBPACK_IMPORTED_MODULE_9__.FileSelectionUi.create(parent, showOnRender, onFileSelected);\n    };\n    Html5QrcodeScanner.prototype.renderCameraSelection = function (cameras) {\n        var _this = this;\n        var $this = this;\n        var scpCameraScanRegion = document.getElementById(this.getDashboardSectionCameraScanRegionId());\n        scpCameraScanRegion.style.textAlign = \"center\";\n        var cameraZoomUi = _ui_scanner_camera_zoom_ui__WEBPACK_IMPORTED_MODULE_12__.CameraZoomUi.create(scpCameraScanRegion, false);\n        var renderCameraZoomUiIfSupported = function (cameraCapabilities) {\n            var zoomCapability = cameraCapabilities.zoomFeature();\n            if (!zoomCapability.isSupported()) {\n                return;\n            }\n            cameraZoomUi.setOnCameraZoomValueChangeCallback(function (zoomValue) {\n                zoomCapability.apply(zoomValue);\n            });\n            var defaultZoom = 1;\n            if (_this.config.defaultZoomValueIfSupported) {\n                defaultZoom = _this.config.defaultZoomValueIfSupported;\n            }\n            defaultZoom = (0,_core__WEBPACK_IMPORTED_MODULE_0__.clip)(defaultZoom, zoomCapability.min(), zoomCapability.max());\n            cameraZoomUi.setValues(zoomCapability.min(), zoomCapability.max(), defaultZoom, zoomCapability.step());\n            cameraZoomUi.show();\n        };\n        var cameraSelectUi = _ui_scanner_camera_selection_ui__WEBPACK_IMPORTED_MODULE_11__.CameraSelectionUi.create(scpCameraScanRegion, cameras);\n        var cameraActionContainer = document.createElement(\"span\");\n        var cameraActionStartButton = _ui_scanner_base__WEBPACK_IMPORTED_MODULE_10__.BaseUiElementFactory.createElement(\"button\", _ui_scanner_base__WEBPACK_IMPORTED_MODULE_10__.PublicUiElementIdAndClasses.CAMERA_START_BUTTON_ID);\n        cameraActionStartButton.innerText\n            = _strings__WEBPACK_IMPORTED_MODULE_2__.Html5QrcodeScannerStrings.scanButtonStartScanningText();\n        cameraActionContainer.appendChild(cameraActionStartButton);\n        var cameraActionStopButton = _ui_scanner_base__WEBPACK_IMPORTED_MODULE_10__.BaseUiElementFactory.createElement(\"button\", _ui_scanner_base__WEBPACK_IMPORTED_MODULE_10__.PublicUiElementIdAndClasses.CAMERA_STOP_BUTTON_ID);\n        cameraActionStopButton.innerText\n            = _strings__WEBPACK_IMPORTED_MODULE_2__.Html5QrcodeScannerStrings.scanButtonStopScanningText();\n        cameraActionStopButton.style.display = \"none\";\n        cameraActionStopButton.disabled = true;\n        cameraActionContainer.appendChild(cameraActionStopButton);\n        var torchButton;\n        var createAndShowTorchButtonIfSupported = function (cameraCapabilities) {\n            if (!cameraCapabilities.torchFeature().isSupported()) {\n                if (torchButton) {\n                    torchButton.hide();\n                }\n                return;\n            }\n            if (!torchButton) {\n                torchButton = _ui_scanner_torch_button__WEBPACK_IMPORTED_MODULE_8__.TorchButton.create(cameraActionContainer, cameraCapabilities.torchFeature(), { display: \"none\", marginLeft: \"5px\" }, function (errorMessage) {\n                    $this.setHeaderMessage(errorMessage, Html5QrcodeScannerStatus.STATUS_WARNING);\n                });\n            }\n            else {\n                torchButton.updateTorchCapability(cameraCapabilities.torchFeature());\n            }\n            torchButton.show();\n        };\n        scpCameraScanRegion.appendChild(cameraActionContainer);\n        var resetCameraActionStartButton = function (shouldShow) {\n            if (!shouldShow) {\n                cameraActionStartButton.style.display = \"none\";\n            }\n            cameraActionStartButton.innerText\n                = _strings__WEBPACK_IMPORTED_MODULE_2__.Html5QrcodeScannerStrings.scanButtonStartScanningText();\n            cameraActionStartButton.style.opacity = \"1\";\n            cameraActionStartButton.disabled = false;\n            if (shouldShow) {\n                cameraActionStartButton.style.display = \"inline-block\";\n            }\n        };\n        cameraActionStartButton.addEventListener(\"click\", function (_) {\n            cameraActionStartButton.innerText\n                = _strings__WEBPACK_IMPORTED_MODULE_2__.Html5QrcodeScannerStrings.scanButtonScanningStarting();\n            cameraSelectUi.disable();\n            cameraActionStartButton.disabled = true;\n            cameraActionStartButton.style.opacity = \"0.5\";\n            if (_this.scanTypeSelector.hasMoreThanOneScanType()) {\n                $this.showHideScanTypeSwapLink(false);\n            }\n            $this.resetHeaderMessage();\n            var cameraId = cameraSelectUi.getValue();\n            $this.persistedDataManager.setLastUsedCameraId(cameraId);\n            $this.html5Qrcode.start(cameraId, toHtml5QrcodeCameraScanConfig($this.config), $this.qrCodeSuccessCallback, $this.qrCodeErrorCallback)\n                .then(function (_) {\n                cameraActionStopButton.disabled = false;\n                cameraActionStopButton.style.display = \"inline-block\";\n                resetCameraActionStartButton(false);\n                var cameraCapabilities = $this.html5Qrcode.getRunningTrackCameraCapabilities();\n                if (_this.config.showTorchButtonIfSupported === true) {\n                    createAndShowTorchButtonIfSupported(cameraCapabilities);\n                }\n                if (_this.config.showZoomSliderIfSupported === true) {\n                    renderCameraZoomUiIfSupported(cameraCapabilities);\n                }\n            })\n                .catch(function (error) {\n                $this.showHideScanTypeSwapLink(true);\n                cameraSelectUi.enable();\n                resetCameraActionStartButton(true);\n                $this.setHeaderMessage(error, Html5QrcodeScannerStatus.STATUS_WARNING);\n            });\n        });\n        if (cameraSelectUi.hasSingleItem()) {\n            cameraActionStartButton.click();\n        }\n        cameraActionStopButton.addEventListener(\"click\", function (_) {\n            if (!$this.html5Qrcode) {\n                throw \"html5Qrcode not defined\";\n            }\n            cameraActionStopButton.disabled = true;\n            $this.html5Qrcode.stop()\n                .then(function (_) {\n                if (_this.scanTypeSelector.hasMoreThanOneScanType()) {\n                    $this.showHideScanTypeSwapLink(true);\n                }\n                cameraSelectUi.enable();\n                cameraActionStartButton.disabled = false;\n                cameraActionStopButton.style.display = \"none\";\n                cameraActionStartButton.style.display = \"inline-block\";\n                if (torchButton) {\n                    torchButton.reset();\n                    torchButton.hide();\n                }\n                cameraZoomUi.removeOnCameraZoomValueChangeCallback();\n                cameraZoomUi.hide();\n                $this.insertCameraScanImageToScanRegion();\n            }).catch(function (error) {\n                cameraActionStopButton.disabled = false;\n                $this.setHeaderMessage(error, Html5QrcodeScannerStatus.STATUS_WARNING);\n            });\n        });\n        if ($this.persistedDataManager.getLastUsedCameraId()) {\n            var cameraId = $this.persistedDataManager.getLastUsedCameraId();\n            if (cameraSelectUi.hasValue(cameraId)) {\n                cameraSelectUi.setValue(cameraId);\n                cameraActionStartButton.click();\n            }\n            else {\n                $this.persistedDataManager.resetLastUsedCameraId();\n            }\n        }\n    };\n    Html5QrcodeScanner.prototype.createSectionSwap = function () {\n        var $this = this;\n        var TEXT_IF_CAMERA_SCAN_SELECTED = _strings__WEBPACK_IMPORTED_MODULE_2__.Html5QrcodeScannerStrings.textIfCameraScanSelected();\n        var TEXT_IF_FILE_SCAN_SELECTED = _strings__WEBPACK_IMPORTED_MODULE_2__.Html5QrcodeScannerStrings.textIfFileScanSelected();\n        var section = document.getElementById(this.getDashboardSectionId());\n        var switchContainer = document.createElement(\"div\");\n        switchContainer.style.textAlign = \"center\";\n        var switchScanTypeLink = _ui_scanner_base__WEBPACK_IMPORTED_MODULE_10__.BaseUiElementFactory.createElement(\"span\", this.getDashboardSectionSwapLinkId());\n        switchScanTypeLink.style.textDecoration = \"underline\";\n        switchScanTypeLink.style.cursor = \"pointer\";\n        switchScanTypeLink.innerText\n            = _ui_scanner_scan_type_selector__WEBPACK_IMPORTED_MODULE_7__.ScanTypeSelector.isCameraScanType(this.currentScanType)\n                ? TEXT_IF_CAMERA_SCAN_SELECTED : TEXT_IF_FILE_SCAN_SELECTED;\n        switchScanTypeLink.addEventListener(\"click\", function () {\n            if (!$this.sectionSwapAllowed) {\n                if ($this.verbose) {\n                    $this.logger.logError(\"Section swap called when not allowed\");\n                }\n                return;\n            }\n            $this.resetHeaderMessage();\n            $this.fileSelectionUi.resetValue();\n            $this.sectionSwapAllowed = false;\n            if (_ui_scanner_scan_type_selector__WEBPACK_IMPORTED_MODULE_7__.ScanTypeSelector.isCameraScanType($this.currentScanType)) {\n                $this.clearScanRegion();\n                $this.getCameraScanRegion().style.display = \"none\";\n                $this.fileSelectionUi.show();\n                switchScanTypeLink.innerText = TEXT_IF_FILE_SCAN_SELECTED;\n                $this.currentScanType = _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScanType.SCAN_TYPE_FILE;\n                $this.insertFileScanImageToScanRegion();\n            }\n            else {\n                $this.clearScanRegion();\n                $this.getCameraScanRegion().style.display = \"block\";\n                $this.fileSelectionUi.hide();\n                switchScanTypeLink.innerText = TEXT_IF_CAMERA_SCAN_SELECTED;\n                $this.currentScanType = _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScanType.SCAN_TYPE_CAMERA;\n                $this.insertCameraScanImageToScanRegion();\n                $this.startCameraScanIfPermissionExistsOnSwap();\n            }\n            $this.sectionSwapAllowed = true;\n        });\n        switchContainer.appendChild(switchScanTypeLink);\n        section.appendChild(switchContainer);\n    };\n    Html5QrcodeScanner.prototype.startCameraScanIfPermissionExistsOnSwap = function () {\n        var _this = this;\n        var $this = this;\n        if (this.persistedDataManager.hasCameraPermissions()) {\n            _camera_permissions__WEBPACK_IMPORTED_MODULE_6__.CameraPermissions.hasPermissions().then(function (hasPermissions) {\n                if (hasPermissions) {\n                    var permissionButton = document.getElementById($this.getCameraPermissionButtonId());\n                    if (!permissionButton) {\n                        _this.logger.logError(\"Permission button not found, fail;\");\n                        throw \"Permission button not found\";\n                    }\n                    permissionButton.click();\n                }\n                else {\n                    $this.persistedDataManager.setHasPermission(false);\n                }\n            }).catch(function (_) {\n                $this.persistedDataManager.setHasPermission(false);\n            });\n            return;\n        }\n    };\n    Html5QrcodeScanner.prototype.resetHeaderMessage = function () {\n        var messageDiv = document.getElementById(this.getHeaderMessageContainerId());\n        messageDiv.style.display = \"none\";\n    };\n    Html5QrcodeScanner.prototype.setHeaderMessage = function (messageText, scannerStatus) {\n        if (!scannerStatus) {\n            scannerStatus = Html5QrcodeScannerStatus.STATUS_DEFAULT;\n        }\n        var messageDiv = this.getHeaderMessageDiv();\n        messageDiv.innerText = messageText;\n        messageDiv.style.display = \"block\";\n        switch (scannerStatus) {\n            case Html5QrcodeScannerStatus.STATUS_SUCCESS:\n                messageDiv.style.background = \"rgba(106, 175, 80, 0.26)\";\n                messageDiv.style.color = \"#477735\";\n                break;\n            case Html5QrcodeScannerStatus.STATUS_WARNING:\n                messageDiv.style.background = \"rgba(203, 36, 49, 0.14)\";\n                messageDiv.style.color = \"#cb2431\";\n                break;\n            case Html5QrcodeScannerStatus.STATUS_DEFAULT:\n            default:\n                messageDiv.style.background = \"rgba(0, 0, 0, 0)\";\n                messageDiv.style.color = \"rgb(17, 17, 17)\";\n                break;\n        }\n    };\n    Html5QrcodeScanner.prototype.showHideScanTypeSwapLink = function (shouldDisplay) {\n        if (this.scanTypeSelector.hasMoreThanOneScanType()) {\n            if (shouldDisplay !== true) {\n                shouldDisplay = false;\n            }\n            this.sectionSwapAllowed = shouldDisplay;\n            this.getDashboardSectionSwapLink().style.display\n                = shouldDisplay ? \"inline-block\" : \"none\";\n        }\n    };\n    Html5QrcodeScanner.prototype.insertCameraScanImageToScanRegion = function () {\n        var $this = this;\n        var qrCodeScanRegion = document.getElementById(this.getScanRegionId());\n        if (this.cameraScanImage) {\n            qrCodeScanRegion.innerHTML = \"<br>\";\n            qrCodeScanRegion.appendChild(this.cameraScanImage);\n            return;\n        }\n        this.cameraScanImage = new Image;\n        this.cameraScanImage.onload = function (_) {\n            qrCodeScanRegion.innerHTML = \"<br>\";\n            qrCodeScanRegion.appendChild($this.cameraScanImage);\n        };\n        this.cameraScanImage.width = 64;\n        this.cameraScanImage.style.opacity = \"0.8\";\n        this.cameraScanImage.src = _image_assets__WEBPACK_IMPORTED_MODULE_3__.ASSET_CAMERA_SCAN;\n        this.cameraScanImage.alt = _strings__WEBPACK_IMPORTED_MODULE_2__.Html5QrcodeScannerStrings.cameraScanAltText();\n    };\n    Html5QrcodeScanner.prototype.insertFileScanImageToScanRegion = function () {\n        var $this = this;\n        var qrCodeScanRegion = document.getElementById(this.getScanRegionId());\n        if (this.fileScanImage) {\n            qrCodeScanRegion.innerHTML = \"<br>\";\n            qrCodeScanRegion.appendChild(this.fileScanImage);\n            return;\n        }\n        this.fileScanImage = new Image;\n        this.fileScanImage.onload = function (_) {\n            qrCodeScanRegion.innerHTML = \"<br>\";\n            qrCodeScanRegion.appendChild($this.fileScanImage);\n        };\n        this.fileScanImage.width = 64;\n        this.fileScanImage.style.opacity = \"0.8\";\n        this.fileScanImage.src = _image_assets__WEBPACK_IMPORTED_MODULE_3__.ASSET_FILE_SCAN;\n        this.fileScanImage.alt = _strings__WEBPACK_IMPORTED_MODULE_2__.Html5QrcodeScannerStrings.fileScanAltText();\n    };\n    Html5QrcodeScanner.prototype.clearScanRegion = function () {\n        var qrCodeScanRegion = document.getElementById(this.getScanRegionId());\n        qrCodeScanRegion.innerHTML = \"\";\n    };\n    Html5QrcodeScanner.prototype.getDashboardSectionId = function () {\n        return \"\".concat(this.elementId, \"__dashboard_section\");\n    };\n    Html5QrcodeScanner.prototype.getDashboardSectionCameraScanRegionId = function () {\n        return \"\".concat(this.elementId, \"__dashboard_section_csr\");\n    };\n    Html5QrcodeScanner.prototype.getDashboardSectionSwapLinkId = function () {\n        return _ui_scanner_base__WEBPACK_IMPORTED_MODULE_10__.PublicUiElementIdAndClasses.SCAN_TYPE_CHANGE_ANCHOR_ID;\n    };\n    Html5QrcodeScanner.prototype.getScanRegionId = function () {\n        return \"\".concat(this.elementId, \"__scan_region\");\n    };\n    Html5QrcodeScanner.prototype.getDashboardId = function () {\n        return \"\".concat(this.elementId, \"__dashboard\");\n    };\n    Html5QrcodeScanner.prototype.getHeaderMessageContainerId = function () {\n        return \"\".concat(this.elementId, \"__header_message\");\n    };\n    Html5QrcodeScanner.prototype.getCameraPermissionButtonId = function () {\n        return _ui_scanner_base__WEBPACK_IMPORTED_MODULE_10__.PublicUiElementIdAndClasses.CAMERA_PERMISSION_BUTTON_ID;\n    };\n    Html5QrcodeScanner.prototype.getCameraScanRegion = function () {\n        return document.getElementById(this.getDashboardSectionCameraScanRegionId());\n    };\n    Html5QrcodeScanner.prototype.getDashboardSectionSwapLink = function () {\n        return document.getElementById(this.getDashboardSectionSwapLinkId());\n    };\n    Html5QrcodeScanner.prototype.getHeaderMessageDiv = function () {\n        return document.getElementById(this.getHeaderMessageContainerId());\n    };\n    return Html5QrcodeScanner;\n}());\n\n//# sourceMappingURL=html5-qrcode-scanner.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9odG1sNS1xcmNvZGUtc2Nhbm5lci5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9odG1sNS1xcmNvZGUtc2Nhbm5lci5qcz84NWQ1Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0bWw1UXJjb2RlQ29uc3RhbnRzLCBIdG1sNVFyY29kZVNjYW5UeXBlLCBIdG1sNVFyY29kZUVycm9yRmFjdG9yeSwgQmFzZUxvZ2dnZXIsIGlzTnVsbE9yVW5kZWZpbmVkLCBjbGlwLCB9IGZyb20gXCIuL2NvcmVcIjtcbmltcG9ydCB7IEh0bWw1UXJjb2RlLCB9IGZyb20gXCIuL2h0bWw1LXFyY29kZVwiO1xuaW1wb3J0IHsgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncywgfSBmcm9tIFwiLi9zdHJpbmdzXCI7XG5pbXBvcnQgeyBBU1NFVF9GSUxFX1NDQU4sIEFTU0VUX0NBTUVSQV9TQ0FOLCB9IGZyb20gXCIuL2ltYWdlLWFzc2V0c1wiO1xuaW1wb3J0IHsgUGVyc2lzdGVkRGF0YU1hbmFnZXIgfSBmcm9tIFwiLi9zdG9yYWdlXCI7XG5pbXBvcnQgeyBMaWJyYXJ5SW5mb0NvbnRhaW5lciB9IGZyb20gXCIuL3VpXCI7XG5pbXBvcnQgeyBDYW1lcmFQZXJtaXNzaW9ucyB9IGZyb20gXCIuL2NhbWVyYS9wZXJtaXNzaW9uc1wiO1xuaW1wb3J0IHsgU2NhblR5cGVTZWxlY3RvciB9IGZyb20gXCIuL3VpL3NjYW5uZXIvc2Nhbi10eXBlLXNlbGVjdG9yXCI7XG5pbXBvcnQgeyBUb3JjaEJ1dHRvbiB9IGZyb20gXCIuL3VpL3NjYW5uZXIvdG9yY2gtYnV0dG9uXCI7XG5pbXBvcnQgeyBGaWxlU2VsZWN0aW9uVWkgfSBmcm9tIFwiLi91aS9zY2FubmVyL2ZpbGUtc2VsZWN0aW9uLXVpXCI7XG5pbXBvcnQgeyBCYXNlVWlFbGVtZW50RmFjdG9yeSwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzIH0gZnJvbSBcIi4vdWkvc2Nhbm5lci9iYXNlXCI7XG5pbXBvcnQgeyBDYW1lcmFTZWxlY3Rpb25VaSB9IGZyb20gXCIuL3VpL3NjYW5uZXIvY2FtZXJhLXNlbGVjdGlvbi11aVwiO1xuaW1wb3J0IHsgQ2FtZXJhWm9vbVVpIH0gZnJvbSBcIi4vdWkvc2Nhbm5lci9jYW1lcmEtem9vbS11aVwiO1xudmFyIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cztcbihmdW5jdGlvbiAoSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzKSB7XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzW0h0bWw1UXJjb2RlU2Nhbm5lclN0YXR1c1tcIlNUQVRVU19ERUZBVUxUXCJdID0gMF0gPSBcIlNUQVRVU19ERUZBVUxUXCI7XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzW0h0bWw1UXJjb2RlU2Nhbm5lclN0YXR1c1tcIlNUQVRVU19TVUNDRVNTXCJdID0gMV0gPSBcIlNUQVRVU19TVUNDRVNTXCI7XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzW0h0bWw1UXJjb2RlU2Nhbm5lclN0YXR1c1tcIlNUQVRVU19XQVJOSU5HXCJdID0gMl0gPSBcIlNUQVRVU19XQVJOSU5HXCI7XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzW0h0bWw1UXJjb2RlU2Nhbm5lclN0YXR1c1tcIlNUQVRVU19SRVFVRVNUSU5HX1BFUk1JU1NJT05cIl0gPSAzXSA9IFwiU1RBVFVTX1JFUVVFU1RJTkdfUEVSTUlTU0lPTlwiO1xufSkoSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzIHx8IChIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMgPSB7fSkpO1xuZnVuY3Rpb24gdG9IdG1sNVFyY29kZUNhbWVyYVNjYW5Db25maWcoY29uZmlnKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZnBzOiBjb25maWcuZnBzLFxuICAgICAgICBxcmJveDogY29uZmlnLnFyYm94LFxuICAgICAgICBhc3BlY3RSYXRpbzogY29uZmlnLmFzcGVjdFJhdGlvLFxuICAgICAgICBkaXNhYmxlRmxpcDogY29uZmlnLmRpc2FibGVGbGlwLFxuICAgICAgICB2aWRlb0NvbnN0cmFpbnRzOiBjb25maWcudmlkZW9Db25zdHJhaW50c1xuICAgIH07XG59XG5mdW5jdGlvbiB0b0h0bWw1UXJjb2RlRnVsbENvbmZpZyhjb25maWcsIHZlcmJvc2UpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBmb3JtYXRzVG9TdXBwb3J0OiBjb25maWcuZm9ybWF0c1RvU3VwcG9ydCxcbiAgICAgICAgdXNlQmFyQ29kZURldGVjdG9ySWZTdXBwb3J0ZWQ6IGNvbmZpZy51c2VCYXJDb2RlRGV0ZWN0b3JJZlN1cHBvcnRlZCxcbiAgICAgICAgZXhwZXJpbWVudGFsRmVhdHVyZXM6IGNvbmZpZy5leHBlcmltZW50YWxGZWF0dXJlcyxcbiAgICAgICAgdmVyYm9zZTogdmVyYm9zZVxuICAgIH07XG59XG52YXIgSHRtbDVRcmNvZGVTY2FubmVyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBIdG1sNVFyY29kZVNjYW5uZXIoZWxlbWVudElkLCBjb25maWcsIHZlcmJvc2UpIHtcbiAgICAgICAgdGhpcy5sYXN0TWF0Y2hGb3VuZCA9IG51bGw7XG4gICAgICAgIHRoaXMuY2FtZXJhU2NhbkltYWdlID0gbnVsbDtcbiAgICAgICAgdGhpcy5maWxlU2NhbkltYWdlID0gbnVsbDtcbiAgICAgICAgdGhpcy5maWxlU2VsZWN0aW9uVWkgPSBudWxsO1xuICAgICAgICB0aGlzLmVsZW1lbnRJZCA9IGVsZW1lbnRJZDtcbiAgICAgICAgdGhpcy5jb25maWcgPSB0aGlzLmNyZWF0ZUNvbmZpZyhjb25maWcpO1xuICAgICAgICB0aGlzLnZlcmJvc2UgPSB2ZXJib3NlID09PSB0cnVlO1xuICAgICAgICBpZiAoIWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGVsZW1lbnRJZCkpIHtcbiAgICAgICAgICAgIHRocm93IFwiSFRNTCBFbGVtZW50IHdpdGggaWQ9XCIuY29uY2F0KGVsZW1lbnRJZCwgXCIgbm90IGZvdW5kXCIpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2NhblR5cGVTZWxlY3RvciA9IG5ldyBTY2FuVHlwZVNlbGVjdG9yKHRoaXMuY29uZmlnLnN1cHBvcnRlZFNjYW5UeXBlcyk7XG4gICAgICAgIHRoaXMuY3VycmVudFNjYW5UeXBlID0gdGhpcy5zY2FuVHlwZVNlbGVjdG9yLmdldERlZmF1bHRTY2FuVHlwZSgpO1xuICAgICAgICB0aGlzLnNlY3Rpb25Td2FwQWxsb3dlZCA9IHRydWU7XG4gICAgICAgIHRoaXMubG9nZ2VyID0gbmV3IEJhc2VMb2dnZ2VyKHRoaXMudmVyYm9zZSk7XG4gICAgICAgIHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIgPSBuZXcgUGVyc2lzdGVkRGF0YU1hbmFnZXIoKTtcbiAgICAgICAgaWYgKGNvbmZpZy5yZW1lbWJlckxhc3RVc2VkQ2FtZXJhICE9PSB0cnVlKSB7XG4gICAgICAgICAgICB0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLnJlc2V0KCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocXJDb2RlU3VjY2Vzc0NhbGxiYWNrLCBxckNvZGVFcnJvckNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMubGFzdE1hdGNoRm91bmQgPSBudWxsO1xuICAgICAgICB0aGlzLnFyQ29kZVN1Y2Nlc3NDYWxsYmFja1xuICAgICAgICAgICAgPSBmdW5jdGlvbiAoZGVjb2RlZFRleHQsIHJlc3VsdCkge1xuICAgICAgICAgICAgICAgIGlmIChxckNvZGVTdWNjZXNzQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgcXJDb2RlU3VjY2Vzc0NhbGxiYWNrKGRlY29kZWRUZXh0LCByZXN1bHQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLmxhc3RNYXRjaEZvdW5kID09PSBkZWNvZGVkVGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmxhc3RNYXRjaEZvdW5kID0gZGVjb2RlZFRleHQ7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnNldEhlYWRlck1lc3NhZ2UoSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5sYXN0TWF0Y2goZGVjb2RlZFRleHQpLCBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMuU1RBVFVTX1NVQ0NFU1MpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIHRoaXMucXJDb2RlRXJyb3JDYWxsYmFjayA9XG4gICAgICAgICAgICBmdW5jdGlvbiAoZXJyb3JNZXNzYWdlLCBlcnJvcikge1xuICAgICAgICAgICAgICAgIGlmIChxckNvZGVFcnJvckNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHFyQ29kZUVycm9yQ2FsbGJhY2soZXJyb3JNZXNzYWdlLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgdmFyIGNvbnRhaW5lciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZWxlbWVudElkKTtcbiAgICAgICAgaWYgKCFjb250YWluZXIpIHtcbiAgICAgICAgICAgIHRocm93IFwiSFRNTCBFbGVtZW50IHdpdGggaWQ9XCIuY29uY2F0KHRoaXMuZWxlbWVudElkLCBcIiBub3QgZm91bmRcIik7XG4gICAgICAgIH1cbiAgICAgICAgY29udGFpbmVyLmlubmVySFRNTCA9IFwiXCI7XG4gICAgICAgIHRoaXMuY3JlYXRlQmFzaWNMYXlvdXQoY29udGFpbmVyKTtcbiAgICAgICAgdGhpcy5odG1sNVFyY29kZSA9IG5ldyBIdG1sNVFyY29kZSh0aGlzLmdldFNjYW5SZWdpb25JZCgpLCB0b0h0bWw1UXJjb2RlRnVsbENvbmZpZyh0aGlzLmNvbmZpZywgdGhpcy52ZXJib3NlKSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLnBhdXNlID0gZnVuY3Rpb24gKHNob3VsZFBhdXNlVmlkZW8pIHtcbiAgICAgICAgaWYgKGlzTnVsbE9yVW5kZWZpbmVkKHNob3VsZFBhdXNlVmlkZW8pIHx8IHNob3VsZFBhdXNlVmlkZW8gIT09IHRydWUpIHtcbiAgICAgICAgICAgIHNob3VsZFBhdXNlVmlkZW8gPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmdldEh0bWw1UXJjb2RlT3JGYWlsKCkucGF1c2Uoc2hvdWxkUGF1c2VWaWRlbyk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLnJlc3VtZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5nZXRIdG1sNVFyY29kZU9yRmFpbCgpLnJlc3VtZSgpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0SHRtbDVRcmNvZGVPckZhaWwoKS5nZXRTdGF0ZSgpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGVtcHR5SHRtbENvbnRhaW5lciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBtYWluQ29udGFpbmVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoX3RoaXMuZWxlbWVudElkKTtcbiAgICAgICAgICAgIGlmIChtYWluQ29udGFpbmVyKSB7XG4gICAgICAgICAgICAgICAgbWFpbkNvbnRhaW5lci5pbm5lckhUTUwgPSBcIlwiO1xuICAgICAgICAgICAgICAgIF90aGlzLnJlc2V0QmFzaWNMYXlvdXQobWFpbkNvbnRhaW5lcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGlmICh0aGlzLmh0bWw1UXJjb2RlKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAgICAgICAgIGlmICghX3RoaXMuaHRtbDVRcmNvZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5odG1sNVFyY29kZS5pc1NjYW5uaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmh0bWw1UXJjb2RlLnN0b3AoKS50aGVuKGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmh0bWw1UXJjb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmh0bWw1UXJjb2RlLmNsZWFyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbXB0eUh0bWxDb250YWluZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMudmVyYm9zZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmxvZ2dlci5sb2dFcnJvcihcIlVuYWJsZSB0byBzdG9wIHFyY29kZSBzY2FubmVyXCIsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuaHRtbDVRcmNvZGUuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICAgICAgZW1wdHlIdG1sQ29udGFpbmVyKCk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmdldFJ1bm5pbmdUcmFja0NhcGFiaWxpdGllcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0SHRtbDVRcmNvZGVPckZhaWwoKS5nZXRSdW5uaW5nVHJhY2tDYXBhYmlsaXRpZXMoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuZ2V0UnVubmluZ1RyYWNrU2V0dGluZ3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEh0bWw1UXJjb2RlT3JGYWlsKCkuZ2V0UnVubmluZ1RyYWNrU2V0dGluZ3MoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuYXBwbHlWaWRlb0NvbnN0cmFpbnRzID0gZnVuY3Rpb24gKHZpZGVvQ29uc3RhaW50cykge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRIdG1sNVFyY29kZU9yRmFpbCgpLmFwcGx5VmlkZW9Db25zdHJhaW50cyh2aWRlb0NvbnN0YWludHMpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXRIdG1sNVFyY29kZU9yRmFpbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmh0bWw1UXJjb2RlKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkNvZGUgc2Nhbm5lciBub3QgaW5pdGlhbGl6ZWQuXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuaHRtbDVRcmNvZGU7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmNyZWF0ZUNvbmZpZyA9IGZ1bmN0aW9uIChjb25maWcpIHtcbiAgICAgICAgaWYgKGNvbmZpZykge1xuICAgICAgICAgICAgaWYgKCFjb25maWcuZnBzKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLmZwcyA9IEh0bWw1UXJjb2RlQ29uc3RhbnRzLlNDQU5fREVGQVVMVF9GUFM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29uZmlnLnJlbWVtYmVyTGFzdFVzZWRDYW1lcmEgIT09ICghSHRtbDVRcmNvZGVDb25zdGFudHMuREVGQVVMVF9SRU1FTUJFUl9MQVNUX0NBTUVSQV9VU0VEKSkge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5yZW1lbWJlckxhc3RVc2VkQ2FtZXJhXG4gICAgICAgICAgICAgICAgICAgID0gSHRtbDVRcmNvZGVDb25zdGFudHMuREVGQVVMVF9SRU1FTUJFUl9MQVNUX0NBTUVSQV9VU0VEO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFjb25maWcuc3VwcG9ydGVkU2NhblR5cGVzKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLnN1cHBvcnRlZFNjYW5UeXBlc1xuICAgICAgICAgICAgICAgICAgICA9IEh0bWw1UXJjb2RlQ29uc3RhbnRzLkRFRkFVTFRfU1VQUE9SVEVEX1NDQU5fVFlQRTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBjb25maWc7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGZwczogSHRtbDVRcmNvZGVDb25zdGFudHMuU0NBTl9ERUZBVUxUX0ZQUyxcbiAgICAgICAgICAgIHJlbWVtYmVyTGFzdFVzZWRDYW1lcmE6IEh0bWw1UXJjb2RlQ29uc3RhbnRzLkRFRkFVTFRfUkVNRU1CRVJfTEFTVF9DQU1FUkFfVVNFRCxcbiAgICAgICAgICAgIHN1cHBvcnRlZFNjYW5UeXBlczogSHRtbDVRcmNvZGVDb25zdGFudHMuREVGQVVMVF9TVVBQT1JURURfU0NBTl9UWVBFXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmNyZWF0ZUJhc2ljTGF5b3V0ID0gZnVuY3Rpb24gKHBhcmVudCkge1xuICAgICAgICBwYXJlbnQuc3R5bGUucG9zaXRpb24gPSBcInJlbGF0aXZlXCI7XG4gICAgICAgIHBhcmVudC5zdHlsZS5wYWRkaW5nID0gXCIwcHhcIjtcbiAgICAgICAgcGFyZW50LnN0eWxlLmJvcmRlciA9IFwiMXB4IHNvbGlkIHNpbHZlclwiO1xuICAgICAgICB0aGlzLmNyZWF0ZUhlYWRlcihwYXJlbnQpO1xuICAgICAgICB2YXIgcXJDb2RlU2NhblJlZ2lvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHZhciBzY2FuUmVnaW9uSWQgPSB0aGlzLmdldFNjYW5SZWdpb25JZCgpO1xuICAgICAgICBxckNvZGVTY2FuUmVnaW9uLmlkID0gc2NhblJlZ2lvbklkO1xuICAgICAgICBxckNvZGVTY2FuUmVnaW9uLnN0eWxlLndpZHRoID0gXCIxMDAlXCI7XG4gICAgICAgIHFyQ29kZVNjYW5SZWdpb24uc3R5bGUubWluSGVpZ2h0ID0gXCIxMDBweFwiO1xuICAgICAgICBxckNvZGVTY2FuUmVnaW9uLnN0eWxlLnRleHRBbGlnbiA9IFwiY2VudGVyXCI7XG4gICAgICAgIHBhcmVudC5hcHBlbmRDaGlsZChxckNvZGVTY2FuUmVnaW9uKTtcbiAgICAgICAgaWYgKFNjYW5UeXBlU2VsZWN0b3IuaXNDYW1lcmFTY2FuVHlwZSh0aGlzLmN1cnJlbnRTY2FuVHlwZSkpIHtcbiAgICAgICAgICAgIHRoaXMuaW5zZXJ0Q2FtZXJhU2NhbkltYWdlVG9TY2FuUmVnaW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmluc2VydEZpbGVTY2FuSW1hZ2VUb1NjYW5SZWdpb24oKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcXJDb2RlRGFzaGJvYXJkID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgdmFyIGRhc2hib2FyZElkID0gdGhpcy5nZXREYXNoYm9hcmRJZCgpO1xuICAgICAgICBxckNvZGVEYXNoYm9hcmQuaWQgPSBkYXNoYm9hcmRJZDtcbiAgICAgICAgcXJDb2RlRGFzaGJvYXJkLnN0eWxlLndpZHRoID0gXCIxMDAlXCI7XG4gICAgICAgIHBhcmVudC5hcHBlbmRDaGlsZChxckNvZGVEYXNoYm9hcmQpO1xuICAgICAgICB0aGlzLnNldHVwSW5pdGlhbERhc2hib2FyZChxckNvZGVEYXNoYm9hcmQpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5yZXNldEJhc2ljTGF5b3V0ID0gZnVuY3Rpb24gKG1haW5Db250YWluZXIpIHtcbiAgICAgICAgbWFpbkNvbnRhaW5lci5zdHlsZS5ib3JkZXIgPSBcIm5vbmVcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuc2V0dXBJbml0aWFsRGFzaGJvYXJkID0gZnVuY3Rpb24gKGRhc2hib2FyZCkge1xuICAgICAgICB0aGlzLmNyZWF0ZVNlY3Rpb24oZGFzaGJvYXJkKTtcbiAgICAgICAgdGhpcy5jcmVhdGVTZWN0aW9uQ29udHJvbFBhbmVsKCk7XG4gICAgICAgIGlmICh0aGlzLnNjYW5UeXBlU2VsZWN0b3IuaGFzTW9yZVRoYW5PbmVTY2FuVHlwZSgpKSB7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVNlY3Rpb25Td2FwKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuY3JlYXRlSGVhZGVyID0gZnVuY3Rpb24gKGRhc2hib2FyZCkge1xuICAgICAgICB2YXIgaGVhZGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgaGVhZGVyLnN0eWxlLnRleHRBbGlnbiA9IFwibGVmdFwiO1xuICAgICAgICBoZWFkZXIuc3R5bGUubWFyZ2luID0gXCIwcHhcIjtcbiAgICAgICAgZGFzaGJvYXJkLmFwcGVuZENoaWxkKGhlYWRlcik7XG4gICAgICAgIHZhciBsaWJyYXJ5SW5mbyA9IG5ldyBMaWJyYXJ5SW5mb0NvbnRhaW5lcigpO1xuICAgICAgICBsaWJyYXJ5SW5mby5yZW5kZXJJbnRvKGhlYWRlcik7XG4gICAgICAgIHZhciBoZWFkZXJNZXNzYWdlQ29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgaGVhZGVyTWVzc2FnZUNvbnRhaW5lci5pZCA9IHRoaXMuZ2V0SGVhZGVyTWVzc2FnZUNvbnRhaW5lcklkKCk7XG4gICAgICAgIGhlYWRlck1lc3NhZ2VDb250YWluZXIuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICBoZWFkZXJNZXNzYWdlQ29udGFpbmVyLnN0eWxlLnRleHRBbGlnbiA9IFwiY2VudGVyXCI7XG4gICAgICAgIGhlYWRlck1lc3NhZ2VDb250YWluZXIuc3R5bGUuZm9udFNpemUgPSBcIjE0cHhcIjtcbiAgICAgICAgaGVhZGVyTWVzc2FnZUNvbnRhaW5lci5zdHlsZS5wYWRkaW5nID0gXCIycHggMTBweFwiO1xuICAgICAgICBoZWFkZXJNZXNzYWdlQ29udGFpbmVyLnN0eWxlLm1hcmdpbiA9IFwiNHB4XCI7XG4gICAgICAgIGhlYWRlck1lc3NhZ2VDb250YWluZXIuc3R5bGUuYm9yZGVyVG9wID0gXCIxcHggc29saWQgI2Y2ZjZmNlwiO1xuICAgICAgICBoZWFkZXIuYXBwZW5kQ2hpbGQoaGVhZGVyTWVzc2FnZUNvbnRhaW5lcik7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmNyZWF0ZVNlY3Rpb24gPSBmdW5jdGlvbiAoZGFzaGJvYXJkKSB7XG4gICAgICAgIHZhciBzZWN0aW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgc2VjdGlvbi5pZCA9IHRoaXMuZ2V0RGFzaGJvYXJkU2VjdGlvbklkKCk7XG4gICAgICAgIHNlY3Rpb24uc3R5bGUud2lkdGggPSBcIjEwMCVcIjtcbiAgICAgICAgc2VjdGlvbi5zdHlsZS5wYWRkaW5nID0gXCIxMHB4IDBweCAxMHB4IDBweFwiO1xuICAgICAgICBzZWN0aW9uLnN0eWxlLnRleHRBbGlnbiA9IFwibGVmdFwiO1xuICAgICAgICBkYXNoYm9hcmQuYXBwZW5kQ2hpbGQoc2VjdGlvbik7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmNyZWF0ZUNhbWVyYUxpc3RVaSA9IGZ1bmN0aW9uIChzY3BDYW1lcmFTY2FuUmVnaW9uLCByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lciwgcmVxdWVzdFBlcm1pc3Npb25CdXR0b24pIHtcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgJHRoaXMuc2hvd0hpZGVTY2FuVHlwZVN3YXBMaW5rKGZhbHNlKTtcbiAgICAgICAgJHRoaXMuc2V0SGVhZGVyTWVzc2FnZShIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmNhbWVyYVBlcm1pc3Npb25SZXF1ZXN0aW5nKCkpO1xuICAgICAgICB2YXIgY3JlYXRlUGVybWlzc2lvbkJ1dHRvbklmTm90RXhpc3RzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKCFyZXF1ZXN0UGVybWlzc2lvbkJ1dHRvbikge1xuICAgICAgICAgICAgICAgICR0aGlzLmNyZWF0ZVBlcm1pc3Npb25CdXR0b24oc2NwQ2FtZXJhU2NhblJlZ2lvbiwgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBIdG1sNVFyY29kZS5nZXRDYW1lcmFzKCkudGhlbihmdW5jdGlvbiAoY2FtZXJhcykge1xuICAgICAgICAgICAgJHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuc2V0SGFzUGVybWlzc2lvbih0cnVlKTtcbiAgICAgICAgICAgICR0aGlzLnNob3dIaWRlU2NhblR5cGVTd2FwTGluayh0cnVlKTtcbiAgICAgICAgICAgICR0aGlzLnJlc2V0SGVhZGVyTWVzc2FnZSgpO1xuICAgICAgICAgICAgaWYgKGNhbWVyYXMgJiYgY2FtZXJhcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgc2NwQ2FtZXJhU2NhblJlZ2lvbi5yZW1vdmVDaGlsZChyZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lcik7XG4gICAgICAgICAgICAgICAgJHRoaXMucmVuZGVyQ2FtZXJhU2VsZWN0aW9uKGNhbWVyYXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuc2V0SGVhZGVyTWVzc2FnZShIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLm5vQ2FtZXJhRm91bmQoKSwgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19XQVJOSU5HKTtcbiAgICAgICAgICAgICAgICBjcmVhdGVQZXJtaXNzaW9uQnV0dG9uSWZOb3RFeGlzdHMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAkdGhpcy5wZXJzaXN0ZWREYXRhTWFuYWdlci5zZXRIYXNQZXJtaXNzaW9uKGZhbHNlKTtcbiAgICAgICAgICAgIGlmIChyZXF1ZXN0UGVybWlzc2lvbkJ1dHRvbikge1xuICAgICAgICAgICAgICAgIHJlcXVlc3RQZXJtaXNzaW9uQnV0dG9uLmRpc2FibGVkID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjcmVhdGVQZXJtaXNzaW9uQnV0dG9uSWZOb3RFeGlzdHMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICR0aGlzLnNldEhlYWRlck1lc3NhZ2UoZXJyb3IsIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cy5TVEFUVVNfV0FSTklORyk7XG4gICAgICAgICAgICAkdGhpcy5zaG93SGlkZVNjYW5UeXBlU3dhcExpbmsodHJ1ZSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5jcmVhdGVQZXJtaXNzaW9uQnV0dG9uID0gZnVuY3Rpb24gKHNjcENhbWVyYVNjYW5SZWdpb24sIHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyKSB7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciByZXF1ZXN0UGVybWlzc2lvbkJ1dHRvbiA9IEJhc2VVaUVsZW1lbnRGYWN0b3J5XG4gICAgICAgICAgICAuY3JlYXRlRWxlbWVudChcImJ1dHRvblwiLCB0aGlzLmdldENhbWVyYVBlcm1pc3Npb25CdXR0b25JZCgpKTtcbiAgICAgICAgcmVxdWVzdFBlcm1pc3Npb25CdXR0b24uaW5uZXJUZXh0XG4gICAgICAgICAgICA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuY2FtZXJhUGVybWlzc2lvblRpdGxlKCk7XG4gICAgICAgIHJlcXVlc3RQZXJtaXNzaW9uQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXF1ZXN0UGVybWlzc2lvbkJ1dHRvbi5kaXNhYmxlZCA9IHRydWU7XG4gICAgICAgICAgICAkdGhpcy5jcmVhdGVDYW1lcmFMaXN0VWkoc2NwQ2FtZXJhU2NhblJlZ2lvbiwgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIsIHJlcXVlc3RQZXJtaXNzaW9uQnV0dG9uKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyLmFwcGVuZENoaWxkKHJlcXVlc3RQZXJtaXNzaW9uQnV0dG9uKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuY3JlYXRlUGVybWlzc2lvbnNVaSA9IGZ1bmN0aW9uIChzY3BDYW1lcmFTY2FuUmVnaW9uLCByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lcikge1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoU2NhblR5cGVTZWxlY3Rvci5pc0NhbWVyYVNjYW5UeXBlKHRoaXMuY3VycmVudFNjYW5UeXBlKVxuICAgICAgICAgICAgJiYgdGhpcy5wZXJzaXN0ZWREYXRhTWFuYWdlci5oYXNDYW1lcmFQZXJtaXNzaW9ucygpKSB7XG4gICAgICAgICAgICBDYW1lcmFQZXJtaXNzaW9ucy5oYXNQZXJtaXNzaW9ucygpLnRoZW4oZnVuY3Rpb24gKGhhc1Blcm1pc3Npb25zKSB7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1Blcm1pc3Npb25zKSB7XG4gICAgICAgICAgICAgICAgICAgICR0aGlzLmNyZWF0ZUNhbWVyYUxpc3RVaShzY3BDYW1lcmFTY2FuUmVnaW9uLCByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5wZXJzaXN0ZWREYXRhTWFuYWdlci5zZXRIYXNQZXJtaXNzaW9uKGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMuY3JlYXRlUGVybWlzc2lvbkJ1dHRvbihzY3BDYW1lcmFTY2FuUmVnaW9uLCByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKF8pIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5wZXJzaXN0ZWREYXRhTWFuYWdlci5zZXRIYXNQZXJtaXNzaW9uKGZhbHNlKTtcbiAgICAgICAgICAgICAgICAkdGhpcy5jcmVhdGVQZXJtaXNzaW9uQnV0dG9uKHNjcENhbWVyYVNjYW5SZWdpb24sIHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY3JlYXRlUGVybWlzc2lvbkJ1dHRvbihzY3BDYW1lcmFTY2FuUmVnaW9uLCByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lcik7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmNyZWF0ZVNlY3Rpb25Db250cm9sUGFuZWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzZWN0aW9uID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5nZXREYXNoYm9hcmRTZWN0aW9uSWQoKSk7XG4gICAgICAgIHZhciBzZWN0aW9uQ29udHJvbFBhbmVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgc2VjdGlvbi5hcHBlbmRDaGlsZChzZWN0aW9uQ29udHJvbFBhbmVsKTtcbiAgICAgICAgdmFyIHNjcENhbWVyYVNjYW5SZWdpb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICBzY3BDYW1lcmFTY2FuUmVnaW9uLmlkID0gdGhpcy5nZXREYXNoYm9hcmRTZWN0aW9uQ2FtZXJhU2NhblJlZ2lvbklkKCk7XG4gICAgICAgIHNjcENhbWVyYVNjYW5SZWdpb24uc3R5bGUuZGlzcGxheVxuICAgICAgICAgICAgPSBTY2FuVHlwZVNlbGVjdG9yLmlzQ2FtZXJhU2NhblR5cGUodGhpcy5jdXJyZW50U2NhblR5cGUpXG4gICAgICAgICAgICAgICAgPyBcImJsb2NrXCIgOiBcIm5vbmVcIjtcbiAgICAgICAgc2VjdGlvbkNvbnRyb2xQYW5lbC5hcHBlbmRDaGlsZChzY3BDYW1lcmFTY2FuUmVnaW9uKTtcbiAgICAgICAgdmFyIHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIuc3R5bGUudGV4dEFsaWduID0gXCJjZW50ZXJcIjtcbiAgICAgICAgc2NwQ2FtZXJhU2NhblJlZ2lvbi5hcHBlbmRDaGlsZChyZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lcik7XG4gICAgICAgIGlmICh0aGlzLnNjYW5UeXBlU2VsZWN0b3IuaXNDYW1lcmFTY2FuUmVxdWlyZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5jcmVhdGVQZXJtaXNzaW9uc1VpKHNjcENhbWVyYVNjYW5SZWdpb24sIHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbmRlckZpbGVTY2FuVWkoc2VjdGlvbkNvbnRyb2xQYW5lbCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLnJlbmRlckZpbGVTY2FuVWkgPSBmdW5jdGlvbiAocGFyZW50KSB7XG4gICAgICAgIHZhciBzaG93T25SZW5kZXIgPSBTY2FuVHlwZVNlbGVjdG9yLmlzRmlsZVNjYW5UeXBlKHRoaXMuY3VycmVudFNjYW5UeXBlKTtcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgdmFyIG9uRmlsZVNlbGVjdGVkID0gZnVuY3Rpb24gKGZpbGUpIHtcbiAgICAgICAgICAgIGlmICghJHRoaXMuaHRtbDVRcmNvZGUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBcImh0bWw1UXJjb2RlIG5vdCBkZWZpbmVkXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIVNjYW5UeXBlU2VsZWN0b3IuaXNGaWxlU2NhblR5cGUoJHRoaXMuY3VycmVudFNjYW5UeXBlKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICR0aGlzLnNldEhlYWRlck1lc3NhZ2UoSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5sb2FkaW5nSW1hZ2UoKSk7XG4gICAgICAgICAgICAkdGhpcy5odG1sNVFyY29kZS5zY2FuRmlsZVYyKGZpbGUsIHRydWUpXG4gICAgICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKGh0bWw1cXJjb2RlUmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgJHRoaXMucmVzZXRIZWFkZXJNZXNzYWdlKCk7XG4gICAgICAgICAgICAgICAgJHRoaXMucXJDb2RlU3VjY2Vzc0NhbGxiYWNrKGh0bWw1cXJjb2RlUmVzdWx0LmRlY29kZWRUZXh0LCBodG1sNXFyY29kZVJlc3VsdCk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5zZXRIZWFkZXJNZXNzYWdlKGVycm9yLCBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMuU1RBVFVTX1dBUk5JTkcpO1xuICAgICAgICAgICAgICAgICR0aGlzLnFyQ29kZUVycm9yQ2FsbGJhY2soZXJyb3IsIEh0bWw1UXJjb2RlRXJyb3JGYWN0b3J5LmNyZWF0ZUZyb20oZXJyb3IpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmZpbGVTZWxlY3Rpb25VaSA9IEZpbGVTZWxlY3Rpb25VaS5jcmVhdGUocGFyZW50LCBzaG93T25SZW5kZXIsIG9uRmlsZVNlbGVjdGVkKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUucmVuZGVyQ2FtZXJhU2VsZWN0aW9uID0gZnVuY3Rpb24gKGNhbWVyYXMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHNjcENhbWVyYVNjYW5SZWdpb24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmdldERhc2hib2FyZFNlY3Rpb25DYW1lcmFTY2FuUmVnaW9uSWQoKSk7XG4gICAgICAgIHNjcENhbWVyYVNjYW5SZWdpb24uc3R5bGUudGV4dEFsaWduID0gXCJjZW50ZXJcIjtcbiAgICAgICAgdmFyIGNhbWVyYVpvb21VaSA9IENhbWVyYVpvb21VaS5jcmVhdGUoc2NwQ2FtZXJhU2NhblJlZ2lvbiwgZmFsc2UpO1xuICAgICAgICB2YXIgcmVuZGVyQ2FtZXJhWm9vbVVpSWZTdXBwb3J0ZWQgPSBmdW5jdGlvbiAoY2FtZXJhQ2FwYWJpbGl0aWVzKSB7XG4gICAgICAgICAgICB2YXIgem9vbUNhcGFiaWxpdHkgPSBjYW1lcmFDYXBhYmlsaXRpZXMuem9vbUZlYXR1cmUoKTtcbiAgICAgICAgICAgIGlmICghem9vbUNhcGFiaWxpdHkuaXNTdXBwb3J0ZWQoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbWVyYVpvb21VaS5zZXRPbkNhbWVyYVpvb21WYWx1ZUNoYW5nZUNhbGxiYWNrKGZ1bmN0aW9uICh6b29tVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB6b29tQ2FwYWJpbGl0eS5hcHBseSh6b29tVmFsdWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2YXIgZGVmYXVsdFpvb20gPSAxO1xuICAgICAgICAgICAgaWYgKF90aGlzLmNvbmZpZy5kZWZhdWx0Wm9vbVZhbHVlSWZTdXBwb3J0ZWQpIHtcbiAgICAgICAgICAgICAgICBkZWZhdWx0Wm9vbSA9IF90aGlzLmNvbmZpZy5kZWZhdWx0Wm9vbVZhbHVlSWZTdXBwb3J0ZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWZhdWx0Wm9vbSA9IGNsaXAoZGVmYXVsdFpvb20sIHpvb21DYXBhYmlsaXR5Lm1pbigpLCB6b29tQ2FwYWJpbGl0eS5tYXgoKSk7XG4gICAgICAgICAgICBjYW1lcmFab29tVWkuc2V0VmFsdWVzKHpvb21DYXBhYmlsaXR5Lm1pbigpLCB6b29tQ2FwYWJpbGl0eS5tYXgoKSwgZGVmYXVsdFpvb20sIHpvb21DYXBhYmlsaXR5LnN0ZXAoKSk7XG4gICAgICAgICAgICBjYW1lcmFab29tVWkuc2hvdygpO1xuICAgICAgICB9O1xuICAgICAgICB2YXIgY2FtZXJhU2VsZWN0VWkgPSBDYW1lcmFTZWxlY3Rpb25VaS5jcmVhdGUoc2NwQ2FtZXJhU2NhblJlZ2lvbiwgY2FtZXJhcyk7XG4gICAgICAgIHZhciBjYW1lcmFBY3Rpb25Db250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic3BhblwiKTtcbiAgICAgICAgdmFyIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uID0gQmFzZVVpRWxlbWVudEZhY3RvcnkuY3JlYXRlRWxlbWVudChcImJ1dHRvblwiLCBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuQ0FNRVJBX1NUQVJUX0JVVFRPTl9JRCk7XG4gICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLmlubmVyVGV4dFxuICAgICAgICAgICAgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnNjYW5CdXR0b25TdGFydFNjYW5uaW5nVGV4dCgpO1xuICAgICAgICBjYW1lcmFBY3Rpb25Db250YWluZXIuYXBwZW5kQ2hpbGQoY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24pO1xuICAgICAgICB2YXIgY2FtZXJhQWN0aW9uU3RvcEJ1dHRvbiA9IEJhc2VVaUVsZW1lbnRGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoXCJidXR0b25cIiwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkNBTUVSQV9TVE9QX0JVVFRPTl9JRCk7XG4gICAgICAgIGNhbWVyYUFjdGlvblN0b3BCdXR0b24uaW5uZXJUZXh0XG4gICAgICAgICAgICA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muc2NhbkJ1dHRvblN0b3BTY2FubmluZ1RleHQoKTtcbiAgICAgICAgY2FtZXJhQWN0aW9uU3RvcEJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICAgIGNhbWVyYUFjdGlvblN0b3BCdXR0b24uZGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICBjYW1lcmFBY3Rpb25Db250YWluZXIuYXBwZW5kQ2hpbGQoY2FtZXJhQWN0aW9uU3RvcEJ1dHRvbik7XG4gICAgICAgIHZhciB0b3JjaEJ1dHRvbjtcbiAgICAgICAgdmFyIGNyZWF0ZUFuZFNob3dUb3JjaEJ1dHRvbklmU3VwcG9ydGVkID0gZnVuY3Rpb24gKGNhbWVyYUNhcGFiaWxpdGllcykge1xuICAgICAgICAgICAgaWYgKCFjYW1lcmFDYXBhYmlsaXRpZXMudG9yY2hGZWF0dXJlKCkuaXNTdXBwb3J0ZWQoKSkge1xuICAgICAgICAgICAgICAgIGlmICh0b3JjaEJ1dHRvbikge1xuICAgICAgICAgICAgICAgICAgICB0b3JjaEJ1dHRvbi5oaWRlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdG9yY2hCdXR0b24pIHtcbiAgICAgICAgICAgICAgICB0b3JjaEJ1dHRvbiA9IFRvcmNoQnV0dG9uLmNyZWF0ZShjYW1lcmFBY3Rpb25Db250YWluZXIsIGNhbWVyYUNhcGFiaWxpdGllcy50b3JjaEZlYXR1cmUoKSwgeyBkaXNwbGF5OiBcIm5vbmVcIiwgbWFyZ2luTGVmdDogXCI1cHhcIiB9LCBmdW5jdGlvbiAoZXJyb3JNZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgICR0aGlzLnNldEhlYWRlck1lc3NhZ2UoZXJyb3JNZXNzYWdlLCBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMuU1RBVFVTX1dBUk5JTkcpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdG9yY2hCdXR0b24udXBkYXRlVG9yY2hDYXBhYmlsaXR5KGNhbWVyYUNhcGFiaWxpdGllcy50b3JjaEZlYXR1cmUoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0b3JjaEJ1dHRvbi5zaG93KCk7XG4gICAgICAgIH07XG4gICAgICAgIHNjcENhbWVyYVNjYW5SZWdpb24uYXBwZW5kQ2hpbGQoY2FtZXJhQWN0aW9uQ29udGFpbmVyKTtcbiAgICAgICAgdmFyIHJlc2V0Q2FtZXJhQWN0aW9uU3RhcnRCdXR0b24gPSBmdW5jdGlvbiAoc2hvdWxkU2hvdykge1xuICAgICAgICAgICAgaWYgKCFzaG91bGRTaG93KSB7XG4gICAgICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24uc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24uaW5uZXJUZXh0XG4gICAgICAgICAgICAgICAgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzXG4gICAgICAgICAgICAgICAgICAgIC5zY2FuQnV0dG9uU3RhcnRTY2FubmluZ1RleHQoKTtcbiAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLnN0eWxlLm9wYWNpdHkgPSBcIjFcIjtcbiAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLmRpc2FibGVkID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAoc2hvdWxkU2hvdykge1xuICAgICAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLnN0eWxlLmRpc3BsYXkgPSBcImlubGluZS1ibG9ja1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgZnVuY3Rpb24gKF8pIHtcbiAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLmlubmVyVGV4dFxuICAgICAgICAgICAgICAgID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5zY2FuQnV0dG9uU2Nhbm5pbmdTdGFydGluZygpO1xuICAgICAgICAgICAgY2FtZXJhU2VsZWN0VWkuZGlzYWJsZSgpO1xuICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24uZGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24uc3R5bGUub3BhY2l0eSA9IFwiMC41XCI7XG4gICAgICAgICAgICBpZiAoX3RoaXMuc2NhblR5cGVTZWxlY3Rvci5oYXNNb3JlVGhhbk9uZVNjYW5UeXBlKCkpIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5zaG93SGlkZVNjYW5UeXBlU3dhcExpbmsoZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJHRoaXMucmVzZXRIZWFkZXJNZXNzYWdlKCk7XG4gICAgICAgICAgICB2YXIgY2FtZXJhSWQgPSBjYW1lcmFTZWxlY3RVaS5nZXRWYWx1ZSgpO1xuICAgICAgICAgICAgJHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuc2V0TGFzdFVzZWRDYW1lcmFJZChjYW1lcmFJZCk7XG4gICAgICAgICAgICAkdGhpcy5odG1sNVFyY29kZS5zdGFydChjYW1lcmFJZCwgdG9IdG1sNVFyY29kZUNhbWVyYVNjYW5Db25maWcoJHRoaXMuY29uZmlnKSwgJHRoaXMucXJDb2RlU3VjY2Vzc0NhbGxiYWNrLCAkdGhpcy5xckNvZGVFcnJvckNhbGxiYWNrKVxuICAgICAgICAgICAgICAgIC50aGVuKGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RvcEJ1dHRvbi5kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0b3BCdXR0b24uc3R5bGUuZGlzcGxheSA9IFwiaW5saW5lLWJsb2NrXCI7XG4gICAgICAgICAgICAgICAgcmVzZXRDYW1lcmFBY3Rpb25TdGFydEJ1dHRvbihmYWxzZSk7XG4gICAgICAgICAgICAgICAgdmFyIGNhbWVyYUNhcGFiaWxpdGllcyA9ICR0aGlzLmh0bWw1UXJjb2RlLmdldFJ1bm5pbmdUcmFja0NhbWVyYUNhcGFiaWxpdGllcygpO1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5jb25maWcuc2hvd1RvcmNoQnV0dG9uSWZTdXBwb3J0ZWQgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgY3JlYXRlQW5kU2hvd1RvcmNoQnV0dG9uSWZTdXBwb3J0ZWQoY2FtZXJhQ2FwYWJpbGl0aWVzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmNvbmZpZy5zaG93Wm9vbVNsaWRlcklmU3VwcG9ydGVkID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlckNhbWVyYVpvb21VaUlmU3VwcG9ydGVkKGNhbWVyYUNhcGFiaWxpdGllcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuc2hvd0hpZGVTY2FuVHlwZVN3YXBMaW5rKHRydWUpO1xuICAgICAgICAgICAgICAgIGNhbWVyYVNlbGVjdFVpLmVuYWJsZSgpO1xuICAgICAgICAgICAgICAgIHJlc2V0Q2FtZXJhQWN0aW9uU3RhcnRCdXR0b24odHJ1ZSk7XG4gICAgICAgICAgICAgICAgJHRoaXMuc2V0SGVhZGVyTWVzc2FnZShlcnJvciwgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19XQVJOSU5HKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGNhbWVyYVNlbGVjdFVpLmhhc1NpbmdsZUl0ZW0oKSkge1xuICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24uY2xpY2soKTtcbiAgICAgICAgfVxuICAgICAgICBjYW1lcmFBY3Rpb25TdG9wQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBmdW5jdGlvbiAoXykge1xuICAgICAgICAgICAgaWYgKCEkdGhpcy5odG1sNVFyY29kZSkge1xuICAgICAgICAgICAgICAgIHRocm93IFwiaHRtbDVRcmNvZGUgbm90IGRlZmluZWRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0b3BCdXR0b24uZGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgJHRoaXMuaHRtbDVRcmNvZGUuc3RvcCgpXG4gICAgICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKF8pIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuc2NhblR5cGVTZWxlY3Rvci5oYXNNb3JlVGhhbk9uZVNjYW5UeXBlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMuc2hvd0hpZGVTY2FuVHlwZVN3YXBMaW5rKHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYW1lcmFTZWxlY3RVaS5lbmFibGUoKTtcbiAgICAgICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0b3BCdXR0b24uc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLnN0eWxlLmRpc3BsYXkgPSBcImlubGluZS1ibG9ja1wiO1xuICAgICAgICAgICAgICAgIGlmICh0b3JjaEJ1dHRvbikge1xuICAgICAgICAgICAgICAgICAgICB0b3JjaEJ1dHRvbi5yZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICB0b3JjaEJ1dHRvbi5oaWRlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbWVyYVpvb21VaS5yZW1vdmVPbkNhbWVyYVpvb21WYWx1ZUNoYW5nZUNhbGxiYWNrKCk7XG4gICAgICAgICAgICAgICAgY2FtZXJhWm9vbVVpLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAkdGhpcy5pbnNlcnRDYW1lcmFTY2FuSW1hZ2VUb1NjYW5SZWdpb24oKTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0b3BCdXR0b24uZGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAkdGhpcy5zZXRIZWFkZXJNZXNzYWdlKGVycm9yLCBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMuU1RBVFVTX1dBUk5JTkcpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoJHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuZ2V0TGFzdFVzZWRDYW1lcmFJZCgpKSB7XG4gICAgICAgICAgICB2YXIgY2FtZXJhSWQgPSAkdGhpcy5wZXJzaXN0ZWREYXRhTWFuYWdlci5nZXRMYXN0VXNlZENhbWVyYUlkKCk7XG4gICAgICAgICAgICBpZiAoY2FtZXJhU2VsZWN0VWkuaGFzVmFsdWUoY2FtZXJhSWQpKSB7XG4gICAgICAgICAgICAgICAgY2FtZXJhU2VsZWN0VWkuc2V0VmFsdWUoY2FtZXJhSWQpO1xuICAgICAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLmNsaWNrKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5wZXJzaXN0ZWREYXRhTWFuYWdlci5yZXNldExhc3RVc2VkQ2FtZXJhSWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5jcmVhdGVTZWN0aW9uU3dhcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgdmFyIFRFWFRfSUZfQ0FNRVJBX1NDQU5fU0VMRUNURUQgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRleHRJZkNhbWVyYVNjYW5TZWxlY3RlZCgpO1xuICAgICAgICB2YXIgVEVYVF9JRl9GSUxFX1NDQU5fU0VMRUNURUQgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRleHRJZkZpbGVTY2FuU2VsZWN0ZWQoKTtcbiAgICAgICAgdmFyIHNlY3Rpb24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmdldERhc2hib2FyZFNlY3Rpb25JZCgpKTtcbiAgICAgICAgdmFyIHN3aXRjaENvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHN3aXRjaENvbnRhaW5lci5zdHlsZS50ZXh0QWxpZ24gPSBcImNlbnRlclwiO1xuICAgICAgICB2YXIgc3dpdGNoU2NhblR5cGVMaW5rID0gQmFzZVVpRWxlbWVudEZhY3RvcnkuY3JlYXRlRWxlbWVudChcInNwYW5cIiwgdGhpcy5nZXREYXNoYm9hcmRTZWN0aW9uU3dhcExpbmtJZCgpKTtcbiAgICAgICAgc3dpdGNoU2NhblR5cGVMaW5rLnN0eWxlLnRleHREZWNvcmF0aW9uID0gXCJ1bmRlcmxpbmVcIjtcbiAgICAgICAgc3dpdGNoU2NhblR5cGVMaW5rLnN0eWxlLmN1cnNvciA9IFwicG9pbnRlclwiO1xuICAgICAgICBzd2l0Y2hTY2FuVHlwZUxpbmsuaW5uZXJUZXh0XG4gICAgICAgICAgICA9IFNjYW5UeXBlU2VsZWN0b3IuaXNDYW1lcmFTY2FuVHlwZSh0aGlzLmN1cnJlbnRTY2FuVHlwZSlcbiAgICAgICAgICAgICAgICA/IFRFWFRfSUZfQ0FNRVJBX1NDQU5fU0VMRUNURUQgOiBURVhUX0lGX0ZJTEVfU0NBTl9TRUxFQ1RFRDtcbiAgICAgICAgc3dpdGNoU2NhblR5cGVMaW5rLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoISR0aGlzLnNlY3Rpb25Td2FwQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIGlmICgkdGhpcy52ZXJib3NlKSB7XG4gICAgICAgICAgICAgICAgICAgICR0aGlzLmxvZ2dlci5sb2dFcnJvcihcIlNlY3Rpb24gc3dhcCBjYWxsZWQgd2hlbiBub3QgYWxsb3dlZFwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJHRoaXMucmVzZXRIZWFkZXJNZXNzYWdlKCk7XG4gICAgICAgICAgICAkdGhpcy5maWxlU2VsZWN0aW9uVWkucmVzZXRWYWx1ZSgpO1xuICAgICAgICAgICAgJHRoaXMuc2VjdGlvblN3YXBBbGxvd2VkID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAoU2NhblR5cGVTZWxlY3Rvci5pc0NhbWVyYVNjYW5UeXBlKCR0aGlzLmN1cnJlbnRTY2FuVHlwZSkpIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5jbGVhclNjYW5SZWdpb24oKTtcbiAgICAgICAgICAgICAgICAkdGhpcy5nZXRDYW1lcmFTY2FuUmVnaW9uKCkuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICAgICAgICAgICR0aGlzLmZpbGVTZWxlY3Rpb25VaS5zaG93KCk7XG4gICAgICAgICAgICAgICAgc3dpdGNoU2NhblR5cGVMaW5rLmlubmVyVGV4dCA9IFRFWFRfSUZfRklMRV9TQ0FOX1NFTEVDVEVEO1xuICAgICAgICAgICAgICAgICR0aGlzLmN1cnJlbnRTY2FuVHlwZSA9IEh0bWw1UXJjb2RlU2NhblR5cGUuU0NBTl9UWVBFX0ZJTEU7XG4gICAgICAgICAgICAgICAgJHRoaXMuaW5zZXJ0RmlsZVNjYW5JbWFnZVRvU2NhblJlZ2lvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuY2xlYXJTY2FuUmVnaW9uKCk7XG4gICAgICAgICAgICAgICAgJHRoaXMuZ2V0Q2FtZXJhU2NhblJlZ2lvbigpLnN0eWxlLmRpc3BsYXkgPSBcImJsb2NrXCI7XG4gICAgICAgICAgICAgICAgJHRoaXMuZmlsZVNlbGVjdGlvblVpLmhpZGUoKTtcbiAgICAgICAgICAgICAgICBzd2l0Y2hTY2FuVHlwZUxpbmsuaW5uZXJUZXh0ID0gVEVYVF9JRl9DQU1FUkFfU0NBTl9TRUxFQ1RFRDtcbiAgICAgICAgICAgICAgICAkdGhpcy5jdXJyZW50U2NhblR5cGUgPSBIdG1sNVFyY29kZVNjYW5UeXBlLlNDQU5fVFlQRV9DQU1FUkE7XG4gICAgICAgICAgICAgICAgJHRoaXMuaW5zZXJ0Q2FtZXJhU2NhbkltYWdlVG9TY2FuUmVnaW9uKCk7XG4gICAgICAgICAgICAgICAgJHRoaXMuc3RhcnRDYW1lcmFTY2FuSWZQZXJtaXNzaW9uRXhpc3RzT25Td2FwKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkdGhpcy5zZWN0aW9uU3dhcEFsbG93ZWQgPSB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgICAgc3dpdGNoQ29udGFpbmVyLmFwcGVuZENoaWxkKHN3aXRjaFNjYW5UeXBlTGluayk7XG4gICAgICAgIHNlY3Rpb24uYXBwZW5kQ2hpbGQoc3dpdGNoQ29udGFpbmVyKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuc3RhcnRDYW1lcmFTY2FuSWZQZXJtaXNzaW9uRXhpc3RzT25Td2FwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICBpZiAodGhpcy5wZXJzaXN0ZWREYXRhTWFuYWdlci5oYXNDYW1lcmFQZXJtaXNzaW9ucygpKSB7XG4gICAgICAgICAgICBDYW1lcmFQZXJtaXNzaW9ucy5oYXNQZXJtaXNzaW9ucygpLnRoZW4oZnVuY3Rpb24gKGhhc1Blcm1pc3Npb25zKSB7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1Blcm1pc3Npb25zKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwZXJtaXNzaW9uQnV0dG9uID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJHRoaXMuZ2V0Q2FtZXJhUGVybWlzc2lvbkJ1dHRvbklkKCkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXBlcm1pc3Npb25CdXR0b24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmxvZ2dlci5sb2dFcnJvcihcIlBlcm1pc3Npb24gYnV0dG9uIG5vdCBmb3VuZCwgZmFpbDtcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBcIlBlcm1pc3Npb24gYnV0dG9uIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHBlcm1pc3Npb25CdXR0b24uY2xpY2soKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICR0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLnNldEhhc1Blcm1pc3Npb24oZmFsc2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICAgICAgJHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuc2V0SGFzUGVybWlzc2lvbihmYWxzZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5yZXNldEhlYWRlck1lc3NhZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBtZXNzYWdlRGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5nZXRIZWFkZXJNZXNzYWdlQ29udGFpbmVySWQoKSk7XG4gICAgICAgIG1lc3NhZ2VEaXYuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5zZXRIZWFkZXJNZXNzYWdlID0gZnVuY3Rpb24gKG1lc3NhZ2VUZXh0LCBzY2FubmVyU3RhdHVzKSB7XG4gICAgICAgIGlmICghc2Nhbm5lclN0YXR1cykge1xuICAgICAgICAgICAgc2Nhbm5lclN0YXR1cyA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cy5TVEFUVVNfREVGQVVMVDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbWVzc2FnZURpdiA9IHRoaXMuZ2V0SGVhZGVyTWVzc2FnZURpdigpO1xuICAgICAgICBtZXNzYWdlRGl2LmlubmVyVGV4dCA9IG1lc3NhZ2VUZXh0O1xuICAgICAgICBtZXNzYWdlRGl2LnN0eWxlLmRpc3BsYXkgPSBcImJsb2NrXCI7XG4gICAgICAgIHN3aXRjaCAoc2Nhbm5lclN0YXR1cykge1xuICAgICAgICAgICAgY2FzZSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMuU1RBVFVTX1NVQ0NFU1M6XG4gICAgICAgICAgICAgICAgbWVzc2FnZURpdi5zdHlsZS5iYWNrZ3JvdW5kID0gXCJyZ2JhKDEwNiwgMTc1LCA4MCwgMC4yNilcIjtcbiAgICAgICAgICAgICAgICBtZXNzYWdlRGl2LnN0eWxlLmNvbG9yID0gXCIjNDc3NzM1XCI7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cy5TVEFUVVNfV0FSTklORzpcbiAgICAgICAgICAgICAgICBtZXNzYWdlRGl2LnN0eWxlLmJhY2tncm91bmQgPSBcInJnYmEoMjAzLCAzNiwgNDksIDAuMTQpXCI7XG4gICAgICAgICAgICAgICAgbWVzc2FnZURpdi5zdHlsZS5jb2xvciA9IFwiI2NiMjQzMVwiO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMuU1RBVFVTX0RFRkFVTFQ6XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIG1lc3NhZ2VEaXYuc3R5bGUuYmFja2dyb3VuZCA9IFwicmdiYSgwLCAwLCAwLCAwKVwiO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2VEaXYuc3R5bGUuY29sb3IgPSBcInJnYigxNywgMTcsIDE3KVwiO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLnNob3dIaWRlU2NhblR5cGVTd2FwTGluayA9IGZ1bmN0aW9uIChzaG91bGREaXNwbGF5KSB7XG4gICAgICAgIGlmICh0aGlzLnNjYW5UeXBlU2VsZWN0b3IuaGFzTW9yZVRoYW5PbmVTY2FuVHlwZSgpKSB7XG4gICAgICAgICAgICBpZiAoc2hvdWxkRGlzcGxheSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIHNob3VsZERpc3BsYXkgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc2VjdGlvblN3YXBBbGxvd2VkID0gc2hvdWxkRGlzcGxheTtcbiAgICAgICAgICAgIHRoaXMuZ2V0RGFzaGJvYXJkU2VjdGlvblN3YXBMaW5rKCkuc3R5bGUuZGlzcGxheVxuICAgICAgICAgICAgICAgID0gc2hvdWxkRGlzcGxheSA/IFwiaW5saW5lLWJsb2NrXCIgOiBcIm5vbmVcIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5pbnNlcnRDYW1lcmFTY2FuSW1hZ2VUb1NjYW5SZWdpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBxckNvZGVTY2FuUmVnaW9uID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5nZXRTY2FuUmVnaW9uSWQoKSk7XG4gICAgICAgIGlmICh0aGlzLmNhbWVyYVNjYW5JbWFnZSkge1xuICAgICAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5pbm5lckhUTUwgPSBcIjxicj5cIjtcbiAgICAgICAgICAgIHFyQ29kZVNjYW5SZWdpb24uYXBwZW5kQ2hpbGQodGhpcy5jYW1lcmFTY2FuSW1hZ2UpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2FtZXJhU2NhbkltYWdlID0gbmV3IEltYWdlO1xuICAgICAgICB0aGlzLmNhbWVyYVNjYW5JbWFnZS5vbmxvYWQgPSBmdW5jdGlvbiAoXykge1xuICAgICAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5pbm5lckhUTUwgPSBcIjxicj5cIjtcbiAgICAgICAgICAgIHFyQ29kZVNjYW5SZWdpb24uYXBwZW5kQ2hpbGQoJHRoaXMuY2FtZXJhU2NhbkltYWdlKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5jYW1lcmFTY2FuSW1hZ2Uud2lkdGggPSA2NDtcbiAgICAgICAgdGhpcy5jYW1lcmFTY2FuSW1hZ2Uuc3R5bGUub3BhY2l0eSA9IFwiMC44XCI7XG4gICAgICAgIHRoaXMuY2FtZXJhU2NhbkltYWdlLnNyYyA9IEFTU0VUX0NBTUVSQV9TQ0FOO1xuICAgICAgICB0aGlzLmNhbWVyYVNjYW5JbWFnZS5hbHQgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmNhbWVyYVNjYW5BbHRUZXh0KCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmluc2VydEZpbGVTY2FuSW1hZ2VUb1NjYW5SZWdpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBxckNvZGVTY2FuUmVnaW9uID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5nZXRTY2FuUmVnaW9uSWQoKSk7XG4gICAgICAgIGlmICh0aGlzLmZpbGVTY2FuSW1hZ2UpIHtcbiAgICAgICAgICAgIHFyQ29kZVNjYW5SZWdpb24uaW5uZXJIVE1MID0gXCI8YnI+XCI7XG4gICAgICAgICAgICBxckNvZGVTY2FuUmVnaW9uLmFwcGVuZENoaWxkKHRoaXMuZmlsZVNjYW5JbWFnZSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5maWxlU2NhbkltYWdlID0gbmV3IEltYWdlO1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW1hZ2Uub25sb2FkID0gZnVuY3Rpb24gKF8pIHtcbiAgICAgICAgICAgIHFyQ29kZVNjYW5SZWdpb24uaW5uZXJIVE1MID0gXCI8YnI+XCI7XG4gICAgICAgICAgICBxckNvZGVTY2FuUmVnaW9uLmFwcGVuZENoaWxkKCR0aGlzLmZpbGVTY2FuSW1hZ2UpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW1hZ2Uud2lkdGggPSA2NDtcbiAgICAgICAgdGhpcy5maWxlU2NhbkltYWdlLnN0eWxlLm9wYWNpdHkgPSBcIjAuOFwiO1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW1hZ2Uuc3JjID0gQVNTRVRfRklMRV9TQ0FOO1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW1hZ2UuYWx0ID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5maWxlU2NhbkFsdFRleHQoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuY2xlYXJTY2FuUmVnaW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcXJDb2RlU2NhblJlZ2lvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZ2V0U2NhblJlZ2lvbklkKCkpO1xuICAgICAgICBxckNvZGVTY2FuUmVnaW9uLmlubmVySFRNTCA9IFwiXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmdldERhc2hib2FyZFNlY3Rpb25JZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiXCIuY29uY2F0KHRoaXMuZWxlbWVudElkLCBcIl9fZGFzaGJvYXJkX3NlY3Rpb25cIik7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmdldERhc2hib2FyZFNlY3Rpb25DYW1lcmFTY2FuUmVnaW9uSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlwiLmNvbmNhdCh0aGlzLmVsZW1lbnRJZCwgXCJfX2Rhc2hib2FyZF9zZWN0aW9uX2NzclwiKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuZ2V0RGFzaGJvYXJkU2VjdGlvblN3YXBMaW5rSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuU0NBTl9UWVBFX0NIQU5HRV9BTkNIT1JfSUQ7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmdldFNjYW5SZWdpb25JZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiXCIuY29uY2F0KHRoaXMuZWxlbWVudElkLCBcIl9fc2Nhbl9yZWdpb25cIik7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmdldERhc2hib2FyZElkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJcIi5jb25jYXQodGhpcy5lbGVtZW50SWQsIFwiX19kYXNoYm9hcmRcIik7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmdldEhlYWRlck1lc3NhZ2VDb250YWluZXJJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiXCIuY29uY2F0KHRoaXMuZWxlbWVudElkLCBcIl9faGVhZGVyX21lc3NhZ2VcIik7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmdldENhbWVyYVBlcm1pc3Npb25CdXR0b25JZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5DQU1FUkFfUEVSTUlTU0lPTl9CVVRUT05fSUQ7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmdldENhbWVyYVNjYW5SZWdpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmdldERhc2hib2FyZFNlY3Rpb25DYW1lcmFTY2FuUmVnaW9uSWQoKSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmdldERhc2hib2FyZFNlY3Rpb25Td2FwTGluayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZ2V0RGFzaGJvYXJkU2VjdGlvblN3YXBMaW5rSWQoKSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmdldEhlYWRlck1lc3NhZ2VEaXYgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmdldEhlYWRlck1lc3NhZ2VDb250YWluZXJJZCgpKTtcbiAgICB9O1xuICAgIHJldHVybiBIdG1sNVFyY29kZVNjYW5uZXI7XG59KCkpO1xuZXhwb3J0IHsgSHRtbDVRcmNvZGVTY2FubmVyIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1odG1sNS1xcmNvZGUtc2Nhbm5lci5qcy5tYXAiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/html5-qrcode-scanner.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/html5-qrcode.js":
+/*!*******************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/html5-qrcode.js ***!
+  \*******************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   Html5Qrcode: () => (/* binding */ Html5Qrcode)\n/* harmony export */ });\n/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core */ \"./node_modules/html5-qrcode/esm/core.js\");\n/* harmony import */ var _strings__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./strings */ \"./node_modules/html5-qrcode/esm/strings.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ \"./node_modules/html5-qrcode/esm/utils.js\");\n/* harmony import */ var _code_decoder__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./code-decoder */ \"./node_modules/html5-qrcode/esm/code-decoder.js\");\n/* harmony import */ var _camera_factories__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./camera/factories */ \"./node_modules/html5-qrcode/esm/camera/factories.js\");\n/* harmony import */ var _camera_retriever__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./camera/retriever */ \"./node_modules/html5-qrcode/esm/camera/retriever.js\");\n/* harmony import */ var _state_manager__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./state-manager */ \"./node_modules/html5-qrcode/esm/state-manager.js\");\nvar __extends = (undefined && undefined.__extends) || (function () {\n    var extendStatics = function (d, b) {\n        extendStatics = Object.setPrototypeOf ||\n            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n        return extendStatics(d, b);\n    };\n    return function (d, b) {\n        if (typeof b !== \"function\" && b !== null)\n            throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\n        extendStatics(d, b);\n        function __() { this.constructor = d; }\n        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n    };\n})();\n\n\n\n\n\n\n\nvar Constants = (function (_super) {\n    __extends(Constants, _super);\n    function Constants() {\n        return _super !== null && _super.apply(this, arguments) || this;\n    }\n    Constants.DEFAULT_WIDTH = 300;\n    Constants.DEFAULT_WIDTH_OFFSET = 2;\n    Constants.FILE_SCAN_MIN_HEIGHT = 300;\n    Constants.FILE_SCAN_HIDDEN_CANVAS_PADDING = 100;\n    Constants.MIN_QR_BOX_SIZE = 50;\n    Constants.SHADED_LEFT = 1;\n    Constants.SHADED_RIGHT = 2;\n    Constants.SHADED_TOP = 3;\n    Constants.SHADED_BOTTOM = 4;\n    Constants.SHADED_REGION_ELEMENT_ID = \"qr-shaded-region\";\n    Constants.VERBOSE = false;\n    Constants.BORDER_SHADER_DEFAULT_COLOR = \"#ffffff\";\n    Constants.BORDER_SHADER_MATCH_COLOR = \"rgb(90, 193, 56)\";\n    return Constants;\n}(_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeConstants));\nvar InternalHtml5QrcodeConfig = (function () {\n    function InternalHtml5QrcodeConfig(config, logger) {\n        this.logger = logger;\n        this.fps = Constants.SCAN_DEFAULT_FPS;\n        if (!config) {\n            this.disableFlip = Constants.DEFAULT_DISABLE_FLIP;\n        }\n        else {\n            if (config.fps) {\n                this.fps = config.fps;\n            }\n            this.disableFlip = config.disableFlip === true;\n            this.qrbox = config.qrbox;\n            this.aspectRatio = config.aspectRatio;\n            this.videoConstraints = config.videoConstraints;\n        }\n    }\n    InternalHtml5QrcodeConfig.prototype.isMediaStreamConstraintsValid = function () {\n        if (!this.videoConstraints) {\n            this.logger.logError(\"Empty videoConstraints\", true);\n            return false;\n        }\n        return _utils__WEBPACK_IMPORTED_MODULE_2__.VideoConstraintsUtil.isMediaStreamConstraintsValid(this.videoConstraints, this.logger);\n    };\n    InternalHtml5QrcodeConfig.prototype.isShadedBoxEnabled = function () {\n        return !(0,_core__WEBPACK_IMPORTED_MODULE_0__.isNullOrUndefined)(this.qrbox);\n    };\n    InternalHtml5QrcodeConfig.create = function (config, logger) {\n        return new InternalHtml5QrcodeConfig(config, logger);\n    };\n    return InternalHtml5QrcodeConfig;\n}());\nvar Html5Qrcode = (function () {\n    function Html5Qrcode(elementId, configOrVerbosityFlag) {\n        this.element = null;\n        this.canvasElement = null;\n        this.scannerPausedUiElement = null;\n        this.hasBorderShaders = null;\n        this.borderShaders = null;\n        this.qrMatch = null;\n        this.renderedCamera = null;\n        this.qrRegion = null;\n        this.context = null;\n        this.lastScanImageFile = null;\n        this.isScanning = false;\n        if (!document.getElementById(elementId)) {\n            throw \"HTML Element with id=\".concat(elementId, \" not found\");\n        }\n        this.elementId = elementId;\n        this.verbose = false;\n        var experimentalFeatureConfig;\n        var configObject;\n        if (typeof configOrVerbosityFlag == \"boolean\") {\n            this.verbose = configOrVerbosityFlag === true;\n        }\n        else if (configOrVerbosityFlag) {\n            configObject = configOrVerbosityFlag;\n            this.verbose = configObject.verbose === true;\n            experimentalFeatureConfig = configObject.experimentalFeatures;\n        }\n        this.logger = new _core__WEBPACK_IMPORTED_MODULE_0__.BaseLoggger(this.verbose);\n        this.qrcode = new _code_decoder__WEBPACK_IMPORTED_MODULE_3__.Html5QrcodeShim(this.getSupportedFormats(configOrVerbosityFlag), this.getUseBarCodeDetectorIfSupported(configObject), this.verbose, this.logger);\n        this.foreverScanTimeout;\n        this.shouldScan = true;\n        this.stateManagerProxy = _state_manager__WEBPACK_IMPORTED_MODULE_6__.StateManagerFactory.create();\n    }\n    Html5Qrcode.prototype.start = function (cameraIdOrConfig, configuration, qrCodeSuccessCallback, qrCodeErrorCallback) {\n        var _this = this;\n        if (!cameraIdOrConfig) {\n            throw \"cameraIdOrConfig is required\";\n        }\n        if (!qrCodeSuccessCallback\n            || typeof qrCodeSuccessCallback != \"function\") {\n            throw \"qrCodeSuccessCallback is required and should be a function.\";\n        }\n        var qrCodeErrorCallbackInternal;\n        if (qrCodeErrorCallback) {\n            qrCodeErrorCallbackInternal = qrCodeErrorCallback;\n        }\n        else {\n            qrCodeErrorCallbackInternal\n                = this.verbose ? this.logger.log : function () { };\n        }\n        var internalConfig = InternalHtml5QrcodeConfig.create(configuration, this.logger);\n        this.clearElement();\n        var videoConstraintsAvailableAndValid = false;\n        if (internalConfig.videoConstraints) {\n            if (!internalConfig.isMediaStreamConstraintsValid()) {\n                this.logger.logError(\"'videoConstraints' is not valid 'MediaStreamConstraints, \"\n                    + \"it will be ignored.'\", true);\n            }\n            else {\n                videoConstraintsAvailableAndValid = true;\n            }\n        }\n        var areVideoConstraintsEnabled = videoConstraintsAvailableAndValid;\n        var element = document.getElementById(this.elementId);\n        var rootElementWidth = element.clientWidth\n            ? element.clientWidth : Constants.DEFAULT_WIDTH;\n        element.style.position = \"relative\";\n        this.shouldScan = true;\n        this.element = element;\n        var $this = this;\n        var toScanningStateChangeTransaction = this.stateManagerProxy.startTransition(_state_manager__WEBPACK_IMPORTED_MODULE_6__.Html5QrcodeScannerState.SCANNING);\n        return new Promise(function (resolve, reject) {\n            var videoConstraints = areVideoConstraintsEnabled\n                ? internalConfig.videoConstraints\n                : $this.createVideoConstraints(cameraIdOrConfig);\n            if (!videoConstraints) {\n                toScanningStateChangeTransaction.cancel();\n                reject(\"videoConstraints should be defined\");\n                return;\n            }\n            var cameraRenderingOptions = {};\n            if (!areVideoConstraintsEnabled || internalConfig.aspectRatio) {\n                cameraRenderingOptions.aspectRatio = internalConfig.aspectRatio;\n            }\n            var renderingCallbacks = {\n                onRenderSurfaceReady: function (viewfinderWidth, viewfinderHeight) {\n                    $this.setupUi(viewfinderWidth, viewfinderHeight, internalConfig);\n                    $this.isScanning = true;\n                    $this.foreverScan(internalConfig, qrCodeSuccessCallback, qrCodeErrorCallbackInternal);\n                }\n            };\n            _camera_factories__WEBPACK_IMPORTED_MODULE_4__.CameraFactory.failIfNotSupported().then(function (factory) {\n                factory.create(videoConstraints).then(function (camera) {\n                    return camera.render(_this.element, cameraRenderingOptions, renderingCallbacks)\n                        .then(function (renderedCamera) {\n                        $this.renderedCamera = renderedCamera;\n                        toScanningStateChangeTransaction.execute();\n                        resolve(null);\n                    })\n                        .catch(function (error) {\n                        toScanningStateChangeTransaction.cancel();\n                        reject(error);\n                    });\n                }).catch(function (error) {\n                    toScanningStateChangeTransaction.cancel();\n                    reject(_strings__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeStrings.errorGettingUserMedia(error));\n                });\n            }).catch(function (_) {\n                toScanningStateChangeTransaction.cancel();\n                reject(_strings__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeStrings.cameraStreamingNotSupported());\n            });\n        });\n    };\n    Html5Qrcode.prototype.pause = function (shouldPauseVideo) {\n        if (!this.stateManagerProxy.isStrictlyScanning()) {\n            throw \"Cannot pause, scanner is not scanning.\";\n        }\n        this.stateManagerProxy.directTransition(_state_manager__WEBPACK_IMPORTED_MODULE_6__.Html5QrcodeScannerState.PAUSED);\n        this.showPausedState();\n        if ((0,_core__WEBPACK_IMPORTED_MODULE_0__.isNullOrUndefined)(shouldPauseVideo) || shouldPauseVideo !== true) {\n            shouldPauseVideo = false;\n        }\n        if (shouldPauseVideo && this.renderedCamera) {\n            this.renderedCamera.pause();\n        }\n    };\n    Html5Qrcode.prototype.resume = function () {\n        if (!this.stateManagerProxy.isPaused()) {\n            throw \"Cannot result, scanner is not paused.\";\n        }\n        if (!this.renderedCamera) {\n            throw \"renderedCamera doesn't exist while trying resume()\";\n        }\n        var $this = this;\n        var transitionToScanning = function () {\n            $this.stateManagerProxy.directTransition(_state_manager__WEBPACK_IMPORTED_MODULE_6__.Html5QrcodeScannerState.SCANNING);\n            $this.hidePausedState();\n        };\n        if (!this.renderedCamera.isPaused()) {\n            transitionToScanning();\n            return;\n        }\n        this.renderedCamera.resume(function () {\n            transitionToScanning();\n        });\n    };\n    Html5Qrcode.prototype.getState = function () {\n        return this.stateManagerProxy.getState();\n    };\n    Html5Qrcode.prototype.stop = function () {\n        var _this = this;\n        if (!this.stateManagerProxy.isScanning()) {\n            throw \"Cannot stop, scanner is not running or paused.\";\n        }\n        var toStoppedStateTransaction = this.stateManagerProxy.startTransition(_state_manager__WEBPACK_IMPORTED_MODULE_6__.Html5QrcodeScannerState.NOT_STARTED);\n        this.shouldScan = false;\n        if (this.foreverScanTimeout) {\n            clearTimeout(this.foreverScanTimeout);\n        }\n        var removeQrRegion = function () {\n            if (!_this.element) {\n                return;\n            }\n            var childElement = document.getElementById(Constants.SHADED_REGION_ELEMENT_ID);\n            if (childElement) {\n                _this.element.removeChild(childElement);\n            }\n        };\n        var $this = this;\n        return this.renderedCamera.close().then(function () {\n            $this.renderedCamera = null;\n            if ($this.element) {\n                $this.element.removeChild($this.canvasElement);\n                $this.canvasElement = null;\n            }\n            removeQrRegion();\n            if ($this.qrRegion) {\n                $this.qrRegion = null;\n            }\n            if ($this.context) {\n                $this.context = null;\n            }\n            toStoppedStateTransaction.execute();\n            $this.hidePausedState();\n            $this.isScanning = false;\n            return Promise.resolve();\n        });\n    };\n    Html5Qrcode.prototype.scanFile = function (imageFile, showImage) {\n        return this.scanFileV2(imageFile, showImage)\n            .then(function (html5qrcodeResult) { return html5qrcodeResult.decodedText; });\n    };\n    Html5Qrcode.prototype.scanFileV2 = function (imageFile, showImage) {\n        var _this = this;\n        if (!imageFile || !(imageFile instanceof File)) {\n            throw \"imageFile argument is mandatory and should be instance \"\n                + \"of File. Use 'event.target.files[0]'.\";\n        }\n        if ((0,_core__WEBPACK_IMPORTED_MODULE_0__.isNullOrUndefined)(showImage)) {\n            showImage = true;\n        }\n        if (!this.stateManagerProxy.canScanFile()) {\n            throw \"Cannot start file scan - ongoing camera scan\";\n        }\n        return new Promise(function (resolve, reject) {\n            _this.possiblyCloseLastScanImageFile();\n            _this.clearElement();\n            _this.lastScanImageFile = URL.createObjectURL(imageFile);\n            var inputImage = new Image;\n            inputImage.onload = function () {\n                var imageWidth = inputImage.width;\n                var imageHeight = inputImage.height;\n                var element = document.getElementById(_this.elementId);\n                var containerWidth = element.clientWidth\n                    ? element.clientWidth : Constants.DEFAULT_WIDTH;\n                var containerHeight = Math.max(element.clientHeight ? element.clientHeight : imageHeight, Constants.FILE_SCAN_MIN_HEIGHT);\n                var config = _this.computeCanvasDrawConfig(imageWidth, imageHeight, containerWidth, containerHeight);\n                if (showImage) {\n                    var visibleCanvas = _this.createCanvasElement(containerWidth, containerHeight, \"qr-canvas-visible\");\n                    visibleCanvas.style.display = \"inline-block\";\n                    element.appendChild(visibleCanvas);\n                    var context_1 = visibleCanvas.getContext(\"2d\");\n                    if (!context_1) {\n                        throw \"Unable to get 2d context from canvas\";\n                    }\n                    context_1.canvas.width = containerWidth;\n                    context_1.canvas.height = containerHeight;\n                    context_1.drawImage(inputImage, 0, 0, imageWidth, imageHeight, config.x, config.y, config.width, config.height);\n                }\n                var padding = Constants.FILE_SCAN_HIDDEN_CANVAS_PADDING;\n                var hiddenImageWidth = Math.max(inputImage.width, config.width);\n                var hiddenImageHeight = Math.max(inputImage.height, config.height);\n                var hiddenCanvasWidth = hiddenImageWidth + 2 * padding;\n                var hiddenCanvasHeight = hiddenImageHeight + 2 * padding;\n                var hiddenCanvas = _this.createCanvasElement(hiddenCanvasWidth, hiddenCanvasHeight);\n                element.appendChild(hiddenCanvas);\n                var context = hiddenCanvas.getContext(\"2d\");\n                if (!context) {\n                    throw \"Unable to get 2d context from canvas\";\n                }\n                context.canvas.width = hiddenCanvasWidth;\n                context.canvas.height = hiddenCanvasHeight;\n                context.drawImage(inputImage, 0, 0, imageWidth, imageHeight, padding, padding, hiddenImageWidth, hiddenImageHeight);\n                try {\n                    _this.qrcode.decodeRobustlyAsync(hiddenCanvas)\n                        .then(function (result) {\n                        resolve(_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeResultFactory.createFromQrcodeResult(result));\n                    })\n                        .catch(reject);\n                }\n                catch (exception) {\n                    reject(\"QR code parse error, error = \".concat(exception));\n                }\n            };\n            inputImage.onerror = reject;\n            inputImage.onabort = reject;\n            inputImage.onstalled = reject;\n            inputImage.onsuspend = reject;\n            inputImage.src = URL.createObjectURL(imageFile);\n        });\n    };\n    Html5Qrcode.prototype.clear = function () {\n        this.clearElement();\n    };\n    Html5Qrcode.getCameras = function () {\n        return _camera_retriever__WEBPACK_IMPORTED_MODULE_5__.CameraRetriever.retrieve();\n    };\n    Html5Qrcode.prototype.getRunningTrackCapabilities = function () {\n        return this.getRenderedCameraOrFail().getRunningTrackCapabilities();\n    };\n    Html5Qrcode.prototype.getRunningTrackSettings = function () {\n        return this.getRenderedCameraOrFail().getRunningTrackSettings();\n    };\n    Html5Qrcode.prototype.getRunningTrackCameraCapabilities = function () {\n        return this.getRenderedCameraOrFail().getCapabilities();\n    };\n    Html5Qrcode.prototype.applyVideoConstraints = function (videoConstaints) {\n        if (!videoConstaints) {\n            throw \"videoConstaints is required argument.\";\n        }\n        else if (!_utils__WEBPACK_IMPORTED_MODULE_2__.VideoConstraintsUtil.isMediaStreamConstraintsValid(videoConstaints, this.logger)) {\n            throw \"invalid videoConstaints passed, check logs for more details\";\n        }\n        return this.getRenderedCameraOrFail().applyVideoConstraints(videoConstaints);\n    };\n    Html5Qrcode.prototype.getRenderedCameraOrFail = function () {\n        if (this.renderedCamera == null) {\n            throw \"Scanning is not in running state, call this API only when\"\n                + \" QR code scanning using camera is in running state.\";\n        }\n        return this.renderedCamera;\n    };\n    Html5Qrcode.prototype.getSupportedFormats = function (configOrVerbosityFlag) {\n        var allFormats = [\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.QR_CODE,\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.AZTEC,\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.CODABAR,\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.CODE_39,\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.CODE_93,\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.CODE_128,\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.DATA_MATRIX,\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.MAXICODE,\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.ITF,\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.EAN_13,\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.EAN_8,\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.PDF_417,\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.RSS_14,\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.RSS_EXPANDED,\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.UPC_A,\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.UPC_E,\n            _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.UPC_EAN_EXTENSION,\n        ];\n        if (!configOrVerbosityFlag\n            || typeof configOrVerbosityFlag == \"boolean\") {\n            return allFormats;\n        }\n        if (!configOrVerbosityFlag.formatsToSupport) {\n            return allFormats;\n        }\n        if (!Array.isArray(configOrVerbosityFlag.formatsToSupport)) {\n            throw \"configOrVerbosityFlag.formatsToSupport should be undefined \"\n                + \"or an array.\";\n        }\n        if (configOrVerbosityFlag.formatsToSupport.length === 0) {\n            throw \"Atleast 1 formatsToSupport is needed.\";\n        }\n        var supportedFormats = [];\n        for (var _i = 0, _a = configOrVerbosityFlag.formatsToSupport; _i < _a.length; _i++) {\n            var format = _a[_i];\n            if ((0,_core__WEBPACK_IMPORTED_MODULE_0__.isValidHtml5QrcodeSupportedFormats)(format)) {\n                supportedFormats.push(format);\n            }\n            else {\n                this.logger.warn(\"Invalid format: \".concat(format, \" passed in config, ignoring.\"));\n            }\n        }\n        if (supportedFormats.length === 0) {\n            throw \"None of formatsToSupport match supported values.\";\n        }\n        return supportedFormats;\n    };\n    Html5Qrcode.prototype.getUseBarCodeDetectorIfSupported = function (config) {\n        if ((0,_core__WEBPACK_IMPORTED_MODULE_0__.isNullOrUndefined)(config)) {\n            return true;\n        }\n        if (!(0,_core__WEBPACK_IMPORTED_MODULE_0__.isNullOrUndefined)(config.useBarCodeDetectorIfSupported)) {\n            return config.useBarCodeDetectorIfSupported !== false;\n        }\n        if ((0,_core__WEBPACK_IMPORTED_MODULE_0__.isNullOrUndefined)(config.experimentalFeatures)) {\n            return true;\n        }\n        var experimentalFeatures = config.experimentalFeatures;\n        if ((0,_core__WEBPACK_IMPORTED_MODULE_0__.isNullOrUndefined)(experimentalFeatures.useBarCodeDetectorIfSupported)) {\n            return true;\n        }\n        return experimentalFeatures.useBarCodeDetectorIfSupported !== false;\n    };\n    Html5Qrcode.prototype.validateQrboxSize = function (viewfinderWidth, viewfinderHeight, internalConfig) {\n        var _this = this;\n        var qrboxSize = internalConfig.qrbox;\n        this.validateQrboxConfig(qrboxSize);\n        var qrDimensions = this.toQrdimensions(viewfinderWidth, viewfinderHeight, qrboxSize);\n        var validateMinSize = function (size) {\n            if (size < Constants.MIN_QR_BOX_SIZE) {\n                throw \"minimum size of 'config.qrbox' dimension value is\"\n                    + \" \".concat(Constants.MIN_QR_BOX_SIZE, \"px.\");\n            }\n        };\n        var correctWidthBasedOnRootElementSize = function (configWidth) {\n            if (configWidth > viewfinderWidth) {\n                _this.logger.warn(\"`qrbox.width` or `qrbox` is larger than the\"\n                    + \" width of the root element. The width will be truncated\"\n                    + \" to the width of root element.\");\n                configWidth = viewfinderWidth;\n            }\n            return configWidth;\n        };\n        validateMinSize(qrDimensions.width);\n        validateMinSize(qrDimensions.height);\n        qrDimensions.width = correctWidthBasedOnRootElementSize(qrDimensions.width);\n    };\n    Html5Qrcode.prototype.validateQrboxConfig = function (qrboxSize) {\n        if (typeof qrboxSize === \"number\") {\n            return;\n        }\n        if (typeof qrboxSize === \"function\") {\n            return;\n        }\n        if (qrboxSize.width === undefined || qrboxSize.height === undefined) {\n            throw \"Invalid instance of QrDimensions passed for \"\n                + \"'config.qrbox'. Both 'width' and 'height' should be set.\";\n        }\n    };\n    Html5Qrcode.prototype.toQrdimensions = function (viewfinderWidth, viewfinderHeight, qrboxSize) {\n        if (typeof qrboxSize === \"number\") {\n            return { width: qrboxSize, height: qrboxSize };\n        }\n        else if (typeof qrboxSize === \"function\") {\n            try {\n                return qrboxSize(viewfinderWidth, viewfinderHeight);\n            }\n            catch (error) {\n                throw new Error(\"qrbox config was passed as a function but it failed with \"\n                    + \"unknown error\" + error);\n            }\n        }\n        return qrboxSize;\n    };\n    Html5Qrcode.prototype.setupUi = function (viewfinderWidth, viewfinderHeight, internalConfig) {\n        if (internalConfig.isShadedBoxEnabled()) {\n            this.validateQrboxSize(viewfinderWidth, viewfinderHeight, internalConfig);\n        }\n        var qrboxSize = (0,_core__WEBPACK_IMPORTED_MODULE_0__.isNullOrUndefined)(internalConfig.qrbox) ?\n            { width: viewfinderWidth, height: viewfinderHeight } : internalConfig.qrbox;\n        this.validateQrboxConfig(qrboxSize);\n        var qrDimensions = this.toQrdimensions(viewfinderWidth, viewfinderHeight, qrboxSize);\n        if (qrDimensions.height > viewfinderHeight) {\n            this.logger.warn(\"[Html5Qrcode] config.qrbox has height that is\"\n                + \"greater than the height of the video stream. Shading will be\"\n                + \" ignored\");\n        }\n        var shouldShadingBeApplied = internalConfig.isShadedBoxEnabled()\n            && qrDimensions.height <= viewfinderHeight;\n        var defaultQrRegion = {\n            x: 0,\n            y: 0,\n            width: viewfinderWidth,\n            height: viewfinderHeight\n        };\n        var qrRegion = shouldShadingBeApplied\n            ? this.getShadedRegionBounds(viewfinderWidth, viewfinderHeight, qrDimensions)\n            : defaultQrRegion;\n        var canvasElement = this.createCanvasElement(qrRegion.width, qrRegion.height);\n        var contextAttributes = { willReadFrequently: true };\n        var context = canvasElement.getContext(\"2d\", contextAttributes);\n        context.canvas.width = qrRegion.width;\n        context.canvas.height = qrRegion.height;\n        this.element.append(canvasElement);\n        if (shouldShadingBeApplied) {\n            this.possiblyInsertShadingElement(this.element, viewfinderWidth, viewfinderHeight, qrDimensions);\n        }\n        this.createScannerPausedUiElement(this.element);\n        this.qrRegion = qrRegion;\n        this.context = context;\n        this.canvasElement = canvasElement;\n    };\n    Html5Qrcode.prototype.createScannerPausedUiElement = function (rootElement) {\n        var scannerPausedUiElement = document.createElement(\"div\");\n        scannerPausedUiElement.innerText = _strings__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeStrings.scannerPaused();\n        scannerPausedUiElement.style.display = \"none\";\n        scannerPausedUiElement.style.position = \"absolute\";\n        scannerPausedUiElement.style.top = \"0px\";\n        scannerPausedUiElement.style.zIndex = \"1\";\n        scannerPausedUiElement.style.background = \"rgba(9, 9, 9, 0.46)\";\n        scannerPausedUiElement.style.color = \"#FFECEC\";\n        scannerPausedUiElement.style.textAlign = \"center\";\n        scannerPausedUiElement.style.width = \"100%\";\n        rootElement.appendChild(scannerPausedUiElement);\n        this.scannerPausedUiElement = scannerPausedUiElement;\n    };\n    Html5Qrcode.prototype.scanContext = function (qrCodeSuccessCallback, qrCodeErrorCallback) {\n        var _this = this;\n        if (this.stateManagerProxy.isPaused()) {\n            return Promise.resolve(false);\n        }\n        return this.qrcode.decodeAsync(this.canvasElement)\n            .then(function (result) {\n            qrCodeSuccessCallback(result.text, _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeResultFactory.createFromQrcodeResult(result));\n            _this.possiblyUpdateShaders(true);\n            return true;\n        }).catch(function (error) {\n            _this.possiblyUpdateShaders(false);\n            var errorMessage = _strings__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeStrings.codeParseError(error);\n            qrCodeErrorCallback(errorMessage, _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeErrorFactory.createFrom(errorMessage));\n            return false;\n        });\n    };\n    Html5Qrcode.prototype.foreverScan = function (internalConfig, qrCodeSuccessCallback, qrCodeErrorCallback) {\n        var _this = this;\n        if (!this.shouldScan) {\n            return;\n        }\n        if (!this.renderedCamera) {\n            return;\n        }\n        var videoElement = this.renderedCamera.getSurface();\n        var widthRatio = videoElement.videoWidth / videoElement.clientWidth;\n        var heightRatio = videoElement.videoHeight / videoElement.clientHeight;\n        if (!this.qrRegion) {\n            throw \"qrRegion undefined when localMediaStream is ready.\";\n        }\n        var sWidthOffset = this.qrRegion.width * widthRatio;\n        var sHeightOffset = this.qrRegion.height * heightRatio;\n        var sxOffset = this.qrRegion.x * widthRatio;\n        var syOffset = this.qrRegion.y * heightRatio;\n        this.context.drawImage(videoElement, sxOffset, syOffset, sWidthOffset, sHeightOffset, 0, 0, this.qrRegion.width, this.qrRegion.height);\n        var triggerNextScan = function () {\n            _this.foreverScanTimeout = setTimeout(function () {\n                _this.foreverScan(internalConfig, qrCodeSuccessCallback, qrCodeErrorCallback);\n            }, _this.getTimeoutFps(internalConfig.fps));\n        };\n        this.scanContext(qrCodeSuccessCallback, qrCodeErrorCallback)\n            .then(function (isSuccessfull) {\n            if (!isSuccessfull && internalConfig.disableFlip !== true) {\n                _this.context.translate(_this.context.canvas.width, 0);\n                _this.context.scale(-1, 1);\n                _this.scanContext(qrCodeSuccessCallback, qrCodeErrorCallback)\n                    .finally(function () {\n                    triggerNextScan();\n                });\n            }\n            else {\n                triggerNextScan();\n            }\n        }).catch(function (error) {\n            _this.logger.logError(\"Error happend while scanning context\", error);\n            triggerNextScan();\n        });\n    };\n    Html5Qrcode.prototype.createVideoConstraints = function (cameraIdOrConfig) {\n        if (typeof cameraIdOrConfig == \"string\") {\n            return { deviceId: { exact: cameraIdOrConfig } };\n        }\n        else if (typeof cameraIdOrConfig == \"object\") {\n            var facingModeKey = \"facingMode\";\n            var deviceIdKey = \"deviceId\";\n            var allowedFacingModeValues_1 = { \"user\": true, \"environment\": true };\n            var exactKey = \"exact\";\n            var isValidFacingModeValue = function (value) {\n                if (value in allowedFacingModeValues_1) {\n                    return true;\n                }\n                else {\n                    throw \"config has invalid 'facingMode' value = \"\n                        + \"'\".concat(value, \"'\");\n                }\n            };\n            var keys = Object.keys(cameraIdOrConfig);\n            if (keys.length !== 1) {\n                throw \"'cameraIdOrConfig' object should have exactly 1 key,\"\n                    + \" if passed as an object, found \".concat(keys.length, \" keys\");\n            }\n            var key = Object.keys(cameraIdOrConfig)[0];\n            if (key !== facingModeKey && key !== deviceIdKey) {\n                throw \"Only '\".concat(facingModeKey, \"' and '\").concat(deviceIdKey, \"' \")\n                    + \" are supported for 'cameraIdOrConfig'\";\n            }\n            if (key === facingModeKey) {\n                var facingMode = cameraIdOrConfig.facingMode;\n                if (typeof facingMode == \"string\") {\n                    if (isValidFacingModeValue(facingMode)) {\n                        return { facingMode: facingMode };\n                    }\n                }\n                else if (typeof facingMode == \"object\") {\n                    if (exactKey in facingMode) {\n                        if (isValidFacingModeValue(facingMode[\"\".concat(exactKey)])) {\n                            return {\n                                facingMode: {\n                                    exact: facingMode[\"\".concat(exactKey)]\n                                }\n                            };\n                        }\n                    }\n                    else {\n                        throw \"'facingMode' should be string or object with\"\n                            + \" \".concat(exactKey, \" as key.\");\n                    }\n                }\n                else {\n                    var type_1 = (typeof facingMode);\n                    throw \"Invalid type of 'facingMode' = \".concat(type_1);\n                }\n            }\n            else {\n                var deviceId = cameraIdOrConfig.deviceId;\n                if (typeof deviceId == \"string\") {\n                    return { deviceId: deviceId };\n                }\n                else if (typeof deviceId == \"object\") {\n                    if (exactKey in deviceId) {\n                        return {\n                            deviceId: { exact: deviceId[\"\".concat(exactKey)] }\n                        };\n                    }\n                    else {\n                        throw \"'deviceId' should be string or object with\"\n                            + \" \".concat(exactKey, \" as key.\");\n                    }\n                }\n                else {\n                    var type_2 = (typeof deviceId);\n                    throw \"Invalid type of 'deviceId' = \".concat(type_2);\n                }\n            }\n        }\n        var type = (typeof cameraIdOrConfig);\n        throw \"Invalid type of 'cameraIdOrConfig' = \".concat(type);\n    };\n    Html5Qrcode.prototype.computeCanvasDrawConfig = function (imageWidth, imageHeight, containerWidth, containerHeight) {\n        if (imageWidth <= containerWidth\n            && imageHeight <= containerHeight) {\n            var xoffset = (containerWidth - imageWidth) / 2;\n            var yoffset = (containerHeight - imageHeight) / 2;\n            return {\n                x: xoffset,\n                y: yoffset,\n                width: imageWidth,\n                height: imageHeight\n            };\n        }\n        else {\n            var formerImageWidth = imageWidth;\n            var formerImageHeight = imageHeight;\n            if (imageWidth > containerWidth) {\n                imageHeight = (containerWidth / imageWidth) * imageHeight;\n                imageWidth = containerWidth;\n            }\n            if (imageHeight > containerHeight) {\n                imageWidth = (containerHeight / imageHeight) * imageWidth;\n                imageHeight = containerHeight;\n            }\n            this.logger.log(\"Image downsampled from \"\n                + \"\".concat(formerImageWidth, \"X\").concat(formerImageHeight)\n                + \" to \".concat(imageWidth, \"X\").concat(imageHeight, \".\"));\n            return this.computeCanvasDrawConfig(imageWidth, imageHeight, containerWidth, containerHeight);\n        }\n    };\n    Html5Qrcode.prototype.clearElement = function () {\n        if (this.stateManagerProxy.isScanning()) {\n            throw \"Cannot clear while scan is ongoing, close it first.\";\n        }\n        var element = document.getElementById(this.elementId);\n        if (element) {\n            element.innerHTML = \"\";\n        }\n    };\n    Html5Qrcode.prototype.possiblyUpdateShaders = function (qrMatch) {\n        if (this.qrMatch === qrMatch) {\n            return;\n        }\n        if (this.hasBorderShaders\n            && this.borderShaders\n            && this.borderShaders.length) {\n            this.borderShaders.forEach(function (shader) {\n                shader.style.backgroundColor = qrMatch\n                    ? Constants.BORDER_SHADER_MATCH_COLOR\n                    : Constants.BORDER_SHADER_DEFAULT_COLOR;\n            });\n        }\n        this.qrMatch = qrMatch;\n    };\n    Html5Qrcode.prototype.possiblyCloseLastScanImageFile = function () {\n        if (this.lastScanImageFile) {\n            URL.revokeObjectURL(this.lastScanImageFile);\n            this.lastScanImageFile = null;\n        }\n    };\n    Html5Qrcode.prototype.createCanvasElement = function (width, height, customId) {\n        var canvasWidth = width;\n        var canvasHeight = height;\n        var canvasElement = document.createElement(\"canvas\");\n        canvasElement.style.width = \"\".concat(canvasWidth, \"px\");\n        canvasElement.style.height = \"\".concat(canvasHeight, \"px\");\n        canvasElement.style.display = \"none\";\n        canvasElement.id = (0,_core__WEBPACK_IMPORTED_MODULE_0__.isNullOrUndefined)(customId)\n            ? \"qr-canvas\" : customId;\n        return canvasElement;\n    };\n    Html5Qrcode.prototype.getShadedRegionBounds = function (width, height, qrboxSize) {\n        if (qrboxSize.width > width || qrboxSize.height > height) {\n            throw \"'config.qrbox' dimensions should not be greater than the \"\n                + \"dimensions of the root HTML element.\";\n        }\n        return {\n            x: (width - qrboxSize.width) / 2,\n            y: (height - qrboxSize.height) / 2,\n            width: qrboxSize.width,\n            height: qrboxSize.height\n        };\n    };\n    Html5Qrcode.prototype.possiblyInsertShadingElement = function (element, width, height, qrboxSize) {\n        if ((width - qrboxSize.width) < 1 || (height - qrboxSize.height) < 1) {\n            return;\n        }\n        var shadingElement = document.createElement(\"div\");\n        shadingElement.style.position = \"absolute\";\n        var rightLeftBorderSize = (width - qrboxSize.width) / 2;\n        var topBottomBorderSize = (height - qrboxSize.height) / 2;\n        shadingElement.style.borderLeft\n            = \"\".concat(rightLeftBorderSize, \"px solid rgba(0, 0, 0, 0.48)\");\n        shadingElement.style.borderRight\n            = \"\".concat(rightLeftBorderSize, \"px solid rgba(0, 0, 0, 0.48)\");\n        shadingElement.style.borderTop\n            = \"\".concat(topBottomBorderSize, \"px solid rgba(0, 0, 0, 0.48)\");\n        shadingElement.style.borderBottom\n            = \"\".concat(topBottomBorderSize, \"px solid rgba(0, 0, 0, 0.48)\");\n        shadingElement.style.boxSizing = \"border-box\";\n        shadingElement.style.top = \"0px\";\n        shadingElement.style.bottom = \"0px\";\n        shadingElement.style.left = \"0px\";\n        shadingElement.style.right = \"0px\";\n        shadingElement.id = \"\".concat(Constants.SHADED_REGION_ELEMENT_ID);\n        if ((width - qrboxSize.width) < 11\n            || (height - qrboxSize.height) < 11) {\n            this.hasBorderShaders = false;\n        }\n        else {\n            var smallSize = 5;\n            var largeSize = 40;\n            this.insertShaderBorders(shadingElement, largeSize, smallSize, -smallSize, null, 0, true);\n            this.insertShaderBorders(shadingElement, largeSize, smallSize, -smallSize, null, 0, false);\n            this.insertShaderBorders(shadingElement, largeSize, smallSize, null, -smallSize, 0, true);\n            this.insertShaderBorders(shadingElement, largeSize, smallSize, null, -smallSize, 0, false);\n            this.insertShaderBorders(shadingElement, smallSize, largeSize + smallSize, -smallSize, null, -smallSize, true);\n            this.insertShaderBorders(shadingElement, smallSize, largeSize + smallSize, null, -smallSize, -smallSize, true);\n            this.insertShaderBorders(shadingElement, smallSize, largeSize + smallSize, -smallSize, null, -smallSize, false);\n            this.insertShaderBorders(shadingElement, smallSize, largeSize + smallSize, null, -smallSize, -smallSize, false);\n            this.hasBorderShaders = true;\n        }\n        element.append(shadingElement);\n    };\n    Html5Qrcode.prototype.insertShaderBorders = function (shaderElem, width, height, top, bottom, side, isLeft) {\n        var elem = document.createElement(\"div\");\n        elem.style.position = \"absolute\";\n        elem.style.backgroundColor = Constants.BORDER_SHADER_DEFAULT_COLOR;\n        elem.style.width = \"\".concat(width, \"px\");\n        elem.style.height = \"\".concat(height, \"px\");\n        if (top !== null) {\n            elem.style.top = \"\".concat(top, \"px\");\n        }\n        if (bottom !== null) {\n            elem.style.bottom = \"\".concat(bottom, \"px\");\n        }\n        if (isLeft) {\n            elem.style.left = \"\".concat(side, \"px\");\n        }\n        else {\n            elem.style.right = \"\".concat(side, \"px\");\n        }\n        if (!this.borderShaders) {\n            this.borderShaders = [];\n        }\n        this.borderShaders.push(elem);\n        shaderElem.appendChild(elem);\n    };\n    Html5Qrcode.prototype.showPausedState = function () {\n        if (!this.scannerPausedUiElement) {\n            throw \"[internal error] scanner paused UI element not found\";\n        }\n        this.scannerPausedUiElement.style.display = \"block\";\n    };\n    Html5Qrcode.prototype.hidePausedState = function () {\n        if (!this.scannerPausedUiElement) {\n            throw \"[internal error] scanner paused UI element not found\";\n        }\n        this.scannerPausedUiElement.style.display = \"none\";\n    };\n    Html5Qrcode.prototype.getTimeoutFps = function (fps) {\n        return 1000 / fps;\n    };\n    return Html5Qrcode;\n}());\n\n//# sourceMappingURL=html5-qrcode.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9odG1sNS1xcmNvZGUuanMuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9odG1sNS1xcmNvZGUuanM/NGMyMCJdLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgQmFzZUxvZ2dnZXIsIEh0bWw1UXJjb2RlUmVzdWx0RmFjdG9yeSwgSHRtbDVRcmNvZGVFcnJvckZhY3RvcnksIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cywgaXNWYWxpZEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cywgSHRtbDVRcmNvZGVDb25zdGFudHMsIGlzTnVsbE9yVW5kZWZpbmVkIH0gZnJvbSBcIi4vY29yZVwiO1xuaW1wb3J0IHsgSHRtbDVRcmNvZGVTdHJpbmdzIH0gZnJvbSBcIi4vc3RyaW5nc1wiO1xuaW1wb3J0IHsgVmlkZW9Db25zdHJhaW50c1V0aWwgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHsgSHRtbDVRcmNvZGVTaGltIH0gZnJvbSBcIi4vY29kZS1kZWNvZGVyXCI7XG5pbXBvcnQgeyBDYW1lcmFGYWN0b3J5IH0gZnJvbSBcIi4vY2FtZXJhL2ZhY3Rvcmllc1wiO1xuaW1wb3J0IHsgQ2FtZXJhUmV0cmlldmVyIH0gZnJvbSBcIi4vY2FtZXJhL3JldHJpZXZlclwiO1xuaW1wb3J0IHsgU3RhdGVNYW5hZ2VyRmFjdG9yeSwgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUgfSBmcm9tIFwiLi9zdGF0ZS1tYW5hZ2VyXCI7XG52YXIgQ29uc3RhbnRzID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoQ29uc3RhbnRzLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIENvbnN0YW50cygpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBDb25zdGFudHMuREVGQVVMVF9XSURUSCA9IDMwMDtcbiAgICBDb25zdGFudHMuREVGQVVMVF9XSURUSF9PRkZTRVQgPSAyO1xuICAgIENvbnN0YW50cy5GSUxFX1NDQU5fTUlOX0hFSUdIVCA9IDMwMDtcbiAgICBDb25zdGFudHMuRklMRV9TQ0FOX0hJRERFTl9DQU5WQVNfUEFERElORyA9IDEwMDtcbiAgICBDb25zdGFudHMuTUlOX1FSX0JPWF9TSVpFID0gNTA7XG4gICAgQ29uc3RhbnRzLlNIQURFRF9MRUZUID0gMTtcbiAgICBDb25zdGFudHMuU0hBREVEX1JJR0hUID0gMjtcbiAgICBDb25zdGFudHMuU0hBREVEX1RPUCA9IDM7XG4gICAgQ29uc3RhbnRzLlNIQURFRF9CT1RUT00gPSA0O1xuICAgIENvbnN0YW50cy5TSEFERURfUkVHSU9OX0VMRU1FTlRfSUQgPSBcInFyLXNoYWRlZC1yZWdpb25cIjtcbiAgICBDb25zdGFudHMuVkVSQk9TRSA9IGZhbHNlO1xuICAgIENvbnN0YW50cy5CT1JERVJfU0hBREVSX0RFRkFVTFRfQ09MT1IgPSBcIiNmZmZmZmZcIjtcbiAgICBDb25zdGFudHMuQk9SREVSX1NIQURFUl9NQVRDSF9DT0xPUiA9IFwicmdiKDkwLCAxOTMsIDU2KVwiO1xuICAgIHJldHVybiBDb25zdGFudHM7XG59KEh0bWw1UXJjb2RlQ29uc3RhbnRzKSk7XG52YXIgSW50ZXJuYWxIdG1sNVFyY29kZUNvbmZpZyA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gSW50ZXJuYWxIdG1sNVFyY29kZUNvbmZpZyhjb25maWcsIGxvZ2dlcikge1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlcjtcbiAgICAgICAgdGhpcy5mcHMgPSBDb25zdGFudHMuU0NBTl9ERUZBVUxUX0ZQUztcbiAgICAgICAgaWYgKCFjb25maWcpIHtcbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZUZsaXAgPSBDb25zdGFudHMuREVGQVVMVF9ESVNBQkxFX0ZMSVA7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLmZwcykge1xuICAgICAgICAgICAgICAgIHRoaXMuZnBzID0gY29uZmlnLmZwcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZUZsaXAgPSBjb25maWcuZGlzYWJsZUZsaXAgPT09IHRydWU7XG4gICAgICAgICAgICB0aGlzLnFyYm94ID0gY29uZmlnLnFyYm94O1xuICAgICAgICAgICAgdGhpcy5hc3BlY3RSYXRpbyA9IGNvbmZpZy5hc3BlY3RSYXRpbztcbiAgICAgICAgICAgIHRoaXMudmlkZW9Db25zdHJhaW50cyA9IGNvbmZpZy52aWRlb0NvbnN0cmFpbnRzO1xuICAgICAgICB9XG4gICAgfVxuICAgIEludGVybmFsSHRtbDVRcmNvZGVDb25maWcucHJvdG90eXBlLmlzTWVkaWFTdHJlYW1Db25zdHJhaW50c1ZhbGlkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMudmlkZW9Db25zdHJhaW50cykge1xuICAgICAgICAgICAgdGhpcy5sb2dnZXIubG9nRXJyb3IoXCJFbXB0eSB2aWRlb0NvbnN0cmFpbnRzXCIsIHRydWUpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBWaWRlb0NvbnN0cmFpbnRzVXRpbC5pc01lZGlhU3RyZWFtQ29uc3RyYWludHNWYWxpZCh0aGlzLnZpZGVvQ29uc3RyYWludHMsIHRoaXMubG9nZ2VyKTtcbiAgICB9O1xuICAgIEludGVybmFsSHRtbDVRcmNvZGVDb25maWcucHJvdG90eXBlLmlzU2hhZGVkQm94RW5hYmxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICFpc051bGxPclVuZGVmaW5lZCh0aGlzLnFyYm94KTtcbiAgICB9O1xuICAgIEludGVybmFsSHRtbDVRcmNvZGVDb25maWcuY3JlYXRlID0gZnVuY3Rpb24gKGNvbmZpZywgbG9nZ2VyKSB7XG4gICAgICAgIHJldHVybiBuZXcgSW50ZXJuYWxIdG1sNVFyY29kZUNvbmZpZyhjb25maWcsIGxvZ2dlcik7XG4gICAgfTtcbiAgICByZXR1cm4gSW50ZXJuYWxIdG1sNVFyY29kZUNvbmZpZztcbn0oKSk7XG52YXIgSHRtbDVRcmNvZGUgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEh0bWw1UXJjb2RlKGVsZW1lbnRJZCwgY29uZmlnT3JWZXJib3NpdHlGbGFnKSB7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuY2FudmFzRWxlbWVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuc2Nhbm5lclBhdXNlZFVpRWxlbWVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuaGFzQm9yZGVyU2hhZGVycyA9IG51bGw7XG4gICAgICAgIHRoaXMuYm9yZGVyU2hhZGVycyA9IG51bGw7XG4gICAgICAgIHRoaXMucXJNYXRjaCA9IG51bGw7XG4gICAgICAgIHRoaXMucmVuZGVyZWRDYW1lcmEgPSBudWxsO1xuICAgICAgICB0aGlzLnFyUmVnaW9uID0gbnVsbDtcbiAgICAgICAgdGhpcy5jb250ZXh0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5sYXN0U2NhbkltYWdlRmlsZSA9IG51bGw7XG4gICAgICAgIHRoaXMuaXNTY2FubmluZyA9IGZhbHNlO1xuICAgICAgICBpZiAoIWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGVsZW1lbnRJZCkpIHtcbiAgICAgICAgICAgIHRocm93IFwiSFRNTCBFbGVtZW50IHdpdGggaWQ9XCIuY29uY2F0KGVsZW1lbnRJZCwgXCIgbm90IGZvdW5kXCIpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZWxlbWVudElkID0gZWxlbWVudElkO1xuICAgICAgICB0aGlzLnZlcmJvc2UgPSBmYWxzZTtcbiAgICAgICAgdmFyIGV4cGVyaW1lbnRhbEZlYXR1cmVDb25maWc7XG4gICAgICAgIHZhciBjb25maWdPYmplY3Q7XG4gICAgICAgIGlmICh0eXBlb2YgY29uZmlnT3JWZXJib3NpdHlGbGFnID09IFwiYm9vbGVhblwiKSB7XG4gICAgICAgICAgICB0aGlzLnZlcmJvc2UgPSBjb25maWdPclZlcmJvc2l0eUZsYWcgPT09IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoY29uZmlnT3JWZXJib3NpdHlGbGFnKSB7XG4gICAgICAgICAgICBjb25maWdPYmplY3QgPSBjb25maWdPclZlcmJvc2l0eUZsYWc7XG4gICAgICAgICAgICB0aGlzLnZlcmJvc2UgPSBjb25maWdPYmplY3QudmVyYm9zZSA9PT0gdHJ1ZTtcbiAgICAgICAgICAgIGV4cGVyaW1lbnRhbEZlYXR1cmVDb25maWcgPSBjb25maWdPYmplY3QuZXhwZXJpbWVudGFsRmVhdHVyZXM7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sb2dnZXIgPSBuZXcgQmFzZUxvZ2dnZXIodGhpcy52ZXJib3NlKTtcbiAgICAgICAgdGhpcy5xcmNvZGUgPSBuZXcgSHRtbDVRcmNvZGVTaGltKHRoaXMuZ2V0U3VwcG9ydGVkRm9ybWF0cyhjb25maWdPclZlcmJvc2l0eUZsYWcpLCB0aGlzLmdldFVzZUJhckNvZGVEZXRlY3RvcklmU3VwcG9ydGVkKGNvbmZpZ09iamVjdCksIHRoaXMudmVyYm9zZSwgdGhpcy5sb2dnZXIpO1xuICAgICAgICB0aGlzLmZvcmV2ZXJTY2FuVGltZW91dDtcbiAgICAgICAgdGhpcy5zaG91bGRTY2FuID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zdGF0ZU1hbmFnZXJQcm94eSA9IFN0YXRlTWFuYWdlckZhY3RvcnkuY3JlYXRlKCk7XG4gICAgfVxuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5zdGFydCA9IGZ1bmN0aW9uIChjYW1lcmFJZE9yQ29uZmlnLCBjb25maWd1cmF0aW9uLCBxckNvZGVTdWNjZXNzQ2FsbGJhY2ssIHFyQ29kZUVycm9yQ2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCFjYW1lcmFJZE9yQ29uZmlnKSB7XG4gICAgICAgICAgICB0aHJvdyBcImNhbWVyYUlkT3JDb25maWcgaXMgcmVxdWlyZWRcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXFyQ29kZVN1Y2Nlc3NDYWxsYmFja1xuICAgICAgICAgICAgfHwgdHlwZW9mIHFyQ29kZVN1Y2Nlc3NDYWxsYmFjayAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHRocm93IFwicXJDb2RlU3VjY2Vzc0NhbGxiYWNrIGlzIHJlcXVpcmVkIGFuZCBzaG91bGQgYmUgYSBmdW5jdGlvbi5cIjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcXJDb2RlRXJyb3JDYWxsYmFja0ludGVybmFsO1xuICAgICAgICBpZiAocXJDb2RlRXJyb3JDYWxsYmFjaykge1xuICAgICAgICAgICAgcXJDb2RlRXJyb3JDYWxsYmFja0ludGVybmFsID0gcXJDb2RlRXJyb3JDYWxsYmFjaztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHFyQ29kZUVycm9yQ2FsbGJhY2tJbnRlcm5hbFxuICAgICAgICAgICAgICAgID0gdGhpcy52ZXJib3NlID8gdGhpcy5sb2dnZXIubG9nIDogZnVuY3Rpb24gKCkgeyB9O1xuICAgICAgICB9XG4gICAgICAgIHZhciBpbnRlcm5hbENvbmZpZyA9IEludGVybmFsSHRtbDVRcmNvZGVDb25maWcuY3JlYXRlKGNvbmZpZ3VyYXRpb24sIHRoaXMubG9nZ2VyKTtcbiAgICAgICAgdGhpcy5jbGVhckVsZW1lbnQoKTtcbiAgICAgICAgdmFyIHZpZGVvQ29uc3RyYWludHNBdmFpbGFibGVBbmRWYWxpZCA9IGZhbHNlO1xuICAgICAgICBpZiAoaW50ZXJuYWxDb25maWcudmlkZW9Db25zdHJhaW50cykge1xuICAgICAgICAgICAgaWYgKCFpbnRlcm5hbENvbmZpZy5pc01lZGlhU3RyZWFtQ29uc3RyYWludHNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIubG9nRXJyb3IoXCIndmlkZW9Db25zdHJhaW50cycgaXMgbm90IHZhbGlkICdNZWRpYVN0cmVhbUNvbnN0cmFpbnRzLCBcIlxuICAgICAgICAgICAgICAgICAgICArIFwiaXQgd2lsbCBiZSBpZ25vcmVkLidcIiwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB2aWRlb0NvbnN0cmFpbnRzQXZhaWxhYmxlQW5kVmFsaWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBhcmVWaWRlb0NvbnN0cmFpbnRzRW5hYmxlZCA9IHZpZGVvQ29uc3RyYWludHNBdmFpbGFibGVBbmRWYWxpZDtcbiAgICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmVsZW1lbnRJZCk7XG4gICAgICAgIHZhciByb290RWxlbWVudFdpZHRoID0gZWxlbWVudC5jbGllbnRXaWR0aFxuICAgICAgICAgICAgPyBlbGVtZW50LmNsaWVudFdpZHRoIDogQ29uc3RhbnRzLkRFRkFVTFRfV0lEVEg7XG4gICAgICAgIGVsZW1lbnQuc3R5bGUucG9zaXRpb24gPSBcInJlbGF0aXZlXCI7XG4gICAgICAgIHRoaXMuc2hvdWxkU2NhbiA9IHRydWU7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciB0b1NjYW5uaW5nU3RhdGVDaGFuZ2VUcmFuc2FjdGlvbiA9IHRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuc3RhcnRUcmFuc2l0aW9uKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlNDQU5OSU5HKTtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgIHZhciB2aWRlb0NvbnN0cmFpbnRzID0gYXJlVmlkZW9Db25zdHJhaW50c0VuYWJsZWRcbiAgICAgICAgICAgICAgICA/IGludGVybmFsQ29uZmlnLnZpZGVvQ29uc3RyYWludHNcbiAgICAgICAgICAgICAgICA6ICR0aGlzLmNyZWF0ZVZpZGVvQ29uc3RyYWludHMoY2FtZXJhSWRPckNvbmZpZyk7XG4gICAgICAgICAgICBpZiAoIXZpZGVvQ29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICB0b1NjYW5uaW5nU3RhdGVDaGFuZ2VUcmFuc2FjdGlvbi5jYW5jZWwoKTtcbiAgICAgICAgICAgICAgICByZWplY3QoXCJ2aWRlb0NvbnN0cmFpbnRzIHNob3VsZCBiZSBkZWZpbmVkXCIpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBjYW1lcmFSZW5kZXJpbmdPcHRpb25zID0ge307XG4gICAgICAgICAgICBpZiAoIWFyZVZpZGVvQ29uc3RyYWludHNFbmFibGVkIHx8IGludGVybmFsQ29uZmlnLmFzcGVjdFJhdGlvKSB7XG4gICAgICAgICAgICAgICAgY2FtZXJhUmVuZGVyaW5nT3B0aW9ucy5hc3BlY3RSYXRpbyA9IGludGVybmFsQ29uZmlnLmFzcGVjdFJhdGlvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHJlbmRlcmluZ0NhbGxiYWNrcyA9IHtcbiAgICAgICAgICAgICAgICBvblJlbmRlclN1cmZhY2VSZWFkeTogZnVuY3Rpb24gKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5zZXR1cFVpKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCwgaW50ZXJuYWxDb25maWcpO1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5pc1NjYW5uaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMuZm9yZXZlclNjYW4oaW50ZXJuYWxDb25maWcsIHFyQ29kZVN1Y2Nlc3NDYWxsYmFjaywgcXJDb2RlRXJyb3JDYWxsYmFja0ludGVybmFsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgQ2FtZXJhRmFjdG9yeS5mYWlsSWZOb3RTdXBwb3J0ZWQoKS50aGVuKGZ1bmN0aW9uIChmYWN0b3J5KSB7XG4gICAgICAgICAgICAgICAgZmFjdG9yeS5jcmVhdGUodmlkZW9Db25zdHJhaW50cykudGhlbihmdW5jdGlvbiAoY2FtZXJhKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjYW1lcmEucmVuZGVyKF90aGlzLmVsZW1lbnQsIGNhbWVyYVJlbmRlcmluZ09wdGlvbnMsIHJlbmRlcmluZ0NhbGxiYWNrcylcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGZ1bmN0aW9uIChyZW5kZXJlZENhbWVyYSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMucmVuZGVyZWRDYW1lcmEgPSByZW5kZXJlZENhbWVyYTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvU2Nhbm5pbmdTdGF0ZUNoYW5nZVRyYW5zYWN0aW9uLmV4ZWN1dGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0b1NjYW5uaW5nU3RhdGVDaGFuZ2VUcmFuc2FjdGlvbi5jYW5jZWwoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICB0b1NjYW5uaW5nU3RhdGVDaGFuZ2VUcmFuc2FjdGlvbi5jYW5jZWwoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KEh0bWw1UXJjb2RlU3RyaW5ncy5lcnJvckdldHRpbmdVc2VyTWVkaWEoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICAgICAgdG9TY2FubmluZ1N0YXRlQ2hhbmdlVHJhbnNhY3Rpb24uY2FuY2VsKCk7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEh0bWw1UXJjb2RlU3RyaW5ncy5jYW1lcmFTdHJlYW1pbmdOb3RTdXBwb3J0ZWQoKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUucGF1c2UgPSBmdW5jdGlvbiAoc2hvdWxkUGF1c2VWaWRlbykge1xuICAgICAgICBpZiAoIXRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuaXNTdHJpY3RseVNjYW5uaW5nKCkpIHtcbiAgICAgICAgICAgIHRocm93IFwiQ2Fubm90IHBhdXNlLCBzY2FubmVyIGlzIG5vdCBzY2FubmluZy5cIjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0YXRlTWFuYWdlclByb3h5LmRpcmVjdFRyYW5zaXRpb24oSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuUEFVU0VEKTtcbiAgICAgICAgdGhpcy5zaG93UGF1c2VkU3RhdGUoKTtcbiAgICAgICAgaWYgKGlzTnVsbE9yVW5kZWZpbmVkKHNob3VsZFBhdXNlVmlkZW8pIHx8IHNob3VsZFBhdXNlVmlkZW8gIT09IHRydWUpIHtcbiAgICAgICAgICAgIHNob3VsZFBhdXNlVmlkZW8gPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2hvdWxkUGF1c2VWaWRlbyAmJiB0aGlzLnJlbmRlcmVkQ2FtZXJhKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVkQ2FtZXJhLnBhdXNlKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5yZXN1bWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5zdGF0ZU1hbmFnZXJQcm94eS5pc1BhdXNlZCgpKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkNhbm5vdCByZXN1bHQsIHNjYW5uZXIgaXMgbm90IHBhdXNlZC5cIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMucmVuZGVyZWRDYW1lcmEpIHtcbiAgICAgICAgICAgIHRocm93IFwicmVuZGVyZWRDYW1lcmEgZG9lc24ndCBleGlzdCB3aGlsZSB0cnlpbmcgcmVzdW1lKClcIjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgdHJhbnNpdGlvblRvU2Nhbm5pbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAkdGhpcy5zdGF0ZU1hbmFnZXJQcm94eS5kaXJlY3RUcmFuc2l0aW9uKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlNDQU5OSU5HKTtcbiAgICAgICAgICAgICR0aGlzLmhpZGVQYXVzZWRTdGF0ZSgpO1xuICAgICAgICB9O1xuICAgICAgICBpZiAoIXRoaXMucmVuZGVyZWRDYW1lcmEuaXNQYXVzZWQoKSkge1xuICAgICAgICAgICAgdHJhbnNpdGlvblRvU2Nhbm5pbmcoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbmRlcmVkQ2FtZXJhLnJlc3VtZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0cmFuc2l0aW9uVG9TY2FubmluZygpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5nZXRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuZ2V0U3RhdGUoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5zdG9wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIXRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuaXNTY2FubmluZygpKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkNhbm5vdCBzdG9wLCBzY2FubmVyIGlzIG5vdCBydW5uaW5nIG9yIHBhdXNlZC5cIjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdG9TdG9wcGVkU3RhdGVUcmFuc2FjdGlvbiA9IHRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuc3RhcnRUcmFuc2l0aW9uKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLk5PVF9TVEFSVEVEKTtcbiAgICAgICAgdGhpcy5zaG91bGRTY2FuID0gZmFsc2U7XG4gICAgICAgIGlmICh0aGlzLmZvcmV2ZXJTY2FuVGltZW91dCkge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuZm9yZXZlclNjYW5UaW1lb3V0KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVtb3ZlUXJSZWdpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoIV90aGlzLmVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgY2hpbGRFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoQ29uc3RhbnRzLlNIQURFRF9SRUdJT05fRUxFTUVOVF9JRCk7XG4gICAgICAgICAgICBpZiAoY2hpbGRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZWxlbWVudC5yZW1vdmVDaGlsZChjaGlsZEVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICByZXR1cm4gdGhpcy5yZW5kZXJlZENhbWVyYS5jbG9zZSgpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgJHRoaXMucmVuZGVyZWRDYW1lcmEgPSBudWxsO1xuICAgICAgICAgICAgaWYgKCR0aGlzLmVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5lbGVtZW50LnJlbW92ZUNoaWxkKCR0aGlzLmNhbnZhc0VsZW1lbnQpO1xuICAgICAgICAgICAgICAgICR0aGlzLmNhbnZhc0VsZW1lbnQgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVtb3ZlUXJSZWdpb24oKTtcbiAgICAgICAgICAgIGlmICgkdGhpcy5xclJlZ2lvbikge1xuICAgICAgICAgICAgICAgICR0aGlzLnFyUmVnaW9uID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgkdGhpcy5jb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuY29udGV4dCA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0b1N0b3BwZWRTdGF0ZVRyYW5zYWN0aW9uLmV4ZWN1dGUoKTtcbiAgICAgICAgICAgICR0aGlzLmhpZGVQYXVzZWRTdGF0ZSgpO1xuICAgICAgICAgICAgJHRoaXMuaXNTY2FubmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5zY2FuRmlsZSA9IGZ1bmN0aW9uIChpbWFnZUZpbGUsIHNob3dJbWFnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zY2FuRmlsZVYyKGltYWdlRmlsZSwgc2hvd0ltYWdlKVxuICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKGh0bWw1cXJjb2RlUmVzdWx0KSB7IHJldHVybiBodG1sNXFyY29kZVJlc3VsdC5kZWNvZGVkVGV4dDsgfSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuc2NhbkZpbGVWMiA9IGZ1bmN0aW9uIChpbWFnZUZpbGUsIHNob3dJbWFnZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIWltYWdlRmlsZSB8fCAhKGltYWdlRmlsZSBpbnN0YW5jZW9mIEZpbGUpKSB7XG4gICAgICAgICAgICB0aHJvdyBcImltYWdlRmlsZSBhcmd1bWVudCBpcyBtYW5kYXRvcnkgYW5kIHNob3VsZCBiZSBpbnN0YW5jZSBcIlxuICAgICAgICAgICAgICAgICsgXCJvZiBGaWxlLiBVc2UgJ2V2ZW50LnRhcmdldC5maWxlc1swXScuXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzTnVsbE9yVW5kZWZpbmVkKHNob3dJbWFnZSkpIHtcbiAgICAgICAgICAgIHNob3dJbWFnZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlTWFuYWdlclByb3h5LmNhblNjYW5GaWxlKCkpIHtcbiAgICAgICAgICAgIHRocm93IFwiQ2Fubm90IHN0YXJ0IGZpbGUgc2NhbiAtIG9uZ29pbmcgY2FtZXJhIHNjYW5cIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAgICAgX3RoaXMucG9zc2libHlDbG9zZUxhc3RTY2FuSW1hZ2VGaWxlKCk7XG4gICAgICAgICAgICBfdGhpcy5jbGVhckVsZW1lbnQoKTtcbiAgICAgICAgICAgIF90aGlzLmxhc3RTY2FuSW1hZ2VGaWxlID0gVVJMLmNyZWF0ZU9iamVjdFVSTChpbWFnZUZpbGUpO1xuICAgICAgICAgICAgdmFyIGlucHV0SW1hZ2UgPSBuZXcgSW1hZ2U7XG4gICAgICAgICAgICBpbnB1dEltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW1hZ2VXaWR0aCA9IGlucHV0SW1hZ2Uud2lkdGg7XG4gICAgICAgICAgICAgICAgdmFyIGltYWdlSGVpZ2h0ID0gaW5wdXRJbWFnZS5oZWlnaHQ7XG4gICAgICAgICAgICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChfdGhpcy5lbGVtZW50SWQpO1xuICAgICAgICAgICAgICAgIHZhciBjb250YWluZXJXaWR0aCA9IGVsZW1lbnQuY2xpZW50V2lkdGhcbiAgICAgICAgICAgICAgICAgICAgPyBlbGVtZW50LmNsaWVudFdpZHRoIDogQ29uc3RhbnRzLkRFRkFVTFRfV0lEVEg7XG4gICAgICAgICAgICAgICAgdmFyIGNvbnRhaW5lckhlaWdodCA9IE1hdGgubWF4KGVsZW1lbnQuY2xpZW50SGVpZ2h0ID8gZWxlbWVudC5jbGllbnRIZWlnaHQgOiBpbWFnZUhlaWdodCwgQ29uc3RhbnRzLkZJTEVfU0NBTl9NSU5fSEVJR0hUKTtcbiAgICAgICAgICAgICAgICB2YXIgY29uZmlnID0gX3RoaXMuY29tcHV0ZUNhbnZhc0RyYXdDb25maWcoaW1hZ2VXaWR0aCwgaW1hZ2VIZWlnaHQsIGNvbnRhaW5lcldpZHRoLCBjb250YWluZXJIZWlnaHQpO1xuICAgICAgICAgICAgICAgIGlmIChzaG93SW1hZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZpc2libGVDYW52YXMgPSBfdGhpcy5jcmVhdGVDYW52YXNFbGVtZW50KGNvbnRhaW5lcldpZHRoLCBjb250YWluZXJIZWlnaHQsIFwicXItY2FudmFzLXZpc2libGVcIik7XG4gICAgICAgICAgICAgICAgICAgIHZpc2libGVDYW52YXMuc3R5bGUuZGlzcGxheSA9IFwiaW5saW5lLWJsb2NrXCI7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQodmlzaWJsZUNhbnZhcyk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjb250ZXh0XzEgPSB2aXNpYmxlQ2FudmFzLmdldENvbnRleHQoXCIyZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb250ZXh0XzEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFwiVW5hYmxlIHRvIGdldCAyZCBjb250ZXh0IGZyb20gY2FudmFzXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY29udGV4dF8xLmNhbnZhcy53aWR0aCA9IGNvbnRhaW5lcldpZHRoO1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0XzEuY2FudmFzLmhlaWdodCA9IGNvbnRhaW5lckhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dF8xLmRyYXdJbWFnZShpbnB1dEltYWdlLCAwLCAwLCBpbWFnZVdpZHRoLCBpbWFnZUhlaWdodCwgY29uZmlnLngsIGNvbmZpZy55LCBjb25maWcud2lkdGgsIGNvbmZpZy5oZWlnaHQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgcGFkZGluZyA9IENvbnN0YW50cy5GSUxFX1NDQU5fSElEREVOX0NBTlZBU19QQURESU5HO1xuICAgICAgICAgICAgICAgIHZhciBoaWRkZW5JbWFnZVdpZHRoID0gTWF0aC5tYXgoaW5wdXRJbWFnZS53aWR0aCwgY29uZmlnLndpZHRoKTtcbiAgICAgICAgICAgICAgICB2YXIgaGlkZGVuSW1hZ2VIZWlnaHQgPSBNYXRoLm1heChpbnB1dEltYWdlLmhlaWdodCwgY29uZmlnLmhlaWdodCk7XG4gICAgICAgICAgICAgICAgdmFyIGhpZGRlbkNhbnZhc1dpZHRoID0gaGlkZGVuSW1hZ2VXaWR0aCArIDIgKiBwYWRkaW5nO1xuICAgICAgICAgICAgICAgIHZhciBoaWRkZW5DYW52YXNIZWlnaHQgPSBoaWRkZW5JbWFnZUhlaWdodCArIDIgKiBwYWRkaW5nO1xuICAgICAgICAgICAgICAgIHZhciBoaWRkZW5DYW52YXMgPSBfdGhpcy5jcmVhdGVDYW52YXNFbGVtZW50KGhpZGRlbkNhbnZhc1dpZHRoLCBoaWRkZW5DYW52YXNIZWlnaHQpO1xuICAgICAgICAgICAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQoaGlkZGVuQ2FudmFzKTtcbiAgICAgICAgICAgICAgICB2YXIgY29udGV4dCA9IGhpZGRlbkNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XG4gICAgICAgICAgICAgICAgaWYgKCFjb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwiVW5hYmxlIHRvIGdldCAyZCBjb250ZXh0IGZyb20gY2FudmFzXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnRleHQuY2FudmFzLndpZHRoID0gaGlkZGVuQ2FudmFzV2lkdGg7XG4gICAgICAgICAgICAgICAgY29udGV4dC5jYW52YXMuaGVpZ2h0ID0gaGlkZGVuQ2FudmFzSGVpZ2h0O1xuICAgICAgICAgICAgICAgIGNvbnRleHQuZHJhd0ltYWdlKGlucHV0SW1hZ2UsIDAsIDAsIGltYWdlV2lkdGgsIGltYWdlSGVpZ2h0LCBwYWRkaW5nLCBwYWRkaW5nLCBoaWRkZW5JbWFnZVdpZHRoLCBoaWRkZW5JbWFnZUhlaWdodCk7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMucXJjb2RlLmRlY29kZVJvYnVzdGx5QXN5bmMoaGlkZGVuQ2FudmFzKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShIdG1sNVFyY29kZVJlc3VsdEZhY3RvcnkuY3JlYXRlRnJvbVFyY29kZVJlc3VsdChyZXN1bHQpKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChyZWplY3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChcIlFSIGNvZGUgcGFyc2UgZXJyb3IsIGVycm9yID0gXCIuY29uY2F0KGV4Y2VwdGlvbikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpbnB1dEltYWdlLm9uZXJyb3IgPSByZWplY3Q7XG4gICAgICAgICAgICBpbnB1dEltYWdlLm9uYWJvcnQgPSByZWplY3Q7XG4gICAgICAgICAgICBpbnB1dEltYWdlLm9uc3RhbGxlZCA9IHJlamVjdDtcbiAgICAgICAgICAgIGlucHV0SW1hZ2Uub25zdXNwZW5kID0gcmVqZWN0O1xuICAgICAgICAgICAgaW5wdXRJbWFnZS5zcmMgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKGltYWdlRmlsZSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNsZWFyRWxlbWVudCgpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUuZ2V0Q2FtZXJhcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIENhbWVyYVJldHJpZXZlci5yZXRyaWV2ZSgpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFJ1bm5pbmdUcmFja0NhcGFiaWxpdGllcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVuZGVyZWRDYW1lcmFPckZhaWwoKS5nZXRSdW5uaW5nVHJhY2tDYXBhYmlsaXRpZXMoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5nZXRSdW5uaW5nVHJhY2tTZXR0aW5ncyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVuZGVyZWRDYW1lcmFPckZhaWwoKS5nZXRSdW5uaW5nVHJhY2tTZXR0aW5ncygpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFJ1bm5pbmdUcmFja0NhbWVyYUNhcGFiaWxpdGllcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVuZGVyZWRDYW1lcmFPckZhaWwoKS5nZXRDYXBhYmlsaXRpZXMoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5hcHBseVZpZGVvQ29uc3RyYWludHMgPSBmdW5jdGlvbiAodmlkZW9Db25zdGFpbnRzKSB7XG4gICAgICAgIGlmICghdmlkZW9Db25zdGFpbnRzKSB7XG4gICAgICAgICAgICB0aHJvdyBcInZpZGVvQ29uc3RhaW50cyBpcyByZXF1aXJlZCBhcmd1bWVudC5cIjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghVmlkZW9Db25zdHJhaW50c1V0aWwuaXNNZWRpYVN0cmVhbUNvbnN0cmFpbnRzVmFsaWQodmlkZW9Db25zdGFpbnRzLCB0aGlzLmxvZ2dlcikpIHtcbiAgICAgICAgICAgIHRocm93IFwiaW52YWxpZCB2aWRlb0NvbnN0YWludHMgcGFzc2VkLCBjaGVjayBsb2dzIGZvciBtb3JlIGRldGFpbHNcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5nZXRSZW5kZXJlZENhbWVyYU9yRmFpbCgpLmFwcGx5VmlkZW9Db25zdHJhaW50cyh2aWRlb0NvbnN0YWludHMpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFJlbmRlcmVkQ2FtZXJhT3JGYWlsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5yZW5kZXJlZENhbWVyYSA9PSBudWxsKSB7XG4gICAgICAgICAgICB0aHJvdyBcIlNjYW5uaW5nIGlzIG5vdCBpbiBydW5uaW5nIHN0YXRlLCBjYWxsIHRoaXMgQVBJIG9ubHkgd2hlblwiXG4gICAgICAgICAgICAgICAgKyBcIiBRUiBjb2RlIHNjYW5uaW5nIHVzaW5nIGNhbWVyYSBpcyBpbiBydW5uaW5nIHN0YXRlLlwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnJlbmRlcmVkQ2FtZXJhO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFN1cHBvcnRlZEZvcm1hdHMgPSBmdW5jdGlvbiAoY29uZmlnT3JWZXJib3NpdHlGbGFnKSB7XG4gICAgICAgIHZhciBhbGxGb3JtYXRzID0gW1xuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlFSX0NPREUsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQVpURUMsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQ09EQUJBUixcbiAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzM5LFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfOTMsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQ09ERV8xMjgsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuREFUQV9NQVRSSVgsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuTUFYSUNPREUsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuSVRGLFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkVBTl8xMyxcbiAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5FQU5fOCxcbiAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5QREZfNDE3LFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlJTU18xNCxcbiAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5SU1NfRVhQQU5ERUQsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0EsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0UsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0VBTl9FWFRFTlNJT04sXG4gICAgICAgIF07XG4gICAgICAgIGlmICghY29uZmlnT3JWZXJib3NpdHlGbGFnXG4gICAgICAgICAgICB8fCB0eXBlb2YgY29uZmlnT3JWZXJib3NpdHlGbGFnID09IFwiYm9vbGVhblwiKSB7XG4gICAgICAgICAgICByZXR1cm4gYWxsRm9ybWF0cztcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWNvbmZpZ09yVmVyYm9zaXR5RmxhZy5mb3JtYXRzVG9TdXBwb3J0KSB7XG4gICAgICAgICAgICByZXR1cm4gYWxsRm9ybWF0cztcbiAgICAgICAgfVxuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoY29uZmlnT3JWZXJib3NpdHlGbGFnLmZvcm1hdHNUb1N1cHBvcnQpKSB7XG4gICAgICAgICAgICB0aHJvdyBcImNvbmZpZ09yVmVyYm9zaXR5RmxhZy5mb3JtYXRzVG9TdXBwb3J0IHNob3VsZCBiZSB1bmRlZmluZWQgXCJcbiAgICAgICAgICAgICAgICArIFwib3IgYW4gYXJyYXkuXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbmZpZ09yVmVyYm9zaXR5RmxhZy5mb3JtYXRzVG9TdXBwb3J0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgXCJBdGxlYXN0IDEgZm9ybWF0c1RvU3VwcG9ydCBpcyBuZWVkZWQuXCI7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHN1cHBvcnRlZEZvcm1hdHMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IGNvbmZpZ09yVmVyYm9zaXR5RmxhZy5mb3JtYXRzVG9TdXBwb3J0OyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIGZvcm1hdCA9IF9hW19pXTtcbiAgICAgICAgICAgIGlmIChpc1ZhbGlkSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzKGZvcm1hdCkpIHtcbiAgICAgICAgICAgICAgICBzdXBwb3J0ZWRGb3JtYXRzLnB1c2goZm9ybWF0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLndhcm4oXCJJbnZhbGlkIGZvcm1hdDogXCIuY29uY2F0KGZvcm1hdCwgXCIgcGFzc2VkIGluIGNvbmZpZywgaWdub3JpbmcuXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoc3VwcG9ydGVkRm9ybWF0cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IFwiTm9uZSBvZiBmb3JtYXRzVG9TdXBwb3J0IG1hdGNoIHN1cHBvcnRlZCB2YWx1ZXMuXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN1cHBvcnRlZEZvcm1hdHM7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuZ2V0VXNlQmFyQ29kZURldGVjdG9ySWZTdXBwb3J0ZWQgPSBmdW5jdGlvbiAoY29uZmlnKSB7XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmaW5lZChjb25maWcpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzTnVsbE9yVW5kZWZpbmVkKGNvbmZpZy51c2VCYXJDb2RlRGV0ZWN0b3JJZlN1cHBvcnRlZCkpIHtcbiAgICAgICAgICAgIHJldHVybiBjb25maWcudXNlQmFyQ29kZURldGVjdG9ySWZTdXBwb3J0ZWQgIT09IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmaW5lZChjb25maWcuZXhwZXJpbWVudGFsRmVhdHVyZXMpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXhwZXJpbWVudGFsRmVhdHVyZXMgPSBjb25maWcuZXhwZXJpbWVudGFsRmVhdHVyZXM7XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmaW5lZChleHBlcmltZW50YWxGZWF0dXJlcy51c2VCYXJDb2RlRGV0ZWN0b3JJZlN1cHBvcnRlZCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBleHBlcmltZW50YWxGZWF0dXJlcy51c2VCYXJDb2RlRGV0ZWN0b3JJZlN1cHBvcnRlZCAhPT0gZmFsc2U7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUudmFsaWRhdGVRcmJveFNpemUgPSBmdW5jdGlvbiAodmlld2ZpbmRlcldpZHRoLCB2aWV3ZmluZGVySGVpZ2h0LCBpbnRlcm5hbENvbmZpZykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcXJib3hTaXplID0gaW50ZXJuYWxDb25maWcucXJib3g7XG4gICAgICAgIHRoaXMudmFsaWRhdGVRcmJveENvbmZpZyhxcmJveFNpemUpO1xuICAgICAgICB2YXIgcXJEaW1lbnNpb25zID0gdGhpcy50b1FyZGltZW5zaW9ucyh2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQsIHFyYm94U2l6ZSk7XG4gICAgICAgIHZhciB2YWxpZGF0ZU1pblNpemUgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICAgICAgICAgICAgaWYgKHNpemUgPCBDb25zdGFudHMuTUlOX1FSX0JPWF9TSVpFKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgXCJtaW5pbXVtIHNpemUgb2YgJ2NvbmZpZy5xcmJveCcgZGltZW5zaW9uIHZhbHVlIGlzXCJcbiAgICAgICAgICAgICAgICAgICAgKyBcIiBcIi5jb25jYXQoQ29uc3RhbnRzLk1JTl9RUl9CT1hfU0laRSwgXCJweC5cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZhciBjb3JyZWN0V2lkdGhCYXNlZE9uUm9vdEVsZW1lbnRTaXplID0gZnVuY3Rpb24gKGNvbmZpZ1dpZHRoKSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnV2lkdGggPiB2aWV3ZmluZGVyV2lkdGgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5sb2dnZXIud2FybihcImBxcmJveC53aWR0aGAgb3IgYHFyYm94YCBpcyBsYXJnZXIgdGhhbiB0aGVcIlxuICAgICAgICAgICAgICAgICAgICArIFwiIHdpZHRoIG9mIHRoZSByb290IGVsZW1lbnQuIFRoZSB3aWR0aCB3aWxsIGJlIHRydW5jYXRlZFwiXG4gICAgICAgICAgICAgICAgICAgICsgXCIgdG8gdGhlIHdpZHRoIG9mIHJvb3QgZWxlbWVudC5cIik7XG4gICAgICAgICAgICAgICAgY29uZmlnV2lkdGggPSB2aWV3ZmluZGVyV2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY29uZmlnV2lkdGg7XG4gICAgICAgIH07XG4gICAgICAgIHZhbGlkYXRlTWluU2l6ZShxckRpbWVuc2lvbnMud2lkdGgpO1xuICAgICAgICB2YWxpZGF0ZU1pblNpemUocXJEaW1lbnNpb25zLmhlaWdodCk7XG4gICAgICAgIHFyRGltZW5zaW9ucy53aWR0aCA9IGNvcnJlY3RXaWR0aEJhc2VkT25Sb290RWxlbWVudFNpemUocXJEaW1lbnNpb25zLndpZHRoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS52YWxpZGF0ZVFyYm94Q29uZmlnID0gZnVuY3Rpb24gKHFyYm94U2l6ZSkge1xuICAgICAgICBpZiAodHlwZW9mIHFyYm94U2l6ZSA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgcXJib3hTaXplID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAocXJib3hTaXplLndpZHRoID09PSB1bmRlZmluZWQgfHwgcXJib3hTaXplLmhlaWdodCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkludmFsaWQgaW5zdGFuY2Ugb2YgUXJEaW1lbnNpb25zIHBhc3NlZCBmb3IgXCJcbiAgICAgICAgICAgICAgICArIFwiJ2NvbmZpZy5xcmJveCcuIEJvdGggJ3dpZHRoJyBhbmQgJ2hlaWdodCcgc2hvdWxkIGJlIHNldC5cIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLnRvUXJkaW1lbnNpb25zID0gZnVuY3Rpb24gKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCwgcXJib3hTaXplKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcXJib3hTaXplID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICByZXR1cm4geyB3aWR0aDogcXJib3hTaXplLCBoZWlnaHQ6IHFyYm94U2l6ZSB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBxcmJveFNpemUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcXJib3hTaXplKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJxcmJveCBjb25maWcgd2FzIHBhc3NlZCBhcyBhIGZ1bmN0aW9uIGJ1dCBpdCBmYWlsZWQgd2l0aCBcIlxuICAgICAgICAgICAgICAgICAgICArIFwidW5rbm93biBlcnJvclwiICsgZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBxcmJveFNpemU7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuc2V0dXBVaSA9IGZ1bmN0aW9uICh2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQsIGludGVybmFsQ29uZmlnKSB7XG4gICAgICAgIGlmIChpbnRlcm5hbENvbmZpZy5pc1NoYWRlZEJveEVuYWJsZWQoKSkge1xuICAgICAgICAgICAgdGhpcy52YWxpZGF0ZVFyYm94U2l6ZSh2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQsIGludGVybmFsQ29uZmlnKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcXJib3hTaXplID0gaXNOdWxsT3JVbmRlZmluZWQoaW50ZXJuYWxDb25maWcucXJib3gpID9cbiAgICAgICAgICAgIHsgd2lkdGg6IHZpZXdmaW5kZXJXaWR0aCwgaGVpZ2h0OiB2aWV3ZmluZGVySGVpZ2h0IH0gOiBpbnRlcm5hbENvbmZpZy5xcmJveDtcbiAgICAgICAgdGhpcy52YWxpZGF0ZVFyYm94Q29uZmlnKHFyYm94U2l6ZSk7XG4gICAgICAgIHZhciBxckRpbWVuc2lvbnMgPSB0aGlzLnRvUXJkaW1lbnNpb25zKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCwgcXJib3hTaXplKTtcbiAgICAgICAgaWYgKHFyRGltZW5zaW9ucy5oZWlnaHQgPiB2aWV3ZmluZGVySGVpZ2h0KSB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci53YXJuKFwiW0h0bWw1UXJjb2RlXSBjb25maWcucXJib3ggaGFzIGhlaWdodCB0aGF0IGlzXCJcbiAgICAgICAgICAgICAgICArIFwiZ3JlYXRlciB0aGFuIHRoZSBoZWlnaHQgb2YgdGhlIHZpZGVvIHN0cmVhbS4gU2hhZGluZyB3aWxsIGJlXCJcbiAgICAgICAgICAgICAgICArIFwiIGlnbm9yZWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNob3VsZFNoYWRpbmdCZUFwcGxpZWQgPSBpbnRlcm5hbENvbmZpZy5pc1NoYWRlZEJveEVuYWJsZWQoKVxuICAgICAgICAgICAgJiYgcXJEaW1lbnNpb25zLmhlaWdodCA8PSB2aWV3ZmluZGVySGVpZ2h0O1xuICAgICAgICB2YXIgZGVmYXVsdFFyUmVnaW9uID0ge1xuICAgICAgICAgICAgeDogMCxcbiAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICB3aWR0aDogdmlld2ZpbmRlcldpZHRoLFxuICAgICAgICAgICAgaGVpZ2h0OiB2aWV3ZmluZGVySGVpZ2h0XG4gICAgICAgIH07XG4gICAgICAgIHZhciBxclJlZ2lvbiA9IHNob3VsZFNoYWRpbmdCZUFwcGxpZWRcbiAgICAgICAgICAgID8gdGhpcy5nZXRTaGFkZWRSZWdpb25Cb3VuZHModmlld2ZpbmRlcldpZHRoLCB2aWV3ZmluZGVySGVpZ2h0LCBxckRpbWVuc2lvbnMpXG4gICAgICAgICAgICA6IGRlZmF1bHRRclJlZ2lvbjtcbiAgICAgICAgdmFyIGNhbnZhc0VsZW1lbnQgPSB0aGlzLmNyZWF0ZUNhbnZhc0VsZW1lbnQocXJSZWdpb24ud2lkdGgsIHFyUmVnaW9uLmhlaWdodCk7XG4gICAgICAgIHZhciBjb250ZXh0QXR0cmlidXRlcyA9IHsgd2lsbFJlYWRGcmVxdWVudGx5OiB0cnVlIH07XG4gICAgICAgIHZhciBjb250ZXh0ID0gY2FudmFzRWxlbWVudC5nZXRDb250ZXh0KFwiMmRcIiwgY29udGV4dEF0dHJpYnV0ZXMpO1xuICAgICAgICBjb250ZXh0LmNhbnZhcy53aWR0aCA9IHFyUmVnaW9uLndpZHRoO1xuICAgICAgICBjb250ZXh0LmNhbnZhcy5oZWlnaHQgPSBxclJlZ2lvbi5oZWlnaHQ7XG4gICAgICAgIHRoaXMuZWxlbWVudC5hcHBlbmQoY2FudmFzRWxlbWVudCk7XG4gICAgICAgIGlmIChzaG91bGRTaGFkaW5nQmVBcHBsaWVkKSB7XG4gICAgICAgICAgICB0aGlzLnBvc3NpYmx5SW5zZXJ0U2hhZGluZ0VsZW1lbnQodGhpcy5lbGVtZW50LCB2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQsIHFyRGltZW5zaW9ucyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jcmVhdGVTY2FubmVyUGF1c2VkVWlFbGVtZW50KHRoaXMuZWxlbWVudCk7XG4gICAgICAgIHRoaXMucXJSZWdpb24gPSBxclJlZ2lvbjtcbiAgICAgICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgdGhpcy5jYW52YXNFbGVtZW50ID0gY2FudmFzRWxlbWVudDtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5jcmVhdGVTY2FubmVyUGF1c2VkVWlFbGVtZW50ID0gZnVuY3Rpb24gKHJvb3RFbGVtZW50KSB7XG4gICAgICAgIHZhciBzY2FubmVyUGF1c2VkVWlFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5pbm5lclRleHQgPSBIdG1sNVFyY29kZVN0cmluZ3Muc2Nhbm5lclBhdXNlZCgpO1xuICAgICAgICBzY2FubmVyUGF1c2VkVWlFbGVtZW50LnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS5wb3NpdGlvbiA9IFwiYWJzb2x1dGVcIjtcbiAgICAgICAgc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS50b3AgPSBcIjBweFwiO1xuICAgICAgICBzY2FubmVyUGF1c2VkVWlFbGVtZW50LnN0eWxlLnpJbmRleCA9IFwiMVwiO1xuICAgICAgICBzY2FubmVyUGF1c2VkVWlFbGVtZW50LnN0eWxlLmJhY2tncm91bmQgPSBcInJnYmEoOSwgOSwgOSwgMC40NilcIjtcbiAgICAgICAgc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS5jb2xvciA9IFwiI0ZGRUNFQ1wiO1xuICAgICAgICBzY2FubmVyUGF1c2VkVWlFbGVtZW50LnN0eWxlLnRleHRBbGlnbiA9IFwiY2VudGVyXCI7XG4gICAgICAgIHNjYW5uZXJQYXVzZWRVaUVsZW1lbnQuc3R5bGUud2lkdGggPSBcIjEwMCVcIjtcbiAgICAgICAgcm9vdEVsZW1lbnQuYXBwZW5kQ2hpbGQoc2Nhbm5lclBhdXNlZFVpRWxlbWVudCk7XG4gICAgICAgIHRoaXMuc2Nhbm5lclBhdXNlZFVpRWxlbWVudCA9IHNjYW5uZXJQYXVzZWRVaUVsZW1lbnQ7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuc2NhbkNvbnRleHQgPSBmdW5jdGlvbiAocXJDb2RlU3VjY2Vzc0NhbGxiYWNrLCBxckNvZGVFcnJvckNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlTWFuYWdlclByb3h5LmlzUGF1c2VkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnFyY29kZS5kZWNvZGVBc3luYyh0aGlzLmNhbnZhc0VsZW1lbnQpXG4gICAgICAgICAgICAudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgICBxckNvZGVTdWNjZXNzQ2FsbGJhY2socmVzdWx0LnRleHQsIEh0bWw1UXJjb2RlUmVzdWx0RmFjdG9yeS5jcmVhdGVGcm9tUXJjb2RlUmVzdWx0KHJlc3VsdCkpO1xuICAgICAgICAgICAgX3RoaXMucG9zc2libHlVcGRhdGVTaGFkZXJzKHRydWUpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgX3RoaXMucG9zc2libHlVcGRhdGVTaGFkZXJzKGZhbHNlKTtcbiAgICAgICAgICAgIHZhciBlcnJvck1lc3NhZ2UgPSBIdG1sNVFyY29kZVN0cmluZ3MuY29kZVBhcnNlRXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgcXJDb2RlRXJyb3JDYWxsYmFjayhlcnJvck1lc3NhZ2UsIEh0bWw1UXJjb2RlRXJyb3JGYWN0b3J5LmNyZWF0ZUZyb20oZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmZvcmV2ZXJTY2FuID0gZnVuY3Rpb24gKGludGVybmFsQ29uZmlnLCBxckNvZGVTdWNjZXNzQ2FsbGJhY2ssIHFyQ29kZUVycm9yQ2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCF0aGlzLnNob3VsZFNjYW4pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMucmVuZGVyZWRDYW1lcmEpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdmlkZW9FbGVtZW50ID0gdGhpcy5yZW5kZXJlZENhbWVyYS5nZXRTdXJmYWNlKCk7XG4gICAgICAgIHZhciB3aWR0aFJhdGlvID0gdmlkZW9FbGVtZW50LnZpZGVvV2lkdGggLyB2aWRlb0VsZW1lbnQuY2xpZW50V2lkdGg7XG4gICAgICAgIHZhciBoZWlnaHRSYXRpbyA9IHZpZGVvRWxlbWVudC52aWRlb0hlaWdodCAvIHZpZGVvRWxlbWVudC5jbGllbnRIZWlnaHQ7XG4gICAgICAgIGlmICghdGhpcy5xclJlZ2lvbikge1xuICAgICAgICAgICAgdGhyb3cgXCJxclJlZ2lvbiB1bmRlZmluZWQgd2hlbiBsb2NhbE1lZGlhU3RyZWFtIGlzIHJlYWR5LlwiO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzV2lkdGhPZmZzZXQgPSB0aGlzLnFyUmVnaW9uLndpZHRoICogd2lkdGhSYXRpbztcbiAgICAgICAgdmFyIHNIZWlnaHRPZmZzZXQgPSB0aGlzLnFyUmVnaW9uLmhlaWdodCAqIGhlaWdodFJhdGlvO1xuICAgICAgICB2YXIgc3hPZmZzZXQgPSB0aGlzLnFyUmVnaW9uLnggKiB3aWR0aFJhdGlvO1xuICAgICAgICB2YXIgc3lPZmZzZXQgPSB0aGlzLnFyUmVnaW9uLnkgKiBoZWlnaHRSYXRpbztcbiAgICAgICAgdGhpcy5jb250ZXh0LmRyYXdJbWFnZSh2aWRlb0VsZW1lbnQsIHN4T2Zmc2V0LCBzeU9mZnNldCwgc1dpZHRoT2Zmc2V0LCBzSGVpZ2h0T2Zmc2V0LCAwLCAwLCB0aGlzLnFyUmVnaW9uLndpZHRoLCB0aGlzLnFyUmVnaW9uLmhlaWdodCk7XG4gICAgICAgIHZhciB0cmlnZ2VyTmV4dFNjYW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5mb3JldmVyU2NhblRpbWVvdXQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5mb3JldmVyU2NhbihpbnRlcm5hbENvbmZpZywgcXJDb2RlU3VjY2Vzc0NhbGxiYWNrLCBxckNvZGVFcnJvckNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0sIF90aGlzLmdldFRpbWVvdXRGcHMoaW50ZXJuYWxDb25maWcuZnBzKSk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc2NhbkNvbnRleHQocXJDb2RlU3VjY2Vzc0NhbGxiYWNrLCBxckNvZGVFcnJvckNhbGxiYWNrKVxuICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKGlzU3VjY2Vzc2Z1bGwpIHtcbiAgICAgICAgICAgIGlmICghaXNTdWNjZXNzZnVsbCAmJiBpbnRlcm5hbENvbmZpZy5kaXNhYmxlRmxpcCAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIF90aGlzLmNvbnRleHQudHJhbnNsYXRlKF90aGlzLmNvbnRleHQuY2FudmFzLndpZHRoLCAwKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5jb250ZXh0LnNjYWxlKC0xLCAxKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5zY2FuQ29udGV4dChxckNvZGVTdWNjZXNzQ2FsbGJhY2ssIHFyQ29kZUVycm9yQ2FsbGJhY2spXG4gICAgICAgICAgICAgICAgICAgIC5maW5hbGx5KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlck5leHRTY2FuKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0cmlnZ2VyTmV4dFNjYW4oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICBfdGhpcy5sb2dnZXIubG9nRXJyb3IoXCJFcnJvciBoYXBwZW5kIHdoaWxlIHNjYW5uaW5nIGNvbnRleHRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgdHJpZ2dlck5leHRTY2FuKCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmNyZWF0ZVZpZGVvQ29uc3RyYWludHMgPSBmdW5jdGlvbiAoY2FtZXJhSWRPckNvbmZpZykge1xuICAgICAgICBpZiAodHlwZW9mIGNhbWVyYUlkT3JDb25maWcgPT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgcmV0dXJuIHsgZGV2aWNlSWQ6IHsgZXhhY3Q6IGNhbWVyYUlkT3JDb25maWcgfSB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBjYW1lcmFJZE9yQ29uZmlnID09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgIHZhciBmYWNpbmdNb2RlS2V5ID0gXCJmYWNpbmdNb2RlXCI7XG4gICAgICAgICAgICB2YXIgZGV2aWNlSWRLZXkgPSBcImRldmljZUlkXCI7XG4gICAgICAgICAgICB2YXIgYWxsb3dlZEZhY2luZ01vZGVWYWx1ZXNfMSA9IHsgXCJ1c2VyXCI6IHRydWUsIFwiZW52aXJvbm1lbnRcIjogdHJ1ZSB9O1xuICAgICAgICAgICAgdmFyIGV4YWN0S2V5ID0gXCJleGFjdFwiO1xuICAgICAgICAgICAgdmFyIGlzVmFsaWRGYWNpbmdNb2RlVmFsdWUgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAodmFsdWUgaW4gYWxsb3dlZEZhY2luZ01vZGVWYWx1ZXNfMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwiY29uZmlnIGhhcyBpbnZhbGlkICdmYWNpbmdNb2RlJyB2YWx1ZSA9IFwiXG4gICAgICAgICAgICAgICAgICAgICAgICArIFwiJ1wiLmNvbmNhdCh2YWx1ZSwgXCInXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGNhbWVyYUlkT3JDb25maWcpO1xuICAgICAgICAgICAgaWYgKGtleXMubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgXCInY2FtZXJhSWRPckNvbmZpZycgb2JqZWN0IHNob3VsZCBoYXZlIGV4YWN0bHkgMSBrZXksXCJcbiAgICAgICAgICAgICAgICAgICAgKyBcIiBpZiBwYXNzZWQgYXMgYW4gb2JqZWN0LCBmb3VuZCBcIi5jb25jYXQoa2V5cy5sZW5ndGgsIFwiIGtleXNcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIga2V5ID0gT2JqZWN0LmtleXMoY2FtZXJhSWRPckNvbmZpZylbMF07XG4gICAgICAgICAgICBpZiAoa2V5ICE9PSBmYWNpbmdNb2RlS2V5ICYmIGtleSAhPT0gZGV2aWNlSWRLZXkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBcIk9ubHkgJ1wiLmNvbmNhdChmYWNpbmdNb2RlS2V5LCBcIicgYW5kICdcIikuY29uY2F0KGRldmljZUlkS2V5LCBcIicgXCIpXG4gICAgICAgICAgICAgICAgICAgICsgXCIgYXJlIHN1cHBvcnRlZCBmb3IgJ2NhbWVyYUlkT3JDb25maWcnXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoa2V5ID09PSBmYWNpbmdNb2RlS2V5KSB7XG4gICAgICAgICAgICAgICAgdmFyIGZhY2luZ01vZGUgPSBjYW1lcmFJZE9yQ29uZmlnLmZhY2luZ01vZGU7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBmYWNpbmdNb2RlID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVmFsaWRGYWNpbmdNb2RlVmFsdWUoZmFjaW5nTW9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IGZhY2luZ01vZGU6IGZhY2luZ01vZGUgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2YgZmFjaW5nTW9kZSA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChleGFjdEtleSBpbiBmYWNpbmdNb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWYWxpZEZhY2luZ01vZGVWYWx1ZShmYWNpbmdNb2RlW1wiXCIuY29uY2F0KGV4YWN0S2V5KV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjaW5nTW9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhhY3Q6IGZhY2luZ01vZGVbXCJcIi5jb25jYXQoZXhhY3RLZXkpXVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFwiJ2ZhY2luZ01vZGUnIHNob3VsZCBiZSBzdHJpbmcgb3Igb2JqZWN0IHdpdGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgXCIgXCIuY29uY2F0KGV4YWN0S2V5LCBcIiBhcyBrZXkuXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHlwZV8xID0gKHR5cGVvZiBmYWNpbmdNb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgXCJJbnZhbGlkIHR5cGUgb2YgJ2ZhY2luZ01vZGUnID0gXCIuY29uY2F0KHR5cGVfMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGRldmljZUlkID0gY2FtZXJhSWRPckNvbmZpZy5kZXZpY2VJZDtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRldmljZUlkID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgZGV2aWNlSWQ6IGRldmljZUlkIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBkZXZpY2VJZCA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChleGFjdEtleSBpbiBkZXZpY2VJZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXZpY2VJZDogeyBleGFjdDogZGV2aWNlSWRbXCJcIi5jb25jYXQoZXhhY3RLZXkpXSB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgXCInZGV2aWNlSWQnIHNob3VsZCBiZSBzdHJpbmcgb3Igb2JqZWN0IHdpdGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgXCIgXCIuY29uY2F0KGV4YWN0S2V5LCBcIiBhcyBrZXkuXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHlwZV8yID0gKHR5cGVvZiBkZXZpY2VJZCk7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwiSW52YWxpZCB0eXBlIG9mICdkZXZpY2VJZCcgPSBcIi5jb25jYXQodHlwZV8yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHR5cGUgPSAodHlwZW9mIGNhbWVyYUlkT3JDb25maWcpO1xuICAgICAgICB0aHJvdyBcIkludmFsaWQgdHlwZSBvZiAnY2FtZXJhSWRPckNvbmZpZycgPSBcIi5jb25jYXQodHlwZSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuY29tcHV0ZUNhbnZhc0RyYXdDb25maWcgPSBmdW5jdGlvbiAoaW1hZ2VXaWR0aCwgaW1hZ2VIZWlnaHQsIGNvbnRhaW5lcldpZHRoLCBjb250YWluZXJIZWlnaHQpIHtcbiAgICAgICAgaWYgKGltYWdlV2lkdGggPD0gY29udGFpbmVyV2lkdGhcbiAgICAgICAgICAgICYmIGltYWdlSGVpZ2h0IDw9IGNvbnRhaW5lckhlaWdodCkge1xuICAgICAgICAgICAgdmFyIHhvZmZzZXQgPSAoY29udGFpbmVyV2lkdGggLSBpbWFnZVdpZHRoKSAvIDI7XG4gICAgICAgICAgICB2YXIgeW9mZnNldCA9IChjb250YWluZXJIZWlnaHQgLSBpbWFnZUhlaWdodCkgLyAyO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB4OiB4b2Zmc2V0LFxuICAgICAgICAgICAgICAgIHk6IHlvZmZzZXQsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGltYWdlV2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBpbWFnZUhlaWdodFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBmb3JtZXJJbWFnZVdpZHRoID0gaW1hZ2VXaWR0aDtcbiAgICAgICAgICAgIHZhciBmb3JtZXJJbWFnZUhlaWdodCA9IGltYWdlSGVpZ2h0O1xuICAgICAgICAgICAgaWYgKGltYWdlV2lkdGggPiBjb250YWluZXJXaWR0aCkge1xuICAgICAgICAgICAgICAgIGltYWdlSGVpZ2h0ID0gKGNvbnRhaW5lcldpZHRoIC8gaW1hZ2VXaWR0aCkgKiBpbWFnZUhlaWdodDtcbiAgICAgICAgICAgICAgICBpbWFnZVdpZHRoID0gY29udGFpbmVyV2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaW1hZ2VIZWlnaHQgPiBjb250YWluZXJIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICBpbWFnZVdpZHRoID0gKGNvbnRhaW5lckhlaWdodCAvIGltYWdlSGVpZ2h0KSAqIGltYWdlV2lkdGg7XG4gICAgICAgICAgICAgICAgaW1hZ2VIZWlnaHQgPSBjb250YWluZXJIZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5sb2coXCJJbWFnZSBkb3duc2FtcGxlZCBmcm9tIFwiXG4gICAgICAgICAgICAgICAgKyBcIlwiLmNvbmNhdChmb3JtZXJJbWFnZVdpZHRoLCBcIlhcIikuY29uY2F0KGZvcm1lckltYWdlSGVpZ2h0KVxuICAgICAgICAgICAgICAgICsgXCIgdG8gXCIuY29uY2F0KGltYWdlV2lkdGgsIFwiWFwiKS5jb25jYXQoaW1hZ2VIZWlnaHQsIFwiLlwiKSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb21wdXRlQ2FudmFzRHJhd0NvbmZpZyhpbWFnZVdpZHRoLCBpbWFnZUhlaWdodCwgY29udGFpbmVyV2lkdGgsIGNvbnRhaW5lckhlaWdodCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5jbGVhckVsZW1lbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlTWFuYWdlclByb3h5LmlzU2Nhbm5pbmcoKSkge1xuICAgICAgICAgICAgdGhyb3cgXCJDYW5ub3QgY2xlYXIgd2hpbGUgc2NhbiBpcyBvbmdvaW5nLCBjbG9zZSBpdCBmaXJzdC5cIjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZWxlbWVudElkKTtcbiAgICAgICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gXCJcIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLnBvc3NpYmx5VXBkYXRlU2hhZGVycyA9IGZ1bmN0aW9uIChxck1hdGNoKSB7XG4gICAgICAgIGlmICh0aGlzLnFyTWF0Y2ggPT09IHFyTWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5oYXNCb3JkZXJTaGFkZXJzXG4gICAgICAgICAgICAmJiB0aGlzLmJvcmRlclNoYWRlcnNcbiAgICAgICAgICAgICYmIHRoaXMuYm9yZGVyU2hhZGVycy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoaXMuYm9yZGVyU2hhZGVycy5mb3JFYWNoKGZ1bmN0aW9uIChzaGFkZXIpIHtcbiAgICAgICAgICAgICAgICBzaGFkZXIuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gcXJNYXRjaFxuICAgICAgICAgICAgICAgICAgICA/IENvbnN0YW50cy5CT1JERVJfU0hBREVSX01BVENIX0NPTE9SXG4gICAgICAgICAgICAgICAgICAgIDogQ29uc3RhbnRzLkJPUkRFUl9TSEFERVJfREVGQVVMVF9DT0xPUjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucXJNYXRjaCA9IHFyTWF0Y2g7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUucG9zc2libHlDbG9zZUxhc3RTY2FuSW1hZ2VGaWxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5sYXN0U2NhbkltYWdlRmlsZSkge1xuICAgICAgICAgICAgVVJMLnJldm9rZU9iamVjdFVSTCh0aGlzLmxhc3RTY2FuSW1hZ2VGaWxlKTtcbiAgICAgICAgICAgIHRoaXMubGFzdFNjYW5JbWFnZUZpbGUgPSBudWxsO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuY3JlYXRlQ2FudmFzRWxlbWVudCA9IGZ1bmN0aW9uICh3aWR0aCwgaGVpZ2h0LCBjdXN0b21JZCkge1xuICAgICAgICB2YXIgY2FudmFzV2lkdGggPSB3aWR0aDtcbiAgICAgICAgdmFyIGNhbnZhc0hlaWdodCA9IGhlaWdodDtcbiAgICAgICAgdmFyIGNhbnZhc0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiY2FudmFzXCIpO1xuICAgICAgICBjYW52YXNFbGVtZW50LnN0eWxlLndpZHRoID0gXCJcIi5jb25jYXQoY2FudmFzV2lkdGgsIFwicHhcIik7XG4gICAgICAgIGNhbnZhc0VsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gXCJcIi5jb25jYXQoY2FudmFzSGVpZ2h0LCBcInB4XCIpO1xuICAgICAgICBjYW52YXNFbGVtZW50LnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgY2FudmFzRWxlbWVudC5pZCA9IGlzTnVsbE9yVW5kZWZpbmVkKGN1c3RvbUlkKVxuICAgICAgICAgICAgPyBcInFyLWNhbnZhc1wiIDogY3VzdG9tSWQ7XG4gICAgICAgIHJldHVybiBjYW52YXNFbGVtZW50O1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFNoYWRlZFJlZ2lvbkJvdW5kcyA9IGZ1bmN0aW9uICh3aWR0aCwgaGVpZ2h0LCBxcmJveFNpemUpIHtcbiAgICAgICAgaWYgKHFyYm94U2l6ZS53aWR0aCA+IHdpZHRoIHx8IHFyYm94U2l6ZS5oZWlnaHQgPiBoZWlnaHQpIHtcbiAgICAgICAgICAgIHRocm93IFwiJ2NvbmZpZy5xcmJveCcgZGltZW5zaW9ucyBzaG91bGQgbm90IGJlIGdyZWF0ZXIgdGhhbiB0aGUgXCJcbiAgICAgICAgICAgICAgICArIFwiZGltZW5zaW9ucyBvZiB0aGUgcm9vdCBIVE1MIGVsZW1lbnQuXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHg6ICh3aWR0aCAtIHFyYm94U2l6ZS53aWR0aCkgLyAyLFxuICAgICAgICAgICAgeTogKGhlaWdodCAtIHFyYm94U2l6ZS5oZWlnaHQpIC8gMixcbiAgICAgICAgICAgIHdpZHRoOiBxcmJveFNpemUud2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQ6IHFyYm94U2l6ZS5oZWlnaHRcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5wb3NzaWJseUluc2VydFNoYWRpbmdFbGVtZW50ID0gZnVuY3Rpb24gKGVsZW1lbnQsIHdpZHRoLCBoZWlnaHQsIHFyYm94U2l6ZSkge1xuICAgICAgICBpZiAoKHdpZHRoIC0gcXJib3hTaXplLndpZHRoKSA8IDEgfHwgKGhlaWdodCAtIHFyYm94U2l6ZS5oZWlnaHQpIDwgMSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzaGFkaW5nRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHNoYWRpbmdFbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gXCJhYnNvbHV0ZVwiO1xuICAgICAgICB2YXIgcmlnaHRMZWZ0Qm9yZGVyU2l6ZSA9ICh3aWR0aCAtIHFyYm94U2l6ZS53aWR0aCkgLyAyO1xuICAgICAgICB2YXIgdG9wQm90dG9tQm9yZGVyU2l6ZSA9IChoZWlnaHQgLSBxcmJveFNpemUuaGVpZ2h0KSAvIDI7XG4gICAgICAgIHNoYWRpbmdFbGVtZW50LnN0eWxlLmJvcmRlckxlZnRcbiAgICAgICAgICAgID0gXCJcIi5jb25jYXQocmlnaHRMZWZ0Qm9yZGVyU2l6ZSwgXCJweCBzb2xpZCByZ2JhKDAsIDAsIDAsIDAuNDgpXCIpO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS5ib3JkZXJSaWdodFxuICAgICAgICAgICAgPSBcIlwiLmNvbmNhdChyaWdodExlZnRCb3JkZXJTaXplLCBcInB4IHNvbGlkIHJnYmEoMCwgMCwgMCwgMC40OClcIik7XG4gICAgICAgIHNoYWRpbmdFbGVtZW50LnN0eWxlLmJvcmRlclRvcFxuICAgICAgICAgICAgPSBcIlwiLmNvbmNhdCh0b3BCb3R0b21Cb3JkZXJTaXplLCBcInB4IHNvbGlkIHJnYmEoMCwgMCwgMCwgMC40OClcIik7XG4gICAgICAgIHNoYWRpbmdFbGVtZW50LnN0eWxlLmJvcmRlckJvdHRvbVxuICAgICAgICAgICAgPSBcIlwiLmNvbmNhdCh0b3BCb3R0b21Cb3JkZXJTaXplLCBcInB4IHNvbGlkIHJnYmEoMCwgMCwgMCwgMC40OClcIik7XG4gICAgICAgIHNoYWRpbmdFbGVtZW50LnN0eWxlLmJveFNpemluZyA9IFwiYm9yZGVyLWJveFwiO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS50b3AgPSBcIjBweFwiO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS5ib3R0b20gPSBcIjBweFwiO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS5sZWZ0ID0gXCIwcHhcIjtcbiAgICAgICAgc2hhZGluZ0VsZW1lbnQuc3R5bGUucmlnaHQgPSBcIjBweFwiO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5pZCA9IFwiXCIuY29uY2F0KENvbnN0YW50cy5TSEFERURfUkVHSU9OX0VMRU1FTlRfSUQpO1xuICAgICAgICBpZiAoKHdpZHRoIC0gcXJib3hTaXplLndpZHRoKSA8IDExXG4gICAgICAgICAgICB8fCAoaGVpZ2h0IC0gcXJib3hTaXplLmhlaWdodCkgPCAxMSkge1xuICAgICAgICAgICAgdGhpcy5oYXNCb3JkZXJTaGFkZXJzID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgc21hbGxTaXplID0gNTtcbiAgICAgICAgICAgIHZhciBsYXJnZVNpemUgPSA0MDtcbiAgICAgICAgICAgIHRoaXMuaW5zZXJ0U2hhZGVyQm9yZGVycyhzaGFkaW5nRWxlbWVudCwgbGFyZ2VTaXplLCBzbWFsbFNpemUsIC1zbWFsbFNpemUsIG51bGwsIDAsIHRydWUpO1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRTaGFkZXJCb3JkZXJzKHNoYWRpbmdFbGVtZW50LCBsYXJnZVNpemUsIHNtYWxsU2l6ZSwgLXNtYWxsU2l6ZSwgbnVsbCwgMCwgZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRTaGFkZXJCb3JkZXJzKHNoYWRpbmdFbGVtZW50LCBsYXJnZVNpemUsIHNtYWxsU2l6ZSwgbnVsbCwgLXNtYWxsU2l6ZSwgMCwgdHJ1ZSk7XG4gICAgICAgICAgICB0aGlzLmluc2VydFNoYWRlckJvcmRlcnMoc2hhZGluZ0VsZW1lbnQsIGxhcmdlU2l6ZSwgc21hbGxTaXplLCBudWxsLCAtc21hbGxTaXplLCAwLCBmYWxzZSk7XG4gICAgICAgICAgICB0aGlzLmluc2VydFNoYWRlckJvcmRlcnMoc2hhZGluZ0VsZW1lbnQsIHNtYWxsU2l6ZSwgbGFyZ2VTaXplICsgc21hbGxTaXplLCAtc21hbGxTaXplLCBudWxsLCAtc21hbGxTaXplLCB0cnVlKTtcbiAgICAgICAgICAgIHRoaXMuaW5zZXJ0U2hhZGVyQm9yZGVycyhzaGFkaW5nRWxlbWVudCwgc21hbGxTaXplLCBsYXJnZVNpemUgKyBzbWFsbFNpemUsIG51bGwsIC1zbWFsbFNpemUsIC1zbWFsbFNpemUsIHRydWUpO1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRTaGFkZXJCb3JkZXJzKHNoYWRpbmdFbGVtZW50LCBzbWFsbFNpemUsIGxhcmdlU2l6ZSArIHNtYWxsU2l6ZSwgLXNtYWxsU2l6ZSwgbnVsbCwgLXNtYWxsU2l6ZSwgZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRTaGFkZXJCb3JkZXJzKHNoYWRpbmdFbGVtZW50LCBzbWFsbFNpemUsIGxhcmdlU2l6ZSArIHNtYWxsU2l6ZSwgbnVsbCwgLXNtYWxsU2l6ZSwgLXNtYWxsU2l6ZSwgZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy5oYXNCb3JkZXJTaGFkZXJzID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbGVtZW50LmFwcGVuZChzaGFkaW5nRWxlbWVudCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuaW5zZXJ0U2hhZGVyQm9yZGVycyA9IGZ1bmN0aW9uIChzaGFkZXJFbGVtLCB3aWR0aCwgaGVpZ2h0LCB0b3AsIGJvdHRvbSwgc2lkZSwgaXNMZWZ0KSB7XG4gICAgICAgIHZhciBlbGVtID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgZWxlbS5zdHlsZS5wb3NpdGlvbiA9IFwiYWJzb2x1dGVcIjtcbiAgICAgICAgZWxlbS5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSBDb25zdGFudHMuQk9SREVSX1NIQURFUl9ERUZBVUxUX0NPTE9SO1xuICAgICAgICBlbGVtLnN0eWxlLndpZHRoID0gXCJcIi5jb25jYXQod2lkdGgsIFwicHhcIik7XG4gICAgICAgIGVsZW0uc3R5bGUuaGVpZ2h0ID0gXCJcIi5jb25jYXQoaGVpZ2h0LCBcInB4XCIpO1xuICAgICAgICBpZiAodG9wICE9PSBudWxsKSB7XG4gICAgICAgICAgICBlbGVtLnN0eWxlLnRvcCA9IFwiXCIuY29uY2F0KHRvcCwgXCJweFwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYm90dG9tICE9PSBudWxsKSB7XG4gICAgICAgICAgICBlbGVtLnN0eWxlLmJvdHRvbSA9IFwiXCIuY29uY2F0KGJvdHRvbSwgXCJweFwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNMZWZ0KSB7XG4gICAgICAgICAgICBlbGVtLnN0eWxlLmxlZnQgPSBcIlwiLmNvbmNhdChzaWRlLCBcInB4XCIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZWxlbS5zdHlsZS5yaWdodCA9IFwiXCIuY29uY2F0KHNpZGUsIFwicHhcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmJvcmRlclNoYWRlcnMpIHtcbiAgICAgICAgICAgIHRoaXMuYm9yZGVyU2hhZGVycyA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYm9yZGVyU2hhZGVycy5wdXNoKGVsZW0pO1xuICAgICAgICBzaGFkZXJFbGVtLmFwcGVuZENoaWxkKGVsZW0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLnNob3dQYXVzZWRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNjYW5uZXJQYXVzZWRVaUVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRocm93IFwiW2ludGVybmFsIGVycm9yXSBzY2FubmVyIHBhdXNlZCBVSSBlbGVtZW50IG5vdCBmb3VuZFwiO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gXCJibG9ja1wiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmhpZGVQYXVzZWRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNjYW5uZXJQYXVzZWRVaUVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRocm93IFwiW2ludGVybmFsIGVycm9yXSBzY2FubmVyIHBhdXNlZCBVSSBlbGVtZW50IG5vdCBmb3VuZFwiO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuZ2V0VGltZW91dEZwcyA9IGZ1bmN0aW9uIChmcHMpIHtcbiAgICAgICAgcmV0dXJuIDEwMDAgLyBmcHM7XG4gICAgfTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGU7XG59KCkpO1xuZXhwb3J0IHsgSHRtbDVRcmNvZGUgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWh0bWw1LXFyY29kZS5qcy5tYXAiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/html5-qrcode.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/image-assets.js":
+/*!*******************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/image-assets.js ***!
+  \*******************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   ASSET_CAMERA_SCAN: () => (/* binding */ ASSET_CAMERA_SCAN),\n/* harmony export */   ASSET_CLOSE_ICON_16PX: () => (/* binding */ ASSET_CLOSE_ICON_16PX),\n/* harmony export */   ASSET_FILE_SCAN: () => (/* binding */ ASSET_FILE_SCAN),\n/* harmony export */   ASSET_INFO_ICON_16PX: () => (/* binding */ ASSET_INFO_ICON_16PX)\n/* harmony export */ });\nvar SVG_XML_PREFIX = \"data:image/svg+xml;base64,\";\nvar ASSET_CAMERA_SCAN = SVG_XML_PREFIX + \"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzNzEuNjQzIDM3MS42NDMiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDM3MS42NDMgMzcxLjY0MyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBhdGggZD0iTTEwNS4wODQgMzguMjcxaDE2My43Njh2MjBIMTA1LjA4NHoiLz48cGF0aCBkPSJNMzExLjU5NiAxOTAuMTg5Yy03LjQ0MS05LjM0Ny0xOC40MDMtMTYuMjA2LTMyLjc0My0yMC41MjJWMzBjMC0xNi41NDItMTMuNDU4LTMwLTMwLTMwSDEyNS4wODRjLTE2LjU0MiAwLTMwIDEzLjQ1OC0zMCAzMHYxMjAuMTQzaC04LjI5NmMtMTYuNTQyIDAtMzAgMTMuNDU4LTMwIDMwdjEuMzMzYTI5LjgwNCAyOS44MDQgMCAwIDAgNC42MDMgMTUuOTM5Yy03LjM0IDUuNDc0LTEyLjEwMyAxNC4yMjEtMTIuMTAzIDI0LjA2MXYxLjMzM2MwIDkuODQgNC43NjMgMTguNTg3IDEyLjEwMyAyNC4wNjJhMjkuODEgMjkuODEgMCAwIDAtNC42MDMgMTUuOTM4djEuMzMzYzAgMTYuNTQyIDEzLjQ1OCAzMCAzMCAzMGg4LjMyNGMuNDI3IDExLjYzMSA3LjUwMyAyMS41ODcgMTcuNTM0IDI2LjE3Ny45MzEgMTAuNTAzIDQuMDg0IDMwLjE4NyAxNC43NjggNDUuNTM3YTkuOTg4IDkuOTg4IDAgMCAwIDguMjE2IDQuMjg4IDkuOTU4IDkuOTU4IDAgMCAwIDUuNzA0LTEuNzkzYzQuNTMzLTMuMTU1IDUuNjUtOS4zODggMi40OTUtMTMuOTIxLTYuNzk4LTkuNzY3LTkuNjAyLTIyLjYwOC0xMC43Ni0zMS40aDgyLjY4NWMuMjcyLjQxNC41NDUuODE4LjgxNSAxLjIxIDMuMTQyIDQuNTQxIDkuMzcyIDUuNjc5IDEzLjkxMyAyLjUzNCA0LjU0Mi0zLjE0MiA1LjY3Ny05LjM3MSAyLjUzNS0xMy45MTMtMTEuOTE5LTE3LjIyOS04Ljc4Ny0zNS44ODQgOS41ODEtNTcuMDEyIDMuMDY3LTIuNjUyIDEyLjMwNy0xMS43MzIgMTEuMjE3LTI0LjAzMy0uODI4LTkuMzQzLTcuMTA5LTE3LjE5NC0xOC42NjktMjMuMzM3YTkuODU3IDkuODU3IDAgMCAwLTEuMDYxLS40ODZjLS40NjYtLjE4Mi0xMS40MDMtNC41NzktOS43NDEtMTUuNzA2IDEuMDA3LTYuNzM3IDE0Ljc2OC04LjI3MyAyMy43NjYtNy42NjYgMjMuMTU2IDEuNTY5IDM5LjY5OCA3LjgwMyA0Ny44MzYgMTguMDI2IDUuNzUyIDcuMjI1IDcuNjA3IDE2LjYyMyA1LjY3MyAyOC43MzMtLjQxMyAyLjU4NS0uODI0IDUuMjQxLTEuMjQ1IDcuOTU5LTUuNzU2IDM3LjE5NC0xMi45MTkgODMuNDgzLTQ5Ljg3IDExNC42NjEtNC4yMjEgMy41NjEtNC43NTYgOS44Ny0xLjE5NCAxNC4wOTJhOS45OCA5Ljk4IDAgMCAwIDcuNjQ4IDMuNTUxIDkuOTU1IDkuOTU1IDAgMCAwIDYuNDQ0LTIuMzU4YzQyLjY3Mi0zNi4wMDUgNTAuODAyLTg4LjUzMyA1Ni43MzctMTI2Ljg4OC40MTUtMi42ODQuODIxLTUuMzA5IDEuMjI5LTcuODYzIDIuODM0LTE3LjcyMS0uNDU1LTMyLjY0MS05Ljc3Mi00NC4zNDV6bS0yMzIuMzA4IDQyLjYyYy01LjUxNCAwLTEwLTQuNDg2LTEwLTEwdi0xLjMzM2MwLTUuNTE0IDQuNDg2LTEwIDEwLTEwaDE1djIxLjMzM2gtMTV6bS0yLjUtNTIuNjY2YzAtNS41MTQgNC40ODYtMTAgMTAtMTBoNy41djIxLjMzM2gtNy41Yy01LjUxNCAwLTEwLTQuNDg2LTEwLTEwdi0xLjMzM3ptMTcuNSA5My45OTloLTcuNWMtNS41MTQgMC0xMC00LjQ4Ni0xMC0xMHYtMS4zMzNjMC01LjUxNCA0LjQ4Ni0xMCAxMC0xMGg3LjV2MjEuMzMzem0zMC43OTYgMjguODg3Yy01LjUxNCAwLTEwLTQuNDg2LTEwLTEwdi04LjI3MWg5MS40NTdjLS44NTEgNi42NjgtLjQzNyAxMi43ODcuNzMxIDE4LjI3MWgtODIuMTg4em03OS40ODItMTEzLjY5OGMtMy4xMjQgMjAuOTA2IDEyLjQyNyAzMy4xODQgMjEuNjI1IDM3LjA0IDUuNDQxIDIuOTY4IDcuNTUxIDUuNjQ3IDcuNzAxIDcuMTg4LjIxIDIuMTUtMi41NTMgNS42ODQtNC40NzcgNy4yNTEtLjQ4Mi4zNzgtLjkyOS44LTEuMzM1IDEuMjYxLTYuOTg3IDcuOTM2LTExLjk4MiAxNS41Mi0xNS40MzIgMjIuNjg4aC05Ny41NjRWMzBjMC01LjUxNCA0LjQ4Ni0xMCAxMC0xMGgxMjMuNzY5YzUuNTE0IDAgMTAgNC40ODYgMTAgMTB2MTM1LjU3OWMtMy4wMzItLjM4MS02LjE1LS42OTQtOS4zODktLjkxNC0yNS4xNTktMS42OTQtNDIuMzcgNy43NDgtNDQuODk4IDI0LjY2NnoiLz48cGF0aCBkPSJNMTc5LjEyOSA4My4xNjdoLTI0LjA2YTUgNSAwIDAgMC01IDV2MjQuMDYxYTUgNSAwIDAgMCA1IDVoMjQuMDZhNSA1IDAgMCAwIDUtNVY4OC4xNjdhNSA1IDAgMCAwLTUtNXpNMTcyLjYyOSAxNDIuODZoLTEyLjU2VjEzMC44YTUgNSAwIDEgMC0xMCAwdjE3LjA2MWE1IDUgMCAwIDAgNSA1aDE3LjU2YTUgNSAwIDEgMCAwLTEwLjAwMXpNMjE2LjU2OCA4My4xNjdoLTI0LjA2YTUgNSAwIDAgMC01IDV2MjQuMDYxYTUgNSAwIDAgMCA1IDVoMjQuMDZhNSA1IDAgMCAwIDUtNVY4OC4xNjdhNSA1IDAgMCAwLTUtNXptLTUgMjQuMDYxaC0xNC4wNlY5My4xNjdoMTQuMDZ2MTQuMDYxek0yMTEuNjY5IDEyNS45MzZIMTk3LjQxYTUgNSAwIDAgMC01IDV2MTQuMjU3YTUgNSAwIDAgMCA1IDVoMTQuMjU5YTUgNSAwIDAgMCA1LTV2LTE0LjI1N2E1IDUgMCAwIDAtNS01eiIvPjwvc3ZnPg==\";\nvar ASSET_FILE_SCAN = SVG_XML_PREFIX + \"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1OS4wMTggNTkuMDE4IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1OS4wMTggNTkuMDE4IiB4bWw6c3BhY2U9InByZXNlcnZlIj48cGF0aCBkPSJtNTguNzQxIDU0LjgwOS01Ljk2OS02LjI0NGExMC43NCAxMC43NCAwIDAgMCAyLjgyLTcuMjVjMC01Ljk1My00Ljg0My0xMC43OTYtMTAuNzk2LTEwLjc5NlMzNCAzNS4zNjEgMzQgNDEuMzE0IDM4Ljg0MyA1Mi4xMSA0NC43OTYgNTIuMTFjMi40NDEgMCA0LjY4OC0uODI0IDYuNDk5LTIuMTk2bDYuMDAxIDYuMjc3YS45OTguOTk4IDAgMCAwIDEuNDE0LjAzMiAxIDEgMCAwIDAgLjAzMS0xLjQxNHpNMzYgNDEuMzE0YzAtNC44NSAzLjk0Ni04Ljc5NiA4Ljc5Ni04Ljc5NnM4Ljc5NiAzLjk0NiA4Ljc5NiA4Ljc5Ni0zLjk0NiA4Ljc5Ni04Ljc5NiA4Ljc5NlMzNiA0Ni4xNjQgMzYgNDEuMzE0ek0xMC40MzEgMTYuMDg4YzAgMy4wNyAyLjQ5OCA1LjU2OCA1LjU2OSA1LjU2OHM1LjU2OS0yLjQ5OCA1LjU2OS01LjU2OGMwLTMuMDcxLTIuNDk4LTUuNTY5LTUuNTY5LTUuNTY5cy01LjU2OSAyLjQ5OC01LjU2OSA1LjU2OXptOS4xMzggMGMwIDEuOTY4LTEuNjAyIDMuNTY4LTMuNTY5IDMuNTY4cy0zLjU2OS0xLjYwMS0zLjU2OS0zLjU2OCAxLjYwMi0zLjU2OSAzLjU2OS0zLjU2OSAzLjU2OSAxLjYwMSAzLjU2OSAzLjU2OXoiLz48cGF0aCBkPSJtMzAuODgyIDI4Ljk4NyA5LjE4LTEwLjA1NCAxMS4yNjIgMTAuMzIzYTEgMSAwIDAgMCAxLjM1MS0xLjQ3NWwtMTItMTFhMSAxIDAgMCAwLTEuNDE0LjA2M2wtOS43OTQgMTAuNzI3LTQuNzQzLTQuNzQzYTEuMDAzIDEuMDAzIDAgMCAwLTEuMzY4LS4wNDRMNi4zMzkgMzcuNzY4YTEgMSAwIDEgMCAxLjMyMiAxLjUwMWwxNi4zMTMtMTQuMzYyIDcuMzE5IDcuMzE4YS45OTkuOTk5IDAgMSAwIDEuNDE0LTEuNDE0bC0xLjgyNS0xLjgyNHoiLz48cGF0aCBkPSJNMzAgNDYuNTE4SDJ2LTQyaDU0djI4YTEgMSAwIDEgMCAyIDB2LTI5YTEgMSAwIDAgMC0xLTFIMWExIDEgMCAwIDAtMSAxdjQ0YTEgMSAwIDAgMCAxIDFoMjlhMSAxIDAgMSAwIDAtMnoiLz48L3N2Zz4=\";\nvar ASSET_INFO_ICON_16PX = SVG_XML_PREFIX + \"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NjAgNDYwIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA0NjAgNDYwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48cGF0aCBkPSJNMjMwIDBDMTAyLjk3NSAwIDAgMTAyLjk3NSAwIDIzMHMxMDIuOTc1IDIzMCAyMzAgMjMwIDIzMC0xMDIuOTc0IDIzMC0yMzBTMzU3LjAyNSAwIDIzMCAwem0zOC4zMzMgMzc3LjM2YzAgOC42NzYtNy4wMzQgMTUuNzEtMTUuNzEgMTUuNzFoLTQzLjEwMWMtOC42NzYgMC0xNS43MS03LjAzNC0xNS43MS0xNS43MVYyMDIuNDc3YzAtOC42NzYgNy4wMzMtMTUuNzEgMTUuNzEtMTUuNzFoNDMuMTAxYzguNjc2IDAgMTUuNzEgNy4wMzMgMTUuNzEgMTUuNzFWMzc3LjM2ek0yMzAgMTU3Yy0yMS41MzkgMC0zOS0xNy40NjEtMzktMzlzMTcuNDYxLTM5IDM5LTM5IDM5IDE3LjQ2MSAzOSAzOS0xNy40NjEgMzktMzkgMzl6Ii8+PC9zdmc+\";\nvar ASSET_CLOSE_ICON_16PX = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAQgAAAEIBarqQRAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAE1SURBVDiNfdI7S0NBEAXgLya1otFgpbYSbISAgpXYi6CmiH9KCAiChaVga6OiWPgfRDQ+0itaGVNosXtluWwcuMzePfM4M3sq8lbHBubwg1dc4m1E/J/N4ghDPOIsfk/4xiEao5KX0McFljN4C9d4QTPXuY99jP3DsIoDPGM6BY5i5yI5R7O4q+ImFkJY2DCh3cAH2klyB+9J1xUMMAG7eCh1a+Mr+k48b5diXrFVwwLuS+BJ9MfR7+G0FHOHhTHhnXNWS87VDF4pcnfQK4Ep7XScNLmPTZgURNKKYENYWDpzW1BhscS1WHS8CDgURFJQrWcoF3c13KKbgg1BYQfy8xZWEzTTw1QZbAoKu8FqJnktdu5hcVSHmchiILzzuaDQvjBzV2m8yohCE1jHfPx/xhU+y4G/D75ELlRJsSYAAAAASUVORK5CYII=\";\n//# sourceMappingURL=image-assets.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9pbWFnZS1hc3NldHMuanMuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL2ltYWdlLWFzc2V0cy5qcz8xYzhkIl0sInNvdXJjZXNDb250ZW50IjpbInZhciBTVkdfWE1MX1BSRUZJWCA9IFwiZGF0YTppbWFnZS9zdmcreG1sO2Jhc2U2NCxcIjtcbmV4cG9ydCB2YXIgQVNTRVRfQ0FNRVJBX1NDQU4gPSBTVkdfWE1MX1BSRUZJWCArIFwiUEhOMlp5QjRiV3h1Y3owaWFIUjBjRG92TDNkM2R5NTNNeTV2Y21jdk1qQXdNQzl6ZG1jaUlIWnBaWGRDYjNnOUlqQWdNQ0F6TnpFdU5qUXpJRE0zTVM0Mk5ETWlJSE4wZVd4bFBTSmxibUZpYkdVdFltRmphMmR5YjNWdVpEcHVaWGNnTUNBd0lETTNNUzQyTkRNZ016Y3hMalkwTXlJZ2VHMXNPbk53WVdObFBTSndjbVZ6WlhKMlpTSStQSEJoZEdnZ1pEMGlUVEV3TlM0d09EUWdNemd1TWpjeGFERTJNeTQzTmpoMk1qQklNVEExTGpBNE5Ib2lMejQ4Y0dGMGFDQmtQU0pOTXpFeExqVTVOaUF4T1RBdU1UZzVZeTAzTGpRME1TMDVMak0wTnkweE9DNDBNRE10TVRZdU1qQTJMVE15TGpjME15MHlNQzQxTWpKV016QmpNQzB4Tmk0MU5ESXRNVE11TkRVNExUTXdMVE13TFRNd1NERXlOUzR3T0RSakxURTJMalUwTWlBd0xUTXdJREV6TGpRMU9DMHpNQ0F6TUhZeE1qQXVNVFF6YUMwNExqSTVObU10TVRZdU5UUXlJREF0TXpBZ01UTXVORFU0TFRNd0lETXdkakV1TXpNellUSTVMamd3TkNBeU9TNDRNRFFnTUNBd0lEQWdOQzQyTURNZ01UVXVPVE01WXkwM0xqTTBJRFV1TkRjMExURXlMakV3TXlBeE5DNHlNakV0TVRJdU1UQXpJREkwTGpBMk1YWXhMak16TTJNd0lEa3VPRFFnTkM0M05qTWdNVGd1TlRnM0lERXlMakV3TXlBeU5DNHdOakpoTWprdU9ERWdNamt1T0RFZ01DQXdJREF0TkM0Mk1ETWdNVFV1T1RNNGRqRXVNek16WXpBZ01UWXVOVFF5SURFekxqUTFPQ0F6TUNBek1DQXpNR2c0TGpNeU5HTXVOREkzSURFeExqWXpNU0EzTGpVd015QXlNUzQxT0RjZ01UY3VOVE0wSURJMkxqRTNOeTQ1TXpFZ01UQXVOVEF6SURRdU1EZzBJRE13TGpFNE55QXhOQzQzTmpnZ05EVXVOVE0zWVRrdU9UZzRJRGt1T1RnNElEQWdNQ0F3SURndU1qRTJJRFF1TWpnNElEa3VPVFU0SURrdU9UVTRJREFnTUNBd0lEVXVOekEwTFRFdU56a3pZelF1TlRNekxUTXVNVFUxSURVdU5qVXRPUzR6T0RnZ01pNDBPVFV0TVRNdU9USXhMVFl1TnprNExUa3VOelkzTFRrdU5qQXlMVEl5TGpZd09DMHhNQzQzTmkwek1TNDBhRGd5TGpZNE5XTXVNamN5TGpReE5DNDFORFV1T0RFNExqZ3hOU0F4TGpJeElETXVNVFF5SURRdU5UUXhJRGt1TXpjeUlEVXVOamM1SURFekxqa3hNeUF5TGpVek5DQTBMalUwTWkwekxqRTBNaUExTGpZM055MDVMak0zTVNBeUxqVXpOUzB4TXk0NU1UTXRNVEV1T1RFNUxURTNMakl5T1MwNExqYzROeTB6TlM0NE9EUWdPUzQxT0RFdE5UY3VNREV5SURNdU1EWTNMVEl1TmpVeUlERXlMak13TnkweE1TNDNNeklnTVRFdU1qRTNMVEkwTGpBek15MHVPREk0TFRrdU16UXpMVGN1TVRBNUxURTNMakU1TkMweE9DNDJOamt0TWpNdU16TTNZVGt1T0RVM0lEa3VPRFUzSURBZ01DQXdMVEV1TURZeExTNDBPRFpqTFM0ME5qWXRMakU0TWkweE1TNDBNRE10TkM0MU56a3RPUzQzTkRFdE1UVXVOekEySURFdU1EQTNMVFl1TnpNM0lERTBMamMyT0MwNExqSTNNeUF5TXk0M05qWXROeTQyTmpZZ01qTXVNVFUySURFdU5UWTVJRE01TGpZNU9DQTNMamd3TXlBME55NDRNellnTVRndU1ESTJJRFV1TnpVeUlEY3VNakkxSURjdU5qQTNJREUyTGpZeU15QTFMalkzTXlBeU9DNDNNek10TGpReE15QXlMalU0TlMwdU9ESTBJRFV1TWpReExURXVNalExSURjdU9UVTVMVFV1TnpVMklETTNMakU1TkMweE1pNDVNVGtnT0RNdU5EZ3pMVFE1TGpnM0lERXhOQzQyTmpFdE5DNHlNakVnTXk0MU5qRXROQzQzTlRZZ09TNDROeTB4TGpFNU5DQXhOQzR3T1RKaE9TNDVPQ0E1TGprNElEQWdNQ0F3SURjdU5qUTRJRE11TlRVeElEa3VPVFUxSURrdU9UVTFJREFnTUNBd0lEWXVORFEwTFRJdU16VTRZelF5TGpZM01pMHpOaTR3TURVZ05UQXVPREF5TFRnNExqVXpNeUExTmk0M016Y3RNVEkyTGpnNE9DNDBNVFV0TWk0Mk9EUXVPREl4TFRVdU16QTVJREV1TWpJNUxUY3VPRFl6SURJdU9ETTBMVEUzTGpjeU1TMHVORFUxTFRNeUxqWTBNUzA1TGpjM01pMDBOQzR6TkRWNmJTMHlNekl1TXpBNElEUXlMall5WXkwMUxqVXhOQ0F3TFRFd0xUUXVORGcyTFRFd0xURXdkaTB4TGpNek0yTXdMVFV1TlRFMElEUXVORGcyTFRFd0lERXdMVEV3YURFMWRqSXhMak16TTJndE1UVjZiUzB5TGpVdE5USXVOalkyWXpBdE5TNDFNVFFnTkM0ME9EWXRNVEFnTVRBdE1UQm9OeTQxZGpJeExqTXpNMmd0Tnk0MVl5MDFMalV4TkNBd0xURXdMVFF1TkRnMkxURXdMVEV3ZGkweExqTXpNM3B0TVRjdU5TQTVNeTQ1T1Rsb0xUY3VOV010TlM0MU1UUWdNQzB4TUMwMExqUTROaTB4TUMweE1IWXRNUzR6TXpOak1DMDFMalV4TkNBMExqUTROaTB4TUNBeE1DMHhNR2czTGpWMk1qRXVNek16ZW0wek1DNDNPVFlnTWpndU9EZzNZeTAxTGpVeE5DQXdMVEV3TFRRdU5EZzJMVEV3TFRFd2RpMDRMakkzTVdnNU1TNDBOVGRqTFM0NE5URWdOaTQyTmpndExqUXpOeUF4TWk0M09EY3VOek14SURFNExqSTNNV2d0T0RJdU1UZzRlbTAzT1M0ME9ESXRNVEV6TGpZNU9HTXRNeTR4TWpRZ01qQXVPVEEySURFeUxqUXlOeUF6TXk0eE9EUWdNakV1TmpJMUlETTNMakEwSURVdU5EUXhJREl1T1RZNElEY3VOVFV4SURVdU5qUTNJRGN1TnpBeElEY3VNVGc0TGpJeElESXVNVFV0TWk0MU5UTWdOUzQyT0RRdE5DNDBOemNnTnk0eU5URXRMalE0TWk0ek56Z3RMamt5T1M0NExURXVNek0xSURFdU1qWXhMVFl1T1RnM0lEY3VPVE0yTFRFeExqazRNaUF4TlM0MU1pMHhOUzQwTXpJZ01qSXVOamc0YUMwNU55NDFOalJXTXpCak1DMDFMalV4TkNBMExqUTROaTB4TUNBeE1DMHhNR2d4TWpNdU56WTVZelV1TlRFMElEQWdNVEFnTkM0ME9EWWdNVEFnTVRCMk1UTTFMalUzT1dNdE15NHdNekl0TGpNNE1TMDJMakUxTFM0Mk9UUXRPUzR6T0RrdExqa3hOQzB5TlM0eE5Ua3RNUzQyT1RRdE5ESXVNemNnTnk0M05EZ3RORFF1T0RrNElESTBMalkyTm5vaUx6NDhjR0YwYUNCa1BTSk5NVGM1TGpFeU9TQTRNeTR4Tmpkb0xUSTBMakEyWVRVZ05TQXdJREFnTUMwMUlEVjJNalF1TURZeFlUVWdOU0F3SURBZ01DQTFJRFZvTWpRdU1EWmhOU0ExSURBZ01DQXdJRFV0TlZZNE9DNHhOamRoTlNBMUlEQWdNQ0F3TFRVdE5YcE5NVGN5TGpZeU9TQXhOREl1T0Rab0xURXlMalUyVmpFek1DNDRZVFVnTlNBd0lERWdNQzB4TUNBd2RqRTNMakEyTVdFMUlEVWdNQ0F3SURBZ05TQTFhREUzTGpVMllUVWdOU0F3SURFZ01DQXdMVEV3TGpBd01YcE5NakUyTGpVMk9DQTRNeTR4Tmpkb0xUSTBMakEyWVRVZ05TQXdJREFnTUMwMUlEVjJNalF1TURZeFlUVWdOU0F3SURBZ01DQTFJRFZvTWpRdU1EWmhOU0ExSURBZ01DQXdJRFV0TlZZNE9DNHhOamRoTlNBMUlEQWdNQ0F3TFRVdE5YcHRMVFVnTWpRdU1EWXhhQzB4TkM0d05sWTVNeTR4Tmpkb01UUXVNRFoyTVRRdU1EWXhlazB5TVRFdU5qWTVJREV5TlM0NU16WklNVGszTGpReFlUVWdOU0F3SURBZ01DMDFJRFYyTVRRdU1qVTNZVFVnTlNBd0lEQWdNQ0ExSURWb01UUXVNalU1WVRVZ05TQXdJREFnTUNBMUxUVjJMVEUwTGpJMU4yRTFJRFVnTUNBd0lEQXROUzAxZWlJdlBqd3ZjM1puUGc9PVwiO1xuZXhwb3J0IHZhciBBU1NFVF9GSUxFX1NDQU4gPSBTVkdfWE1MX1BSRUZJWCArIFwiUEhOMlp5QjRiV3h1Y3owaWFIUjBjRG92TDNkM2R5NTNNeTV2Y21jdk1qQXdNQzl6ZG1jaUlIWnBaWGRDYjNnOUlqQWdNQ0ExT1M0d01UZ2dOVGt1TURFNElpQnpkSGxzWlQwaVpXNWhZbXhsTFdKaFkydG5jbTkxYm1RNmJtVjNJREFnTUNBMU9TNHdNVGdnTlRrdU1ERTRJaUI0Yld3NmMzQmhZMlU5SW5CeVpYTmxjblpsSWo0OGNHRjBhQ0JrUFNKdE5UZ3VOelF4SURVMExqZ3dPUzAxTGprMk9TMDJMakkwTkdFeE1DNDNOQ0F4TUM0M05DQXdJREFnTUNBeUxqZ3lMVGN1TWpWak1DMDFMamsxTXkwMExqZzBNeTB4TUM0M09UWXRNVEF1TnprMkxURXdMamM1TmxNek5DQXpOUzR6TmpFZ016UWdOREV1TXpFMElETTRMamcwTXlBMU1pNHhNU0EwTkM0M09UWWdOVEl1TVRGak1pNDBOREVnTUNBMExqWTRPQzB1T0RJMElEWXVORGs1TFRJdU1UazJiRFl1TURBeElEWXVNamMzWVM0NU9UZ3VPVGs0SURBZ01DQXdJREV1TkRFMExqQXpNaUF4SURFZ01DQXdJREFnTGpBek1TMHhMalF4TkhwTk16WWdOREV1TXpFMFl6QXROQzQ0TlNBekxqazBOaTA0TGpjNU5pQTRMamM1TmkwNExqYzVObk00TGpjNU5pQXpMamswTmlBNExqYzVOaUE0TGpjNU5pMHpMamswTmlBNExqYzVOaTA0TGpjNU5pQTRMamM1TmxNek5pQTBOaTR4TmpRZ016WWdOREV1TXpFMGVrMHhNQzQwTXpFZ01UWXVNRGc0WXpBZ015NHdOeUF5TGpRNU9DQTFMalUyT0NBMUxqVTJPU0ExTGpVMk9ITTFMalUyT1MweUxqUTVPQ0ExTGpVMk9TMDFMalUyT0dNd0xUTXVNRGN4TFRJdU5EazRMVFV1TlRZNUxUVXVOVFk1TFRVdU5UWTVjeTAxTGpVMk9TQXlMalE1T0MwMUxqVTJPU0ExTGpVMk9YcHRPUzR4TXpnZ01HTXdJREV1T1RZNExURXVOakF5SURNdU5UWTRMVE11TlRZNUlETXVOVFk0Y3kwekxqVTJPUzB4TGpZd01TMHpMalUyT1MwekxqVTJPQ0F4TGpZd01pMHpMalUyT1NBekxqVTJPUzB6TGpVMk9TQXpMalUyT1NBeExqWXdNU0F6TGpVMk9TQXpMalUyT1hvaUx6NDhjR0YwYUNCa1BTSnRNekF1T0RneUlESTRMams0TnlBNUxqRTRMVEV3TGpBMU5DQXhNUzR5TmpJZ01UQXVNekl6WVRFZ01TQXdJREFnTUNBeExqTTFNUzB4TGpRM05Xd3RNVEl0TVRGaE1TQXhJREFnTUNBd0xURXVOREUwTGpBMk0yd3RPUzQzT1RRZ01UQXVOekkzTFRRdU56UXpMVFF1TnpRellURXVNREF6SURFdU1EQXpJREFnTUNBd0xURXVNelk0TFM0d05EUk1OaTR6TXprZ016Y3VOelk0WVRFZ01TQXdJREVnTUNBeExqTXlNaUF4TGpVd01Xd3hOaTR6TVRNdE1UUXVNell5SURjdU16RTVJRGN1TXpFNFlTNDVPVGt1T1RrNUlEQWdNU0F3SURFdU5ERTBMVEV1TkRFMGJDMHhMamd5TlMweExqZ3lOSG9pTHo0OGNHRjBhQ0JrUFNKTk16QWdORFl1TlRFNFNESjJMVFF5YURVMGRqSTRZVEVnTVNBd0lERWdNQ0F5SURCMkxUSTVZVEVnTVNBd0lEQWdNQzB4TFRGSU1XRXhJREVnTUNBd0lEQXRNU0F4ZGpRMFlURWdNU0F3SURBZ01DQXhJREZvTWpsaE1TQXhJREFnTVNBd0lEQXRNbm9pTHo0OEwzTjJaejQ9XCI7XG5leHBvcnQgdmFyIEFTU0VUX0lORk9fSUNPTl8xNlBYID0gU1ZHX1hNTF9QUkVGSVggKyBcIlBITjJaeUI0Yld4dWN6MGlhSFIwY0RvdkwzZDNkeTUzTXk1dmNtY3ZNakF3TUM5emRtY2lJSFpwWlhkQ2IzZzlJakFnTUNBME5qQWdORFl3SWlCemRIbHNaVDBpWlc1aFlteGxMV0poWTJ0bmNtOTFibVE2Ym1WM0lEQWdNQ0EwTmpBZ05EWXdJaUI0Yld3NmMzQmhZMlU5SW5CeVpYTmxjblpsSWo0OGNHRjBhQ0JrUFNKTk1qTXdJREJETVRBeUxqazNOU0F3SURBZ01UQXlMamszTlNBd0lESXpNSE14TURJdU9UYzFJREl6TUNBeU16QWdNak13SURJek1DMHhNREl1T1RjMElESXpNQzB5TXpCVE16VTNMakF5TlNBd0lESXpNQ0F3ZW0wek9DNHpNek1nTXpjM0xqTTJZekFnT0M0Mk56WXROeTR3TXpRZ01UVXVOekV0TVRVdU56RWdNVFV1TnpGb0xUUXpMakV3TVdNdE9DNDJOellnTUMweE5TNDNNUzAzTGpBek5DMHhOUzQzTVMweE5TNDNNVll5TURJdU5EYzNZekF0T0M0Mk56WWdOeTR3TXpNdE1UVXVOekVnTVRVdU56RXRNVFV1TnpGb05ETXVNVEF4WXpndU5qYzJJREFnTVRVdU56RWdOeTR3TXpNZ01UVXVOekVnTVRVdU56RldNemMzTGpNMmVrMHlNekFnTVRVM1l5MHlNUzQxTXprZ01DMHpPUzB4Tnk0ME5qRXRNemt0TXpsek1UY3VORFl4TFRNNUlETTVMVE01SURNNUlERTNMalEyTVNBek9TQXpPUzB4Tnk0ME5qRWdNemt0TXprZ016bDZJaTgrUEM5emRtYytcIjtcbmV4cG9ydCB2YXIgQVNTRVRfQ0xPU0VfSUNPTl8xNlBYID0gXCJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUJBQUFBQVFDQVlBQUFBZjgvOWhBQUFBQkhOQ1NWUUlDQWdJZkFoa2lBQUFBQWx3U0ZsekFBQUFRZ0FBQUVJQmFycVFSQUFBQUJsMFJWaDBVMjltZEhkaGNtVUFkM2QzTG1sdWEzTmpZWEJsTG05eVo1dnVQQm9BQUFFMVNVUkJWRGlOZmRJN1MwTkJFQVhnTHlhMW90RmdwYllTYklTQWdwWFlpNkNtaUg5S0NBaUNoYVZnYTZPaVdQZ2ZSRFErMGl0YUdWTm9zWHRsdVd3Y3VNemVQZk00TTNzcThsYkhCdWJ3ZzFkYzRtMUUvSi9ONGdoRFBPSXNmay80eGlFYW81S1gwTWNGbGpONEM5ZDRRVFBYdVk5OWpQM0RzSW9EUEdNNkJZNWk1eUk1UjdPNHErSW1Ga0pZMkRDaDNjQUgya2x5Qis5SjF4VU1NQUc3ZUNoMWErTXIrazQ4YjVkaVhyRlZ3d0x1UytCSjlNZlI3K0cwRkhPSGhUSGhuWE5XUzg3VkRGNHBjbmZRSzRFcDdYU2NOTG1QVFpnVVJOS0tZRU5ZV0RwelcxQmhzY1MxV0hTOENEZ1VSRkpRcldjb0YzYzEzS0tiZ2cxQllRZnk4eFpXRXpUVHcxUVpiQW9LdThGcUpua3RkdTVoY1ZTSG1jaGlJTHp6dWFEUXZqQnpWMm04eW9oQ0UxakhmUHgveGhVK3k0Ry9ENzVFTGxSSnNTWUFBQUFBU1VWT1JLNUNZSUk9XCI7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pbWFnZS1hc3NldHMuanMubWFwIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/image-assets.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/index.js":
+/*!************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/index.js ***!
+  \************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   Html5Qrcode: () => (/* reexport safe */ _html5_qrcode__WEBPACK_IMPORTED_MODULE_0__.Html5Qrcode),\n/* harmony export */   Html5QrcodeScanType: () => (/* reexport safe */ _core__WEBPACK_IMPORTED_MODULE_2__.Html5QrcodeScanType),\n/* harmony export */   Html5QrcodeScanner: () => (/* reexport safe */ _html5_qrcode_scanner__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeScanner),\n/* harmony export */   Html5QrcodeScannerState: () => (/* reexport safe */ _state_manager__WEBPACK_IMPORTED_MODULE_3__.Html5QrcodeScannerState),\n/* harmony export */   Html5QrcodeSupportedFormats: () => (/* reexport safe */ _core__WEBPACK_IMPORTED_MODULE_2__.Html5QrcodeSupportedFormats)\n/* harmony export */ });\n/* harmony import */ var _html5_qrcode__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./html5-qrcode */ \"./node_modules/html5-qrcode/esm/html5-qrcode.js\");\n/* harmony import */ var _html5_qrcode_scanner__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./html5-qrcode-scanner */ \"./node_modules/html5-qrcode/esm/html5-qrcode-scanner.js\");\n/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./core */ \"./node_modules/html5-qrcode/esm/core.js\");\n/* harmony import */ var _state_manager__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./state-manager */ \"./node_modules/html5-qrcode/esm/state-manager.js\");\n\n\n\n\n\n//# sourceMappingURL=index.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9pbmRleC5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9pbmRleC5qcz83ODRlIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCB7IEh0bWw1UXJjb2RlIH0gZnJvbSBcIi4vaHRtbDUtcXJjb2RlXCI7XG5leHBvcnQgeyBIdG1sNVFyY29kZVNjYW5uZXIgfSBmcm9tIFwiLi9odG1sNS1xcmNvZGUtc2Nhbm5lclwiO1xuZXhwb3J0IHsgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzIH0gZnJvbSBcIi4vY29yZVwiO1xuZXhwb3J0IHsgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUgfSBmcm9tIFwiLi9zdGF0ZS1tYW5hZ2VyXCI7XG5leHBvcnQgeyBIdG1sNVFyY29kZVNjYW5UeXBlIH0gZnJvbSBcIi4vY29yZVwiO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW5kZXguanMubWFwIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/index.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/native-bar-code-detector.js":
+/*!*******************************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/native-bar-code-detector.js ***!
+  \*******************************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   BarcodeDetectorDelegate: () => (/* binding */ BarcodeDetectorDelegate)\n/* harmony export */ });\n/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core */ \"./node_modules/html5-qrcode/esm/core.js\");\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar __generator = (undefined && undefined.__generator) || function (thisArg, body) {\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n    return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n    function verb(n) { return function (v) { return step([n, v]); }; }\n    function step(op) {\n        if (f) throw new TypeError(\"Generator is already executing.\");\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\n            if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n            if (y = 0, t) op = [op[0] & 2, t.value];\n            switch (op[0]) {\n                case 0: case 1: t = op; break;\n                case 4: _.label++; return { value: op[1], done: false };\n                case 5: _.label++; y = op[1]; op = [0]; continue;\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\n                default:\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                    if (t[2]) _.ops.pop();\n                    _.trys.pop(); continue;\n            }\n            op = body.call(thisArg, _);\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n    }\n};\n\nvar BarcodeDetectorDelegate = (function () {\n    function BarcodeDetectorDelegate(requestedFormats, verbose, logger) {\n        this.formatMap = new Map([\n            [_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.QR_CODE, \"qr_code\"],\n            [_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.AZTEC, \"aztec\"],\n            [_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.CODABAR, \"codabar\"],\n            [_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.CODE_39, \"code_39\"],\n            [_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.CODE_93, \"code_93\"],\n            [_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.CODE_128, \"code_128\"],\n            [_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.DATA_MATRIX, \"data_matrix\"],\n            [_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.ITF, \"itf\"],\n            [_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.EAN_13, \"ean_13\"],\n            [_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.EAN_8, \"ean_8\"],\n            [_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.PDF_417, \"pdf417\"],\n            [_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.UPC_A, \"upc_a\"],\n            [_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeSupportedFormats.UPC_E, \"upc_e\"]\n        ]);\n        this.reverseFormatMap = this.createReverseFormatMap();\n        if (!BarcodeDetectorDelegate.isSupported()) {\n            throw \"Use html5qrcode.min.js without edit, Use \"\n                + \"BarcodeDetectorDelegate only if it isSupported();\";\n        }\n        this.verbose = verbose;\n        this.logger = logger;\n        var formats = this.createBarcodeDetectorFormats(requestedFormats);\n        this.detector = new BarcodeDetector(formats);\n        if (!this.detector) {\n            throw \"BarcodeDetector detector not supported\";\n        }\n    }\n    BarcodeDetectorDelegate.isSupported = function () {\n        if (!(\"BarcodeDetector\" in window)) {\n            return false;\n        }\n        var dummyDetector = new BarcodeDetector({ formats: [\"qr_code\"] });\n        return typeof dummyDetector !== \"undefined\";\n    };\n    BarcodeDetectorDelegate.prototype.decodeAsync = function (canvas) {\n        return __awaiter(this, void 0, void 0, function () {\n            var barcodes, largestBarcode;\n            return __generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0: return [4, this.detector.detect(canvas)];\n                    case 1:\n                        barcodes = _a.sent();\n                        if (!barcodes || barcodes.length === 0) {\n                            throw \"No barcode or QR code detected.\";\n                        }\n                        largestBarcode = this.selectLargestBarcode(barcodes);\n                        return [2, {\n                                text: largestBarcode.rawValue,\n                                format: _core__WEBPACK_IMPORTED_MODULE_0__.QrcodeResultFormat.create(this.toHtml5QrcodeSupportedFormats(largestBarcode.format)),\n                                debugData: this.createDebugData()\n                            }];\n                }\n            });\n        });\n    };\n    BarcodeDetectorDelegate.prototype.selectLargestBarcode = function (barcodes) {\n        var largestBarcode = null;\n        var maxArea = 0;\n        for (var _i = 0, barcodes_1 = barcodes; _i < barcodes_1.length; _i++) {\n            var barcode = barcodes_1[_i];\n            var area = barcode.boundingBox.width * barcode.boundingBox.height;\n            if (area > maxArea) {\n                maxArea = area;\n                largestBarcode = barcode;\n            }\n        }\n        if (!largestBarcode) {\n            throw \"No largest barcode found\";\n        }\n        return largestBarcode;\n    };\n    BarcodeDetectorDelegate.prototype.createBarcodeDetectorFormats = function (requestedFormats) {\n        var formats = [];\n        for (var _i = 0, requestedFormats_1 = requestedFormats; _i < requestedFormats_1.length; _i++) {\n            var requestedFormat = requestedFormats_1[_i];\n            if (this.formatMap.has(requestedFormat)) {\n                formats.push(this.formatMap.get(requestedFormat));\n            }\n            else {\n                this.logger.warn(\"\".concat(requestedFormat, \" is not supported by\")\n                    + \"BarcodeDetectorDelegate\");\n            }\n        }\n        return { formats: formats };\n    };\n    BarcodeDetectorDelegate.prototype.toHtml5QrcodeSupportedFormats = function (barcodeDetectorFormat) {\n        if (!this.reverseFormatMap.has(barcodeDetectorFormat)) {\n            throw \"reverseFormatMap doesn't have \".concat(barcodeDetectorFormat);\n        }\n        return this.reverseFormatMap.get(barcodeDetectorFormat);\n    };\n    BarcodeDetectorDelegate.prototype.createReverseFormatMap = function () {\n        var result = new Map();\n        this.formatMap.forEach(function (value, key, _) {\n            result.set(value, key);\n        });\n        return result;\n    };\n    BarcodeDetectorDelegate.prototype.createDebugData = function () {\n        return { decoderName: \"BarcodeDetector\" };\n    };\n    return BarcodeDetectorDelegate;\n}());\n\n//# sourceMappingURL=native-bar-code-detector.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9uYXRpdmUtYmFyLWNvZGUtZGV0ZWN0b3IuanMuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL25hdGl2ZS1iYXItY29kZS1kZXRlY3Rvci5qcz9kZTljIl0sInNvdXJjZXNDb250ZW50IjpbInZhciBfX2F3YWl0ZXIgPSAodGhpcyAmJiB0aGlzLl9fYXdhaXRlcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xuICAgIGZ1bmN0aW9uIGFkb3B0KHZhbHVlKSB7IHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUodmFsdWUpOyB9KTsgfVxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IGFkb3B0KHJlc3VsdC52YWx1ZSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XG4gICAgfSk7XG59O1xudmFyIF9fZ2VuZXJhdG9yID0gKHRoaXMgJiYgdGhpcy5fX2dlbmVyYXRvcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIGJvZHkpIHtcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xuICAgIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcbiAgICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xuICAgICAgICB3aGlsZSAoZyAmJiAoZyA9IDAsIG9wWzBdICYmIChfID0gMCkpLCBfKSB0cnkge1xuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xuICAgICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XG4gICAgfVxufTtcbmltcG9ydCB7IFFyY29kZVJlc3VsdEZvcm1hdCwgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzIH0gZnJvbSBcIi4vY29yZVwiO1xudmFyIEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZShyZXF1ZXN0ZWRGb3JtYXRzLCB2ZXJib3NlLCBsb2dnZXIpIHtcbiAgICAgICAgdGhpcy5mb3JtYXRNYXAgPSBuZXcgTWFwKFtcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUVJfQ09ERSwgXCJxcl9jb2RlXCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5BWlRFQywgXCJhenRlY1wiXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQ09EQUJBUiwgXCJjb2RhYmFyXCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzM5LCBcImNvZGVfMzlcIl0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfOTMsIFwiY29kZV85M1wiXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQ09ERV8xMjgsIFwiY29kZV8xMjhcIl0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkRBVEFfTUFUUklYLCBcImRhdGFfbWF0cml4XCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5JVEYsIFwiaXRmXCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5FQU5fMTMsIFwiZWFuXzEzXCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5FQU5fOCwgXCJlYW5fOFwiXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUERGXzQxNywgXCJwZGY0MTdcIl0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlVQQ19BLCBcInVwY19hXCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5VUENfRSwgXCJ1cGNfZVwiXVxuICAgICAgICBdKTtcbiAgICAgICAgdGhpcy5yZXZlcnNlRm9ybWF0TWFwID0gdGhpcy5jcmVhdGVSZXZlcnNlRm9ybWF0TWFwKCk7XG4gICAgICAgIGlmICghQmFyY29kZURldGVjdG9yRGVsZWdhdGUuaXNTdXBwb3J0ZWQoKSkge1xuICAgICAgICAgICAgdGhyb3cgXCJVc2UgaHRtbDVxcmNvZGUubWluLmpzIHdpdGhvdXQgZWRpdCwgVXNlIFwiXG4gICAgICAgICAgICAgICAgKyBcIkJhcmNvZGVEZXRlY3RvckRlbGVnYXRlIG9ubHkgaWYgaXQgaXNTdXBwb3J0ZWQoKTtcIjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnZlcmJvc2UgPSB2ZXJib3NlO1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlcjtcbiAgICAgICAgdmFyIGZvcm1hdHMgPSB0aGlzLmNyZWF0ZUJhcmNvZGVEZXRlY3RvckZvcm1hdHMocmVxdWVzdGVkRm9ybWF0cyk7XG4gICAgICAgIHRoaXMuZGV0ZWN0b3IgPSBuZXcgQmFyY29kZURldGVjdG9yKGZvcm1hdHMpO1xuICAgICAgICBpZiAoIXRoaXMuZGV0ZWN0b3IpIHtcbiAgICAgICAgICAgIHRocm93IFwiQmFyY29kZURldGVjdG9yIGRldGVjdG9yIG5vdCBzdXBwb3J0ZWRcIjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZS5pc1N1cHBvcnRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCEoXCJCYXJjb2RlRGV0ZWN0b3JcIiBpbiB3aW5kb3cpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGR1bW15RGV0ZWN0b3IgPSBuZXcgQmFyY29kZURldGVjdG9yKHsgZm9ybWF0czogW1wicXJfY29kZVwiXSB9KTtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBkdW1teURldGVjdG9yICE9PSBcInVuZGVmaW5lZFwiO1xuICAgIH07XG4gICAgQmFyY29kZURldGVjdG9yRGVsZWdhdGUucHJvdG90eXBlLmRlY29kZUFzeW5jID0gZnVuY3Rpb24gKGNhbnZhcykge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgYmFyY29kZXMsIGxhcmdlc3RCYXJjb2RlO1xuICAgICAgICAgICAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoX2EubGFiZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOiByZXR1cm4gWzQsIHRoaXMuZGV0ZWN0b3IuZGV0ZWN0KGNhbnZhcyldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBiYXJjb2RlcyA9IF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYmFyY29kZXMgfHwgYmFyY29kZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgXCJObyBiYXJjb2RlIG9yIFFSIGNvZGUgZGV0ZWN0ZWQuXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBsYXJnZXN0QmFyY29kZSA9IHRoaXMuc2VsZWN0TGFyZ2VzdEJhcmNvZGUoYmFyY29kZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ6IGxhcmdlc3RCYXJjb2RlLnJhd1ZhbHVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXQ6IFFyY29kZVJlc3VsdEZvcm1hdC5jcmVhdGUodGhpcy50b0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyhsYXJnZXN0QmFyY29kZS5mb3JtYXQpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVidWdEYXRhOiB0aGlzLmNyZWF0ZURlYnVnRGF0YSgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQmFyY29kZURldGVjdG9yRGVsZWdhdGUucHJvdG90eXBlLnNlbGVjdExhcmdlc3RCYXJjb2RlID0gZnVuY3Rpb24gKGJhcmNvZGVzKSB7XG4gICAgICAgIHZhciBsYXJnZXN0QmFyY29kZSA9IG51bGw7XG4gICAgICAgIHZhciBtYXhBcmVhID0gMDtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBiYXJjb2Rlc18xID0gYmFyY29kZXM7IF9pIDwgYmFyY29kZXNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBiYXJjb2RlID0gYmFyY29kZXNfMVtfaV07XG4gICAgICAgICAgICB2YXIgYXJlYSA9IGJhcmNvZGUuYm91bmRpbmdCb3gud2lkdGggKiBiYXJjb2RlLmJvdW5kaW5nQm94LmhlaWdodDtcbiAgICAgICAgICAgIGlmIChhcmVhID4gbWF4QXJlYSkge1xuICAgICAgICAgICAgICAgIG1heEFyZWEgPSBhcmVhO1xuICAgICAgICAgICAgICAgIGxhcmdlc3RCYXJjb2RlID0gYmFyY29kZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIWxhcmdlc3RCYXJjb2RlKSB7XG4gICAgICAgICAgICB0aHJvdyBcIk5vIGxhcmdlc3QgYmFyY29kZSBmb3VuZFwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsYXJnZXN0QmFyY29kZTtcbiAgICB9O1xuICAgIEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlLnByb3RvdHlwZS5jcmVhdGVCYXJjb2RlRGV0ZWN0b3JGb3JtYXRzID0gZnVuY3Rpb24gKHJlcXVlc3RlZEZvcm1hdHMpIHtcbiAgICAgICAgdmFyIGZvcm1hdHMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCByZXF1ZXN0ZWRGb3JtYXRzXzEgPSByZXF1ZXN0ZWRGb3JtYXRzOyBfaSA8IHJlcXVlc3RlZEZvcm1hdHNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciByZXF1ZXN0ZWRGb3JtYXQgPSByZXF1ZXN0ZWRGb3JtYXRzXzFbX2ldO1xuICAgICAgICAgICAgaWYgKHRoaXMuZm9ybWF0TWFwLmhhcyhyZXF1ZXN0ZWRGb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgZm9ybWF0cy5wdXNoKHRoaXMuZm9ybWF0TWFwLmdldChyZXF1ZXN0ZWRGb3JtYXQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLndhcm4oXCJcIi5jb25jYXQocmVxdWVzdGVkRm9ybWF0LCBcIiBpcyBub3Qgc3VwcG9ydGVkIGJ5XCIpXG4gICAgICAgICAgICAgICAgICAgICsgXCJCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBmb3JtYXRzOiBmb3JtYXRzIH07XG4gICAgfTtcbiAgICBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZS5wcm90b3R5cGUudG9IdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMgPSBmdW5jdGlvbiAoYmFyY29kZURldGVjdG9yRm9ybWF0KSB7XG4gICAgICAgIGlmICghdGhpcy5yZXZlcnNlRm9ybWF0TWFwLmhhcyhiYXJjb2RlRGV0ZWN0b3JGb3JtYXQpKSB7XG4gICAgICAgICAgICB0aHJvdyBcInJldmVyc2VGb3JtYXRNYXAgZG9lc24ndCBoYXZlIFwiLmNvbmNhdChiYXJjb2RlRGV0ZWN0b3JGb3JtYXQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnJldmVyc2VGb3JtYXRNYXAuZ2V0KGJhcmNvZGVEZXRlY3RvckZvcm1hdCk7XG4gICAgfTtcbiAgICBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZS5wcm90b3R5cGUuY3JlYXRlUmV2ZXJzZUZvcm1hdE1hcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5mb3JtYXRNYXAuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSwgXykge1xuICAgICAgICAgICAgcmVzdWx0LnNldCh2YWx1ZSwga2V5KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZS5wcm90b3R5cGUuY3JlYXRlRGVidWdEYXRhID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4geyBkZWNvZGVyTmFtZTogXCJCYXJjb2RlRGV0ZWN0b3JcIiB9O1xuICAgIH07XG4gICAgcmV0dXJuIEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlO1xufSgpKTtcbmV4cG9ydCB7IEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1uYXRpdmUtYmFyLWNvZGUtZGV0ZWN0b3IuanMubWFwIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/native-bar-code-detector.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/state-manager.js":
+/*!********************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/state-manager.js ***!
+  \********************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   Html5QrcodeScannerState: () => (/* binding */ Html5QrcodeScannerState),\n/* harmony export */   StateManagerFactory: () => (/* binding */ StateManagerFactory),\n/* harmony export */   StateManagerProxy: () => (/* binding */ StateManagerProxy)\n/* harmony export */ });\nvar Html5QrcodeScannerState;\n(function (Html5QrcodeScannerState) {\n    Html5QrcodeScannerState[Html5QrcodeScannerState[\"UNKNOWN\"] = 0] = \"UNKNOWN\";\n    Html5QrcodeScannerState[Html5QrcodeScannerState[\"NOT_STARTED\"] = 1] = \"NOT_STARTED\";\n    Html5QrcodeScannerState[Html5QrcodeScannerState[\"SCANNING\"] = 2] = \"SCANNING\";\n    Html5QrcodeScannerState[Html5QrcodeScannerState[\"PAUSED\"] = 3] = \"PAUSED\";\n})(Html5QrcodeScannerState || (Html5QrcodeScannerState = {}));\nvar StateManagerImpl = (function () {\n    function StateManagerImpl() {\n        this.state = Html5QrcodeScannerState.NOT_STARTED;\n        this.onGoingTransactionNewState = Html5QrcodeScannerState.UNKNOWN;\n    }\n    StateManagerImpl.prototype.directTransition = function (newState) {\n        this.failIfTransitionOngoing();\n        this.validateTransition(newState);\n        this.state = newState;\n    };\n    StateManagerImpl.prototype.startTransition = function (newState) {\n        this.failIfTransitionOngoing();\n        this.validateTransition(newState);\n        this.onGoingTransactionNewState = newState;\n        return this;\n    };\n    StateManagerImpl.prototype.execute = function () {\n        if (this.onGoingTransactionNewState\n            === Html5QrcodeScannerState.UNKNOWN) {\n            throw \"Transaction is already cancelled, cannot execute().\";\n        }\n        var tempNewState = this.onGoingTransactionNewState;\n        this.onGoingTransactionNewState = Html5QrcodeScannerState.UNKNOWN;\n        this.directTransition(tempNewState);\n    };\n    StateManagerImpl.prototype.cancel = function () {\n        if (this.onGoingTransactionNewState\n            === Html5QrcodeScannerState.UNKNOWN) {\n            throw \"Transaction is already cancelled, cannot cancel().\";\n        }\n        this.onGoingTransactionNewState = Html5QrcodeScannerState.UNKNOWN;\n    };\n    StateManagerImpl.prototype.getState = function () {\n        return this.state;\n    };\n    StateManagerImpl.prototype.failIfTransitionOngoing = function () {\n        if (this.onGoingTransactionNewState\n            !== Html5QrcodeScannerState.UNKNOWN) {\n            throw \"Cannot transition to a new state, already under transition\";\n        }\n    };\n    StateManagerImpl.prototype.validateTransition = function (newState) {\n        switch (this.state) {\n            case Html5QrcodeScannerState.UNKNOWN:\n                throw \"Transition from unknown is not allowed\";\n            case Html5QrcodeScannerState.NOT_STARTED:\n                this.failIfNewStateIs(newState, [Html5QrcodeScannerState.PAUSED]);\n                break;\n            case Html5QrcodeScannerState.SCANNING:\n                break;\n            case Html5QrcodeScannerState.PAUSED:\n                break;\n        }\n    };\n    StateManagerImpl.prototype.failIfNewStateIs = function (newState, disallowedStatesToTransition) {\n        for (var _i = 0, disallowedStatesToTransition_1 = disallowedStatesToTransition; _i < disallowedStatesToTransition_1.length; _i++) {\n            var disallowedState = disallowedStatesToTransition_1[_i];\n            if (newState === disallowedState) {\n                throw \"Cannot transition from \".concat(this.state, \" to \").concat(newState);\n            }\n        }\n    };\n    return StateManagerImpl;\n}());\nvar StateManagerProxy = (function () {\n    function StateManagerProxy(stateManager) {\n        this.stateManager = stateManager;\n    }\n    StateManagerProxy.prototype.startTransition = function (newState) {\n        return this.stateManager.startTransition(newState);\n    };\n    StateManagerProxy.prototype.directTransition = function (newState) {\n        this.stateManager.directTransition(newState);\n    };\n    StateManagerProxy.prototype.getState = function () {\n        return this.stateManager.getState();\n    };\n    StateManagerProxy.prototype.canScanFile = function () {\n        return this.stateManager.getState() === Html5QrcodeScannerState.NOT_STARTED;\n    };\n    StateManagerProxy.prototype.isScanning = function () {\n        return this.stateManager.getState() !== Html5QrcodeScannerState.NOT_STARTED;\n    };\n    StateManagerProxy.prototype.isStrictlyScanning = function () {\n        return this.stateManager.getState() === Html5QrcodeScannerState.SCANNING;\n    };\n    StateManagerProxy.prototype.isPaused = function () {\n        return this.stateManager.getState() === Html5QrcodeScannerState.PAUSED;\n    };\n    return StateManagerProxy;\n}());\n\nvar StateManagerFactory = (function () {\n    function StateManagerFactory() {\n    }\n    StateManagerFactory.create = function () {\n        return new StateManagerProxy(new StateManagerImpl());\n    };\n    return StateManagerFactory;\n}());\n\n//# sourceMappingURL=state-manager.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9zdGF0ZS1tYW5hZ2VyLmpzLmpzIiwibWFwcGluZ3MiOiI7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vc3RhdGUtbWFuYWdlci5qcz9kOTFiIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCB2YXIgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGU7XG4oZnVuY3Rpb24gKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlKSB7XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGVbSHRtbDVRcmNvZGVTY2FubmVyU3RhdGVbXCJVTktOT1dOXCJdID0gMF0gPSBcIlVOS05PV05cIjtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZVtIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZVtcIk5PVF9TVEFSVEVEXCJdID0gMV0gPSBcIk5PVF9TVEFSVEVEXCI7XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGVbSHRtbDVRcmNvZGVTY2FubmVyU3RhdGVbXCJTQ0FOTklOR1wiXSA9IDJdID0gXCJTQ0FOTklOR1wiO1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlW0h0bWw1UXJjb2RlU2Nhbm5lclN0YXRlW1wiUEFVU0VEXCJdID0gM10gPSBcIlBBVVNFRFwiO1xufSkoSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUgfHwgKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlID0ge30pKTtcbnZhciBTdGF0ZU1hbmFnZXJJbXBsID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBTdGF0ZU1hbmFnZXJJbXBsKCkge1xuICAgICAgICB0aGlzLnN0YXRlID0gSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuTk9UX1NUQVJURUQ7XG4gICAgICAgIHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGUgPSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOO1xuICAgIH1cbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5kaXJlY3RUcmFuc2l0aW9uID0gZnVuY3Rpb24gKG5ld1N0YXRlKSB7XG4gICAgICAgIHRoaXMuZmFpbElmVHJhbnNpdGlvbk9uZ29pbmcoKTtcbiAgICAgICAgdGhpcy52YWxpZGF0ZVRyYW5zaXRpb24obmV3U3RhdGUpO1xuICAgICAgICB0aGlzLnN0YXRlID0gbmV3U3RhdGU7XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5zdGFydFRyYW5zaXRpb24gPSBmdW5jdGlvbiAobmV3U3RhdGUpIHtcbiAgICAgICAgdGhpcy5mYWlsSWZUcmFuc2l0aW9uT25nb2luZygpO1xuICAgICAgICB0aGlzLnZhbGlkYXRlVHJhbnNpdGlvbihuZXdTdGF0ZSk7XG4gICAgICAgIHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGUgPSBuZXdTdGF0ZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5leGVjdXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5vbkdvaW5nVHJhbnNhY3Rpb25OZXdTdGF0ZVxuICAgICAgICAgICAgPT09IEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlVOS05PV04pIHtcbiAgICAgICAgICAgIHRocm93IFwiVHJhbnNhY3Rpb24gaXMgYWxyZWFkeSBjYW5jZWxsZWQsIGNhbm5vdCBleGVjdXRlKCkuXCI7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRlbXBOZXdTdGF0ZSA9IHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGU7XG4gICAgICAgIHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGUgPSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOO1xuICAgICAgICB0aGlzLmRpcmVjdFRyYW5zaXRpb24odGVtcE5ld1N0YXRlKTtcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlckltcGwucHJvdG90eXBlLmNhbmNlbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGVcbiAgICAgICAgICAgID09PSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOKSB7XG4gICAgICAgICAgICB0aHJvdyBcIlRyYW5zYWN0aW9uIGlzIGFscmVhZHkgY2FuY2VsbGVkLCBjYW5ub3QgY2FuY2VsKCkuXCI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vbkdvaW5nVHJhbnNhY3Rpb25OZXdTdGF0ZSA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlVOS05PV047XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5nZXRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGU7XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5mYWlsSWZUcmFuc2l0aW9uT25nb2luZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGVcbiAgICAgICAgICAgICE9PSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkNhbm5vdCB0cmFuc2l0aW9uIHRvIGEgbmV3IHN0YXRlLCBhbHJlYWR5IHVuZGVyIHRyYW5zaXRpb25cIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU3RhdGVNYW5hZ2VySW1wbC5wcm90b3R5cGUudmFsaWRhdGVUcmFuc2l0aW9uID0gZnVuY3Rpb24gKG5ld1N0YXRlKSB7XG4gICAgICAgIHN3aXRjaCAodGhpcy5zdGF0ZSkge1xuICAgICAgICAgICAgY2FzZSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOOlxuICAgICAgICAgICAgICAgIHRocm93IFwiVHJhbnNpdGlvbiBmcm9tIHVua25vd24gaXMgbm90IGFsbG93ZWRcIjtcbiAgICAgICAgICAgIGNhc2UgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuTk9UX1NUQVJURUQ6XG4gICAgICAgICAgICAgICAgdGhpcy5mYWlsSWZOZXdTdGF0ZUlzKG5ld1N0YXRlLCBbSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuUEFVU0VEXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlNDQU5OSU5HOlxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5QQVVTRUQ6XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlckltcGwucHJvdG90eXBlLmZhaWxJZk5ld1N0YXRlSXMgPSBmdW5jdGlvbiAobmV3U3RhdGUsIGRpc2FsbG93ZWRTdGF0ZXNUb1RyYW5zaXRpb24pIHtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBkaXNhbGxvd2VkU3RhdGVzVG9UcmFuc2l0aW9uXzEgPSBkaXNhbGxvd2VkU3RhdGVzVG9UcmFuc2l0aW9uOyBfaSA8IGRpc2FsbG93ZWRTdGF0ZXNUb1RyYW5zaXRpb25fMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBkaXNhbGxvd2VkU3RhdGUgPSBkaXNhbGxvd2VkU3RhdGVzVG9UcmFuc2l0aW9uXzFbX2ldO1xuICAgICAgICAgICAgaWYgKG5ld1N0YXRlID09PSBkaXNhbGxvd2VkU3RhdGUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBcIkNhbm5vdCB0cmFuc2l0aW9uIGZyb20gXCIuY29uY2F0KHRoaXMuc3RhdGUsIFwiIHRvIFwiKS5jb25jYXQobmV3U3RhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gU3RhdGVNYW5hZ2VySW1wbDtcbn0oKSk7XG52YXIgU3RhdGVNYW5hZ2VyUHJveHkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFN0YXRlTWFuYWdlclByb3h5KHN0YXRlTWFuYWdlcikge1xuICAgICAgICB0aGlzLnN0YXRlTWFuYWdlciA9IHN0YXRlTWFuYWdlcjtcbiAgICB9XG4gICAgU3RhdGVNYW5hZ2VyUHJveHkucHJvdG90eXBlLnN0YXJ0VHJhbnNpdGlvbiA9IGZ1bmN0aW9uIChuZXdTdGF0ZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZU1hbmFnZXIuc3RhcnRUcmFuc2l0aW9uKG5ld1N0YXRlKTtcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlclByb3h5LnByb3RvdHlwZS5kaXJlY3RUcmFuc2l0aW9uID0gZnVuY3Rpb24gKG5ld1N0YXRlKSB7XG4gICAgICAgIHRoaXMuc3RhdGVNYW5hZ2VyLmRpcmVjdFRyYW5zaXRpb24obmV3U3RhdGUpO1xuICAgIH07XG4gICAgU3RhdGVNYW5hZ2VyUHJveHkucHJvdG90eXBlLmdldFN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZU1hbmFnZXIuZ2V0U3RhdGUoKTtcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlclByb3h5LnByb3RvdHlwZS5jYW5TY2FuRmlsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGVNYW5hZ2VyLmdldFN0YXRlKCkgPT09IEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLk5PVF9TVEFSVEVEO1xuICAgIH07XG4gICAgU3RhdGVNYW5hZ2VyUHJveHkucHJvdG90eXBlLmlzU2Nhbm5pbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlTWFuYWdlci5nZXRTdGF0ZSgpICE9PSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5OT1RfU1RBUlRFRDtcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlclByb3h5LnByb3RvdHlwZS5pc1N0cmljdGx5U2Nhbm5pbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlTWFuYWdlci5nZXRTdGF0ZSgpID09PSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5TQ0FOTklORztcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlclByb3h5LnByb3RvdHlwZS5pc1BhdXNlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGVNYW5hZ2VyLmdldFN0YXRlKCkgPT09IEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlBBVVNFRDtcbiAgICB9O1xuICAgIHJldHVybiBTdGF0ZU1hbmFnZXJQcm94eTtcbn0oKSk7XG5leHBvcnQgeyBTdGF0ZU1hbmFnZXJQcm94eSB9O1xudmFyIFN0YXRlTWFuYWdlckZhY3RvcnkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFN0YXRlTWFuYWdlckZhY3RvcnkoKSB7XG4gICAgfVxuICAgIFN0YXRlTWFuYWdlckZhY3RvcnkuY3JlYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gbmV3IFN0YXRlTWFuYWdlclByb3h5KG5ldyBTdGF0ZU1hbmFnZXJJbXBsKCkpO1xuICAgIH07XG4gICAgcmV0dXJuIFN0YXRlTWFuYWdlckZhY3Rvcnk7XG59KCkpO1xuZXhwb3J0IHsgU3RhdGVNYW5hZ2VyRmFjdG9yeSB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c3RhdGUtbWFuYWdlci5qcy5tYXAiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/state-manager.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/storage.js":
+/*!**************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/storage.js ***!
+  \**************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   PersistedDataManager: () => (/* binding */ PersistedDataManager)\n/* harmony export */ });\nvar PersistedDataFactory = (function () {\n    function PersistedDataFactory() {\n    }\n    PersistedDataFactory.createDefault = function () {\n        return {\n            hasPermission: false,\n            lastUsedCameraId: null\n        };\n    };\n    return PersistedDataFactory;\n}());\nvar PersistedDataManager = (function () {\n    function PersistedDataManager() {\n        this.data = PersistedDataFactory.createDefault();\n        var data = localStorage.getItem(PersistedDataManager.LOCAL_STORAGE_KEY);\n        if (!data) {\n            this.reset();\n        }\n        else {\n            this.data = JSON.parse(data);\n        }\n    }\n    PersistedDataManager.prototype.hasCameraPermissions = function () {\n        return this.data.hasPermission;\n    };\n    PersistedDataManager.prototype.getLastUsedCameraId = function () {\n        return this.data.lastUsedCameraId;\n    };\n    PersistedDataManager.prototype.setHasPermission = function (hasPermission) {\n        this.data.hasPermission = hasPermission;\n        this.flush();\n    };\n    PersistedDataManager.prototype.setLastUsedCameraId = function (lastUsedCameraId) {\n        this.data.lastUsedCameraId = lastUsedCameraId;\n        this.flush();\n    };\n    PersistedDataManager.prototype.resetLastUsedCameraId = function () {\n        this.data.lastUsedCameraId = null;\n        this.flush();\n    };\n    PersistedDataManager.prototype.reset = function () {\n        this.data = PersistedDataFactory.createDefault();\n        this.flush();\n    };\n    PersistedDataManager.prototype.flush = function () {\n        localStorage.setItem(PersistedDataManager.LOCAL_STORAGE_KEY, JSON.stringify(this.data));\n    };\n    PersistedDataManager.LOCAL_STORAGE_KEY = \"HTML5_QRCODE_DATA\";\n    return PersistedDataManager;\n}());\n\n//# sourceMappingURL=storage.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9zdG9yYWdlLmpzLmpzIiwibWFwcGluZ3MiOiI7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL3N0b3JhZ2UuanM/Nzk4NCJdLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgUGVyc2lzdGVkRGF0YUZhY3RvcnkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFBlcnNpc3RlZERhdGFGYWN0b3J5KCkge1xuICAgIH1cbiAgICBQZXJzaXN0ZWREYXRhRmFjdG9yeS5jcmVhdGVEZWZhdWx0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaGFzUGVybWlzc2lvbjogZmFsc2UsXG4gICAgICAgICAgICBsYXN0VXNlZENhbWVyYUlkOiBudWxsXG4gICAgICAgIH07XG4gICAgfTtcbiAgICByZXR1cm4gUGVyc2lzdGVkRGF0YUZhY3Rvcnk7XG59KCkpO1xudmFyIFBlcnNpc3RlZERhdGFNYW5hZ2VyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBQZXJzaXN0ZWREYXRhTWFuYWdlcigpIHtcbiAgICAgICAgdGhpcy5kYXRhID0gUGVyc2lzdGVkRGF0YUZhY3RvcnkuY3JlYXRlRGVmYXVsdCgpO1xuICAgICAgICB2YXIgZGF0YSA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKFBlcnNpc3RlZERhdGFNYW5hZ2VyLkxPQ0FMX1NUT1JBR0VfS0VZKTtcbiAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmRhdGEgPSBKU09OLnBhcnNlKGRhdGEpO1xuICAgICAgICB9XG4gICAgfVxuICAgIFBlcnNpc3RlZERhdGFNYW5hZ2VyLnByb3RvdHlwZS5oYXNDYW1lcmFQZXJtaXNzaW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF0YS5oYXNQZXJtaXNzaW9uO1xuICAgIH07XG4gICAgUGVyc2lzdGVkRGF0YU1hbmFnZXIucHJvdG90eXBlLmdldExhc3RVc2VkQ2FtZXJhSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRhdGEubGFzdFVzZWRDYW1lcmFJZDtcbiAgICB9O1xuICAgIFBlcnNpc3RlZERhdGFNYW5hZ2VyLnByb3RvdHlwZS5zZXRIYXNQZXJtaXNzaW9uID0gZnVuY3Rpb24gKGhhc1Blcm1pc3Npb24pIHtcbiAgICAgICAgdGhpcy5kYXRhLmhhc1Blcm1pc3Npb24gPSBoYXNQZXJtaXNzaW9uO1xuICAgICAgICB0aGlzLmZsdXNoKCk7XG4gICAgfTtcbiAgICBQZXJzaXN0ZWREYXRhTWFuYWdlci5wcm90b3R5cGUuc2V0TGFzdFVzZWRDYW1lcmFJZCA9IGZ1bmN0aW9uIChsYXN0VXNlZENhbWVyYUlkKSB7XG4gICAgICAgIHRoaXMuZGF0YS5sYXN0VXNlZENhbWVyYUlkID0gbGFzdFVzZWRDYW1lcmFJZDtcbiAgICAgICAgdGhpcy5mbHVzaCgpO1xuICAgIH07XG4gICAgUGVyc2lzdGVkRGF0YU1hbmFnZXIucHJvdG90eXBlLnJlc2V0TGFzdFVzZWRDYW1lcmFJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kYXRhLmxhc3RVc2VkQ2FtZXJhSWQgPSBudWxsO1xuICAgICAgICB0aGlzLmZsdXNoKCk7XG4gICAgfTtcbiAgICBQZXJzaXN0ZWREYXRhTWFuYWdlci5wcm90b3R5cGUucmVzZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZGF0YSA9IFBlcnNpc3RlZERhdGFGYWN0b3J5LmNyZWF0ZURlZmF1bHQoKTtcbiAgICAgICAgdGhpcy5mbHVzaCgpO1xuICAgIH07XG4gICAgUGVyc2lzdGVkRGF0YU1hbmFnZXIucHJvdG90eXBlLmZsdXNoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShQZXJzaXN0ZWREYXRhTWFuYWdlci5MT0NBTF9TVE9SQUdFX0tFWSwgSlNPTi5zdHJpbmdpZnkodGhpcy5kYXRhKSk7XG4gICAgfTtcbiAgICBQZXJzaXN0ZWREYXRhTWFuYWdlci5MT0NBTF9TVE9SQUdFX0tFWSA9IFwiSFRNTDVfUVJDT0RFX0RBVEFcIjtcbiAgICByZXR1cm4gUGVyc2lzdGVkRGF0YU1hbmFnZXI7XG59KCkpO1xuZXhwb3J0IHsgUGVyc2lzdGVkRGF0YU1hbmFnZXIgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXN0b3JhZ2UuanMubWFwIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/storage.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/strings.js":
+/*!**************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/strings.js ***!
+  \**************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   Html5QrcodeScannerStrings: () => (/* binding */ Html5QrcodeScannerStrings),\n/* harmony export */   Html5QrcodeStrings: () => (/* binding */ Html5QrcodeStrings),\n/* harmony export */   LibraryInfoStrings: () => (/* binding */ LibraryInfoStrings)\n/* harmony export */ });\nvar Html5QrcodeStrings = (function () {\n    function Html5QrcodeStrings() {\n    }\n    Html5QrcodeStrings.codeParseError = function (exception) {\n        return \"QR code parse error, error = \".concat(exception);\n    };\n    Html5QrcodeStrings.errorGettingUserMedia = function (error) {\n        return \"Error getting userMedia, error = \".concat(error);\n    };\n    Html5QrcodeStrings.onlyDeviceSupportedError = function () {\n        return \"The device doesn't support navigator.mediaDevices , only \"\n            + \"supported cameraIdOrConfig in this case is deviceId parameter \"\n            + \"(string).\";\n    };\n    Html5QrcodeStrings.cameraStreamingNotSupported = function () {\n        return \"Camera streaming not supported by the browser.\";\n    };\n    Html5QrcodeStrings.unableToQuerySupportedDevices = function () {\n        return \"Unable to query supported devices, unknown error.\";\n    };\n    Html5QrcodeStrings.insecureContextCameraQueryError = function () {\n        return \"Camera access is only supported in secure context like https \"\n            + \"or localhost.\";\n    };\n    Html5QrcodeStrings.scannerPaused = function () {\n        return \"Scanner paused\";\n    };\n    return Html5QrcodeStrings;\n}());\n\nvar Html5QrcodeScannerStrings = (function () {\n    function Html5QrcodeScannerStrings() {\n    }\n    Html5QrcodeScannerStrings.scanningStatus = function () {\n        return \"Scanning\";\n    };\n    Html5QrcodeScannerStrings.idleStatus = function () {\n        return \"Idle\";\n    };\n    Html5QrcodeScannerStrings.errorStatus = function () {\n        return \"Error\";\n    };\n    Html5QrcodeScannerStrings.permissionStatus = function () {\n        return \"Permission\";\n    };\n    Html5QrcodeScannerStrings.noCameraFoundErrorStatus = function () {\n        return \"No Cameras\";\n    };\n    Html5QrcodeScannerStrings.lastMatch = function (decodedText) {\n        return \"Last Match: \".concat(decodedText);\n    };\n    Html5QrcodeScannerStrings.codeScannerTitle = function () {\n        return \"Code Scanner\";\n    };\n    Html5QrcodeScannerStrings.cameraPermissionTitle = function () {\n        return \"Request Camera Permissions\";\n    };\n    Html5QrcodeScannerStrings.cameraPermissionRequesting = function () {\n        return \"Requesting camera permissions...\";\n    };\n    Html5QrcodeScannerStrings.noCameraFound = function () {\n        return \"No camera found\";\n    };\n    Html5QrcodeScannerStrings.scanButtonStopScanningText = function () {\n        return \"Stop Scanning\";\n    };\n    Html5QrcodeScannerStrings.scanButtonStartScanningText = function () {\n        return \"Start Scanning\";\n    };\n    Html5QrcodeScannerStrings.torchOnButton = function () {\n        return \"Switch On Torch\";\n    };\n    Html5QrcodeScannerStrings.torchOffButton = function () {\n        return \"Switch Off Torch\";\n    };\n    Html5QrcodeScannerStrings.torchOnFailedMessage = function () {\n        return \"Failed to turn on torch\";\n    };\n    Html5QrcodeScannerStrings.torchOffFailedMessage = function () {\n        return \"Failed to turn off torch\";\n    };\n    Html5QrcodeScannerStrings.scanButtonScanningStarting = function () {\n        return \"Launching Camera...\";\n    };\n    Html5QrcodeScannerStrings.textIfCameraScanSelected = function () {\n        return \"Scan an Image File\";\n    };\n    Html5QrcodeScannerStrings.textIfFileScanSelected = function () {\n        return \"Scan using camera directly\";\n    };\n    Html5QrcodeScannerStrings.selectCamera = function () {\n        return \"Select Camera\";\n    };\n    Html5QrcodeScannerStrings.fileSelectionChooseImage = function () {\n        return \"Choose Image\";\n    };\n    Html5QrcodeScannerStrings.fileSelectionChooseAnother = function () {\n        return \"Choose Another\";\n    };\n    Html5QrcodeScannerStrings.fileSelectionNoImageSelected = function () {\n        return \"No image choosen\";\n    };\n    Html5QrcodeScannerStrings.anonymousCameraPrefix = function () {\n        return \"Anonymous Camera\";\n    };\n    Html5QrcodeScannerStrings.dragAndDropMessage = function () {\n        return \"Or drop an image to scan\";\n    };\n    Html5QrcodeScannerStrings.dragAndDropMessageOnlyImages = function () {\n        return \"Or drop an image to scan (other files not supported)\";\n    };\n    Html5QrcodeScannerStrings.zoom = function () {\n        return \"zoom\";\n    };\n    Html5QrcodeScannerStrings.loadingImage = function () {\n        return \"Loading image...\";\n    };\n    Html5QrcodeScannerStrings.cameraScanAltText = function () {\n        return \"Camera based scan\";\n    };\n    Html5QrcodeScannerStrings.fileScanAltText = function () {\n        return \"Fule based scan\";\n    };\n    return Html5QrcodeScannerStrings;\n}());\n\nvar LibraryInfoStrings = (function () {\n    function LibraryInfoStrings() {\n    }\n    LibraryInfoStrings.poweredBy = function () {\n        return \"Powered by \";\n    };\n    LibraryInfoStrings.reportIssues = function () {\n        return \"Report issues\";\n    };\n    return LibraryInfoStrings;\n}());\n\n//# sourceMappingURL=strings.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9zdHJpbmdzLmpzLmpzIiwibWFwcGluZ3MiOiI7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vc3RyaW5ncy5qcz8xNGEzIl0sInNvdXJjZXNDb250ZW50IjpbInZhciBIdG1sNVFyY29kZVN0cmluZ3MgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEh0bWw1UXJjb2RlU3RyaW5ncygpIHtcbiAgICB9XG4gICAgSHRtbDVRcmNvZGVTdHJpbmdzLmNvZGVQYXJzZUVycm9yID0gZnVuY3Rpb24gKGV4Y2VwdGlvbikge1xuICAgICAgICByZXR1cm4gXCJRUiBjb2RlIHBhcnNlIGVycm9yLCBlcnJvciA9IFwiLmNvbmNhdChleGNlcHRpb24pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTdHJpbmdzLmVycm9yR2V0dGluZ1VzZXJNZWRpYSA9IGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICByZXR1cm4gXCJFcnJvciBnZXR0aW5nIHVzZXJNZWRpYSwgZXJyb3IgPSBcIi5jb25jYXQoZXJyb3IpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTdHJpbmdzLm9ubHlEZXZpY2VTdXBwb3J0ZWRFcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiVGhlIGRldmljZSBkb2Vzbid0IHN1cHBvcnQgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcyAsIG9ubHkgXCJcbiAgICAgICAgICAgICsgXCJzdXBwb3J0ZWQgY2FtZXJhSWRPckNvbmZpZyBpbiB0aGlzIGNhc2UgaXMgZGV2aWNlSWQgcGFyYW1ldGVyIFwiXG4gICAgICAgICAgICArIFwiKHN0cmluZykuXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVN0cmluZ3MuY2FtZXJhU3RyZWFtaW5nTm90U3VwcG9ydGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJDYW1lcmEgc3RyZWFtaW5nIG5vdCBzdXBwb3J0ZWQgYnkgdGhlIGJyb3dzZXIuXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVN0cmluZ3MudW5hYmxlVG9RdWVyeVN1cHBvcnRlZERldmljZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlVuYWJsZSB0byBxdWVyeSBzdXBwb3J0ZWQgZGV2aWNlcywgdW5rbm93biBlcnJvci5cIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU3RyaW5ncy5pbnNlY3VyZUNvbnRleHRDYW1lcmFRdWVyeUVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJDYW1lcmEgYWNjZXNzIGlzIG9ubHkgc3VwcG9ydGVkIGluIHNlY3VyZSBjb250ZXh0IGxpa2UgaHR0cHMgXCJcbiAgICAgICAgICAgICsgXCJvciBsb2NhbGhvc3QuXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVN0cmluZ3Muc2Nhbm5lclBhdXNlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiU2Nhbm5lciBwYXVzZWRcIjtcbiAgICB9O1xuICAgIHJldHVybiBIdG1sNVFyY29kZVN0cmluZ3M7XG59KCkpO1xuZXhwb3J0IHsgSHRtbDVRcmNvZGVTdHJpbmdzIH07XG52YXIgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncyA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncygpIHtcbiAgICB9XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5zY2FubmluZ1N0YXR1cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiU2Nhbm5pbmdcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuaWRsZVN0YXR1cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiSWRsZVwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5lcnJvclN0YXR1cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiRXJyb3JcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MucGVybWlzc2lvblN0YXR1cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiUGVybWlzc2lvblwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5ub0NhbWVyYUZvdW5kRXJyb3JTdGF0dXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIk5vIENhbWVyYXNcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MubGFzdE1hdGNoID0gZnVuY3Rpb24gKGRlY29kZWRUZXh0KSB7XG4gICAgICAgIHJldHVybiBcIkxhc3QgTWF0Y2g6IFwiLmNvbmNhdChkZWNvZGVkVGV4dCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmNvZGVTY2FubmVyVGl0bGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkNvZGUgU2Nhbm5lclwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5jYW1lcmFQZXJtaXNzaW9uVGl0bGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlJlcXVlc3QgQ2FtZXJhIFBlcm1pc3Npb25zXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmNhbWVyYVBlcm1pc3Npb25SZXF1ZXN0aW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJSZXF1ZXN0aW5nIGNhbWVyYSBwZXJtaXNzaW9ucy4uLlwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5ub0NhbWVyYUZvdW5kID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJObyBjYW1lcmEgZm91bmRcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muc2NhbkJ1dHRvblN0b3BTY2FubmluZ1RleHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlN0b3AgU2Nhbm5pbmdcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muc2NhbkJ1dHRvblN0YXJ0U2Nhbm5pbmdUZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJTdGFydCBTY2FubmluZ1wiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50b3JjaE9uQnV0dG9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJTd2l0Y2ggT24gVG9yY2hcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudG9yY2hPZmZCdXR0b24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlN3aXRjaCBPZmYgVG9yY2hcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudG9yY2hPbkZhaWxlZE1lc3NhZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkZhaWxlZCB0byB0dXJuIG9uIHRvcmNoXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRvcmNoT2ZmRmFpbGVkTWVzc2FnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiRmFpbGVkIHRvIHR1cm4gb2ZmIHRvcmNoXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnNjYW5CdXR0b25TY2FubmluZ1N0YXJ0aW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJMYXVuY2hpbmcgQ2FtZXJhLi4uXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRleHRJZkNhbWVyYVNjYW5TZWxlY3RlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiU2NhbiBhbiBJbWFnZSBGaWxlXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRleHRJZkZpbGVTY2FuU2VsZWN0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlNjYW4gdXNpbmcgY2FtZXJhIGRpcmVjdGx5XCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnNlbGVjdENhbWVyYSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiU2VsZWN0IENhbWVyYVwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5maWxlU2VsZWN0aW9uQ2hvb3NlSW1hZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkNob29zZSBJbWFnZVwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5maWxlU2VsZWN0aW9uQ2hvb3NlQW5vdGhlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiQ2hvb3NlIEFub3RoZXJcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZmlsZVNlbGVjdGlvbk5vSW1hZ2VTZWxlY3RlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiTm8gaW1hZ2UgY2hvb3NlblwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5hbm9ueW1vdXNDYW1lcmFQcmVmaXggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkFub255bW91cyBDYW1lcmFcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZHJhZ0FuZERyb3BNZXNzYWdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJPciBkcm9wIGFuIGltYWdlIHRvIHNjYW5cIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZHJhZ0FuZERyb3BNZXNzYWdlT25seUltYWdlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiT3IgZHJvcCBhbiBpbWFnZSB0byBzY2FuIChvdGhlciBmaWxlcyBub3Qgc3VwcG9ydGVkKVwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy56b29tID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJ6b29tXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmxvYWRpbmdJbWFnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiTG9hZGluZyBpbWFnZS4uLlwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5jYW1lcmFTY2FuQWx0VGV4dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiQ2FtZXJhIGJhc2VkIHNjYW5cIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZmlsZVNjYW5BbHRUZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJGdWxlIGJhc2VkIHNjYW5cIjtcbiAgICB9O1xuICAgIHJldHVybiBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzO1xufSgpKTtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MgfTtcbnZhciBMaWJyYXJ5SW5mb1N0cmluZ3MgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIExpYnJhcnlJbmZvU3RyaW5ncygpIHtcbiAgICB9XG4gICAgTGlicmFyeUluZm9TdHJpbmdzLnBvd2VyZWRCeSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiUG93ZXJlZCBieSBcIjtcbiAgICB9O1xuICAgIExpYnJhcnlJbmZvU3RyaW5ncy5yZXBvcnRJc3N1ZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlJlcG9ydCBpc3N1ZXNcIjtcbiAgICB9O1xuICAgIHJldHVybiBMaWJyYXJ5SW5mb1N0cmluZ3M7XG59KCkpO1xuZXhwb3J0IHsgTGlicmFyeUluZm9TdHJpbmdzIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1zdHJpbmdzLmpzLm1hcCJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/strings.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/ui.js":
+/*!*********************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/ui.js ***!
+  \*********************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   LibraryInfoContainer: () => (/* binding */ LibraryInfoContainer)\n/* harmony export */ });\n/* harmony import */ var _image_assets__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./image-assets */ \"./node_modules/html5-qrcode/esm/image-assets.js\");\n/* harmony import */ var _strings__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./strings */ \"./node_modules/html5-qrcode/esm/strings.js\");\n\n\nvar LibraryInfoDiv = (function () {\n    function LibraryInfoDiv() {\n        this.infoDiv = document.createElement(\"div\");\n    }\n    LibraryInfoDiv.prototype.renderInto = function (parent) {\n        this.infoDiv.style.position = \"absolute\";\n        this.infoDiv.style.top = \"10px\";\n        this.infoDiv.style.right = \"10px\";\n        this.infoDiv.style.zIndex = \"2\";\n        this.infoDiv.style.display = \"none\";\n        this.infoDiv.style.padding = \"5pt\";\n        this.infoDiv.style.border = \"1px solid #171717\";\n        this.infoDiv.style.fontSize = \"10pt\";\n        this.infoDiv.style.background = \"rgb(0 0 0 / 69%)\";\n        this.infoDiv.style.borderRadius = \"5px\";\n        this.infoDiv.style.textAlign = \"center\";\n        this.infoDiv.style.fontWeight = \"400\";\n        this.infoDiv.style.color = \"white\";\n        this.infoDiv.innerText = _strings__WEBPACK_IMPORTED_MODULE_1__.LibraryInfoStrings.poweredBy();\n        var projectLink = document.createElement(\"a\");\n        projectLink.innerText = \"ScanApp\";\n        projectLink.href = \"https://scanapp.org\";\n        projectLink.target = \"new\";\n        projectLink.style.color = \"white\";\n        this.infoDiv.appendChild(projectLink);\n        var breakElemFirst = document.createElement(\"br\");\n        var breakElemSecond = document.createElement(\"br\");\n        this.infoDiv.appendChild(breakElemFirst);\n        this.infoDiv.appendChild(breakElemSecond);\n        var reportIssueLink = document.createElement(\"a\");\n        reportIssueLink.innerText = _strings__WEBPACK_IMPORTED_MODULE_1__.LibraryInfoStrings.reportIssues();\n        reportIssueLink.href = \"https://github.com/mebjas/html5-qrcode/issues\";\n        reportIssueLink.target = \"new\";\n        reportIssueLink.style.color = \"white\";\n        this.infoDiv.appendChild(reportIssueLink);\n        parent.appendChild(this.infoDiv);\n    };\n    LibraryInfoDiv.prototype.show = function () {\n        this.infoDiv.style.display = \"block\";\n    };\n    LibraryInfoDiv.prototype.hide = function () {\n        this.infoDiv.style.display = \"none\";\n    };\n    return LibraryInfoDiv;\n}());\nvar LibraryInfoIcon = (function () {\n    function LibraryInfoIcon(onTapIn, onTapOut) {\n        this.isShowingInfoIcon = true;\n        this.onTapIn = onTapIn;\n        this.onTapOut = onTapOut;\n        this.infoIcon = document.createElement(\"img\");\n    }\n    LibraryInfoIcon.prototype.renderInto = function (parent) {\n        var _this = this;\n        this.infoIcon.alt = \"Info icon\";\n        this.infoIcon.src = _image_assets__WEBPACK_IMPORTED_MODULE_0__.ASSET_INFO_ICON_16PX;\n        this.infoIcon.style.position = \"absolute\";\n        this.infoIcon.style.top = \"4px\";\n        this.infoIcon.style.right = \"4px\";\n        this.infoIcon.style.opacity = \"0.6\";\n        this.infoIcon.style.cursor = \"pointer\";\n        this.infoIcon.style.zIndex = \"2\";\n        this.infoIcon.style.width = \"16px\";\n        this.infoIcon.style.height = \"16px\";\n        this.infoIcon.onmouseover = function (_) { return _this.onHoverIn(); };\n        this.infoIcon.onmouseout = function (_) { return _this.onHoverOut(); };\n        this.infoIcon.onclick = function (_) { return _this.onClick(); };\n        parent.appendChild(this.infoIcon);\n    };\n    LibraryInfoIcon.prototype.onHoverIn = function () {\n        if (this.isShowingInfoIcon) {\n            this.infoIcon.style.opacity = \"1\";\n        }\n    };\n    LibraryInfoIcon.prototype.onHoverOut = function () {\n        if (this.isShowingInfoIcon) {\n            this.infoIcon.style.opacity = \"0.6\";\n        }\n    };\n    LibraryInfoIcon.prototype.onClick = function () {\n        if (this.isShowingInfoIcon) {\n            this.isShowingInfoIcon = false;\n            this.onTapIn();\n            this.infoIcon.src = _image_assets__WEBPACK_IMPORTED_MODULE_0__.ASSET_CLOSE_ICON_16PX;\n            this.infoIcon.style.opacity = \"1\";\n        }\n        else {\n            this.isShowingInfoIcon = true;\n            this.onTapOut();\n            this.infoIcon.src = _image_assets__WEBPACK_IMPORTED_MODULE_0__.ASSET_INFO_ICON_16PX;\n            this.infoIcon.style.opacity = \"0.6\";\n        }\n    };\n    return LibraryInfoIcon;\n}());\nvar LibraryInfoContainer = (function () {\n    function LibraryInfoContainer() {\n        var _this = this;\n        this.infoDiv = new LibraryInfoDiv();\n        this.infoIcon = new LibraryInfoIcon(function () {\n            _this.infoDiv.show();\n        }, function () {\n            _this.infoDiv.hide();\n        });\n    }\n    LibraryInfoContainer.prototype.renderInto = function (parent) {\n        this.infoDiv.renderInto(parent);\n        this.infoIcon.renderInto(parent);\n    };\n    return LibraryInfoContainer;\n}());\n\n//# sourceMappingURL=ui.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL3VpLmpzPzcxOWQiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQVNTRVRfQ0xPU0VfSUNPTl8xNlBYLCBBU1NFVF9JTkZPX0lDT05fMTZQWCB9IGZyb20gXCIuL2ltYWdlLWFzc2V0c1wiO1xuaW1wb3J0IHsgTGlicmFyeUluZm9TdHJpbmdzIH0gZnJvbSBcIi4vc3RyaW5nc1wiO1xudmFyIExpYnJhcnlJbmZvRGl2ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBMaWJyYXJ5SW5mb0RpdigpIHtcbiAgICAgICAgdGhpcy5pbmZvRGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICB9XG4gICAgTGlicmFyeUluZm9EaXYucHJvdG90eXBlLnJlbmRlckludG8gPSBmdW5jdGlvbiAocGFyZW50KSB7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5wb3NpdGlvbiA9IFwiYWJzb2x1dGVcIjtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLnRvcCA9IFwiMTBweFwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUucmlnaHQgPSBcIjEwcHhcIjtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLnpJbmRleCA9IFwiMlwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUucGFkZGluZyA9IFwiNXB0XCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5ib3JkZXIgPSBcIjFweCBzb2xpZCAjMTcxNzE3XCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5mb250U2l6ZSA9IFwiMTBwdFwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUuYmFja2dyb3VuZCA9IFwicmdiKDAgMCAwIC8gNjklKVwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUuYm9yZGVyUmFkaXVzID0gXCI1cHhcIjtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLnRleHRBbGlnbiA9IFwiY2VudGVyXCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5mb250V2VpZ2h0ID0gXCI0MDBcIjtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLmNvbG9yID0gXCJ3aGl0ZVwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuaW5uZXJUZXh0ID0gTGlicmFyeUluZm9TdHJpbmdzLnBvd2VyZWRCeSgpO1xuICAgICAgICB2YXIgcHJvamVjdExpbmsgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiYVwiKTtcbiAgICAgICAgcHJvamVjdExpbmsuaW5uZXJUZXh0ID0gXCJTY2FuQXBwXCI7XG4gICAgICAgIHByb2plY3RMaW5rLmhyZWYgPSBcImh0dHBzOi8vc2NhbmFwcC5vcmdcIjtcbiAgICAgICAgcHJvamVjdExpbmsudGFyZ2V0ID0gXCJuZXdcIjtcbiAgICAgICAgcHJvamVjdExpbmsuc3R5bGUuY29sb3IgPSBcIndoaXRlXCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5hcHBlbmRDaGlsZChwcm9qZWN0TGluayk7XG4gICAgICAgIHZhciBicmVha0VsZW1GaXJzdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJiclwiKTtcbiAgICAgICAgdmFyIGJyZWFrRWxlbVNlY29uZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJiclwiKTtcbiAgICAgICAgdGhpcy5pbmZvRGl2LmFwcGVuZENoaWxkKGJyZWFrRWxlbUZpcnN0KTtcbiAgICAgICAgdGhpcy5pbmZvRGl2LmFwcGVuZENoaWxkKGJyZWFrRWxlbVNlY29uZCk7XG4gICAgICAgIHZhciByZXBvcnRJc3N1ZUxpbmsgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiYVwiKTtcbiAgICAgICAgcmVwb3J0SXNzdWVMaW5rLmlubmVyVGV4dCA9IExpYnJhcnlJbmZvU3RyaW5ncy5yZXBvcnRJc3N1ZXMoKTtcbiAgICAgICAgcmVwb3J0SXNzdWVMaW5rLmhyZWYgPSBcImh0dHBzOi8vZ2l0aHViLmNvbS9tZWJqYXMvaHRtbDUtcXJjb2RlL2lzc3Vlc1wiO1xuICAgICAgICByZXBvcnRJc3N1ZUxpbmsudGFyZ2V0ID0gXCJuZXdcIjtcbiAgICAgICAgcmVwb3J0SXNzdWVMaW5rLnN0eWxlLmNvbG9yID0gXCJ3aGl0ZVwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuYXBwZW5kQ2hpbGQocmVwb3J0SXNzdWVMaW5rKTtcbiAgICAgICAgcGFyZW50LmFwcGVuZENoaWxkKHRoaXMuaW5mb0Rpdik7XG4gICAgfTtcbiAgICBMaWJyYXJ5SW5mb0Rpdi5wcm90b3R5cGUuc2hvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLmRpc3BsYXkgPSBcImJsb2NrXCI7XG4gICAgfTtcbiAgICBMaWJyYXJ5SW5mb0Rpdi5wcm90b3R5cGUuaGlkZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICB9O1xuICAgIHJldHVybiBMaWJyYXJ5SW5mb0Rpdjtcbn0oKSk7XG52YXIgTGlicmFyeUluZm9JY29uID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBMaWJyYXJ5SW5mb0ljb24ob25UYXBJbiwgb25UYXBPdXQpIHtcbiAgICAgICAgdGhpcy5pc1Nob3dpbmdJbmZvSWNvbiA9IHRydWU7XG4gICAgICAgIHRoaXMub25UYXBJbiA9IG9uVGFwSW47XG4gICAgICAgIHRoaXMub25UYXBPdXQgPSBvblRhcE91dDtcbiAgICAgICAgdGhpcy5pbmZvSWNvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJpbWdcIik7XG4gICAgfVxuICAgIExpYnJhcnlJbmZvSWNvbi5wcm90b3R5cGUucmVuZGVySW50byA9IGZ1bmN0aW9uIChwYXJlbnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5pbmZvSWNvbi5hbHQgPSBcIkluZm8gaWNvblwiO1xuICAgICAgICB0aGlzLmluZm9JY29uLnNyYyA9IEFTU0VUX0lORk9fSUNPTl8xNlBYO1xuICAgICAgICB0aGlzLmluZm9JY29uLnN0eWxlLnBvc2l0aW9uID0gXCJhYnNvbHV0ZVwiO1xuICAgICAgICB0aGlzLmluZm9JY29uLnN0eWxlLnRvcCA9IFwiNHB4XCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUucmlnaHQgPSBcIjRweFwiO1xuICAgICAgICB0aGlzLmluZm9JY29uLnN0eWxlLm9wYWNpdHkgPSBcIjAuNlwiO1xuICAgICAgICB0aGlzLmluZm9JY29uLnN0eWxlLmN1cnNvciA9IFwicG9pbnRlclwiO1xuICAgICAgICB0aGlzLmluZm9JY29uLnN0eWxlLnpJbmRleCA9IFwiMlwiO1xuICAgICAgICB0aGlzLmluZm9JY29uLnN0eWxlLndpZHRoID0gXCIxNnB4XCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUuaGVpZ2h0ID0gXCIxNnB4XCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24ub25tb3VzZW92ZXIgPSBmdW5jdGlvbiAoXykgeyByZXR1cm4gX3RoaXMub25Ib3ZlckluKCk7IH07XG4gICAgICAgIHRoaXMuaW5mb0ljb24ub25tb3VzZW91dCA9IGZ1bmN0aW9uIChfKSB7IHJldHVybiBfdGhpcy5vbkhvdmVyT3V0KCk7IH07XG4gICAgICAgIHRoaXMuaW5mb0ljb24ub25jbGljayA9IGZ1bmN0aW9uIChfKSB7IHJldHVybiBfdGhpcy5vbkNsaWNrKCk7IH07XG4gICAgICAgIHBhcmVudC5hcHBlbmRDaGlsZCh0aGlzLmluZm9JY29uKTtcbiAgICB9O1xuICAgIExpYnJhcnlJbmZvSWNvbi5wcm90b3R5cGUub25Ib3ZlckluID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pc1Nob3dpbmdJbmZvSWNvbikge1xuICAgICAgICAgICAgdGhpcy5pbmZvSWNvbi5zdHlsZS5vcGFjaXR5ID0gXCIxXCI7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIExpYnJhcnlJbmZvSWNvbi5wcm90b3R5cGUub25Ib3Zlck91dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNTaG93aW5nSW5mb0ljb24pIHtcbiAgICAgICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUub3BhY2l0eSA9IFwiMC42XCI7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIExpYnJhcnlJbmZvSWNvbi5wcm90b3R5cGUub25DbGljayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNTaG93aW5nSW5mb0ljb24pIHtcbiAgICAgICAgICAgIHRoaXMuaXNTaG93aW5nSW5mb0ljb24gPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMub25UYXBJbigpO1xuICAgICAgICAgICAgdGhpcy5pbmZvSWNvbi5zcmMgPSBBU1NFVF9DTE9TRV9JQ09OXzE2UFg7XG4gICAgICAgICAgICB0aGlzLmluZm9JY29uLnN0eWxlLm9wYWNpdHkgPSBcIjFcIjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuaXNTaG93aW5nSW5mb0ljb24gPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5vblRhcE91dCgpO1xuICAgICAgICAgICAgdGhpcy5pbmZvSWNvbi5zcmMgPSBBU1NFVF9JTkZPX0lDT05fMTZQWDtcbiAgICAgICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUub3BhY2l0eSA9IFwiMC42XCI7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBMaWJyYXJ5SW5mb0ljb247XG59KCkpO1xudmFyIExpYnJhcnlJbmZvQ29udGFpbmVyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBMaWJyYXJ5SW5mb0NvbnRhaW5lcigpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5pbmZvRGl2ID0gbmV3IExpYnJhcnlJbmZvRGl2KCk7XG4gICAgICAgIHRoaXMuaW5mb0ljb24gPSBuZXcgTGlicmFyeUluZm9JY29uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLmluZm9EaXYuc2hvdygpO1xuICAgICAgICB9LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5pbmZvRGl2LmhpZGUoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIExpYnJhcnlJbmZvQ29udGFpbmVyLnByb3RvdHlwZS5yZW5kZXJJbnRvID0gZnVuY3Rpb24gKHBhcmVudCkge1xuICAgICAgICB0aGlzLmluZm9EaXYucmVuZGVySW50byhwYXJlbnQpO1xuICAgICAgICB0aGlzLmluZm9JY29uLnJlbmRlckludG8ocGFyZW50KTtcbiAgICB9O1xuICAgIHJldHVybiBMaWJyYXJ5SW5mb0NvbnRhaW5lcjtcbn0oKSk7XG5leHBvcnQgeyBMaWJyYXJ5SW5mb0NvbnRhaW5lciB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dWkuanMubWFwIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/ui.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/ui/scanner/base.js":
+/*!**********************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/ui/scanner/base.js ***!
+  \**********************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   BaseUiElementFactory: () => (/* binding */ BaseUiElementFactory),\n/* harmony export */   PublicUiElementIdAndClasses: () => (/* binding */ PublicUiElementIdAndClasses)\n/* harmony export */ });\nvar PublicUiElementIdAndClasses = (function () {\n    function PublicUiElementIdAndClasses() {\n    }\n    PublicUiElementIdAndClasses.ALL_ELEMENT_CLASS = \"html5-qrcode-element\";\n    PublicUiElementIdAndClasses.CAMERA_PERMISSION_BUTTON_ID = \"html5-qrcode-button-camera-permission\";\n    PublicUiElementIdAndClasses.CAMERA_START_BUTTON_ID = \"html5-qrcode-button-camera-start\";\n    PublicUiElementIdAndClasses.CAMERA_STOP_BUTTON_ID = \"html5-qrcode-button-camera-stop\";\n    PublicUiElementIdAndClasses.TORCH_BUTTON_ID = \"html5-qrcode-button-torch\";\n    PublicUiElementIdAndClasses.CAMERA_SELECTION_SELECT_ID = \"html5-qrcode-select-camera\";\n    PublicUiElementIdAndClasses.FILE_SELECTION_BUTTON_ID = \"html5-qrcode-button-file-selection\";\n    PublicUiElementIdAndClasses.ZOOM_SLIDER_ID = \"html5-qrcode-input-range-zoom\";\n    PublicUiElementIdAndClasses.SCAN_TYPE_CHANGE_ANCHOR_ID = \"html5-qrcode-anchor-scan-type-change\";\n    PublicUiElementIdAndClasses.TORCH_BUTTON_CLASS_TORCH_ON = \"html5-qrcode-button-torch-on\";\n    PublicUiElementIdAndClasses.TORCH_BUTTON_CLASS_TORCH_OFF = \"html5-qrcode-button-torch-off\";\n    return PublicUiElementIdAndClasses;\n}());\n\nvar BaseUiElementFactory = (function () {\n    function BaseUiElementFactory() {\n    }\n    BaseUiElementFactory.createElement = function (elementType, elementId) {\n        var element = (document.createElement(elementType));\n        element.id = elementId;\n        element.classList.add(PublicUiElementIdAndClasses.ALL_ELEMENT_CLASS);\n        if (elementType === \"button\") {\n            element.setAttribute(\"type\", \"button\");\n        }\n        return element;\n    };\n    return BaseUiElementFactory;\n}());\n\n//# sourceMappingURL=base.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS9zY2FubmVyL2Jhc2UuanMuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS9zY2FubmVyL2Jhc2UuanM/NDE0ZiJdLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMoKSB7XG4gICAgfVxuICAgIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5BTExfRUxFTUVOVF9DTEFTUyA9IFwiaHRtbDUtcXJjb2RlLWVsZW1lbnRcIjtcbiAgICBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuQ0FNRVJBX1BFUk1JU1NJT05fQlVUVE9OX0lEID0gXCJodG1sNS1xcmNvZGUtYnV0dG9uLWNhbWVyYS1wZXJtaXNzaW9uXCI7XG4gICAgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkNBTUVSQV9TVEFSVF9CVVRUT05fSUQgPSBcImh0bWw1LXFyY29kZS1idXR0b24tY2FtZXJhLXN0YXJ0XCI7XG4gICAgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkNBTUVSQV9TVE9QX0JVVFRPTl9JRCA9IFwiaHRtbDUtcXJjb2RlLWJ1dHRvbi1jYW1lcmEtc3RvcFwiO1xuICAgIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5UT1JDSF9CVVRUT05fSUQgPSBcImh0bWw1LXFyY29kZS1idXR0b24tdG9yY2hcIjtcbiAgICBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuQ0FNRVJBX1NFTEVDVElPTl9TRUxFQ1RfSUQgPSBcImh0bWw1LXFyY29kZS1zZWxlY3QtY2FtZXJhXCI7XG4gICAgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkZJTEVfU0VMRUNUSU9OX0JVVFRPTl9JRCA9IFwiaHRtbDUtcXJjb2RlLWJ1dHRvbi1maWxlLXNlbGVjdGlvblwiO1xuICAgIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5aT09NX1NMSURFUl9JRCA9IFwiaHRtbDUtcXJjb2RlLWlucHV0LXJhbmdlLXpvb21cIjtcbiAgICBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuU0NBTl9UWVBFX0NIQU5HRV9BTkNIT1JfSUQgPSBcImh0bWw1LXFyY29kZS1hbmNob3Itc2Nhbi10eXBlLWNoYW5nZVwiO1xuICAgIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5UT1JDSF9CVVRUT05fQ0xBU1NfVE9SQ0hfT04gPSBcImh0bWw1LXFyY29kZS1idXR0b24tdG9yY2gtb25cIjtcbiAgICBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuVE9SQ0hfQlVUVE9OX0NMQVNTX1RPUkNIX09GRiA9IFwiaHRtbDUtcXJjb2RlLWJ1dHRvbi10b3JjaC1vZmZcIjtcbiAgICByZXR1cm4gUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzO1xufSgpKTtcbmV4cG9ydCB7IFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3NlcyB9O1xudmFyIEJhc2VVaUVsZW1lbnRGYWN0b3J5ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBCYXNlVWlFbGVtZW50RmFjdG9yeSgpIHtcbiAgICB9XG4gICAgQmFzZVVpRWxlbWVudEZhY3RvcnkuY3JlYXRlRWxlbWVudCA9IGZ1bmN0aW9uIChlbGVtZW50VHlwZSwgZWxlbWVudElkKSB7XG4gICAgICAgIHZhciBlbGVtZW50ID0gKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoZWxlbWVudFR5cGUpKTtcbiAgICAgICAgZWxlbWVudC5pZCA9IGVsZW1lbnRJZDtcbiAgICAgICAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5BTExfRUxFTUVOVF9DTEFTUyk7XG4gICAgICAgIGlmIChlbGVtZW50VHlwZSA9PT0gXCJidXR0b25cIikge1xuICAgICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoXCJ0eXBlXCIsIFwiYnV0dG9uXCIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlbGVtZW50O1xuICAgIH07XG4gICAgcmV0dXJuIEJhc2VVaUVsZW1lbnRGYWN0b3J5O1xufSgpKTtcbmV4cG9ydCB7IEJhc2VVaUVsZW1lbnRGYWN0b3J5IH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1iYXNlLmpzLm1hcCJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/ui/scanner/base.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/ui/scanner/camera-selection-ui.js":
+/*!*************************************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/ui/scanner/camera-selection-ui.js ***!
+  \*************************************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   CameraSelectionUi: () => (/* binding */ CameraSelectionUi)\n/* harmony export */ });\n/* harmony import */ var _base__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./base */ \"./node_modules/html5-qrcode/esm/ui/scanner/base.js\");\n/* harmony import */ var _strings__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../strings */ \"./node_modules/html5-qrcode/esm/strings.js\");\n\n\nvar CameraSelectionUi = (function () {\n    function CameraSelectionUi(cameras) {\n        this.selectElement = _base__WEBPACK_IMPORTED_MODULE_0__.BaseUiElementFactory.createElement(\"select\", _base__WEBPACK_IMPORTED_MODULE_0__.PublicUiElementIdAndClasses.CAMERA_SELECTION_SELECT_ID);\n        this.cameras = cameras;\n        this.options = [];\n    }\n    CameraSelectionUi.prototype.render = function (parentElement) {\n        var cameraSelectionContainer = document.createElement(\"span\");\n        cameraSelectionContainer.style.marginRight = \"10px\";\n        var numCameras = this.cameras.length;\n        if (numCameras === 0) {\n            throw new Error(\"No cameras found\");\n        }\n        if (numCameras === 1) {\n            cameraSelectionContainer.style.display = \"none\";\n        }\n        else {\n            var selectCameraString = _strings__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeScannerStrings.selectCamera();\n            cameraSelectionContainer.innerText\n                = \"\".concat(selectCameraString, \" (\").concat(this.cameras.length, \")  \");\n        }\n        var anonymousCameraId = 1;\n        for (var _i = 0, _a = this.cameras; _i < _a.length; _i++) {\n            var camera = _a[_i];\n            var value = camera.id;\n            var name_1 = camera.label == null ? value : camera.label;\n            if (!name_1 || name_1 === \"\") {\n                name_1 = [\n                    _strings__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeScannerStrings.anonymousCameraPrefix(),\n                    anonymousCameraId++\n                ].join(\" \");\n            }\n            var option = document.createElement(\"option\");\n            option.value = value;\n            option.innerText = name_1;\n            this.options.push(option);\n            this.selectElement.appendChild(option);\n        }\n        cameraSelectionContainer.appendChild(this.selectElement);\n        parentElement.appendChild(cameraSelectionContainer);\n    };\n    CameraSelectionUi.prototype.disable = function () {\n        this.selectElement.disabled = true;\n    };\n    CameraSelectionUi.prototype.isDisabled = function () {\n        return this.selectElement.disabled === true;\n    };\n    CameraSelectionUi.prototype.enable = function () {\n        this.selectElement.disabled = false;\n    };\n    CameraSelectionUi.prototype.getValue = function () {\n        return this.selectElement.value;\n    };\n    CameraSelectionUi.prototype.hasValue = function (value) {\n        for (var _i = 0, _a = this.options; _i < _a.length; _i++) {\n            var option = _a[_i];\n            if (option.value === value) {\n                return true;\n            }\n        }\n        return false;\n    };\n    CameraSelectionUi.prototype.setValue = function (value) {\n        if (!this.hasValue(value)) {\n            throw new Error(\"\".concat(value, \" is not present in the camera list.\"));\n        }\n        this.selectElement.value = value;\n    };\n    CameraSelectionUi.prototype.hasSingleItem = function () {\n        return this.cameras.length === 1;\n    };\n    CameraSelectionUi.prototype.numCameras = function () {\n        return this.cameras.length;\n    };\n    CameraSelectionUi.create = function (parentElement, cameras) {\n        var cameraSelectUi = new CameraSelectionUi(cameras);\n        cameraSelectUi.render(parentElement);\n        return cameraSelectUi;\n    };\n    return CameraSelectionUi;\n}());\n\n//# sourceMappingURL=camera-selection-ui.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS9zY2FubmVyL2NhbWVyYS1zZWxlY3Rpb24tdWkuanMuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS9zY2FubmVyL2NhbWVyYS1zZWxlY3Rpb24tdWkuanM/NzNkZCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCYXNlVWlFbGVtZW50RmFjdG9yeSwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzIH0gZnJvbSBcIi4vYmFzZVwiO1xuaW1wb3J0IHsgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncyB9IGZyb20gXCIuLi8uLi9zdHJpbmdzXCI7XG52YXIgQ2FtZXJhU2VsZWN0aW9uVWkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYVNlbGVjdGlvblVpKGNhbWVyYXMpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RFbGVtZW50ID0gQmFzZVVpRWxlbWVudEZhY3RvcnlcbiAgICAgICAgICAgIC5jcmVhdGVFbGVtZW50KFwic2VsZWN0XCIsIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5DQU1FUkFfU0VMRUNUSU9OX1NFTEVDVF9JRCk7XG4gICAgICAgIHRoaXMuY2FtZXJhcyA9IGNhbWVyYXM7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IFtdO1xuICAgIH1cbiAgICBDYW1lcmFTZWxlY3Rpb25VaS5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHBhcmVudEVsZW1lbnQpIHtcbiAgICAgICAgdmFyIGNhbWVyYVNlbGVjdGlvbkNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIpO1xuICAgICAgICBjYW1lcmFTZWxlY3Rpb25Db250YWluZXIuc3R5bGUubWFyZ2luUmlnaHQgPSBcIjEwcHhcIjtcbiAgICAgICAgdmFyIG51bUNhbWVyYXMgPSB0aGlzLmNhbWVyYXMubGVuZ3RoO1xuICAgICAgICBpZiAobnVtQ2FtZXJhcyA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gY2FtZXJhcyBmb3VuZFwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobnVtQ2FtZXJhcyA9PT0gMSkge1xuICAgICAgICAgICAgY2FtZXJhU2VsZWN0aW9uQ29udGFpbmVyLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBzZWxlY3RDYW1lcmFTdHJpbmcgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnNlbGVjdENhbWVyYSgpO1xuICAgICAgICAgICAgY2FtZXJhU2VsZWN0aW9uQ29udGFpbmVyLmlubmVyVGV4dFxuICAgICAgICAgICAgICAgID0gXCJcIi5jb25jYXQoc2VsZWN0Q2FtZXJhU3RyaW5nLCBcIiAoXCIpLmNvbmNhdCh0aGlzLmNhbWVyYXMubGVuZ3RoLCBcIikgIFwiKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYW5vbnltb3VzQ2FtZXJhSWQgPSAxO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5jYW1lcmFzOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIGNhbWVyYSA9IF9hW19pXTtcbiAgICAgICAgICAgIHZhciB2YWx1ZSA9IGNhbWVyYS5pZDtcbiAgICAgICAgICAgIHZhciBuYW1lXzEgPSBjYW1lcmEubGFiZWwgPT0gbnVsbCA/IHZhbHVlIDogY2FtZXJhLmxhYmVsO1xuICAgICAgICAgICAgaWYgKCFuYW1lXzEgfHwgbmFtZV8xID09PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgbmFtZV8xID0gW1xuICAgICAgICAgICAgICAgICAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmFub255bW91c0NhbWVyYVByZWZpeCgpLFxuICAgICAgICAgICAgICAgICAgICBhbm9ueW1vdXNDYW1lcmFJZCsrXG4gICAgICAgICAgICAgICAgXS5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBvcHRpb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwib3B0aW9uXCIpO1xuICAgICAgICAgICAgb3B0aW9uLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICBvcHRpb24uaW5uZXJUZXh0ID0gbmFtZV8xO1xuICAgICAgICAgICAgdGhpcy5vcHRpb25zLnB1c2gob3B0aW9uKTtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0RWxlbWVudC5hcHBlbmRDaGlsZChvcHRpb24pO1xuICAgICAgICB9XG4gICAgICAgIGNhbWVyYVNlbGVjdGlvbkNvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLnNlbGVjdEVsZW1lbnQpO1xuICAgICAgICBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKGNhbWVyYVNlbGVjdGlvbkNvbnRhaW5lcik7XG4gICAgfTtcbiAgICBDYW1lcmFTZWxlY3Rpb25VaS5wcm90b3R5cGUuZGlzYWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RFbGVtZW50LmRpc2FibGVkID0gdHJ1ZTtcbiAgICB9O1xuICAgIENhbWVyYVNlbGVjdGlvblVpLnByb3RvdHlwZS5pc0Rpc2FibGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZWxlY3RFbGVtZW50LmRpc2FibGVkID09PSB0cnVlO1xuICAgIH07XG4gICAgQ2FtZXJhU2VsZWN0aW9uVWkucHJvdG90eXBlLmVuYWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RFbGVtZW50LmRpc2FibGVkID0gZmFsc2U7XG4gICAgfTtcbiAgICBDYW1lcmFTZWxlY3Rpb25VaS5wcm90b3R5cGUuZ2V0VmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlbGVjdEVsZW1lbnQudmFsdWU7XG4gICAgfTtcbiAgICBDYW1lcmFTZWxlY3Rpb25VaS5wcm90b3R5cGUuaGFzVmFsdWUgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMub3B0aW9uczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBvcHRpb24gPSBfYVtfaV07XG4gICAgICAgICAgICBpZiAob3B0aW9uLnZhbHVlID09PSB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIENhbWVyYVNlbGVjdGlvblVpLnByb3RvdHlwZS5zZXRWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICBpZiAoIXRoaXMuaGFzVmFsdWUodmFsdWUpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJcIi5jb25jYXQodmFsdWUsIFwiIGlzIG5vdCBwcmVzZW50IGluIHRoZSBjYW1lcmEgbGlzdC5cIikpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2VsZWN0RWxlbWVudC52YWx1ZSA9IHZhbHVlO1xuICAgIH07XG4gICAgQ2FtZXJhU2VsZWN0aW9uVWkucHJvdG90eXBlLmhhc1NpbmdsZUl0ZW0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbWVyYXMubGVuZ3RoID09PSAxO1xuICAgIH07XG4gICAgQ2FtZXJhU2VsZWN0aW9uVWkucHJvdG90eXBlLm51bUNhbWVyYXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbWVyYXMubGVuZ3RoO1xuICAgIH07XG4gICAgQ2FtZXJhU2VsZWN0aW9uVWkuY3JlYXRlID0gZnVuY3Rpb24gKHBhcmVudEVsZW1lbnQsIGNhbWVyYXMpIHtcbiAgICAgICAgdmFyIGNhbWVyYVNlbGVjdFVpID0gbmV3IENhbWVyYVNlbGVjdGlvblVpKGNhbWVyYXMpO1xuICAgICAgICBjYW1lcmFTZWxlY3RVaS5yZW5kZXIocGFyZW50RWxlbWVudCk7XG4gICAgICAgIHJldHVybiBjYW1lcmFTZWxlY3RVaTtcbiAgICB9O1xuICAgIHJldHVybiBDYW1lcmFTZWxlY3Rpb25VaTtcbn0oKSk7XG5leHBvcnQgeyBDYW1lcmFTZWxlY3Rpb25VaSB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y2FtZXJhLXNlbGVjdGlvbi11aS5qcy5tYXAiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/ui/scanner/camera-selection-ui.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/ui/scanner/camera-zoom-ui.js":
+/*!********************************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/ui/scanner/camera-zoom-ui.js ***!
+  \********************************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   CameraZoomUi: () => (/* binding */ CameraZoomUi)\n/* harmony export */ });\n/* harmony import */ var _base__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./base */ \"./node_modules/html5-qrcode/esm/ui/scanner/base.js\");\n/* harmony import */ var _strings__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../strings */ \"./node_modules/html5-qrcode/esm/strings.js\");\n\n\nvar CameraZoomUi = (function () {\n    function CameraZoomUi() {\n        this.onChangeCallback = null;\n        this.zoomElementContainer = document.createElement(\"div\");\n        this.rangeInput = _base__WEBPACK_IMPORTED_MODULE_0__.BaseUiElementFactory.createElement(\"input\", _base__WEBPACK_IMPORTED_MODULE_0__.PublicUiElementIdAndClasses.ZOOM_SLIDER_ID);\n        this.rangeInput.type = \"range\";\n        this.rangeText = document.createElement(\"span\");\n        this.rangeInput.min = \"1\";\n        this.rangeInput.max = \"5\";\n        this.rangeInput.value = \"1\";\n        this.rangeInput.step = \"0.1\";\n    }\n    CameraZoomUi.prototype.render = function (parentElement, renderOnCreate) {\n        this.zoomElementContainer.style.display\n            = renderOnCreate ? \"block\" : \"none\";\n        this.zoomElementContainer.style.padding = \"5px 10px\";\n        this.zoomElementContainer.style.textAlign = \"center\";\n        parentElement.appendChild(this.zoomElementContainer);\n        this.rangeInput.style.display = \"inline-block\";\n        this.rangeInput.style.width = \"50%\";\n        this.rangeInput.style.height = \"5px\";\n        this.rangeInput.style.background = \"#d3d3d3\";\n        this.rangeInput.style.outline = \"none\";\n        this.rangeInput.style.opacity = \"0.7\";\n        var zoomString = _strings__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeScannerStrings.zoom();\n        this.rangeText.innerText = \"\".concat(this.rangeInput.value, \"x \").concat(zoomString);\n        this.rangeText.style.marginRight = \"10px\";\n        var $this = this;\n        this.rangeInput.addEventListener(\"input\", function () { return $this.onValueChange(); });\n        this.rangeInput.addEventListener(\"change\", function () { return $this.onValueChange(); });\n        this.zoomElementContainer.appendChild(this.rangeInput);\n        this.zoomElementContainer.appendChild(this.rangeText);\n    };\n    CameraZoomUi.prototype.onValueChange = function () {\n        var zoomString = _strings__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeScannerStrings.zoom();\n        this.rangeText.innerText = \"\".concat(this.rangeInput.value, \"x \").concat(zoomString);\n        if (this.onChangeCallback) {\n            this.onChangeCallback(parseFloat(this.rangeInput.value));\n        }\n    };\n    CameraZoomUi.prototype.setValues = function (minValue, maxValue, defaultValue, step) {\n        this.rangeInput.min = minValue.toString();\n        this.rangeInput.max = maxValue.toString();\n        this.rangeInput.step = step.toString();\n        this.rangeInput.value = defaultValue.toString();\n        this.onValueChange();\n    };\n    CameraZoomUi.prototype.show = function () {\n        this.zoomElementContainer.style.display = \"block\";\n    };\n    CameraZoomUi.prototype.hide = function () {\n        this.zoomElementContainer.style.display = \"none\";\n    };\n    CameraZoomUi.prototype.setOnCameraZoomValueChangeCallback = function (onChangeCallback) {\n        this.onChangeCallback = onChangeCallback;\n    };\n    CameraZoomUi.prototype.removeOnCameraZoomValueChangeCallback = function () {\n        this.onChangeCallback = null;\n    };\n    CameraZoomUi.create = function (parentElement, renderOnCreate) {\n        var cameraZoomUi = new CameraZoomUi();\n        cameraZoomUi.render(parentElement, renderOnCreate);\n        return cameraZoomUi;\n    };\n    return CameraZoomUi;\n}());\n\n//# sourceMappingURL=camera-zoom-ui.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS9zY2FubmVyL2NhbWVyYS16b29tLXVpLmpzLmpzIiwibWFwcGluZ3MiOiI7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vdWkvc2Nhbm5lci9jYW1lcmEtem9vbS11aS5qcz9lNmYxIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJhc2VVaUVsZW1lbnRGYWN0b3J5LCBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMgfSBmcm9tIFwiLi9iYXNlXCI7XG5pbXBvcnQgeyBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzIH0gZnJvbSBcIi4uLy4uL3N0cmluZ3NcIjtcbnZhciBDYW1lcmFab29tVWkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYVpvb21VaSgpIHtcbiAgICAgICAgdGhpcy5vbkNoYW5nZUNhbGxiYWNrID0gbnVsbDtcbiAgICAgICAgdGhpcy56b29tRWxlbWVudENvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dCA9IEJhc2VVaUVsZW1lbnRGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoXCJpbnB1dFwiLCBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuWk9PTV9TTElERVJfSUQpO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQudHlwZSA9IFwicmFuZ2VcIjtcbiAgICAgICAgdGhpcy5yYW5nZVRleHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic3BhblwiKTtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0Lm1pbiA9IFwiMVwiO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQubWF4ID0gXCI1XCI7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dC52YWx1ZSA9IFwiMVwiO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQuc3RlcCA9IFwiMC4xXCI7XG4gICAgfVxuICAgIENhbWVyYVpvb21VaS5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHBhcmVudEVsZW1lbnQsIHJlbmRlck9uQ3JlYXRlKSB7XG4gICAgICAgIHRoaXMuem9vbUVsZW1lbnRDb250YWluZXIuc3R5bGUuZGlzcGxheVxuICAgICAgICAgICAgPSByZW5kZXJPbkNyZWF0ZSA/IFwiYmxvY2tcIiA6IFwibm9uZVwiO1xuICAgICAgICB0aGlzLnpvb21FbGVtZW50Q29udGFpbmVyLnN0eWxlLnBhZGRpbmcgPSBcIjVweCAxMHB4XCI7XG4gICAgICAgIHRoaXMuem9vbUVsZW1lbnRDb250YWluZXIuc3R5bGUudGV4dEFsaWduID0gXCJjZW50ZXJcIjtcbiAgICAgICAgcGFyZW50RWxlbWVudC5hcHBlbmRDaGlsZCh0aGlzLnpvb21FbGVtZW50Q29udGFpbmVyKTtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnN0eWxlLmRpc3BsYXkgPSBcImlubGluZS1ibG9ja1wiO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQuc3R5bGUud2lkdGggPSBcIjUwJVwiO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQuc3R5bGUuaGVpZ2h0ID0gXCI1cHhcIjtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnN0eWxlLmJhY2tncm91bmQgPSBcIiNkM2QzZDNcIjtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnN0eWxlLm91dGxpbmUgPSBcIm5vbmVcIjtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnN0eWxlLm9wYWNpdHkgPSBcIjAuN1wiO1xuICAgICAgICB2YXIgem9vbVN0cmluZyA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muem9vbSgpO1xuICAgICAgICB0aGlzLnJhbmdlVGV4dC5pbm5lclRleHQgPSBcIlwiLmNvbmNhdCh0aGlzLnJhbmdlSW5wdXQudmFsdWUsIFwieCBcIikuY29uY2F0KHpvb21TdHJpbmcpO1xuICAgICAgICB0aGlzLnJhbmdlVGV4dC5zdHlsZS5tYXJnaW5SaWdodCA9IFwiMTBweFwiO1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQuYWRkRXZlbnRMaXN0ZW5lcihcImlucHV0XCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuICR0aGlzLm9uVmFsdWVDaGFuZ2UoKTsgfSk7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dC5hZGRFdmVudExpc3RlbmVyKFwiY2hhbmdlXCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuICR0aGlzLm9uVmFsdWVDaGFuZ2UoKTsgfSk7XG4gICAgICAgIHRoaXMuem9vbUVsZW1lbnRDb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5yYW5nZUlucHV0KTtcbiAgICAgICAgdGhpcy56b29tRWxlbWVudENvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLnJhbmdlVGV4dCk7XG4gICAgfTtcbiAgICBDYW1lcmFab29tVWkucHJvdG90eXBlLm9uVmFsdWVDaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB6b29tU3RyaW5nID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy56b29tKCk7XG4gICAgICAgIHRoaXMucmFuZ2VUZXh0LmlubmVyVGV4dCA9IFwiXCIuY29uY2F0KHRoaXMucmFuZ2VJbnB1dC52YWx1ZSwgXCJ4IFwiKS5jb25jYXQoem9vbVN0cmluZyk7XG4gICAgICAgIGlmICh0aGlzLm9uQ2hhbmdlQ2FsbGJhY2spIHtcbiAgICAgICAgICAgIHRoaXMub25DaGFuZ2VDYWxsYmFjayhwYXJzZUZsb2F0KHRoaXMucmFuZ2VJbnB1dC52YWx1ZSkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDYW1lcmFab29tVWkucHJvdG90eXBlLnNldFZhbHVlcyA9IGZ1bmN0aW9uIChtaW5WYWx1ZSwgbWF4VmFsdWUsIGRlZmF1bHRWYWx1ZSwgc3RlcCkge1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQubWluID0gbWluVmFsdWUudG9TdHJpbmcoKTtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0Lm1heCA9IG1heFZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dC5zdGVwID0gc3RlcC50b1N0cmluZygpO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQudmFsdWUgPSBkZWZhdWx0VmFsdWUudG9TdHJpbmcoKTtcbiAgICAgICAgdGhpcy5vblZhbHVlQ2hhbmdlKCk7XG4gICAgfTtcbiAgICBDYW1lcmFab29tVWkucHJvdG90eXBlLnNob3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuem9vbUVsZW1lbnRDb250YWluZXIuc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIjtcbiAgICB9O1xuICAgIENhbWVyYVpvb21VaS5wcm90b3R5cGUuaGlkZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy56b29tRWxlbWVudENvbnRhaW5lci5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgfTtcbiAgICBDYW1lcmFab29tVWkucHJvdG90eXBlLnNldE9uQ2FtZXJhWm9vbVZhbHVlQ2hhbmdlQ2FsbGJhY2sgPSBmdW5jdGlvbiAob25DaGFuZ2VDYWxsYmFjaykge1xuICAgICAgICB0aGlzLm9uQ2hhbmdlQ2FsbGJhY2sgPSBvbkNoYW5nZUNhbGxiYWNrO1xuICAgIH07XG4gICAgQ2FtZXJhWm9vbVVpLnByb3RvdHlwZS5yZW1vdmVPbkNhbWVyYVpvb21WYWx1ZUNoYW5nZUNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLm9uQ2hhbmdlQ2FsbGJhY2sgPSBudWxsO1xuICAgIH07XG4gICAgQ2FtZXJhWm9vbVVpLmNyZWF0ZSA9IGZ1bmN0aW9uIChwYXJlbnRFbGVtZW50LCByZW5kZXJPbkNyZWF0ZSkge1xuICAgICAgICB2YXIgY2FtZXJhWm9vbVVpID0gbmV3IENhbWVyYVpvb21VaSgpO1xuICAgICAgICBjYW1lcmFab29tVWkucmVuZGVyKHBhcmVudEVsZW1lbnQsIHJlbmRlck9uQ3JlYXRlKTtcbiAgICAgICAgcmV0dXJuIGNhbWVyYVpvb21VaTtcbiAgICB9O1xuICAgIHJldHVybiBDYW1lcmFab29tVWk7XG59KCkpO1xuZXhwb3J0IHsgQ2FtZXJhWm9vbVVpIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jYW1lcmEtem9vbS11aS5qcy5tYXAiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/ui/scanner/camera-zoom-ui.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/ui/scanner/file-selection-ui.js":
+/*!***********************************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/ui/scanner/file-selection-ui.js ***!
+  \***********************************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   FileSelectionUi: () => (/* binding */ FileSelectionUi)\n/* harmony export */ });\n/* harmony import */ var _strings__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../strings */ \"./node_modules/html5-qrcode/esm/strings.js\");\n/* harmony import */ var _base__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./base */ \"./node_modules/html5-qrcode/esm/ui/scanner/base.js\");\n\n\nvar FileSelectionUi = (function () {\n    function FileSelectionUi(parentElement, showOnRender, onFileSelected) {\n        this.fileBasedScanRegion = this.createFileBasedScanRegion();\n        this.fileBasedScanRegion.style.display\n            = showOnRender ? \"block\" : \"none\";\n        parentElement.appendChild(this.fileBasedScanRegion);\n        var fileScanLabel = document.createElement(\"label\");\n        fileScanLabel.setAttribute(\"for\", this.getFileScanInputId());\n        fileScanLabel.style.display = \"inline-block\";\n        this.fileBasedScanRegion.appendChild(fileScanLabel);\n        this.fileSelectionButton\n            = _base__WEBPACK_IMPORTED_MODULE_1__.BaseUiElementFactory.createElement(\"button\", _base__WEBPACK_IMPORTED_MODULE_1__.PublicUiElementIdAndClasses.FILE_SELECTION_BUTTON_ID);\n        this.setInitialValueToButton();\n        this.fileSelectionButton.addEventListener(\"click\", function (_) {\n            fileScanLabel.click();\n        });\n        fileScanLabel.append(this.fileSelectionButton);\n        this.fileScanInput\n            = _base__WEBPACK_IMPORTED_MODULE_1__.BaseUiElementFactory.createElement(\"input\", this.getFileScanInputId());\n        this.fileScanInput.type = \"file\";\n        this.fileScanInput.accept = \"image/*\";\n        this.fileScanInput.style.display = \"none\";\n        fileScanLabel.appendChild(this.fileScanInput);\n        var $this = this;\n        this.fileScanInput.addEventListener(\"change\", function (e) {\n            if (e == null || e.target == null) {\n                return;\n            }\n            var target = e.target;\n            if (target.files && target.files.length === 0) {\n                return;\n            }\n            var fileList = target.files;\n            var file = fileList[0];\n            var fileName = file.name;\n            $this.setImageNameToButton(fileName);\n            onFileSelected(file);\n        });\n        var dragAndDropMessage = this.createDragAndDropMessage();\n        this.fileBasedScanRegion.appendChild(dragAndDropMessage);\n        this.fileBasedScanRegion.addEventListener(\"dragenter\", function (event) {\n            $this.fileBasedScanRegion.style.border\n                = $this.fileBasedScanRegionActiveBorder();\n            event.stopPropagation();\n            event.preventDefault();\n        });\n        this.fileBasedScanRegion.addEventListener(\"dragleave\", function (event) {\n            $this.fileBasedScanRegion.style.border\n                = $this.fileBasedScanRegionDefaultBorder();\n            event.stopPropagation();\n            event.preventDefault();\n        });\n        this.fileBasedScanRegion.addEventListener(\"dragover\", function (event) {\n            $this.fileBasedScanRegion.style.border\n                = $this.fileBasedScanRegionActiveBorder();\n            event.stopPropagation();\n            event.preventDefault();\n        });\n        this.fileBasedScanRegion.addEventListener(\"drop\", function (event) {\n            event.stopPropagation();\n            event.preventDefault();\n            $this.fileBasedScanRegion.style.border\n                = $this.fileBasedScanRegionDefaultBorder();\n            var dataTransfer = event.dataTransfer;\n            if (dataTransfer) {\n                var files = dataTransfer.files;\n                if (!files || files.length === 0) {\n                    return;\n                }\n                var isAnyFileImage = false;\n                for (var i = 0; i < files.length; ++i) {\n                    var file = files.item(i);\n                    if (!file) {\n                        continue;\n                    }\n                    var imageType = /image.*/;\n                    if (!file.type.match(imageType)) {\n                        continue;\n                    }\n                    isAnyFileImage = true;\n                    var fileName = file.name;\n                    $this.setImageNameToButton(fileName);\n                    onFileSelected(file);\n                    dragAndDropMessage.innerText\n                        = _strings__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScannerStrings.dragAndDropMessage();\n                    break;\n                }\n                if (!isAnyFileImage) {\n                    dragAndDropMessage.innerText\n                        = _strings__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScannerStrings.dragAndDropMessageOnlyImages();\n                }\n            }\n        });\n    }\n    FileSelectionUi.prototype.hide = function () {\n        this.fileBasedScanRegion.style.display = \"none\";\n        this.fileScanInput.disabled = true;\n    };\n    FileSelectionUi.prototype.show = function () {\n        this.fileBasedScanRegion.style.display = \"block\";\n        this.fileScanInput.disabled = false;\n    };\n    FileSelectionUi.prototype.isShowing = function () {\n        return this.fileBasedScanRegion.style.display === \"block\";\n    };\n    FileSelectionUi.prototype.resetValue = function () {\n        this.fileScanInput.value = \"\";\n        this.setInitialValueToButton();\n    };\n    FileSelectionUi.prototype.createFileBasedScanRegion = function () {\n        var fileBasedScanRegion = document.createElement(\"div\");\n        fileBasedScanRegion.style.textAlign = \"center\";\n        fileBasedScanRegion.style.margin = \"auto\";\n        fileBasedScanRegion.style.width = \"80%\";\n        fileBasedScanRegion.style.maxWidth = \"600px\";\n        fileBasedScanRegion.style.border\n            = this.fileBasedScanRegionDefaultBorder();\n        fileBasedScanRegion.style.padding = \"10px\";\n        fileBasedScanRegion.style.marginBottom = \"10px\";\n        return fileBasedScanRegion;\n    };\n    FileSelectionUi.prototype.fileBasedScanRegionDefaultBorder = function () {\n        return \"6px dashed #ebebeb\";\n    };\n    FileSelectionUi.prototype.fileBasedScanRegionActiveBorder = function () {\n        return \"6px dashed rgb(153 151 151)\";\n    };\n    FileSelectionUi.prototype.createDragAndDropMessage = function () {\n        var dragAndDropMessage = document.createElement(\"div\");\n        dragAndDropMessage.innerText\n            = _strings__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScannerStrings.dragAndDropMessage();\n        dragAndDropMessage.style.fontWeight = \"400\";\n        return dragAndDropMessage;\n    };\n    FileSelectionUi.prototype.setImageNameToButton = function (imageFileName) {\n        var MAX_CHARS = 20;\n        if (imageFileName.length > MAX_CHARS) {\n            var start8Chars = imageFileName.substring(0, 8);\n            var length_1 = imageFileName.length;\n            var last8Chars = imageFileName.substring(length_1 - 8, length_1);\n            imageFileName = \"\".concat(start8Chars, \"....\").concat(last8Chars);\n        }\n        var newText = _strings__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScannerStrings.fileSelectionChooseAnother()\n            + \" - \"\n            + imageFileName;\n        this.fileSelectionButton.innerText = newText;\n    };\n    FileSelectionUi.prototype.setInitialValueToButton = function () {\n        var initialText = _strings__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScannerStrings.fileSelectionChooseImage()\n            + \" - \"\n            + _strings__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScannerStrings.fileSelectionNoImageSelected();\n        this.fileSelectionButton.innerText = initialText;\n    };\n    FileSelectionUi.prototype.getFileScanInputId = function () {\n        return \"html5-qrcode-private-filescan-input\";\n    };\n    FileSelectionUi.create = function (parentElement, showOnRender, onFileSelected) {\n        var button = new FileSelectionUi(parentElement, showOnRender, onFileSelected);\n        return button;\n    };\n    return FileSelectionUi;\n}());\n\n//# sourceMappingURL=file-selection-ui.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS9zY2FubmVyL2ZpbGUtc2VsZWN0aW9uLXVpLmpzLmpzIiwibWFwcGluZ3MiOiI7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vdWkvc2Nhbm5lci9maWxlLXNlbGVjdGlvbi11aS5qcz85NWFlIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MgfSBmcm9tIFwiLi4vLi4vc3RyaW5nc1wiO1xuaW1wb3J0IHsgQmFzZVVpRWxlbWVudEZhY3RvcnksIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3NlcyB9IGZyb20gXCIuL2Jhc2VcIjtcbnZhciBGaWxlU2VsZWN0aW9uVWkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEZpbGVTZWxlY3Rpb25VaShwYXJlbnRFbGVtZW50LCBzaG93T25SZW5kZXIsIG9uRmlsZVNlbGVjdGVkKSB7XG4gICAgICAgIHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbiA9IHRoaXMuY3JlYXRlRmlsZUJhc2VkU2NhblJlZ2lvbigpO1xuICAgICAgICB0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb24uc3R5bGUuZGlzcGxheVxuICAgICAgICAgICAgPSBzaG93T25SZW5kZXIgPyBcImJsb2NrXCIgOiBcIm5vbmVcIjtcbiAgICAgICAgcGFyZW50RWxlbWVudC5hcHBlbmRDaGlsZCh0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb24pO1xuICAgICAgICB2YXIgZmlsZVNjYW5MYWJlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJsYWJlbFwiKTtcbiAgICAgICAgZmlsZVNjYW5MYWJlbC5zZXRBdHRyaWJ1dGUoXCJmb3JcIiwgdGhpcy5nZXRGaWxlU2NhbklucHV0SWQoKSk7XG4gICAgICAgIGZpbGVTY2FuTGFiZWwuc3R5bGUuZGlzcGxheSA9IFwiaW5saW5lLWJsb2NrXCI7XG4gICAgICAgIHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5hcHBlbmRDaGlsZChmaWxlU2NhbkxhYmVsKTtcbiAgICAgICAgdGhpcy5maWxlU2VsZWN0aW9uQnV0dG9uXG4gICAgICAgICAgICA9IEJhc2VVaUVsZW1lbnRGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoXCJidXR0b25cIiwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkZJTEVfU0VMRUNUSU9OX0JVVFRPTl9JRCk7XG4gICAgICAgIHRoaXMuc2V0SW5pdGlhbFZhbHVlVG9CdXR0b24oKTtcbiAgICAgICAgdGhpcy5maWxlU2VsZWN0aW9uQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBmdW5jdGlvbiAoXykge1xuICAgICAgICAgICAgZmlsZVNjYW5MYWJlbC5jbGljaygpO1xuICAgICAgICB9KTtcbiAgICAgICAgZmlsZVNjYW5MYWJlbC5hcHBlbmQodGhpcy5maWxlU2VsZWN0aW9uQnV0dG9uKTtcbiAgICAgICAgdGhpcy5maWxlU2NhbklucHV0XG4gICAgICAgICAgICA9IEJhc2VVaUVsZW1lbnRGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoXCJpbnB1dFwiLCB0aGlzLmdldEZpbGVTY2FuSW5wdXRJZCgpKTtcbiAgICAgICAgdGhpcy5maWxlU2NhbklucHV0LnR5cGUgPSBcImZpbGVcIjtcbiAgICAgICAgdGhpcy5maWxlU2NhbklucHV0LmFjY2VwdCA9IFwiaW1hZ2UvKlwiO1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW5wdXQuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICBmaWxlU2NhbkxhYmVsLmFwcGVuZENoaWxkKHRoaXMuZmlsZVNjYW5JbnB1dCk7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbnB1dC5hZGRFdmVudExpc3RlbmVyKFwiY2hhbmdlXCIsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBpZiAoZSA9PSBudWxsIHx8IGUudGFyZ2V0ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgdGFyZ2V0ID0gZS50YXJnZXQ7XG4gICAgICAgICAgICBpZiAodGFyZ2V0LmZpbGVzICYmIHRhcmdldC5maWxlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZmlsZUxpc3QgPSB0YXJnZXQuZmlsZXM7XG4gICAgICAgICAgICB2YXIgZmlsZSA9IGZpbGVMaXN0WzBdO1xuICAgICAgICAgICAgdmFyIGZpbGVOYW1lID0gZmlsZS5uYW1lO1xuICAgICAgICAgICAgJHRoaXMuc2V0SW1hZ2VOYW1lVG9CdXR0b24oZmlsZU5hbWUpO1xuICAgICAgICAgICAgb25GaWxlU2VsZWN0ZWQoZmlsZSk7XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgZHJhZ0FuZERyb3BNZXNzYWdlID0gdGhpcy5jcmVhdGVEcmFnQW5kRHJvcE1lc3NhZ2UoKTtcbiAgICAgICAgdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLmFwcGVuZENoaWxkKGRyYWdBbmREcm9wTWVzc2FnZSk7XG4gICAgICAgIHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5hZGRFdmVudExpc3RlbmVyKFwiZHJhZ2VudGVyXCIsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgJHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5ib3JkZXJcbiAgICAgICAgICAgICAgICA9ICR0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb25BY3RpdmVCb3JkZXIoKTtcbiAgICAgICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5hZGRFdmVudExpc3RlbmVyKFwiZHJhZ2xlYXZlXCIsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgJHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5ib3JkZXJcbiAgICAgICAgICAgICAgICA9ICR0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb25EZWZhdWx0Qm9yZGVyKCk7XG4gICAgICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb24uYWRkRXZlbnRMaXN0ZW5lcihcImRyYWdvdmVyXCIsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgJHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5ib3JkZXJcbiAgICAgICAgICAgICAgICA9ICR0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb25BY3RpdmVCb3JkZXIoKTtcbiAgICAgICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5hZGRFdmVudExpc3RlbmVyKFwiZHJvcFwiLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICR0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb24uc3R5bGUuYm9yZGVyXG4gICAgICAgICAgICAgICAgPSAkdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uRGVmYXVsdEJvcmRlcigpO1xuICAgICAgICAgICAgdmFyIGRhdGFUcmFuc2ZlciA9IGV2ZW50LmRhdGFUcmFuc2ZlcjtcbiAgICAgICAgICAgIGlmIChkYXRhVHJhbnNmZXIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZmlsZXMgPSBkYXRhVHJhbnNmZXIuZmlsZXM7XG4gICAgICAgICAgICAgICAgaWYgKCFmaWxlcyB8fCBmaWxlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgaXNBbnlGaWxlSW1hZ2UgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGZpbGVzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmaWxlID0gZmlsZXMuaXRlbShpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFmaWxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgaW1hZ2VUeXBlID0gL2ltYWdlLiovO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWZpbGUudHlwZS5tYXRjaChpbWFnZVR5cGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpc0FueUZpbGVJbWFnZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmaWxlTmFtZSA9IGZpbGUubmFtZTtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMuc2V0SW1hZ2VOYW1lVG9CdXR0b24oZmlsZU5hbWUpO1xuICAgICAgICAgICAgICAgICAgICBvbkZpbGVTZWxlY3RlZChmaWxlKTtcbiAgICAgICAgICAgICAgICAgICAgZHJhZ0FuZERyb3BNZXNzYWdlLmlubmVyVGV4dFxuICAgICAgICAgICAgICAgICAgICAgICAgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmRyYWdBbmREcm9wTWVzc2FnZSgpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCFpc0FueUZpbGVJbWFnZSkge1xuICAgICAgICAgICAgICAgICAgICBkcmFnQW5kRHJvcE1lc3NhZ2UuaW5uZXJUZXh0XG4gICAgICAgICAgICAgICAgICAgICAgICA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZHJhZ0FuZERyb3BNZXNzYWdlT25seUltYWdlcygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIEZpbGVTZWxlY3Rpb25VaS5wcm90b3R5cGUuaGlkZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgdGhpcy5maWxlU2NhbklucHV0LmRpc2FibGVkID0gdHJ1ZTtcbiAgICB9O1xuICAgIEZpbGVTZWxlY3Rpb25VaS5wcm90b3R5cGUuc2hvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLmRpc3BsYXkgPSBcImJsb2NrXCI7XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbnB1dC5kaXNhYmxlZCA9IGZhbHNlO1xuICAgIH07XG4gICAgRmlsZVNlbGVjdGlvblVpLnByb3RvdHlwZS5pc1Nob3dpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb24uc3R5bGUuZGlzcGxheSA9PT0gXCJibG9ja1wiO1xuICAgIH07XG4gICAgRmlsZVNlbGVjdGlvblVpLnByb3RvdHlwZS5yZXNldFZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW5wdXQudmFsdWUgPSBcIlwiO1xuICAgICAgICB0aGlzLnNldEluaXRpYWxWYWx1ZVRvQnV0dG9uKCk7XG4gICAgfTtcbiAgICBGaWxlU2VsZWN0aW9uVWkucHJvdG90eXBlLmNyZWF0ZUZpbGVCYXNlZFNjYW5SZWdpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBmaWxlQmFzZWRTY2FuUmVnaW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS50ZXh0QWxpZ24gPSBcImNlbnRlclwiO1xuICAgICAgICBmaWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLm1hcmdpbiA9IFwiYXV0b1wiO1xuICAgICAgICBmaWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLndpZHRoID0gXCI4MCVcIjtcbiAgICAgICAgZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5tYXhXaWR0aCA9IFwiNjAwcHhcIjtcbiAgICAgICAgZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5ib3JkZXJcbiAgICAgICAgICAgID0gdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uRGVmYXVsdEJvcmRlcigpO1xuICAgICAgICBmaWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLnBhZGRpbmcgPSBcIjEwcHhcIjtcbiAgICAgICAgZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5tYXJnaW5Cb3R0b20gPSBcIjEwcHhcIjtcbiAgICAgICAgcmV0dXJuIGZpbGVCYXNlZFNjYW5SZWdpb247XG4gICAgfTtcbiAgICBGaWxlU2VsZWN0aW9uVWkucHJvdG90eXBlLmZpbGVCYXNlZFNjYW5SZWdpb25EZWZhdWx0Qm9yZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCI2cHggZGFzaGVkICNlYmViZWJcIjtcbiAgICB9O1xuICAgIEZpbGVTZWxlY3Rpb25VaS5wcm90b3R5cGUuZmlsZUJhc2VkU2NhblJlZ2lvbkFjdGl2ZUJvcmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiNnB4IGRhc2hlZCByZ2IoMTUzIDE1MSAxNTEpXCI7XG4gICAgfTtcbiAgICBGaWxlU2VsZWN0aW9uVWkucHJvdG90eXBlLmNyZWF0ZURyYWdBbmREcm9wTWVzc2FnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGRyYWdBbmREcm9wTWVzc2FnZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIGRyYWdBbmREcm9wTWVzc2FnZS5pbm5lclRleHRcbiAgICAgICAgICAgID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5kcmFnQW5kRHJvcE1lc3NhZ2UoKTtcbiAgICAgICAgZHJhZ0FuZERyb3BNZXNzYWdlLnN0eWxlLmZvbnRXZWlnaHQgPSBcIjQwMFwiO1xuICAgICAgICByZXR1cm4gZHJhZ0FuZERyb3BNZXNzYWdlO1xuICAgIH07XG4gICAgRmlsZVNlbGVjdGlvblVpLnByb3RvdHlwZS5zZXRJbWFnZU5hbWVUb0J1dHRvbiA9IGZ1bmN0aW9uIChpbWFnZUZpbGVOYW1lKSB7XG4gICAgICAgIHZhciBNQVhfQ0hBUlMgPSAyMDtcbiAgICAgICAgaWYgKGltYWdlRmlsZU5hbWUubGVuZ3RoID4gTUFYX0NIQVJTKSB7XG4gICAgICAgICAgICB2YXIgc3RhcnQ4Q2hhcnMgPSBpbWFnZUZpbGVOYW1lLnN1YnN0cmluZygwLCA4KTtcbiAgICAgICAgICAgIHZhciBsZW5ndGhfMSA9IGltYWdlRmlsZU5hbWUubGVuZ3RoO1xuICAgICAgICAgICAgdmFyIGxhc3Q4Q2hhcnMgPSBpbWFnZUZpbGVOYW1lLnN1YnN0cmluZyhsZW5ndGhfMSAtIDgsIGxlbmd0aF8xKTtcbiAgICAgICAgICAgIGltYWdlRmlsZU5hbWUgPSBcIlwiLmNvbmNhdChzdGFydDhDaGFycywgXCIuLi4uXCIpLmNvbmNhdChsYXN0OENoYXJzKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbmV3VGV4dCA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZmlsZVNlbGVjdGlvbkNob29zZUFub3RoZXIoKVxuICAgICAgICAgICAgKyBcIiAtIFwiXG4gICAgICAgICAgICArIGltYWdlRmlsZU5hbWU7XG4gICAgICAgIHRoaXMuZmlsZVNlbGVjdGlvbkJ1dHRvbi5pbm5lclRleHQgPSBuZXdUZXh0O1xuICAgIH07XG4gICAgRmlsZVNlbGVjdGlvblVpLnByb3RvdHlwZS5zZXRJbml0aWFsVmFsdWVUb0J1dHRvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGluaXRpYWxUZXh0ID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5maWxlU2VsZWN0aW9uQ2hvb3NlSW1hZ2UoKVxuICAgICAgICAgICAgKyBcIiAtIFwiXG4gICAgICAgICAgICArIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZmlsZVNlbGVjdGlvbk5vSW1hZ2VTZWxlY3RlZCgpO1xuICAgICAgICB0aGlzLmZpbGVTZWxlY3Rpb25CdXR0b24uaW5uZXJUZXh0ID0gaW5pdGlhbFRleHQ7XG4gICAgfTtcbiAgICBGaWxlU2VsZWN0aW9uVWkucHJvdG90eXBlLmdldEZpbGVTY2FuSW5wdXRJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiaHRtbDUtcXJjb2RlLXByaXZhdGUtZmlsZXNjYW4taW5wdXRcIjtcbiAgICB9O1xuICAgIEZpbGVTZWxlY3Rpb25VaS5jcmVhdGUgPSBmdW5jdGlvbiAocGFyZW50RWxlbWVudCwgc2hvd09uUmVuZGVyLCBvbkZpbGVTZWxlY3RlZCkge1xuICAgICAgICB2YXIgYnV0dG9uID0gbmV3IEZpbGVTZWxlY3Rpb25VaShwYXJlbnRFbGVtZW50LCBzaG93T25SZW5kZXIsIG9uRmlsZVNlbGVjdGVkKTtcbiAgICAgICAgcmV0dXJuIGJ1dHRvbjtcbiAgICB9O1xuICAgIHJldHVybiBGaWxlU2VsZWN0aW9uVWk7XG59KCkpO1xuZXhwb3J0IHsgRmlsZVNlbGVjdGlvblVpIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1maWxlLXNlbGVjdGlvbi11aS5qcy5tYXAiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/ui/scanner/file-selection-ui.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/ui/scanner/scan-type-selector.js":
+/*!************************************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/ui/scanner/scan-type-selector.js ***!
+  \************************************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   ScanTypeSelector: () => (/* binding */ ScanTypeSelector)\n/* harmony export */ });\n/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../core */ \"./node_modules/html5-qrcode/esm/core.js\");\n\nvar ScanTypeSelector = (function () {\n    function ScanTypeSelector(supportedScanTypes) {\n        this.supportedScanTypes = this.validateAndReturnScanTypes(supportedScanTypes);\n    }\n    ScanTypeSelector.prototype.getDefaultScanType = function () {\n        return this.supportedScanTypes[0];\n    };\n    ScanTypeSelector.prototype.hasMoreThanOneScanType = function () {\n        return this.supportedScanTypes.length > 1;\n    };\n    ScanTypeSelector.prototype.isCameraScanRequired = function () {\n        for (var _i = 0, _a = this.supportedScanTypes; _i < _a.length; _i++) {\n            var scanType = _a[_i];\n            if (ScanTypeSelector.isCameraScanType(scanType)) {\n                return true;\n            }\n        }\n        return false;\n    };\n    ScanTypeSelector.isCameraScanType = function (scanType) {\n        return scanType === _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScanType.SCAN_TYPE_CAMERA;\n    };\n    ScanTypeSelector.isFileScanType = function (scanType) {\n        return scanType === _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScanType.SCAN_TYPE_FILE;\n    };\n    ScanTypeSelector.prototype.validateAndReturnScanTypes = function (supportedScanTypes) {\n        if (!supportedScanTypes || supportedScanTypes.length === 0) {\n            return _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeConstants.DEFAULT_SUPPORTED_SCAN_TYPE;\n        }\n        var maxExpectedValues = _core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeConstants.DEFAULT_SUPPORTED_SCAN_TYPE.length;\n        if (supportedScanTypes.length > maxExpectedValues) {\n            throw \"Max \".concat(maxExpectedValues, \" values expected for \")\n                + \"supportedScanTypes\";\n        }\n        for (var _i = 0, supportedScanTypes_1 = supportedScanTypes; _i < supportedScanTypes_1.length; _i++) {\n            var scanType = supportedScanTypes_1[_i];\n            if (!_core__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeConstants.DEFAULT_SUPPORTED_SCAN_TYPE.includes(scanType)) {\n                throw \"Unsupported scan type \".concat(scanType);\n            }\n        }\n        return supportedScanTypes;\n    };\n    return ScanTypeSelector;\n}());\n\n//# sourceMappingURL=scan-type-selector.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS9zY2FubmVyL3NjYW4tdHlwZS1zZWxlY3Rvci5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS9zY2FubmVyL3NjYW4tdHlwZS1zZWxlY3Rvci5qcz9hYmVlIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0bWw1UXJjb2RlU2NhblR5cGUsIEh0bWw1UXJjb2RlQ29uc3RhbnRzIH0gZnJvbSBcIi4uLy4uL2NvcmVcIjtcbnZhciBTY2FuVHlwZVNlbGVjdG9yID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBTY2FuVHlwZVNlbGVjdG9yKHN1cHBvcnRlZFNjYW5UeXBlcykge1xuICAgICAgICB0aGlzLnN1cHBvcnRlZFNjYW5UeXBlcyA9IHRoaXMudmFsaWRhdGVBbmRSZXR1cm5TY2FuVHlwZXMoc3VwcG9ydGVkU2NhblR5cGVzKTtcbiAgICB9XG4gICAgU2NhblR5cGVTZWxlY3Rvci5wcm90b3R5cGUuZ2V0RGVmYXVsdFNjYW5UeXBlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdXBwb3J0ZWRTY2FuVHlwZXNbMF07XG4gICAgfTtcbiAgICBTY2FuVHlwZVNlbGVjdG9yLnByb3RvdHlwZS5oYXNNb3JlVGhhbk9uZVNjYW5UeXBlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdXBwb3J0ZWRTY2FuVHlwZXMubGVuZ3RoID4gMTtcbiAgICB9O1xuICAgIFNjYW5UeXBlU2VsZWN0b3IucHJvdG90eXBlLmlzQ2FtZXJhU2NhblJlcXVpcmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5zdXBwb3J0ZWRTY2FuVHlwZXM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2NhblR5cGUgPSBfYVtfaV07XG4gICAgICAgICAgICBpZiAoU2NhblR5cGVTZWxlY3Rvci5pc0NhbWVyYVNjYW5UeXBlKHNjYW5UeXBlKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIFNjYW5UeXBlU2VsZWN0b3IuaXNDYW1lcmFTY2FuVHlwZSA9IGZ1bmN0aW9uIChzY2FuVHlwZSkge1xuICAgICAgICByZXR1cm4gc2NhblR5cGUgPT09IEh0bWw1UXJjb2RlU2NhblR5cGUuU0NBTl9UWVBFX0NBTUVSQTtcbiAgICB9O1xuICAgIFNjYW5UeXBlU2VsZWN0b3IuaXNGaWxlU2NhblR5cGUgPSBmdW5jdGlvbiAoc2NhblR5cGUpIHtcbiAgICAgICAgcmV0dXJuIHNjYW5UeXBlID09PSBIdG1sNVFyY29kZVNjYW5UeXBlLlNDQU5fVFlQRV9GSUxFO1xuICAgIH07XG4gICAgU2NhblR5cGVTZWxlY3Rvci5wcm90b3R5cGUudmFsaWRhdGVBbmRSZXR1cm5TY2FuVHlwZXMgPSBmdW5jdGlvbiAoc3VwcG9ydGVkU2NhblR5cGVzKSB7XG4gICAgICAgIGlmICghc3VwcG9ydGVkU2NhblR5cGVzIHx8IHN1cHBvcnRlZFNjYW5UeXBlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1NVUFBPUlRFRF9TQ0FOX1RZUEU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1heEV4cGVjdGVkVmFsdWVzID0gSHRtbDVRcmNvZGVDb25zdGFudHMuREVGQVVMVF9TVVBQT1JURURfU0NBTl9UWVBFLmxlbmd0aDtcbiAgICAgICAgaWYgKHN1cHBvcnRlZFNjYW5UeXBlcy5sZW5ndGggPiBtYXhFeHBlY3RlZFZhbHVlcykge1xuICAgICAgICAgICAgdGhyb3cgXCJNYXggXCIuY29uY2F0KG1heEV4cGVjdGVkVmFsdWVzLCBcIiB2YWx1ZXMgZXhwZWN0ZWQgZm9yIFwiKVxuICAgICAgICAgICAgICAgICsgXCJzdXBwb3J0ZWRTY2FuVHlwZXNcIjtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIHN1cHBvcnRlZFNjYW5UeXBlc18xID0gc3VwcG9ydGVkU2NhblR5cGVzOyBfaSA8IHN1cHBvcnRlZFNjYW5UeXBlc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHNjYW5UeXBlID0gc3VwcG9ydGVkU2NhblR5cGVzXzFbX2ldO1xuICAgICAgICAgICAgaWYgKCFIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1NVUFBPUlRFRF9TQ0FOX1RZUEVcbiAgICAgICAgICAgICAgICAuaW5jbHVkZXMoc2NhblR5cGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgXCJVbnN1cHBvcnRlZCBzY2FuIHR5cGUgXCIuY29uY2F0KHNjYW5UeXBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3VwcG9ydGVkU2NhblR5cGVzO1xuICAgIH07XG4gICAgcmV0dXJuIFNjYW5UeXBlU2VsZWN0b3I7XG59KCkpO1xuZXhwb3J0IHsgU2NhblR5cGVTZWxlY3RvciB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c2Nhbi10eXBlLXNlbGVjdG9yLmpzLm1hcCJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/ui/scanner/scan-type-selector.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/ui/scanner/torch-button.js":
+/*!******************************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/ui/scanner/torch-button.js ***!
+  \******************************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   TorchButton: () => (/* binding */ TorchButton)\n/* harmony export */ });\n/* harmony import */ var _strings__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../strings */ \"./node_modules/html5-qrcode/esm/strings.js\");\n/* harmony import */ var _base__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./base */ \"./node_modules/html5-qrcode/esm/ui/scanner/base.js\");\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar __generator = (undefined && undefined.__generator) || function (thisArg, body) {\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n    return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n    function verb(n) { return function (v) { return step([n, v]); }; }\n    function step(op) {\n        if (f) throw new TypeError(\"Generator is already executing.\");\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\n            if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n            if (y = 0, t) op = [op[0] & 2, t.value];\n            switch (op[0]) {\n                case 0: case 1: t = op; break;\n                case 4: _.label++; return { value: op[1], done: false };\n                case 5: _.label++; y = op[1]; op = [0]; continue;\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\n                default:\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                    if (t[2]) _.ops.pop();\n                    _.trys.pop(); continue;\n            }\n            op = body.call(thisArg, _);\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n    }\n};\n\n\nvar TorchController = (function () {\n    function TorchController(torchCapability, buttonController, onTorchActionFailureCallback) {\n        this.isTorchOn = false;\n        this.torchCapability = torchCapability;\n        this.buttonController = buttonController;\n        this.onTorchActionFailureCallback = onTorchActionFailureCallback;\n    }\n    TorchController.prototype.isTorchEnabled = function () {\n        return this.isTorchOn;\n    };\n    TorchController.prototype.flipState = function () {\n        return __awaiter(this, void 0, void 0, function () {\n            var isTorchOnExpected, error_1;\n            return __generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0:\n                        this.buttonController.disable();\n                        isTorchOnExpected = !this.isTorchOn;\n                        _a.label = 1;\n                    case 1:\n                        _a.trys.push([1, 3, , 4]);\n                        return [4, this.torchCapability.apply(isTorchOnExpected)];\n                    case 2:\n                        _a.sent();\n                        this.updateUiBasedOnLatestSettings(this.torchCapability.value(), isTorchOnExpected);\n                        return [3, 4];\n                    case 3:\n                        error_1 = _a.sent();\n                        this.propagateFailure(isTorchOnExpected, error_1);\n                        this.buttonController.enable();\n                        return [3, 4];\n                    case 4: return [2];\n                }\n            });\n        });\n    };\n    TorchController.prototype.updateUiBasedOnLatestSettings = function (isTorchOn, isTorchOnExpected) {\n        if (isTorchOn === isTorchOnExpected) {\n            this.buttonController.setText(isTorchOnExpected\n                ? _strings__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScannerStrings.torchOffButton()\n                : _strings__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScannerStrings.torchOnButton());\n            this.isTorchOn = isTorchOnExpected;\n        }\n        else {\n            this.propagateFailure(isTorchOnExpected);\n        }\n        this.buttonController.enable();\n    };\n    TorchController.prototype.propagateFailure = function (isTorchOnExpected, error) {\n        var errorMessage = isTorchOnExpected\n            ? _strings__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScannerStrings.torchOnFailedMessage()\n            : _strings__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScannerStrings.torchOffFailedMessage();\n        if (error) {\n            errorMessage += \"; Error = \" + error;\n        }\n        this.onTorchActionFailureCallback(errorMessage);\n    };\n    TorchController.prototype.reset = function () {\n        this.isTorchOn = false;\n    };\n    return TorchController;\n}());\nvar TorchButton = (function () {\n    function TorchButton(torchCapability, onTorchActionFailureCallback) {\n        this.onTorchActionFailureCallback = onTorchActionFailureCallback;\n        this.torchButton\n            = _base__WEBPACK_IMPORTED_MODULE_1__.BaseUiElementFactory.createElement(\"button\", _base__WEBPACK_IMPORTED_MODULE_1__.PublicUiElementIdAndClasses.TORCH_BUTTON_ID);\n        this.torchController = new TorchController(torchCapability, this, onTorchActionFailureCallback);\n    }\n    TorchButton.prototype.render = function (parentElement, torchButtonOptions) {\n        var _this = this;\n        this.torchButton.innerText\n            = _strings__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScannerStrings.torchOnButton();\n        this.torchButton.style.display = torchButtonOptions.display;\n        this.torchButton.style.marginLeft = torchButtonOptions.marginLeft;\n        var $this = this;\n        this.torchButton.addEventListener(\"click\", function (_) { return __awaiter(_this, void 0, void 0, function () {\n            return __generator(this, function (_a) {\n                switch (_a.label) {\n                    case 0: return [4, $this.torchController.flipState()];\n                    case 1:\n                        _a.sent();\n                        if ($this.torchController.isTorchEnabled()) {\n                            $this.torchButton.classList.remove(_base__WEBPACK_IMPORTED_MODULE_1__.PublicUiElementIdAndClasses.TORCH_BUTTON_CLASS_TORCH_OFF);\n                            $this.torchButton.classList.add(_base__WEBPACK_IMPORTED_MODULE_1__.PublicUiElementIdAndClasses.TORCH_BUTTON_CLASS_TORCH_ON);\n                        }\n                        else {\n                            $this.torchButton.classList.remove(_base__WEBPACK_IMPORTED_MODULE_1__.PublicUiElementIdAndClasses.TORCH_BUTTON_CLASS_TORCH_ON);\n                            $this.torchButton.classList.add(_base__WEBPACK_IMPORTED_MODULE_1__.PublicUiElementIdAndClasses.TORCH_BUTTON_CLASS_TORCH_OFF);\n                        }\n                        return [2];\n                }\n            });\n        }); });\n        parentElement.appendChild(this.torchButton);\n    };\n    TorchButton.prototype.updateTorchCapability = function (torchCapability) {\n        this.torchController = new TorchController(torchCapability, this, this.onTorchActionFailureCallback);\n    };\n    TorchButton.prototype.getTorchButton = function () {\n        return this.torchButton;\n    };\n    TorchButton.prototype.hide = function () {\n        this.torchButton.style.display = \"none\";\n    };\n    TorchButton.prototype.show = function () {\n        this.torchButton.style.display = \"inline-block\";\n    };\n    TorchButton.prototype.disable = function () {\n        this.torchButton.disabled = true;\n    };\n    TorchButton.prototype.enable = function () {\n        this.torchButton.disabled = false;\n    };\n    TorchButton.prototype.setText = function (text) {\n        this.torchButton.innerText = text;\n    };\n    TorchButton.prototype.reset = function () {\n        this.torchButton.innerText = _strings__WEBPACK_IMPORTED_MODULE_0__.Html5QrcodeScannerStrings.torchOnButton();\n        this.torchController.reset();\n    };\n    TorchButton.create = function (parentElement, torchCapability, torchButtonOptions, onTorchActionFailureCallback) {\n        var button = new TorchButton(torchCapability, onTorchActionFailureCallback);\n        button.render(parentElement, torchButtonOptions);\n        return button;\n    };\n    return TorchButton;\n}());\n\n//# sourceMappingURL=torch-button.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS9zY2FubmVyL3RvcmNoLWJ1dHRvbi5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS9zY2FubmVyL3RvcmNoLWJ1dHRvbi5qcz8zMzAzIl0sInNvdXJjZXNDb250ZW50IjpbInZhciBfX2F3YWl0ZXIgPSAodGhpcyAmJiB0aGlzLl9fYXdhaXRlcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xuICAgIGZ1bmN0aW9uIGFkb3B0KHZhbHVlKSB7IHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUodmFsdWUpOyB9KTsgfVxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IGFkb3B0KHJlc3VsdC52YWx1ZSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XG4gICAgfSk7XG59O1xudmFyIF9fZ2VuZXJhdG9yID0gKHRoaXMgJiYgdGhpcy5fX2dlbmVyYXRvcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIGJvZHkpIHtcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xuICAgIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcbiAgICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xuICAgICAgICB3aGlsZSAoZyAmJiAoZyA9IDAsIG9wWzBdICYmIChfID0gMCkpLCBfKSB0cnkge1xuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xuICAgICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XG4gICAgfVxufTtcbmltcG9ydCB7IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MgfSBmcm9tIFwiLi4vLi4vc3RyaW5nc1wiO1xuaW1wb3J0IHsgQmFzZVVpRWxlbWVudEZhY3RvcnksIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3NlcyB9IGZyb20gXCIuL2Jhc2VcIjtcbnZhciBUb3JjaENvbnRyb2xsZXIgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFRvcmNoQ29udHJvbGxlcih0b3JjaENhcGFiaWxpdHksIGJ1dHRvbkNvbnRyb2xsZXIsIG9uVG9yY2hBY3Rpb25GYWlsdXJlQ2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5pc1RvcmNoT24gPSBmYWxzZTtcbiAgICAgICAgdGhpcy50b3JjaENhcGFiaWxpdHkgPSB0b3JjaENhcGFiaWxpdHk7XG4gICAgICAgIHRoaXMuYnV0dG9uQ29udHJvbGxlciA9IGJ1dHRvbkNvbnRyb2xsZXI7XG4gICAgICAgIHRoaXMub25Ub3JjaEFjdGlvbkZhaWx1cmVDYWxsYmFjayA9IG9uVG9yY2hBY3Rpb25GYWlsdXJlQ2FsbGJhY2s7XG4gICAgfVxuICAgIFRvcmNoQ29udHJvbGxlci5wcm90b3R5cGUuaXNUb3JjaEVuYWJsZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlzVG9yY2hPbjtcbiAgICB9O1xuICAgIFRvcmNoQ29udHJvbGxlci5wcm90b3R5cGUuZmxpcFN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgaXNUb3JjaE9uRXhwZWN0ZWQsIGVycm9yXzE7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChfYS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1dHRvbkNvbnRyb2xsZXIuZGlzYWJsZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNUb3JjaE9uRXhwZWN0ZWQgPSAhdGhpcy5pc1RvcmNoT247XG4gICAgICAgICAgICAgICAgICAgICAgICBfYS5sYWJlbCA9IDE7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLnRyeXMucHVzaChbMSwgMywgLCA0XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQsIHRoaXMudG9yY2hDYXBhYmlsaXR5LmFwcGx5KGlzVG9yY2hPbkV4cGVjdGVkKV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlVWlCYXNlZE9uTGF0ZXN0U2V0dGluZ3ModGhpcy50b3JjaENhcGFiaWxpdHkudmFsdWUoKSwgaXNUb3JjaE9uRXhwZWN0ZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFszLCA0XTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JfMSA9IF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucHJvcGFnYXRlRmFpbHVyZShpc1RvcmNoT25FeHBlY3RlZCwgZXJyb3JfMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1dHRvbkNvbnRyb2xsZXIuZW5hYmxlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzMsIDRdO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ6IHJldHVybiBbMl07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgVG9yY2hDb250cm9sbGVyLnByb3RvdHlwZS51cGRhdGVVaUJhc2VkT25MYXRlc3RTZXR0aW5ncyA9IGZ1bmN0aW9uIChpc1RvcmNoT24sIGlzVG9yY2hPbkV4cGVjdGVkKSB7XG4gICAgICAgIGlmIChpc1RvcmNoT24gPT09IGlzVG9yY2hPbkV4cGVjdGVkKSB7XG4gICAgICAgICAgICB0aGlzLmJ1dHRvbkNvbnRyb2xsZXIuc2V0VGV4dChpc1RvcmNoT25FeHBlY3RlZFxuICAgICAgICAgICAgICAgID8gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50b3JjaE9mZkJ1dHRvbigpXG4gICAgICAgICAgICAgICAgOiBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRvcmNoT25CdXR0b24oKSk7XG4gICAgICAgICAgICB0aGlzLmlzVG9yY2hPbiA9IGlzVG9yY2hPbkV4cGVjdGVkO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5wcm9wYWdhdGVGYWlsdXJlKGlzVG9yY2hPbkV4cGVjdGVkKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJ1dHRvbkNvbnRyb2xsZXIuZW5hYmxlKCk7XG4gICAgfTtcbiAgICBUb3JjaENvbnRyb2xsZXIucHJvdG90eXBlLnByb3BhZ2F0ZUZhaWx1cmUgPSBmdW5jdGlvbiAoaXNUb3JjaE9uRXhwZWN0ZWQsIGVycm9yKSB7XG4gICAgICAgIHZhciBlcnJvck1lc3NhZ2UgPSBpc1RvcmNoT25FeHBlY3RlZFxuICAgICAgICAgICAgPyBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRvcmNoT25GYWlsZWRNZXNzYWdlKClcbiAgICAgICAgICAgIDogSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50b3JjaE9mZkZhaWxlZE1lc3NhZ2UoKTtcbiAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICBlcnJvck1lc3NhZ2UgKz0gXCI7IEVycm9yID0gXCIgKyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9uVG9yY2hBY3Rpb25GYWlsdXJlQ2FsbGJhY2soZXJyb3JNZXNzYWdlKTtcbiAgICB9O1xuICAgIFRvcmNoQ29udHJvbGxlci5wcm90b3R5cGUucmVzZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuaXNUb3JjaE9uID0gZmFsc2U7XG4gICAgfTtcbiAgICByZXR1cm4gVG9yY2hDb250cm9sbGVyO1xufSgpKTtcbnZhciBUb3JjaEJ1dHRvbiA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gVG9yY2hCdXR0b24odG9yY2hDYXBhYmlsaXR5LCBvblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMub25Ub3JjaEFjdGlvbkZhaWx1cmVDYWxsYmFjayA9IG9uVG9yY2hBY3Rpb25GYWlsdXJlQ2FsbGJhY2s7XG4gICAgICAgIHRoaXMudG9yY2hCdXR0b25cbiAgICAgICAgICAgID0gQmFzZVVpRWxlbWVudEZhY3RvcnkuY3JlYXRlRWxlbWVudChcImJ1dHRvblwiLCBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuVE9SQ0hfQlVUVE9OX0lEKTtcbiAgICAgICAgdGhpcy50b3JjaENvbnRyb2xsZXIgPSBuZXcgVG9yY2hDb250cm9sbGVyKHRvcmNoQ2FwYWJpbGl0eSwgdGhpcywgb25Ub3JjaEFjdGlvbkZhaWx1cmVDYWxsYmFjayk7XG4gICAgfVxuICAgIFRvcmNoQnV0dG9uLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocGFyZW50RWxlbWVudCwgdG9yY2hCdXR0b25PcHRpb25zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMudG9yY2hCdXR0b24uaW5uZXJUZXh0XG4gICAgICAgICAgICA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudG9yY2hPbkJ1dHRvbigpO1xuICAgICAgICB0aGlzLnRvcmNoQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSB0b3JjaEJ1dHRvbk9wdGlvbnMuZGlzcGxheTtcbiAgICAgICAgdGhpcy50b3JjaEJ1dHRvbi5zdHlsZS5tYXJnaW5MZWZ0ID0gdG9yY2hCdXR0b25PcHRpb25zLm1hcmdpbkxlZnQ7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMudG9yY2hCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGZ1bmN0aW9uIChfKSB7IHJldHVybiBfX2F3YWl0ZXIoX3RoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChfYS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6IHJldHVybiBbNCwgJHRoaXMudG9yY2hDb250cm9sbGVyLmZsaXBTdGF0ZSgpXTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgX2Euc2VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCR0aGlzLnRvcmNoQ29udHJvbGxlci5pc1RvcmNoRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMudG9yY2hCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuVE9SQ0hfQlVUVE9OX0NMQVNTX1RPUkNIX09GRik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMudG9yY2hCdXR0b24uY2xhc3NMaXN0LmFkZChQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuVE9SQ0hfQlVUVE9OX0NMQVNTX1RPUkNIX09OKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLnRvcmNoQnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlRPUkNIX0JVVFRPTl9DTEFTU19UT1JDSF9PTik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMudG9yY2hCdXR0b24uY2xhc3NMaXN0LmFkZChQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuVE9SQ0hfQlVUVE9OX0NMQVNTX1RPUkNIX09GRik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzJdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTsgfSk7XG4gICAgICAgIHBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQodGhpcy50b3JjaEJ1dHRvbik7XG4gICAgfTtcbiAgICBUb3JjaEJ1dHRvbi5wcm90b3R5cGUudXBkYXRlVG9yY2hDYXBhYmlsaXR5ID0gZnVuY3Rpb24gKHRvcmNoQ2FwYWJpbGl0eSkge1xuICAgICAgICB0aGlzLnRvcmNoQ29udHJvbGxlciA9IG5ldyBUb3JjaENvbnRyb2xsZXIodG9yY2hDYXBhYmlsaXR5LCB0aGlzLCB0aGlzLm9uVG9yY2hBY3Rpb25GYWlsdXJlQ2FsbGJhY2spO1xuICAgIH07XG4gICAgVG9yY2hCdXR0b24ucHJvdG90eXBlLmdldFRvcmNoQnV0dG9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy50b3JjaEJ1dHRvbjtcbiAgICB9O1xuICAgIFRvcmNoQnV0dG9uLnByb3RvdHlwZS5oaWRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnRvcmNoQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICB9O1xuICAgIFRvcmNoQnV0dG9uLnByb3RvdHlwZS5zaG93ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnRvcmNoQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSBcImlubGluZS1ibG9ja1wiO1xuICAgIH07XG4gICAgVG9yY2hCdXR0b24ucHJvdG90eXBlLmRpc2FibGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudG9yY2hCdXR0b24uZGlzYWJsZWQgPSB0cnVlO1xuICAgIH07XG4gICAgVG9yY2hCdXR0b24ucHJvdG90eXBlLmVuYWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy50b3JjaEJ1dHRvbi5kaXNhYmxlZCA9IGZhbHNlO1xuICAgIH07XG4gICAgVG9yY2hCdXR0b24ucHJvdG90eXBlLnNldFRleHQgPSBmdW5jdGlvbiAodGV4dCkge1xuICAgICAgICB0aGlzLnRvcmNoQnV0dG9uLmlubmVyVGV4dCA9IHRleHQ7XG4gICAgfTtcbiAgICBUb3JjaEJ1dHRvbi5wcm90b3R5cGUucmVzZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudG9yY2hCdXR0b24uaW5uZXJUZXh0ID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50b3JjaE9uQnV0dG9uKCk7XG4gICAgICAgIHRoaXMudG9yY2hDb250cm9sbGVyLnJlc2V0KCk7XG4gICAgfTtcbiAgICBUb3JjaEJ1dHRvbi5jcmVhdGUgPSBmdW5jdGlvbiAocGFyZW50RWxlbWVudCwgdG9yY2hDYXBhYmlsaXR5LCB0b3JjaEJ1dHRvbk9wdGlvbnMsIG9uVG9yY2hBY3Rpb25GYWlsdXJlQ2FsbGJhY2spIHtcbiAgICAgICAgdmFyIGJ1dHRvbiA9IG5ldyBUb3JjaEJ1dHRvbih0b3JjaENhcGFiaWxpdHksIG9uVG9yY2hBY3Rpb25GYWlsdXJlQ2FsbGJhY2spO1xuICAgICAgICBidXR0b24ucmVuZGVyKHBhcmVudEVsZW1lbnQsIHRvcmNoQnV0dG9uT3B0aW9ucyk7XG4gICAgICAgIHJldHVybiBidXR0b247XG4gICAgfTtcbiAgICByZXR1cm4gVG9yY2hCdXR0b247XG59KCkpO1xuZXhwb3J0IHsgVG9yY2hCdXR0b24gfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXRvcmNoLWJ1dHRvbi5qcy5tYXAiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/ui/scanner/torch-button.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/utils.js":
+/*!************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/utils.js ***!
+  \************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   VideoConstraintsUtil: () => (/* binding */ VideoConstraintsUtil)\n/* harmony export */ });\nvar VideoConstraintsUtil = (function () {\n    function VideoConstraintsUtil() {\n    }\n    VideoConstraintsUtil.isMediaStreamConstraintsValid = function (videoConstraints, logger) {\n        if (typeof videoConstraints !== \"object\") {\n            var typeofVideoConstraints = typeof videoConstraints;\n            logger.logError(\"videoConstraints should be of type object, the \"\n                + \"object passed is of type \".concat(typeofVideoConstraints, \".\"), true);\n            return false;\n        }\n        var bannedKeys = [\n            \"autoGainControl\",\n            \"channelCount\",\n            \"echoCancellation\",\n            \"latency\",\n            \"noiseSuppression\",\n            \"sampleRate\",\n            \"sampleSize\",\n            \"volume\"\n        ];\n        var bannedkeysSet = new Set(bannedKeys);\n        var keysInVideoConstraints = Object.keys(videoConstraints);\n        for (var _i = 0, keysInVideoConstraints_1 = keysInVideoConstraints; _i < keysInVideoConstraints_1.length; _i++) {\n            var key = keysInVideoConstraints_1[_i];\n            if (bannedkeysSet.has(key)) {\n                logger.logError(\"\".concat(key, \" is not supported videoConstaints.\"), true);\n                return false;\n            }\n        }\n        return true;\n    };\n    return VideoConstraintsUtil;\n}());\n\n//# sourceMappingURL=utils.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91dGlscy5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL3V0aWxzLmpzPzYxNjQiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIFZpZGVvQ29uc3RyYWludHNVdGlsID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBWaWRlb0NvbnN0cmFpbnRzVXRpbCgpIHtcbiAgICB9XG4gICAgVmlkZW9Db25zdHJhaW50c1V0aWwuaXNNZWRpYVN0cmVhbUNvbnN0cmFpbnRzVmFsaWQgPSBmdW5jdGlvbiAodmlkZW9Db25zdHJhaW50cywgbG9nZ2VyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgdmlkZW9Db25zdHJhaW50cyAhPT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgdmFyIHR5cGVvZlZpZGVvQ29uc3RyYWludHMgPSB0eXBlb2YgdmlkZW9Db25zdHJhaW50cztcbiAgICAgICAgICAgIGxvZ2dlci5sb2dFcnJvcihcInZpZGVvQ29uc3RyYWludHMgc2hvdWxkIGJlIG9mIHR5cGUgb2JqZWN0LCB0aGUgXCJcbiAgICAgICAgICAgICAgICArIFwib2JqZWN0IHBhc3NlZCBpcyBvZiB0eXBlIFwiLmNvbmNhdCh0eXBlb2ZWaWRlb0NvbnN0cmFpbnRzLCBcIi5cIiksIHRydWUpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBiYW5uZWRLZXlzID0gW1xuICAgICAgICAgICAgXCJhdXRvR2FpbkNvbnRyb2xcIixcbiAgICAgICAgICAgIFwiY2hhbm5lbENvdW50XCIsXG4gICAgICAgICAgICBcImVjaG9DYW5jZWxsYXRpb25cIixcbiAgICAgICAgICAgIFwibGF0ZW5jeVwiLFxuICAgICAgICAgICAgXCJub2lzZVN1cHByZXNzaW9uXCIsXG4gICAgICAgICAgICBcInNhbXBsZVJhdGVcIixcbiAgICAgICAgICAgIFwic2FtcGxlU2l6ZVwiLFxuICAgICAgICAgICAgXCJ2b2x1bWVcIlxuICAgICAgICBdO1xuICAgICAgICB2YXIgYmFubmVka2V5c1NldCA9IG5ldyBTZXQoYmFubmVkS2V5cyk7XG4gICAgICAgIHZhciBrZXlzSW5WaWRlb0NvbnN0cmFpbnRzID0gT2JqZWN0LmtleXModmlkZW9Db25zdHJhaW50cyk7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwga2V5c0luVmlkZW9Db25zdHJhaW50c18xID0ga2V5c0luVmlkZW9Db25zdHJhaW50czsgX2kgPCBrZXlzSW5WaWRlb0NvbnN0cmFpbnRzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0ga2V5c0luVmlkZW9Db25zdHJhaW50c18xW19pXTtcbiAgICAgICAgICAgIGlmIChiYW5uZWRrZXlzU2V0LmhhcyhrZXkpKSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmxvZ0Vycm9yKFwiXCIuY29uY2F0KGtleSwgXCIgaXMgbm90IHN1cHBvcnRlZCB2aWRlb0NvbnN0YWludHMuXCIpLCB0cnVlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICByZXR1cm4gVmlkZW9Db25zdHJhaW50c1V0aWw7XG59KCkpO1xuZXhwb3J0IHsgVmlkZW9Db25zdHJhaW50c1V0aWwgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXV0aWxzLmpzLm1hcCJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/utils.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/esm/zxing-html5-qrcode-decoder.js":
+/*!*********************************************************************!*\
+  !*** ./node_modules/html5-qrcode/esm/zxing-html5-qrcode-decoder.js ***!
+  \*********************************************************************/
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   ZXingHtml5QrcodeDecoder: () => (/* binding */ ZXingHtml5QrcodeDecoder)\n/* harmony export */ });\n/* harmony import */ var _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../third_party/zxing-js.umd */ \"./node_modules/html5-qrcode/third_party/zxing-js.umd.js\");\n/* harmony import */ var _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./core */ \"./node_modules/html5-qrcode/esm/core.js\");\n\n\nvar ZXingHtml5QrcodeDecoder = (function () {\n    function ZXingHtml5QrcodeDecoder(requestedFormats, verbose, logger) {\n        this.formatMap = new Map([\n            [_core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.QR_CODE, _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.QR_CODE],\n            [_core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.AZTEC, _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.AZTEC],\n            [_core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.CODABAR, _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.CODABAR],\n            [_core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.CODE_39, _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.CODE_39],\n            [_core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.CODE_93, _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.CODE_93],\n            [\n                _core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.CODE_128,\n                _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.CODE_128\n            ],\n            [\n                _core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.DATA_MATRIX,\n                _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.DATA_MATRIX\n            ],\n            [\n                _core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.MAXICODE,\n                _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.MAXICODE\n            ],\n            [_core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.ITF, _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.ITF],\n            [_core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.EAN_13, _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.EAN_13],\n            [_core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.EAN_8, _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.EAN_8],\n            [_core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.PDF_417, _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.PDF_417],\n            [_core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.RSS_14, _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.RSS_14],\n            [\n                _core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.RSS_EXPANDED,\n                _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.RSS_EXPANDED\n            ],\n            [_core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.UPC_A, _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.UPC_A],\n            [_core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.UPC_E, _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.UPC_E],\n            [\n                _core__WEBPACK_IMPORTED_MODULE_1__.Html5QrcodeSupportedFormats.UPC_EAN_EXTENSION,\n                _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BarcodeFormat.UPC_EAN_EXTENSION\n            ]\n        ]);\n        this.reverseFormatMap = this.createReverseFormatMap();\n        if (!_third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__) {\n            throw \"Use html5qrcode.min.js without edit, ZXing not found.\";\n        }\n        this.verbose = verbose;\n        this.logger = logger;\n        var formats = this.createZXingFormats(requestedFormats);\n        var hints = new Map();\n        hints.set(_third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.DecodeHintType.POSSIBLE_FORMATS, formats);\n        hints.set(_third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.DecodeHintType.TRY_HARDER, false);\n        this.hints = hints;\n    }\n    ZXingHtml5QrcodeDecoder.prototype.decodeAsync = function (canvas) {\n        var _this = this;\n        return new Promise(function (resolve, reject) {\n            try {\n                resolve(_this.decode(canvas));\n            }\n            catch (error) {\n                reject(error);\n            }\n        });\n    };\n    ZXingHtml5QrcodeDecoder.prototype.decode = function (canvas) {\n        var zxingDecoder = new _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.MultiFormatReader(this.verbose, this.hints);\n        var luminanceSource = new _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.HTMLCanvasElementLuminanceSource(canvas);\n        var binaryBitmap = new _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.BinaryBitmap(new _third_party_zxing_js_umd__WEBPACK_IMPORTED_MODULE_0__.HybridBinarizer(luminanceSource));\n        var result = zxingDecoder.decode(binaryBitmap);\n        return {\n            text: result.text,\n            format: _core__WEBPACK_IMPORTED_MODULE_1__.QrcodeResultFormat.create(this.toHtml5QrcodeSupportedFormats(result.format)),\n            debugData: this.createDebugData()\n        };\n    };\n    ZXingHtml5QrcodeDecoder.prototype.createReverseFormatMap = function () {\n        var result = new Map();\n        this.formatMap.forEach(function (value, key, _) {\n            result.set(value, key);\n        });\n        return result;\n    };\n    ZXingHtml5QrcodeDecoder.prototype.toHtml5QrcodeSupportedFormats = function (zxingFormat) {\n        if (!this.reverseFormatMap.has(zxingFormat)) {\n            throw \"reverseFormatMap doesn't have \".concat(zxingFormat);\n        }\n        return this.reverseFormatMap.get(zxingFormat);\n    };\n    ZXingHtml5QrcodeDecoder.prototype.createZXingFormats = function (requestedFormats) {\n        var zxingFormats = [];\n        for (var _i = 0, requestedFormats_1 = requestedFormats; _i < requestedFormats_1.length; _i++) {\n            var requestedFormat = requestedFormats_1[_i];\n            if (this.formatMap.has(requestedFormat)) {\n                zxingFormats.push(this.formatMap.get(requestedFormat));\n            }\n            else {\n                this.logger.logError(\"\".concat(requestedFormat, \" is not supported by\")\n                    + \"ZXingHtml5QrcodeShim\");\n            }\n        }\n        return zxingFormats;\n    };\n    ZXingHtml5QrcodeDecoder.prototype.createDebugData = function () {\n        return { decoderName: \"zxing-js\" };\n    };\n    return ZXingHtml5QrcodeDecoder;\n}());\n\n//# sourceMappingURL=zxing-html5-qrcode-decoder.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS96eGluZy1odG1sNS1xcmNvZGUtZGVjb2Rlci5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS96eGluZy1odG1sNS1xcmNvZGUtZGVjb2Rlci5qcz80MzFmIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIFpYaW5nIGZyb20gXCIuLi90aGlyZF9wYXJ0eS96eGluZy1qcy51bWRcIjtcbmltcG9ydCB7IFFyY29kZVJlc3VsdEZvcm1hdCwgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzIH0gZnJvbSBcIi4vY29yZVwiO1xudmFyIFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBaWGluZ0h0bWw1UXJjb2RlRGVjb2RlcihyZXF1ZXN0ZWRGb3JtYXRzLCB2ZXJib3NlLCBsb2dnZXIpIHtcbiAgICAgICAgdGhpcy5mb3JtYXRNYXAgPSBuZXcgTWFwKFtcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUVJfQ09ERSwgWlhpbmcuQmFyY29kZUZvcm1hdC5RUl9DT0RFXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQVpURUMsIFpYaW5nLkJhcmNvZGVGb3JtYXQuQVpURUNdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RBQkFSLCBaWGluZy5CYXJjb2RlRm9ybWF0LkNPREFCQVJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzM5LCBaWGluZy5CYXJjb2RlRm9ybWF0LkNPREVfMzldLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzkzLCBaWGluZy5CYXJjb2RlRm9ybWF0LkNPREVfOTNdLFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzEyOCxcbiAgICAgICAgICAgICAgICBaWGluZy5CYXJjb2RlRm9ybWF0LkNPREVfMTI4XG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5EQVRBX01BVFJJWCxcbiAgICAgICAgICAgICAgICBaWGluZy5CYXJjb2RlRm9ybWF0LkRBVEFfTUFUUklYXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5NQVhJQ09ERSxcbiAgICAgICAgICAgICAgICBaWGluZy5CYXJjb2RlRm9ybWF0Lk1BWElDT0RFXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5JVEYsIFpYaW5nLkJhcmNvZGVGb3JtYXQuSVRGXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuRUFOXzEzLCBaWGluZy5CYXJjb2RlRm9ybWF0LkVBTl8xM10sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkVBTl84LCBaWGluZy5CYXJjb2RlRm9ybWF0LkVBTl84XSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUERGXzQxNywgWlhpbmcuQmFyY29kZUZvcm1hdC5QREZfNDE3XSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUlNTXzE0LCBaWGluZy5CYXJjb2RlRm9ybWF0LlJTU18xNF0sXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlJTU19FWFBBTkRFRCxcbiAgICAgICAgICAgICAgICBaWGluZy5CYXJjb2RlRm9ybWF0LlJTU19FWFBBTkRFRFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0EsIFpYaW5nLkJhcmNvZGVGb3JtYXQuVVBDX0FdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5VUENfRSwgWlhpbmcuQmFyY29kZUZvcm1hdC5VUENfRV0sXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlVQQ19FQU5fRVhURU5TSU9OLFxuICAgICAgICAgICAgICAgIFpYaW5nLkJhcmNvZGVGb3JtYXQuVVBDX0VBTl9FWFRFTlNJT05cbiAgICAgICAgICAgIF1cbiAgICAgICAgXSk7XG4gICAgICAgIHRoaXMucmV2ZXJzZUZvcm1hdE1hcCA9IHRoaXMuY3JlYXRlUmV2ZXJzZUZvcm1hdE1hcCgpO1xuICAgICAgICBpZiAoIVpYaW5nKSB7XG4gICAgICAgICAgICB0aHJvdyBcIlVzZSBodG1sNXFyY29kZS5taW4uanMgd2l0aG91dCBlZGl0LCBaWGluZyBub3QgZm91bmQuXCI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy52ZXJib3NlID0gdmVyYm9zZTtcbiAgICAgICAgdGhpcy5sb2dnZXIgPSBsb2dnZXI7XG4gICAgICAgIHZhciBmb3JtYXRzID0gdGhpcy5jcmVhdGVaWGluZ0Zvcm1hdHMocmVxdWVzdGVkRm9ybWF0cyk7XG4gICAgICAgIHZhciBoaW50cyA9IG5ldyBNYXAoKTtcbiAgICAgICAgaGludHMuc2V0KFpYaW5nLkRlY29kZUhpbnRUeXBlLlBPU1NJQkxFX0ZPUk1BVFMsIGZvcm1hdHMpO1xuICAgICAgICBoaW50cy5zZXQoWlhpbmcuRGVjb2RlSGludFR5cGUuVFJZX0hBUkRFUiwgZmFsc2UpO1xuICAgICAgICB0aGlzLmhpbnRzID0gaGludHM7XG4gICAgfVxuICAgIFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyLnByb3RvdHlwZS5kZWNvZGVBc3luYyA9IGZ1bmN0aW9uIChjYW52YXMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShfdGhpcy5kZWNvZGUoY2FudmFzKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyLnByb3RvdHlwZS5kZWNvZGUgPSBmdW5jdGlvbiAoY2FudmFzKSB7XG4gICAgICAgIHZhciB6eGluZ0RlY29kZXIgPSBuZXcgWlhpbmcuTXVsdGlGb3JtYXRSZWFkZXIodGhpcy52ZXJib3NlLCB0aGlzLmhpbnRzKTtcbiAgICAgICAgdmFyIGx1bWluYW5jZVNvdXJjZSA9IG5ldyBaWGluZy5IVE1MQ2FudmFzRWxlbWVudEx1bWluYW5jZVNvdXJjZShjYW52YXMpO1xuICAgICAgICB2YXIgYmluYXJ5Qml0bWFwID0gbmV3IFpYaW5nLkJpbmFyeUJpdG1hcChuZXcgWlhpbmcuSHlicmlkQmluYXJpemVyKGx1bWluYW5jZVNvdXJjZSkpO1xuICAgICAgICB2YXIgcmVzdWx0ID0genhpbmdEZWNvZGVyLmRlY29kZShiaW5hcnlCaXRtYXApO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdGV4dDogcmVzdWx0LnRleHQsXG4gICAgICAgICAgICBmb3JtYXQ6IFFyY29kZVJlc3VsdEZvcm1hdC5jcmVhdGUodGhpcy50b0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyhyZXN1bHQuZm9ybWF0KSksXG4gICAgICAgICAgICBkZWJ1Z0RhdGE6IHRoaXMuY3JlYXRlRGVidWdEYXRhKClcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyLnByb3RvdHlwZS5jcmVhdGVSZXZlcnNlRm9ybWF0TWFwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLmZvcm1hdE1hcC5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZSwga2V5LCBfKSB7XG4gICAgICAgICAgICByZXN1bHQuc2V0KHZhbHVlLCBrZXkpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyLnByb3RvdHlwZS50b0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyA9IGZ1bmN0aW9uICh6eGluZ0Zvcm1hdCkge1xuICAgICAgICBpZiAoIXRoaXMucmV2ZXJzZUZvcm1hdE1hcC5oYXMoenhpbmdGb3JtYXQpKSB7XG4gICAgICAgICAgICB0aHJvdyBcInJldmVyc2VGb3JtYXRNYXAgZG9lc24ndCBoYXZlIFwiLmNvbmNhdCh6eGluZ0Zvcm1hdCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMucmV2ZXJzZUZvcm1hdE1hcC5nZXQoenhpbmdGb3JtYXQpO1xuICAgIH07XG4gICAgWlhpbmdIdG1sNVFyY29kZURlY29kZXIucHJvdG90eXBlLmNyZWF0ZVpYaW5nRm9ybWF0cyA9IGZ1bmN0aW9uIChyZXF1ZXN0ZWRGb3JtYXRzKSB7XG4gICAgICAgIHZhciB6eGluZ0Zvcm1hdHMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCByZXF1ZXN0ZWRGb3JtYXRzXzEgPSByZXF1ZXN0ZWRGb3JtYXRzOyBfaSA8IHJlcXVlc3RlZEZvcm1hdHNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciByZXF1ZXN0ZWRGb3JtYXQgPSByZXF1ZXN0ZWRGb3JtYXRzXzFbX2ldO1xuICAgICAgICAgICAgaWYgKHRoaXMuZm9ybWF0TWFwLmhhcyhyZXF1ZXN0ZWRGb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgenhpbmdGb3JtYXRzLnB1c2godGhpcy5mb3JtYXRNYXAuZ2V0KHJlcXVlc3RlZEZvcm1hdCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIubG9nRXJyb3IoXCJcIi5jb25jYXQocmVxdWVzdGVkRm9ybWF0LCBcIiBpcyBub3Qgc3VwcG9ydGVkIGJ5XCIpXG4gICAgICAgICAgICAgICAgICAgICsgXCJaWGluZ0h0bWw1UXJjb2RlU2hpbVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4genhpbmdGb3JtYXRzO1xuICAgIH07XG4gICAgWlhpbmdIdG1sNVFyY29kZURlY29kZXIucHJvdG90eXBlLmNyZWF0ZURlYnVnRGF0YSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHsgZGVjb2Rlck5hbWU6IFwienhpbmctanNcIiB9O1xuICAgIH07XG4gICAgcmV0dXJuIFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyO1xufSgpKTtcbmV4cG9ydCB7IFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD16eGluZy1odG1sNS1xcmNvZGUtZGVjb2Rlci5qcy5tYXAiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/esm/zxing-html5-qrcode-decoder.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/html5-qrcode/third_party/zxing-js.umd.js":
+/*!***************************************************************!*\
+  !*** ./node_modules/html5-qrcode/third_party/zxing-js.umd.js ***!
+  \***************************************************************/
+/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
+
+eval("(function (global, factory) {\n     true ? factory(exports) :\n    0;\n}(this, (function (exports) { 'use strict';\n\n    function isNullOrUndefined(obj) {\n        return obj === null || obj === undefined;\n    }\n\n    /*\n     * Copyright 2008 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /* global Reflect, Promise */\n\n    var extendStatics = Object.setPrototypeOf ||\n        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n\n    function __extends(d, b) {\n        extendStatics(d, b);\n        function __() { this.constructor = d; }\n        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n    }\n\n    function fixProto(target, prototype) {\n        var setPrototypeOf = Object.setPrototypeOf;\n        setPrototypeOf ? setPrototypeOf(target, prototype) : (target.__proto__ = prototype);\n    }\n\n    function fixStack(target, fn) {\n        if (fn === void 0) {\n            fn = target.constructor;\n        }\n        var captureStackTrace = Error.captureStackTrace;\n        captureStackTrace && captureStackTrace(target, fn);\n    }\n\n    var CustomError = (function (_super) {\n        __extends(CustomError, _super);\n        function CustomError(message) {\n            var _newTarget = this.constructor;\n            var _this = _super.call(this, message) || this;\n            Object.defineProperty(_this, 'name', {\n                value: _newTarget.name,\n                enumerable: false\n            });\n            fixProto(_this, _newTarget.prototype);\n            fixStack(_this);\n            return _this;\n        }\n        \n        return CustomError;\n    })(Error);\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class Exception extends CustomError {\n        /**\n         * Allows Exception to be constructed directly\n         * with some message and prototype definition.\n         */\n        constructor(message = undefined) {\n            super(message);\n            this.message = message;\n        }\n        getKind() {\n            const ex = this.constructor;\n            return ex.kind;\n        }\n    }\n    /**\n     * It's typed as string so it can be extended and overriden.\n     */\n    Exception.kind = 'Exception';\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class ArgumentException extends Exception {\n    }\n    ArgumentException.kind = 'ArgumentException';\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class IllegalArgumentException extends Exception {\n    }\n    IllegalArgumentException.kind = 'IllegalArgumentException';\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    class BinaryBitmap {\n        constructor(binarizer) {\n            this.binarizer = binarizer;\n            if (binarizer === null) {\n                throw new IllegalArgumentException('Binarizer must be non-null.');\n            }\n        }\n        /**\n         * @return The width of the bitmap.\n         */\n        getWidth() {\n            return this.binarizer.getWidth();\n        }\n        /**\n         * @return The height of the bitmap.\n         */\n        getHeight() {\n            return this.binarizer.getHeight();\n        }\n        /**\n         * Converts one row of luminance data to 1 bit data. May actually do the conversion, or return\n         * cached data. Callers should assume this method is expensive and call it as seldom as possible.\n         * This method is intended for decoding 1D barcodes and may choose to apply sharpening.\n         *\n         * @param y The row to fetch, which must be in [0, bitmap height)\n         * @param row An optional preallocated array. If null or too small, it will be ignored.\n         *            If used, the Binarizer will call BitArray.clear(). Always use the returned object.\n         * @return The array of bits for this row (true means black).\n         * @throws NotFoundException if row can't be binarized\n         */\n        getBlackRow(y /*int*/, row) {\n            return this.binarizer.getBlackRow(y, row);\n        }\n        /**\n         * Converts a 2D array of luminance data to 1 bit. As above, assume this method is expensive\n         * and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or\n         * may not apply sharpening. Therefore, a row from this matrix may not be identical to one\n         * fetched using getBlackRow(), so don't mix and match between them.\n         *\n         * @return The 2D array of bits for the image (true means black).\n         * @throws NotFoundException if image can't be binarized to make a matrix\n         */\n        getBlackMatrix() {\n            // The matrix is created on demand the first time it is requested, then cached. There are two\n            // reasons for this:\n            // 1. This work will never be done if the caller only installs 1D Reader objects, or if a\n            //    1D Reader finds a barcode before the 2D Readers run.\n            // 2. This work will only be done once even if the caller installs multiple 2D Readers.\n            if (this.matrix === null || this.matrix === undefined) {\n                this.matrix = this.binarizer.getBlackMatrix();\n            }\n            return this.matrix;\n        }\n        /**\n         * @return Whether this bitmap can be cropped.\n         */\n        isCropSupported() {\n            return this.binarizer.getLuminanceSource().isCropSupported();\n        }\n        /**\n         * Returns a new object with cropped image data. Implementations may keep a reference to the\n         * original data rather than a copy. Only callable if isCropSupported() is true.\n         *\n         * @param left The left coordinate, which must be in [0,getWidth())\n         * @param top The top coordinate, which must be in [0,getHeight())\n         * @param width The width of the rectangle to crop.\n         * @param height The height of the rectangle to crop.\n         * @return A cropped version of this object.\n         */\n        crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n            const newSource = this.binarizer.getLuminanceSource().crop(left, top, width, height);\n            return new BinaryBitmap(this.binarizer.createBinarizer(newSource));\n        }\n        /**\n         * @return Whether this bitmap supports counter-clockwise rotation.\n         */\n        isRotateSupported() {\n            return this.binarizer.getLuminanceSource().isRotateSupported();\n        }\n        /**\n         * Returns a new object with rotated image data by 90 degrees counterclockwise.\n         * Only callable if {@link #isRotateSupported()} is true.\n         *\n         * @return A rotated version of this object.\n         */\n        rotateCounterClockwise() {\n            const newSource = this.binarizer.getLuminanceSource().rotateCounterClockwise();\n            return new BinaryBitmap(this.binarizer.createBinarizer(newSource));\n        }\n        /**\n         * Returns a new object with rotated image data by 45 degrees counterclockwise.\n         * Only callable if {@link #isRotateSupported()} is true.\n         *\n         * @return A rotated version of this object.\n         */\n        rotateCounterClockwise45() {\n            const newSource = this.binarizer.getLuminanceSource().rotateCounterClockwise45();\n            return new BinaryBitmap(this.binarizer.createBinarizer(newSource));\n        }\n        /*@Override*/\n        toString() {\n            try {\n                return this.getBlackMatrix().toString();\n            }\n            catch (e /*: NotFoundException*/) {\n                return '';\n            }\n        }\n    }\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class ChecksumException extends Exception {\n        static getChecksumInstance() {\n            return new ChecksumException();\n        }\n    }\n    ChecksumException.kind = 'ChecksumException';\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * This class hierarchy provides a set of methods to convert luminance data to 1 bit data.\n     * It allows the algorithm to vary polymorphically, for example allowing a very expensive\n     * thresholding technique for servers and a fast one for mobile. It also permits the implementation\n     * to vary, e.g. a JNI version for Android and a Java fallback version for other platforms.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class Binarizer {\n        constructor(source) {\n            this.source = source;\n        }\n        getLuminanceSource() {\n            return this.source;\n        }\n        getWidth() {\n            return this.source.getWidth();\n        }\n        getHeight() {\n            return this.source.getHeight();\n        }\n    }\n\n    class System {\n        // public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)\n        /**\n         * Makes a copy of a array.\n         */\n        static arraycopy(src, srcPos, dest, destPos, length) {\n            // TODO: better use split or set?\n            while (length--) {\n                dest[destPos++] = src[srcPos++];\n            }\n        }\n        /**\n         * Returns the current time in milliseconds.\n         */\n        static currentTimeMillis() {\n            return Date.now();\n        }\n    }\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class IndexOutOfBoundsException extends Exception {\n    }\n    IndexOutOfBoundsException.kind = 'IndexOutOfBoundsException';\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException {\n        constructor(index = undefined, message = undefined) {\n            super(message);\n            this.index = index;\n            this.message = message;\n        }\n    }\n    ArrayIndexOutOfBoundsException.kind = 'ArrayIndexOutOfBoundsException';\n\n    class Arrays {\n        /**\n         * Assigns the specified int value to each element of the specified array\n         * of ints.\n         *\n         * @param a the array to be filled\n         * @param val the value to be stored in all elements of the array\n         */\n        static fill(a, val) {\n            for (let i = 0, len = a.length; i < len; i++)\n                a[i] = val;\n        }\n        /**\n         * Assigns the specified int value to each element of the specified\n         * range of the specified array of ints.  The range to be filled\n         * extends from index {@code fromIndex}, inclusive, to index\n         * {@code toIndex}, exclusive.  (If {@code fromIndex==toIndex}, the\n         * range to be filled is empty.)\n         *\n         * @param a the array to be filled\n         * @param fromIndex the index of the first element (inclusive) to be\n         *        filled with the specified value\n         * @param toIndex the index of the last element (exclusive) to be\n         *        filled with the specified value\n         * @param val the value to be stored in all elements of the array\n         * @throws IllegalArgumentException if {@code fromIndex > toIndex}\n         * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or\n         *         {@code toIndex > a.length}\n         */\n        static fillWithin(a, fromIndex, toIndex, val) {\n            Arrays.rangeCheck(a.length, fromIndex, toIndex);\n            for (let i = fromIndex; i < toIndex; i++)\n                a[i] = val;\n        }\n        /**\n         * Checks that {@code fromIndex} and {@code toIndex} are in\n         * the range and throws an exception if they aren't.\n         */\n        static rangeCheck(arrayLength, fromIndex, toIndex) {\n            if (fromIndex > toIndex) {\n                throw new IllegalArgumentException('fromIndex(' + fromIndex + ') > toIndex(' + toIndex + ')');\n            }\n            if (fromIndex < 0) {\n                throw new ArrayIndexOutOfBoundsException(fromIndex);\n            }\n            if (toIndex > arrayLength) {\n                throw new ArrayIndexOutOfBoundsException(toIndex);\n            }\n        }\n        static asList(...args) {\n            return args;\n        }\n        static create(rows, cols, value) {\n            let arr = Array.from({ length: rows });\n            return arr.map(x => Array.from({ length: cols }).fill(value));\n        }\n        static createInt32Array(rows, cols, value) {\n            let arr = Array.from({ length: rows });\n            return arr.map(x => Int32Array.from({ length: cols }).fill(value));\n        }\n        static equals(first, second) {\n            if (!first) {\n                return false;\n            }\n            if (!second) {\n                return false;\n            }\n            if (!first.length) {\n                return false;\n            }\n            if (!second.length) {\n                return false;\n            }\n            if (first.length !== second.length) {\n                return false;\n            }\n            for (let i = 0, length = first.length; i < length; i++) {\n                if (first[i] !== second[i]) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        static hashCode(a) {\n            if (a === null) {\n                return 0;\n            }\n            let result = 1;\n            for (const element of a) {\n                result = 31 * result + element;\n            }\n            return result;\n        }\n        static fillUint8Array(a, value) {\n            for (let i = 0; i !== a.length; i++) {\n                a[i] = value;\n            }\n        }\n        static copyOf(original, newLength) {\n            return original.slice(0, newLength);\n        }\n        static copyOfUint8Array(original, newLength) {\n            if (original.length <= newLength) {\n                const newArray = new Uint8Array(newLength);\n                newArray.set(original);\n                return newArray;\n            }\n            return original.slice(0, newLength);\n        }\n        static copyOfRange(original, from, to) {\n            const newLength = to - from;\n            const copy = new Int32Array(newLength);\n            System.arraycopy(original, from, copy, 0, newLength);\n            return copy;\n        }\n        /*\n        * Returns the index of of the element in a sorted array or (-n-1) where n is the insertion point\n        * for the new element.\n        * Parameters:\n        *     ar - A sorted array\n        *     el - An element to search for\n        *     comparator - A comparator function. The function takes two arguments: (a, b) and returns:\n        *        a negative number  if a is less than b;\n        *        0 if a is equal to b;\n        *        a positive number of a is greater than b.\n        * The array may contain duplicate elements. If there are more than one equal elements in the array,\n        * the returned value can be the index of any one of the equal elements.\n        *\n        * http://jsfiddle.net/aryzhov/pkfst550/\n        */\n        static binarySearch(ar, el, comparator) {\n            if (undefined === comparator) {\n                comparator = Arrays.numberComparator;\n            }\n            let m = 0;\n            let n = ar.length - 1;\n            while (m <= n) {\n                const k = (n + m) >> 1;\n                const cmp = comparator(el, ar[k]);\n                if (cmp > 0) {\n                    m = k + 1;\n                }\n                else if (cmp < 0) {\n                    n = k - 1;\n                }\n                else {\n                    return k;\n                }\n            }\n            return -m - 1;\n        }\n        static numberComparator(a, b) {\n            return a - b;\n        }\n    }\n\n    /**\n     * Ponyfill for Java's Integer class.\n     */\n    class Integer {\n        static numberOfTrailingZeros(i) {\n            let y;\n            if (i === 0)\n                return 32;\n            let n = 31;\n            y = i << 16;\n            if (y !== 0) {\n                n -= 16;\n                i = y;\n            }\n            y = i << 8;\n            if (y !== 0) {\n                n -= 8;\n                i = y;\n            }\n            y = i << 4;\n            if (y !== 0) {\n                n -= 4;\n                i = y;\n            }\n            y = i << 2;\n            if (y !== 0) {\n                n -= 2;\n                i = y;\n            }\n            return n - ((i << 1) >>> 31);\n        }\n        static numberOfLeadingZeros(i) {\n            // HD, Figure 5-6\n            if (i === 0) {\n                return 32;\n            }\n            let n = 1;\n            if (i >>> 16 === 0) {\n                n += 16;\n                i <<= 16;\n            }\n            if (i >>> 24 === 0) {\n                n += 8;\n                i <<= 8;\n            }\n            if (i >>> 28 === 0) {\n                n += 4;\n                i <<= 4;\n            }\n            if (i >>> 30 === 0) {\n                n += 2;\n                i <<= 2;\n            }\n            n -= i >>> 31;\n            return n;\n        }\n        static toHexString(i) {\n            return i.toString(16);\n        }\n        static toBinaryString(intNumber) {\n            return String(parseInt(String(intNumber), 2));\n        }\n        // Returns the number of one-bits in the two's complement binary representation of the specified int value. This function is sometimes referred to as the population count.\n        // Returns:\n        // the number of one-bits in the two's complement binary representation of the specified int value.\n        static bitCount(i) {\n            // HD, Figure 5-2\n            i = i - ((i >>> 1) & 0x55555555);\n            i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);\n            i = (i + (i >>> 4)) & 0x0f0f0f0f;\n            i = i + (i >>> 8);\n            i = i + (i >>> 16);\n            return i & 0x3f;\n        }\n        static truncDivision(dividend, divisor) {\n            return Math.trunc(dividend / divisor);\n        }\n        /**\n         * Converts A string to an integer.\n         * @param s A string to convert into a number.\n         * @param radix A value between 2 and 36 that specifies the base of the number in numString. If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal. All other strings are considered decimal.\n         */\n        static parseInt(num, radix = undefined) {\n            return parseInt(num, radix);\n        }\n    }\n    Integer.MIN_VALUE_32_BITS = -2147483648;\n    Integer.MAX_VALUE = Number.MAX_SAFE_INTEGER;\n\n    /**\n     * <p>A simple, fast array of bits, represented compactly by an array of ints internally.</p>\n     *\n     * @author Sean Owen\n     */\n    class BitArray /*implements Cloneable*/ {\n        // For testing only\n        constructor(size /*int*/, bits) {\n            if (undefined === size) {\n                this.size = 0;\n                this.bits = new Int32Array(1);\n            }\n            else {\n                this.size = size;\n                if (undefined === bits || null === bits) {\n                    this.bits = BitArray.makeArray(size);\n                }\n                else {\n                    this.bits = bits;\n                }\n            }\n        }\n        getSize() {\n            return this.size;\n        }\n        getSizeInBytes() {\n            return Math.floor((this.size + 7) / 8);\n        }\n        ensureCapacity(size /*int*/) {\n            if (size > this.bits.length * 32) {\n                const newBits = BitArray.makeArray(size);\n                System.arraycopy(this.bits, 0, newBits, 0, this.bits.length);\n                this.bits = newBits;\n            }\n        }\n        /**\n         * @param i bit to get\n         * @return true iff bit i is set\n         */\n        get(i /*int*/) {\n            return (this.bits[Math.floor(i / 32)] & (1 << (i & 0x1F))) !== 0;\n        }\n        /**\n         * Sets bit i.\n         *\n         * @param i bit to set\n         */\n        set(i /*int*/) {\n            this.bits[Math.floor(i / 32)] |= 1 << (i & 0x1F);\n        }\n        /**\n         * Flips bit i.\n         *\n         * @param i bit to set\n         */\n        flip(i /*int*/) {\n            this.bits[Math.floor(i / 32)] ^= 1 << (i & 0x1F);\n        }\n        /**\n         * @param from first bit to check\n         * @return index of first bit that is set, starting from the given index, or size if none are set\n         *  at or beyond this given index\n         * @see #getNextUnset(int)\n         */\n        getNextSet(from /*int*/) {\n            const size = this.size;\n            if (from >= size) {\n                return size;\n            }\n            const bits = this.bits;\n            let bitsOffset = Math.floor(from / 32);\n            let currentBits = bits[bitsOffset];\n            // mask off lesser bits first\n            currentBits &= ~((1 << (from & 0x1F)) - 1);\n            const length = bits.length;\n            while (currentBits === 0) {\n                if (++bitsOffset === length) {\n                    return size;\n                }\n                currentBits = bits[bitsOffset];\n            }\n            const result = (bitsOffset * 32) + Integer.numberOfTrailingZeros(currentBits);\n            return result > size ? size : result;\n        }\n        /**\n         * @param from index to start looking for unset bit\n         * @return index of next unset bit, or {@code size} if none are unset until the end\n         * @see #getNextSet(int)\n         */\n        getNextUnset(from /*int*/) {\n            const size = this.size;\n            if (from >= size) {\n                return size;\n            }\n            const bits = this.bits;\n            let bitsOffset = Math.floor(from / 32);\n            let currentBits = ~bits[bitsOffset];\n            // mask off lesser bits first\n            currentBits &= ~((1 << (from & 0x1F)) - 1);\n            const length = bits.length;\n            while (currentBits === 0) {\n                if (++bitsOffset === length) {\n                    return size;\n                }\n                currentBits = ~bits[bitsOffset];\n            }\n            const result = (bitsOffset * 32) + Integer.numberOfTrailingZeros(currentBits);\n            return result > size ? size : result;\n        }\n        /**\n         * Sets a block of 32 bits, starting at bit i.\n         *\n         * @param i first bit to set\n         * @param newBits the new value of the next 32 bits. Note again that the least-significant bit\n         * corresponds to bit i, the next-least-significant to i+1, and so on.\n         */\n        setBulk(i /*int*/, newBits /*int*/) {\n            this.bits[Math.floor(i / 32)] = newBits;\n        }\n        /**\n         * Sets a range of bits.\n         *\n         * @param start start of range, inclusive.\n         * @param end end of range, exclusive\n         */\n        setRange(start /*int*/, end /*int*/) {\n            if (end < start || start < 0 || end > this.size) {\n                throw new IllegalArgumentException();\n            }\n            if (end === start) {\n                return;\n            }\n            end--; // will be easier to treat this as the last actually set bit -- inclusive\n            const firstInt = Math.floor(start / 32);\n            const lastInt = Math.floor(end / 32);\n            const bits = this.bits;\n            for (let i = firstInt; i <= lastInt; i++) {\n                const firstBit = i > firstInt ? 0 : start & 0x1F;\n                const lastBit = i < lastInt ? 31 : end & 0x1F;\n                // Ones from firstBit to lastBit, inclusive\n                const mask = (2 << lastBit) - (1 << firstBit);\n                bits[i] |= mask;\n            }\n        }\n        /**\n         * Clears all bits (sets to false).\n         */\n        clear() {\n            const max = this.bits.length;\n            const bits = this.bits;\n            for (let i = 0; i < max; i++) {\n                bits[i] = 0;\n            }\n        }\n        /**\n         * Efficient method to check if a range of bits is set, or not set.\n         *\n         * @param start start of range, inclusive.\n         * @param end end of range, exclusive\n         * @param value if true, checks that bits in range are set, otherwise checks that they are not set\n         * \n         * @return true iff all bits are set or not set in range, according to value argument\n         * @throws IllegalArgumentException if end is less than start or the range is not contained in the array\n         */\n        isRange(start /*int*/, end /*int*/, value) {\n            if (end < start || start < 0 || end > this.size) {\n                throw new IllegalArgumentException();\n            }\n            if (end === start) {\n                return true; // empty range matches\n            }\n            end--; // will be easier to treat this as the last actually set bit -- inclusive\n            const firstInt = Math.floor(start / 32);\n            const lastInt = Math.floor(end / 32);\n            const bits = this.bits;\n            for (let i = firstInt; i <= lastInt; i++) {\n                const firstBit = i > firstInt ? 0 : start & 0x1F;\n                const lastBit = i < lastInt ? 31 : end & 0x1F;\n                // Ones from firstBit to lastBit, inclusive\n                const mask = (2 << lastBit) - (1 << firstBit) & 0xFFFFFFFF;\n                // TYPESCRIPTPORT: & 0xFFFFFFFF added to discard anything after 32 bits, as ES has 53 bits\n                // Return false if we're looking for 1s and the masked bits[i] isn't all 1s (is: that,\n                // equals the mask, or we're looking for 0s and the masked portion is not all 0s\n                if ((bits[i] & mask) !== (value ? mask : 0)) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        appendBit(bit) {\n            this.ensureCapacity(this.size + 1);\n            if (bit) {\n                this.bits[Math.floor(this.size / 32)] |= 1 << (this.size & 0x1F);\n            }\n            this.size++;\n        }\n        /**\n         * Appends the least-significant bits, from value, in order from most-significant to\n         * least-significant. For example, appending 6 bits from 0x000001E will append the bits\n         * 0, 1, 1, 1, 1, 0 in that order.\n         *\n         * @param value {@code int} containing bits to append\n         * @param numBits bits from value to append\n         */\n        appendBits(value /*int*/, numBits /*int*/) {\n            if (numBits < 0 || numBits > 32) {\n                throw new IllegalArgumentException('Num bits must be between 0 and 32');\n            }\n            this.ensureCapacity(this.size + numBits);\n            // const appendBit = this.appendBit;\n            for (let numBitsLeft = numBits; numBitsLeft > 0; numBitsLeft--) {\n                this.appendBit(((value >> (numBitsLeft - 1)) & 0x01) === 1);\n            }\n        }\n        appendBitArray(other) {\n            const otherSize = other.size;\n            this.ensureCapacity(this.size + otherSize);\n            // const appendBit = this.appendBit;\n            for (let i = 0; i < otherSize; i++) {\n                this.appendBit(other.get(i));\n            }\n        }\n        xor(other) {\n            if (this.size !== other.size) {\n                throw new IllegalArgumentException('Sizes don\\'t match');\n            }\n            const bits = this.bits;\n            for (let i = 0, length = bits.length; i < length; i++) {\n                // The last int could be incomplete (i.e. not have 32 bits in\n                // it) but there is no problem since 0 XOR 0 == 0.\n                bits[i] ^= other.bits[i];\n            }\n        }\n        /**\n         *\n         * @param bitOffset first bit to start writing\n         * @param array array to write into. Bytes are written most-significant byte first. This is the opposite\n         *  of the internal representation, which is exposed by {@link #getBitArray()}\n         * @param offset position in array to start writing\n         * @param numBytes how many bytes to write\n         */\n        toBytes(bitOffset /*int*/, array, offset /*int*/, numBytes /*int*/) {\n            for (let i = 0; i < numBytes; i++) {\n                let theByte = 0;\n                for (let j = 0; j < 8; j++) {\n                    if (this.get(bitOffset)) {\n                        theByte |= 1 << (7 - j);\n                    }\n                    bitOffset++;\n                }\n                array[offset + i] = /*(byte)*/ theByte;\n            }\n        }\n        /**\n         * @return underlying array of ints. The first element holds the first 32 bits, and the least\n         *         significant bit is bit 0.\n         */\n        getBitArray() {\n            return this.bits;\n        }\n        /**\n         * Reverses all bits in the array.\n         */\n        reverse() {\n            const newBits = new Int32Array(this.bits.length);\n            // reverse all int's first\n            const len = Math.floor((this.size - 1) / 32);\n            const oldBitsLen = len + 1;\n            const bits = this.bits;\n            for (let i = 0; i < oldBitsLen; i++) {\n                let x = bits[i];\n                x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1);\n                x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2);\n                x = ((x >> 4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) << 4);\n                x = ((x >> 8) & 0x00ff00ff) | ((x & 0x00ff00ff) << 8);\n                x = ((x >> 16) & 0x0000ffff) | ((x & 0x0000ffff) << 16);\n                newBits[len - i] = /*(int)*/ x;\n            }\n            // now correct the int's if the bit size isn't a multiple of 32\n            if (this.size !== oldBitsLen * 32) {\n                const leftOffset = oldBitsLen * 32 - this.size;\n                let currentInt = newBits[0] >>> leftOffset;\n                for (let i = 1; i < oldBitsLen; i++) {\n                    const nextInt = newBits[i];\n                    currentInt |= nextInt << (32 - leftOffset);\n                    newBits[i - 1] = currentInt;\n                    currentInt = nextInt >>> leftOffset;\n                }\n                newBits[oldBitsLen - 1] = currentInt;\n            }\n            this.bits = newBits;\n        }\n        static makeArray(size /*int*/) {\n            return new Int32Array(Math.floor((size + 31) / 32));\n        }\n        /*@Override*/\n        equals(o) {\n            if (!(o instanceof BitArray)) {\n                return false;\n            }\n            const other = o;\n            return this.size === other.size && Arrays.equals(this.bits, other.bits);\n        }\n        /*@Override*/\n        hashCode() {\n            return 31 * this.size + Arrays.hashCode(this.bits);\n        }\n        /*@Override*/\n        toString() {\n            let result = '';\n            for (let i = 0, size = this.size; i < size; i++) {\n                if ((i & 0x07) === 0) {\n                    result += ' ';\n                }\n                result += this.get(i) ? 'X' : '.';\n            }\n            return result;\n        }\n        /*@Override*/\n        clone() {\n            return new BitArray(this.size, this.bits.slice());\n        }\n    }\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing {*/\n    /**\n     * Encapsulates a type of hint that a caller may pass to a barcode reader to help it\n     * more quickly or accurately decode it. It is up to implementations to decide what,\n     * if anything, to do with the information that is supplied.\n     *\n     * @author Sean Owen\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @see Reader#decode(BinaryBitmap,java.util.Map)\n     */\n    var DecodeHintType;\n    (function (DecodeHintType) {\n        /**\n         * Unspecified, application-specific hint. Maps to an unspecified {@link Object}.\n         */\n        DecodeHintType[DecodeHintType[\"OTHER\"] = 0] = \"OTHER\"; /*(Object.class)*/\n        /**\n         * Image is a pure monochrome image of a barcode. Doesn't matter what it maps to;\n         * use {@link Boolean#TRUE}.\n         */\n        DecodeHintType[DecodeHintType[\"PURE_BARCODE\"] = 1] = \"PURE_BARCODE\"; /*(Void.class)*/\n        /**\n         * Image is known to be of one of a few possible formats.\n         * Maps to a {@link List} of {@link BarcodeFormat}s.\n         */\n        DecodeHintType[DecodeHintType[\"POSSIBLE_FORMATS\"] = 2] = \"POSSIBLE_FORMATS\"; /*(List.class)*/\n        /**\n         * Spend more time to try to find a barcode; optimize for accuracy, not speed.\n         * Doesn't matter what it maps to; use {@link Boolean#TRUE}.\n         */\n        DecodeHintType[DecodeHintType[\"TRY_HARDER\"] = 3] = \"TRY_HARDER\"; /*(Void.class)*/\n        /**\n         * Specifies what character encoding to use when decoding, where applicable (type String)\n         */\n        DecodeHintType[DecodeHintType[\"CHARACTER_SET\"] = 4] = \"CHARACTER_SET\"; /*(String.class)*/\n        /**\n         * Allowed lengths of encoded data -- reject anything else. Maps to an {@code Int32Array}.\n         */\n        DecodeHintType[DecodeHintType[\"ALLOWED_LENGTHS\"] = 5] = \"ALLOWED_LENGTHS\"; /*(Int32Array.class)*/\n        /**\n         * Assume Code 39 codes employ a check digit. Doesn't matter what it maps to;\n         * use {@link Boolean#TRUE}.\n         */\n        DecodeHintType[DecodeHintType[\"ASSUME_CODE_39_CHECK_DIGIT\"] = 6] = \"ASSUME_CODE_39_CHECK_DIGIT\"; /*(Void.class)*/\n        /**\n         * Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed.\n         * For example this affects FNC1 handling for Code 128 (aka GS1-128). Doesn't matter what it maps to;\n         * use {@link Boolean#TRUE}.\n         */\n        DecodeHintType[DecodeHintType[\"ASSUME_GS1\"] = 7] = \"ASSUME_GS1\"; /*(Void.class)*/\n        /**\n         * If true, return the start and end digits in a Codabar barcode instead of stripping them. They\n         * are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them\n         * to not be. Doesn't matter what it maps to; use {@link Boolean#TRUE}.\n         */\n        DecodeHintType[DecodeHintType[\"RETURN_CODABAR_START_END\"] = 8] = \"RETURN_CODABAR_START_END\"; /*(Void.class)*/\n        /**\n         * The caller needs to be notified via callback when a possible {@link ResultPoint}\n         * is found. Maps to a {@link ResultPointCallback}.\n         */\n        DecodeHintType[DecodeHintType[\"NEED_RESULT_POINT_CALLBACK\"] = 9] = \"NEED_RESULT_POINT_CALLBACK\"; /*(ResultPointCallback.class)*/\n        /**\n         * Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this.\n         * Maps to an {@code Int32Array} of the allowed extension lengths, for example [2], [5], or [2, 5].\n         * If it is optional to have an extension, do not set this hint. If this is set,\n         * and a UPC or EAN barcode is found but an extension is not, then no result will be returned\n         * at all.\n         */\n        DecodeHintType[DecodeHintType[\"ALLOWED_EAN_EXTENSIONS\"] = 10] = \"ALLOWED_EAN_EXTENSIONS\"; /*(Int32Array.class)*/\n        // End of enumeration values.\n        /**\n         * Data type the hint is expecting.\n         * Among the possible values the {@link Void} stands out as being used for\n         * hints that do not expect a value to be supplied (flag hints). Such hints\n         * will possibly have their value ignored, or replaced by a\n         * {@link Boolean#TRUE}. Hint suppliers should probably use\n         * {@link Boolean#TRUE} as directed by the actual hint documentation.\n         */\n        // private valueType: Class<?>\n        // DecodeHintType(valueType: Class<?>) {\n        //   this.valueType = valueType\n        // }\n        // public getValueType(): Class<?> {\n        //   return valueType\n        // }\n    })(DecodeHintType || (DecodeHintType = {}));\n    var DecodeHintType$1 = DecodeHintType;\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class FormatException extends Exception {\n        static getFormatInstance() {\n            return new FormatException();\n        }\n    }\n    FormatException.kind = 'FormatException';\n\n    /*import java.util.HashMap;*/\n    /*import java.util.Map;*/\n    var CharacterSetValueIdentifiers;\n    (function (CharacterSetValueIdentifiers) {\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp437\"] = 0] = \"Cp437\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_1\"] = 1] = \"ISO8859_1\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_2\"] = 2] = \"ISO8859_2\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_3\"] = 3] = \"ISO8859_3\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_4\"] = 4] = \"ISO8859_4\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_5\"] = 5] = \"ISO8859_5\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_6\"] = 6] = \"ISO8859_6\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_7\"] = 7] = \"ISO8859_7\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_8\"] = 8] = \"ISO8859_8\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_9\"] = 9] = \"ISO8859_9\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_10\"] = 10] = \"ISO8859_10\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_11\"] = 11] = \"ISO8859_11\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_13\"] = 12] = \"ISO8859_13\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_14\"] = 13] = \"ISO8859_14\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_15\"] = 14] = \"ISO8859_15\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_16\"] = 15] = \"ISO8859_16\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"SJIS\"] = 16] = \"SJIS\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp1250\"] = 17] = \"Cp1250\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp1251\"] = 18] = \"Cp1251\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp1252\"] = 19] = \"Cp1252\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp1256\"] = 20] = \"Cp1256\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"UnicodeBigUnmarked\"] = 21] = \"UnicodeBigUnmarked\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"UTF8\"] = 22] = \"UTF8\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ASCII\"] = 23] = \"ASCII\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Big5\"] = 24] = \"Big5\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"GB18030\"] = 25] = \"GB18030\";\n        CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"EUC_KR\"] = 26] = \"EUC_KR\";\n    })(CharacterSetValueIdentifiers || (CharacterSetValueIdentifiers = {}));\n    /**\n     * Encapsulates a Character Set ECI, according to \"Extended Channel Interpretations\" 5.3.1.1\n     * of ISO 18004.\n     *\n     * @author Sean Owen\n     */\n    class CharacterSetECI {\n        constructor(valueIdentifier, valuesParam, name, ...otherEncodingNames) {\n            this.valueIdentifier = valueIdentifier;\n            this.name = name;\n            if (typeof valuesParam === 'number') {\n                this.values = Int32Array.from([valuesParam]);\n            }\n            else {\n                this.values = valuesParam;\n            }\n            this.otherEncodingNames = otherEncodingNames;\n            CharacterSetECI.VALUE_IDENTIFIER_TO_ECI.set(valueIdentifier, this);\n            CharacterSetECI.NAME_TO_ECI.set(name, this);\n            const values = this.values;\n            for (let i = 0, length = values.length; i !== length; i++) {\n                const v = values[i];\n                CharacterSetECI.VALUES_TO_ECI.set(v, this);\n            }\n            for (const otherName of otherEncodingNames) {\n                CharacterSetECI.NAME_TO_ECI.set(otherName, this);\n            }\n        }\n        // CharacterSetECI(value: number /*int*/) {\n        //   this(new Int32Array {value})\n        // }\n        // CharacterSetECI(value: number /*int*/, String... otherEncodingNames) {\n        //   this.values = new Int32Array {value}\n        //   this.otherEncodingNames = otherEncodingNames\n        // }\n        // CharacterSetECI(values: Int32Array, String... otherEncodingNames) {\n        //   this.values = values\n        //   this.otherEncodingNames = otherEncodingNames\n        // }\n        getValueIdentifier() {\n            return this.valueIdentifier;\n        }\n        getName() {\n            return this.name;\n        }\n        getValue() {\n            return this.values[0];\n        }\n        /**\n         * @param value character set ECI value\n         * @return {@code CharacterSetECI} representing ECI of given value, or null if it is legal but\n         *   unsupported\n         * @throws FormatException if ECI value is invalid\n         */\n        static getCharacterSetECIByValue(value /*int*/) {\n            if (value < 0 || value >= 900) {\n                throw new FormatException('incorect value');\n            }\n            const characterSet = CharacterSetECI.VALUES_TO_ECI.get(value);\n            if (undefined === characterSet) {\n                throw new FormatException('incorect value');\n            }\n            return characterSet;\n        }\n        /**\n         * @param name character set ECI encoding name\n         * @return CharacterSetECI representing ECI for character encoding, or null if it is legal\n         *   but unsupported\n         */\n        static getCharacterSetECIByName(name) {\n            const characterSet = CharacterSetECI.NAME_TO_ECI.get(name);\n            if (undefined === characterSet) {\n                throw new FormatException('incorect value');\n            }\n            return characterSet;\n        }\n        equals(o) {\n            if (!(o instanceof CharacterSetECI)) {\n                return false;\n            }\n            const other = o;\n            return this.getName() === other.getName();\n        }\n    }\n    CharacterSetECI.VALUE_IDENTIFIER_TO_ECI = new Map();\n    CharacterSetECI.VALUES_TO_ECI = new Map();\n    CharacterSetECI.NAME_TO_ECI = new Map();\n    // Enum name is a Java encoding valid for java.lang and java.io\n    // TYPESCRIPTPORT: changed the main label for ISO as the TextEncoder did not recognized them in the form from java\n    // (eg ISO8859_1 must be ISO88591 or ISO8859-1 or ISO-8859-1)\n    // later on: well, except 16 wich does not work with ISO885916 so used ISO-8859-1 form for default\n    CharacterSetECI.Cp437 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp437, Int32Array.from([0, 2]), 'Cp437');\n    CharacterSetECI.ISO8859_1 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_1, Int32Array.from([1, 3]), 'ISO-8859-1', 'ISO88591', 'ISO8859_1');\n    CharacterSetECI.ISO8859_2 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_2, 4, 'ISO-8859-2', 'ISO88592', 'ISO8859_2');\n    CharacterSetECI.ISO8859_3 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_3, 5, 'ISO-8859-3', 'ISO88593', 'ISO8859_3');\n    CharacterSetECI.ISO8859_4 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_4, 6, 'ISO-8859-4', 'ISO88594', 'ISO8859_4');\n    CharacterSetECI.ISO8859_5 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_5, 7, 'ISO-8859-5', 'ISO88595', 'ISO8859_5');\n    CharacterSetECI.ISO8859_6 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_6, 8, 'ISO-8859-6', 'ISO88596', 'ISO8859_6');\n    CharacterSetECI.ISO8859_7 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_7, 9, 'ISO-8859-7', 'ISO88597', 'ISO8859_7');\n    CharacterSetECI.ISO8859_8 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_8, 10, 'ISO-8859-8', 'ISO88598', 'ISO8859_8');\n    CharacterSetECI.ISO8859_9 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_9, 11, 'ISO-8859-9', 'ISO88599', 'ISO8859_9');\n    CharacterSetECI.ISO8859_10 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_10, 12, 'ISO-8859-10', 'ISO885910', 'ISO8859_10');\n    CharacterSetECI.ISO8859_11 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_11, 13, 'ISO-8859-11', 'ISO885911', 'ISO8859_11');\n    CharacterSetECI.ISO8859_13 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_13, 15, 'ISO-8859-13', 'ISO885913', 'ISO8859_13');\n    CharacterSetECI.ISO8859_14 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_14, 16, 'ISO-8859-14', 'ISO885914', 'ISO8859_14');\n    CharacterSetECI.ISO8859_15 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_15, 17, 'ISO-8859-15', 'ISO885915', 'ISO8859_15');\n    CharacterSetECI.ISO8859_16 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_16, 18, 'ISO-8859-16', 'ISO885916', 'ISO8859_16');\n    CharacterSetECI.SJIS = new CharacterSetECI(CharacterSetValueIdentifiers.SJIS, 20, 'SJIS', 'Shift_JIS');\n    CharacterSetECI.Cp1250 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp1250, 21, 'Cp1250', 'windows-1250');\n    CharacterSetECI.Cp1251 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp1251, 22, 'Cp1251', 'windows-1251');\n    CharacterSetECI.Cp1252 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp1252, 23, 'Cp1252', 'windows-1252');\n    CharacterSetECI.Cp1256 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp1256, 24, 'Cp1256', 'windows-1256');\n    CharacterSetECI.UnicodeBigUnmarked = new CharacterSetECI(CharacterSetValueIdentifiers.UnicodeBigUnmarked, 25, 'UnicodeBigUnmarked', 'UTF-16BE', 'UnicodeBig');\n    CharacterSetECI.UTF8 = new CharacterSetECI(CharacterSetValueIdentifiers.UTF8, 26, 'UTF8', 'UTF-8');\n    CharacterSetECI.ASCII = new CharacterSetECI(CharacterSetValueIdentifiers.ASCII, Int32Array.from([27, 170]), 'ASCII', 'US-ASCII');\n    CharacterSetECI.Big5 = new CharacterSetECI(CharacterSetValueIdentifiers.Big5, 28, 'Big5');\n    CharacterSetECI.GB18030 = new CharacterSetECI(CharacterSetValueIdentifiers.GB18030, 29, 'GB18030', 'GB2312', 'EUC_CN', 'GBK');\n    CharacterSetECI.EUC_KR = new CharacterSetECI(CharacterSetValueIdentifiers.EUC_KR, 30, 'EUC_KR', 'EUC-KR');\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class UnsupportedOperationException extends Exception {\n    }\n    UnsupportedOperationException.kind = 'UnsupportedOperationException';\n\n    /**\n     * Responsible for en/decoding strings.\n     */\n    class StringEncoding {\n        /**\n         * Decodes some Uint8Array to a string format.\n         */\n        static decode(bytes, encoding) {\n            const encodingName = this.encodingName(encoding);\n            if (this.customDecoder) {\n                return this.customDecoder(bytes, encodingName);\n            }\n            // Increases browser support.\n            if (typeof TextDecoder === 'undefined' || this.shouldDecodeOnFallback(encodingName)) {\n                return this.decodeFallback(bytes, encodingName);\n            }\n            return new TextDecoder(encodingName).decode(bytes);\n        }\n        /**\n         * Checks if the decoding method should use the fallback for decoding\n         * once Node TextDecoder doesn't support all encoding formats.\n         *\n         * @param encodingName\n         */\n        static shouldDecodeOnFallback(encodingName) {\n            return !StringEncoding.isBrowser() && encodingName === 'ISO-8859-1';\n        }\n        /**\n         * Encodes some string into a Uint8Array.\n         */\n        static encode(s, encoding) {\n            const encodingName = this.encodingName(encoding);\n            if (this.customEncoder) {\n                return this.customEncoder(s, encodingName);\n            }\n            // Increases browser support.\n            if (typeof TextEncoder === 'undefined') {\n                return this.encodeFallback(s);\n            }\n            // TextEncoder only encodes to UTF8 by default as specified by encoding.spec.whatwg.org\n            return new TextEncoder().encode(s);\n        }\n        static isBrowser() {\n            return (typeof window !== 'undefined' && {}.toString.call(window) === '[object Window]');\n        }\n        /**\n         * Returns the string value from some encoding character set.\n         */\n        static encodingName(encoding) {\n            return typeof encoding === 'string'\n                ? encoding\n                : encoding.getName();\n        }\n        /**\n         * Returns character set from some encoding character set.\n         */\n        static encodingCharacterSet(encoding) {\n            if (encoding instanceof CharacterSetECI) {\n                return encoding;\n            }\n            return CharacterSetECI.getCharacterSetECIByName(encoding);\n        }\n        /**\n         * Runs a fallback for the native decoding funcion.\n         */\n        static decodeFallback(bytes, encoding) {\n            const characterSet = this.encodingCharacterSet(encoding);\n            if (StringEncoding.isDecodeFallbackSupported(characterSet)) {\n                let s = '';\n                for (let i = 0, length = bytes.length; i < length; i++) {\n                    let h = bytes[i].toString(16);\n                    if (h.length < 2) {\n                        h = '0' + h;\n                    }\n                    s += '%' + h;\n                }\n                return decodeURIComponent(s);\n            }\n            if (characterSet.equals(CharacterSetECI.UnicodeBigUnmarked)) {\n                return String.fromCharCode.apply(null, new Uint16Array(bytes.buffer));\n            }\n            throw new UnsupportedOperationException(`Encoding ${this.encodingName(encoding)} not supported by fallback.`);\n        }\n        static isDecodeFallbackSupported(characterSet) {\n            return characterSet.equals(CharacterSetECI.UTF8) ||\n                characterSet.equals(CharacterSetECI.ISO8859_1) ||\n                characterSet.equals(CharacterSetECI.ASCII);\n        }\n        /**\n         * Runs a fallback for the native encoding funcion.\n         *\n         * @see https://stackoverflow.com/a/17192845/4367683\n         */\n        static encodeFallback(s) {\n            const encodedURIstring = btoa(unescape(encodeURIComponent(s)));\n            const charList = encodedURIstring.split('');\n            const uintArray = [];\n            for (let i = 0; i < charList.length; i++) {\n                uintArray.push(charList[i].charCodeAt(0));\n            }\n            return new Uint8Array(uintArray);\n        }\n    }\n\n    /*\n     * Copyright (C) 2010 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * Common string-related functions.\n     *\n     * @author Sean Owen\n     * @author Alex Dupre\n     */\n    class StringUtils {\n        // SHIFT_JIS.equalsIgnoreCase(PLATFORM_DEFAULT_ENCODING) ||\n        // EUC_JP.equalsIgnoreCase(PLATFORM_DEFAULT_ENCODING);\n        static castAsNonUtf8Char(code, encoding = null) {\n            // ISO 8859-1 is the Java default as UTF-8 is JavaScripts\n            // you can see this method as a Java version of String.fromCharCode\n            const e = encoding ? encoding.getName() : this.ISO88591;\n            // use passed format (fromCharCode will return UTF8 encoding)\n            return StringEncoding.decode(new Uint8Array([code]), e);\n        }\n        /**\n         * @param bytes bytes encoding a string, whose encoding should be guessed\n         * @param hints decode hints if applicable\n         * @return name of guessed encoding; at the moment will only guess one of:\n         *  {@link #SHIFT_JIS}, {@link #UTF8}, {@link #ISO88591}, or the platform\n         *  default encoding if none of these can possibly be correct\n         */\n        static guessEncoding(bytes, hints) {\n            if (hints !== null && hints !== undefined && undefined !== hints.get(DecodeHintType$1.CHARACTER_SET)) {\n                return hints.get(DecodeHintType$1.CHARACTER_SET).toString();\n            }\n            // For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS,\n            // which should be by far the most common encodings.\n            const length = bytes.length;\n            let canBeISO88591 = true;\n            let canBeShiftJIS = true;\n            let canBeUTF8 = true;\n            let utf8BytesLeft = 0;\n            // int utf8LowChars = 0\n            let utf2BytesChars = 0;\n            let utf3BytesChars = 0;\n            let utf4BytesChars = 0;\n            let sjisBytesLeft = 0;\n            // int sjisLowChars = 0\n            let sjisKatakanaChars = 0;\n            // int sjisDoubleBytesChars = 0\n            let sjisCurKatakanaWordLength = 0;\n            let sjisCurDoubleBytesWordLength = 0;\n            let sjisMaxKatakanaWordLength = 0;\n            let sjisMaxDoubleBytesWordLength = 0;\n            // int isoLowChars = 0\n            // int isoHighChars = 0\n            let isoHighOther = 0;\n            const utf8bom = bytes.length > 3 &&\n                bytes[0] === /*(byte) */ 0xEF &&\n                bytes[1] === /*(byte) */ 0xBB &&\n                bytes[2] === /*(byte) */ 0xBF;\n            for (let i = 0; i < length && (canBeISO88591 || canBeShiftJIS || canBeUTF8); i++) {\n                const value = bytes[i] & 0xFF;\n                // UTF-8 stuff\n                if (canBeUTF8) {\n                    if (utf8BytesLeft > 0) {\n                        if ((value & 0x80) === 0) {\n                            canBeUTF8 = false;\n                        }\n                        else {\n                            utf8BytesLeft--;\n                        }\n                    }\n                    else if ((value & 0x80) !== 0) {\n                        if ((value & 0x40) === 0) {\n                            canBeUTF8 = false;\n                        }\n                        else {\n                            utf8BytesLeft++;\n                            if ((value & 0x20) === 0) {\n                                utf2BytesChars++;\n                            }\n                            else {\n                                utf8BytesLeft++;\n                                if ((value & 0x10) === 0) {\n                                    utf3BytesChars++;\n                                }\n                                else {\n                                    utf8BytesLeft++;\n                                    if ((value & 0x08) === 0) {\n                                        utf4BytesChars++;\n                                    }\n                                    else {\n                                        canBeUTF8 = false;\n                                    }\n                                }\n                            }\n                        }\n                    } // else {\n                    // utf8LowChars++\n                    // }\n                }\n                // ISO-8859-1 stuff\n                if (canBeISO88591) {\n                    if (value > 0x7F && value < 0xA0) {\n                        canBeISO88591 = false;\n                    }\n                    else if (value > 0x9F) {\n                        if (value < 0xC0 || value === 0xD7 || value === 0xF7) {\n                            isoHighOther++;\n                        } // else {\n                        // isoHighChars++\n                        // }\n                    } // else {\n                    // isoLowChars++\n                    // }\n                }\n                // Shift_JIS stuff\n                if (canBeShiftJIS) {\n                    if (sjisBytesLeft > 0) {\n                        if (value < 0x40 || value === 0x7F || value > 0xFC) {\n                            canBeShiftJIS = false;\n                        }\n                        else {\n                            sjisBytesLeft--;\n                        }\n                    }\n                    else if (value === 0x80 || value === 0xA0 || value > 0xEF) {\n                        canBeShiftJIS = false;\n                    }\n                    else if (value > 0xA0 && value < 0xE0) {\n                        sjisKatakanaChars++;\n                        sjisCurDoubleBytesWordLength = 0;\n                        sjisCurKatakanaWordLength++;\n                        if (sjisCurKatakanaWordLength > sjisMaxKatakanaWordLength) {\n                            sjisMaxKatakanaWordLength = sjisCurKatakanaWordLength;\n                        }\n                    }\n                    else if (value > 0x7F) {\n                        sjisBytesLeft++;\n                        // sjisDoubleBytesChars++\n                        sjisCurKatakanaWordLength = 0;\n                        sjisCurDoubleBytesWordLength++;\n                        if (sjisCurDoubleBytesWordLength > sjisMaxDoubleBytesWordLength) {\n                            sjisMaxDoubleBytesWordLength = sjisCurDoubleBytesWordLength;\n                        }\n                    }\n                    else {\n                        // sjisLowChars++\n                        sjisCurKatakanaWordLength = 0;\n                        sjisCurDoubleBytesWordLength = 0;\n                    }\n                }\n            }\n            if (canBeUTF8 && utf8BytesLeft > 0) {\n                canBeUTF8 = false;\n            }\n            if (canBeShiftJIS && sjisBytesLeft > 0) {\n                canBeShiftJIS = false;\n            }\n            // Easy -- if there is BOM or at least 1 valid not-single byte character (and no evidence it can't be UTF-8), done\n            if (canBeUTF8 && (utf8bom || utf2BytesChars + utf3BytesChars + utf4BytesChars > 0)) {\n                return StringUtils.UTF8;\n            }\n            // Easy -- if assuming Shift_JIS or at least 3 valid consecutive not-ascii characters (and no evidence it can't be), done\n            if (canBeShiftJIS && (StringUtils.ASSUME_SHIFT_JIS || sjisMaxKatakanaWordLength >= 3 || sjisMaxDoubleBytesWordLength >= 3)) {\n                return StringUtils.SHIFT_JIS;\n            }\n            // Distinguishing Shift_JIS and ISO-8859-1 can be a little tough for short words. The crude heuristic is:\n            // - If we saw\n            //   - only two consecutive katakana chars in the whole text, or\n            //   - at least 10% of bytes that could be \"upper\" not-alphanumeric Latin1,\n            // - then we conclude Shift_JIS, else ISO-8859-1\n            if (canBeISO88591 && canBeShiftJIS) {\n                return (sjisMaxKatakanaWordLength === 2 && sjisKatakanaChars === 2) || isoHighOther * 10 >= length\n                    ? StringUtils.SHIFT_JIS : StringUtils.ISO88591;\n            }\n            // Otherwise, try in order ISO-8859-1, Shift JIS, UTF-8 and fall back to default platform encoding\n            if (canBeISO88591) {\n                return StringUtils.ISO88591;\n            }\n            if (canBeShiftJIS) {\n                return StringUtils.SHIFT_JIS;\n            }\n            if (canBeUTF8) {\n                return StringUtils.UTF8;\n            }\n            // Otherwise, we take a wild guess with platform encoding\n            return StringUtils.PLATFORM_DEFAULT_ENCODING;\n        }\n        /**\n         *\n         * @see https://stackoverflow.com/a/13439711/4367683\n         *\n         * @param append The new string to append.\n         * @param args Argumets values to be formated.\n         */\n        static format(append, ...args) {\n            let i = -1;\n            function callback(exp, p0, p1, p2, p3, p4) {\n                if (exp === '%%')\n                    return '%';\n                if (args[++i] === undefined)\n                    return undefined;\n                exp = p2 ? parseInt(p2.substr(1)) : undefined;\n                let base = p3 ? parseInt(p3.substr(1)) : undefined;\n                let val;\n                switch (p4) {\n                    case 's':\n                        val = args[i];\n                        break;\n                    case 'c':\n                        val = args[i][0];\n                        break;\n                    case 'f':\n                        val = parseFloat(args[i]).toFixed(exp);\n                        break;\n                    case 'p':\n                        val = parseFloat(args[i]).toPrecision(exp);\n                        break;\n                    case 'e':\n                        val = parseFloat(args[i]).toExponential(exp);\n                        break;\n                    case 'x':\n                        val = parseInt(args[i]).toString(base ? base : 16);\n                        break;\n                    case 'd':\n                        val = parseFloat(parseInt(args[i], base ? base : 10).toPrecision(exp)).toFixed(0);\n                        break;\n                }\n                val = typeof val === 'object' ? JSON.stringify(val) : (+val).toString(base);\n                let size = parseInt(p1); /* padding size */\n                let ch = p1 && (p1[0] + '') === '0' ? '0' : ' '; /* isnull? */\n                while (val.length < size)\n                    val = p0 !== undefined ? val + ch : ch + val; /* isminus? */\n                return val;\n            }\n            let regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g;\n            return append.replace(regex, callback);\n        }\n        /**\n         *\n         */\n        static getBytes(str, encoding) {\n            return StringEncoding.encode(str, encoding);\n        }\n        /**\n         * Returns the charcode at the specified index or at index zero.\n         */\n        static getCharCode(str, index = 0) {\n            return str.charCodeAt(index);\n        }\n        /**\n         * Returns char for given charcode\n         */\n        static getCharAt(charCode) {\n            return String.fromCharCode(charCode);\n        }\n    }\n    StringUtils.SHIFT_JIS = CharacterSetECI.SJIS.getName(); // \"SJIS\"\n    StringUtils.GB2312 = 'GB2312';\n    StringUtils.ISO88591 = CharacterSetECI.ISO8859_1.getName(); // \"ISO8859_1\"\n    StringUtils.EUC_JP = 'EUC_JP';\n    StringUtils.UTF8 = CharacterSetECI.UTF8.getName(); // \"UTF8\"\n    StringUtils.PLATFORM_DEFAULT_ENCODING = StringUtils.UTF8; // \"UTF8\"//Charset.defaultCharset().name()\n    StringUtils.ASSUME_SHIFT_JIS = false;\n\n    class StringBuilder {\n        constructor(value = '') {\n            this.value = value;\n        }\n        enableDecoding(encoding) {\n            this.encoding = encoding;\n            return this;\n        }\n        append(s) {\n            if (typeof s === 'string') {\n                this.value += s.toString();\n            }\n            else if (this.encoding) {\n                // use passed format (fromCharCode will return UTF8 encoding)\n                this.value += StringUtils.castAsNonUtf8Char(s, this.encoding);\n            }\n            else {\n                // correctly converts from UTF-8, but not other encodings\n                this.value += String.fromCharCode(s);\n            }\n            return this;\n        }\n        appendChars(str, offset, len) {\n            for (let i = offset; offset < offset + len; i++) {\n                this.append(str[i]);\n            }\n            return this;\n        }\n        length() {\n            return this.value.length;\n        }\n        charAt(n) {\n            return this.value.charAt(n);\n        }\n        deleteCharAt(n) {\n            this.value = this.value.substr(0, n) + this.value.substring(n + 1);\n        }\n        setCharAt(n, c) {\n            this.value = this.value.substr(0, n) + c + this.value.substr(n + 1);\n        }\n        substring(start, end) {\n            return this.value.substring(start, end);\n        }\n        /**\n         * @note helper method for RSS Expanded\n         */\n        setLengthToZero() {\n            this.value = '';\n        }\n        toString() {\n            return this.value;\n        }\n        insert(n, c) {\n            this.value = this.value.substr(0, n) + c + this.value.substr(n + c.length);\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Represents a 2D matrix of bits. In function arguments below, and throughout the common\n     * module, x is the column position, and y is the row position. The ordering is always x, y.\n     * The origin is at the top-left.</p>\n     *\n     * <p>Internally the bits are represented in a 1-D array of 32-bit ints. However, each row begins\n     * with a new int. This is done intentionally so that we can copy out a row into a BitArray very\n     * efficiently.</p>\n     *\n     * <p>The ordering of bits is row-major. Within each int, the least significant bits are used first,\n     * meaning they represent lower x values. This is compatible with BitArray's implementation.</p>\n     *\n     * @author Sean Owen\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class BitMatrix /*implements Cloneable*/ {\n        /**\n         * Creates an empty square {@link BitMatrix}.\n         *\n         * @param dimension height and width\n         */\n        // public constructor(dimension: number /*int*/) {\n        //   this(dimension, dimension)\n        // }\n        /**\n         * Creates an empty {@link BitMatrix}.\n         *\n         * @param width bit matrix width\n         * @param height bit matrix height\n         */\n        // public constructor(width: number /*int*/, height: number /*int*/) {\n        //   if (width < 1 || height < 1) {\n        //     throw new IllegalArgumentException(\"Both dimensions must be greater than 0\")\n        //   }\n        //   this.width = width\n        //   this.height = height\n        //   this.rowSize = (width + 31) / 32\n        //   bits = new int[rowSize * height];\n        // }\n        constructor(width /*int*/, height /*int*/, rowSize /*int*/, bits) {\n            this.width = width;\n            this.height = height;\n            this.rowSize = rowSize;\n            this.bits = bits;\n            if (undefined === height || null === height) {\n                height = width;\n            }\n            this.height = height;\n            if (width < 1 || height < 1) {\n                throw new IllegalArgumentException('Both dimensions must be greater than 0');\n            }\n            if (undefined === rowSize || null === rowSize) {\n                rowSize = Math.floor((width + 31) / 32);\n            }\n            this.rowSize = rowSize;\n            if (undefined === bits || null === bits) {\n                this.bits = new Int32Array(this.rowSize * this.height);\n            }\n        }\n        /**\n         * Interprets a 2D array of booleans as a {@link BitMatrix}, where \"true\" means an \"on\" bit.\n         *\n         * @function parse\n         * @param image bits of the image, as a row-major 2D array. Elements are arrays representing rows\n         * @return {@link BitMatrix} representation of image\n         */\n        static parseFromBooleanArray(image) {\n            const height = image.length;\n            const width = image[0].length;\n            const bits = new BitMatrix(width, height);\n            for (let i = 0; i < height; i++) {\n                const imageI = image[i];\n                for (let j = 0; j < width; j++) {\n                    if (imageI[j]) {\n                        bits.set(j, i);\n                    }\n                }\n            }\n            return bits;\n        }\n        /**\n         *\n         * @function parse\n         * @param stringRepresentation\n         * @param setString\n         * @param unsetString\n         */\n        static parseFromString(stringRepresentation, setString, unsetString) {\n            if (stringRepresentation === null) {\n                throw new IllegalArgumentException('stringRepresentation cannot be null');\n            }\n            const bits = new Array(stringRepresentation.length);\n            let bitsPos = 0;\n            let rowStartPos = 0;\n            let rowLength = -1;\n            let nRows = 0;\n            let pos = 0;\n            while (pos < stringRepresentation.length) {\n                if (stringRepresentation.charAt(pos) === '\\n' ||\n                    stringRepresentation.charAt(pos) === '\\r') {\n                    if (bitsPos > rowStartPos) {\n                        if (rowLength === -1) {\n                            rowLength = bitsPos - rowStartPos;\n                        }\n                        else if (bitsPos - rowStartPos !== rowLength) {\n                            throw new IllegalArgumentException('row lengths do not match');\n                        }\n                        rowStartPos = bitsPos;\n                        nRows++;\n                    }\n                    pos++;\n                }\n                else if (stringRepresentation.substring(pos, pos + setString.length) === setString) {\n                    pos += setString.length;\n                    bits[bitsPos] = true;\n                    bitsPos++;\n                }\n                else if (stringRepresentation.substring(pos, pos + unsetString.length) === unsetString) {\n                    pos += unsetString.length;\n                    bits[bitsPos] = false;\n                    bitsPos++;\n                }\n                else {\n                    throw new IllegalArgumentException('illegal character encountered: ' + stringRepresentation.substring(pos));\n                }\n            }\n            // no EOL at end?\n            if (bitsPos > rowStartPos) {\n                if (rowLength === -1) {\n                    rowLength = bitsPos - rowStartPos;\n                }\n                else if (bitsPos - rowStartPos !== rowLength) {\n                    throw new IllegalArgumentException('row lengths do not match');\n                }\n                nRows++;\n            }\n            const matrix = new BitMatrix(rowLength, nRows);\n            for (let i = 0; i < bitsPos; i++) {\n                if (bits[i]) {\n                    matrix.set(Math.floor(i % rowLength), Math.floor(i / rowLength));\n                }\n            }\n            return matrix;\n        }\n        /**\n         * <p>Gets the requested bit, where true means black.</p>\n         *\n         * @param x The horizontal component (i.e. which column)\n         * @param y The vertical component (i.e. which row)\n         * @return value of given bit in matrix\n         */\n        get(x /*int*/, y /*int*/) {\n            const offset = y * this.rowSize + Math.floor(x / 32);\n            return ((this.bits[offset] >>> (x & 0x1f)) & 1) !== 0;\n        }\n        /**\n         * <p>Sets the given bit to true.</p>\n         *\n         * @param x The horizontal component (i.e. which column)\n         * @param y The vertical component (i.e. which row)\n         */\n        set(x /*int*/, y /*int*/) {\n            const offset = y * this.rowSize + Math.floor(x / 32);\n            this.bits[offset] |= (1 << (x & 0x1f)) & 0xFFFFFFFF;\n        }\n        unset(x /*int*/, y /*int*/) {\n            const offset = y * this.rowSize + Math.floor(x / 32);\n            this.bits[offset] &= ~((1 << (x & 0x1f)) & 0xFFFFFFFF);\n        }\n        /**\n         * <p>Flips the given bit.</p>\n         *\n         * @param x The horizontal component (i.e. which column)\n         * @param y The vertical component (i.e. which row)\n         */\n        flip(x /*int*/, y /*int*/) {\n            const offset = y * this.rowSize + Math.floor(x / 32);\n            this.bits[offset] ^= ((1 << (x & 0x1f)) & 0xFFFFFFFF);\n        }\n        /**\n         * Exclusive-or (XOR): Flip the bit in this {@code BitMatrix} if the corresponding\n         * mask bit is set.\n         *\n         * @param mask XOR mask\n         */\n        xor(mask) {\n            if (this.width !== mask.getWidth() || this.height !== mask.getHeight()\n                || this.rowSize !== mask.getRowSize()) {\n                throw new IllegalArgumentException('input matrix dimensions do not match');\n            }\n            const rowArray = new BitArray(Math.floor(this.width / 32) + 1);\n            const rowSize = this.rowSize;\n            const bits = this.bits;\n            for (let y = 0, height = this.height; y < height; y++) {\n                const offset = y * rowSize;\n                const row = mask.getRow(y, rowArray).getBitArray();\n                for (let x = 0; x < rowSize; x++) {\n                    bits[offset + x] ^= row[x];\n                }\n            }\n        }\n        /**\n         * Clears all bits (sets to false).\n         */\n        clear() {\n            const bits = this.bits;\n            const max = bits.length;\n            for (let i = 0; i < max; i++) {\n                bits[i] = 0;\n            }\n        }\n        /**\n         * <p>Sets a square region of the bit matrix to true.</p>\n         *\n         * @param left The horizontal position to begin at (inclusive)\n         * @param top The vertical position to begin at (inclusive)\n         * @param width The width of the region\n         * @param height The height of the region\n         */\n        setRegion(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n            if (top < 0 || left < 0) {\n                throw new IllegalArgumentException('Left and top must be nonnegative');\n            }\n            if (height < 1 || width < 1) {\n                throw new IllegalArgumentException('Height and width must be at least 1');\n            }\n            const right = left + width;\n            const bottom = top + height;\n            if (bottom > this.height || right > this.width) {\n                throw new IllegalArgumentException('The region must fit inside the matrix');\n            }\n            const rowSize = this.rowSize;\n            const bits = this.bits;\n            for (let y = top; y < bottom; y++) {\n                const offset = y * rowSize;\n                for (let x = left; x < right; x++) {\n                    bits[offset + Math.floor(x / 32)] |= ((1 << (x & 0x1f)) & 0xFFFFFFFF);\n                }\n            }\n        }\n        /**\n         * A fast method to retrieve one row of data from the matrix as a BitArray.\n         *\n         * @param y The row to retrieve\n         * @param row An optional caller-allocated BitArray, will be allocated if null or too small\n         * @return The resulting BitArray - this reference should always be used even when passing\n         *         your own row\n         */\n        getRow(y /*int*/, row) {\n            if (row === null || row === undefined || row.getSize() < this.width) {\n                row = new BitArray(this.width);\n            }\n            else {\n                row.clear();\n            }\n            const rowSize = this.rowSize;\n            const bits = this.bits;\n            const offset = y * rowSize;\n            for (let x = 0; x < rowSize; x++) {\n                row.setBulk(x * 32, bits[offset + x]);\n            }\n            return row;\n        }\n        /**\n         * @param y row to set\n         * @param row {@link BitArray} to copy from\n         */\n        setRow(y /*int*/, row) {\n            System.arraycopy(row.getBitArray(), 0, this.bits, y * this.rowSize, this.rowSize);\n        }\n        /**\n         * Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees\n         */\n        rotate180() {\n            const width = this.getWidth();\n            const height = this.getHeight();\n            let topRow = new BitArray(width);\n            let bottomRow = new BitArray(width);\n            for (let i = 0, length = Math.floor((height + 1) / 2); i < length; i++) {\n                topRow = this.getRow(i, topRow);\n                bottomRow = this.getRow(height - 1 - i, bottomRow);\n                topRow.reverse();\n                bottomRow.reverse();\n                this.setRow(i, bottomRow);\n                this.setRow(height - 1 - i, topRow);\n            }\n        }\n        /**\n         * This is useful in detecting the enclosing rectangle of a 'pure' barcode.\n         *\n         * @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white\n         */\n        getEnclosingRectangle() {\n            const width = this.width;\n            const height = this.height;\n            const rowSize = this.rowSize;\n            const bits = this.bits;\n            let left = width;\n            let top = height;\n            let right = -1;\n            let bottom = -1;\n            for (let y = 0; y < height; y++) {\n                for (let x32 = 0; x32 < rowSize; x32++) {\n                    const theBits = bits[y * rowSize + x32];\n                    if (theBits !== 0) {\n                        if (y < top) {\n                            top = y;\n                        }\n                        if (y > bottom) {\n                            bottom = y;\n                        }\n                        if (x32 * 32 < left) {\n                            let bit = 0;\n                            while (((theBits << (31 - bit)) & 0xFFFFFFFF) === 0) {\n                                bit++;\n                            }\n                            if ((x32 * 32 + bit) < left) {\n                                left = x32 * 32 + bit;\n                            }\n                        }\n                        if (x32 * 32 + 31 > right) {\n                            let bit = 31;\n                            while ((theBits >>> bit) === 0) {\n                                bit--;\n                            }\n                            if ((x32 * 32 + bit) > right) {\n                                right = x32 * 32 + bit;\n                            }\n                        }\n                    }\n                }\n            }\n            if (right < left || bottom < top) {\n                return null;\n            }\n            return Int32Array.from([left, top, right - left + 1, bottom - top + 1]);\n        }\n        /**\n         * This is useful in detecting a corner of a 'pure' barcode.\n         *\n         * @return {@code x,y} coordinate of top-left-most 1 bit, or null if it is all white\n         */\n        getTopLeftOnBit() {\n            const rowSize = this.rowSize;\n            const bits = this.bits;\n            let bitsOffset = 0;\n            while (bitsOffset < bits.length && bits[bitsOffset] === 0) {\n                bitsOffset++;\n            }\n            if (bitsOffset === bits.length) {\n                return null;\n            }\n            const y = bitsOffset / rowSize;\n            let x = (bitsOffset % rowSize) * 32;\n            const theBits = bits[bitsOffset];\n            let bit = 0;\n            while (((theBits << (31 - bit)) & 0xFFFFFFFF) === 0) {\n                bit++;\n            }\n            x += bit;\n            return Int32Array.from([x, y]);\n        }\n        getBottomRightOnBit() {\n            const rowSize = this.rowSize;\n            const bits = this.bits;\n            let bitsOffset = bits.length - 1;\n            while (bitsOffset >= 0 && bits[bitsOffset] === 0) {\n                bitsOffset--;\n            }\n            if (bitsOffset < 0) {\n                return null;\n            }\n            const y = Math.floor(bitsOffset / rowSize);\n            let x = Math.floor(bitsOffset % rowSize) * 32;\n            const theBits = bits[bitsOffset];\n            let bit = 31;\n            while ((theBits >>> bit) === 0) {\n                bit--;\n            }\n            x += bit;\n            return Int32Array.from([x, y]);\n        }\n        /**\n         * @return The width of the matrix\n         */\n        getWidth() {\n            return this.width;\n        }\n        /**\n         * @return The height of the matrix\n         */\n        getHeight() {\n            return this.height;\n        }\n        /**\n         * @return The row size of the matrix\n         */\n        getRowSize() {\n            return this.rowSize;\n        }\n        /*@Override*/\n        equals(o) {\n            if (!(o instanceof BitMatrix)) {\n                return false;\n            }\n            const other = o;\n            return this.width === other.width && this.height === other.height && this.rowSize === other.rowSize &&\n                Arrays.equals(this.bits, other.bits);\n        }\n        /*@Override*/\n        hashCode() {\n            let hash = this.width;\n            hash = 31 * hash + this.width;\n            hash = 31 * hash + this.height;\n            hash = 31 * hash + this.rowSize;\n            hash = 31 * hash + Arrays.hashCode(this.bits);\n            return hash;\n        }\n        /**\n         * @return string representation using \"X\" for set and \" \" for unset bits\n         */\n        /*@Override*/\n        // public toString(): string {\n        //   return toString(\": \"X, \"  \")\n        // }\n        /**\n         * @param setString representation of a set bit\n         * @param unsetString representation of an unset bit\n         * @return string representation of entire matrix utilizing given strings\n         */\n        // public toString(setString: string = \"X \", unsetString: string = \"  \"): string {\n        //   return this.buildToString(setString, unsetString, \"\\n\")\n        // }\n        /**\n         * @param setString representation of a set bit\n         * @param unsetString representation of an unset bit\n         * @param lineSeparator newline character in string representation\n         * @return string representation of entire matrix utilizing given strings and line separator\n         * @deprecated call {@link #toString(String,String)} only, which uses \\n line separator always\n         */\n        // @Deprecated\n        toString(setString = 'X ', unsetString = '  ', lineSeparator = '\\n') {\n            return this.buildToString(setString, unsetString, lineSeparator);\n        }\n        buildToString(setString, unsetString, lineSeparator) {\n            let result = new StringBuilder();\n            // result.append(lineSeparator);\n            for (let y = 0, height = this.height; y < height; y++) {\n                for (let x = 0, width = this.width; x < width; x++) {\n                    result.append(this.get(x, y) ? setString : unsetString);\n                }\n                result.append(lineSeparator);\n            }\n            return result.toString();\n        }\n        /*@Override*/\n        clone() {\n            return new BitMatrix(this.width, this.height, this.rowSize, this.bits.slice());\n        }\n    }\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class NotFoundException extends Exception {\n        static getNotFoundInstance() {\n            return new NotFoundException();\n        }\n    }\n    NotFoundException.kind = 'NotFoundException';\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * This Binarizer implementation uses the old ZXing global histogram approach. It is suitable\n     * for low-end mobile devices which don't have enough CPU or memory to use a local thresholding\n     * algorithm. However, because it picks a global black point, it cannot handle difficult shadows\n     * and gradients.\n     *\n     * Faster mobile devices and all desktop applications should probably use HybridBinarizer instead.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @author Sean Owen\n     */\n    class GlobalHistogramBinarizer extends Binarizer {\n        constructor(source) {\n            super(source);\n            this.luminances = GlobalHistogramBinarizer.EMPTY;\n            this.buckets = new Int32Array(GlobalHistogramBinarizer.LUMINANCE_BUCKETS);\n        }\n        // Applies simple sharpening to the row data to improve performance of the 1D Readers.\n        /*@Override*/\n        getBlackRow(y /*int*/, row) {\n            const source = this.getLuminanceSource();\n            const width = source.getWidth();\n            if (row === undefined || row === null || row.getSize() < width) {\n                row = new BitArray(width);\n            }\n            else {\n                row.clear();\n            }\n            this.initArrays(width);\n            const localLuminances = source.getRow(y, this.luminances);\n            const localBuckets = this.buckets;\n            for (let x = 0; x < width; x++) {\n                localBuckets[(localLuminances[x] & 0xff) >> GlobalHistogramBinarizer.LUMINANCE_SHIFT]++;\n            }\n            const blackPoint = GlobalHistogramBinarizer.estimateBlackPoint(localBuckets);\n            if (width < 3) {\n                // Special case for very small images\n                for (let x = 0; x < width; x++) {\n                    if ((localLuminances[x] & 0xff) < blackPoint) {\n                        row.set(x);\n                    }\n                }\n            }\n            else {\n                let left = localLuminances[0] & 0xff;\n                let center = localLuminances[1] & 0xff;\n                for (let x = 1; x < width - 1; x++) {\n                    const right = localLuminances[x + 1] & 0xff;\n                    // A simple -1 4 -1 box filter with a weight of 2.\n                    if (((center * 4) - left - right) / 2 < blackPoint) {\n                        row.set(x);\n                    }\n                    left = center;\n                    center = right;\n                }\n            }\n            return row;\n        }\n        // Does not sharpen the data, as this call is intended to only be used by 2D Readers.\n        /*@Override*/\n        getBlackMatrix() {\n            const source = this.getLuminanceSource();\n            const width = source.getWidth();\n            const height = source.getHeight();\n            const matrix = new BitMatrix(width, height);\n            // Quickly calculates the histogram by sampling four rows from the image. This proved to be\n            // more robust on the blackbox tests than sampling a diagonal as we used to do.\n            this.initArrays(width);\n            const localBuckets = this.buckets;\n            for (let y = 1; y < 5; y++) {\n                const row = Math.floor((height * y) / 5);\n                const localLuminances = source.getRow(row, this.luminances);\n                const right = Math.floor((width * 4) / 5);\n                for (let x = Math.floor(width / 5); x < right; x++) {\n                    const pixel = localLuminances[x] & 0xff;\n                    localBuckets[pixel >> GlobalHistogramBinarizer.LUMINANCE_SHIFT]++;\n                }\n            }\n            const blackPoint = GlobalHistogramBinarizer.estimateBlackPoint(localBuckets);\n            // We delay reading the entire image luminance until the black point estimation succeeds.\n            // Although we end up reading four rows twice, it is consistent with our motto of\n            // \"fail quickly\" which is necessary for continuous scanning.\n            const localLuminances = source.getMatrix();\n            for (let y = 0; y < height; y++) {\n                const offset = y * width;\n                for (let x = 0; x < width; x++) {\n                    const pixel = localLuminances[offset + x] & 0xff;\n                    if (pixel < blackPoint) {\n                        matrix.set(x, y);\n                    }\n                }\n            }\n            return matrix;\n        }\n        /*@Override*/\n        createBinarizer(source) {\n            return new GlobalHistogramBinarizer(source);\n        }\n        initArrays(luminanceSize /*int*/) {\n            if (this.luminances.length < luminanceSize) {\n                this.luminances = new Uint8ClampedArray(luminanceSize);\n            }\n            const buckets = this.buckets;\n            for (let x = 0; x < GlobalHistogramBinarizer.LUMINANCE_BUCKETS; x++) {\n                buckets[x] = 0;\n            }\n        }\n        static estimateBlackPoint(buckets) {\n            // Find the tallest peak in the histogram.\n            const numBuckets = buckets.length;\n            let maxBucketCount = 0;\n            let firstPeak = 0;\n            let firstPeakSize = 0;\n            for (let x = 0; x < numBuckets; x++) {\n                if (buckets[x] > firstPeakSize) {\n                    firstPeak = x;\n                    firstPeakSize = buckets[x];\n                }\n                if (buckets[x] > maxBucketCount) {\n                    maxBucketCount = buckets[x];\n                }\n            }\n            // Find the second-tallest peak which is somewhat far from the tallest peak.\n            let secondPeak = 0;\n            let secondPeakScore = 0;\n            for (let x = 0; x < numBuckets; x++) {\n                const distanceToBiggest = x - firstPeak;\n                // Encourage more distant second peaks by multiplying by square of distance.\n                const score = buckets[x] * distanceToBiggest * distanceToBiggest;\n                if (score > secondPeakScore) {\n                    secondPeak = x;\n                    secondPeakScore = score;\n                }\n            }\n            // Make sure firstPeak corresponds to the black peak.\n            if (firstPeak > secondPeak) {\n                const temp = firstPeak;\n                firstPeak = secondPeak;\n                secondPeak = temp;\n            }\n            // If there is too little contrast in the image to pick a meaningful black point, throw rather\n            // than waste time trying to decode the image, and risk false positives.\n            if (secondPeak - firstPeak <= numBuckets / 16) {\n                throw new NotFoundException();\n            }\n            // Find a valley between them that is low and closer to the white peak.\n            let bestValley = secondPeak - 1;\n            let bestValleyScore = -1;\n            for (let x = secondPeak - 1; x > firstPeak; x--) {\n                const fromFirst = x - firstPeak;\n                const score = fromFirst * fromFirst * (secondPeak - x) * (maxBucketCount - buckets[x]);\n                if (score > bestValleyScore) {\n                    bestValley = x;\n                    bestValleyScore = score;\n                }\n            }\n            return bestValley << GlobalHistogramBinarizer.LUMINANCE_SHIFT;\n        }\n    }\n    GlobalHistogramBinarizer.LUMINANCE_BITS = 5;\n    GlobalHistogramBinarizer.LUMINANCE_SHIFT = 8 - GlobalHistogramBinarizer.LUMINANCE_BITS;\n    GlobalHistogramBinarizer.LUMINANCE_BUCKETS = 1 << GlobalHistogramBinarizer.LUMINANCE_BITS;\n    GlobalHistogramBinarizer.EMPTY = Uint8ClampedArray.from([0]);\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * This class implements a local thresholding algorithm, which while slower than the\n     * GlobalHistogramBinarizer, is fairly efficient for what it does. It is designed for\n     * high frequency images of barcodes with black data on white backgrounds. For this application,\n     * it does a much better job than a global blackpoint with severe shadows and gradients.\n     * However it tends to produce artifacts on lower frequency images and is therefore not\n     * a good general purpose binarizer for uses outside ZXing.\n     *\n     * This class extends GlobalHistogramBinarizer, using the older histogram approach for 1D readers,\n     * and the newer local approach for 2D readers. 1D decoding using a per-row histogram is already\n     * inherently local, and only fails for horizontal gradients. We can revisit that problem later,\n     * but for now it was not a win to use local blocks for 1D.\n     *\n     * This Binarizer is the default for the unit tests and the recommended class for library users.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class HybridBinarizer extends GlobalHistogramBinarizer {\n        constructor(source) {\n            super(source);\n            this.matrix = null;\n        }\n        /**\n         * Calculates the final BitMatrix once for all requests. This could be called once from the\n         * constructor instead, but there are some advantages to doing it lazily, such as making\n         * profiling easier, and not doing heavy lifting when callers don't expect it.\n         */\n        /*@Override*/\n        getBlackMatrix() {\n            if (this.matrix !== null) {\n                return this.matrix;\n            }\n            const source = this.getLuminanceSource();\n            const width = source.getWidth();\n            const height = source.getHeight();\n            if (width >= HybridBinarizer.MINIMUM_DIMENSION && height >= HybridBinarizer.MINIMUM_DIMENSION) {\n                const luminances = source.getMatrix();\n                let subWidth = width >> HybridBinarizer.BLOCK_SIZE_POWER;\n                if ((width & HybridBinarizer.BLOCK_SIZE_MASK) !== 0) {\n                    subWidth++;\n                }\n                let subHeight = height >> HybridBinarizer.BLOCK_SIZE_POWER;\n                if ((height & HybridBinarizer.BLOCK_SIZE_MASK) !== 0) {\n                    subHeight++;\n                }\n                const blackPoints = HybridBinarizer.calculateBlackPoints(luminances, subWidth, subHeight, width, height);\n                const newMatrix = new BitMatrix(width, height);\n                HybridBinarizer.calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix);\n                this.matrix = newMatrix;\n            }\n            else {\n                // If the image is too small, fall back to the global histogram approach.\n                this.matrix = super.getBlackMatrix();\n            }\n            return this.matrix;\n        }\n        /*@Override*/\n        createBinarizer(source) {\n            return new HybridBinarizer(source);\n        }\n        /**\n         * For each block in the image, calculate the average black point using a 5x5 grid\n         * of the blocks around it. Also handles the corner cases (fractional blocks are computed based\n         * on the last pixels in the row/column which are also used in the previous block).\n         */\n        static calculateThresholdForBlock(luminances, subWidth /*int*/, subHeight /*int*/, width /*int*/, height /*int*/, blackPoints, matrix) {\n            const maxYOffset = height - HybridBinarizer.BLOCK_SIZE;\n            const maxXOffset = width - HybridBinarizer.BLOCK_SIZE;\n            for (let y = 0; y < subHeight; y++) {\n                let yoffset = y << HybridBinarizer.BLOCK_SIZE_POWER;\n                if (yoffset > maxYOffset) {\n                    yoffset = maxYOffset;\n                }\n                const top = HybridBinarizer.cap(y, 2, subHeight - 3);\n                for (let x = 0; x < subWidth; x++) {\n                    let xoffset = x << HybridBinarizer.BLOCK_SIZE_POWER;\n                    if (xoffset > maxXOffset) {\n                        xoffset = maxXOffset;\n                    }\n                    const left = HybridBinarizer.cap(x, 2, subWidth - 3);\n                    let sum = 0;\n                    for (let z = -2; z <= 2; z++) {\n                        const blackRow = blackPoints[top + z];\n                        sum += blackRow[left - 2] + blackRow[left - 1] + blackRow[left] + blackRow[left + 1] + blackRow[left + 2];\n                    }\n                    const average = sum / 25;\n                    HybridBinarizer.thresholdBlock(luminances, xoffset, yoffset, average, width, matrix);\n                }\n            }\n        }\n        static cap(value /*int*/, min /*int*/, max /*int*/) {\n            return value < min ? min : value > max ? max : value;\n        }\n        /**\n         * Applies a single threshold to a block of pixels.\n         */\n        static thresholdBlock(luminances, xoffset /*int*/, yoffset /*int*/, threshold /*int*/, stride /*int*/, matrix) {\n            for (let y = 0, offset = yoffset * stride + xoffset; y < HybridBinarizer.BLOCK_SIZE; y++, offset += stride) {\n                for (let x = 0; x < HybridBinarizer.BLOCK_SIZE; x++) {\n                    // Comparison needs to be <= so that black == 0 pixels are black even if the threshold is 0.\n                    if ((luminances[offset + x] & 0xFF) <= threshold) {\n                        matrix.set(xoffset + x, yoffset + y);\n                    }\n                }\n            }\n        }\n        /**\n         * Calculates a single black point for each block of pixels and saves it away.\n         * See the following thread for a discussion of this algorithm:\n         *  http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0\n         */\n        static calculateBlackPoints(luminances, subWidth /*int*/, subHeight /*int*/, width /*int*/, height /*int*/) {\n            const maxYOffset = height - HybridBinarizer.BLOCK_SIZE;\n            const maxXOffset = width - HybridBinarizer.BLOCK_SIZE;\n            // tslint:disable-next-line:whitespace\n            const blackPoints = new Array(subHeight); // subWidth\n            for (let y = 0; y < subHeight; y++) {\n                blackPoints[y] = new Int32Array(subWidth);\n                let yoffset = y << HybridBinarizer.BLOCK_SIZE_POWER;\n                if (yoffset > maxYOffset) {\n                    yoffset = maxYOffset;\n                }\n                for (let x = 0; x < subWidth; x++) {\n                    let xoffset = x << HybridBinarizer.BLOCK_SIZE_POWER;\n                    if (xoffset > maxXOffset) {\n                        xoffset = maxXOffset;\n                    }\n                    let sum = 0;\n                    let min = 0xFF;\n                    let max = 0;\n                    for (let yy = 0, offset = yoffset * width + xoffset; yy < HybridBinarizer.BLOCK_SIZE; yy++, offset += width) {\n                        for (let xx = 0; xx < HybridBinarizer.BLOCK_SIZE; xx++) {\n                            const pixel = luminances[offset + xx] & 0xFF;\n                            sum += pixel;\n                            // still looking for good contrast\n                            if (pixel < min) {\n                                min = pixel;\n                            }\n                            if (pixel > max) {\n                                max = pixel;\n                            }\n                        }\n                        // short-circuit min/max tests once dynamic range is met\n                        if (max - min > HybridBinarizer.MIN_DYNAMIC_RANGE) {\n                            // finish the rest of the rows quickly\n                            for (yy++, offset += width; yy < HybridBinarizer.BLOCK_SIZE; yy++, offset += width) {\n                                for (let xx = 0; xx < HybridBinarizer.BLOCK_SIZE; xx++) {\n                                    sum += luminances[offset + xx] & 0xFF;\n                                }\n                            }\n                        }\n                    }\n                    // The default estimate is the average of the values in the block.\n                    let average = sum >> (HybridBinarizer.BLOCK_SIZE_POWER * 2);\n                    if (max - min <= HybridBinarizer.MIN_DYNAMIC_RANGE) {\n                        // If variation within the block is low, assume this is a block with only light or only\n                        // dark pixels. In that case we do not want to use the average, as it would divide this\n                        // low contrast area into black and white pixels, essentially creating data out of noise.\n                        //\n                        // The default assumption is that the block is light/background. Since no estimate for\n                        // the level of dark pixels exists locally, use half the min for the block.\n                        average = min / 2;\n                        if (y > 0 && x > 0) {\n                            // Correct the \"white background\" assumption for blocks that have neighbors by comparing\n                            // the pixels in this block to the previously calculated black points. This is based on\n                            // the fact that dark barcode symbology is always surrounded by some amount of light\n                            // background for which reasonable black point estimates were made. The bp estimated at\n                            // the boundaries is used for the interior.\n                            // The (min < bp) is arbitrary but works better than other heuristics that were tried.\n                            const averageNeighborBlackPoint = (blackPoints[y - 1][x] + (2 * blackPoints[y][x - 1]) + blackPoints[y - 1][x - 1]) / 4;\n                            if (min < averageNeighborBlackPoint) {\n                                average = averageNeighborBlackPoint;\n                            }\n                        }\n                    }\n                    blackPoints[y][x] = average;\n                }\n            }\n            return blackPoints;\n        }\n    }\n    // This class uses 5x5 blocks to compute local luminance, where each block is 8x8 pixels.\n    // So this is the smallest dimension in each axis we can accept.\n    HybridBinarizer.BLOCK_SIZE_POWER = 3;\n    HybridBinarizer.BLOCK_SIZE = 1 << HybridBinarizer.BLOCK_SIZE_POWER; // ...0100...00\n    HybridBinarizer.BLOCK_SIZE_MASK = HybridBinarizer.BLOCK_SIZE - 1; // ...0011...11\n    HybridBinarizer.MINIMUM_DIMENSION = HybridBinarizer.BLOCK_SIZE * 5;\n    HybridBinarizer.MIN_DYNAMIC_RANGE = 24;\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing {*/\n    /**\n     * The purpose of this class hierarchy is to abstract different bitmap implementations across\n     * platforms into a standard interface for requesting greyscale luminance values. The interface\n     * only provides immutable methods; therefore crop and rotation create copies. This is to ensure\n     * that one Reader does not modify the original luminance source and leave it in an unknown state\n     * for other Readers in the chain.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class LuminanceSource {\n        constructor(width /*int*/, height /*int*/) {\n            this.width = width;\n            this.height = height;\n        }\n        /**\n         * @return The width of the bitmap.\n         */\n        getWidth() {\n            return this.width;\n        }\n        /**\n         * @return The height of the bitmap.\n         */\n        getHeight() {\n            return this.height;\n        }\n        /**\n         * @return Whether this subclass supports cropping.\n         */\n        isCropSupported() {\n            return false;\n        }\n        /**\n         * Returns a new object with cropped image data. Implementations may keep a reference to the\n         * original data rather than a copy. Only callable if isCropSupported() is true.\n         *\n         * @param left The left coordinate, which must be in [0,getWidth())\n         * @param top The top coordinate, which must be in [0,getHeight())\n         * @param width The width of the rectangle to crop.\n         * @param height The height of the rectangle to crop.\n         * @return A cropped version of this object.\n         */\n        crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n            throw new UnsupportedOperationException('This luminance source does not support cropping.');\n        }\n        /**\n         * @return Whether this subclass supports counter-clockwise rotation.\n         */\n        isRotateSupported() {\n            return false;\n        }\n        /**\n         * Returns a new object with rotated image data by 90 degrees counterclockwise.\n         * Only callable if {@link #isRotateSupported()} is true.\n         *\n         * @return A rotated version of this object.\n         */\n        rotateCounterClockwise() {\n            throw new UnsupportedOperationException('This luminance source does not support rotation by 90 degrees.');\n        }\n        /**\n         * Returns a new object with rotated image data by 45 degrees counterclockwise.\n         * Only callable if {@link #isRotateSupported()} is true.\n         *\n         * @return A rotated version of this object.\n         */\n        rotateCounterClockwise45() {\n            throw new UnsupportedOperationException('This luminance source does not support rotation by 45 degrees.');\n        }\n        /*@Override*/\n        toString() {\n            const row = new Uint8ClampedArray(this.width);\n            let result = new StringBuilder();\n            for (let y = 0; y < this.height; y++) {\n                const sourceRow = this.getRow(y, row);\n                for (let x = 0; x < this.width; x++) {\n                    const luminance = sourceRow[x] & 0xFF;\n                    let c;\n                    if (luminance < 0x40) {\n                        c = '#';\n                    }\n                    else if (luminance < 0x80) {\n                        c = '+';\n                    }\n                    else if (luminance < 0xC0) {\n                        c = '.';\n                    }\n                    else {\n                        c = ' ';\n                    }\n                    result.append(c);\n                }\n                result.append('\\n');\n            }\n            return result.toString();\n        }\n    }\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing {*/\n    /**\n     * A wrapper implementation of {@link LuminanceSource} which inverts the luminances it returns -- black becomes\n     * white and vice versa, and each value becomes (255-value).\n     *\n     * @author Sean Owen\n     */\n    class InvertedLuminanceSource extends LuminanceSource {\n        constructor(delegate) {\n            super(delegate.getWidth(), delegate.getHeight());\n            this.delegate = delegate;\n        }\n        /*@Override*/\n        getRow(y /*int*/, row) {\n            const sourceRow = this.delegate.getRow(y, row);\n            const width = this.getWidth();\n            for (let i = 0; i < width; i++) {\n                sourceRow[i] = /*(byte)*/ (255 - (sourceRow[i] & 0xFF));\n            }\n            return sourceRow;\n        }\n        /*@Override*/\n        getMatrix() {\n            const matrix = this.delegate.getMatrix();\n            const length = this.getWidth() * this.getHeight();\n            const invertedMatrix = new Uint8ClampedArray(length);\n            for (let i = 0; i < length; i++) {\n                invertedMatrix[i] = /*(byte)*/ (255 - (matrix[i] & 0xFF));\n            }\n            return invertedMatrix;\n        }\n        /*@Override*/\n        isCropSupported() {\n            return this.delegate.isCropSupported();\n        }\n        /*@Override*/\n        crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n            return new InvertedLuminanceSource(this.delegate.crop(left, top, width, height));\n        }\n        /*@Override*/\n        isRotateSupported() {\n            return this.delegate.isRotateSupported();\n        }\n        /**\n         * @return original delegate {@link LuminanceSource} since invert undoes itself\n         */\n        /*@Override*/\n        invert() {\n            return this.delegate;\n        }\n        /*@Override*/\n        rotateCounterClockwise() {\n            return new InvertedLuminanceSource(this.delegate.rotateCounterClockwise());\n        }\n        /*@Override*/\n        rotateCounterClockwise45() {\n            return new InvertedLuminanceSource(this.delegate.rotateCounterClockwise45());\n        }\n    }\n\n    /**\n     * @deprecated Moving to @zxing/browser\n     */\n    class HTMLCanvasElementLuminanceSource extends LuminanceSource {\n        constructor(canvas) {\n            super(canvas.width, canvas.height);\n            this.canvas = canvas;\n            this.tempCanvasElement = null;\n            this.buffer = HTMLCanvasElementLuminanceSource.makeBufferFromCanvasImageData(canvas);\n        }\n        static makeBufferFromCanvasImageData(canvas) {\n            const imageData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);\n            return HTMLCanvasElementLuminanceSource.toGrayscaleBuffer(imageData.data, canvas.width, canvas.height);\n        }\n        static toGrayscaleBuffer(imageBuffer, width, height) {\n            const grayscaleBuffer = new Uint8ClampedArray(width * height);\n            for (let i = 0, j = 0, length = imageBuffer.length; i < length; i += 4, j++) {\n                let gray;\n                const alpha = imageBuffer[i + 3];\n                // The color of fully-transparent pixels is irrelevant. They are often, technically, fully-transparent\n                // black (0 alpha, and then 0 RGB). They are often used, of course as the \"white\" area in a\n                // barcode image. Force any such pixel to be white:\n                if (alpha === 0) {\n                    gray = 0xFF;\n                }\n                else {\n                    const pixelR = imageBuffer[i];\n                    const pixelG = imageBuffer[i + 1];\n                    const pixelB = imageBuffer[i + 2];\n                    // .299R + 0.587G + 0.114B (YUV/YIQ for PAL and NTSC),\n                    // (306*R) >> 10 is approximately equal to R*0.299, and so on.\n                    // 0x200 >> 10 is 0.5, it implements rounding.\n                    gray = (306 * pixelR +\n                        601 * pixelG +\n                        117 * pixelB +\n                        0x200) >> 10;\n                }\n                grayscaleBuffer[j] = gray;\n            }\n            return grayscaleBuffer;\n        }\n        getRow(y /*int*/, row) {\n            if (y < 0 || y >= this.getHeight()) {\n                throw new IllegalArgumentException('Requested row is outside the image: ' + y);\n            }\n            const width = this.getWidth();\n            const start = y * width;\n            if (row === null) {\n                row = this.buffer.slice(start, start + width);\n            }\n            else {\n                if (row.length < width) {\n                    row = new Uint8ClampedArray(width);\n                }\n                // The underlying raster of image consists of bytes with the luminance values\n                // TODO: can avoid set/slice?\n                row.set(this.buffer.slice(start, start + width));\n            }\n            return row;\n        }\n        getMatrix() {\n            return this.buffer;\n        }\n        isCropSupported() {\n            return true;\n        }\n        crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n            super.crop(left, top, width, height);\n            return this;\n        }\n        /**\n         * This is always true, since the image is a gray-scale image.\n         *\n         * @return true\n         */\n        isRotateSupported() {\n            return true;\n        }\n        rotateCounterClockwise() {\n            this.rotate(-90);\n            return this;\n        }\n        rotateCounterClockwise45() {\n            this.rotate(-45);\n            return this;\n        }\n        getTempCanvasElement() {\n            if (null === this.tempCanvasElement) {\n                const tempCanvasElement = this.canvas.ownerDocument.createElement('canvas');\n                tempCanvasElement.width = this.canvas.width;\n                tempCanvasElement.height = this.canvas.height;\n                this.tempCanvasElement = tempCanvasElement;\n            }\n            return this.tempCanvasElement;\n        }\n        rotate(angle) {\n            const tempCanvasElement = this.getTempCanvasElement();\n            const tempContext = tempCanvasElement.getContext('2d');\n            const angleRadians = angle * HTMLCanvasElementLuminanceSource.DEGREE_TO_RADIANS;\n            // Calculate and set new dimensions for temp canvas\n            const width = this.canvas.width;\n            const height = this.canvas.height;\n            const newWidth = Math.ceil(Math.abs(Math.cos(angleRadians)) * width + Math.abs(Math.sin(angleRadians)) * height);\n            const newHeight = Math.ceil(Math.abs(Math.sin(angleRadians)) * width + Math.abs(Math.cos(angleRadians)) * height);\n            tempCanvasElement.width = newWidth;\n            tempCanvasElement.height = newHeight;\n            // Draw at center of temp canvas to prevent clipping of image data\n            tempContext.translate(newWidth / 2, newHeight / 2);\n            tempContext.rotate(angleRadians);\n            tempContext.drawImage(this.canvas, width / -2, height / -2);\n            this.buffer = HTMLCanvasElementLuminanceSource.makeBufferFromCanvasImageData(tempCanvasElement);\n            return this;\n        }\n        invert() {\n            return new InvertedLuminanceSource(this);\n        }\n    }\n    HTMLCanvasElementLuminanceSource.DEGREE_TO_RADIANS = Math.PI / 180;\n\n    /**\n     * @deprecated Moving to @zxing/browser\n     *\n     * Video input device metadata containing the id and label of the device if available.\n     */\n    class VideoInputDevice {\n        /**\n         * Creates an instance of VideoInputDevice.\n         *\n         * @param {string} deviceId the video input device id\n         * @param {string} label the label of the device if available\n         */\n        constructor(deviceId, label, groupId) {\n            this.deviceId = deviceId;\n            this.label = label;\n            /** @inheritdoc */\n            this.kind = 'videoinput';\n            this.groupId = groupId || undefined;\n        }\n        /** @inheritdoc */\n        toJSON() {\n            return {\n                kind: this.kind,\n                groupId: this.groupId,\n                deviceId: this.deviceId,\n                label: this.label,\n            };\n        }\n    }\n\n    var __awaiter = ((globalThis || __webpack_require__.g || self || window || undefined) && (globalThis || __webpack_require__.g || self || window || undefined).__awaiter) || function (thisArg, _arguments, P, generator) {\n        function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n        return new (P || (P = Promise))(function (resolve, reject) {\n            function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n            function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n            function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n            step((generator = generator.apply(thisArg, _arguments || [])).next());\n        });\n    };\n    /**\n     * @deprecated Moving to @zxing/browser\n     *\n     * Base class for browser code reader.\n     */\n    class BrowserCodeReader {\n        /**\n         * Creates an instance of BrowserCodeReader.\n         * @param {Reader} reader The reader instance to decode the barcode\n         * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent successful decode tries\n         *\n         * @memberOf BrowserCodeReader\n         */\n        constructor(reader, timeBetweenScansMillis = 500, _hints) {\n            this.reader = reader;\n            this.timeBetweenScansMillis = timeBetweenScansMillis;\n            this._hints = _hints;\n            /**\n             * This will break the loop.\n             */\n            this._stopContinuousDecode = false;\n            /**\n             * This will break the loop.\n             */\n            this._stopAsyncDecode = false;\n            /**\n             * Delay time between decode attempts made by the scanner.\n             */\n            this._timeBetweenDecodingAttempts = 0;\n        }\n        /**\n         * If navigator is present.\n         */\n        get hasNavigator() {\n            return typeof navigator !== 'undefined';\n        }\n        /**\n         * If mediaDevices under navigator is supported.\n         */\n        get isMediaDevicesSuported() {\n            return this.hasNavigator && !!navigator.mediaDevices;\n        }\n        /**\n         * If enumerateDevices under navigator is supported.\n         */\n        get canEnumerateDevices() {\n            return !!(this.isMediaDevicesSuported && navigator.mediaDevices.enumerateDevices);\n        }\n        /** Time between two decoding tries in milli seconds. */\n        get timeBetweenDecodingAttempts() {\n            return this._timeBetweenDecodingAttempts;\n        }\n        /**\n         * Change the time span the decoder waits between two decoding tries.\n         *\n         * @param {number} millis Time between two decoding tries in milli seconds.\n         */\n        set timeBetweenDecodingAttempts(millis) {\n            this._timeBetweenDecodingAttempts = millis < 0 ? 0 : millis;\n        }\n        /**\n         * Sets the hints.\n         */\n        set hints(hints) {\n            this._hints = hints || null;\n        }\n        /**\n         * Sets the hints.\n         */\n        get hints() {\n            return this._hints;\n        }\n        /**\n         * Lists all the available video input devices.\n         */\n        listVideoInputDevices() {\n            return __awaiter(this, void 0, void 0, function* () {\n                if (!this.hasNavigator) {\n                    throw new Error('Can\\'t enumerate devices, navigator is not present.');\n                }\n                if (!this.canEnumerateDevices) {\n                    throw new Error('Can\\'t enumerate devices, method not supported.');\n                }\n                const devices = yield navigator.mediaDevices.enumerateDevices();\n                const videoDevices = [];\n                for (const device of devices) {\n                    const kind = device.kind === 'video' ? 'videoinput' : device.kind;\n                    if (kind !== 'videoinput') {\n                        continue;\n                    }\n                    const deviceId = device.deviceId || device.id;\n                    const label = device.label || `Video device ${videoDevices.length + 1}`;\n                    const groupId = device.groupId;\n                    const videoDevice = { deviceId, label, kind, groupId };\n                    videoDevices.push(videoDevice);\n                }\n                return videoDevices;\n            });\n        }\n        /**\n         * Obtain the list of available devices with type 'videoinput'.\n         *\n         * @returns {Promise<VideoInputDevice[]>} an array of available video input devices\n         *\n         * @memberOf BrowserCodeReader\n         *\n         * @deprecated Use `listVideoInputDevices` instead.\n         */\n        getVideoInputDevices() {\n            return __awaiter(this, void 0, void 0, function* () {\n                const devices = yield this.listVideoInputDevices();\n                return devices.map(d => new VideoInputDevice(d.deviceId, d.label));\n            });\n        }\n        /**\n         * Let's you find a device using it's Id.\n         */\n        findDeviceById(deviceId) {\n            return __awaiter(this, void 0, void 0, function* () {\n                const devices = yield this.listVideoInputDevices();\n                if (!devices) {\n                    return null;\n                }\n                return devices.find(x => x.deviceId === deviceId);\n            });\n        }\n        /**\n         * Decodes the barcode from the device specified by deviceId while showing the video in the specified video element.\n         *\n         * @param deviceId the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available.\n         * @param video the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n         * @returns The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         *\n         * @deprecated Use `decodeOnceFromVideoDevice` instead.\n         */\n        decodeFromInputVideoDevice(deviceId, videoSource) {\n            return __awaiter(this, void 0, void 0, function* () {\n                return yield this.decodeOnceFromVideoDevice(deviceId, videoSource);\n            });\n        }\n        /**\n         * In one attempt, tries to decode the barcode from the device specified by deviceId while showing the video in the specified video element.\n         *\n         * @param deviceId the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available.\n         * @param video the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n         * @returns The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         */\n        decodeOnceFromVideoDevice(deviceId, videoSource) {\n            return __awaiter(this, void 0, void 0, function* () {\n                this.reset();\n                let videoConstraints;\n                if (!deviceId) {\n                    videoConstraints = { facingMode: 'environment' };\n                }\n                else {\n                    videoConstraints = { deviceId: { exact: deviceId } };\n                }\n                const constraints = { video: videoConstraints };\n                return yield this.decodeOnceFromConstraints(constraints, videoSource);\n            });\n        }\n        /**\n         * In one attempt, tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.\n         *\n         * @param constraints the media stream constraints to get s valid media stream to decode from\n         * @param video the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n         * @returns The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         */\n        decodeOnceFromConstraints(constraints, videoSource) {\n            return __awaiter(this, void 0, void 0, function* () {\n                const stream = yield navigator.mediaDevices.getUserMedia(constraints);\n                return yield this.decodeOnceFromStream(stream, videoSource);\n            });\n        }\n        /**\n         * In one attempt, tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.\n         *\n         * @param {MediaStream} [constraints] the media stream constraints to get s valid media stream to decode from\n         * @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n         * @returns {Promise<Result>} The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         */\n        decodeOnceFromStream(stream, videoSource) {\n            return __awaiter(this, void 0, void 0, function* () {\n                this.reset();\n                const video = yield this.attachStreamToVideo(stream, videoSource);\n                const result = yield this.decodeOnce(video);\n                return result;\n            });\n        }\n        /**\n         * Continuously decodes the barcode from the device specified by device while showing the video in the specified video element.\n         *\n         * @param {string|null} [deviceId] the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available.\n         * @param {string|HTMLVideoElement|null} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n         * @returns {Promise<void>}\n         *\n         * @memberOf BrowserCodeReader\n         *\n         * @deprecated Use `decodeFromVideoDevice` instead.\n         */\n        decodeFromInputVideoDeviceContinuously(deviceId, videoSource, callbackFn) {\n            return __awaiter(this, void 0, void 0, function* () {\n                return yield this.decodeFromVideoDevice(deviceId, videoSource, callbackFn);\n            });\n        }\n        /**\n         * Continuously tries to decode the barcode from the device specified by device while showing the video in the specified video element.\n         *\n         * @param {string|null} [deviceId] the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available.\n         * @param {string|HTMLVideoElement|null} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n         * @returns {Promise<void>}\n         *\n         * @memberOf BrowserCodeReader\n         */\n        decodeFromVideoDevice(deviceId, videoSource, callbackFn) {\n            return __awaiter(this, void 0, void 0, function* () {\n                let videoConstraints;\n                if (!deviceId) {\n                    videoConstraints = { facingMode: 'environment' };\n                }\n                else {\n                    videoConstraints = { deviceId: { exact: deviceId } };\n                }\n                const constraints = { video: videoConstraints };\n                return yield this.decodeFromConstraints(constraints, videoSource, callbackFn);\n            });\n        }\n        /**\n         * Continuously tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.\n         *\n         * @param {MediaStream} [constraints] the media stream constraints to get s valid media stream to decode from\n         * @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n         * @returns {Promise<Result>} The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         */\n        decodeFromConstraints(constraints, videoSource, callbackFn) {\n            return __awaiter(this, void 0, void 0, function* () {\n                const stream = yield navigator.mediaDevices.getUserMedia(constraints);\n                return yield this.decodeFromStream(stream, videoSource, callbackFn);\n            });\n        }\n        /**\n         * In one attempt, tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.\n         *\n         * @param {MediaStream} [constraints] the media stream constraints to get s valid media stream to decode from\n         * @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n         * @returns {Promise<Result>} The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         */\n        decodeFromStream(stream, videoSource, callbackFn) {\n            return __awaiter(this, void 0, void 0, function* () {\n                this.reset();\n                const video = yield this.attachStreamToVideo(stream, videoSource);\n                return yield this.decodeContinuously(video, callbackFn);\n            });\n        }\n        /**\n         * Breaks the decoding loop.\n         */\n        stopAsyncDecode() {\n            this._stopAsyncDecode = true;\n        }\n        /**\n         * Breaks the decoding loop.\n         */\n        stopContinuousDecode() {\n            this._stopContinuousDecode = true;\n        }\n        /**\n         * Sets the new stream and request a new decoding-with-delay.\n         *\n         * @param stream The stream to be shown in the video element.\n         * @param decodeFn A callback for the decode method.\n         */\n        attachStreamToVideo(stream, videoSource) {\n            return __awaiter(this, void 0, void 0, function* () {\n                const videoElement = this.prepareVideoElement(videoSource);\n                this.addVideoSource(videoElement, stream);\n                this.videoElement = videoElement;\n                this.stream = stream;\n                yield this.playVideoOnLoadAsync(videoElement);\n                return videoElement;\n            });\n        }\n        /**\n         *\n         * @param videoElement\n         */\n        playVideoOnLoadAsync(videoElement) {\n            return new Promise((resolve, reject) => this.playVideoOnLoad(videoElement, () => resolve()));\n        }\n        /**\n         * Binds listeners and callbacks to the videoElement.\n         *\n         * @param element\n         * @param callbackFn\n         */\n        playVideoOnLoad(element, callbackFn) {\n            this.videoEndedListener = () => this.stopStreams();\n            this.videoCanPlayListener = () => this.tryPlayVideo(element);\n            element.addEventListener('ended', this.videoEndedListener);\n            element.addEventListener('canplay', this.videoCanPlayListener);\n            element.addEventListener('playing', callbackFn);\n            // if canplay was already fired, we won't know when to play, so just give it a try\n            this.tryPlayVideo(element);\n        }\n        /**\n         * Checks if the given video element is currently playing.\n         */\n        isVideoPlaying(video) {\n            return video.currentTime > 0 && !video.paused && !video.ended && video.readyState > 2;\n        }\n        /**\n         * Just tries to play the video and logs any errors.\n         * The play call is only made is the video is not already playing.\n         */\n        tryPlayVideo(videoElement) {\n            return __awaiter(this, void 0, void 0, function* () {\n                if (this.isVideoPlaying(videoElement)) {\n                    console.warn('Trying to play video that is already playing.');\n                    return;\n                }\n                try {\n                    yield videoElement.play();\n                }\n                catch (_a) {\n                    console.warn('It was not possible to play the video.');\n                }\n            });\n        }\n        /**\n         * Searches and validates a media element.\n         */\n        getMediaElement(mediaElementId, type) {\n            const mediaElement = document.getElementById(mediaElementId);\n            if (!mediaElement) {\n                throw new ArgumentException(`element with id '${mediaElementId}' not found`);\n            }\n            if (mediaElement.nodeName.toLowerCase() !== type.toLowerCase()) {\n                throw new ArgumentException(`element with id '${mediaElementId}' must be an ${type} element`);\n            }\n            return mediaElement;\n        }\n        /**\n         * Decodes the barcode from an image.\n         *\n         * @param {(string|HTMLImageElement)} [source] The image element that can be either an element id or the element itself. Can be undefined in which case the decoding will be done from the imageUrl parameter.\n         * @param {string} [url]\n         * @returns {Promise<Result>} The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         */\n        decodeFromImage(source, url) {\n            if (!source && !url) {\n                throw new ArgumentException('either imageElement with a src set or an url must be provided');\n            }\n            if (url && !source) {\n                return this.decodeFromImageUrl(url);\n            }\n            return this.decodeFromImageElement(source);\n        }\n        /**\n         * Decodes the barcode from a video.\n         *\n         * @param {(string|HTMLImageElement)} [source] The image element that can be either an element id or the element itself. Can be undefined in which case the decoding will be done from the imageUrl parameter.\n         * @param {string} [url]\n         * @returns {Promise<Result>} The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         */\n        decodeFromVideo(source, url) {\n            if (!source && !url) {\n                throw new ArgumentException('Either an element with a src set or an URL must be provided');\n            }\n            if (url && !source) {\n                return this.decodeFromVideoUrl(url);\n            }\n            return this.decodeFromVideoElement(source);\n        }\n        /**\n         * Decodes continuously the barcode from a video.\n         *\n         * @param {(string|HTMLImageElement)} [source] The image element that can be either an element id or the element itself. Can be undefined in which case the decoding will be done from the imageUrl parameter.\n         * @param {string} [url]\n         * @returns {Promise<Result>} The decoding result.\n         *\n         * @memberOf BrowserCodeReader\n         *\n         * @experimental\n         */\n        decodeFromVideoContinuously(source, url, callbackFn) {\n            if (undefined === source && undefined === url) {\n                throw new ArgumentException('Either an element with a src set or an URL must be provided');\n            }\n            if (url && !source) {\n                return this.decodeFromVideoUrlContinuously(url, callbackFn);\n            }\n            return this.decodeFromVideoElementContinuously(source, callbackFn);\n        }\n        /**\n         * Decodes something from an image HTML element.\n         */\n        decodeFromImageElement(source) {\n            if (!source) {\n                throw new ArgumentException('An image element must be provided.');\n            }\n            this.reset();\n            const element = this.prepareImageElement(source);\n            this.imageElement = element;\n            let task;\n            if (this.isImageLoaded(element)) {\n                task = this.decodeOnce(element, false, true);\n            }\n            else {\n                task = this._decodeOnLoadImage(element);\n            }\n            return task;\n        }\n        /**\n         * Decodes something from an image HTML element.\n         */\n        decodeFromVideoElement(source) {\n            const element = this._decodeFromVideoElementSetup(source);\n            return this._decodeOnLoadVideo(element);\n        }\n        /**\n         * Decodes something from an image HTML element.\n         */\n        decodeFromVideoElementContinuously(source, callbackFn) {\n            const element = this._decodeFromVideoElementSetup(source);\n            return this._decodeOnLoadVideoContinuously(element, callbackFn);\n        }\n        /**\n         * Sets up the video source so it can be decoded when loaded.\n         *\n         * @param source The video source element.\n         */\n        _decodeFromVideoElementSetup(source) {\n            if (!source) {\n                throw new ArgumentException('A video element must be provided.');\n            }\n            this.reset();\n            const element = this.prepareVideoElement(source);\n            // defines the video element before starts decoding\n            this.videoElement = element;\n            return element;\n        }\n        /**\n         * Decodes an image from a URL.\n         */\n        decodeFromImageUrl(url) {\n            if (!url) {\n                throw new ArgumentException('An URL must be provided.');\n            }\n            this.reset();\n            const element = this.prepareImageElement();\n            this.imageElement = element;\n            const decodeTask = this._decodeOnLoadImage(element);\n            element.src = url;\n            return decodeTask;\n        }\n        /**\n         * Decodes an image from a URL.\n         */\n        decodeFromVideoUrl(url) {\n            if (!url) {\n                throw new ArgumentException('An URL must be provided.');\n            }\n            this.reset();\n            // creates a new element\n            const element = this.prepareVideoElement();\n            const decodeTask = this.decodeFromVideoElement(element);\n            element.src = url;\n            return decodeTask;\n        }\n        /**\n         * Decodes an image from a URL.\n         *\n         * @experimental\n         */\n        decodeFromVideoUrlContinuously(url, callbackFn) {\n            if (!url) {\n                throw new ArgumentException('An URL must be provided.');\n            }\n            this.reset();\n            // creates a new element\n            const element = this.prepareVideoElement();\n            const decodeTask = this.decodeFromVideoElementContinuously(element, callbackFn);\n            element.src = url;\n            return decodeTask;\n        }\n        _decodeOnLoadImage(element) {\n            return new Promise((resolve, reject) => {\n                this.imageLoadedListener = () => this.decodeOnce(element, false, true).then(resolve, reject);\n                element.addEventListener('load', this.imageLoadedListener);\n            });\n        }\n        _decodeOnLoadVideo(videoElement) {\n            return __awaiter(this, void 0, void 0, function* () {\n                // plays the video\n                yield this.playVideoOnLoadAsync(videoElement);\n                // starts decoding after played the video\n                return yield this.decodeOnce(videoElement);\n            });\n        }\n        _decodeOnLoadVideoContinuously(videoElement, callbackFn) {\n            return __awaiter(this, void 0, void 0, function* () {\n                // plays the video\n                yield this.playVideoOnLoadAsync(videoElement);\n                // starts decoding after played the video\n                this.decodeContinuously(videoElement, callbackFn);\n            });\n        }\n        isImageLoaded(img) {\n            // During the onload event, IE correctly identifies any images that\n            // weren’t downloaded as not complete. Others should too. Gecko-based\n            // browsers act like NS4 in that they report this incorrectly.\n            if (!img.complete) {\n                return false;\n            }\n            // However, they do have two very useful properties: naturalWidth and\n            // naturalHeight. These give the true size of the image. If it failed\n            // to load, either of these should be zero.\n            if (img.naturalWidth === 0) {\n                return false;\n            }\n            // No other way of checking: assume it’s ok.\n            return true;\n        }\n        prepareImageElement(imageSource) {\n            let imageElement;\n            if (typeof imageSource === 'undefined') {\n                imageElement = document.createElement('img');\n                imageElement.width = 200;\n                imageElement.height = 200;\n            }\n            if (typeof imageSource === 'string') {\n                imageElement = this.getMediaElement(imageSource, 'img');\n            }\n            if (imageSource instanceof HTMLImageElement) {\n                imageElement = imageSource;\n            }\n            return imageElement;\n        }\n        /**\n         * Sets a HTMLVideoElement for scanning or creates a new one.\n         *\n         * @param videoSource The HTMLVideoElement to be set.\n         */\n        prepareVideoElement(videoSource) {\n            let videoElement;\n            if (!videoSource && typeof document !== 'undefined') {\n                videoElement = document.createElement('video');\n                videoElement.width = 200;\n                videoElement.height = 200;\n            }\n            if (typeof videoSource === 'string') {\n                videoElement = this.getMediaElement(videoSource, 'video');\n            }\n            if (videoSource instanceof HTMLVideoElement) {\n                videoElement = videoSource;\n            }\n            // Needed for iOS 11\n            videoElement.setAttribute('autoplay', 'true');\n            videoElement.setAttribute('muted', 'true');\n            videoElement.setAttribute('playsinline', 'true');\n            return videoElement;\n        }\n        /**\n         * Tries to decode from the video input until it finds some value.\n         */\n        decodeOnce(element, retryIfNotFound = true, retryIfChecksumOrFormatError = true) {\n            this._stopAsyncDecode = false;\n            const loop = (resolve, reject) => {\n                if (this._stopAsyncDecode) {\n                    reject(new NotFoundException('Video stream has ended before any code could be detected.'));\n                    this._stopAsyncDecode = undefined;\n                    return;\n                }\n                try {\n                    const result = this.decode(element);\n                    resolve(result);\n                }\n                catch (e) {\n                    const ifNotFound = retryIfNotFound && e instanceof NotFoundException;\n                    const isChecksumOrFormatError = e instanceof ChecksumException || e instanceof FormatException;\n                    const ifChecksumOrFormat = isChecksumOrFormatError && retryIfChecksumOrFormatError;\n                    if (ifNotFound || ifChecksumOrFormat) {\n                        // trying again\n                        return setTimeout(loop, this._timeBetweenDecodingAttempts, resolve, reject);\n                    }\n                    reject(e);\n                }\n            };\n            return new Promise((resolve, reject) => loop(resolve, reject));\n        }\n        /**\n         * Continuously decodes from video input.\n         */\n        decodeContinuously(element, callbackFn) {\n            this._stopContinuousDecode = false;\n            const loop = () => {\n                if (this._stopContinuousDecode) {\n                    this._stopContinuousDecode = undefined;\n                    return;\n                }\n                try {\n                    const result = this.decode(element);\n                    callbackFn(result, null);\n                    setTimeout(loop, this.timeBetweenScansMillis);\n                }\n                catch (e) {\n                    callbackFn(null, e);\n                    const isChecksumOrFormatError = e instanceof ChecksumException || e instanceof FormatException;\n                    const isNotFound = e instanceof NotFoundException;\n                    if (isChecksumOrFormatError || isNotFound) {\n                        // trying again\n                        setTimeout(loop, this._timeBetweenDecodingAttempts);\n                    }\n                }\n            };\n            loop();\n        }\n        /**\n         * Gets the BinaryBitmap for ya! (and decodes it)\n         */\n        decode(element) {\n            // get binary bitmap for decode function\n            const binaryBitmap = this.createBinaryBitmap(element);\n            return this.decodeBitmap(binaryBitmap);\n        }\n        /**\n         * Returns true if media element is indeed a {@link HtmlVideoElement}.\n         */\n        _isHTMLVideoElement(mediaElement) {\n            const potentialVideo = mediaElement;\n            return potentialVideo.videoWidth !== 0;\n        }\n        /**\n         * Overwriting this allows you to manipulate the next frame in anyway\n         * you want before decode.\n         */\n        drawFrameOnCanvas(\n            srcElement, dimensions, canvasElementContext) {\n            if (!dimensions) {\n                dimensions = {\n                    sx: 0,\n                    sy: 0,\n                    sWidth: srcElement.videoWidth,\n                    sHeight: srcElement.videoHeight,\n                    dx: 0,\n                    dy: 0,\n                    dWidth: srcElement.videoWidth,\n                    dHeight: srcElement.videoHeight};\n            }\n            if (!canvasElementContext) {\n                canvasElementContext = this.captureCanvasContext;\n            }\n            canvasElementContext.drawImage(\n                srcElement,\n                dimensions.sx,\n                dimensions.sy,\n                dimensions.sWidth,\n                dimensions.sHeight,\n                dimensions.dx,\n                dimensions.dy,\n                dimensions.dWidth,\n                dimensions.dHeight);\n        }\n        /**\n         * Ovewriting this allows you to manipulate the snapshot image in anyway\n         *  you want before decode.\n         */\n        drawImageOnCanvas(\n            srcElement,\n            dimensions,\n            canvasElementContext = this.captureCanvasContext) {\n            if (!dimensions) {\n                dimensions = {\n                    sx: 0,\n                    sy: 0,\n                    sWidth: srcElement.naturalWidth,\n                    sHeight: srcElement.naturalHeight,\n                    dx: 0,\n                    dy: 0,\n                    dWidth: srcElement.naturalWidth,\n                    dHeight: srcElement.naturalHeight\n                };\n            }\n            if (!canvasElementContext) {\n                canvasElementContext = this.captureCanvasContext;\n            }\n            canvasElementContext.drawImage(\n                srcElement,\n                dimensions.sx,\n                dimensions.sy,\n                dimensions.sWidth,\n                dimensions.sHeight,\n                dimensions.dx,\n                dimensions.dy,\n                dimensions.dWidth,\n                dimensions.dHeight);\n        }\n        /**\n         * Creates a binaryBitmap based in some image source.\n         *\n         * @param mediaElement HTML element containing drawable image source.\n         */\n        createBinaryBitmap(mediaElement) {\n            const ctx = this.getCaptureCanvasContext(mediaElement);\n            if (this._isHTMLVideoElement(mediaElement)) {\n                this.drawFrameOnCanvas(mediaElement);\n            } else {\n                this.drawImageOnCanvas(mediaElement);\n            }\n            const canvas = this.getCaptureCanvas(mediaElement);\n            const luminanceSource = new HTMLCanvasElementLuminanceSource(canvas);\n            const hybridBinarizer = new HybridBinarizer(luminanceSource);\n\n            return new BinaryBitmap(hybridBinarizer);\n        }\n\n        getCaptureCanvasContext(mediaElement) {\n            if (!this.captureCanvasContext) {\n                const elem = this.getCaptureCanvas(mediaElement);\n                const ctx = elem.getContext('2d');\n                this.captureCanvasContext = ctx;\n            }\n            return this.captureCanvasContext;\n        }\n        getCaptureCanvas(mediaElement) {\n            if (!this.captureCanvas) {\n                const elem = this.createCaptureCanvas(mediaElement);\n                this.captureCanvas = elem;\n            }\n            return this.captureCanvas;\n        }\n        /**\n         * Call the encapsulated readers decode\n         */\n        decodeBitmap(binaryBitmap) {\n            return this.reader.decode(binaryBitmap, this._hints);\n        }\n        /**\n         * 🖌 Prepares the canvas for capture and scan frames.\n         */\n        createCaptureCanvas(mediaElement) {\n            if (typeof document === 'undefined') {\n                this._destroyCaptureCanvas();\n                return null;\n            }\n            const canvasElement = document.createElement('canvas');\n            let width;\n            let height;\n            if (typeof mediaElement !== 'undefined') {\n                if (mediaElement instanceof HTMLVideoElement) {\n                    width = mediaElement.videoWidth;\n                    height = mediaElement.videoHeight;\n                }\n                else if (mediaElement instanceof HTMLImageElement) {\n                    width = mediaElement.naturalWidth || mediaElement.width;\n                    height = mediaElement.naturalHeight || mediaElement.height;\n                }\n            }\n            canvasElement.style.width = width + 'px';\n            canvasElement.style.height = height + 'px';\n            canvasElement.width = width;\n            canvasElement.height = height;\n            return canvasElement;\n        }\n        /**\n         * Stops the continuous scan and cleans the stream.\n         */\n        stopStreams() {\n            if (this.stream) {\n                this.stream.getVideoTracks().forEach(t => t.stop());\n                this.stream = undefined;\n            }\n            if (this._stopAsyncDecode === false) {\n                this.stopAsyncDecode();\n            }\n            if (this._stopContinuousDecode === false) {\n                this.stopContinuousDecode();\n            }\n        }\n        /**\n         * Resets the code reader to the initial state. Cancels any ongoing barcode scanning from video or camera.\n         *\n         * @memberOf BrowserCodeReader\n         */\n        reset() {\n            // stops the camera, preview and scan 🔴\n            this.stopStreams();\n            // clean and forget about HTML elements\n            this._destroyVideoElement();\n            this._destroyImageElement();\n            this._destroyCaptureCanvas();\n        }\n        _destroyVideoElement() {\n            if (!this.videoElement) {\n                return;\n            }\n            // first gives freedon to the element 🕊\n            if (typeof this.videoEndedListener !== 'undefined') {\n                this.videoElement.removeEventListener('ended', this.videoEndedListener);\n            }\n            if (typeof this.videoPlayingEventListener !== 'undefined') {\n                this.videoElement.removeEventListener('playing', this.videoPlayingEventListener);\n            }\n            if (typeof this.videoCanPlayListener !== 'undefined') {\n                this.videoElement.removeEventListener('loadedmetadata', this.videoCanPlayListener);\n            }\n            // then forgets about that element 😢\n            this.cleanVideoSource(this.videoElement);\n            this.videoElement = undefined;\n        }\n        _destroyImageElement() {\n            if (!this.imageElement) {\n                return;\n            }\n            // first gives freedon to the element 🕊\n            if (undefined !== this.imageLoadedListener) {\n                this.imageElement.removeEventListener('load', this.imageLoadedListener);\n            }\n            // then forget about that element 😢\n            this.imageElement.src = undefined;\n            this.imageElement.removeAttribute('src');\n            this.imageElement = undefined;\n        }\n        /**\n         * Cleans canvas references 🖌\n         */\n        _destroyCaptureCanvas() {\n            // then forget about that element 😢\n            this.captureCanvasContext = undefined;\n            this.captureCanvas = undefined;\n        }\n        /**\n         * Defines what the videoElement src will be.\n         *\n         * @param videoElement\n         * @param stream\n         */\n        addVideoSource(videoElement, stream) {\n            // Older browsers may not have `srcObject`\n            try {\n                // @note Throws Exception if interrupted by a new loaded request\n                videoElement.srcObject = stream;\n            }\n            catch (err) {\n                // @note Avoid using this in new browsers, as it is going away.\n                videoElement.src = URL.createObjectURL(stream);\n            }\n        }\n        /**\n         * Unbinds a HTML video src property.\n         *\n         * @param videoElement\n         */\n        cleanVideoSource(videoElement) {\n            try {\n                videoElement.srcObject = null;\n            }\n            catch (err) {\n                videoElement.src = '';\n            }\n            this.videoElement.removeAttribute('src');\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates the result of decoding a barcode within an image.</p>\n     *\n     * @author Sean Owen\n     */\n    class Result {\n        // public constructor(private text: string,\n        //               Uint8Array rawBytes,\n        //               ResultPoconst resultPoints: Int32Array,\n        //               BarcodeFormat format) {\n        //   this(text, rawBytes, resultPoints, format, System.currentTimeMillis())\n        // }\n        // public constructor(text: string,\n        //               Uint8Array rawBytes,\n        //               ResultPoconst resultPoints: Int32Array,\n        //               BarcodeFormat format,\n        //               long timestamp) {\n        //   this(text, rawBytes, rawBytes == null ? 0 : 8 * rawBytes.length,\n        //        resultPoints, format, timestamp)\n        // }\n        constructor(text, rawBytes, numBits = rawBytes == null ? 0 : 8 * rawBytes.length, resultPoints, format, timestamp = System.currentTimeMillis()) {\n            this.text = text;\n            this.rawBytes = rawBytes;\n            this.numBits = numBits;\n            this.resultPoints = resultPoints;\n            this.format = format;\n            this.timestamp = timestamp;\n            this.text = text;\n            this.rawBytes = rawBytes;\n            if (undefined === numBits || null === numBits) {\n                this.numBits = (rawBytes === null || rawBytes === undefined) ? 0 : 8 * rawBytes.length;\n            }\n            else {\n                this.numBits = numBits;\n            }\n            this.resultPoints = resultPoints;\n            this.format = format;\n            this.resultMetadata = null;\n            if (undefined === timestamp || null === timestamp) {\n                this.timestamp = System.currentTimeMillis();\n            }\n            else {\n                this.timestamp = timestamp;\n            }\n        }\n        /**\n         * @return raw text encoded by the barcode\n         */\n        getText() {\n            return this.text;\n        }\n        /**\n         * @return raw bytes encoded by the barcode, if applicable, otherwise {@code null}\n         */\n        getRawBytes() {\n            return this.rawBytes;\n        }\n        /**\n         * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length\n         * @since 3.3.0\n         */\n        getNumBits() {\n            return this.numBits;\n        }\n        /**\n         * @return points related to the barcode in the image. These are typically points\n         *         identifying finder patterns or the corners of the barcode. The exact meaning is\n         *         specific to the type of barcode that was decoded.\n         */\n        getResultPoints() {\n            return this.resultPoints;\n        }\n        /**\n         * @return {@link BarcodeFormat} representing the format of the barcode that was decoded\n         */\n        getBarcodeFormat() {\n            return this.format;\n        }\n        /**\n         * @return {@link Map} mapping {@link ResultMetadataType} keys to values. May be\n         *   {@code null}. This contains optional metadata about what was detected about the barcode,\n         *   like orientation.\n         */\n        getResultMetadata() {\n            return this.resultMetadata;\n        }\n        putMetadata(type, value) {\n            if (this.resultMetadata === null) {\n                this.resultMetadata = new Map();\n            }\n            this.resultMetadata.set(type, value);\n        }\n        putAllMetadata(metadata) {\n            if (metadata !== null) {\n                if (this.resultMetadata === null) {\n                    this.resultMetadata = metadata;\n                }\n                else {\n                    this.resultMetadata = new Map(metadata);\n                }\n            }\n        }\n        addResultPoints(newPoints) {\n            const oldPoints = this.resultPoints;\n            if (oldPoints === null) {\n                this.resultPoints = newPoints;\n            }\n            else if (newPoints !== null && newPoints.length > 0) {\n                const allPoints = new Array(oldPoints.length + newPoints.length);\n                System.arraycopy(oldPoints, 0, allPoints, 0, oldPoints.length);\n                System.arraycopy(newPoints, 0, allPoints, oldPoints.length, newPoints.length);\n                this.resultPoints = allPoints;\n            }\n        }\n        getTimestamp() {\n            return this.timestamp;\n        }\n        /*@Override*/\n        toString() {\n            return this.text;\n        }\n    }\n\n    /*\n     * Direct port to TypeScript of ZXing by Adrian Toșcă\n     */\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing {*/\n    /**\n     * Enumerates barcode formats known to this package. Please keep alphabetized.\n     *\n     * @author Sean Owen\n     */\n    var BarcodeFormat;\n    (function (BarcodeFormat) {\n        /** Aztec 2D barcode format. */\n        BarcodeFormat[BarcodeFormat[\"AZTEC\"] = 0] = \"AZTEC\";\n        /** CODABAR 1D format. */\n        BarcodeFormat[BarcodeFormat[\"CODABAR\"] = 1] = \"CODABAR\";\n        /** Code 39 1D format. */\n        BarcodeFormat[BarcodeFormat[\"CODE_39\"] = 2] = \"CODE_39\";\n        /** Code 93 1D format. */\n        BarcodeFormat[BarcodeFormat[\"CODE_93\"] = 3] = \"CODE_93\";\n        /** Code 128 1D format. */\n        BarcodeFormat[BarcodeFormat[\"CODE_128\"] = 4] = \"CODE_128\";\n        /** Data Matrix 2D barcode format. */\n        BarcodeFormat[BarcodeFormat[\"DATA_MATRIX\"] = 5] = \"DATA_MATRIX\";\n        /** EAN-8 1D format. */\n        BarcodeFormat[BarcodeFormat[\"EAN_8\"] = 6] = \"EAN_8\";\n        /** EAN-13 1D format. */\n        BarcodeFormat[BarcodeFormat[\"EAN_13\"] = 7] = \"EAN_13\";\n        /** ITF (Interleaved Two of Five) 1D format. */\n        BarcodeFormat[BarcodeFormat[\"ITF\"] = 8] = \"ITF\";\n        /** MaxiCode 2D barcode format. */\n        BarcodeFormat[BarcodeFormat[\"MAXICODE\"] = 9] = \"MAXICODE\";\n        /** PDF417 format. */\n        BarcodeFormat[BarcodeFormat[\"PDF_417\"] = 10] = \"PDF_417\";\n        /** QR Code 2D barcode format. */\n        BarcodeFormat[BarcodeFormat[\"QR_CODE\"] = 11] = \"QR_CODE\";\n        /** RSS 14 */\n        BarcodeFormat[BarcodeFormat[\"RSS_14\"] = 12] = \"RSS_14\";\n        /** RSS EXPANDED */\n        BarcodeFormat[BarcodeFormat[\"RSS_EXPANDED\"] = 13] = \"RSS_EXPANDED\";\n        /** UPC-A 1D format. */\n        BarcodeFormat[BarcodeFormat[\"UPC_A\"] = 14] = \"UPC_A\";\n        /** UPC-E 1D format. */\n        BarcodeFormat[BarcodeFormat[\"UPC_E\"] = 15] = \"UPC_E\";\n        /** UPC/EAN extension format. Not a stand-alone format. */\n        BarcodeFormat[BarcodeFormat[\"UPC_EAN_EXTENSION\"] = 16] = \"UPC_EAN_EXTENSION\";\n    })(BarcodeFormat || (BarcodeFormat = {}));\n    var BarcodeFormat$1 = BarcodeFormat;\n\n    /*namespace com.google.zxing {*/\n    /**\n     * Represents some type of metadata about the result of the decoding that the decoder\n     * wishes to communicate back to the caller.\n     *\n     * @author Sean Owen\n     */\n    var ResultMetadataType;\n    (function (ResultMetadataType) {\n        /**\n         * Unspecified, application-specific metadata. Maps to an unspecified {@link Object}.\n         */\n        ResultMetadataType[ResultMetadataType[\"OTHER\"] = 0] = \"OTHER\";\n        /**\n         * Denotes the likely approximate orientation of the barcode in the image. This value\n         * is given as degrees rotated clockwise from the normal, upright orientation.\n         * For example a 1D barcode which was found by reading top-to-bottom would be\n         * said to have orientation \"90\". This key maps to an {@link Integer} whose\n         * value is in the range [0,360).\n         */\n        ResultMetadataType[ResultMetadataType[\"ORIENTATION\"] = 1] = \"ORIENTATION\";\n        /**\n         * <p>2D barcode formats typically encode text, but allow for a sort of 'byte mode'\n         * which is sometimes used to encode binary data. While {@link Result} makes available\n         * the complete raw bytes in the barcode for these formats, it does not offer the bytes\n         * from the byte segments alone.</p>\n         *\n         * <p>This maps to a {@link java.util.List} of byte arrays corresponding to the\n         * raw bytes in the byte segments in the barcode, in order.</p>\n         */\n        ResultMetadataType[ResultMetadataType[\"BYTE_SEGMENTS\"] = 2] = \"BYTE_SEGMENTS\";\n        /**\n         * Error correction level used, if applicable. The value type depends on the\n         * format, but is typically a String.\n         */\n        ResultMetadataType[ResultMetadataType[\"ERROR_CORRECTION_LEVEL\"] = 3] = \"ERROR_CORRECTION_LEVEL\";\n        /**\n         * For some periodicals, indicates the issue number as an {@link Integer}.\n         */\n        ResultMetadataType[ResultMetadataType[\"ISSUE_NUMBER\"] = 4] = \"ISSUE_NUMBER\";\n        /**\n         * For some products, indicates the suggested retail price in the barcode as a\n         * formatted {@link String}.\n         */\n        ResultMetadataType[ResultMetadataType[\"SUGGESTED_PRICE\"] = 5] = \"SUGGESTED_PRICE\";\n        /**\n         * For some products, the possible country of manufacture as a {@link String} denoting the\n         * ISO country code. Some map to multiple possible countries, like \"US/CA\".\n         */\n        ResultMetadataType[ResultMetadataType[\"POSSIBLE_COUNTRY\"] = 6] = \"POSSIBLE_COUNTRY\";\n        /**\n         * For some products, the extension text\n         */\n        ResultMetadataType[ResultMetadataType[\"UPC_EAN_EXTENSION\"] = 7] = \"UPC_EAN_EXTENSION\";\n        /**\n         * PDF417-specific metadata\n         */\n        ResultMetadataType[ResultMetadataType[\"PDF417_EXTRA_METADATA\"] = 8] = \"PDF417_EXTRA_METADATA\";\n        /**\n         * If the code format supports structured append and the current scanned code is part of one then the\n         * sequence number is given with it.\n         */\n        ResultMetadataType[ResultMetadataType[\"STRUCTURED_APPEND_SEQUENCE\"] = 9] = \"STRUCTURED_APPEND_SEQUENCE\";\n        /**\n         * If the code format supports structured append and the current scanned code is part of one then the\n         * parity is given with it.\n         */\n        ResultMetadataType[ResultMetadataType[\"STRUCTURED_APPEND_PARITY\"] = 10] = \"STRUCTURED_APPEND_PARITY\";\n    })(ResultMetadataType || (ResultMetadataType = {}));\n    var ResultMetadataType$1 = ResultMetadataType;\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing.common {*/\n    /*import java.util.List;*/\n    /**\n     * <p>Encapsulates the result of decoding a matrix of bits. This typically\n     * applies to 2D barcode formats. For now it contains the raw bytes obtained,\n     * as well as a String interpretation of those bytes, if applicable.</p>\n     *\n     * @author Sean Owen\n     */\n    class DecoderResult {\n        // public constructor(rawBytes: Uint8Array,\n        //                      text: string,\n        //                      List<Uint8Array> byteSegments,\n        //                      String ecLevel) {\n        //   this(rawBytes, text, byteSegments, ecLevel, -1, -1)\n        // }\n        constructor(rawBytes, text, byteSegments, ecLevel, structuredAppendSequenceNumber = -1, structuredAppendParity = -1) {\n            this.rawBytes = rawBytes;\n            this.text = text;\n            this.byteSegments = byteSegments;\n            this.ecLevel = ecLevel;\n            this.structuredAppendSequenceNumber = structuredAppendSequenceNumber;\n            this.structuredAppendParity = structuredAppendParity;\n            this.numBits = (rawBytes === undefined || rawBytes === null) ? 0 : 8 * rawBytes.length;\n        }\n        /**\n         * @return raw bytes representing the result, or {@code null} if not applicable\n         */\n        getRawBytes() {\n            return this.rawBytes;\n        }\n        /**\n         * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length\n         * @since 3.3.0\n         */\n        getNumBits() {\n            return this.numBits;\n        }\n        /**\n         * @param numBits overrides the number of bits that are valid in {@link #getRawBytes()}\n         * @since 3.3.0\n         */\n        setNumBits(numBits /*int*/) {\n            this.numBits = numBits;\n        }\n        /**\n         * @return text representation of the result\n         */\n        getText() {\n            return this.text;\n        }\n        /**\n         * @return list of byte segments in the result, or {@code null} if not applicable\n         */\n        getByteSegments() {\n            return this.byteSegments;\n        }\n        /**\n         * @return name of error correction level used, or {@code null} if not applicable\n         */\n        getECLevel() {\n            return this.ecLevel;\n        }\n        /**\n         * @return number of errors corrected, or {@code null} if not applicable\n         */\n        getErrorsCorrected() {\n            return this.errorsCorrected;\n        }\n        setErrorsCorrected(errorsCorrected /*Integer*/) {\n            this.errorsCorrected = errorsCorrected;\n        }\n        /**\n         * @return number of erasures corrected, or {@code null} if not applicable\n         */\n        getErasures() {\n            return this.erasures;\n        }\n        setErasures(erasures /*Integer*/) {\n            this.erasures = erasures;\n        }\n        /**\n         * @return arbitrary additional metadata\n         */\n        getOther() {\n            return this.other;\n        }\n        setOther(other) {\n            this.other = other;\n        }\n        hasStructuredAppend() {\n            return this.structuredAppendParity >= 0 && this.structuredAppendSequenceNumber >= 0;\n        }\n        getStructuredAppendParity() {\n            return this.structuredAppendParity;\n        }\n        getStructuredAppendSequenceNumber() {\n            return this.structuredAppendSequenceNumber;\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>This class contains utility methods for performing mathematical operations over\n     * the Galois Fields. Operations use a given primitive polynomial in calculations.</p>\n     *\n     * <p>Throughout this package, elements of the GF are represented as an {@code int}\n     * for convenience and speed (but at the cost of memory).\n     * </p>\n     *\n     * @author Sean Owen\n     * @author David Olivier\n     */\n    class AbstractGenericGF {\n        /**\n         * @return 2 to the power of a in GF(size)\n         */\n        exp(a) {\n            return this.expTable[a];\n        }\n        /**\n         * @return base 2 log of a in GF(size)\n         */\n        log(a /*int*/) {\n            if (a === 0) {\n                throw new IllegalArgumentException();\n            }\n            return this.logTable[a];\n        }\n        /**\n         * Implements both addition and subtraction -- they are the same in GF(size).\n         *\n         * @return sum/difference of a and b\n         */\n        static addOrSubtract(a /*int*/, b /*int*/) {\n            return a ^ b;\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Represents a polynomial whose coefficients are elements of a GF.\n     * Instances of this class are immutable.</p>\n     *\n     * <p>Much credit is due to William Rucklidge since portions of this code are an indirect\n     * port of his C++ Reed-Solomon implementation.</p>\n     *\n     * @author Sean Owen\n     */\n    class GenericGFPoly {\n        /**\n         * @param field the {@link GenericGF} instance representing the field to use\n         * to perform computations\n         * @param coefficients coefficients as ints representing elements of GF(size), arranged\n         * from most significant (highest-power term) coefficient to least significant\n         * @throws IllegalArgumentException if argument is null or empty,\n         * or if leading coefficient is 0 and this is not a\n         * constant polynomial (that is, it is not the monomial \"0\")\n         */\n        constructor(field, coefficients) {\n            if (coefficients.length === 0) {\n                throw new IllegalArgumentException();\n            }\n            this.field = field;\n            const coefficientsLength = coefficients.length;\n            if (coefficientsLength > 1 && coefficients[0] === 0) {\n                // Leading term must be non-zero for anything except the constant polynomial \"0\"\n                let firstNonZero = 1;\n                while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) {\n                    firstNonZero++;\n                }\n                if (firstNonZero === coefficientsLength) {\n                    this.coefficients = Int32Array.from([0]);\n                }\n                else {\n                    this.coefficients = new Int32Array(coefficientsLength - firstNonZero);\n                    System.arraycopy(coefficients, firstNonZero, this.coefficients, 0, this.coefficients.length);\n                }\n            }\n            else {\n                this.coefficients = coefficients;\n            }\n        }\n        getCoefficients() {\n            return this.coefficients;\n        }\n        /**\n         * @return degree of this polynomial\n         */\n        getDegree() {\n            return this.coefficients.length - 1;\n        }\n        /**\n         * @return true iff this polynomial is the monomial \"0\"\n         */\n        isZero() {\n            return this.coefficients[0] === 0;\n        }\n        /**\n         * @return coefficient of x^degree term in this polynomial\n         */\n        getCoefficient(degree /*int*/) {\n            return this.coefficients[this.coefficients.length - 1 - degree];\n        }\n        /**\n         * @return evaluation of this polynomial at a given point\n         */\n        evaluateAt(a /*int*/) {\n            if (a === 0) {\n                // Just return the x^0 coefficient\n                return this.getCoefficient(0);\n            }\n            const coefficients = this.coefficients;\n            let result;\n            if (a === 1) {\n                // Just the sum of the coefficients\n                result = 0;\n                for (let i = 0, length = coefficients.length; i !== length; i++) {\n                    const coefficient = coefficients[i];\n                    result = AbstractGenericGF.addOrSubtract(result, coefficient);\n                }\n                return result;\n            }\n            result = coefficients[0];\n            const size = coefficients.length;\n            const field = this.field;\n            for (let i = 1; i < size; i++) {\n                result = AbstractGenericGF.addOrSubtract(field.multiply(a, result), coefficients[i]);\n            }\n            return result;\n        }\n        addOrSubtract(other) {\n            if (!this.field.equals(other.field)) {\n                throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field');\n            }\n            if (this.isZero()) {\n                return other;\n            }\n            if (other.isZero()) {\n                return this;\n            }\n            let smallerCoefficients = this.coefficients;\n            let largerCoefficients = other.coefficients;\n            if (smallerCoefficients.length > largerCoefficients.length) {\n                const temp = smallerCoefficients;\n                smallerCoefficients = largerCoefficients;\n                largerCoefficients = temp;\n            }\n            let sumDiff = new Int32Array(largerCoefficients.length);\n            const lengthDiff = largerCoefficients.length - smallerCoefficients.length;\n            // Copy high-order terms only found in higher-degree polynomial's coefficients\n            System.arraycopy(largerCoefficients, 0, sumDiff, 0, lengthDiff);\n            for (let i = lengthDiff; i < largerCoefficients.length; i++) {\n                sumDiff[i] = AbstractGenericGF.addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);\n            }\n            return new GenericGFPoly(this.field, sumDiff);\n        }\n        multiply(other) {\n            if (!this.field.equals(other.field)) {\n                throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field');\n            }\n            if (this.isZero() || other.isZero()) {\n                return this.field.getZero();\n            }\n            const aCoefficients = this.coefficients;\n            const aLength = aCoefficients.length;\n            const bCoefficients = other.coefficients;\n            const bLength = bCoefficients.length;\n            const product = new Int32Array(aLength + bLength - 1);\n            const field = this.field;\n            for (let i = 0; i < aLength; i++) {\n                const aCoeff = aCoefficients[i];\n                for (let j = 0; j < bLength; j++) {\n                    product[i + j] = AbstractGenericGF.addOrSubtract(product[i + j], field.multiply(aCoeff, bCoefficients[j]));\n                }\n            }\n            return new GenericGFPoly(field, product);\n        }\n        multiplyScalar(scalar /*int*/) {\n            if (scalar === 0) {\n                return this.field.getZero();\n            }\n            if (scalar === 1) {\n                return this;\n            }\n            const size = this.coefficients.length;\n            const field = this.field;\n            const product = new Int32Array(size);\n            const coefficients = this.coefficients;\n            for (let i = 0; i < size; i++) {\n                product[i] = field.multiply(coefficients[i], scalar);\n            }\n            return new GenericGFPoly(field, product);\n        }\n        multiplyByMonomial(degree /*int*/, coefficient /*int*/) {\n            if (degree < 0) {\n                throw new IllegalArgumentException();\n            }\n            if (coefficient === 0) {\n                return this.field.getZero();\n            }\n            const coefficients = this.coefficients;\n            const size = coefficients.length;\n            const product = new Int32Array(size + degree);\n            const field = this.field;\n            for (let i = 0; i < size; i++) {\n                product[i] = field.multiply(coefficients[i], coefficient);\n            }\n            return new GenericGFPoly(field, product);\n        }\n        divide(other) {\n            if (!this.field.equals(other.field)) {\n                throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field');\n            }\n            if (other.isZero()) {\n                throw new IllegalArgumentException('Divide by 0');\n            }\n            const field = this.field;\n            let quotient = field.getZero();\n            let remainder = this;\n            const denominatorLeadingTerm = other.getCoefficient(other.getDegree());\n            const inverseDenominatorLeadingTerm = field.inverse(denominatorLeadingTerm);\n            while (remainder.getDegree() >= other.getDegree() && !remainder.isZero()) {\n                const degreeDifference = remainder.getDegree() - other.getDegree();\n                const scale = field.multiply(remainder.getCoefficient(remainder.getDegree()), inverseDenominatorLeadingTerm);\n                const term = other.multiplyByMonomial(degreeDifference, scale);\n                const iterationQuotient = field.buildMonomial(degreeDifference, scale);\n                quotient = quotient.addOrSubtract(iterationQuotient);\n                remainder = remainder.addOrSubtract(term);\n            }\n            return [quotient, remainder];\n        }\n        /*@Override*/\n        toString() {\n            let result = '';\n            for (let degree = this.getDegree(); degree >= 0; degree--) {\n                let coefficient = this.getCoefficient(degree);\n                if (coefficient !== 0) {\n                    if (coefficient < 0) {\n                        result += ' - ';\n                        coefficient = -coefficient;\n                    }\n                    else {\n                        if (result.length > 0) {\n                            result += ' + ';\n                        }\n                    }\n                    if (degree === 0 || coefficient !== 1) {\n                        const alphaPower = this.field.log(coefficient);\n                        if (alphaPower === 0) {\n                            result += '1';\n                        }\n                        else if (alphaPower === 1) {\n                            result += 'a';\n                        }\n                        else {\n                            result += 'a^';\n                            result += alphaPower;\n                        }\n                    }\n                    if (degree !== 0) {\n                        if (degree === 1) {\n                            result += 'x';\n                        }\n                        else {\n                            result += 'x^';\n                            result += degree;\n                        }\n                    }\n                }\n            }\n            return result;\n        }\n    }\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class ArithmeticException extends Exception {\n    }\n    ArithmeticException.kind = 'ArithmeticException';\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>This class contains utility methods for performing mathematical operations over\n     * the Galois Fields. Operations use a given primitive polynomial in calculations.</p>\n     *\n     * <p>Throughout this package, elements of the GF are represented as an {@code int}\n     * for convenience and speed (but at the cost of memory).\n     * </p>\n     *\n     * @author Sean Owen\n     * @author David Olivier\n     */\n    class GenericGF extends AbstractGenericGF {\n        /**\n         * Create a representation of GF(size) using the given primitive polynomial.\n         *\n         * @param primitive irreducible polynomial whose coefficients are represented by\n         *  the bits of an int, where the least-significant bit represents the constant\n         *  coefficient\n         * @param size the size of the field\n         * @param b the factor b in the generator polynomial can be 0- or 1-based\n         *  (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))).\n         *  In most cases it should be 1, but for QR code it is 0.\n         */\n        constructor(primitive /*int*/, size /*int*/, generatorBase /*int*/) {\n            super();\n            this.primitive = primitive;\n            this.size = size;\n            this.generatorBase = generatorBase;\n            const expTable = new Int32Array(size);\n            let x = 1;\n            for (let i = 0; i < size; i++) {\n                expTable[i] = x;\n                x *= 2; // we're assuming the generator alpha is 2\n                if (x >= size) {\n                    x ^= primitive;\n                    x &= size - 1;\n                }\n            }\n            this.expTable = expTable;\n            const logTable = new Int32Array(size);\n            for (let i = 0; i < size - 1; i++) {\n                logTable[expTable[i]] = i;\n            }\n            this.logTable = logTable;\n            // logTable[0] == 0 but this should never be used\n            this.zero = new GenericGFPoly(this, Int32Array.from([0]));\n            this.one = new GenericGFPoly(this, Int32Array.from([1]));\n        }\n        getZero() {\n            return this.zero;\n        }\n        getOne() {\n            return this.one;\n        }\n        /**\n         * @return the monomial representing coefficient * x^degree\n         */\n        buildMonomial(degree /*int*/, coefficient /*int*/) {\n            if (degree < 0) {\n                throw new IllegalArgumentException();\n            }\n            if (coefficient === 0) {\n                return this.zero;\n            }\n            const coefficients = new Int32Array(degree + 1);\n            coefficients[0] = coefficient;\n            return new GenericGFPoly(this, coefficients);\n        }\n        /**\n         * @return multiplicative inverse of a\n         */\n        inverse(a /*int*/) {\n            if (a === 0) {\n                throw new ArithmeticException();\n            }\n            return this.expTable[this.size - this.logTable[a] - 1];\n        }\n        /**\n         * @return product of a and b in GF(size)\n         */\n        multiply(a /*int*/, b /*int*/) {\n            if (a === 0 || b === 0) {\n                return 0;\n            }\n            return this.expTable[(this.logTable[a] + this.logTable[b]) % (this.size - 1)];\n        }\n        getSize() {\n            return this.size;\n        }\n        getGeneratorBase() {\n            return this.generatorBase;\n        }\n        /*@Override*/\n        toString() {\n            return ('GF(0x' + Integer.toHexString(this.primitive) + ',' + this.size + ')');\n        }\n        equals(o) {\n            return o === this;\n        }\n    }\n    GenericGF.AZTEC_DATA_12 = new GenericGF(0x1069, 4096, 1); // x^12 + x^6 + x^5 + x^3 + 1\n    GenericGF.AZTEC_DATA_10 = new GenericGF(0x409, 1024, 1); // x^10 + x^3 + 1\n    GenericGF.AZTEC_DATA_6 = new GenericGF(0x43, 64, 1); // x^6 + x + 1\n    GenericGF.AZTEC_PARAM = new GenericGF(0x13, 16, 1); // x^4 + x + 1\n    GenericGF.QR_CODE_FIELD_256 = new GenericGF(0x011d, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1\n    GenericGF.DATA_MATRIX_FIELD_256 = new GenericGF(0x012d, 256, 1); // x^8 + x^5 + x^3 + x^2 + 1\n    GenericGF.AZTEC_DATA_8 = GenericGF.DATA_MATRIX_FIELD_256;\n    GenericGF.MAXICODE_FIELD_64 = GenericGF.AZTEC_DATA_6;\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class ReedSolomonException extends Exception {\n    }\n    ReedSolomonException.kind = 'ReedSolomonException';\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class IllegalStateException extends Exception {\n    }\n    IllegalStateException.kind = 'IllegalStateException';\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Implements Reed-Solomon decoding, as the name implies.</p>\n     *\n     * <p>The algorithm will not be explained here, but the following references were helpful\n     * in creating this implementation:</p>\n     *\n     * <ul>\n     * <li>Bruce Maggs.\n     * <a href=\"http://www.cs.cmu.edu/afs/cs.cmu.edu/project/pscico-guyb/realworld/www/rs_decode.ps\">\n     * \"Decoding Reed-Solomon Codes\"</a> (see discussion of Forney's Formula)</li>\n     * <li>J.I. Hall. <a href=\"www.mth.msu.edu/~jhall/classes/codenotes/GRS.pdf\">\n     * \"Chapter 5. Generalized Reed-Solomon Codes\"</a>\n     * (see discussion of Euclidean algorithm)</li>\n     * </ul>\n     *\n     * <p>Much credit is due to William Rucklidge since portions of this code are an indirect\n     * port of his C++ Reed-Solomon implementation.</p>\n     *\n     * @author Sean Owen\n     * @author William Rucklidge\n     * @author sanfordsquires\n     */\n    class ReedSolomonDecoder {\n        constructor(field) {\n            this.field = field;\n        }\n        /**\n         * <p>Decodes given set of received codewords, which include both data and error-correction\n         * codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place,\n         * in the input.</p>\n         *\n         * @param received data and error-correction codewords\n         * @param twoS number of error-correction codewords available\n         * @throws ReedSolomonException if decoding fails for any reason\n         */\n        decode(received, twoS /*int*/) {\n            const field = this.field;\n            const poly = new GenericGFPoly(field, received);\n            const syndromeCoefficients = new Int32Array(twoS);\n            let noError = true;\n            for (let i = 0; i < twoS; i++) {\n                const evalResult = poly.evaluateAt(field.exp(i + field.getGeneratorBase()));\n                syndromeCoefficients[syndromeCoefficients.length - 1 - i] = evalResult;\n                if (evalResult !== 0) {\n                    noError = false;\n                }\n            }\n            if (noError) {\n                return;\n            }\n            const syndrome = new GenericGFPoly(field, syndromeCoefficients);\n            const sigmaOmega = this.runEuclideanAlgorithm(field.buildMonomial(twoS, 1), syndrome, twoS);\n            const sigma = sigmaOmega[0];\n            const omega = sigmaOmega[1];\n            const errorLocations = this.findErrorLocations(sigma);\n            const errorMagnitudes = this.findErrorMagnitudes(omega, errorLocations);\n            for (let i = 0; i < errorLocations.length; i++) {\n                const position = received.length - 1 - field.log(errorLocations[i]);\n                if (position < 0) {\n                    throw new ReedSolomonException('Bad error location');\n                }\n                received[position] = GenericGF.addOrSubtract(received[position], errorMagnitudes[i]);\n            }\n        }\n        runEuclideanAlgorithm(a, b, R /*int*/) {\n            // Assume a's degree is >= b's\n            if (a.getDegree() < b.getDegree()) {\n                const temp = a;\n                a = b;\n                b = temp;\n            }\n            const field = this.field;\n            let rLast = a;\n            let r = b;\n            let tLast = field.getZero();\n            let t = field.getOne();\n            // Run Euclidean algorithm until r's degree is less than R/2\n            while (r.getDegree() >= (R / 2 | 0)) {\n                let rLastLast = rLast;\n                let tLastLast = tLast;\n                rLast = r;\n                tLast = t;\n                // Divide rLastLast by rLast, with quotient in q and remainder in r\n                if (rLast.isZero()) {\n                    // Oops, Euclidean algorithm already terminated?\n                    throw new ReedSolomonException('r_{i-1} was zero');\n                }\n                r = rLastLast;\n                let q = field.getZero();\n                const denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree());\n                const dltInverse = field.inverse(denominatorLeadingTerm);\n                while (r.getDegree() >= rLast.getDegree() && !r.isZero()) {\n                    const degreeDiff = r.getDegree() - rLast.getDegree();\n                    const scale = field.multiply(r.getCoefficient(r.getDegree()), dltInverse);\n                    q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale));\n                    r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale));\n                }\n                t = q.multiply(tLast).addOrSubtract(tLastLast);\n                if (r.getDegree() >= rLast.getDegree()) {\n                    throw new IllegalStateException('Division algorithm failed to reduce polynomial?');\n                }\n            }\n            const sigmaTildeAtZero = t.getCoefficient(0);\n            if (sigmaTildeAtZero === 0) {\n                throw new ReedSolomonException('sigmaTilde(0) was zero');\n            }\n            const inverse = field.inverse(sigmaTildeAtZero);\n            const sigma = t.multiplyScalar(inverse);\n            const omega = r.multiplyScalar(inverse);\n            return [sigma, omega];\n        }\n        findErrorLocations(errorLocator) {\n            // This is a direct application of Chien's search\n            const numErrors = errorLocator.getDegree();\n            if (numErrors === 1) { // shortcut\n                return Int32Array.from([errorLocator.getCoefficient(1)]);\n            }\n            const result = new Int32Array(numErrors);\n            let e = 0;\n            const field = this.field;\n            for (let i = 1; i < field.getSize() && e < numErrors; i++) {\n                if (errorLocator.evaluateAt(i) === 0) {\n                    result[e] = field.inverse(i);\n                    e++;\n                }\n            }\n            if (e !== numErrors) {\n                throw new ReedSolomonException('Error locator degree does not match number of roots');\n            }\n            return result;\n        }\n        findErrorMagnitudes(errorEvaluator, errorLocations) {\n            // This is directly applying Forney's Formula\n            const s = errorLocations.length;\n            const result = new Int32Array(s);\n            const field = this.field;\n            for (let i = 0; i < s; i++) {\n                const xiInverse = field.inverse(errorLocations[i]);\n                let denominator = 1;\n                for (let j = 0; j < s; j++) {\n                    if (i !== j) {\n                        // denominator = field.multiply(denominator,\n                        //    GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse)))\n                        // Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug.\n                        // Below is a funny-looking workaround from Steven Parkes\n                        const term = field.multiply(errorLocations[j], xiInverse);\n                        const termPlus1 = (term & 0x1) === 0 ? term | 1 : term & ~1;\n                        denominator = field.multiply(denominator, termPlus1);\n                    }\n                }\n                result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denominator));\n                if (field.getGeneratorBase() !== 0) {\n                    result[i] = field.multiply(result[i], xiInverse);\n                }\n            }\n            return result;\n        }\n    }\n\n    /*\n     * Copyright 2010 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    // import java.util.Arrays;\n    var Table;\n    (function (Table) {\n        Table[Table[\"UPPER\"] = 0] = \"UPPER\";\n        Table[Table[\"LOWER\"] = 1] = \"LOWER\";\n        Table[Table[\"MIXED\"] = 2] = \"MIXED\";\n        Table[Table[\"DIGIT\"] = 3] = \"DIGIT\";\n        Table[Table[\"PUNCT\"] = 4] = \"PUNCT\";\n        Table[Table[\"BINARY\"] = 5] = \"BINARY\";\n    })(Table || (Table = {}));\n    /**\n     * <p>The main class which implements Aztec Code decoding -- as opposed to locating and extracting\n     * the Aztec Code from an image.</p>\n     *\n     * @author David Olivier\n     */\n    class Decoder {\n        decode(detectorResult) {\n            this.ddata = detectorResult;\n            let matrix = detectorResult.getBits();\n            let rawbits = this.extractBits(matrix);\n            let correctedBits = this.correctBits(rawbits);\n            let rawBytes = Decoder.convertBoolArrayToByteArray(correctedBits);\n            let result = Decoder.getEncodedData(correctedBits);\n            let decoderResult = new DecoderResult(rawBytes, result, null, null);\n            decoderResult.setNumBits(correctedBits.length);\n            return decoderResult;\n        }\n        // This method is used for testing the high-level encoder\n        static highLevelDecode(correctedBits) {\n            return this.getEncodedData(correctedBits);\n        }\n        /**\n         * Gets the string encoded in the aztec code bits\n         *\n         * @return the decoded string\n         */\n        static getEncodedData(correctedBits) {\n            let endIndex = correctedBits.length;\n            let latchTable = Table.UPPER; // table most recently latched to\n            let shiftTable = Table.UPPER; // table to use for the next read\n            let result = '';\n            let index = 0;\n            while (index < endIndex) {\n                if (shiftTable === Table.BINARY) {\n                    if (endIndex - index < 5) {\n                        break;\n                    }\n                    let length = Decoder.readCode(correctedBits, index, 5);\n                    index += 5;\n                    if (length === 0) {\n                        if (endIndex - index < 11) {\n                            break;\n                        }\n                        length = Decoder.readCode(correctedBits, index, 11) + 31;\n                        index += 11;\n                    }\n                    for (let charCount = 0; charCount < length; charCount++) {\n                        if (endIndex - index < 8) {\n                            index = endIndex; // Force outer loop to exit\n                            break;\n                        }\n                        const code = Decoder.readCode(correctedBits, index, 8);\n                        result += /*(char)*/ StringUtils.castAsNonUtf8Char(code);\n                        index += 8;\n                    }\n                    // Go back to whatever mode we had been in\n                    shiftTable = latchTable;\n                }\n                else {\n                    let size = shiftTable === Table.DIGIT ? 4 : 5;\n                    if (endIndex - index < size) {\n                        break;\n                    }\n                    let code = Decoder.readCode(correctedBits, index, size);\n                    index += size;\n                    let str = Decoder.getCharacter(shiftTable, code);\n                    if (str.startsWith('CTRL_')) {\n                        // Table changes\n                        // ISO/IEC 24778:2008 prescribes ending a shift sequence in the mode from which it was invoked.\n                        // That's including when that mode is a shift.\n                        // Our test case dlusbs.png for issue #642 exercises that.\n                        latchTable = shiftTable; // Latch the current mode, so as to return to Upper after U/S B/S\n                        shiftTable = Decoder.getTable(str.charAt(5));\n                        if (str.charAt(6) === 'L') {\n                            latchTable = shiftTable;\n                        }\n                    }\n                    else {\n                        result += str;\n                        // Go back to whatever mode we had been in\n                        shiftTable = latchTable;\n                    }\n                }\n            }\n            return result;\n        }\n        /**\n         * gets the table corresponding to the char passed\n         */\n        static getTable(t) {\n            switch (t) {\n                case 'L':\n                    return Table.LOWER;\n                case 'P':\n                    return Table.PUNCT;\n                case 'M':\n                    return Table.MIXED;\n                case 'D':\n                    return Table.DIGIT;\n                case 'B':\n                    return Table.BINARY;\n                case 'U':\n                default:\n                    return Table.UPPER;\n            }\n        }\n        /**\n         * Gets the character (or string) corresponding to the passed code in the given table\n         *\n         * @param table the table used\n         * @param code the code of the character\n         */\n        static getCharacter(table, code) {\n            switch (table) {\n                case Table.UPPER:\n                    return Decoder.UPPER_TABLE[code];\n                case Table.LOWER:\n                    return Decoder.LOWER_TABLE[code];\n                case Table.MIXED:\n                    return Decoder.MIXED_TABLE[code];\n                case Table.PUNCT:\n                    return Decoder.PUNCT_TABLE[code];\n                case Table.DIGIT:\n                    return Decoder.DIGIT_TABLE[code];\n                default:\n                    // Should not reach here.\n                    throw new IllegalStateException('Bad table');\n            }\n        }\n        /**\n         * <p>Performs RS error correction on an array of bits.</p>\n         *\n         * @return the corrected array\n         * @throws FormatException if the input contains too many errors\n         */\n        correctBits(rawbits) {\n            let gf;\n            let codewordSize;\n            if (this.ddata.getNbLayers() <= 2) {\n                codewordSize = 6;\n                gf = GenericGF.AZTEC_DATA_6;\n            }\n            else if (this.ddata.getNbLayers() <= 8) {\n                codewordSize = 8;\n                gf = GenericGF.AZTEC_DATA_8;\n            }\n            else if (this.ddata.getNbLayers() <= 22) {\n                codewordSize = 10;\n                gf = GenericGF.AZTEC_DATA_10;\n            }\n            else {\n                codewordSize = 12;\n                gf = GenericGF.AZTEC_DATA_12;\n            }\n            let numDataCodewords = this.ddata.getNbDatablocks();\n            let numCodewords = rawbits.length / codewordSize;\n            if (numCodewords < numDataCodewords) {\n                throw new FormatException();\n            }\n            let offset = rawbits.length % codewordSize;\n            let dataWords = new Int32Array(numCodewords);\n            for (let i = 0; i < numCodewords; i++, offset += codewordSize) {\n                dataWords[i] = Decoder.readCode(rawbits, offset, codewordSize);\n            }\n            try {\n                let rsDecoder = new ReedSolomonDecoder(gf);\n                rsDecoder.decode(dataWords, numCodewords - numDataCodewords);\n            }\n            catch (ex) {\n                throw new FormatException(ex);\n            }\n            // Now perform the unstuffing operation.\n            // First, count how many bits are going to be thrown out as stuffing\n            let mask = (1 << codewordSize) - 1;\n            let stuffedBits = 0;\n            for (let i = 0; i < numDataCodewords; i++) {\n                let dataWord = dataWords[i];\n                if (dataWord === 0 || dataWord === mask) {\n                    throw new FormatException();\n                }\n                else if (dataWord === 1 || dataWord === mask - 1) {\n                    stuffedBits++;\n                }\n            }\n            // Now, actually unpack the bits and remove the stuffing\n            let correctedBits = new Array(numDataCodewords * codewordSize - stuffedBits);\n            let index = 0;\n            for (let i = 0; i < numDataCodewords; i++) {\n                let dataWord = dataWords[i];\n                if (dataWord === 1 || dataWord === mask - 1) {\n                    // next codewordSize-1 bits are all zeros or all ones\n                    correctedBits.fill(dataWord > 1, index, index + codewordSize - 1);\n                    // Arrays.fill(correctedBits, index, index + codewordSize - 1, dataWord > 1);\n                    index += codewordSize - 1;\n                }\n                else {\n                    for (let bit = codewordSize - 1; bit >= 0; --bit) {\n                        correctedBits[index++] = (dataWord & (1 << bit)) !== 0;\n                    }\n                }\n            }\n            return correctedBits;\n        }\n        /**\n         * Gets the array of bits from an Aztec Code matrix\n         *\n         * @return the array of bits\n         */\n        extractBits(matrix) {\n            let compact = this.ddata.isCompact();\n            let layers = this.ddata.getNbLayers();\n            let baseMatrixSize = (compact ? 11 : 14) + layers * 4; // not including alignment lines\n            let alignmentMap = new Int32Array(baseMatrixSize);\n            let rawbits = new Array(this.totalBitsInLayer(layers, compact));\n            if (compact) {\n                for (let i = 0; i < alignmentMap.length; i++) {\n                    alignmentMap[i] = i;\n                }\n            }\n            else {\n                let matrixSize = baseMatrixSize + 1 + 2 * Integer.truncDivision((Integer.truncDivision(baseMatrixSize, 2) - 1), 15);\n                let origCenter = baseMatrixSize / 2;\n                let center = Integer.truncDivision(matrixSize, 2);\n                for (let i = 0; i < origCenter; i++) {\n                    let newOffset = i + Integer.truncDivision(i, 15);\n                    alignmentMap[origCenter - i - 1] = center - newOffset - 1;\n                    alignmentMap[origCenter + i] = center + newOffset + 1;\n                }\n            }\n            for (let i = 0, rowOffset = 0; i < layers; i++) {\n                let rowSize = (layers - i) * 4 + (compact ? 9 : 12);\n                // The top-left most point of this layer is <low, low> (not including alignment lines)\n                let low = i * 2;\n                // The bottom-right most point of this layer is <high, high> (not including alignment lines)\n                let high = baseMatrixSize - 1 - low;\n                // We pull bits from the two 2 x rowSize columns and two rowSize x 2 rows\n                for (let j = 0; j < rowSize; j++) {\n                    let columnOffset = j * 2;\n                    for (let k = 0; k < 2; k++) {\n                        // left column\n                        rawbits[rowOffset + columnOffset + k] =\n                            matrix.get(alignmentMap[low + k], alignmentMap[low + j]);\n                        // bottom row\n                        rawbits[rowOffset + 2 * rowSize + columnOffset + k] =\n                            matrix.get(alignmentMap[low + j], alignmentMap[high - k]);\n                        // right column\n                        rawbits[rowOffset + 4 * rowSize + columnOffset + k] =\n                            matrix.get(alignmentMap[high - k], alignmentMap[high - j]);\n                        // top row\n                        rawbits[rowOffset + 6 * rowSize + columnOffset + k] =\n                            matrix.get(alignmentMap[high - j], alignmentMap[low + k]);\n                    }\n                }\n                rowOffset += rowSize * 8;\n            }\n            return rawbits;\n        }\n        /**\n         * Reads a code of given length and at given index in an array of bits\n         */\n        static readCode(rawbits, startIndex, length) {\n            let res = 0;\n            for (let i = startIndex; i < startIndex + length; i++) {\n                res <<= 1;\n                if (rawbits[i]) {\n                    res |= 0x01;\n                }\n            }\n            return res;\n        }\n        /**\n         * Reads a code of length 8 in an array of bits, padding with zeros\n         */\n        static readByte(rawbits, startIndex) {\n            let n = rawbits.length - startIndex;\n            if (n >= 8) {\n                return Decoder.readCode(rawbits, startIndex, 8);\n            }\n            return Decoder.readCode(rawbits, startIndex, n) << (8 - n);\n        }\n        /**\n         * Packs a bit array into bytes, most significant bit first\n         */\n        static convertBoolArrayToByteArray(boolArr) {\n            let byteArr = new Uint8Array((boolArr.length + 7) / 8);\n            for (let i = 0; i < byteArr.length; i++) {\n                byteArr[i] = Decoder.readByte(boolArr, 8 * i);\n            }\n            return byteArr;\n        }\n        totalBitsInLayer(layers, compact) {\n            return ((compact ? 88 : 112) + 16 * layers) * layers;\n        }\n    }\n    Decoder.UPPER_TABLE = [\n        'CTRL_PS', ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',\n        'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'CTRL_LL', 'CTRL_ML', 'CTRL_DL', 'CTRL_BS'\n    ];\n    Decoder.LOWER_TABLE = [\n        'CTRL_PS', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',\n        'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'CTRL_US', 'CTRL_ML', 'CTRL_DL', 'CTRL_BS'\n    ];\n    Decoder.MIXED_TABLE = [\n        // Module parse failed: Octal literal in strict mode (50:29)\n        // so number string were scaped\n        'CTRL_PS', ' ', '\\\\1', '\\\\2', '\\\\3', '\\\\4', '\\\\5', '\\\\6', '\\\\7', '\\b', '\\t', '\\n',\n        '\\\\13', '\\f', '\\r', '\\\\33', '\\\\34', '\\\\35', '\\\\36', '\\\\37', '@', '\\\\', '^', '_',\n        '`', '|', '~', '\\\\177', 'CTRL_LL', 'CTRL_UL', 'CTRL_PL', 'CTRL_BS'\n    ];\n    Decoder.PUNCT_TABLE = [\n        '', '\\r', '\\r\\n', '. ', ', ', ': ', '!', '\"', '#', '$', '%', '&', '\\'', '(', ')',\n        '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', ']', '{', '}', 'CTRL_UL'\n    ];\n    Decoder.DIGIT_TABLE = [\n        'CTRL_PS', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ',', '.', 'CTRL_UL', 'CTRL_US'\n    ];\n\n    /*\n     * Copyright 2012 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing.common.detector {*/\n    /**\n     * General math-related and numeric utility functions.\n     */\n    class MathUtils {\n        constructor() { }\n        /**\n         * Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its\n         * argument to the nearest int, where x.5 rounds up to x+1. Semantics of this shortcut\n         * differ slightly from {@link Math#round(float)} in that half rounds down for negative\n         * values. -2.5 rounds to -3, not -2. For purposes here it makes no difference.\n         *\n         * @param d real value to round\n         * @return nearest {@code int}\n         */\n        static round(d /*float*/) {\n            if (NaN === d)\n                return 0;\n            if (d <= Number.MIN_SAFE_INTEGER)\n                return Number.MIN_SAFE_INTEGER;\n            if (d >= Number.MAX_SAFE_INTEGER)\n                return Number.MAX_SAFE_INTEGER;\n            return /*(int) */ (d + (d < 0.0 ? -0.5 : 0.5)) | 0;\n        }\n        // TYPESCRIPTPORT: maybe remove round method and call directly Math.round, it looks like it doesn't make sense for js\n        /**\n         * @param aX point A x coordinate\n         * @param aY point A y coordinate\n         * @param bX point B x coordinate\n         * @param bY point B y coordinate\n         * @return Euclidean distance between points A and B\n         */\n        static distance(aX /*float|int*/, aY /*float|int*/, bX /*float|int*/, bY /*float|int*/) {\n            const xDiff = aX - bX;\n            const yDiff = aY - bY;\n            return /*(float) */ Math.sqrt(xDiff * xDiff + yDiff * yDiff);\n        }\n        /**\n         * @param aX point A x coordinate\n         * @param aY point A y coordinate\n         * @param bX point B x coordinate\n         * @param bY point B y coordinate\n         * @return Euclidean distance between points A and B\n         */\n        // public static distance(aX: number /*int*/, aY: number /*int*/, bX: number /*int*/, bY: number /*int*/): float {\n        //   const xDiff = aX - bX\n        //   const yDiff = aY - bY\n        //   return (float) Math.sqrt(xDiff * xDiff + yDiff * yDiff);\n        // }\n        /**\n         * @param array values to sum\n         * @return sum of values in array\n         */\n        static sum(array) {\n            let count = 0;\n            for (let i = 0, length = array.length; i !== length; i++) {\n                const a = array[i];\n                count += a;\n            }\n            return count;\n        }\n    }\n\n    /**\n     * Ponyfill for Java's Float class.\n     */\n    class Float {\n        /**\n         * SincTS has no difference between int and float, there's all numbers,\n         * this is used only to polyfill Java code.\n         */\n        static floatToIntBits(f) {\n            return f;\n        }\n    }\n    /**\n     * The float max value in JS is the number max value.\n     */\n    Float.MAX_VALUE = Number.MAX_SAFE_INTEGER;\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates a point of interest in an image containing a barcode. Typically, this\n     * would be the location of a finder pattern or the corner of the barcode, for example.</p>\n     *\n     * @author Sean Owen\n     */\n    class ResultPoint {\n        constructor(x, y) {\n            this.x = x;\n            this.y = y;\n        }\n        getX() {\n            return this.x;\n        }\n        getY() {\n            return this.y;\n        }\n        /*@Override*/\n        equals(other) {\n            if (other instanceof ResultPoint) {\n                const otherPoint = other;\n                return this.x === otherPoint.x && this.y === otherPoint.y;\n            }\n            return false;\n        }\n        /*@Override*/\n        hashCode() {\n            return 31 * Float.floatToIntBits(this.x) + Float.floatToIntBits(this.y);\n        }\n        /*@Override*/\n        toString() {\n            return '(' + this.x + ',' + this.y + ')';\n        }\n        /**\n         * Orders an array of three ResultPoints in an order [A,B,C] such that AB is less than AC\n         * and BC is less than AC, and the angle between BC and BA is less than 180 degrees.\n         *\n         * @param patterns array of three {@code ResultPoint} to order\n         */\n        static orderBestPatterns(patterns) {\n            // Find distances between pattern centers\n            const zeroOneDistance = this.distance(patterns[0], patterns[1]);\n            const oneTwoDistance = this.distance(patterns[1], patterns[2]);\n            const zeroTwoDistance = this.distance(patterns[0], patterns[2]);\n            let pointA;\n            let pointB;\n            let pointC;\n            // Assume one closest to other two is B; A and C will just be guesses at first\n            if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) {\n                pointB = patterns[0];\n                pointA = patterns[1];\n                pointC = patterns[2];\n            }\n            else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) {\n                pointB = patterns[1];\n                pointA = patterns[0];\n                pointC = patterns[2];\n            }\n            else {\n                pointB = patterns[2];\n                pointA = patterns[0];\n                pointC = patterns[1];\n            }\n            // Use cross product to figure out whether A and C are correct or flipped.\n            // This asks whether BC x BA has a positive z component, which is the arrangement\n            // we want for A, B, C. If it's negative, then we've got it flipped around and\n            // should swap A and C.\n            if (this.crossProductZ(pointA, pointB, pointC) < 0.0) {\n                const temp = pointA;\n                pointA = pointC;\n                pointC = temp;\n            }\n            patterns[0] = pointA;\n            patterns[1] = pointB;\n            patterns[2] = pointC;\n        }\n        /**\n         * @param pattern1 first pattern\n         * @param pattern2 second pattern\n         * @return distance between two points\n         */\n        static distance(pattern1, pattern2) {\n            return MathUtils.distance(pattern1.x, pattern1.y, pattern2.x, pattern2.y);\n        }\n        /**\n         * Returns the z component of the cross product between vectors BC and BA.\n         */\n        static crossProductZ(pointA, pointB, pointC) {\n            const bX = pointB.x;\n            const bY = pointB.y;\n            return ((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX));\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates the result of detecting a barcode in an image. This includes the raw\n     * matrix of black/white pixels corresponding to the barcode, and possibly points of interest\n     * in the image, like the location of finder patterns or corners of the barcode in the image.</p>\n     *\n     * @author Sean Owen\n     */\n    class DetectorResult {\n        constructor(bits, points) {\n            this.bits = bits;\n            this.points = points;\n        }\n        getBits() {\n            return this.bits;\n        }\n        getPoints() {\n            return this.points;\n        }\n    }\n\n    /*\n     * Copyright 2010 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Extends {@link DetectorResult} with more information specific to the Aztec format,\n     * like the number of layers and whether it's compact.</p>\n     *\n     * @author Sean Owen\n     */\n    class AztecDetectorResult extends DetectorResult {\n        constructor(bits, points, compact, nbDatablocks, nbLayers) {\n            super(bits, points);\n            this.compact = compact;\n            this.nbDatablocks = nbDatablocks;\n            this.nbLayers = nbLayers;\n        }\n        getNbLayers() {\n            return this.nbLayers;\n        }\n        getNbDatablocks() {\n            return this.nbDatablocks;\n        }\n        isCompact() {\n            return this.compact;\n        }\n    }\n\n    /*\n     * Copyright 2010 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>\n     * Detects a candidate barcode-like rectangular region within an image. It\n     * starts around the center of the image, increases the size of the candidate\n     * region until it finds a white rectangular region. By keeping track of the\n     * last black points it encountered, it determines the corners of the barcode.\n     * </p>\n     *\n     * @author David Olivier\n     */\n    class WhiteRectangleDetector {\n        // public constructor(private image: BitMatrix) /*throws NotFoundException*/ {\n        //   this(image, INIT_SIZE, image.getWidth() / 2, image.getHeight() / 2)\n        // }\n        /**\n         * @param image barcode image to find a rectangle in\n         * @param initSize initial size of search area around center\n         * @param x x position of search center\n         * @param y y position of search center\n         * @throws NotFoundException if image is too small to accommodate {@code initSize}\n         */\n        constructor(image, initSize /*int*/, x /*int*/, y /*int*/) {\n            this.image = image;\n            this.height = image.getHeight();\n            this.width = image.getWidth();\n            if (undefined === initSize || null === initSize) {\n                initSize = WhiteRectangleDetector.INIT_SIZE;\n            }\n            if (undefined === x || null === x) {\n                x = image.getWidth() / 2 | 0;\n            }\n            if (undefined === y || null === y) {\n                y = image.getHeight() / 2 | 0;\n            }\n            const halfsize = initSize / 2 | 0;\n            this.leftInit = x - halfsize;\n            this.rightInit = x + halfsize;\n            this.upInit = y - halfsize;\n            this.downInit = y + halfsize;\n            if (this.upInit < 0 || this.leftInit < 0 || this.downInit >= this.height || this.rightInit >= this.width) {\n                throw new NotFoundException();\n            }\n        }\n        /**\n         * <p>\n         * Detects a candidate barcode-like rectangular region within an image. It\n         * starts around the center of the image, increases the size of the candidate\n         * region until it finds a white rectangular region.\n         * </p>\n         *\n         * @return {@link ResultPoint}[] describing the corners of the rectangular\n         *         region. The first and last points are opposed on the diagonal, as\n         *         are the second and third. The first point will be the topmost\n         *         point and the last, the bottommost. The second point will be\n         *         leftmost and the third, the rightmost\n         * @throws NotFoundException if no Data Matrix Code can be found\n         */\n        detect() {\n            let left = this.leftInit;\n            let right = this.rightInit;\n            let up = this.upInit;\n            let down = this.downInit;\n            let sizeExceeded = false;\n            let aBlackPointFoundOnBorder = true;\n            let atLeastOneBlackPointFoundOnBorder = false;\n            let atLeastOneBlackPointFoundOnRight = false;\n            let atLeastOneBlackPointFoundOnBottom = false;\n            let atLeastOneBlackPointFoundOnLeft = false;\n            let atLeastOneBlackPointFoundOnTop = false;\n            const width = this.width;\n            const height = this.height;\n            while (aBlackPointFoundOnBorder) {\n                aBlackPointFoundOnBorder = false;\n                // .....\n                // .   |\n                // .....\n                let rightBorderNotWhite = true;\n                while ((rightBorderNotWhite || !atLeastOneBlackPointFoundOnRight) && right < width) {\n                    rightBorderNotWhite = this.containsBlackPoint(up, down, right, false);\n                    if (rightBorderNotWhite) {\n                        right++;\n                        aBlackPointFoundOnBorder = true;\n                        atLeastOneBlackPointFoundOnRight = true;\n                    }\n                    else if (!atLeastOneBlackPointFoundOnRight) {\n                        right++;\n                    }\n                }\n                if (right >= width) {\n                    sizeExceeded = true;\n                    break;\n                }\n                // .....\n                // .   .\n                // .___.\n                let bottomBorderNotWhite = true;\n                while ((bottomBorderNotWhite || !atLeastOneBlackPointFoundOnBottom) && down < height) {\n                    bottomBorderNotWhite = this.containsBlackPoint(left, right, down, true);\n                    if (bottomBorderNotWhite) {\n                        down++;\n                        aBlackPointFoundOnBorder = true;\n                        atLeastOneBlackPointFoundOnBottom = true;\n                    }\n                    else if (!atLeastOneBlackPointFoundOnBottom) {\n                        down++;\n                    }\n                }\n                if (down >= height) {\n                    sizeExceeded = true;\n                    break;\n                }\n                // .....\n                // |   .\n                // .....\n                let leftBorderNotWhite = true;\n                while ((leftBorderNotWhite || !atLeastOneBlackPointFoundOnLeft) && left >= 0) {\n                    leftBorderNotWhite = this.containsBlackPoint(up, down, left, false);\n                    if (leftBorderNotWhite) {\n                        left--;\n                        aBlackPointFoundOnBorder = true;\n                        atLeastOneBlackPointFoundOnLeft = true;\n                    }\n                    else if (!atLeastOneBlackPointFoundOnLeft) {\n                        left--;\n                    }\n                }\n                if (left < 0) {\n                    sizeExceeded = true;\n                    break;\n                }\n                // .___.\n                // .   .\n                // .....\n                let topBorderNotWhite = true;\n                while ((topBorderNotWhite || !atLeastOneBlackPointFoundOnTop) && up >= 0) {\n                    topBorderNotWhite = this.containsBlackPoint(left, right, up, true);\n                    if (topBorderNotWhite) {\n                        up--;\n                        aBlackPointFoundOnBorder = true;\n                        atLeastOneBlackPointFoundOnTop = true;\n                    }\n                    else if (!atLeastOneBlackPointFoundOnTop) {\n                        up--;\n                    }\n                }\n                if (up < 0) {\n                    sizeExceeded = true;\n                    break;\n                }\n                if (aBlackPointFoundOnBorder) {\n                    atLeastOneBlackPointFoundOnBorder = true;\n                }\n            }\n            if (!sizeExceeded && atLeastOneBlackPointFoundOnBorder) {\n                const maxSize = right - left;\n                let z = null;\n                for (let i = 1; z === null && i < maxSize; i++) {\n                    z = this.getBlackPointOnSegment(left, down - i, left + i, down);\n                }\n                if (z == null) {\n                    throw new NotFoundException();\n                }\n                let t = null;\n                // go down right\n                for (let i = 1; t === null && i < maxSize; i++) {\n                    t = this.getBlackPointOnSegment(left, up + i, left + i, up);\n                }\n                if (t == null) {\n                    throw new NotFoundException();\n                }\n                let x = null;\n                // go down left\n                for (let i = 1; x === null && i < maxSize; i++) {\n                    x = this.getBlackPointOnSegment(right, up + i, right - i, up);\n                }\n                if (x == null) {\n                    throw new NotFoundException();\n                }\n                let y = null;\n                // go up left\n                for (let i = 1; y === null && i < maxSize; i++) {\n                    y = this.getBlackPointOnSegment(right, down - i, right - i, down);\n                }\n                if (y == null) {\n                    throw new NotFoundException();\n                }\n                return this.centerEdges(y, z, x, t);\n            }\n            else {\n                throw new NotFoundException();\n            }\n        }\n        getBlackPointOnSegment(aX /*float*/, aY /*float*/, bX /*float*/, bY /*float*/) {\n            const dist = MathUtils.round(MathUtils.distance(aX, aY, bX, bY));\n            const xStep = (bX - aX) / dist;\n            const yStep = (bY - aY) / dist;\n            const image = this.image;\n            for (let i = 0; i < dist; i++) {\n                const x = MathUtils.round(aX + i * xStep);\n                const y = MathUtils.round(aY + i * yStep);\n                if (image.get(x, y)) {\n                    return new ResultPoint(x, y);\n                }\n            }\n            return null;\n        }\n        /**\n         * recenters the points of a constant distance towards the center\n         *\n         * @param y bottom most point\n         * @param z left most point\n         * @param x right most point\n         * @param t top most point\n         * @return {@link ResultPoint}[] describing the corners of the rectangular\n         *         region. The first and last points are opposed on the diagonal, as\n         *         are the second and third. The first point will be the topmost\n         *         point and the last, the bottommost. The second point will be\n         *         leftmost and the third, the rightmost\n         */\n        centerEdges(y, z, x, t) {\n            //\n            //       t            t\n            //  z                      x\n            //        x    OR    z\n            //   y                    y\n            //\n            const yi = y.getX();\n            const yj = y.getY();\n            const zi = z.getX();\n            const zj = z.getY();\n            const xi = x.getX();\n            const xj = x.getY();\n            const ti = t.getX();\n            const tj = t.getY();\n            const CORR = WhiteRectangleDetector.CORR;\n            if (yi < this.width / 2.0) {\n                return [\n                    new ResultPoint(ti - CORR, tj + CORR),\n                    new ResultPoint(zi + CORR, zj + CORR),\n                    new ResultPoint(xi - CORR, xj - CORR),\n                    new ResultPoint(yi + CORR, yj - CORR)\n                ];\n            }\n            else {\n                return [\n                    new ResultPoint(ti + CORR, tj + CORR),\n                    new ResultPoint(zi + CORR, zj - CORR),\n                    new ResultPoint(xi - CORR, xj + CORR),\n                    new ResultPoint(yi - CORR, yj - CORR)\n                ];\n            }\n        }\n        /**\n         * Determines whether a segment contains a black point\n         *\n         * @param a          min value of the scanned coordinate\n         * @param b          max value of the scanned coordinate\n         * @param fixed      value of fixed coordinate\n         * @param horizontal set to true if scan must be horizontal, false if vertical\n         * @return true if a black point has been found, else false.\n         */\n        containsBlackPoint(a /*int*/, b /*int*/, fixed /*int*/, horizontal) {\n            const image = this.image;\n            if (horizontal) {\n                for (let x = a; x <= b; x++) {\n                    if (image.get(x, fixed)) {\n                        return true;\n                    }\n                }\n            }\n            else {\n                for (let y = a; y <= b; y++) {\n                    if (image.get(fixed, y)) {\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n    }\n    WhiteRectangleDetector.INIT_SIZE = 10;\n    WhiteRectangleDetector.CORR = 1;\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * Implementations of this class can, given locations of finder patterns for a QR code in an\n     * image, sample the right points in the image to reconstruct the QR code, accounting for\n     * perspective distortion. It is abstracted since it is relatively expensive and should be allowed\n     * to take advantage of platform-specific optimized implementations, like Sun's Java Advanced\n     * Imaging library, but which may not be available in other environments such as J2ME, and vice\n     * versa.\n     *\n     * The implementation used can be controlled by calling {@link #setGridSampler(GridSampler)}\n     * with an instance of a class which implements this interface.\n     *\n     * @author Sean Owen\n     */\n    class GridSampler {\n        /**\n         * <p>Checks a set of points that have been transformed to sample points on an image against\n         * the image's dimensions to see if the point are even within the image.</p>\n         *\n         * <p>This method will actually \"nudge\" the endpoints back onto the image if they are found to be\n         * barely (less than 1 pixel) off the image. This accounts for imperfect detection of finder\n         * patterns in an image where the QR Code runs all the way to the image border.</p>\n         *\n         * <p>For efficiency, the method will check points from either end of the line until one is found\n         * to be within the image. Because the set of points are assumed to be linear, this is valid.</p>\n         *\n         * @param image image into which the points should map\n         * @param points actual points in x1,y1,...,xn,yn form\n         * @throws NotFoundException if an endpoint is lies outside the image boundaries\n         */\n        static checkAndNudgePoints(image, points) {\n            const width = image.getWidth();\n            const height = image.getHeight();\n            // Check and nudge points from start until we see some that are OK:\n            let nudged = true;\n            for (let offset = 0; offset < points.length && nudged; offset += 2) {\n                const x = Math.floor(points[offset]);\n                const y = Math.floor(points[offset + 1]);\n                if (x < -1 || x > width || y < -1 || y > height) {\n                    throw new NotFoundException();\n                }\n                nudged = false;\n                if (x === -1) {\n                    points[offset] = 0.0;\n                    nudged = true;\n                }\n                else if (x === width) {\n                    points[offset] = width - 1;\n                    nudged = true;\n                }\n                if (y === -1) {\n                    points[offset + 1] = 0.0;\n                    nudged = true;\n                }\n                else if (y === height) {\n                    points[offset + 1] = height - 1;\n                    nudged = true;\n                }\n            }\n            // Check and nudge points from end:\n            nudged = true;\n            for (let offset = points.length - 2; offset >= 0 && nudged; offset -= 2) {\n                const x = Math.floor(points[offset]);\n                const y = Math.floor(points[offset + 1]);\n                if (x < -1 || x > width || y < -1 || y > height) {\n                    throw new NotFoundException();\n                }\n                nudged = false;\n                if (x === -1) {\n                    points[offset] = 0.0;\n                    nudged = true;\n                }\n                else if (x === width) {\n                    points[offset] = width - 1;\n                    nudged = true;\n                }\n                if (y === -1) {\n                    points[offset + 1] = 0.0;\n                    nudged = true;\n                }\n                else if (y === height) {\n                    points[offset + 1] = height - 1;\n                    nudged = true;\n                }\n            }\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing.common {*/\n    /**\n     * <p>This class implements a perspective transform in two dimensions. Given four source and four\n     * destination points, it will compute the transformation implied between them. The code is based\n     * directly upon section 3.4.2 of George Wolberg's \"Digital Image Warping\"; see pages 54-56.</p>\n     *\n     * @author Sean Owen\n     */\n    class PerspectiveTransform {\n        constructor(a11 /*float*/, a21 /*float*/, a31 /*float*/, a12 /*float*/, a22 /*float*/, a32 /*float*/, a13 /*float*/, a23 /*float*/, a33 /*float*/) {\n            this.a11 = a11;\n            this.a21 = a21;\n            this.a31 = a31;\n            this.a12 = a12;\n            this.a22 = a22;\n            this.a32 = a32;\n            this.a13 = a13;\n            this.a23 = a23;\n            this.a33 = a33;\n        }\n        static quadrilateralToQuadrilateral(x0 /*float*/, y0 /*float*/, x1 /*float*/, y1 /*float*/, x2 /*float*/, y2 /*float*/, x3 /*float*/, y3 /*float*/, x0p /*float*/, y0p /*float*/, x1p /*float*/, y1p /*float*/, x2p /*float*/, y2p /*float*/, x3p /*float*/, y3p /*float*/) {\n            const qToS = PerspectiveTransform.quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);\n            const sToQ = PerspectiveTransform.squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);\n            return sToQ.times(qToS);\n        }\n        transformPoints(points) {\n            const max = points.length;\n            const a11 = this.a11;\n            const a12 = this.a12;\n            const a13 = this.a13;\n            const a21 = this.a21;\n            const a22 = this.a22;\n            const a23 = this.a23;\n            const a31 = this.a31;\n            const a32 = this.a32;\n            const a33 = this.a33;\n            for (let i = 0; i < max; i += 2) {\n                const x = points[i];\n                const y = points[i + 1];\n                const denominator = a13 * x + a23 * y + a33;\n                points[i] = (a11 * x + a21 * y + a31) / denominator;\n                points[i + 1] = (a12 * x + a22 * y + a32) / denominator;\n            }\n        }\n        transformPointsWithValues(xValues, yValues) {\n            const a11 = this.a11;\n            const a12 = this.a12;\n            const a13 = this.a13;\n            const a21 = this.a21;\n            const a22 = this.a22;\n            const a23 = this.a23;\n            const a31 = this.a31;\n            const a32 = this.a32;\n            const a33 = this.a33;\n            const n = xValues.length;\n            for (let i = 0; i < n; i++) {\n                const x = xValues[i];\n                const y = yValues[i];\n                const denominator = a13 * x + a23 * y + a33;\n                xValues[i] = (a11 * x + a21 * y + a31) / denominator;\n                yValues[i] = (a12 * x + a22 * y + a32) / denominator;\n            }\n        }\n        static squareToQuadrilateral(x0 /*float*/, y0 /*float*/, x1 /*float*/, y1 /*float*/, x2 /*float*/, y2 /*float*/, x3 /*float*/, y3 /*float*/) {\n            const dx3 = x0 - x1 + x2 - x3;\n            const dy3 = y0 - y1 + y2 - y3;\n            if (dx3 === 0.0 && dy3 === 0.0) {\n                // Affine\n                return new PerspectiveTransform(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0.0, 0.0, 1.0);\n            }\n            else {\n                const dx1 = x1 - x2;\n                const dx2 = x3 - x2;\n                const dy1 = y1 - y2;\n                const dy2 = y3 - y2;\n                const denominator = dx1 * dy2 - dx2 * dy1;\n                const a13 = (dx3 * dy2 - dx2 * dy3) / denominator;\n                const a23 = (dx1 * dy3 - dx3 * dy1) / denominator;\n                return new PerspectiveTransform(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, y1 - y0 + a13 * y1, y3 - y0 + a23 * y3, y0, a13, a23, 1.0);\n            }\n        }\n        static quadrilateralToSquare(x0 /*float*/, y0 /*float*/, x1 /*float*/, y1 /*float*/, x2 /*float*/, y2 /*float*/, x3 /*float*/, y3 /*float*/) {\n            // Here, the adjoint serves as the inverse:\n            return PerspectiveTransform.squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint();\n        }\n        buildAdjoint() {\n            // Adjoint is the transpose of the cofactor matrix:\n            return new PerspectiveTransform(this.a22 * this.a33 - this.a23 * this.a32, this.a23 * this.a31 - this.a21 * this.a33, this.a21 * this.a32 - this.a22 * this.a31, this.a13 * this.a32 - this.a12 * this.a33, this.a11 * this.a33 - this.a13 * this.a31, this.a12 * this.a31 - this.a11 * this.a32, this.a12 * this.a23 - this.a13 * this.a22, this.a13 * this.a21 - this.a11 * this.a23, this.a11 * this.a22 - this.a12 * this.a21);\n        }\n        times(other) {\n            return new PerspectiveTransform(this.a11 * other.a11 + this.a21 * other.a12 + this.a31 * other.a13, this.a11 * other.a21 + this.a21 * other.a22 + this.a31 * other.a23, this.a11 * other.a31 + this.a21 * other.a32 + this.a31 * other.a33, this.a12 * other.a11 + this.a22 * other.a12 + this.a32 * other.a13, this.a12 * other.a21 + this.a22 * other.a22 + this.a32 * other.a23, this.a12 * other.a31 + this.a22 * other.a32 + this.a32 * other.a33, this.a13 * other.a11 + this.a23 * other.a12 + this.a33 * other.a13, this.a13 * other.a21 + this.a23 * other.a22 + this.a33 * other.a23, this.a13 * other.a31 + this.a23 * other.a32 + this.a33 * other.a33);\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * @author Sean Owen\n     */\n    class DefaultGridSampler extends GridSampler {\n        /*@Override*/\n        sampleGrid(image, dimensionX /*int*/, dimensionY /*int*/, p1ToX /*float*/, p1ToY /*float*/, p2ToX /*float*/, p2ToY /*float*/, p3ToX /*float*/, p3ToY /*float*/, p4ToX /*float*/, p4ToY /*float*/, p1FromX /*float*/, p1FromY /*float*/, p2FromX /*float*/, p2FromY /*float*/, p3FromX /*float*/, p3FromY /*float*/, p4FromX /*float*/, p4FromY /*float*/) {\n            const transform = PerspectiveTransform.quadrilateralToQuadrilateral(p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY, p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY);\n            return this.sampleGridWithTransform(image, dimensionX, dimensionY, transform);\n        }\n        /*@Override*/\n        sampleGridWithTransform(image, dimensionX /*int*/, dimensionY /*int*/, transform) {\n            if (dimensionX <= 0 || dimensionY <= 0) {\n                throw new NotFoundException();\n            }\n            const bits = new BitMatrix(dimensionX, dimensionY);\n            const points = new Float32Array(2 * dimensionX);\n            for (let y = 0; y < dimensionY; y++) {\n                const max = points.length;\n                const iValue = y + 0.5;\n                for (let x = 0; x < max; x += 2) {\n                    points[x] = (x / 2) + 0.5;\n                    points[x + 1] = iValue;\n                }\n                transform.transformPoints(points);\n                // Quick check to see if points transformed to something inside the image\n                // sufficient to check the endpoints\n                GridSampler.checkAndNudgePoints(image, points);\n                try {\n                    for (let x = 0; x < max; x += 2) {\n                        if (image.get(Math.floor(points[x]), Math.floor(points[x + 1]))) {\n                            // Black(-ish) pixel\n                            bits.set(x / 2, y);\n                        }\n                    }\n                }\n                catch (aioobe /*: ArrayIndexOutOfBoundsException*/) {\n                    // This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting\n                    // transform gets \"twisted\" such that it maps a straight line of points to a set of points\n                    // whose endpoints are in bounds, but others are not. There is probably some mathematical\n                    // way to detect this about the transformation that I don't know yet.\n                    // This results in an ugly runtime exception despite our clever checks above -- can't have\n                    // that. We could check each point's coordinates but that feels duplicative. We settle for\n                    // catching and wrapping ArrayIndexOutOfBoundsException.\n                    throw new NotFoundException();\n                }\n            }\n            return bits;\n        }\n    }\n\n    class GridSamplerInstance {\n        /**\n         * Sets the implementation of GridSampler used by the library. One global\n         * instance is stored, which may sound problematic. But, the implementation provided\n         * ought to be appropriate for the entire platform, and all uses of this library\n         * in the whole lifetime of the JVM. For instance, an Android activity can swap in\n         * an implementation that takes advantage of native platform libraries.\n         *\n         * @param newGridSampler The platform-specific object to install.\n         */\n        static setGridSampler(newGridSampler) {\n            GridSamplerInstance.gridSampler = newGridSampler;\n        }\n        /**\n         * @return the current implementation of GridSampler\n         */\n        static getInstance() {\n            return GridSamplerInstance.gridSampler;\n        }\n    }\n    GridSamplerInstance.gridSampler = new DefaultGridSampler();\n\n    /*\n     * Copyright 2010 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    class Point {\n        constructor(x, y) {\n            this.x = x;\n            this.y = y;\n        }\n        toResultPoint() {\n            return new ResultPoint(this.getX(), this.getY());\n        }\n        getX() {\n            return this.x;\n        }\n        getY() {\n            return this.y;\n        }\n    }\n    /**\n     * Encapsulates logic that can detect an Aztec Code in an image, even if the Aztec Code\n     * is rotated or skewed, or partially obscured.\n     *\n     * @author David Olivier\n     * @author Frank Yellin\n     */\n    class Detector {\n        constructor(image) {\n            this.EXPECTED_CORNER_BITS = new Int32Array([\n                0xee0,\n                0x1dc,\n                0x83b,\n                0x707,\n            ]);\n            this.image = image;\n        }\n        detect() {\n            return this.detectMirror(false);\n        }\n        /**\n         * Detects an Aztec Code in an image.\n         *\n         * @param isMirror if true, image is a mirror-image of original\n         * @return {@link AztecDetectorResult} encapsulating results of detecting an Aztec Code\n         * @throws NotFoundException if no Aztec Code can be found\n         */\n        detectMirror(isMirror) {\n            // 1. Get the center of the aztec matrix\n            let pCenter = this.getMatrixCenter();\n            // 2. Get the center points of the four diagonal points just outside the bull's eye\n            //  [topRight, bottomRight, bottomLeft, topLeft]\n            let bullsEyeCorners = this.getBullsEyeCorners(pCenter);\n            if (isMirror) {\n                let temp = bullsEyeCorners[0];\n                bullsEyeCorners[0] = bullsEyeCorners[2];\n                bullsEyeCorners[2] = temp;\n            }\n            // 3. Get the size of the matrix and other parameters from the bull's eye\n            this.extractParameters(bullsEyeCorners);\n            // 4. Sample the grid\n            let bits = this.sampleGrid(this.image, bullsEyeCorners[this.shift % 4], bullsEyeCorners[(this.shift + 1) % 4], bullsEyeCorners[(this.shift + 2) % 4], bullsEyeCorners[(this.shift + 3) % 4]);\n            // 5. Get the corners of the matrix.\n            let corners = this.getMatrixCornerPoints(bullsEyeCorners);\n            return new AztecDetectorResult(bits, corners, this.compact, this.nbDataBlocks, this.nbLayers);\n        }\n        /**\n         * Extracts the number of data layers and data blocks from the layer around the bull's eye.\n         *\n         * @param bullsEyeCorners the array of bull's eye corners\n         * @throws NotFoundException in case of too many errors or invalid parameters\n         */\n        extractParameters(bullsEyeCorners) {\n            if (!this.isValidPoint(bullsEyeCorners[0]) || !this.isValidPoint(bullsEyeCorners[1]) ||\n                !this.isValidPoint(bullsEyeCorners[2]) || !this.isValidPoint(bullsEyeCorners[3])) {\n                throw new NotFoundException();\n            }\n            let length = 2 * this.nbCenterLayers;\n            // Get the bits around the bull's eye\n            let sides = new Int32Array([\n                this.sampleLine(bullsEyeCorners[0], bullsEyeCorners[1], length),\n                this.sampleLine(bullsEyeCorners[1], bullsEyeCorners[2], length),\n                this.sampleLine(bullsEyeCorners[2], bullsEyeCorners[3], length),\n                this.sampleLine(bullsEyeCorners[3], bullsEyeCorners[0], length) // Top\n            ]);\n            // bullsEyeCorners[shift] is the corner of the bulls'eye that has three\n            // orientation marks.\n            // sides[shift] is the row/column that goes from the corner with three\n            // orientation marks to the corner with two.\n            this.shift = this.getRotation(sides, length);\n            // Flatten the parameter bits into a single 28- or 40-bit long\n            let parameterData = 0;\n            for (let i = 0; i < 4; i++) {\n                let side = sides[(this.shift + i) % 4];\n                if (this.compact) {\n                    // Each side of the form ..XXXXXXX. where Xs are parameter data\n                    parameterData <<= 7;\n                    parameterData += (side >> 1) & 0x7F;\n                }\n                else {\n                    // Each side of the form ..XXXXX.XXXXX. where Xs are parameter data\n                    parameterData <<= 10;\n                    parameterData += ((side >> 2) & (0x1f << 5)) + ((side >> 1) & 0x1F);\n                }\n            }\n            // Corrects parameter data using RS.  Returns just the data portion\n            // without the error correction.\n            let correctedData = this.getCorrectedParameterData(parameterData, this.compact);\n            if (this.compact) {\n                // 8 bits:  2 bits layers and 6 bits data blocks\n                this.nbLayers = (correctedData >> 6) + 1;\n                this.nbDataBlocks = (correctedData & 0x3F) + 1;\n            }\n            else {\n                // 16 bits:  5 bits layers and 11 bits data blocks\n                this.nbLayers = (correctedData >> 11) + 1;\n                this.nbDataBlocks = (correctedData & 0x7FF) + 1;\n            }\n        }\n        getRotation(sides, length) {\n            // In a normal pattern, we expect to See\n            //   **    .*             D       A\n            //   *      *\n            //\n            //   .      *\n            //   ..    ..             C       B\n            //\n            // Grab the 3 bits from each of the sides the form the locator pattern and concatenate\n            // into a 12-bit integer.  Start with the bit at A\n            let cornerBits = 0;\n            sides.forEach((side, idx, arr) => {\n                // XX......X where X's are orientation marks\n                let t = ((side >> (length - 2)) << 1) + (side & 1);\n                cornerBits = (cornerBits << 3) + t;\n            });\n            // for (var side in sides) {\n            //     // XX......X where X's are orientation marks\n            //     var t = ((side >> (length - 2)) << 1) + (side & 1);\n            //     cornerBits = (cornerBits << 3) + t;\n            // }\n            // Mov the bottom bit to the top, so that the three bits of the locator pattern at A are\n            // together.  cornerBits is now:\n            //  3 orientation bits at A || 3 orientation bits at B || ... || 3 orientation bits at D\n            cornerBits = ((cornerBits & 1) << 11) + (cornerBits >> 1);\n            // The result shift indicates which element of BullsEyeCorners[] goes into the top-left\n            // corner. Since the four rotation values have a Hamming distance of 8, we\n            // can easily tolerate two errors.\n            for (let shift = 0; shift < 4; shift++) {\n                if (Integer.bitCount(cornerBits ^ this.EXPECTED_CORNER_BITS[shift]) <= 2) {\n                    return shift;\n                }\n            }\n            throw new NotFoundException();\n        }\n        /**\n         * Corrects the parameter bits using Reed-Solomon algorithm.\n         *\n         * @param parameterData parameter bits\n         * @param compact true if this is a compact Aztec code\n         * @throws NotFoundException if the array contains too many errors\n         */\n        getCorrectedParameterData(parameterData, compact) {\n            let numCodewords;\n            let numDataCodewords;\n            if (compact) {\n                numCodewords = 7;\n                numDataCodewords = 2;\n            }\n            else {\n                numCodewords = 10;\n                numDataCodewords = 4;\n            }\n            let numECCodewords = numCodewords - numDataCodewords;\n            let parameterWords = new Int32Array(numCodewords);\n            for (let i = numCodewords - 1; i >= 0; --i) {\n                parameterWords[i] = parameterData & 0xF;\n                parameterData >>= 4;\n            }\n            try {\n                let rsDecoder = new ReedSolomonDecoder(GenericGF.AZTEC_PARAM);\n                rsDecoder.decode(parameterWords, numECCodewords);\n            }\n            catch (ignored) {\n                throw new NotFoundException();\n            }\n            // Toss the error correction.  Just return the data as an integer\n            let result = 0;\n            for (let i = 0; i < numDataCodewords; i++) {\n                result = (result << 4) + parameterWords[i];\n            }\n            return result;\n        }\n        /**\n         * Finds the corners of a bull-eye centered on the passed point.\n         * This returns the centers of the diagonal points just outside the bull's eye\n         * Returns [topRight, bottomRight, bottomLeft, topLeft]\n         *\n         * @param pCenter Center point\n         * @return The corners of the bull-eye\n         * @throws NotFoundException If no valid bull-eye can be found\n         */\n        getBullsEyeCorners(pCenter) {\n            let pina = pCenter;\n            let pinb = pCenter;\n            let pinc = pCenter;\n            let pind = pCenter;\n            let color = true;\n            for (this.nbCenterLayers = 1; this.nbCenterLayers < 9; this.nbCenterLayers++) {\n                let pouta = this.getFirstDifferent(pina, color, 1, -1);\n                let poutb = this.getFirstDifferent(pinb, color, 1, 1);\n                let poutc = this.getFirstDifferent(pinc, color, -1, 1);\n                let poutd = this.getFirstDifferent(pind, color, -1, -1);\n                // d      a\n                //\n                // c      b\n                if (this.nbCenterLayers > 2) {\n                    let q = (this.distancePoint(poutd, pouta) * this.nbCenterLayers) / (this.distancePoint(pind, pina) * (this.nbCenterLayers + 2));\n                    if (q < 0.75 || q > 1.25 || !this.isWhiteOrBlackRectangle(pouta, poutb, poutc, poutd)) {\n                        break;\n                    }\n                }\n                pina = pouta;\n                pinb = poutb;\n                pinc = poutc;\n                pind = poutd;\n                color = !color;\n            }\n            if (this.nbCenterLayers !== 5 && this.nbCenterLayers !== 7) {\n                throw new NotFoundException();\n            }\n            this.compact = this.nbCenterLayers === 5;\n            // Expand the square by .5 pixel in each direction so that we're on the border\n            // between the white square and the black square\n            let pinax = new ResultPoint(pina.getX() + 0.5, pina.getY() - 0.5);\n            let pinbx = new ResultPoint(pinb.getX() + 0.5, pinb.getY() + 0.5);\n            let pincx = new ResultPoint(pinc.getX() - 0.5, pinc.getY() + 0.5);\n            let pindx = new ResultPoint(pind.getX() - 0.5, pind.getY() - 0.5);\n            // Expand the square so that its corners are the centers of the points\n            // just outside the bull's eye.\n            return this.expandSquare([pinax, pinbx, pincx, pindx], 2 * this.nbCenterLayers - 3, 2 * this.nbCenterLayers);\n        }\n        /**\n         * Finds a candidate center point of an Aztec code from an image\n         *\n         * @return the center point\n         */\n        getMatrixCenter() {\n            let pointA;\n            let pointB;\n            let pointC;\n            let pointD;\n            // Get a white rectangle that can be the border of the matrix in center bull's eye or\n            try {\n                let cornerPoints = new WhiteRectangleDetector(this.image).detect();\n                pointA = cornerPoints[0];\n                pointB = cornerPoints[1];\n                pointC = cornerPoints[2];\n                pointD = cornerPoints[3];\n            }\n            catch (e) {\n                // This exception can be in case the initial rectangle is white\n                // In that case, surely in the bull's eye, we try to expand the rectangle.\n                let cx = this.image.getWidth() / 2;\n                let cy = this.image.getHeight() / 2;\n                pointA = this.getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toResultPoint();\n                pointB = this.getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toResultPoint();\n                pointC = this.getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint();\n                pointD = this.getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint();\n            }\n            // Compute the center of the rectangle\n            let cx = MathUtils.round((pointA.getX() + pointD.getX() + pointB.getX() + pointC.getX()) / 4.0);\n            let cy = MathUtils.round((pointA.getY() + pointD.getY() + pointB.getY() + pointC.getY()) / 4.0);\n            // Redetermine the white rectangle starting from previously computed center.\n            // This will ensure that we end up with a white rectangle in center bull's eye\n            // in order to compute a more accurate center.\n            try {\n                let cornerPoints = new WhiteRectangleDetector(this.image, 15, cx, cy).detect();\n                pointA = cornerPoints[0];\n                pointB = cornerPoints[1];\n                pointC = cornerPoints[2];\n                pointD = cornerPoints[3];\n            }\n            catch (e) {\n                // This exception can be in case the initial rectangle is white\n                // In that case we try to expand the rectangle.\n                pointA = this.getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toResultPoint();\n                pointB = this.getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toResultPoint();\n                pointC = this.getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint();\n                pointD = this.getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint();\n            }\n            // Recompute the center of the rectangle\n            cx = MathUtils.round((pointA.getX() + pointD.getX() + pointB.getX() + pointC.getX()) / 4.0);\n            cy = MathUtils.round((pointA.getY() + pointD.getY() + pointB.getY() + pointC.getY()) / 4.0);\n            return new Point(cx, cy);\n        }\n        /**\n         * Gets the Aztec code corners from the bull's eye corners and the parameters.\n         *\n         * @param bullsEyeCorners the array of bull's eye corners\n         * @return the array of aztec code corners\n         */\n        getMatrixCornerPoints(bullsEyeCorners) {\n            return this.expandSquare(bullsEyeCorners, 2 * this.nbCenterLayers, this.getDimension());\n        }\n        /**\n         * Creates a BitMatrix by sampling the provided image.\n         * topLeft, topRight, bottomRight, and bottomLeft are the centers of the squares on the\n         * diagonal just outside the bull's eye.\n         */\n        sampleGrid(image, topLeft, topRight, bottomRight, bottomLeft) {\n            let sampler = GridSamplerInstance.getInstance();\n            let dimension = this.getDimension();\n            let low = dimension / 2 - this.nbCenterLayers;\n            let high = dimension / 2 + this.nbCenterLayers;\n            return sampler.sampleGrid(image, dimension, dimension, low, low, // topleft\n            high, low, // topright\n            high, high, // bottomright\n            low, high, // bottomleft\n            topLeft.getX(), topLeft.getY(), topRight.getX(), topRight.getY(), bottomRight.getX(), bottomRight.getY(), bottomLeft.getX(), bottomLeft.getY());\n        }\n        /**\n         * Samples a line.\n         *\n         * @param p1   start point (inclusive)\n         * @param p2   end point (exclusive)\n         * @param size number of bits\n         * @return the array of bits as an int (first bit is high-order bit of result)\n         */\n        sampleLine(p1, p2, size) {\n            let result = 0;\n            let d = this.distanceResultPoint(p1, p2);\n            let moduleSize = d / size;\n            let px = p1.getX();\n            let py = p1.getY();\n            let dx = moduleSize * (p2.getX() - p1.getX()) / d;\n            let dy = moduleSize * (p2.getY() - p1.getY()) / d;\n            for (let i = 0; i < size; i++) {\n                if (this.image.get(MathUtils.round(px + i * dx), MathUtils.round(py + i * dy))) {\n                    result |= 1 << (size - i - 1);\n                }\n            }\n            return result;\n        }\n        /**\n         * @return true if the border of the rectangle passed in parameter is compound of white points only\n         *         or black points only\n         */\n        isWhiteOrBlackRectangle(p1, p2, p3, p4) {\n            let corr = 3;\n            p1 = new Point(p1.getX() - corr, p1.getY() + corr);\n            p2 = new Point(p2.getX() - corr, p2.getY() - corr);\n            p3 = new Point(p3.getX() + corr, p3.getY() - corr);\n            p4 = new Point(p4.getX() + corr, p4.getY() + corr);\n            let cInit = this.getColor(p4, p1);\n            if (cInit === 0) {\n                return false;\n            }\n            let c = this.getColor(p1, p2);\n            if (c !== cInit) {\n                return false;\n            }\n            c = this.getColor(p2, p3);\n            if (c !== cInit) {\n                return false;\n            }\n            c = this.getColor(p3, p4);\n            return c === cInit;\n        }\n        /**\n         * Gets the color of a segment\n         *\n         * @return 1 if segment more than 90% black, -1 if segment is more than 90% white, 0 else\n         */\n        getColor(p1, p2) {\n            let d = this.distancePoint(p1, p2);\n            let dx = (p2.getX() - p1.getX()) / d;\n            let dy = (p2.getY() - p1.getY()) / d;\n            let error = 0;\n            let px = p1.getX();\n            let py = p1.getY();\n            let colorModel = this.image.get(p1.getX(), p1.getY());\n            let iMax = Math.ceil(d);\n            for (let i = 0; i < iMax; i++) {\n                px += dx;\n                py += dy;\n                if (this.image.get(MathUtils.round(px), MathUtils.round(py)) !== colorModel) {\n                    error++;\n                }\n            }\n            let errRatio = error / d;\n            if (errRatio > 0.1 && errRatio < 0.9) {\n                return 0;\n            }\n            return (errRatio <= 0.1) === colorModel ? 1 : -1;\n        }\n        /**\n         * Gets the coordinate of the first point with a different color in the given direction\n         */\n        getFirstDifferent(init, color, dx, dy) {\n            let x = init.getX() + dx;\n            let y = init.getY() + dy;\n            while (this.isValid(x, y) && this.image.get(x, y) === color) {\n                x += dx;\n                y += dy;\n            }\n            x -= dx;\n            y -= dy;\n            while (this.isValid(x, y) && this.image.get(x, y) === color) {\n                x += dx;\n            }\n            x -= dx;\n            while (this.isValid(x, y) && this.image.get(x, y) === color) {\n                y += dy;\n            }\n            y -= dy;\n            return new Point(x, y);\n        }\n        /**\n         * Expand the square represented by the corner points by pushing out equally in all directions\n         *\n         * @param cornerPoints the corners of the square, which has the bull's eye at its center\n         * @param oldSide the original length of the side of the square in the target bit matrix\n         * @param newSide the new length of the size of the square in the target bit matrix\n         * @return the corners of the expanded square\n         */\n        expandSquare(cornerPoints, oldSide, newSide) {\n            let ratio = newSide / (2.0 * oldSide);\n            let dx = cornerPoints[0].getX() - cornerPoints[2].getX();\n            let dy = cornerPoints[0].getY() - cornerPoints[2].getY();\n            let centerx = (cornerPoints[0].getX() + cornerPoints[2].getX()) / 2.0;\n            let centery = (cornerPoints[0].getY() + cornerPoints[2].getY()) / 2.0;\n            let result0 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy);\n            let result2 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy);\n            dx = cornerPoints[1].getX() - cornerPoints[3].getX();\n            dy = cornerPoints[1].getY() - cornerPoints[3].getY();\n            centerx = (cornerPoints[1].getX() + cornerPoints[3].getX()) / 2.0;\n            centery = (cornerPoints[1].getY() + cornerPoints[3].getY()) / 2.0;\n            let result1 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy);\n            let result3 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy);\n            let results = [result0, result1, result2, result3];\n            return results;\n        }\n        isValid(x, y) {\n            return x >= 0 && x < this.image.getWidth() && y > 0 && y < this.image.getHeight();\n        }\n        isValidPoint(point) {\n            let x = MathUtils.round(point.getX());\n            let y = MathUtils.round(point.getY());\n            return this.isValid(x, y);\n        }\n        distancePoint(a, b) {\n            return MathUtils.distance(a.getX(), a.getY(), b.getX(), b.getY());\n        }\n        distanceResultPoint(a, b) {\n            return MathUtils.distance(a.getX(), a.getY(), b.getX(), b.getY());\n        }\n        getDimension() {\n            if (this.compact) {\n                return 4 * this.nbLayers + 11;\n            }\n            if (this.nbLayers <= 4) {\n                return 4 * this.nbLayers + 15;\n            }\n            return 4 * this.nbLayers + 2 * (Integer.truncDivision((this.nbLayers - 4), 8) + 1) + 15;\n        }\n    }\n\n    /*\n     * Copyright 2010 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    // import java.util.List;\n    // import java.util.Map;\n    /**\n     * This implementation can detect and decode Aztec codes in an image.\n     *\n     * @author David Olivier\n     */\n    class AztecReader {\n        /**\n         * Locates and decodes a Data Matrix code in an image.\n         *\n         * @return a String representing the content encoded by the Data Matrix code\n         * @throws NotFoundException if a Data Matrix code cannot be found\n         * @throws FormatException if a Data Matrix code cannot be decoded\n         */\n        decode(image, hints = null) {\n            let exception = null;\n            let detector = new Detector(image.getBlackMatrix());\n            let points = null;\n            let decoderResult = null;\n            try {\n                let detectorResult = detector.detectMirror(false);\n                points = detectorResult.getPoints();\n                this.reportFoundResultPoints(hints, points);\n                decoderResult = new Decoder().decode(detectorResult);\n            }\n            catch (e) {\n                exception = e;\n            }\n            if (decoderResult == null) {\n                try {\n                    let detectorResult = detector.detectMirror(true);\n                    points = detectorResult.getPoints();\n                    this.reportFoundResultPoints(hints, points);\n                    decoderResult = new Decoder().decode(detectorResult);\n                }\n                catch (e) {\n                    if (exception != null) {\n                        throw exception;\n                    }\n                    throw e;\n                }\n            }\n            let result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), decoderResult.getNumBits(), points, BarcodeFormat$1.AZTEC, System.currentTimeMillis());\n            let byteSegments = decoderResult.getByteSegments();\n            if (byteSegments != null) {\n                result.putMetadata(ResultMetadataType$1.BYTE_SEGMENTS, byteSegments);\n            }\n            let ecLevel = decoderResult.getECLevel();\n            if (ecLevel != null) {\n                result.putMetadata(ResultMetadataType$1.ERROR_CORRECTION_LEVEL, ecLevel);\n            }\n            return result;\n        }\n        reportFoundResultPoints(hints, points) {\n            if (hints != null) {\n                let rpcb = hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n                if (rpcb != null) {\n                    points.forEach((point, idx, arr) => {\n                        rpcb.foundPossibleResultPoint(point);\n                    });\n                }\n            }\n        }\n        // @Override\n        reset() {\n            // do nothing\n        }\n    }\n\n    /**\n     * Aztec Code reader to use from browser.\n     *\n     * @class BrowserAztecCodeReader\n     * @extends {BrowserCodeReader}\n     */\n    class BrowserAztecCodeReader extends BrowserCodeReader {\n        /**\n         * Creates an instance of BrowserAztecCodeReader.\n         * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n         *\n         * @memberOf BrowserAztecCodeReader\n         */\n        constructor(timeBetweenScansMillis = 500) {\n            super(new AztecReader(), timeBetweenScansMillis);\n        }\n    }\n\n    /**\n     * Encapsulates functionality and implementation that is common to all families\n     * of one-dimensional barcodes.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @author Sean Owen\n     */\n    class OneDReader {\n        /*\n        @Override\n        public Result decode(BinaryBitmap image) throws NotFoundException, FormatException {\n          return decode(image, null);\n        }\n        */\n        // Note that we don't try rotation without the try harder flag, even if rotation was supported.\n        // @Override\n        decode(image, hints) {\n            try {\n                return this.doDecode(image, hints);\n            }\n            catch (nfe) {\n                const tryHarder = hints && (hints.get(DecodeHintType$1.TRY_HARDER) === true);\n                if (tryHarder && image.isRotateSupported()) {\n                    const rotatedImage = image.rotateCounterClockwise();\n                    const result = this.doDecode(rotatedImage, hints);\n                    // Record that we found it rotated 90 degrees CCW / 270 degrees CW\n                    const metadata = result.getResultMetadata();\n                    let orientation = 270;\n                    if (metadata !== null && (metadata.get(ResultMetadataType$1.ORIENTATION) === true)) {\n                        // But if we found it reversed in doDecode(), add in that result here:\n                        orientation = (orientation + metadata.get(ResultMetadataType$1.ORIENTATION) % 360);\n                    }\n                    result.putMetadata(ResultMetadataType$1.ORIENTATION, orientation);\n                    // Update result points\n                    const points = result.getResultPoints();\n                    if (points !== null) {\n                        const height = rotatedImage.getHeight();\n                        for (let i = 0; i < points.length; i++) {\n                            points[i] = new ResultPoint(height - points[i].getY() - 1, points[i].getX());\n                        }\n                    }\n                    return result;\n                }\n                else {\n                    throw new NotFoundException();\n                }\n            }\n        }\n        // @Override\n        reset() {\n            // do nothing\n        }\n        /**\n         * We're going to examine rows from the middle outward, searching alternately above and below the\n         * middle, and farther out each time. rowStep is the number of rows between each successive\n         * attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then\n         * middle + rowStep, then middle - (2 * rowStep), etc.\n         * rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily\n         * decided that moving up and down by about 1/16 of the image is pretty good; we try more of the\n         * image if \"trying harder\".\n         *\n         * @param image The image to decode\n         * @param hints Any hints that were requested\n         * @return The contents of the decoded barcode\n         * @throws NotFoundException Any spontaneous errors which occur\n         */\n        doDecode(image, hints) {\n            const width = image.getWidth();\n            const height = image.getHeight();\n            let row = new BitArray(width);\n            const tryHarder = hints && (hints.get(DecodeHintType$1.TRY_HARDER) === true);\n            const rowStep = Math.max(1, height >> (tryHarder ? 8 : 5));\n            let maxLines;\n            if (tryHarder) {\n                maxLines = height; // Look at the whole image, not just the center\n            }\n            else {\n                maxLines = 15; // 15 rows spaced 1/32 apart is roughly the middle half of the image\n            }\n            const middle = Math.trunc(height / 2);\n            for (let x = 0; x < maxLines; x++) {\n                // Scanning from the middle out. Determine which row we're looking at next:\n                const rowStepsAboveOrBelow = Math.trunc((x + 1) / 2);\n                const isAbove = (x & 0x01) === 0; // i.e. is x even?\n                const rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow);\n                if (rowNumber < 0 || rowNumber >= height) {\n                    // Oops, if we run off the top or bottom, stop\n                    break;\n                }\n                // Estimate black point for this row and load it:\n                try {\n                    row = image.getBlackRow(rowNumber, row);\n                }\n                catch (ignored) {\n                    continue;\n                }\n                // While we have the image data in a BitArray, it's fairly cheap to reverse it in place to\n                // handle decoding upside down barcodes.\n                for (let attempt = 0; attempt < 2; attempt++) {\n                    if (attempt === 1) { // trying again?\n                        row.reverse(); // reverse the row and continue\n                        // This means we will only ever draw result points *once* in the life of this method\n                        // since we want to avoid drawing the wrong points after flipping the row, and,\n                        // don't want to clutter with noise from every single row scan -- just the scans\n                        // that start on the center line.\n                        if (hints && (hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK) === true)) {\n                            const newHints = new Map();\n                            hints.forEach((hint, key) => newHints.set(key, hint));\n                            newHints.delete(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n                            hints = newHints;\n                        }\n                    }\n                    try {\n                        // Look for a barcode\n                        const result = this.decodeRow(rowNumber, row, hints);\n                        // We found our barcode\n                        if (attempt === 1) {\n                            // But it was upside down, so note that\n                            result.putMetadata(ResultMetadataType$1.ORIENTATION, 180);\n                            // And remember to flip the result points horizontally.\n                            const points = result.getResultPoints();\n                            if (points !== null) {\n                                points[0] = new ResultPoint(width - points[0].getX() - 1, points[0].getY());\n                                points[1] = new ResultPoint(width - points[1].getX() - 1, points[1].getY());\n                            }\n                        }\n                        return result;\n                    }\n                    catch (re) {\n                        // continue -- just couldn't decode this row\n                    }\n                }\n            }\n            throw new NotFoundException();\n        }\n        /**\n         * Records the size of successive runs of white and black pixels in a row, starting at a given point.\n         * The values are recorded in the given array, and the number of runs recorded is equal to the size\n         * of the array. If the row starts on a white pixel at the given start point, then the first count\n         * recorded is the run of white pixels starting from that point; likewise it is the count of a run\n         * of black pixels if the row begin on a black pixels at that point.\n         *\n         * @param row row to count from\n         * @param start offset into row to start at\n         * @param counters array into which to record counts\n         * @throws NotFoundException if counters cannot be filled entirely from row before running out\n         *  of pixels\n         */\n        static recordPattern(row, start, counters) {\n            const numCounters = counters.length;\n            for (let index = 0; index < numCounters; index++)\n                counters[index] = 0;\n            const end = row.getSize();\n            if (start >= end) {\n                throw new NotFoundException();\n            }\n            let isWhite = !row.get(start);\n            let counterPosition = 0;\n            let i = start;\n            while (i < end) {\n                if (row.get(i) !== isWhite) {\n                    counters[counterPosition]++;\n                }\n                else {\n                    if (++counterPosition === numCounters) {\n                        break;\n                    }\n                    else {\n                        counters[counterPosition] = 1;\n                        isWhite = !isWhite;\n                    }\n                }\n                i++;\n            }\n            // If we read fully the last section of pixels and filled up our counters -- or filled\n            // the last counter but ran off the side of the image, OK. Otherwise, a problem.\n            if (!(counterPosition === numCounters || (counterPosition === numCounters - 1 && i === end))) {\n                throw new NotFoundException();\n            }\n        }\n        static recordPatternInReverse(row, start, counters) {\n            // This could be more efficient I guess\n            let numTransitionsLeft = counters.length;\n            let last = row.get(start);\n            while (start > 0 && numTransitionsLeft >= 0) {\n                if (row.get(--start) !== last) {\n                    numTransitionsLeft--;\n                    last = !last;\n                }\n            }\n            if (numTransitionsLeft >= 0) {\n                throw new NotFoundException();\n            }\n            OneDReader.recordPattern(row, start + 1, counters);\n        }\n        /**\n         * Determines how closely a set of observed counts of runs of black/white values matches a given\n         * target pattern. This is reported as the ratio of the total variance from the expected pattern\n         * proportions across all pattern elements, to the length of the pattern.\n         *\n         * @param counters observed counters\n         * @param pattern expected pattern\n         * @param maxIndividualVariance The most any counter can differ before we give up\n         * @return ratio of total variance between counters and pattern compared to total pattern size\n         */\n        static patternMatchVariance(counters, pattern, maxIndividualVariance) {\n            const numCounters = counters.length;\n            let total = 0;\n            let patternLength = 0;\n            for (let i = 0; i < numCounters; i++) {\n                total += counters[i];\n                patternLength += pattern[i];\n            }\n            if (total < patternLength) {\n                // If we don't even have one pixel per unit of bar width, assume this is too small\n                // to reliably match, so fail:\n                return Number.POSITIVE_INFINITY;\n            }\n            const unitBarWidth = total / patternLength;\n            maxIndividualVariance *= unitBarWidth;\n            let totalVariance = 0.0;\n            for (let x = 0; x < numCounters; x++) {\n                const counter = counters[x];\n                const scaledPattern = pattern[x] * unitBarWidth;\n                const variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter;\n                if (variance > maxIndividualVariance) {\n                    return Number.POSITIVE_INFINITY;\n                }\n                totalVariance += variance;\n            }\n            return totalVariance / total;\n        }\n    }\n\n    /**\n     * <p>Decodes Code 128 barcodes.</p>\n     *\n     * @author Sean Owen\n     */\n    class Code128Reader extends OneDReader {\n        static findStartPattern(row) {\n            const width = row.getSize();\n            const rowOffset = row.getNextSet(0);\n            let counterPosition = 0;\n            let counters = Int32Array.from([0, 0, 0, 0, 0, 0]);\n            let patternStart = rowOffset;\n            let isWhite = false;\n            const patternLength = 6;\n            for (let i = rowOffset; i < width; i++) {\n                if (row.get(i) !== isWhite) {\n                    counters[counterPosition]++;\n                }\n                else {\n                    if (counterPosition === (patternLength - 1)) {\n                        let bestVariance = Code128Reader.MAX_AVG_VARIANCE;\n                        let bestMatch = -1;\n                        for (let startCode = Code128Reader.CODE_START_A; startCode <= Code128Reader.CODE_START_C; startCode++) {\n                            const variance = OneDReader.patternMatchVariance(counters, Code128Reader.CODE_PATTERNS[startCode], Code128Reader.MAX_INDIVIDUAL_VARIANCE);\n                            if (variance < bestVariance) {\n                                bestVariance = variance;\n                                bestMatch = startCode;\n                            }\n                        }\n                        // Look for whitespace before start pattern, >= 50% of width of start pattern\n                        if (bestMatch >= 0 &&\n                            row.isRange(Math.max(0, patternStart - (i - patternStart) / 2), patternStart, false)) {\n                            return Int32Array.from([patternStart, i, bestMatch]);\n                        }\n                        patternStart += counters[0] + counters[1];\n                        counters = counters.slice(2, counters.length - 1);\n                        counters[counterPosition - 1] = 0;\n                        counters[counterPosition] = 0;\n                        counterPosition--;\n                    }\n                    else {\n                        counterPosition++;\n                    }\n                    counters[counterPosition] = 1;\n                    isWhite = !isWhite;\n                }\n            }\n            throw new NotFoundException();\n        }\n        static decodeCode(row, counters, rowOffset) {\n            OneDReader.recordPattern(row, rowOffset, counters);\n            let bestVariance = Code128Reader.MAX_AVG_VARIANCE; // worst variance we'll accept\n            let bestMatch = -1;\n            for (let d = 0; d < Code128Reader.CODE_PATTERNS.length; d++) {\n                const pattern = Code128Reader.CODE_PATTERNS[d];\n                const variance = this.patternMatchVariance(counters, pattern, Code128Reader.MAX_INDIVIDUAL_VARIANCE);\n                if (variance < bestVariance) {\n                    bestVariance = variance;\n                    bestMatch = d;\n                }\n            }\n            // TODO We're overlooking the fact that the STOP pattern has 7 values, not 6.\n            if (bestMatch >= 0) {\n                return bestMatch;\n            }\n            else {\n                throw new NotFoundException();\n            }\n        }\n        decodeRow(rowNumber, row, hints) {\n            const convertFNC1 = hints && (hints.get(DecodeHintType$1.ASSUME_GS1) === true);\n            const startPatternInfo = Code128Reader.findStartPattern(row);\n            const startCode = startPatternInfo[2];\n            let currentRawCodesIndex = 0;\n            const rawCodes = new Uint8Array(20);\n            rawCodes[currentRawCodesIndex++] = startCode;\n            let codeSet;\n            switch (startCode) {\n                case Code128Reader.CODE_START_A:\n                    codeSet = Code128Reader.CODE_CODE_A;\n                    break;\n                case Code128Reader.CODE_START_B:\n                    codeSet = Code128Reader.CODE_CODE_B;\n                    break;\n                case Code128Reader.CODE_START_C:\n                    codeSet = Code128Reader.CODE_CODE_C;\n                    break;\n                default:\n                    throw new FormatException();\n            }\n            let done = false;\n            let isNextShifted = false;\n            let result = '';\n            let lastStart = startPatternInfo[0];\n            let nextStart = startPatternInfo[1];\n            const counters = Int32Array.from([0, 0, 0, 0, 0, 0]);\n            let lastCode = 0;\n            let code = 0;\n            let checksumTotal = startCode;\n            let multiplier = 0;\n            let lastCharacterWasPrintable = true;\n            let upperMode = false;\n            let shiftUpperMode = false;\n            while (!done) {\n                const unshift = isNextShifted;\n                isNextShifted = false;\n                // Save off last code\n                lastCode = code;\n                // Decode another code from image\n                code = Code128Reader.decodeCode(row, counters, nextStart);\n                rawCodes[currentRawCodesIndex++] = code;\n                // Remember whether the last code was printable or not (excluding CODE_STOP)\n                if (code !== Code128Reader.CODE_STOP) {\n                    lastCharacterWasPrintable = true;\n                }\n                // Add to checksum computation (if not CODE_STOP of course)\n                if (code !== Code128Reader.CODE_STOP) {\n                    multiplier++;\n                    checksumTotal += multiplier * code;\n                }\n                // Advance to where the next code will to start\n                lastStart = nextStart;\n                nextStart += counters.reduce((previous, current) => previous + current, 0);\n                // Take care of illegal start codes\n                switch (code) {\n                    case Code128Reader.CODE_START_A:\n                    case Code128Reader.CODE_START_B:\n                    case Code128Reader.CODE_START_C:\n                        throw new FormatException();\n                }\n                switch (codeSet) {\n                    case Code128Reader.CODE_CODE_A:\n                        if (code < 64) {\n                            if (shiftUpperMode === upperMode) {\n                                result += String.fromCharCode((' '.charCodeAt(0) + code));\n                            }\n                            else {\n                                result += String.fromCharCode((' '.charCodeAt(0) + code + 128));\n                            }\n                            shiftUpperMode = false;\n                        }\n                        else if (code < 96) {\n                            if (shiftUpperMode === upperMode) {\n                                result += String.fromCharCode((code - 64));\n                            }\n                            else {\n                                result += String.fromCharCode((code + 64));\n                            }\n                            shiftUpperMode = false;\n                        }\n                        else {\n                            // Don't let CODE_STOP, which always appears, affect whether whether we think the last\n                            // code was printable or not.\n                            if (code !== Code128Reader.CODE_STOP) {\n                                lastCharacterWasPrintable = false;\n                            }\n                            switch (code) {\n                                case Code128Reader.CODE_FNC_1:\n                                    if (convertFNC1) {\n                                        if (result.length === 0) {\n                                            // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code\n                                            // is FNC1 then this is GS1-128. We add the symbology identifier.\n                                            result += ']C1';\n                                        }\n                                        else {\n                                            // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS)\n                                            result += String.fromCharCode(29);\n                                        }\n                                    }\n                                    break;\n                                case Code128Reader.CODE_FNC_2:\n                                case Code128Reader.CODE_FNC_3:\n                                    // do nothing?\n                                    break;\n                                case Code128Reader.CODE_FNC_4_A:\n                                    if (!upperMode && shiftUpperMode) {\n                                        upperMode = true;\n                                        shiftUpperMode = false;\n                                    }\n                                    else if (upperMode && shiftUpperMode) {\n                                        upperMode = false;\n                                        shiftUpperMode = false;\n                                    }\n                                    else {\n                                        shiftUpperMode = true;\n                                    }\n                                    break;\n                                case Code128Reader.CODE_SHIFT:\n                                    isNextShifted = true;\n                                    codeSet = Code128Reader.CODE_CODE_B;\n                                    break;\n                                case Code128Reader.CODE_CODE_B:\n                                    codeSet = Code128Reader.CODE_CODE_B;\n                                    break;\n                                case Code128Reader.CODE_CODE_C:\n                                    codeSet = Code128Reader.CODE_CODE_C;\n                                    break;\n                                case Code128Reader.CODE_STOP:\n                                    done = true;\n                                    break;\n                            }\n                        }\n                        break;\n                    case Code128Reader.CODE_CODE_B:\n                        if (code < 96) {\n                            if (shiftUpperMode === upperMode) {\n                                result += String.fromCharCode((' '.charCodeAt(0) + code));\n                            }\n                            else {\n                                result += String.fromCharCode((' '.charCodeAt(0) + code + 128));\n                            }\n                            shiftUpperMode = false;\n                        }\n                        else {\n                            if (code !== Code128Reader.CODE_STOP) {\n                                lastCharacterWasPrintable = false;\n                            }\n                            switch (code) {\n                                case Code128Reader.CODE_FNC_1:\n                                    if (convertFNC1) {\n                                        if (result.length === 0) {\n                                            // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code\n                                            // is FNC1 then this is GS1-128. We add the symbology identifier.\n                                            result += ']C1';\n                                        }\n                                        else {\n                                            // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS)\n                                            result += String.fromCharCode(29);\n                                        }\n                                    }\n                                    break;\n                                case Code128Reader.CODE_FNC_2:\n                                case Code128Reader.CODE_FNC_3:\n                                    // do nothing?\n                                    break;\n                                case Code128Reader.CODE_FNC_4_B:\n                                    if (!upperMode && shiftUpperMode) {\n                                        upperMode = true;\n                                        shiftUpperMode = false;\n                                    }\n                                    else if (upperMode && shiftUpperMode) {\n                                        upperMode = false;\n                                        shiftUpperMode = false;\n                                    }\n                                    else {\n                                        shiftUpperMode = true;\n                                    }\n                                    break;\n                                case Code128Reader.CODE_SHIFT:\n                                    isNextShifted = true;\n                                    codeSet = Code128Reader.CODE_CODE_A;\n                                    break;\n                                case Code128Reader.CODE_CODE_A:\n                                    codeSet = Code128Reader.CODE_CODE_A;\n                                    break;\n                                case Code128Reader.CODE_CODE_C:\n                                    codeSet = Code128Reader.CODE_CODE_C;\n                                    break;\n                                case Code128Reader.CODE_STOP:\n                                    done = true;\n                                    break;\n                            }\n                        }\n                        break;\n                    case Code128Reader.CODE_CODE_C:\n                        if (code < 100) {\n                            if (code < 10) {\n                                result += '0';\n                            }\n                            result += code;\n                        }\n                        else {\n                            if (code !== Code128Reader.CODE_STOP) {\n                                lastCharacterWasPrintable = false;\n                            }\n                            switch (code) {\n                                case Code128Reader.CODE_FNC_1:\n                                    if (convertFNC1) {\n                                        if (result.length === 0) {\n                                            // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code\n                                            // is FNC1 then this is GS1-128. We add the symbology identifier.\n                                            result += ']C1';\n                                        }\n                                        else {\n                                            // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS)\n                                            result += String.fromCharCode(29);\n                                        }\n                                    }\n                                    break;\n                                case Code128Reader.CODE_CODE_A:\n                                    codeSet = Code128Reader.CODE_CODE_A;\n                                    break;\n                                case Code128Reader.CODE_CODE_B:\n                                    codeSet = Code128Reader.CODE_CODE_B;\n                                    break;\n                                case Code128Reader.CODE_STOP:\n                                    done = true;\n                                    break;\n                            }\n                        }\n                        break;\n                }\n                // Unshift back to another code set if we were shifted\n                if (unshift) {\n                    codeSet = codeSet === Code128Reader.CODE_CODE_A ? Code128Reader.CODE_CODE_B : Code128Reader.CODE_CODE_A;\n                }\n            }\n            const lastPatternSize = nextStart - lastStart;\n            // Check for ample whitespace following pattern, but, to do this we first need to remember that\n            // we fudged decoding CODE_STOP since it actually has 7 bars, not 6. There is a black bar left\n            // to read off. Would be slightly better to properly read. Here we just skip it:\n            nextStart = row.getNextUnset(nextStart);\n            if (!row.isRange(nextStart, Math.min(row.getSize(), nextStart + (nextStart - lastStart) / 2), false)) {\n                throw new NotFoundException();\n            }\n            // Pull out from sum the value of the penultimate check code\n            checksumTotal -= multiplier * lastCode;\n            // lastCode is the checksum then:\n            if (checksumTotal % 103 !== lastCode) {\n                throw new ChecksumException();\n            }\n            // Need to pull out the check digits from string\n            const resultLength = result.length;\n            if (resultLength === 0) {\n                // false positive\n                throw new NotFoundException();\n            }\n            // Only bother if the result had at least one character, and if the checksum digit happened to\n            // be a printable character. If it was just interpreted as a control code, nothing to remove.\n            if (resultLength > 0 && lastCharacterWasPrintable) {\n                if (codeSet === Code128Reader.CODE_CODE_C) {\n                    result = result.substring(0, resultLength - 2);\n                }\n                else {\n                    result = result.substring(0, resultLength - 1);\n                }\n            }\n            const left = (startPatternInfo[1] + startPatternInfo[0]) / 2.0;\n            const right = lastStart + lastPatternSize / 2.0;\n            const rawCodesSize = rawCodes.length;\n            const rawBytes = new Uint8Array(rawCodesSize);\n            for (let i = 0; i < rawCodesSize; i++) {\n                rawBytes[i] = rawCodes[i];\n            }\n            const points = [new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber)];\n            return new Result(result, rawBytes, 0, points, BarcodeFormat$1.CODE_128, new Date().getTime());\n        }\n    }\n    Code128Reader.CODE_PATTERNS = [\n        Int32Array.from([2, 1, 2, 2, 2, 2]),\n        Int32Array.from([2, 2, 2, 1, 2, 2]),\n        Int32Array.from([2, 2, 2, 2, 2, 1]),\n        Int32Array.from([1, 2, 1, 2, 2, 3]),\n        Int32Array.from([1, 2, 1, 3, 2, 2]),\n        Int32Array.from([1, 3, 1, 2, 2, 2]),\n        Int32Array.from([1, 2, 2, 2, 1, 3]),\n        Int32Array.from([1, 2, 2, 3, 1, 2]),\n        Int32Array.from([1, 3, 2, 2, 1, 2]),\n        Int32Array.from([2, 2, 1, 2, 1, 3]),\n        Int32Array.from([2, 2, 1, 3, 1, 2]),\n        Int32Array.from([2, 3, 1, 2, 1, 2]),\n        Int32Array.from([1, 1, 2, 2, 3, 2]),\n        Int32Array.from([1, 2, 2, 1, 3, 2]),\n        Int32Array.from([1, 2, 2, 2, 3, 1]),\n        Int32Array.from([1, 1, 3, 2, 2, 2]),\n        Int32Array.from([1, 2, 3, 1, 2, 2]),\n        Int32Array.from([1, 2, 3, 2, 2, 1]),\n        Int32Array.from([2, 2, 3, 2, 1, 1]),\n        Int32Array.from([2, 2, 1, 1, 3, 2]),\n        Int32Array.from([2, 2, 1, 2, 3, 1]),\n        Int32Array.from([2, 1, 3, 2, 1, 2]),\n        Int32Array.from([2, 2, 3, 1, 1, 2]),\n        Int32Array.from([3, 1, 2, 1, 3, 1]),\n        Int32Array.from([3, 1, 1, 2, 2, 2]),\n        Int32Array.from([3, 2, 1, 1, 2, 2]),\n        Int32Array.from([3, 2, 1, 2, 2, 1]),\n        Int32Array.from([3, 1, 2, 2, 1, 2]),\n        Int32Array.from([3, 2, 2, 1, 1, 2]),\n        Int32Array.from([3, 2, 2, 2, 1, 1]),\n        Int32Array.from([2, 1, 2, 1, 2, 3]),\n        Int32Array.from([2, 1, 2, 3, 2, 1]),\n        Int32Array.from([2, 3, 2, 1, 2, 1]),\n        Int32Array.from([1, 1, 1, 3, 2, 3]),\n        Int32Array.from([1, 3, 1, 1, 2, 3]),\n        Int32Array.from([1, 3, 1, 3, 2, 1]),\n        Int32Array.from([1, 1, 2, 3, 1, 3]),\n        Int32Array.from([1, 3, 2, 1, 1, 3]),\n        Int32Array.from([1, 3, 2, 3, 1, 1]),\n        Int32Array.from([2, 1, 1, 3, 1, 3]),\n        Int32Array.from([2, 3, 1, 1, 1, 3]),\n        Int32Array.from([2, 3, 1, 3, 1, 1]),\n        Int32Array.from([1, 1, 2, 1, 3, 3]),\n        Int32Array.from([1, 1, 2, 3, 3, 1]),\n        Int32Array.from([1, 3, 2, 1, 3, 1]),\n        Int32Array.from([1, 1, 3, 1, 2, 3]),\n        Int32Array.from([1, 1, 3, 3, 2, 1]),\n        Int32Array.from([1, 3, 3, 1, 2, 1]),\n        Int32Array.from([3, 1, 3, 1, 2, 1]),\n        Int32Array.from([2, 1, 1, 3, 3, 1]),\n        Int32Array.from([2, 3, 1, 1, 3, 1]),\n        Int32Array.from([2, 1, 3, 1, 1, 3]),\n        Int32Array.from([2, 1, 3, 3, 1, 1]),\n        Int32Array.from([2, 1, 3, 1, 3, 1]),\n        Int32Array.from([3, 1, 1, 1, 2, 3]),\n        Int32Array.from([3, 1, 1, 3, 2, 1]),\n        Int32Array.from([3, 3, 1, 1, 2, 1]),\n        Int32Array.from([3, 1, 2, 1, 1, 3]),\n        Int32Array.from([3, 1, 2, 3, 1, 1]),\n        Int32Array.from([3, 3, 2, 1, 1, 1]),\n        Int32Array.from([3, 1, 4, 1, 1, 1]),\n        Int32Array.from([2, 2, 1, 4, 1, 1]),\n        Int32Array.from([4, 3, 1, 1, 1, 1]),\n        Int32Array.from([1, 1, 1, 2, 2, 4]),\n        Int32Array.from([1, 1, 1, 4, 2, 2]),\n        Int32Array.from([1, 2, 1, 1, 2, 4]),\n        Int32Array.from([1, 2, 1, 4, 2, 1]),\n        Int32Array.from([1, 4, 1, 1, 2, 2]),\n        Int32Array.from([1, 4, 1, 2, 2, 1]),\n        Int32Array.from([1, 1, 2, 2, 1, 4]),\n        Int32Array.from([1, 1, 2, 4, 1, 2]),\n        Int32Array.from([1, 2, 2, 1, 1, 4]),\n        Int32Array.from([1, 2, 2, 4, 1, 1]),\n        Int32Array.from([1, 4, 2, 1, 1, 2]),\n        Int32Array.from([1, 4, 2, 2, 1, 1]),\n        Int32Array.from([2, 4, 1, 2, 1, 1]),\n        Int32Array.from([2, 2, 1, 1, 1, 4]),\n        Int32Array.from([4, 1, 3, 1, 1, 1]),\n        Int32Array.from([2, 4, 1, 1, 1, 2]),\n        Int32Array.from([1, 3, 4, 1, 1, 1]),\n        Int32Array.from([1, 1, 1, 2, 4, 2]),\n        Int32Array.from([1, 2, 1, 1, 4, 2]),\n        Int32Array.from([1, 2, 1, 2, 4, 1]),\n        Int32Array.from([1, 1, 4, 2, 1, 2]),\n        Int32Array.from([1, 2, 4, 1, 1, 2]),\n        Int32Array.from([1, 2, 4, 2, 1, 1]),\n        Int32Array.from([4, 1, 1, 2, 1, 2]),\n        Int32Array.from([4, 2, 1, 1, 1, 2]),\n        Int32Array.from([4, 2, 1, 2, 1, 1]),\n        Int32Array.from([2, 1, 2, 1, 4, 1]),\n        Int32Array.from([2, 1, 4, 1, 2, 1]),\n        Int32Array.from([4, 1, 2, 1, 2, 1]),\n        Int32Array.from([1, 1, 1, 1, 4, 3]),\n        Int32Array.from([1, 1, 1, 3, 4, 1]),\n        Int32Array.from([1, 3, 1, 1, 4, 1]),\n        Int32Array.from([1, 1, 4, 1, 1, 3]),\n        Int32Array.from([1, 1, 4, 3, 1, 1]),\n        Int32Array.from([4, 1, 1, 1, 1, 3]),\n        Int32Array.from([4, 1, 1, 3, 1, 1]),\n        Int32Array.from([1, 1, 3, 1, 4, 1]),\n        Int32Array.from([1, 1, 4, 1, 3, 1]),\n        Int32Array.from([3, 1, 1, 1, 4, 1]),\n        Int32Array.from([4, 1, 1, 1, 3, 1]),\n        Int32Array.from([2, 1, 1, 4, 1, 2]),\n        Int32Array.from([2, 1, 1, 2, 1, 4]),\n        Int32Array.from([2, 1, 1, 2, 3, 2]),\n        Int32Array.from([2, 3, 3, 1, 1, 1, 2]),\n    ];\n    Code128Reader.MAX_AVG_VARIANCE = 0.25;\n    Code128Reader.MAX_INDIVIDUAL_VARIANCE = 0.7;\n    Code128Reader.CODE_SHIFT = 98;\n    Code128Reader.CODE_CODE_C = 99;\n    Code128Reader.CODE_CODE_B = 100;\n    Code128Reader.CODE_CODE_A = 101;\n    Code128Reader.CODE_FNC_1 = 102;\n    Code128Reader.CODE_FNC_2 = 97;\n    Code128Reader.CODE_FNC_3 = 96;\n    Code128Reader.CODE_FNC_4_A = 101;\n    Code128Reader.CODE_FNC_4_B = 100;\n    Code128Reader.CODE_START_A = 103;\n    Code128Reader.CODE_START_B = 104;\n    Code128Reader.CODE_START_C = 105;\n    Code128Reader.CODE_STOP = 106;\n\n    /**\n     * <p>Decodes Code 39 barcodes. Supports \"Full ASCII Code 39\" if USE_CODE_39_EXTENDED_MODE is set.</p>\n     *\n     * @author Sean Owen\n     * @see Code93Reader\n     */\n    class Code39Reader extends OneDReader {\n        /**\n         * Creates a reader that assumes all encoded data is data, and does not treat the final\n         * character as a check digit. It will not decoded \"extended Code 39\" sequences.\n         */\n        // public Code39Reader() {\n        //   this(false);\n        // }\n        /**\n         * Creates a reader that can be configured to check the last character as a check digit.\n         * It will not decoded \"extended Code 39\" sequences.\n         *\n         * @param usingCheckDigit if true, treat the last data character as a check digit, not\n         * data, and verify that the checksum passes.\n         */\n        // public Code39Reader(boolean usingCheckDigit) {\n        //   this(usingCheckDigit, false);\n        // }\n        /**\n         * Creates a reader that can be configured to check the last character as a check digit,\n         * or optionally attempt to decode \"extended Code 39\" sequences that are used to encode\n         * the full ASCII character set.\n         *\n         * @param usingCheckDigit if true, treat the last data character as a check digit, not\n         * data, and verify that the checksum passes.\n         * @param extendedMode if true, will attempt to decode extended Code 39 sequences in the\n         * text.\n         */\n        constructor(usingCheckDigit = false, extendedMode = false) {\n            super();\n            this.usingCheckDigit = usingCheckDigit;\n            this.extendedMode = extendedMode;\n            this.decodeRowResult = '';\n            this.counters = new Int32Array(9);\n        }\n        decodeRow(rowNumber, row, hints) {\n            let theCounters = this.counters;\n            theCounters.fill(0);\n            this.decodeRowResult = '';\n            let start = Code39Reader.findAsteriskPattern(row, theCounters);\n            // Read off white space\n            let nextStart = row.getNextSet(start[1]);\n            let end = row.getSize();\n            let decodedChar;\n            let lastStart;\n            do {\n                Code39Reader.recordPattern(row, nextStart, theCounters);\n                let pattern = Code39Reader.toNarrowWidePattern(theCounters);\n                if (pattern < 0) {\n                    throw new NotFoundException();\n                }\n                decodedChar = Code39Reader.patternToChar(pattern);\n                this.decodeRowResult += decodedChar;\n                lastStart = nextStart;\n                for (let counter of theCounters) {\n                    nextStart += counter;\n                }\n                // Read off white space\n                nextStart = row.getNextSet(nextStart);\n            } while (decodedChar !== '*');\n            this.decodeRowResult = this.decodeRowResult.substring(0, this.decodeRowResult.length - 1); // remove asterisk\n            // Look for whitespace after pattern:\n            let lastPatternSize = 0;\n            for (let counter of theCounters) {\n                lastPatternSize += counter;\n            }\n            let whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize;\n            // If 50% of last pattern size, following last pattern, is not whitespace, fail\n            // (but if it's whitespace to the very end of the image, that's OK)\n            if (nextStart !== end && (whiteSpaceAfterEnd * 2) < lastPatternSize) {\n                throw new NotFoundException();\n            }\n            if (this.usingCheckDigit) {\n                let max = this.decodeRowResult.length - 1;\n                let total = 0;\n                for (let i = 0; i < max; i++) {\n                    total += Code39Reader.ALPHABET_STRING.indexOf(this.decodeRowResult.charAt(i));\n                }\n                if (this.decodeRowResult.charAt(max) !== Code39Reader.ALPHABET_STRING.charAt(total % 43)) {\n                    throw new ChecksumException();\n                }\n                this.decodeRowResult = this.decodeRowResult.substring(0, max);\n            }\n            if (this.decodeRowResult.length === 0) {\n                // false positive\n                throw new NotFoundException();\n            }\n            let resultString;\n            if (this.extendedMode) {\n                resultString = Code39Reader.decodeExtended(this.decodeRowResult);\n            }\n            else {\n                resultString = this.decodeRowResult;\n            }\n            let left = (start[1] + start[0]) / 2.0;\n            let right = lastStart + lastPatternSize / 2.0;\n            return new Result(resultString, null, 0, [new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber)], BarcodeFormat$1.CODE_39, new Date().getTime());\n        }\n        static findAsteriskPattern(row, counters) {\n            let width = row.getSize();\n            let rowOffset = row.getNextSet(0);\n            let counterPosition = 0;\n            let patternStart = rowOffset;\n            let isWhite = false;\n            let patternLength = counters.length;\n            for (let i = rowOffset; i < width; i++) {\n                if (row.get(i) !== isWhite) {\n                    counters[counterPosition]++;\n                }\n                else {\n                    if (counterPosition === patternLength - 1) {\n                        // Look for whitespace before start pattern, >= 50% of width of start pattern\n                        if (this.toNarrowWidePattern(counters) === Code39Reader.ASTERISK_ENCODING &&\n                            row.isRange(Math.max(0, patternStart - Math.floor((i - patternStart) / 2)), patternStart, false)) {\n                            return [patternStart, i];\n                        }\n                        patternStart += counters[0] + counters[1];\n                        counters.copyWithin(0, 2, 2 + counterPosition - 1);\n                        counters[counterPosition - 1] = 0;\n                        counters[counterPosition] = 0;\n                        counterPosition--;\n                    }\n                    else {\n                        counterPosition++;\n                    }\n                    counters[counterPosition] = 1;\n                    isWhite = !isWhite;\n                }\n            }\n            throw new NotFoundException();\n        }\n        // For efficiency, returns -1 on failure. Not throwing here saved as many as 700 exceptions\n        // per image when using some of our blackbox images.\n        static toNarrowWidePattern(counters) {\n            let numCounters = counters.length;\n            let maxNarrowCounter = 0;\n            let wideCounters;\n            do {\n                let minCounter = 0x7fffffff;\n                for (let counter of counters) {\n                    if (counter < minCounter && counter > maxNarrowCounter) {\n                        minCounter = counter;\n                    }\n                }\n                maxNarrowCounter = minCounter;\n                wideCounters = 0;\n                let totalWideCountersWidth = 0;\n                let pattern = 0;\n                for (let i = 0; i < numCounters; i++) {\n                    let counter = counters[i];\n                    if (counter > maxNarrowCounter) {\n                        pattern |= 1 << (numCounters - 1 - i);\n                        wideCounters++;\n                        totalWideCountersWidth += counter;\n                    }\n                }\n                if (wideCounters === 3) {\n                    // Found 3 wide counters, but are they close enough in width?\n                    // We can perform a cheap, conservative check to see if any individual\n                    // counter is more than 1.5 times the average:\n                    for (let i = 0; i < numCounters && wideCounters > 0; i++) {\n                        let counter = counters[i];\n                        if (counter > maxNarrowCounter) {\n                            wideCounters--;\n                            // totalWideCountersWidth = 3 * average, so this checks if counter >= 3/2 * average\n                            if ((counter * 2) >= totalWideCountersWidth) {\n                                return -1;\n                            }\n                        }\n                    }\n                    return pattern;\n                }\n            } while (wideCounters > 3);\n            return -1;\n        }\n        static patternToChar(pattern) {\n            for (let i = 0; i < Code39Reader.CHARACTER_ENCODINGS.length; i++) {\n                if (Code39Reader.CHARACTER_ENCODINGS[i] === pattern) {\n                    return Code39Reader.ALPHABET_STRING.charAt(i);\n                }\n            }\n            if (pattern === Code39Reader.ASTERISK_ENCODING) {\n                return '*';\n            }\n            throw new NotFoundException();\n        }\n        static decodeExtended(encoded) {\n            let length = encoded.length;\n            let decoded = '';\n            for (let i = 0; i < length; i++) {\n                let c = encoded.charAt(i);\n                if (c === '+' || c === '$' || c === '%' || c === '/') {\n                    let next = encoded.charAt(i + 1);\n                    let decodedChar = '\\0';\n                    switch (c) {\n                        case '+':\n                            // +A to +Z map to a to z\n                            if (next >= 'A' && next <= 'Z') {\n                                decodedChar = String.fromCharCode(next.charCodeAt(0) + 32);\n                            }\n                            else {\n                                throw new FormatException();\n                            }\n                            break;\n                        case '$':\n                            // $A to $Z map to control codes SH to SB\n                            if (next >= 'A' && next <= 'Z') {\n                                decodedChar = String.fromCharCode(next.charCodeAt(0) - 64);\n                            }\n                            else {\n                                throw new FormatException();\n                            }\n                            break;\n                        case '%':\n                            // %A to %E map to control codes ESC to US\n                            if (next >= 'A' && next <= 'E') {\n                                decodedChar = String.fromCharCode(next.charCodeAt(0) - 38);\n                            }\n                            else if (next >= 'F' && next <= 'J') {\n                                decodedChar = String.fromCharCode(next.charCodeAt(0) - 11);\n                            }\n                            else if (next >= 'K' && next <= 'O') {\n                                decodedChar = String.fromCharCode(next.charCodeAt(0) + 16);\n                            }\n                            else if (next >= 'P' && next <= 'T') {\n                                decodedChar = String.fromCharCode(next.charCodeAt(0) + 43);\n                            }\n                            else if (next === 'U') {\n                                decodedChar = '\\0';\n                            }\n                            else if (next === 'V') {\n                                decodedChar = '@';\n                            }\n                            else if (next === 'W') {\n                                decodedChar = '`';\n                            }\n                            else if (next === 'X' || next === 'Y' || next === 'Z') {\n                                decodedChar = '\\x7f';\n                            }\n                            else {\n                                throw new FormatException();\n                            }\n                            break;\n                        case '/':\n                            // /A to /O map to ! to , and /Z maps to :\n                            if (next >= 'A' && next <= 'O') {\n                                decodedChar = String.fromCharCode(next.charCodeAt(0) - 32);\n                            }\n                            else if (next === 'Z') {\n                                decodedChar = ':';\n                            }\n                            else {\n                                throw new FormatException();\n                            }\n                            break;\n                    }\n                    decoded += decodedChar;\n                    // bump up i again since we read two characters\n                    i++;\n                }\n                else {\n                    decoded += c;\n                }\n            }\n            return decoded;\n        }\n    }\n    Code39Reader.ALPHABET_STRING = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%';\n    /**\n     * These represent the encodings of characters, as patterns of wide and narrow bars.\n     * The 9 least-significant bits of each int correspond to the pattern of wide and narrow,\n     * with 1s representing \"wide\" and 0s representing narrow.\n     */\n    Code39Reader.CHARACTER_ENCODINGS = [\n        0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064,\n        0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C,\n        0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016,\n        0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x0A8,\n        0x0A2, 0x08A, 0x02A // /-%\n    ];\n    Code39Reader.ASTERISK_ENCODING = 0x094;\n\n    /**\n     * <p>Decodes ITF barcodes.</p>\n     *\n     * @author Tjieco\n     */\n    class ITFReader extends OneDReader {\n        constructor() {\n            // private static W = 3; // Pixel width of a 3x wide line\n            // private static w = 2; // Pixel width of a 2x wide line\n            // private static N = 1; // Pixed width of a narrow line\n            super(...arguments);\n            // Stores the actual narrow line width of the image being decoded.\n            this.narrowLineWidth = -1;\n        }\n        // See ITFWriter.PATTERNS\n        /*\n      \n        /!**\n         * Patterns of Wide / Narrow lines to indicate each digit\n         *!/\n        */\n        decodeRow(rowNumber, row, hints) {\n            // Find out where the Middle section (payload) starts & ends\n            let startRange = this.decodeStart(row);\n            let endRange = this.decodeEnd(row);\n            let result = new StringBuilder();\n            ITFReader.decodeMiddle(row, startRange[1], endRange[0], result);\n            let resultString = result.toString();\n            let allowedLengths = null;\n            if (hints != null) {\n                allowedLengths = hints.get(DecodeHintType$1.ALLOWED_LENGTHS);\n            }\n            if (allowedLengths == null) {\n                allowedLengths = ITFReader.DEFAULT_ALLOWED_LENGTHS;\n            }\n            // To avoid false positives with 2D barcodes (and other patterns), make\n            // an assumption that the decoded string must be a 'standard' length if it's short\n            let length = resultString.length;\n            let lengthOK = false;\n            let maxAllowedLength = 0;\n            for (let value of allowedLengths) {\n                if (length === value) {\n                    lengthOK = true;\n                    break;\n                }\n                if (value > maxAllowedLength) {\n                    maxAllowedLength = value;\n                }\n            }\n            if (!lengthOK && length > maxAllowedLength) {\n                lengthOK = true;\n            }\n            if (!lengthOK) {\n                throw new FormatException();\n            }\n            const points = [new ResultPoint(startRange[1], rowNumber), new ResultPoint(endRange[0], rowNumber)];\n            let resultReturn = new Result(resultString, null, // no natural byte representation for these barcodes\n            0, points, BarcodeFormat$1.ITF, new Date().getTime());\n            return resultReturn;\n        }\n        /*\n        /!**\n         * @param row          row of black/white values to search\n         * @param payloadStart offset of start pattern\n         * @param resultString {@link StringBuilder} to append decoded chars to\n         * @throws NotFoundException if decoding could not complete successfully\n         *!/*/\n        static decodeMiddle(row, payloadStart, payloadEnd, resultString) {\n            // Digits are interleaved in pairs - 5 black lines for one digit, and the\n            // 5\n            // interleaved white lines for the second digit.\n            // Therefore, need to scan 10 lines and then\n            // split these into two arrays\n            let counterDigitPair = new Int32Array(10); // 10\n            let counterBlack = new Int32Array(5); // 5\n            let counterWhite = new Int32Array(5); // 5\n            counterDigitPair.fill(0);\n            counterBlack.fill(0);\n            counterWhite.fill(0);\n            while (payloadStart < payloadEnd) {\n                // Get 10 runs of black/white.\n                OneDReader.recordPattern(row, payloadStart, counterDigitPair);\n                // Split them into each array\n                for (let k = 0; k < 5; k++) {\n                    let twoK = 2 * k;\n                    counterBlack[k] = counterDigitPair[twoK];\n                    counterWhite[k] = counterDigitPair[twoK + 1];\n                }\n                let bestMatch = ITFReader.decodeDigit(counterBlack);\n                resultString.append(bestMatch.toString());\n                bestMatch = this.decodeDigit(counterWhite);\n                resultString.append(bestMatch.toString());\n                counterDigitPair.forEach(function (counterDigit) {\n                    payloadStart += counterDigit;\n                });\n            }\n        }\n        /*/!**\n         * Identify where the start of the middle / payload section starts.\n         *\n         * @param row row of black/white values to search\n         * @return Array, containing index of start of 'start block' and end of\n         *         'start block'\n         *!/*/\n        decodeStart(row) {\n            let endStart = ITFReader.skipWhiteSpace(row);\n            let startPattern = ITFReader.findGuardPattern(row, endStart, ITFReader.START_PATTERN);\n            // Determine the width of a narrow line in pixels. We can do this by\n            // getting the width of the start pattern and dividing by 4 because its\n            // made up of 4 narrow lines.\n            this.narrowLineWidth = (startPattern[1] - startPattern[0]) / 4;\n            this.validateQuietZone(row, startPattern[0]);\n            return startPattern;\n        }\n        /*/!**\n         * The start & end patterns must be pre/post fixed by a quiet zone. This\n         * zone must be at least 10 times the width of a narrow line.  Scan back until\n         * we either get to the start of the barcode or match the necessary number of\n         * quiet zone pixels.\n         *\n         * Note: Its assumed the row is reversed when using this method to find\n         * quiet zone after the end pattern.\n         *\n         * ref: http://www.barcode-1.net/i25code.html\n         *\n         * @param row bit array representing the scanned barcode.\n         * @param startPattern index into row of the start or end pattern.\n         * @throws NotFoundException if the quiet zone cannot be found\n         *!/*/\n        validateQuietZone(row, startPattern) {\n            let quietCount = this.narrowLineWidth * 10; // expect to find this many pixels of quiet zone\n            // if there are not so many pixel at all let's try as many as possible\n            quietCount = quietCount < startPattern ? quietCount : startPattern;\n            for (let i = startPattern - 1; quietCount > 0 && i >= 0; i--) {\n                if (row.get(i)) {\n                    break;\n                }\n                quietCount--;\n            }\n            if (quietCount !== 0) {\n                // Unable to find the necessary number of quiet zone pixels.\n                throw new NotFoundException();\n            }\n        }\n        /*\n        /!**\n         * Skip all whitespace until we get to the first black line.\n         *\n         * @param row row of black/white values to search\n         * @return index of the first black line.\n         * @throws NotFoundException Throws exception if no black lines are found in the row\n         *!/*/\n        static skipWhiteSpace(row) {\n            const width = row.getSize();\n            const endStart = row.getNextSet(0);\n            if (endStart === width) {\n                throw new NotFoundException();\n            }\n            return endStart;\n        }\n        /*/!**\n         * Identify where the end of the middle / payload section ends.\n         *\n         * @param row row of black/white values to search\n         * @return Array, containing index of start of 'end block' and end of 'end\n         *         block'\n         *!/*/\n        decodeEnd(row) {\n            // For convenience, reverse the row and then\n            // search from 'the start' for the end block\n            row.reverse();\n            try {\n                let endStart = ITFReader.skipWhiteSpace(row);\n                let endPattern;\n                try {\n                    endPattern = ITFReader.findGuardPattern(row, endStart, ITFReader.END_PATTERN_REVERSED[0]);\n                }\n                catch (error) {\n                    if (error instanceof NotFoundException) {\n                        endPattern = ITFReader.findGuardPattern(row, endStart, ITFReader.END_PATTERN_REVERSED[1]);\n                    }\n                }\n                // The start & end patterns must be pre/post fixed by a quiet zone. This\n                // zone must be at least 10 times the width of a narrow line.\n                // ref: http://www.barcode-1.net/i25code.html\n                this.validateQuietZone(row, endPattern[0]);\n                // Now recalculate the indices of where the 'endblock' starts & stops to\n                // accommodate\n                // the reversed nature of the search\n                let temp = endPattern[0];\n                endPattern[0] = row.getSize() - endPattern[1];\n                endPattern[1] = row.getSize() - temp;\n                return endPattern;\n            }\n            finally {\n                // Put the row back the right way.\n                row.reverse();\n            }\n        }\n        /*\n        /!**\n         * @param row       row of black/white values to search\n         * @param rowOffset position to start search\n         * @param pattern   pattern of counts of number of black and white pixels that are\n         *                  being searched for as a pattern\n         * @return start/end horizontal offset of guard pattern, as an array of two\n         *         ints\n         * @throws NotFoundException if pattern is not found\n         *!/*/\n        static findGuardPattern(row, rowOffset, pattern) {\n            let patternLength = pattern.length;\n            let counters = new Int32Array(patternLength);\n            let width = row.getSize();\n            let isWhite = false;\n            let counterPosition = 0;\n            let patternStart = rowOffset;\n            counters.fill(0);\n            for (let x = rowOffset; x < width; x++) {\n                if (row.get(x) !== isWhite) {\n                    counters[counterPosition]++;\n                }\n                else {\n                    if (counterPosition === patternLength - 1) {\n                        if (OneDReader.patternMatchVariance(counters, pattern, ITFReader.MAX_INDIVIDUAL_VARIANCE) < ITFReader.MAX_AVG_VARIANCE) {\n                            return [patternStart, x];\n                        }\n                        patternStart += counters[0] + counters[1];\n                        System.arraycopy(counters, 2, counters, 0, counterPosition - 1);\n                        counters[counterPosition - 1] = 0;\n                        counters[counterPosition] = 0;\n                        counterPosition--;\n                    }\n                    else {\n                        counterPosition++;\n                    }\n                    counters[counterPosition] = 1;\n                    isWhite = !isWhite;\n                }\n            }\n            throw new NotFoundException();\n        }\n        /*/!**\n         * Attempts to decode a sequence of ITF black/white lines into single\n         * digit.\n         *\n         * @param counters the counts of runs of observed black/white/black/... values\n         * @return The decoded digit\n         * @throws NotFoundException if digit cannot be decoded\n         *!/*/\n        static decodeDigit(counters) {\n            let bestVariance = ITFReader.MAX_AVG_VARIANCE; // worst variance we'll accept\n            let bestMatch = -1;\n            let max = ITFReader.PATTERNS.length;\n            for (let i = 0; i < max; i++) {\n                let pattern = ITFReader.PATTERNS[i];\n                let variance = OneDReader.patternMatchVariance(counters, pattern, ITFReader.MAX_INDIVIDUAL_VARIANCE);\n                if (variance < bestVariance) {\n                    bestVariance = variance;\n                    bestMatch = i;\n                }\n                else if (variance === bestVariance) {\n                    // if we find a second 'best match' with the same variance, we can not reliably report to have a suitable match\n                    bestMatch = -1;\n                }\n            }\n            if (bestMatch >= 0) {\n                return bestMatch % 10;\n            }\n            else {\n                throw new NotFoundException();\n            }\n        }\n    }\n    ITFReader.PATTERNS = [\n        Int32Array.from([1, 1, 2, 2, 1]),\n        Int32Array.from([2, 1, 1, 1, 2]),\n        Int32Array.from([1, 2, 1, 1, 2]),\n        Int32Array.from([2, 2, 1, 1, 1]),\n        Int32Array.from([1, 1, 2, 1, 2]),\n        Int32Array.from([2, 1, 2, 1, 1]),\n        Int32Array.from([1, 2, 2, 1, 1]),\n        Int32Array.from([1, 1, 1, 2, 2]),\n        Int32Array.from([2, 1, 1, 2, 1]),\n        Int32Array.from([1, 2, 1, 2, 1]),\n        Int32Array.from([1, 1, 3, 3, 1]),\n        Int32Array.from([3, 1, 1, 1, 3]),\n        Int32Array.from([1, 3, 1, 1, 3]),\n        Int32Array.from([3, 3, 1, 1, 1]),\n        Int32Array.from([1, 1, 3, 1, 3]),\n        Int32Array.from([3, 1, 3, 1, 1]),\n        Int32Array.from([1, 3, 3, 1, 1]),\n        Int32Array.from([1, 1, 1, 3, 3]),\n        Int32Array.from([3, 1, 1, 3, 1]),\n        Int32Array.from([1, 3, 1, 3, 1]) // 9\n    ];\n    ITFReader.MAX_AVG_VARIANCE = 0.38;\n    ITFReader.MAX_INDIVIDUAL_VARIANCE = 0.5;\n    /* /!** Valid ITF lengths. Anything longer than the largest value is also allowed. *!/*/\n    ITFReader.DEFAULT_ALLOWED_LENGTHS = [6, 8, 10, 12, 14];\n    /*/!**\n     * Start/end guard pattern.\n     *\n     * Note: The end pattern is reversed because the row is reversed before\n     * searching for the END_PATTERN\n     *!/*/\n    ITFReader.START_PATTERN = Int32Array.from([1, 1, 1, 1]);\n    ITFReader.END_PATTERN_REVERSED = [\n        Int32Array.from([1, 1, 2]),\n        Int32Array.from([1, 1, 3]) // 3x\n    ];\n\n    /**\n     * <p>Encapsulates functionality and implementation that is common to UPC and EAN families\n     * of one-dimensional barcodes.</p>\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @author Sean Owen\n     * @author alasdair@google.com (Alasdair Mackintosh)\n     */\n    class AbstractUPCEANReader extends OneDReader {\n        constructor() {\n            super(...arguments);\n            this.decodeRowStringBuffer = '';\n        }\n\n        static findStartGuardPattern(row) {\n            let foundStart = false;\n            let startRange;\n            let nextStart = 0;\n            let counters = Int32Array.from([0, 0, 0]);\n            while (!foundStart) {\n                counters = Int32Array.from([0, 0, 0]);\n                startRange = AbstractUPCEANReader.findGuardPattern(row, nextStart, false, this.START_END_PATTERN, counters);\n                let start = startRange[0];\n                nextStart = startRange[1];\n                let quietStart = start - (nextStart - start);\n                if (quietStart >= 0) {\n                    foundStart = row.isRange(quietStart, start, false);\n                }\n            }\n            return startRange;\n        }\n        static checkChecksum(s) {\n            return AbstractUPCEANReader.checkStandardUPCEANChecksum(s);\n        }\n        static checkStandardUPCEANChecksum(s) {\n            let length = s.length;\n            if (length === 0)\n                return false;\n            let check = parseInt(s.charAt(length - 1), 10);\n            return AbstractUPCEANReader.getStandardUPCEANChecksum(s.substring(0, length - 1)) === check;\n        }\n        static getStandardUPCEANChecksum(s) {\n            let length = s.length;\n            let sum = 0;\n            for (let i = length - 1; i >= 0; i -= 2) {\n                let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n                if (digit < 0 || digit > 9) {\n                    throw new FormatException();\n                }\n                sum += digit;\n            }\n            sum *= 3;\n            for (let i = length - 2; i >= 0; i -= 2) {\n                let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n                if (digit < 0 || digit > 9) {\n                    throw new FormatException();\n                }\n                sum += digit;\n            }\n            return (1000 - sum) % 10;\n        }\n        static decodeEnd(row, endStart) {\n            return AbstractUPCEANReader.findGuardPattern(row, endStart, false, AbstractUPCEANReader.START_END_PATTERN, new Int32Array(AbstractUPCEANReader.START_END_PATTERN.length).fill(0));\n        }\n        /**\n         * @throws NotFoundException\n         */\n        static findGuardPatternWithoutCounters(row, rowOffset, whiteFirst, pattern) {\n            return this.findGuardPattern(row, rowOffset, whiteFirst, pattern, new Int32Array(pattern.length));\n        }\n        /**\n         * @param row row of black/white values to search\n         * @param rowOffset position to start search\n         * @param whiteFirst if true, indicates that the pattern specifies white/black/white/...\n         * pixel counts, otherwise, it is interpreted as black/white/black/...\n         * @param pattern pattern of counts of number of black and white pixels that are being\n         * searched for as a pattern\n         * @param counters array of counters, as long as pattern, to re-use\n         * @return start/end horizontal offset of guard pattern, as an array of two ints\n         * @throws NotFoundException if pattern is not found\n         */\n        static findGuardPattern(row, rowOffset, whiteFirst, pattern, counters) {\n            let width = row.getSize();\n            rowOffset = whiteFirst ? row.getNextUnset(rowOffset) : row.getNextSet(rowOffset);\n            let counterPosition = 0;\n            let patternStart = rowOffset;\n            let patternLength = pattern.length;\n            let isWhite = whiteFirst;\n            for (let x = rowOffset; x < width; x++) {\n                if (row.get(x) !== isWhite) {\n                    counters[counterPosition]++;\n                }\n                else {\n                    if (counterPosition === patternLength - 1) {\n                        if (OneDReader.patternMatchVariance(counters, pattern, AbstractUPCEANReader.MAX_INDIVIDUAL_VARIANCE) < AbstractUPCEANReader.MAX_AVG_VARIANCE) {\n                            return Int32Array.from([patternStart, x]);\n                        }\n                        patternStart += counters[0] + counters[1];\n                        let slice = counters.slice(2, counters.length - 1);\n                        for (let i = 0; i < counterPosition - 1; i++) {\n                            counters[i] = slice[i];\n                        }\n                        counters[counterPosition - 1] = 0;\n                        counters[counterPosition] = 0;\n                        counterPosition--;\n                    }\n                    else {\n                        counterPosition++;\n                    }\n                    counters[counterPosition] = 1;\n                    isWhite = !isWhite;\n                }\n            }\n            throw new NotFoundException();\n        }\n        static decodeDigit(row, counters, rowOffset, patterns) {\n            this.recordPattern(row, rowOffset, counters);\n            let bestVariance = this.MAX_AVG_VARIANCE;\n            let bestMatch = -1;\n            let max = patterns.length;\n            for (let i = 0; i < max; i++) {\n                let pattern = patterns[i];\n                let variance = OneDReader.patternMatchVariance(counters, pattern, AbstractUPCEANReader.MAX_INDIVIDUAL_VARIANCE);\n                if (variance < bestVariance) {\n                    bestVariance = variance;\n                    bestMatch = i;\n                }\n            }\n            if (bestMatch >= 0) {\n                return bestMatch;\n            }\n            else {\n                throw new NotFoundException();\n            }\n        }\n    }\n    // These two values are critical for determining how permissive the decoding will be.\n    // We've arrived at these values through a lot of trial and error. Setting them any higher\n    // lets false positives creep in quickly.\n    AbstractUPCEANReader.MAX_AVG_VARIANCE = 0.48;\n    AbstractUPCEANReader.MAX_INDIVIDUAL_VARIANCE = 0.7;\n    /**\n     * Start/end guard pattern.\n     */\n    AbstractUPCEANReader.START_END_PATTERN = Int32Array.from([1, 1, 1]);\n    /**\n     * Pattern marking the middle of a UPC/EAN pattern, separating the two halves.\n     */\n    AbstractUPCEANReader.MIDDLE_PATTERN = Int32Array.from([1, 1, 1, 1, 1]);\n    /**\n     * end guard pattern.\n     */\n    AbstractUPCEANReader.END_PATTERN = Int32Array.from([1, 1, 1, 1, 1, 1]);\n    /**\n     * \"Odd\", or \"L\" patterns used to encode UPC/EAN digits.\n     */\n    AbstractUPCEANReader.L_PATTERNS = [\n        Int32Array.from([3, 2, 1, 1]),\n        Int32Array.from([2, 2, 2, 1]),\n        Int32Array.from([2, 1, 2, 2]),\n        Int32Array.from([1, 4, 1, 1]),\n        Int32Array.from([1, 1, 3, 2]),\n        Int32Array.from([1, 2, 3, 1]),\n        Int32Array.from([1, 1, 1, 4]),\n        Int32Array.from([1, 3, 1, 2]),\n        Int32Array.from([1, 2, 1, 3]),\n        Int32Array.from([3, 1, 1, 2]),\n    ];\n\n    /**\n     * @see UPCEANExtension2Support\n     */\n    class UPCEANExtension5Support {\n        constructor() {\n            this.CHECK_DIGIT_ENCODINGS = [0x18, 0x14, 0x12, 0x11, 0x0C, 0x06, 0x03, 0x0A, 0x09, 0x05];\n            this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]);\n            this.decodeRowStringBuffer = '';\n        }\n        decodeRow(rowNumber, row, extensionStartRange) {\n            let result = this.decodeRowStringBuffer;\n            let end = this.decodeMiddle(row, extensionStartRange, result);\n            let resultString = result.toString();\n            let extensionData = UPCEANExtension5Support.parseExtensionString(resultString);\n            let resultPoints = [\n                new ResultPoint((extensionStartRange[0] + extensionStartRange[1]) / 2.0, rowNumber),\n                new ResultPoint(end, rowNumber)\n            ];\n            let extensionResult = new Result(resultString, null, 0, resultPoints, BarcodeFormat$1.UPC_EAN_EXTENSION, new Date().getTime());\n            if (extensionData != null) {\n                extensionResult.putAllMetadata(extensionData);\n            }\n            return extensionResult;\n        }\n        decodeMiddle(row, startRange, resultString) {\n            let counters = this.decodeMiddleCounters;\n            counters[0] = 0;\n            counters[1] = 0;\n            counters[2] = 0;\n            counters[3] = 0;\n            let end = row.getSize();\n            let rowOffset = startRange[1];\n            let lgPatternFound = 0;\n            for (let x = 0; x < 5 && rowOffset < end; x++) {\n                let bestMatch = AbstractUPCEANReader.decodeDigit(\n                    row,\n                    counters,\n                    rowOffset,\n                    AbstractUPCEANReader.L_AND_G_PATTERNS);\n                resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch % 10));\n                for (let counter of counters) {\n                    rowOffset += counter;\n                }\n                if (bestMatch >= 10) {\n                    lgPatternFound |= 1 << (4 - x);\n                }\n                if (x !== 4) {\n                    // Read off separator if not last\n                    rowOffset = row.getNextSet(rowOffset);\n                    rowOffset = row.getNextUnset(rowOffset);\n                }\n            }\n            if (resultString.length !== 5) {\n                throw new NotFoundException();\n            }\n            let checkDigit = this.determineCheckDigit(lgPatternFound);\n            if (UPCEANExtension5Support.extensionChecksum(resultString.toString()) !== checkDigit) {\n                throw new NotFoundException();\n            }\n            return rowOffset;\n        }\n        static extensionChecksum(s) {\n            let length = s.length;\n            let sum = 0;\n            for (let i = length - 2; i >= 0; i -= 2) {\n                sum += s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n            }\n            sum *= 3;\n            for (let i = length - 1; i >= 0; i -= 2) {\n                sum += s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n            }\n            sum *= 3;\n            return sum % 10;\n        }\n        determineCheckDigit(lgPatternFound) {\n            for (let d = 0; d < 10; d++) {\n                if (lgPatternFound === this.CHECK_DIGIT_ENCODINGS[d]) {\n                    return d;\n                }\n            }\n            throw new NotFoundException();\n        }\n        static parseExtensionString(raw) {\n            if (raw.length !== 5) {\n                return null;\n            }\n            let value = UPCEANExtension5Support.parseExtension5String(raw);\n            if (value == null) {\n                return null;\n            }\n            return new Map([[ResultMetadataType$1.SUGGESTED_PRICE, value]]);\n        }\n        static parseExtension5String(raw) {\n            let currency;\n            switch (raw.charAt(0)) {\n                case '0':\n                    currency = '£';\n                    break;\n                case '5':\n                    currency = '$';\n                    break;\n                case '9':\n                    // Reference: http://www.jollytech.com\n                    switch (raw) {\n                        case '90000':\n                            // No suggested retail price\n                            return null;\n                        case '99991':\n                            // Complementary\n                            return '0.00';\n                        case '99990':\n                            return 'Used';\n                    }\n                    // Otherwise... unknown currency?\n                    currency = '';\n                    break;\n                default:\n                    currency = '';\n                    break;\n            }\n            let rawAmount = parseInt(raw.substring(1));\n            let unitsString = (rawAmount / 100).toString();\n            let hundredths = rawAmount % 100;\n            let hundredthsString = hundredths < 10 ? '0' + hundredths : hundredths.toString(); // fixme\n            return currency + unitsString + '.' + hundredthsString;\n        }\n    }\n\n    /**\n     * @see UPCEANExtension5Support\n     */\n    class UPCEANExtension2Support {\n        constructor() {\n            this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]);\n            this.decodeRowStringBuffer = '';\n        }\n        decodeRow(rowNumber, row, extensionStartRange) {\n            let result = this.decodeRowStringBuffer;\n            let end = this.decodeMiddle(row, extensionStartRange, result);\n            let resultString = result.toString();\n            let extensionData = UPCEANExtension2Support.parseExtensionString(resultString);\n            let resultPoints = [\n                new ResultPoint((extensionStartRange[0] + extensionStartRange[1]) / 2.0, rowNumber),\n                new ResultPoint(end, rowNumber)\n            ];\n            let extensionResult = new Result(resultString, null, 0, resultPoints, BarcodeFormat$1.UPC_EAN_EXTENSION, new Date().getTime());\n            if (extensionData != null) {\n                extensionResult.putAllMetadata(extensionData);\n            }\n            return extensionResult;\n        }\n        decodeMiddle(row, startRange, resultString) {\n            let counters = this.decodeMiddleCounters;\n            counters[0] = 0;\n            counters[1] = 0;\n            counters[2] = 0;\n            counters[3] = 0;\n            let end = row.getSize();\n            let rowOffset = startRange[1];\n            let checkParity = 0;\n            for (let x = 0; x < 2 && rowOffset < end; x++) {\n                let bestMatch = AbstractUPCEANReader.decodeDigit(row, counters, rowOffset, AbstractUPCEANReader.L_AND_G_PATTERNS);\n                resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch % 10));\n                for (let counter of counters) {\n                    rowOffset += counter;\n                }\n                if (bestMatch >= 10) {\n                    checkParity |= 1 << (1 - x);\n                }\n                if (x !== 1) {\n                    // Read off separator if not last\n                    rowOffset = row.getNextSet(rowOffset);\n                    rowOffset = row.getNextUnset(rowOffset);\n                }\n            }\n            if (resultString.length !== 2) {\n                throw new NotFoundException();\n            }\n            if (parseInt(resultString.toString()) % 4 !== checkParity) {\n                throw new NotFoundException();\n            }\n            return rowOffset;\n        }\n        static parseExtensionString(raw) {\n            if (raw.length !== 2) {\n                return null;\n            }\n            return new Map([[ResultMetadataType$1.ISSUE_NUMBER, parseInt(raw)]]);\n        }\n    }\n\n    class UPCEANExtensionSupport {\n        static decodeRow(rowNumber, row, rowOffset) {\n            let extensionStartRange = AbstractUPCEANReader.findGuardPattern(\n                row,\n                rowOffset,\n                false,\n                this.EXTENSION_START_PATTERN,\n                new Int32Array(this.EXTENSION_START_PATTERN.length).fill(0));\n            try {\n                // return null;\n                let fiveSupport = new UPCEANExtension5Support();\n                return fiveSupport.decodeRow(rowNumber, row, extensionStartRange);\n            }\n            catch (err) {\n                // return null;\n                let twoSupport = new UPCEANExtension2Support();\n                return twoSupport.decodeRow(rowNumber, row, extensionStartRange);\n            }\n        }\n    }\n    UPCEANExtensionSupport.EXTENSION_START_PATTERN = Int32Array.from([1, 1, 2]);\n\n    /**\n     * <p>Encapsulates functionality and implementation that is common to UPC and EAN families\n     * of one-dimensional barcodes.</p>\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @author Sean Owen\n     * @author alasdair@google.com (Alasdair Mackintosh)\n     */\n    class UPCEANReader extends AbstractUPCEANReader {\n        constructor() {\n            super();\n            this.decodeRowStringBuffer = '';\n            UPCEANReader.L_AND_G_PATTERNS = UPCEANReader.L_PATTERNS.map(arr => Int32Array.from(arr));\n            for (let i = 10; i < 20; i++) {\n                let widths = UPCEANReader.L_PATTERNS[i - 10];\n                let reversedWidths = new Int32Array(widths.length);\n                for (let j = 0; j < widths.length; j++) {\n                    reversedWidths[j] = widths[widths.length - j - 1];\n                }\n                UPCEANReader.L_AND_G_PATTERNS[i] = reversedWidths;\n            }\n        }\n        decodeRow(rowNumber, row, hints) {\n            let startGuardRange = UPCEANReader.findStartGuardPattern(row);\n            let resultPointCallback = hints == null ? null : hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n            if (resultPointCallback != null) {\n                const resultPoint = new ResultPoint((startGuardRange[0] + startGuardRange[1]) / 2.0, rowNumber);\n                resultPointCallback.foundPossibleResultPoint(resultPoint);\n            }\n            let budello = this.decodeMiddle(row, startGuardRange, this.decodeRowStringBuffer);\n            let endStart = budello.rowOffset;\n            let result = budello.resultString;\n            if (resultPointCallback != null) {\n                const resultPoint = new ResultPoint(endStart, rowNumber);\n                resultPointCallback.foundPossibleResultPoint(resultPoint);\n            }\n            let endRange = this.decodeEnd(row, endStart);\n            if (resultPointCallback != null) {\n                const resultPoint = new ResultPoint((endRange[0] + endRange[1]) / 2.0, rowNumber);\n                resultPointCallback.foundPossibleResultPoint(resultPoint);\n            }\n            // Make sure there is a quiet zone at least as big as the end pattern after the barcode. The\n            // spec might want more whitespace, but in practice this is the maximum we can count on.\n            let end = endRange[1];\n            let quietEnd = end + (end - endRange[0]);\n            if (quietEnd >= row.getSize() || !row.isRange(end, quietEnd, false)) {\n                throw new NotFoundException();\n            }\n            let resultString = result.toString();\n            // UPC/EAN should never be less than 8 chars anyway\n            if (resultString.length < 8) {\n                throw new FormatException();\n            }\n            if (!UPCEANReader.checkChecksum(resultString)) {\n                throw new ChecksumException();\n            }\n            let left = (startGuardRange[1] + startGuardRange[0]) / 2.0;\n            let right = (endRange[1] + endRange[0]) / 2.0;\n            let format = this.getBarcodeFormat();\n            let resultPoint = [new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber)];\n            let decodeResult = new Result(resultString, null, 0, resultPoint, format, new Date().getTime());\n            let extensionLength = 0;\n            try {\n                let extensionResult = UPCEANExtensionSupport.decodeRow(rowNumber, row, endRange[1]);\n                decodeResult.putMetadata(ResultMetadataType$1.UPC_EAN_EXTENSION, extensionResult.getText());\n                decodeResult.putAllMetadata(extensionResult.getResultMetadata());\n                decodeResult.addResultPoints(extensionResult.getResultPoints());\n                extensionLength = extensionResult.getText().length;\n            }\n            catch (ignoreError) {}\n            let allowedExtensions = hints == null ? null : hints.get(DecodeHintType$1.ALLOWED_EAN_EXTENSIONS);\n            if (allowedExtensions != null) {\n                let valid = false;\n                for (let length in allowedExtensions) {\n                    if (extensionLength.toString() === length) { // check me\n                        valid = true;\n                        break;\n                    }\n                }\n                if (!valid) {\n                    throw new NotFoundException();\n                }\n            }\n            return decodeResult;\n        }\n        decodeEnd(row, endStart) {\n            return UPCEANReader.findGuardPattern(\n                row, endStart, false, UPCEANReader.START_END_PATTERN,\n                new Int32Array(UPCEANReader.START_END_PATTERN.length).fill(0));\n        }\n        static checkChecksum(s) {\n            return UPCEANReader.checkStandardUPCEANChecksum(s);\n        }\n        static checkStandardUPCEANChecksum(s) {\n            let length = s.length;\n            if (length === 0)\n                return false;\n            let check = parseInt(s.charAt(length - 1), 10);\n            return UPCEANReader.getStandardUPCEANChecksum(s.substring(0, length - 1)) === check;\n        }\n        static getStandardUPCEANChecksum(s) {\n            let length = s.length;\n            let sum = 0;\n            for (let i = length - 1; i >= 0; i -= 2) {\n                let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n                if (digit < 0 || digit > 9) {\n                    throw new FormatException();\n                }\n                sum += digit;\n            }\n            sum *= 3;\n            for (let i = length - 2; i >= 0; i -= 2) {\n                let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n                if (digit < 0 || digit > 9) {\n                    throw new FormatException();\n                }\n                sum += digit;\n            }\n            return (1000 - sum) % 10;\n        }\n    }\n\n    /**\n     * <p>Implements decoding of the EAN-13 format.</p>\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @author Sean Owen\n     * @author alasdair@google.com (Alasdair Mackintosh)\n     */\n    class EAN13Reader extends UPCEANReader {\n        constructor() {\n            super();\n            this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]);\n        }\n        decodeMiddle(row, startRange, resultString) {\n            let counters = this.decodeMiddleCounters;\n            counters[0] = 0;\n            counters[1] = 0;\n            counters[2] = 0;\n            counters[3] = 0;\n            let end = row.getSize();\n            let rowOffset = startRange[1];\n            let lgPatternFound = 0;\n            for (let x = 0; x < 6 && rowOffset < end; x++) {\n                let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_AND_G_PATTERNS);\n                resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch % 10));\n                for (let counter of counters) {\n                    rowOffset += counter;\n                }\n                if (bestMatch >= 10) {\n                    lgPatternFound |= 1 << (5 - x);\n                }\n            }\n            resultString = EAN13Reader.determineFirstDigit(resultString, lgPatternFound);\n            let middleRange = UPCEANReader.findGuardPattern(\n                row,\n                rowOffset,\n                true,\n                UPCEANReader.MIDDLE_PATTERN,\n                new Int32Array(UPCEANReader.MIDDLE_PATTERN.length).fill(0));\n            rowOffset = middleRange[1];\n            for (let x = 0; x < 6 && rowOffset < end; x++) {\n                let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS);\n                resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch));\n                for (let counter of counters) {\n                    rowOffset += counter;\n                }\n            }\n            return { rowOffset, resultString };\n        }\n        getBarcodeFormat() {\n            return BarcodeFormat$1.EAN_13;\n        }\n        static determineFirstDigit(resultString, lgPatternFound) {\n            for (let d = 0; d < 10; d++) {\n                if (lgPatternFound === this.FIRST_DIGIT_ENCODINGS[d]) {\n                    resultString = String.fromCharCode(('0'.charCodeAt(0) + d)) + resultString;\n                    return resultString;\n                }\n            }\n            throw new NotFoundException();\n        }\n    }\n    EAN13Reader.FIRST_DIGIT_ENCODINGS = [0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A];\n\n    /**\n     * <p>Implements decoding of the EAN-8 format.</p>\n     *\n     * @author Sean Owen\n     */\n    class EAN8Reader extends UPCEANReader {\n        constructor() {\n            super();\n            this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]);\n        }\n        decodeMiddle(row, startRange, resultString) {\n            const counters = this.decodeMiddleCounters;\n            counters[0] = 0;\n            counters[1] = 0;\n            counters[2] = 0;\n            counters[3] = 0;\n            let end = row.getSize();\n            let rowOffset = startRange[1];\n            for (let x = 0; x < 4 && rowOffset < end; x++) {\n                let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS);\n                resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch));\n                for (let counter of counters) {\n                    rowOffset += counter;\n                }\n            }\n            let middleRange = UPCEANReader.findGuardPattern(row, rowOffset, true, UPCEANReader.MIDDLE_PATTERN, new Int32Array(UPCEANReader.MIDDLE_PATTERN.length).fill(0));\n            rowOffset = middleRange[1];\n            for (let x = 0; x < 4 && rowOffset < end; x++) {\n                let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS);\n                resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch));\n                for (let counter of counters) {\n                    rowOffset += counter;\n                }\n            }\n            return { rowOffset, resultString };\n        }\n        getBarcodeFormat() {\n            return BarcodeFormat$1.EAN_8;\n        }\n    }\n\n    /**\n     * Encapsulates functionality and implementation that is common to all families\n     * of one-dimensional barcodes.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @author Sean Owen\n     * @author sam2332 (Sam Rudloff)\n     *\n     * @source https://github.com/zxing/zxing/blob/3c96923276dd5785d58eb970b6ba3f80d36a9505/core/src/main/java/com/google/zxing/oned/UPCAReader.java\n     *\n     * @experimental\n     */\n    class UPCAReader extends UPCEANReader {\n        constructor() {\n            super(...arguments);\n            this.ean13Reader = new EAN13Reader();\n        }\n        // @Override\n        getBarcodeFormat() {\n            return BarcodeFormat$1.UPC_A;\n        }\n        // Note that we don't try rotation without the try harder flag, even if rotation was supported.\n        // @Override\n        decode(image, hints) {\n            return this.maybeReturnResult(this.ean13Reader.decode(image));\n        }\n        // @Override\n        decodeRow(rowNumber, row, hints) {\n            return this.maybeReturnResult(this.ean13Reader.decodeRow(rowNumber, row, hints));\n        }\n        // @Override\n        decodeMiddle(row, startRange, resultString) {\n            return this.ean13Reader.decodeMiddle(row, startRange, resultString);\n        }\n        maybeReturnResult(result) {\n            let text = result.getText();\n            if (text.charAt(0) === '0') {\n                let upcaResult = new Result(text.substring(1), null, null, result.getResultPoints(), BarcodeFormat$1.UPC_A);\n                if (result.getResultMetadata() != null) {\n                    upcaResult.putAllMetadata(result.getResultMetadata());\n                }\n                return upcaResult;\n            }\n            else {\n                throw new NotFoundException();\n            }\n        }\n        reset() {\n            this.ean13Reader.reset();\n        }\n    }\n\n    /**\n     * <p>Implements decoding of the UPC-E format.</p>\n     * <p><a href=\"http://www.barcodeisland.com/upce.phtml\">This</a> is a great reference for\n     * UPC-E information.</p>\n     *\n     * @author Sean Owen\n     *\n     * @source https://github.com/zxing/zxing/blob/3c96923276dd5785d58eb970b6ba3f80d36a9505/core/src/main/java/com/google/zxing/oned/UPCEReader.java\n     *\n     * @experimental\n     */\n    /* final */ class UPCEReader extends UPCEANReader {\n        constructor() {\n            super();\n            this.decodeMiddleCounters = new Int32Array(4);\n        }\n        /**\n         * @throws NotFoundException\n         */\n        // @Override\n        decodeMiddle(row, startRange, result) {\n            const counters = this.decodeMiddleCounters.map(x => x);\n            counters[0] = 0;\n            counters[1] = 0;\n            counters[2] = 0;\n            counters[3] = 0;\n            const end = row.getSize();\n            let rowOffset = startRange[1];\n            let lgPatternFound = 0;\n            for (let x = 0; x < 6 && rowOffset < end; x++) {\n                const bestMatch = UPCEReader.decodeDigit(\n                    row, counters, rowOffset, UPCEReader.L_AND_G_PATTERNS);\n                result += String.fromCharCode(('0'.charCodeAt(0) + (bestMatch % 10)));\n                for (let counter of counters) {\n                    rowOffset += counter;\n                }\n                if (bestMatch >= 10) {\n                    lgPatternFound |= (1 << (5 - x));\n                }\n            }\n            let resultString = UPCEReader.determineNumSysAndCheckDigit(\n                result, lgPatternFound);\n            return {rowOffset, resultString};\n        }\n        /**\n         * @throws NotFoundException\n         */\n        // @Override\n        decodeEnd(row, endStart) {\n            return UPCEReader.findGuardPatternWithoutCounters(\n                row, endStart, true, UPCEReader.MIDDLE_END_PATTERN);\n        }\n        /**\n         * @throws FormatException\n         */\n        // @Override\n        checkChecksum(s) {\n            return UPCEANReader.checkChecksum(UPCEReader.convertUPCEtoUPCA(s));\n        }\n        /**\n         * @throws NotFoundException\n         */\n        static determineNumSysAndCheckDigit(resultString, lgPatternFound) {\n            for (let numSys = 0; numSys <= 1; numSys++) {\n                for (let d = 0; d < 10; d++) {\n                    if (lgPatternFound === this.NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d]) {\n                        let prefix = String.fromCharCode('0'.charCodeAt(0) + numSys);\n                        let suffix = String.fromCharCode('0'.charCodeAt(0) + d);\n                        return prefix + resultString + suffix;\n                    }\n                }\n            }\n            throw NotFoundException.getNotFoundInstance();\n        }\n        // @Override\n        getBarcodeFormat() {\n            return BarcodeFormat$1.UPC_E;\n        }\n        /**\n         * Expands a UPC-E value back into its full, equivalent UPC-A code value.\n         *\n         * @param upce UPC-E code as string of digits\n         * @return equivalent UPC-A code as string of digits\n         */\n        static convertUPCEtoUPCA(upce) {\n            // the following line is equivalent to upce.getChars(1, 7, upceChars, 0);\n            const upceChars = upce.slice(1, 7).split('').map(x => x.charCodeAt(0));\n            const result = new StringBuilder( /*12*/);\n            result.append(upce.charAt(0));\n            let lastChar = upceChars[5];\n            switch (lastChar) {\n                case 0:\n                case 1:\n                case 2:\n                    result.appendChars(upceChars, 0, 2);\n                    result.append(lastChar);\n                    result.append('0000');\n                    result.appendChars(upceChars, 2, 3);\n                    break;\n                case 3:\n                    result.appendChars(upceChars, 0, 3);\n                    result.append('00000');\n                    result.appendChars(upceChars, 3, 2);\n                    break;\n                case 4:\n                    result.appendChars(upceChars, 0, 4);\n                    result.append('00000');\n                    result.append(upceChars[4]);\n                    break;\n                default:\n                    result.appendChars(upceChars, 0, 5);\n                    result.append('0000');\n                    result.append(lastChar);\n                    break;\n            }\n            // Only append check digit in conversion if supplied\n            if (upce.length >= 8) {\n                result.append(upce.charAt(7));\n            }\n            return result.toString();\n        }\n    }\n    /**\n     * The pattern that marks the middle, and end, of a UPC-E pattern.\n     * There is no \"second half\" to a UPC-E barcode.\n     */\n    UPCEReader.MIDDLE_END_PATTERN = Int32Array.from([1, 1, 1, 1, 1, 1]);\n    // For an UPC-E barcode, the final digit is represented by the parities used\n    // to encode the middle six digits, according to the table below.\n    //\n    //                Parity of next 6 digits\n    //    Digit   0     1     2     3     4     5\n    //       0    Even   Even  Even Odd  Odd   Odd\n    //       1    Even   Even  Odd  Even Odd   Odd\n    //       2    Even   Even  Odd  Odd  Even  Odd\n    //       3    Even   Even  Odd  Odd  Odd   Even\n    //       4    Even   Odd   Even Even Odd   Odd\n    //       5    Even   Odd   Odd  Even Even  Odd\n    //       6    Even   Odd   Odd  Odd  Even  Even\n    //       7    Even   Odd   Even Odd  Even  Odd\n    //       8    Even   Odd   Even Odd  Odd   Even\n    //       9    Even   Odd   Odd  Even Odd   Even\n    //\n    // The encoding is represented by the following array, which is a bit pattern\n    // using Odd = 0 and Even = 1. For example, 5 is represented by:\n    //\n    //              Odd Even Even Odd Odd Even\n    // in binary:\n    //                0    1    1   0   0    1   == 0x19\n    //\n    /**\n     * See {@link #L_AND_G_PATTERNS}; these values similarly represent patterns of\n     * even-odd parity encodings of digits that imply both the number system (0 or 1)\n     * used, and the check digit.\n     */\n    UPCEReader.NUMSYS_AND_CHECK_DIGIT_PATTERNS = [\n        Int32Array.from([0x38, 0x34, 0x32, 0x31, 0x2C, 0x26, 0x23, 0x2A, 0x29, 0x25]),\n        Int32Array.from([0x07, 0x0B, 0x0D, 0x0E, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A]),\n    ];\n\n    /**\n     * <p>A reader that can read all available UPC/EAN formats. If a caller wants to try to\n     * read all such formats, it is most efficient to use this implementation rather than invoke\n     * individual readers.</p>\n     *\n     * @author Sean Owen\n     */\n    class MultiFormatUPCEANReader extends OneDReader {\n        constructor(hints) {\n            super();\n            let possibleFormats = hints == null ? null : hints.get(DecodeHintType$1.POSSIBLE_FORMATS);\n            let readers = [];\n            if (!isNullOrUndefined(possibleFormats)) {\n                if (possibleFormats.indexOf(BarcodeFormat$1.EAN_13) > -1) {\n                    readers.push(new EAN13Reader());\n                }\n                if (possibleFormats.indexOf(BarcodeFormat$1.UPC_A) > -1) {\n                    readers.push(new UPCAReader());\n                }\n                if (possibleFormats.indexOf(BarcodeFormat$1.EAN_8) > -1) {\n                    readers.push(new EAN8Reader());\n                }\n                if (possibleFormats.indexOf(BarcodeFormat$1.UPC_E) > -1) {\n                    readers.push(new UPCEReader());\n                }\n            } else {\n                // No hints provided.\n                readers.push(new EAN13Reader());\n                readers.push(new UPCAReader());\n                readers.push(new EAN8Reader());\n                readers.push(new UPCEReader());\n            }\n            this.readers = readers;\n        }\n        decodeRow(rowNumber, row, hints) {\n            for (let reader of this.readers) {\n                try {\n                    // const result: Result = reader.decodeRow(rowNumber, row, startGuardPattern, hints);\n                    const result = reader.decodeRow(rowNumber, row, hints);\n                    // Special case: a 12-digit code encoded in UPC-A is identical to a \"0\"\n                    // followed by those 12 digits encoded as EAN-13. Each will recognize such a code,\n                    // UPC-A as a 12-digit string and EAN-13 as a 13-digit string starting with \"0\".\n                    // Individually these are correct and their readers will both read such a code\n                    // and correctly call it EAN-13, or UPC-A, respectively.\n                    //\n                    // In this case, if we've been looking for both types, we'd like to call it\n                    // a UPC-A code. But for efficiency we only run the EAN-13 decoder to also read\n                    // UPC-A. So we special case it here, and convert an EAN-13 result to a UPC-A\n                    // result if appropriate.\n                    //\n                    // But, don't return UPC-A if UPC-A was not a requested format!\n                    const ean13MayBeUPCA = result.getBarcodeFormat() === BarcodeFormat$1.EAN_13 &&\n                        result.getText().charAt(0) === '0';\n                    // @SuppressWarnings(\"unchecked\")\n                    const possibleFormats = hints == null ? null : hints.get(DecodeHintType$1.POSSIBLE_FORMATS);\n                    const canReturnUPCA = possibleFormats == null || possibleFormats.includes(BarcodeFormat$1.UPC_A);\n                    if (ean13MayBeUPCA && canReturnUPCA) {\n                        const rawBytes = result.getRawBytes();\n                        // Transfer the metadata across\n                        const resultUPCA = new Result(\n                            result.getText().substring(1),\n                            rawBytes,\n                            (rawBytes ? rawBytes.length : null),\n                            result.getResultPoints(),\n                            BarcodeFormat$1.UPC_A);\n                        resultUPCA.putAllMetadata(result.getResultMetadata());\n                        return resultUPCA;\n                    }\n                    return result;\n                }\n                catch (err) {\n                    // continue;\n                }\n            }\n            throw new NotFoundException();\n        }\n        reset() {\n            for (let reader of this.readers) {\n                reader.reset();\n            }\n        }\n    }\n\n    // import Integer from '../../util/Integer';\n    // import Float from '../../util/Float';\n    class AbstractRSSReader extends OneDReader {\n        constructor() {\n            super();\n            this.decodeFinderCounters = new Int32Array(4);\n            this.dataCharacterCounters = new Int32Array(8);\n            this.oddRoundingErrors = new Array(4);\n            this.evenRoundingErrors = new Array(4);\n            this.oddCounts = new Array(this.dataCharacterCounters.length / 2);\n            this.evenCounts = new Array(this.dataCharacterCounters.length / 2);\n        }\n        getDecodeFinderCounters() {\n            return this.decodeFinderCounters;\n        }\n        getDataCharacterCounters() {\n            return this.dataCharacterCounters;\n        }\n        getOddRoundingErrors() {\n            return this.oddRoundingErrors;\n        }\n        getEvenRoundingErrors() {\n            return this.evenRoundingErrors;\n        }\n        getOddCounts() {\n            return this.oddCounts;\n        }\n        getEvenCounts() {\n            return this.evenCounts;\n        }\n        parseFinderValue(counters, finderPatterns) {\n            for (let value = 0; value < finderPatterns.length; value++) {\n                if (OneDReader.patternMatchVariance(counters, finderPatterns[value], AbstractRSSReader.MAX_INDIVIDUAL_VARIANCE) < AbstractRSSReader.MAX_AVG_VARIANCE) {\n                    return value;\n                }\n            }\n            throw new NotFoundException();\n        }\n        /**\n         * @param array values to sum\n         * @return sum of values\n         * @deprecated call {@link MathUtils#sum(int[])}\n         */\n        static count(array) {\n            return MathUtils.sum(new Int32Array(array));\n        }\n        static increment(array, errors) {\n            let index = 0;\n            let biggestError = errors[0];\n            for (let i = 1; i < array.length; i++) {\n                if (errors[i] > biggestError) {\n                    biggestError = errors[i];\n                    index = i;\n                }\n            }\n            array[index]++;\n        }\n        static decrement(array, errors) {\n            let index = 0;\n            let biggestError = errors[0];\n            for (let i = 1; i < array.length; i++) {\n                if (errors[i] < biggestError) {\n                    biggestError = errors[i];\n                    index = i;\n                }\n            }\n            array[index]--;\n        }\n        static isFinderPattern(counters) {\n            let firstTwoSum = counters[0] + counters[1];\n            let sum = firstTwoSum + counters[2] + counters[3];\n            let ratio = firstTwoSum / sum;\n            if (ratio >= AbstractRSSReader.MIN_FINDER_PATTERN_RATIO && ratio <= AbstractRSSReader.MAX_FINDER_PATTERN_RATIO) {\n                // passes ratio test in spec, but see if the counts are unreasonable\n                let minCounter = Number.MAX_SAFE_INTEGER;\n                let maxCounter = Number.MIN_SAFE_INTEGER;\n                for (let counter of counters) {\n                    if (counter > maxCounter) {\n                        maxCounter = counter;\n                    }\n                    if (counter < minCounter) {\n                        minCounter = counter;\n                    }\n                }\n                return maxCounter < 10 * minCounter;\n            }\n            return false;\n        }\n    }\n    AbstractRSSReader.MAX_AVG_VARIANCE = 0.2;\n    AbstractRSSReader.MAX_INDIVIDUAL_VARIANCE = 0.45;\n    AbstractRSSReader.MIN_FINDER_PATTERN_RATIO = 9.5 / 12.0;\n    AbstractRSSReader.MAX_FINDER_PATTERN_RATIO = 12.5 / 14.0;\n\n    class DataCharacter {\n        constructor(value, checksumPortion) {\n            this.value = value;\n            this.checksumPortion = checksumPortion;\n        }\n        getValue() {\n            return this.value;\n        }\n        getChecksumPortion() {\n            return this.checksumPortion;\n        }\n        toString() {\n            return this.value + '(' + this.checksumPortion + ')';\n        }\n        equals(o) {\n            if (!(o instanceof DataCharacter)) {\n                return false;\n            }\n            const that = o;\n            return this.value === that.value && this.checksumPortion === that.checksumPortion;\n        }\n        hashCode() {\n            return this.value ^ this.checksumPortion;\n        }\n    }\n\n    class FinderPattern {\n        constructor(value, startEnd, start, end, rowNumber) {\n            this.value = value;\n            this.startEnd = startEnd;\n            this.value = value;\n            this.startEnd = startEnd;\n            this.resultPoints = new Array();\n            this.resultPoints.push(new ResultPoint(start, rowNumber));\n            this.resultPoints.push(new ResultPoint(end, rowNumber));\n        }\n        getValue() {\n            return this.value;\n        }\n        getStartEnd() {\n            return this.startEnd;\n        }\n        getResultPoints() {\n            return this.resultPoints;\n        }\n        equals(o) {\n            if (!(o instanceof FinderPattern)) {\n                return false;\n            }\n            const that = o;\n            return this.value === that.value;\n        }\n        hashCode() {\n            return this.value;\n        }\n    }\n\n    /**\n     * RSS util functions.\n     */\n    class RSSUtils {\n        constructor() { }\n        static getRSSvalue(widths, maxWidth, noNarrow) {\n            let n = 0;\n            for (let width of widths) {\n                n += width;\n            }\n            let val = 0;\n            let narrowMask = 0;\n            let elements = widths.length;\n            for (let bar = 0; bar < elements - 1; bar++) {\n                let elmWidth;\n                for (elmWidth = 1, narrowMask |= 1 << bar; elmWidth < widths[bar]; elmWidth++, narrowMask &= ~(1 << bar)) {\n                    let subVal = RSSUtils.combins(n - elmWidth - 1, elements - bar - 2);\n                    if (noNarrow && (narrowMask === 0) && (n - elmWidth - (elements - bar - 1) >= elements - bar - 1)) {\n                        subVal -= RSSUtils.combins(n - elmWidth - (elements - bar), elements - bar - 2);\n                    }\n                    if (elements - bar - 1 > 1) {\n                        let lessVal = 0;\n                        for (let mxwElement = n - elmWidth - (elements - bar - 2); mxwElement > maxWidth; mxwElement--) {\n                            lessVal += RSSUtils.combins(n - elmWidth - mxwElement - 1, elements - bar - 3);\n                        }\n                        subVal -= lessVal * (elements - 1 - bar);\n                    }\n                    else if (n - elmWidth > maxWidth) {\n                        subVal--;\n                    }\n                    val += subVal;\n                }\n                n -= elmWidth;\n            }\n            return val;\n        }\n        static combins(n, r) {\n            let maxDenom;\n            let minDenom;\n            if (n - r > r) {\n                minDenom = r;\n                maxDenom = n - r;\n            }\n            else {\n                minDenom = n - r;\n                maxDenom = r;\n            }\n            let val = 1;\n            let j = 1;\n            for (let i = n; i > maxDenom; i--) {\n                val *= i;\n                if (j <= minDenom) {\n                    val /= j;\n                    j++;\n                }\n            }\n            while ((j <= minDenom)) {\n                val /= j;\n                j++;\n            }\n            return val;\n        }\n    }\n\n    class BitArrayBuilder {\n        static buildBitArray(pairs) {\n            let charNumber = (pairs.length * 2) - 1;\n            if (pairs[pairs.length - 1].getRightChar() == null) {\n                charNumber -= 1;\n            }\n            let size = 12 * charNumber;\n            let binary = new BitArray(size);\n            let accPos = 0;\n            let firstPair = pairs[0];\n            let firstValue = firstPair.getRightChar().getValue();\n            for (let i = 11; i >= 0; --i) {\n                if ((firstValue & (1 << i)) != 0) {\n                    binary.set(accPos);\n                }\n                accPos++;\n            }\n            for (let i = 1; i < pairs.length; ++i) {\n                let currentPair = pairs[i];\n                let leftValue = currentPair.getLeftChar().getValue();\n                for (let j = 11; j >= 0; --j) {\n                    if ((leftValue & (1 << j)) != 0) {\n                        binary.set(accPos);\n                    }\n                    accPos++;\n                }\n                if (currentPair.getRightChar() != null) {\n                    let rightValue = currentPair.getRightChar().getValue();\n                    for (let j = 11; j >= 0; --j) {\n                        if ((rightValue & (1 << j)) != 0) {\n                            binary.set(accPos);\n                        }\n                        accPos++;\n                    }\n                }\n            }\n            return binary;\n        }\n    }\n\n    class BlockParsedResult {\n        constructor(finished, decodedInformation) {\n            if (decodedInformation) {\n                this.decodedInformation = null;\n            }\n            else {\n                this.finished = finished;\n                this.decodedInformation = decodedInformation;\n            }\n        }\n        getDecodedInformation() {\n            return this.decodedInformation;\n        }\n        isFinished() {\n            return this.finished;\n        }\n    }\n\n    class DecodedObject {\n        constructor(newPosition) {\n            this.newPosition = newPosition;\n        }\n        getNewPosition() {\n            return this.newPosition;\n        }\n    }\n\n    class DecodedChar extends DecodedObject {\n        constructor(newPosition, value) {\n            super(newPosition);\n            this.value = value;\n        }\n        getValue() {\n            return this.value;\n        }\n        isFNC1() {\n            return this.value === DecodedChar.FNC1;\n        }\n    }\n    DecodedChar.FNC1 = '$';\n\n    class DecodedInformation extends DecodedObject {\n        constructor(newPosition, newString, remainingValue) {\n            super(newPosition);\n            if (remainingValue) {\n                this.remaining = true;\n                this.remainingValue = this.remainingValue;\n            }\n            else {\n                this.remaining = false;\n                this.remainingValue = 0;\n            }\n            this.newString = newString;\n        }\n        getNewString() {\n            return this.newString;\n        }\n        isRemaining() {\n            return this.remaining;\n        }\n        getRemainingValue() {\n            return this.remainingValue;\n        }\n    }\n\n    class DecodedNumeric extends DecodedObject {\n        constructor(newPosition, firstDigit, secondDigit) {\n            super(newPosition);\n            if (firstDigit < 0 || firstDigit > 10 || secondDigit < 0 || secondDigit > 10) {\n                throw new FormatException();\n            }\n            this.firstDigit = firstDigit;\n            this.secondDigit = secondDigit;\n        }\n        getFirstDigit() {\n            return this.firstDigit;\n        }\n        getSecondDigit() {\n            return this.secondDigit;\n        }\n        getValue() {\n            return this.firstDigit * 10 + this.secondDigit;\n        }\n        isFirstDigitFNC1() {\n            return this.firstDigit === DecodedNumeric.FNC1;\n        }\n        isSecondDigitFNC1() {\n            return this.secondDigit === DecodedNumeric.FNC1;\n        }\n        isAnyFNC1() {\n            return this.firstDigit === DecodedNumeric.FNC1 || this.secondDigit === DecodedNumeric.FNC1;\n        }\n    }\n    DecodedNumeric.FNC1 = 10;\n\n    class FieldParser {\n        constructor() {\n        }\n        static parseFieldsInGeneralPurpose(rawInformation) {\n            if (!rawInformation) {\n                return null;\n            }\n            // Processing 2-digit AIs\n            if (rawInformation.length < 2) {\n                throw new NotFoundException();\n            }\n            let firstTwoDigits = rawInformation.substring(0, 2);\n            for (let dataLength of FieldParser.TWO_DIGIT_DATA_LENGTH) {\n                if (dataLength[0] === firstTwoDigits) {\n                    if (dataLength[1] === FieldParser.VARIABLE_LENGTH) {\n                        return FieldParser.processVariableAI(2, dataLength[2], rawInformation);\n                    }\n                    return FieldParser.processFixedAI(2, dataLength[1], rawInformation);\n                }\n            }\n            if (rawInformation.length < 3) {\n                throw new NotFoundException();\n            }\n            let firstThreeDigits = rawInformation.substring(0, 3);\n            for (let dataLength of FieldParser.THREE_DIGIT_DATA_LENGTH) {\n                if (dataLength[0] === firstThreeDigits) {\n                    if (dataLength[1] === FieldParser.VARIABLE_LENGTH) {\n                        return FieldParser.processVariableAI(3, dataLength[2], rawInformation);\n                    }\n                    return FieldParser.processFixedAI(3, dataLength[1], rawInformation);\n                }\n            }\n            for (let dataLength of FieldParser.THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH) {\n                if (dataLength[0] === firstThreeDigits) {\n                    if (dataLength[1] === FieldParser.VARIABLE_LENGTH) {\n                        return FieldParser.processVariableAI(4, dataLength[2], rawInformation);\n                    }\n                    return FieldParser.processFixedAI(4, dataLength[1], rawInformation);\n                }\n            }\n            if (rawInformation.length < 4) {\n                throw new NotFoundException();\n            }\n            let firstFourDigits = rawInformation.substring(0, 4);\n            for (let dataLength of FieldParser.FOUR_DIGIT_DATA_LENGTH) {\n                if (dataLength[0] === firstFourDigits) {\n                    if (dataLength[1] === FieldParser.VARIABLE_LENGTH) {\n                        return FieldParser.processVariableAI(4, dataLength[2], rawInformation);\n                    }\n                    return FieldParser.processFixedAI(4, dataLength[1], rawInformation);\n                }\n            }\n            throw new NotFoundException();\n        }\n        static processFixedAI(aiSize, fieldSize, rawInformation) {\n            if (rawInformation.length < aiSize) {\n                throw new NotFoundException();\n            }\n            let ai = rawInformation.substring(0, aiSize);\n            if (rawInformation.length < aiSize + fieldSize) {\n                throw new NotFoundException();\n            }\n            let field = rawInformation.substring(aiSize, aiSize + fieldSize);\n            let remaining = rawInformation.substring(aiSize + fieldSize);\n            let result = '(' + ai + ')' + field;\n            let parsedAI = FieldParser.parseFieldsInGeneralPurpose(remaining);\n            return parsedAI == null ? result : result + parsedAI;\n        }\n        static processVariableAI(aiSize, variableFieldSize, rawInformation) {\n            let ai = rawInformation.substring(0, aiSize);\n            let maxSize;\n            if (rawInformation.length < aiSize + variableFieldSize) {\n                maxSize = rawInformation.length;\n            }\n            else {\n                maxSize = aiSize + variableFieldSize;\n            }\n            let field = rawInformation.substring(aiSize, maxSize);\n            let remaining = rawInformation.substring(maxSize);\n            let result = '(' + ai + ')' + field;\n            let parsedAI = FieldParser.parseFieldsInGeneralPurpose(remaining);\n            return parsedAI == null ? result : result + parsedAI;\n        }\n    }\n    FieldParser.VARIABLE_LENGTH = [];\n    FieldParser.TWO_DIGIT_DATA_LENGTH = [\n        ['00', 18],\n        ['01', 14],\n        ['02', 14],\n        ['10', FieldParser.VARIABLE_LENGTH, 20],\n        ['11', 6],\n        ['12', 6],\n        ['13', 6],\n        ['15', 6],\n        ['17', 6],\n        ['20', 2],\n        ['21', FieldParser.VARIABLE_LENGTH, 20],\n        ['22', FieldParser.VARIABLE_LENGTH, 29],\n        ['30', FieldParser.VARIABLE_LENGTH, 8],\n        ['37', FieldParser.VARIABLE_LENGTH, 8],\n        // internal company codes\n        ['90', FieldParser.VARIABLE_LENGTH, 30],\n        ['91', FieldParser.VARIABLE_LENGTH, 30],\n        ['92', FieldParser.VARIABLE_LENGTH, 30],\n        ['93', FieldParser.VARIABLE_LENGTH, 30],\n        ['94', FieldParser.VARIABLE_LENGTH, 30],\n        ['95', FieldParser.VARIABLE_LENGTH, 30],\n        ['96', FieldParser.VARIABLE_LENGTH, 30],\n        ['97', FieldParser.VARIABLE_LENGTH, 3],\n        ['98', FieldParser.VARIABLE_LENGTH, 30],\n        ['99', FieldParser.VARIABLE_LENGTH, 30],\n    ];\n    FieldParser.THREE_DIGIT_DATA_LENGTH = [\n        // Same format as above\n        ['240', FieldParser.VARIABLE_LENGTH, 30],\n        ['241', FieldParser.VARIABLE_LENGTH, 30],\n        ['242', FieldParser.VARIABLE_LENGTH, 6],\n        ['250', FieldParser.VARIABLE_LENGTH, 30],\n        ['251', FieldParser.VARIABLE_LENGTH, 30],\n        ['253', FieldParser.VARIABLE_LENGTH, 17],\n        ['254', FieldParser.VARIABLE_LENGTH, 20],\n        ['400', FieldParser.VARIABLE_LENGTH, 30],\n        ['401', FieldParser.VARIABLE_LENGTH, 30],\n        ['402', 17],\n        ['403', FieldParser.VARIABLE_LENGTH, 30],\n        ['410', 13],\n        ['411', 13],\n        ['412', 13],\n        ['413', 13],\n        ['414', 13],\n        ['420', FieldParser.VARIABLE_LENGTH, 20],\n        ['421', FieldParser.VARIABLE_LENGTH, 15],\n        ['422', 3],\n        ['423', FieldParser.VARIABLE_LENGTH, 15],\n        ['424', 3],\n        ['425', 3],\n        ['426', 3],\n    ];\n    FieldParser.THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH = [\n        // Same format as above\n        ['310', 6],\n        ['311', 6],\n        ['312', 6],\n        ['313', 6],\n        ['314', 6],\n        ['315', 6],\n        ['316', 6],\n        ['320', 6],\n        ['321', 6],\n        ['322', 6],\n        ['323', 6],\n        ['324', 6],\n        ['325', 6],\n        ['326', 6],\n        ['327', 6],\n        ['328', 6],\n        ['329', 6],\n        ['330', 6],\n        ['331', 6],\n        ['332', 6],\n        ['333', 6],\n        ['334', 6],\n        ['335', 6],\n        ['336', 6],\n        ['340', 6],\n        ['341', 6],\n        ['342', 6],\n        ['343', 6],\n        ['344', 6],\n        ['345', 6],\n        ['346', 6],\n        ['347', 6],\n        ['348', 6],\n        ['349', 6],\n        ['350', 6],\n        ['351', 6],\n        ['352', 6],\n        ['353', 6],\n        ['354', 6],\n        ['355', 6],\n        ['356', 6],\n        ['357', 6],\n        ['360', 6],\n        ['361', 6],\n        ['362', 6],\n        ['363', 6],\n        ['364', 6],\n        ['365', 6],\n        ['366', 6],\n        ['367', 6],\n        ['368', 6],\n        ['369', 6],\n        ['390', FieldParser.VARIABLE_LENGTH, 15],\n        ['391', FieldParser.VARIABLE_LENGTH, 18],\n        ['392', FieldParser.VARIABLE_LENGTH, 15],\n        ['393', FieldParser.VARIABLE_LENGTH, 18],\n        ['703', FieldParser.VARIABLE_LENGTH, 30],\n    ];\n    FieldParser.FOUR_DIGIT_DATA_LENGTH = [\n        // Same format as above\n        ['7001', 13],\n        ['7002', FieldParser.VARIABLE_LENGTH, 30],\n        ['7003', 10],\n        ['8001', 14],\n        ['8002', FieldParser.VARIABLE_LENGTH, 20],\n        ['8003', FieldParser.VARIABLE_LENGTH, 30],\n        ['8004', FieldParser.VARIABLE_LENGTH, 30],\n        ['8005', 6],\n        ['8006', 18],\n        ['8007', FieldParser.VARIABLE_LENGTH, 30],\n        ['8008', FieldParser.VARIABLE_LENGTH, 12],\n        ['8018', 18],\n        ['8020', FieldParser.VARIABLE_LENGTH, 25],\n        ['8100', 6],\n        ['8101', 10],\n        ['8102', 2],\n        ['8110', FieldParser.VARIABLE_LENGTH, 70],\n        ['8200', FieldParser.VARIABLE_LENGTH, 70],\n    ];\n\n    class GeneralAppIdDecoder {\n        constructor(information) {\n            this.buffer = new StringBuilder();\n            this.information = information;\n        }\n        decodeAllCodes(buff, initialPosition) {\n            let currentPosition = initialPosition;\n            let remaining = null;\n            do {\n                let info = this.decodeGeneralPurposeField(currentPosition, remaining);\n                let parsedFields = FieldParser.parseFieldsInGeneralPurpose(info.getNewString());\n                if (parsedFields != null) {\n                    buff.append(parsedFields);\n                }\n                if (info.isRemaining()) {\n                    remaining = '' + info.getRemainingValue();\n                }\n                else {\n                    remaining = null;\n                }\n                if (currentPosition === info.getNewPosition()) { // No step forward!\n                    break;\n                }\n                currentPosition = info.getNewPosition();\n            } while (true);\n            return buff.toString();\n        }\n        isStillNumeric(pos) {\n            // It's numeric if it still has 7 positions\n            // and one of the first 4 bits is \"1\".\n            if (pos + 7 > this.information.getSize()) {\n                return pos + 4 <= this.information.getSize();\n            }\n            for (let i = pos; i < pos + 3; ++i) {\n                if (this.information.get(i)) {\n                    return true;\n                }\n            }\n            return this.information.get(pos + 3);\n        }\n        decodeNumeric(pos) {\n            if (pos + 7 > this.information.getSize()) {\n                let numeric = this.extractNumericValueFromBitArray(pos, 4);\n                if (numeric === 0) {\n                    return new DecodedNumeric(this.information.getSize(), DecodedNumeric.FNC1, DecodedNumeric.FNC1);\n                }\n                return new DecodedNumeric(this.information.getSize(), numeric - 1, DecodedNumeric.FNC1);\n            }\n            let numeric = this.extractNumericValueFromBitArray(pos, 7);\n            let digit1 = (numeric - 8) / 11;\n            let digit2 = (numeric - 8) % 11;\n            return new DecodedNumeric(pos + 7, digit1, digit2);\n        }\n        extractNumericValueFromBitArray(pos, bits) {\n            return GeneralAppIdDecoder.extractNumericValueFromBitArray(this.information, pos, bits);\n        }\n        static extractNumericValueFromBitArray(information, pos, bits) {\n            let value = 0;\n            for (let i = 0; i < bits; ++i) {\n                if (information.get(pos + i)) {\n                    value |= 1 << (bits - i - 1);\n                }\n            }\n            return value;\n        }\n        decodeGeneralPurposeField(pos, remaining) {\n            // this.buffer.setLength(0);\n            this.buffer.setLengthToZero();\n            if (remaining != null) {\n                this.buffer.append(remaining);\n            }\n            this.current.setPosition(pos);\n            let lastDecoded = this.parseBlocks();\n            if (lastDecoded != null && lastDecoded.isRemaining()) {\n                return new DecodedInformation(this.current.getPosition(), this.buffer.toString(), lastDecoded.getRemainingValue());\n            }\n            return new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n        }\n        parseBlocks() {\n            let isFinished;\n            let result;\n            do {\n                let initialPosition = this.current.getPosition();\n                if (this.current.isAlpha()) {\n                    result = this.parseAlphaBlock();\n                    isFinished = result.isFinished();\n                }\n                else if (this.current.isIsoIec646()) {\n                    result = this.parseIsoIec646Block();\n                    isFinished = result.isFinished();\n                }\n                else { // it must be numeric\n                    result = this.parseNumericBlock();\n                    isFinished = result.isFinished();\n                }\n                let positionChanged = initialPosition !== this.current.getPosition();\n                if (!positionChanged && !isFinished) {\n                    break;\n                }\n            } while (!isFinished);\n            return result.getDecodedInformation();\n        }\n        parseNumericBlock() {\n            while (this.isStillNumeric(this.current.getPosition())) {\n                let numeric = this.decodeNumeric(this.current.getPosition());\n                this.current.setPosition(numeric.getNewPosition());\n                if (numeric.isFirstDigitFNC1()) {\n                    let information;\n                    if (numeric.isSecondDigitFNC1()) {\n                        information = new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n                    }\n                    else {\n                        information = new DecodedInformation(this.current.getPosition(), this.buffer.toString(), numeric.getSecondDigit());\n                    }\n                    return new BlockParsedResult(true, information);\n                }\n                this.buffer.append(numeric.getFirstDigit());\n                if (numeric.isSecondDigitFNC1()) {\n                    let information = new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n                    return new BlockParsedResult(true, information);\n                }\n                this.buffer.append(numeric.getSecondDigit());\n            }\n            if (this.isNumericToAlphaNumericLatch(this.current.getPosition())) {\n                this.current.setAlpha();\n                this.current.incrementPosition(4);\n            }\n            return new BlockParsedResult(false);\n        }\n        parseIsoIec646Block() {\n            while (this.isStillIsoIec646(this.current.getPosition())) {\n                let iso = this.decodeIsoIec646(this.current.getPosition());\n                this.current.setPosition(iso.getNewPosition());\n                if (iso.isFNC1()) {\n                    let information = new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n                    return new BlockParsedResult(true, information);\n                }\n                this.buffer.append(iso.getValue());\n            }\n            if (this.isAlphaOr646ToNumericLatch(this.current.getPosition())) {\n                this.current.incrementPosition(3);\n                this.current.setNumeric();\n            }\n            else if (this.isAlphaTo646ToAlphaLatch(this.current.getPosition())) {\n                if (this.current.getPosition() + 5 < this.information.getSize()) {\n                    this.current.incrementPosition(5);\n                }\n                else {\n                    this.current.setPosition(this.information.getSize());\n                }\n                this.current.setAlpha();\n            }\n            return new BlockParsedResult(false);\n        }\n        parseAlphaBlock() {\n            while (this.isStillAlpha(this.current.getPosition())) {\n                let alpha = this.decodeAlphanumeric(this.current.getPosition());\n                this.current.setPosition(alpha.getNewPosition());\n                if (alpha.isFNC1()) {\n                    let information = new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n                    return new BlockParsedResult(true, information); // end of the char block\n                }\n                this.buffer.append(alpha.getValue());\n            }\n            if (this.isAlphaOr646ToNumericLatch(this.current.getPosition())) {\n                this.current.incrementPosition(3);\n                this.current.setNumeric();\n            }\n            else if (this.isAlphaTo646ToAlphaLatch(this.current.getPosition())) {\n                if (this.current.getPosition() + 5 < this.information.getSize()) {\n                    this.current.incrementPosition(5);\n                }\n                else {\n                    this.current.setPosition(this.information.getSize());\n                }\n                this.current.setIsoIec646();\n            }\n            return new BlockParsedResult(false);\n        }\n        isStillIsoIec646(pos) {\n            if (pos + 5 > this.information.getSize()) {\n                return false;\n            }\n            let fiveBitValue = this.extractNumericValueFromBitArray(pos, 5);\n            if (fiveBitValue >= 5 && fiveBitValue < 16) {\n                return true;\n            }\n            if (pos + 7 > this.information.getSize()) {\n                return false;\n            }\n            let sevenBitValue = this.extractNumericValueFromBitArray(pos, 7);\n            if (sevenBitValue >= 64 && sevenBitValue < 116) {\n                return true;\n            }\n            if (pos + 8 > this.information.getSize()) {\n                return false;\n            }\n            let eightBitValue = this.extractNumericValueFromBitArray(pos, 8);\n            return eightBitValue >= 232 && eightBitValue < 253;\n        }\n        decodeIsoIec646(pos) {\n            let fiveBitValue = this.extractNumericValueFromBitArray(pos, 5);\n            if (fiveBitValue === 15) {\n                return new DecodedChar(pos + 5, DecodedChar.FNC1);\n            }\n            if (fiveBitValue >= 5 && fiveBitValue < 15) {\n                return new DecodedChar(pos + 5, ('0' + (fiveBitValue - 5)));\n            }\n            let sevenBitValue = this.extractNumericValueFromBitArray(pos, 7);\n            if (sevenBitValue >= 64 && sevenBitValue < 90) {\n                return new DecodedChar(pos + 7, ('' + (sevenBitValue + 1)));\n            }\n            if (sevenBitValue >= 90 && sevenBitValue < 116) {\n                return new DecodedChar(pos + 7, ('' + (sevenBitValue + 7)));\n            }\n            let eightBitValue = this.extractNumericValueFromBitArray(pos, 8);\n            let c;\n            switch (eightBitValue) {\n                case 232:\n                    c = '!';\n                    break;\n                case 233:\n                    c = '\"';\n                    break;\n                case 234:\n                    c = '%';\n                    break;\n                case 235:\n                    c = '&';\n                    break;\n                case 236:\n                    c = '\\'';\n                    break;\n                case 237:\n                    c = '(';\n                    break;\n                case 238:\n                    c = ')';\n                    break;\n                case 239:\n                    c = '*';\n                    break;\n                case 240:\n                    c = '+';\n                    break;\n                case 241:\n                    c = ',';\n                    break;\n                case 242:\n                    c = '-';\n                    break;\n                case 243:\n                    c = '.';\n                    break;\n                case 244:\n                    c = '/';\n                    break;\n                case 245:\n                    c = ':';\n                    break;\n                case 246:\n                    c = ';';\n                    break;\n                case 247:\n                    c = '<';\n                    break;\n                case 248:\n                    c = '=';\n                    break;\n                case 249:\n                    c = '>';\n                    break;\n                case 250:\n                    c = '?';\n                    break;\n                case 251:\n                    c = '_';\n                    break;\n                case 252:\n                    c = ' ';\n                    break;\n                default:\n                    throw new FormatException();\n            }\n            return new DecodedChar(pos + 8, c);\n        }\n        isStillAlpha(pos) {\n            if (pos + 5 > this.information.getSize()) {\n                return false;\n            }\n            // We now check if it's a valid 5-bit value (0..9 and FNC1)\n            let fiveBitValue = this.extractNumericValueFromBitArray(pos, 5);\n            if (fiveBitValue >= 5 && fiveBitValue < 16) {\n                return true;\n            }\n            if (pos + 6 > this.information.getSize()) {\n                return false;\n            }\n            let sixBitValue = this.extractNumericValueFromBitArray(pos, 6);\n            return sixBitValue >= 16 && sixBitValue < 63; // 63 not included\n        }\n        decodeAlphanumeric(pos) {\n            let fiveBitValue = this.extractNumericValueFromBitArray(pos, 5);\n            if (fiveBitValue === 15) {\n                return new DecodedChar(pos + 5, DecodedChar.FNC1);\n            }\n            if (fiveBitValue >= 5 && fiveBitValue < 15) {\n                return new DecodedChar(pos + 5, ('0' + (fiveBitValue - 5)));\n            }\n            let sixBitValue = this.extractNumericValueFromBitArray(pos, 6);\n            if (sixBitValue >= 32 && sixBitValue < 58) {\n                return new DecodedChar(pos + 6, ('' + (sixBitValue + 33)));\n            }\n            let c;\n            switch (sixBitValue) {\n                case 58:\n                    c = '*';\n                    break;\n                case 59:\n                    c = ',';\n                    break;\n                case 60:\n                    c = '-';\n                    break;\n                case 61:\n                    c = '.';\n                    break;\n                case 62:\n                    c = '/';\n                    break;\n                default:\n                    throw new IllegalStateException('Decoding invalid alphanumeric value: ' + sixBitValue);\n            }\n            return new DecodedChar(pos + 6, c);\n        }\n        isAlphaTo646ToAlphaLatch(pos) {\n            if (pos + 1 > this.information.getSize()) {\n                return false;\n            }\n            for (let i = 0; i < 5 && i + pos < this.information.getSize(); ++i) {\n                if (i === 2) {\n                    if (!this.information.get(pos + 2)) {\n                        return false;\n                    }\n                }\n                else if (this.information.get(pos + i)) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        isAlphaOr646ToNumericLatch(pos) {\n            // Next is alphanumeric if there are 3 positions and they are all zeros\n            if (pos + 3 > this.information.getSize()) {\n                return false;\n            }\n            for (let i = pos; i < pos + 3; ++i) {\n                if (this.information.get(i)) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        isNumericToAlphaNumericLatch(pos) {\n            // Next is alphanumeric if there are 4 positions and they are all zeros, or\n            // if there is a subset of this just before the end of the symbol\n            if (pos + 1 > this.information.getSize()) {\n                return false;\n            }\n            for (let i = 0; i < 4 && i + pos < this.information.getSize(); ++i) {\n                if (this.information.get(pos + i)) {\n                    return false;\n                }\n            }\n            return true;\n        }\n    }\n\n    class AbstractExpandedDecoder {\n        constructor(information) {\n            this.information = information;\n            this.generalDecoder = new GeneralAppIdDecoder(information);\n        }\n        getInformation() {\n            return this.information;\n        }\n        getGeneralDecoder() {\n            return this.generalDecoder;\n        }\n    }\n\n    class AI01decoder extends AbstractExpandedDecoder {\n        constructor(information) {\n            super(information);\n        }\n        encodeCompressedGtin(buf, currentPos) {\n            buf.append('(01)');\n            let initialPosition = buf.length();\n            buf.append('9');\n            this.encodeCompressedGtinWithoutAI(buf, currentPos, initialPosition);\n        }\n        encodeCompressedGtinWithoutAI(buf, currentPos, initialBufferPosition) {\n            for (let i = 0; i < 4; ++i) {\n                let currentBlock = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos + 10 * i, 10);\n                if (currentBlock / 100 === 0) {\n                    buf.append('0');\n                }\n                if (currentBlock / 10 === 0) {\n                    buf.append('0');\n                }\n                buf.append(currentBlock);\n            }\n            AI01decoder.appendCheckDigit(buf, initialBufferPosition);\n        }\n        static appendCheckDigit(buf, currentPos) {\n            let checkDigit = 0;\n            for (let i = 0; i < 13; i++) {\n                // let digit = buf.charAt(i + currentPos) - '0';\n                // To be checked\n                let digit = buf.charAt(i + currentPos).charCodeAt(0) - '0'.charCodeAt(0);\n                checkDigit += (i & 0x01) === 0 ? 3 * digit : digit;\n            }\n            checkDigit = 10 - (checkDigit % 10);\n            if (checkDigit === 10) {\n                checkDigit = 0;\n            }\n            buf.append(checkDigit);\n        }\n    }\n    AI01decoder.GTIN_SIZE = 40;\n\n    class AI01AndOtherAIs extends AI01decoder {\n        // the second one is the encodation method, and the other two are for the variable length\n        constructor(information) {\n            super(information);\n        }\n        parseInformation() {\n            let buff = new StringBuilder();\n            buff.append('(01)');\n            let initialGtinPosition = buff.length();\n            let firstGtinDigit = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01AndOtherAIs.HEADER_SIZE, 4);\n            buff.append(firstGtinDigit);\n            this.encodeCompressedGtinWithoutAI(buff, AI01AndOtherAIs.HEADER_SIZE + 4, initialGtinPosition);\n            return this.getGeneralDecoder().decodeAllCodes(buff, AI01AndOtherAIs.HEADER_SIZE + 44);\n        }\n    }\n    AI01AndOtherAIs.HEADER_SIZE = 1 + 1 + 2; // first bit encodes the linkage flag,\n\n    class AnyAIDecoder extends AbstractExpandedDecoder {\n        constructor(information) {\n            super(information);\n        }\n        parseInformation() {\n            let buf = new StringBuilder();\n            return this.getGeneralDecoder().decodeAllCodes(buf, AnyAIDecoder.HEADER_SIZE);\n        }\n    }\n    AnyAIDecoder.HEADER_SIZE = 2 + 1 + 2;\n\n    class AI01weightDecoder extends AI01decoder {\n        constructor(information) {\n            super(information);\n        }\n        encodeCompressedWeight(buf, currentPos, weightSize) {\n            let originalWeightNumeric = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos, weightSize);\n            this.addWeightCode(buf, originalWeightNumeric);\n            let weightNumeric = this.checkWeight(originalWeightNumeric);\n            let currentDivisor = 100000;\n            for (let i = 0; i < 5; ++i) {\n                if (weightNumeric / currentDivisor === 0) {\n                    buf.append('0');\n                }\n                currentDivisor /= 10;\n            }\n            buf.append(weightNumeric);\n        }\n    }\n\n    class AI013x0xDecoder extends AI01weightDecoder {\n        constructor(information) {\n            super(information);\n        }\n        parseInformation() {\n            if (this.getInformation().getSize() != AI013x0xDecoder.HEADER_SIZE + AI01weightDecoder.GTIN_SIZE + AI013x0xDecoder.WEIGHT_SIZE) {\n                throw new NotFoundException();\n            }\n            let buf = new StringBuilder();\n            this.encodeCompressedGtin(buf, AI013x0xDecoder.HEADER_SIZE);\n            this.encodeCompressedWeight(buf, AI013x0xDecoder.HEADER_SIZE + AI01weightDecoder.GTIN_SIZE, AI013x0xDecoder.WEIGHT_SIZE);\n            return buf.toString();\n        }\n    }\n    AI013x0xDecoder.HEADER_SIZE = 4 + 1;\n    AI013x0xDecoder.WEIGHT_SIZE = 15;\n\n    class AI013103decoder extends AI013x0xDecoder {\n        constructor(information) {\n            super(information);\n        }\n        addWeightCode(buf, weight) {\n            buf.append('(3103)');\n        }\n        checkWeight(weight) {\n            return weight;\n        }\n    }\n\n    class AI01320xDecoder extends AI013x0xDecoder {\n        constructor(information) {\n            super(information);\n        }\n        addWeightCode(buf, weight) {\n            if (weight < 10000) {\n                buf.append('(3202)');\n            }\n            else {\n                buf.append('(3203)');\n            }\n        }\n        checkWeight(weight) {\n            if (weight < 10000) {\n                return weight;\n            }\n            return weight - 10000;\n        }\n    }\n\n    class AI01392xDecoder extends AI01decoder {\n        constructor(information) {\n            super(information);\n        }\n        parseInformation() {\n            if (this.getInformation().getSize() < AI01392xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE) {\n                throw new NotFoundException();\n            }\n            let buf = new StringBuilder();\n            this.encodeCompressedGtin(buf, AI01392xDecoder.HEADER_SIZE);\n            let lastAIdigit = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01392xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE, AI01392xDecoder.LAST_DIGIT_SIZE);\n            buf.append('(392');\n            buf.append(lastAIdigit);\n            buf.append(')');\n            let decodedInformation = this.getGeneralDecoder().decodeGeneralPurposeField(AI01392xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE + AI01392xDecoder.LAST_DIGIT_SIZE, null);\n            buf.append(decodedInformation.getNewString());\n            return buf.toString();\n        }\n    }\n    AI01392xDecoder.HEADER_SIZE = 5 + 1 + 2;\n    AI01392xDecoder.LAST_DIGIT_SIZE = 2;\n\n    class AI01393xDecoder extends AI01decoder {\n        constructor(information) {\n            super(information);\n        }\n        parseInformation() {\n            if (this.getInformation().getSize() < AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE) {\n                throw new NotFoundException();\n            }\n            let buf = new StringBuilder();\n            this.encodeCompressedGtin(buf, AI01393xDecoder.HEADER_SIZE);\n            let lastAIdigit = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE, AI01393xDecoder.LAST_DIGIT_SIZE);\n            buf.append('(393');\n            buf.append(lastAIdigit);\n            buf.append(')');\n            let firstThreeDigits = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE + AI01393xDecoder.LAST_DIGIT_SIZE, AI01393xDecoder.FIRST_THREE_DIGITS_SIZE);\n            if (firstThreeDigits / 100 == 0) {\n                buf.append('0');\n            }\n            if (firstThreeDigits / 10 == 0) {\n                buf.append('0');\n            }\n            buf.append(firstThreeDigits);\n            let generalInformation = this.getGeneralDecoder().decodeGeneralPurposeField(AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE + AI01393xDecoder.LAST_DIGIT_SIZE + AI01393xDecoder.FIRST_THREE_DIGITS_SIZE, null);\n            buf.append(generalInformation.getNewString());\n            return buf.toString();\n        }\n    }\n    AI01393xDecoder.HEADER_SIZE = 5 + 1 + 2;\n    AI01393xDecoder.LAST_DIGIT_SIZE = 2;\n    AI01393xDecoder.FIRST_THREE_DIGITS_SIZE = 10;\n\n    class AI013x0x1xDecoder extends AI01weightDecoder {\n        constructor(information, firstAIdigits, dateCode) {\n            super(information);\n            this.dateCode = dateCode;\n            this.firstAIdigits = firstAIdigits;\n        }\n        parseInformation() {\n            if (this.getInformation().getSize() != AI013x0x1xDecoder.HEADER_SIZE + AI013x0x1xDecoder.GTIN_SIZE + AI013x0x1xDecoder.WEIGHT_SIZE + AI013x0x1xDecoder.DATE_SIZE) {\n                throw new NotFoundException();\n            }\n            let buf = new StringBuilder();\n            this.encodeCompressedGtin(buf, AI013x0x1xDecoder.HEADER_SIZE);\n            this.encodeCompressedWeight(buf, AI013x0x1xDecoder.HEADER_SIZE + AI013x0x1xDecoder.GTIN_SIZE, AI013x0x1xDecoder.WEIGHT_SIZE);\n            this.encodeCompressedDate(buf, AI013x0x1xDecoder.HEADER_SIZE + AI013x0x1xDecoder.GTIN_SIZE + AI013x0x1xDecoder.WEIGHT_SIZE);\n            return buf.toString();\n        }\n        encodeCompressedDate(buf, currentPos) {\n            let numericDate = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos, AI013x0x1xDecoder.DATE_SIZE);\n            if (numericDate == 38400) {\n                return;\n            }\n            buf.append('(');\n            buf.append(this.dateCode);\n            buf.append(')');\n            let day = numericDate % 32;\n            numericDate /= 32;\n            let month = numericDate % 12 + 1;\n            numericDate /= 12;\n            let year = numericDate;\n            if (year / 10 == 0) {\n                buf.append('0');\n            }\n            buf.append(year);\n            if (month / 10 == 0) {\n                buf.append('0');\n            }\n            buf.append(month);\n            if (day / 10 == 0) {\n                buf.append('0');\n            }\n            buf.append(day);\n        }\n        addWeightCode(buf, weight) {\n            buf.append('(');\n            buf.append(this.firstAIdigits);\n            buf.append(weight / 100000);\n            buf.append(')');\n        }\n        checkWeight(weight) {\n            return weight % 100000;\n        }\n    }\n    AI013x0x1xDecoder.HEADER_SIZE = 7 + 1;\n    AI013x0x1xDecoder.WEIGHT_SIZE = 20;\n    AI013x0x1xDecoder.DATE_SIZE = 16;\n\n    function createDecoder(information) {\n        try {\n            if (information.get(1)) {\n                return new AI01AndOtherAIs(information);\n            }\n            if (!information.get(2)) {\n                return new AnyAIDecoder(information);\n            }\n            let fourBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 4);\n            switch (fourBitEncodationMethod) {\n                case 4: return new AI013103decoder(information);\n                case 5: return new AI01320xDecoder(information);\n            }\n            let fiveBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 5);\n            switch (fiveBitEncodationMethod) {\n                case 12: return new AI01392xDecoder(information);\n                case 13: return new AI01393xDecoder(information);\n            }\n            let sevenBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 7);\n            switch (sevenBitEncodationMethod) {\n                case 56: return new AI013x0x1xDecoder(information, '310', '11');\n                case 57: return new AI013x0x1xDecoder(information, '320', '11');\n                case 58: return new AI013x0x1xDecoder(information, '310', '13');\n                case 59: return new AI013x0x1xDecoder(information, '320', '13');\n                case 60: return new AI013x0x1xDecoder(information, '310', '15');\n                case 61: return new AI013x0x1xDecoder(information, '320', '15');\n                case 62: return new AI013x0x1xDecoder(information, '310', '17');\n                case 63: return new AI013x0x1xDecoder(information, '320', '17');\n            }\n        }\n        catch (e) {\n            console.log(e);\n            throw new IllegalStateException('unknown decoder: ' + information);\n        }\n    }\n\n    class ExpandedPair {\n        constructor(leftChar, rightChar, finderPatter, mayBeLast) {\n            this.leftchar = leftChar;\n            this.rightchar = rightChar;\n            this.finderpattern = finderPatter;\n            this.maybeLast = mayBeLast;\n        }\n        mayBeLast() {\n            return this.maybeLast;\n        }\n        getLeftChar() {\n            return this.leftchar;\n        }\n        getRightChar() {\n            return this.rightchar;\n        }\n        getFinderPattern() {\n            return this.finderpattern;\n        }\n        mustBeLast() {\n            return this.rightchar == null;\n        }\n        toString() {\n            return '[ ' + this.leftchar + ', ' + this.rightchar + ' : ' + (this.finderpattern == null ? 'null' : this.finderpattern.getValue()) + ' ]';\n        }\n        static equals(o1, o2) {\n            if (!(o1 instanceof ExpandedPair)) {\n                return false;\n            }\n            return ExpandedPair.equalsOrNull(o1.leftchar, o2.leftchar) &&\n                ExpandedPair.equalsOrNull(o1.rightchar, o2.rightchar) &&\n                ExpandedPair.equalsOrNull(o1.finderpattern, o2.finderpattern);\n        }\n        static equalsOrNull(o1, o2) {\n            return o1 === null ? o2 === null : ExpandedPair.equals(o1, o2);\n        }\n        hashCode() {\n            // return ExpandedPair.hashNotNull(leftChar) ^ hashNotNull(rightChar) ^ hashNotNull(finderPattern);\n            let value = this.leftchar.getValue() ^ this.rightchar.getValue() ^ this.finderpattern.getValue();\n            return value;\n        }\n    }\n\n    class ExpandedRow {\n        constructor(pairs, rowNumber, wasReversed) {\n            this.pairs = pairs;\n            this.rowNumber = rowNumber;\n            this.wasReversed = wasReversed;\n        }\n        getPairs() {\n            return this.pairs;\n        }\n        getRowNumber() {\n            return this.rowNumber;\n        }\n        isReversed() {\n            return this.wasReversed;\n        }\n        // check implementation\n        isEquivalent(otherPairs) {\n            return this.checkEqualitity(this, otherPairs);\n        }\n        // @Override\n        toString() {\n            return '{ ' + this.pairs + ' }';\n        }\n        /**\n         * Two rows are equal if they contain the same pairs in the same order.\n         */\n        // @Override\n        // check implementation\n        equals(o1, o2) {\n            if (!(o1 instanceof ExpandedRow)) {\n                return false;\n            }\n            return this.checkEqualitity(o1, o2) && o1.wasReversed === o2.wasReversed;\n        }\n        checkEqualitity(pair1, pair2) {\n            if (!pair1 || !pair2)\n                return;\n            let result;\n            pair1.forEach((e1, i) => {\n                pair2.forEach(e2 => {\n                    if (e1.getLeftChar().getValue() === e2.getLeftChar().getValue() && e1.getRightChar().getValue() === e2.getRightChar().getValue() && e1.getFinderPatter().getValue() === e2.getFinderPatter().getValue()) {\n                        result = true;\n                    }\n                });\n            });\n            return result;\n        }\n    }\n\n    // import java.util.ArrayList;\n    // import java.util.Iterator;\n    // import java.util.List;\n    // import java.util.Map;\n    // import java.util.Collections;\n    class RSSExpandedReader extends AbstractRSSReader {\n        constructor(verbose) {\n            super(...arguments);\n            this.pairs = new Array(RSSExpandedReader.MAX_PAIRS);\n            this.rows = new Array();\n            this.startEnd = [2];\n            this.verbose = (verbose === true);\n        }\n        decodeRow(rowNumber, row, hints) {\n            // Rows can start with even pattern in case in prev rows there where odd number of patters.\n            // So lets try twice\n            // this.pairs.clear();\n            this.pairs.length = 0;\n            this.startFromEven = false;\n            try {\n                return RSSExpandedReader.constructResult(this.decodeRow2pairs(rowNumber, row));\n            }\n            catch (e) {\n                // OK\n                if (this.verbose) {\n                    console.log(e);\n                }\n            }\n            this.pairs.length = 0;\n            this.startFromEven = true;\n            return RSSExpandedReader.constructResult(this.decodeRow2pairs(rowNumber, row));\n        }\n        reset() {\n            this.pairs.length = 0;\n            this.rows.length = 0;\n        }\n        // Not private for testing\n        decodeRow2pairs(rowNumber, row) {\n            let done = false;\n            while (!done) {\n                try {\n                    this.pairs.push(this.retrieveNextPair(row, this.pairs, rowNumber));\n                }\n                catch (error) {\n                    if (error instanceof NotFoundException) {\n                        if (!this.pairs.length) {\n                            throw new NotFoundException();\n                        }\n                        // exit this loop when retrieveNextPair() fails and throws\n                        done = true;\n                    }\n                }\n            }\n            // TODO: verify sequence of finder patterns as in checkPairSequence()\n            if (this.checkChecksum()) {\n                return this.pairs;\n            }\n            let tryStackedDecode;\n            if (this.rows.length) {\n                tryStackedDecode = true;\n            }\n            else {\n                tryStackedDecode = false;\n            }\n            // let tryStackedDecode = !this.rows.isEmpty();\n            this.storeRow(rowNumber, false); // TODO: deal with reversed rows\n            if (tryStackedDecode) {\n                // When the image is 180-rotated, then rows are sorted in wrong direction.\n                // Try twice with both the directions.\n                let ps = this.checkRowsBoolean(false);\n                if (ps != null) {\n                    return ps;\n                }\n                ps = this.checkRowsBoolean(true);\n                if (ps != null) {\n                    return ps;\n                }\n            }\n            throw new NotFoundException();\n        }\n        // Need to Verify\n        checkRowsBoolean(reverse) {\n            // Limit number of rows we are checking\n            // We use recursive algorithm with pure complexity and don't want it to take forever\n            // Stacked barcode can have up to 11 rows, so 25 seems reasonable enough\n            if (this.rows.length > 25) {\n                this.rows.length = 0; // We will never have a chance to get result, so clear it\n                return null;\n            }\n            this.pairs.length = 0;\n            if (reverse) {\n                this.rows = this.rows.reverse();\n                // Collections.reverse(this.rows);\n            }\n            let ps = null;\n            try {\n                ps = this.checkRows(new Array(), 0);\n            }\n            catch (e) {\n                // OK\n                if (this.verbose) {\n                    console.log(e);\n                }\n            }\n            if (reverse) {\n                this.rows = this.rows.reverse();\n                // Collections.reverse(this.rows);\n            }\n            return ps;\n        }\n        // Try to construct a valid rows sequence\n        // Recursion is used to implement backtracking\n        checkRows(collectedRows, currentRow) {\n            for (let i = currentRow; i < this.rows.length; i++) {\n                let row = this.rows[i];\n                this.pairs.length = 0;\n                for (let collectedRow of collectedRows) {\n                    this.pairs.push(collectedRow.getPairs());\n                }\n                this.pairs.push(row.getPairs());\n                if (!RSSExpandedReader.isValidSequence(this.pairs)) {\n                    continue;\n                }\n                if (this.checkChecksum()) {\n                    return this.pairs;\n                }\n                let rs = new Array(collectedRows);\n                rs.push(row);\n                try {\n                    // Recursion: try to add more rows\n                    return this.checkRows(rs, i + 1);\n                }\n                catch (e) {\n                    // We failed, try the next candidate\n                    if (this.verbose) {\n                        console.log(e);\n                    }\n                }\n            }\n            throw new NotFoundException();\n        }\n        // Whether the pairs form a valid find pattern sequence,\n        // either complete or a prefix\n        static isValidSequence(pairs) {\n            for (let sequence of RSSExpandedReader.FINDER_PATTERN_SEQUENCES) {\n                if (pairs.length > sequence.length) {\n                    continue;\n                }\n                let stop = true;\n                for (let j = 0; j < pairs.length; j++) {\n                    if (pairs[j].getFinderPattern().getValue() != sequence[j]) {\n                        stop = false;\n                        break;\n                    }\n                }\n                if (stop) {\n                    return true;\n                }\n            }\n            return false;\n        }\n        storeRow(rowNumber, wasReversed) {\n            // Discard if duplicate above or below; otherwise insert in order by row number.\n            let insertPos = 0;\n            let prevIsSame = false;\n            let nextIsSame = false;\n            while (insertPos < this.rows.length) {\n                let erow = this.rows[insertPos];\n                if (erow.getRowNumber() > rowNumber) {\n                    nextIsSame = erow.isEquivalent(this.pairs);\n                    break;\n                }\n                prevIsSame = erow.isEquivalent(this.pairs);\n                insertPos++;\n            }\n            if (nextIsSame || prevIsSame) {\n                return;\n            }\n            // When the row was partially decoded (e.g. 2 pairs found instead of 3),\n            // it will prevent us from detecting the barcode.\n            // Try to merge partial rows\n            // Check whether the row is part of an allready detected row\n            if (RSSExpandedReader.isPartialRow(this.pairs, this.rows)) {\n                return;\n            }\n            this.rows.push(insertPos, new ExpandedRow(this.pairs, rowNumber, wasReversed));\n            this.removePartialRows(this.pairs, this.rows);\n        }\n        // Remove all the rows that contains only specified pairs\n        removePartialRows(pairs, rows) {\n            // for (Iterator<ExpandedRow> iterator = rows.iterator(); iterator.hasNext();) {\n            //   ExpandedRow r = iterator.next();\n            //   if (r.getPairs().size() == pairs.size()) {\n            //     continue;\n            //   }\n            //   boolean allFound = true;\n            //   for (ExpandedPair p : r.getPairs()) {\n            //     boolean found = false;\n            //     for (ExpandedPair pp : pairs) {\n            //       if (p.equals(pp)) {\n            //         found = true;\n            //         break;\n            //       }\n            //     }\n            //     if (!found) {\n            //       allFound = false;\n            //       break;\n            //     }\n            //   }\n            //   if (allFound) {\n            //     // 'pairs' contains all the pairs from the row 'r'\n            //     iterator.remove();\n            //   }\n            // }\n            for (let row of rows) {\n                if (row.getPairs().length === pairs.length) {\n                    continue;\n                }\n                for (let p of row.getPairs()) {\n                    for (let pp of pairs) {\n                        if (ExpandedPair.equals(p, pp)) {\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n        // Returns true when one of the rows already contains all the pairs\n        static isPartialRow(pairs, rows) {\n            for (let r of rows) {\n                let allFound = true;\n                for (let p of pairs) {\n                    let found = false;\n                    for (let pp of r.getPairs()) {\n                        if (p.equals(pp)) {\n                            found = true;\n                            break;\n                        }\n                    }\n                    if (!found) {\n                        allFound = false;\n                        break;\n                    }\n                }\n                if (allFound) {\n                    // the row 'r' contain all the pairs from 'pairs'\n                    return true;\n                }\n            }\n            return false;\n        }\n        // Only used for unit testing\n        getRows() {\n            return this.rows;\n        }\n        // Not private for unit testing\n        static constructResult(pairs) {\n            let binary = BitArrayBuilder.buildBitArray(pairs);\n            let decoder = createDecoder(binary);\n            let resultingString = decoder.parseInformation();\n            let firstPoints = pairs[0].getFinderPattern().getResultPoints();\n            let lastPoints = pairs[pairs.length - 1].getFinderPattern().getResultPoints();\n            let points = [firstPoints[0], firstPoints[1], lastPoints[0], lastPoints[1]];\n            return new Result(resultingString, null, null, points, BarcodeFormat$1.RSS_EXPANDED, null);\n        }\n        checkChecksum() {\n            let firstPair = this.pairs.get(0);\n            let checkCharacter = firstPair.getLeftChar();\n            let firstCharacter = firstPair.getRightChar();\n            if (firstCharacter == null) {\n                return false;\n            }\n            let checksum = firstCharacter.getChecksumPortion();\n            let s = 2;\n            for (let i = 1; i < this.pairs.size(); ++i) {\n                let currentPair = this.pairs.get(i);\n                checksum += currentPair.getLeftChar().getChecksumPortion();\n                s++;\n                let currentRightChar = currentPair.getRightChar();\n                if (currentRightChar != null) {\n                    checksum += currentRightChar.getChecksumPortion();\n                    s++;\n                }\n            }\n            checksum %= 211;\n            let checkCharacterValue = 211 * (s - 4) + checksum;\n            return checkCharacterValue == checkCharacter.getValue();\n        }\n        static getNextSecondBar(row, initialPos) {\n            let currentPos;\n            if (row.get(initialPos)) {\n                currentPos = row.getNextUnset(initialPos);\n                currentPos = row.getNextSet(currentPos);\n            }\n            else {\n                currentPos = row.getNextSet(initialPos);\n                currentPos = row.getNextUnset(currentPos);\n            }\n            return currentPos;\n        }\n        // not private for testing\n        retrieveNextPair(row, previousPairs, rowNumber) {\n            let isOddPattern = previousPairs.length % 2 == 0;\n            if (this.startFromEven) {\n                isOddPattern = !isOddPattern;\n            }\n            let pattern;\n            let keepFinding = true;\n            let forcedOffset = -1;\n            do {\n                this.findNextPair(row, previousPairs, forcedOffset);\n                pattern = this.parseFoundFinderPattern(row, rowNumber, isOddPattern);\n                if (pattern == null) {\n                    forcedOffset = RSSExpandedReader.getNextSecondBar(row, this.startEnd[0]);\n                }\n                else {\n                    keepFinding = false;\n                }\n            } while (keepFinding);\n            // When stacked symbol is split over multiple rows, there's no way to guess if this pair can be last or not.\n            // boolean mayBeLast = checkPairSequence(previousPairs, pattern);\n            let leftChar = this.decodeDataCharacter(row, pattern, isOddPattern, true);\n            if (!this.isEmptyPair(previousPairs) && previousPairs[previousPairs.length - 1].mustBeLast()) {\n                throw new NotFoundException();\n            }\n            let rightChar;\n            try {\n                rightChar = this.decodeDataCharacter(row, pattern, isOddPattern, false);\n            }\n            catch (e) {\n                rightChar = null;\n                if (this.verbose) {\n                    console.log(e);\n                }\n            }\n            return new ExpandedPair(leftChar, rightChar, pattern, true);\n        }\n        isEmptyPair(pairs) {\n            if (pairs.length === 0) {\n                return true;\n            }\n            return false;\n        }\n        findNextPair(row, previousPairs, forcedOffset) {\n            let counters = this.getDecodeFinderCounters();\n            counters[0] = 0;\n            counters[1] = 0;\n            counters[2] = 0;\n            counters[3] = 0;\n            let width = row.getSize();\n            let rowOffset;\n            if (forcedOffset >= 0) {\n                rowOffset = forcedOffset;\n            }\n            else if (this.isEmptyPair(previousPairs)) {\n                rowOffset = 0;\n            }\n            else {\n                let lastPair = previousPairs[previousPairs.length - 1];\n                rowOffset = lastPair.getFinderPattern().getStartEnd()[1];\n            }\n            let searchingEvenPair = previousPairs.length % 2 != 0;\n            if (this.startFromEven) {\n                searchingEvenPair = !searchingEvenPair;\n            }\n            let isWhite = false;\n            while (rowOffset < width) {\n                isWhite = !row.get(rowOffset);\n                if (!isWhite) {\n                    break;\n                }\n                rowOffset++;\n            }\n            let counterPosition = 0;\n            let patternStart = rowOffset;\n            for (let x = rowOffset; x < width; x++) {\n                if (row.get(x) != isWhite) {\n                    counters[counterPosition]++;\n                }\n                else {\n                    if (counterPosition == 3) {\n                        if (searchingEvenPair) {\n                            RSSExpandedReader.reverseCounters(counters);\n                        }\n                        if (RSSExpandedReader.isFinderPattern(counters)) {\n                            this.startEnd[0] = patternStart;\n                            this.startEnd[1] = x;\n                            return;\n                        }\n                        if (searchingEvenPair) {\n                            RSSExpandedReader.reverseCounters(counters);\n                        }\n                        patternStart += counters[0] + counters[1];\n                        counters[0] = counters[2];\n                        counters[1] = counters[3];\n                        counters[2] = 0;\n                        counters[3] = 0;\n                        counterPosition--;\n                    }\n                    else {\n                        counterPosition++;\n                    }\n                    counters[counterPosition] = 1;\n                    isWhite = !isWhite;\n                }\n            }\n            throw new NotFoundException();\n        }\n        static reverseCounters(counters) {\n            let length = counters.length;\n            for (let i = 0; i < length / 2; ++i) {\n                let tmp = counters[i];\n                counters[i] = counters[length - i - 1];\n                counters[length - i - 1] = tmp;\n            }\n        }\n        parseFoundFinderPattern(row, rowNumber, oddPattern) {\n            // Actually we found elements 2-5.\n            let firstCounter;\n            let start;\n            let end;\n            if (oddPattern) {\n                // If pattern number is odd, we need to locate element 1 *before* the current block.\n                let firstElementStart = this.startEnd[0] - 1;\n                // Locate element 1\n                while (firstElementStart >= 0 && !row.get(firstElementStart)) {\n                    firstElementStart--;\n                }\n                firstElementStart++;\n                firstCounter = this.startEnd[0] - firstElementStart;\n                start = firstElementStart;\n                end = this.startEnd[1];\n            }\n            else {\n                // If pattern number is even, the pattern is reversed, so we need to locate element 1 *after* the current block.\n                start = this.startEnd[0];\n                end = row.getNextUnset(this.startEnd[1] + 1);\n                firstCounter = end - this.startEnd[1];\n            }\n            // Make 'counters' hold 1-4\n            let counters = this.getDecodeFinderCounters();\n            System.arraycopy(counters, 0, counters, 1, counters.length - 1);\n            counters[0] = firstCounter;\n            let value;\n            try {\n                value = this.parseFinderValue(counters, RSSExpandedReader.FINDER_PATTERNS);\n            }\n            catch (e) {\n                return null;\n            }\n            // return new FinderPattern(value, new int[] { start, end }, start, end, rowNumber});\n            return new FinderPattern(value, [start, end], start, end, rowNumber);\n        }\n        decodeDataCharacter(row, pattern, isOddPattern, leftChar) {\n            let counters = this.getDataCharacterCounters();\n            for (let x = 0; x < counters.length; x++) {\n                counters[x] = 0;\n            }\n            if (leftChar) {\n                RSSExpandedReader.recordPatternInReverse(row, pattern.getStartEnd()[0], counters);\n            }\n            else {\n                RSSExpandedReader.recordPattern(row, pattern.getStartEnd()[1], counters);\n                // reverse it\n                for (let i = 0, j = counters.length - 1; i < j; i++, j--) {\n                    let temp = counters[i];\n                    counters[i] = counters[j];\n                    counters[j] = temp;\n                }\n            } // counters[] has the pixels of the module\n            let numModules = 17; // left and right data characters have all the same length\n            let elementWidth = MathUtils.sum(new Int32Array(counters)) / numModules;\n            // Sanity check: element width for pattern and the character should match\n            let expectedElementWidth = (pattern.getStartEnd()[1] - pattern.getStartEnd()[0]) / 15.0;\n            if (Math.abs(elementWidth - expectedElementWidth) / expectedElementWidth > 0.3) {\n                throw new NotFoundException();\n            }\n            let oddCounts = this.getOddCounts();\n            let evenCounts = this.getEvenCounts();\n            let oddRoundingErrors = this.getOddRoundingErrors();\n            let evenRoundingErrors = this.getEvenRoundingErrors();\n            for (let i = 0; i < counters.length; i++) {\n                let value = 1.0 * counters[i] / elementWidth;\n                let count = value + 0.5; // Round\n                if (count < 1) {\n                    if (value < 0.3) {\n                        throw new NotFoundException();\n                    }\n                    count = 1;\n                }\n                else if (count > 8) {\n                    if (value > 8.7) {\n                        throw new NotFoundException();\n                    }\n                    count = 8;\n                }\n                let offset = i / 2;\n                if ((i & 0x01) == 0) {\n                    oddCounts[offset] = count;\n                    oddRoundingErrors[offset] = value - count;\n                }\n                else {\n                    evenCounts[offset] = count;\n                    evenRoundingErrors[offset] = value - count;\n                }\n            }\n            this.adjustOddEvenCounts(numModules);\n            let weightRowNumber = 4 * pattern.getValue() + (isOddPattern ? 0 : 2) + (leftChar ? 0 : 1) - 1;\n            let oddSum = 0;\n            let oddChecksumPortion = 0;\n            for (let i = oddCounts.length - 1; i >= 0; i--) {\n                if (RSSExpandedReader.isNotA1left(pattern, isOddPattern, leftChar)) {\n                    let weight = RSSExpandedReader.WEIGHTS[weightRowNumber][2 * i];\n                    oddChecksumPortion += oddCounts[i] * weight;\n                }\n                oddSum += oddCounts[i];\n            }\n            let evenChecksumPortion = 0;\n            // int evenSum = 0;\n            for (let i = evenCounts.length - 1; i >= 0; i--) {\n                if (RSSExpandedReader.isNotA1left(pattern, isOddPattern, leftChar)) {\n                    let weight = RSSExpandedReader.WEIGHTS[weightRowNumber][2 * i + 1];\n                    evenChecksumPortion += evenCounts[i] * weight;\n                }\n                // evenSum += evenCounts[i];\n            }\n            let checksumPortion = oddChecksumPortion + evenChecksumPortion;\n            if ((oddSum & 0x01) != 0 || oddSum > 13 || oddSum < 4) {\n                throw new NotFoundException();\n            }\n            let group = (13 - oddSum) / 2;\n            let oddWidest = RSSExpandedReader.SYMBOL_WIDEST[group];\n            let evenWidest = 9 - oddWidest;\n            let vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, true);\n            let vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, false);\n            let tEven = RSSExpandedReader.EVEN_TOTAL_SUBSET[group];\n            let gSum = RSSExpandedReader.GSUM[group];\n            let value = vOdd * tEven + vEven + gSum;\n            return new DataCharacter(value, checksumPortion);\n        }\n        static isNotA1left(pattern, isOddPattern, leftChar) {\n            // A1: pattern.getValue is 0 (A), and it's an oddPattern, and it is a left char\n            return !(pattern.getValue() == 0 && isOddPattern && leftChar);\n        }\n        adjustOddEvenCounts(numModules) {\n            let oddSum = MathUtils.sum(new Int32Array(this.getOddCounts()));\n            let evenSum = MathUtils.sum(new Int32Array(this.getEvenCounts()));\n            let incrementOdd = false;\n            let decrementOdd = false;\n            if (oddSum > 13) {\n                decrementOdd = true;\n            }\n            else if (oddSum < 4) {\n                incrementOdd = true;\n            }\n            let incrementEven = false;\n            let decrementEven = false;\n            if (evenSum > 13) {\n                decrementEven = true;\n            }\n            else if (evenSum < 4) {\n                incrementEven = true;\n            }\n            let mismatch = oddSum + evenSum - numModules;\n            let oddParityBad = (oddSum & 0x01) == 1;\n            let evenParityBad = (evenSum & 0x01) == 0;\n            if (mismatch == 1) {\n                if (oddParityBad) {\n                    if (evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    decrementOdd = true;\n                }\n                else {\n                    if (!evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    decrementEven = true;\n                }\n            }\n            else if (mismatch == -1) {\n                if (oddParityBad) {\n                    if (evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    incrementOdd = true;\n                }\n                else {\n                    if (!evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    incrementEven = true;\n                }\n            }\n            else if (mismatch == 0) {\n                if (oddParityBad) {\n                    if (!evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    // Both bad\n                    if (oddSum < evenSum) {\n                        incrementOdd = true;\n                        decrementEven = true;\n                    }\n                    else {\n                        decrementOdd = true;\n                        incrementEven = true;\n                    }\n                }\n                else {\n                    if (evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    // Nothing to do!\n                }\n            }\n            else {\n                throw new NotFoundException();\n            }\n            if (incrementOdd) {\n                if (decrementOdd) {\n                    throw new NotFoundException();\n                }\n                RSSExpandedReader.increment(this.getOddCounts(), this.getOddRoundingErrors());\n            }\n            if (decrementOdd) {\n                RSSExpandedReader.decrement(this.getOddCounts(), this.getOddRoundingErrors());\n            }\n            if (incrementEven) {\n                if (decrementEven) {\n                    throw new NotFoundException();\n                }\n                RSSExpandedReader.increment(this.getEvenCounts(), this.getOddRoundingErrors());\n            }\n            if (decrementEven) {\n                RSSExpandedReader.decrement(this.getEvenCounts(), this.getEvenRoundingErrors());\n            }\n        }\n    }\n    RSSExpandedReader.SYMBOL_WIDEST = [7, 5, 4, 3, 1];\n    RSSExpandedReader.EVEN_TOTAL_SUBSET = [4, 20, 52, 104, 204];\n    RSSExpandedReader.GSUM = [0, 348, 1388, 2948, 3988];\n    RSSExpandedReader.FINDER_PATTERNS = [\n        Int32Array.from([1, 8, 4, 1]),\n        Int32Array.from([3, 6, 4, 1]),\n        Int32Array.from([3, 4, 6, 1]),\n        Int32Array.from([3, 2, 8, 1]),\n        Int32Array.from([2, 6, 5, 1]),\n        Int32Array.from([2, 2, 9, 1]) // F\n    ];\n    RSSExpandedReader.WEIGHTS = [\n        [1, 3, 9, 27, 81, 32, 96, 77],\n        [20, 60, 180, 118, 143, 7, 21, 63],\n        [189, 145, 13, 39, 117, 140, 209, 205],\n        [193, 157, 49, 147, 19, 57, 171, 91],\n        [62, 186, 136, 197, 169, 85, 44, 132],\n        [185, 133, 188, 142, 4, 12, 36, 108],\n        [113, 128, 173, 97, 80, 29, 87, 50],\n        [150, 28, 84, 41, 123, 158, 52, 156],\n        [46, 138, 203, 187, 139, 206, 196, 166],\n        [76, 17, 51, 153, 37, 111, 122, 155],\n        [43, 129, 176, 106, 107, 110, 119, 146],\n        [16, 48, 144, 10, 30, 90, 59, 177],\n        [109, 116, 137, 200, 178, 112, 125, 164],\n        [70, 210, 208, 202, 184, 130, 179, 115],\n        [134, 191, 151, 31, 93, 68, 204, 190],\n        [148, 22, 66, 198, 172, 94, 71, 2],\n        [6, 18, 54, 162, 64, 192, 154, 40],\n        [120, 149, 25, 75, 14, 42, 126, 167],\n        [79, 26, 78, 23, 69, 207, 199, 175],\n        [103, 98, 83, 38, 114, 131, 182, 124],\n        [161, 61, 183, 127, 170, 88, 53, 159],\n        [55, 165, 73, 8, 24, 72, 5, 15],\n        [45, 135, 194, 160, 58, 174, 100, 89]\n    ];\n    RSSExpandedReader.FINDER_PAT_A = 0;\n    RSSExpandedReader.FINDER_PAT_B = 1;\n    RSSExpandedReader.FINDER_PAT_C = 2;\n    RSSExpandedReader.FINDER_PAT_D = 3;\n    RSSExpandedReader.FINDER_PAT_E = 4;\n    RSSExpandedReader.FINDER_PAT_F = 5;\n    RSSExpandedReader.FINDER_PATTERN_SEQUENCES = [\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_D],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_C],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_F],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_F, RSSExpandedReader.FINDER_PAT_F],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_D],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_E],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_F, RSSExpandedReader.FINDER_PAT_F],\n        [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_F, RSSExpandedReader.FINDER_PAT_F],\n    ];\n    RSSExpandedReader.MAX_PAIRS = 11;\n\n    class Pair extends DataCharacter {\n        constructor(value, checksumPortion, finderPattern) {\n            super(value, checksumPortion);\n            this.count = 0;\n            this.finderPattern = finderPattern;\n        }\n        getFinderPattern() {\n            return this.finderPattern;\n        }\n        getCount() {\n            return this.count;\n        }\n        incrementCount() {\n            this.count++;\n        }\n    }\n\n    class RSS14Reader extends AbstractRSSReader {\n        constructor() {\n            super(...arguments);\n            this.possibleLeftPairs = [];\n            this.possibleRightPairs = [];\n        }\n        decodeRow(rowNumber, row, hints) {\n            const leftPair = this.decodePair(row, false, rowNumber, hints);\n            RSS14Reader.addOrTally(this.possibleLeftPairs, leftPair);\n            row.reverse();\n            let rightPair = this.decodePair(row, true, rowNumber, hints);\n            RSS14Reader.addOrTally(this.possibleRightPairs, rightPair);\n            row.reverse();\n            for (let left of this.possibleLeftPairs) {\n                if (left.getCount() > 1) {\n                    for (let right of this.possibleRightPairs) {\n                        if (right.getCount() > 1 && RSS14Reader.checkChecksum(left, right)) {\n                            return RSS14Reader.constructResult(left, right);\n                        }\n                    }\n                }\n            }\n            throw new NotFoundException();\n        }\n        static addOrTally(possiblePairs, pair) {\n            if (pair == null) {\n                return;\n            }\n            let found = false;\n            for (let other of possiblePairs) {\n                if (other.getValue() === pair.getValue()) {\n                    other.incrementCount();\n                    found = true;\n                    break;\n                }\n            }\n            if (!found) {\n                possiblePairs.push(pair);\n            }\n        }\n        reset() {\n            this.possibleLeftPairs.length = 0;\n            this.possibleRightPairs.length = 0;\n        }\n        static constructResult(leftPair, rightPair) {\n            let symbolValue = 4537077 * leftPair.getValue() + rightPair.getValue();\n            let text = new String(symbolValue).toString();\n            let buffer = new StringBuilder();\n            for (let i = 13 - text.length; i > 0; i--) {\n                buffer.append('0');\n            }\n            buffer.append(text);\n            let checkDigit = 0;\n            for (let i = 0; i < 13; i++) {\n                let digit = buffer.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n                checkDigit += ((i & 0x01) === 0) ? 3 * digit : digit;\n            }\n            checkDigit = 10 - (checkDigit % 10);\n            if (checkDigit === 10) {\n                checkDigit = 0;\n            }\n            buffer.append(checkDigit.toString());\n            let leftPoints = leftPair.getFinderPattern().getResultPoints();\n            let rightPoints = rightPair.getFinderPattern().getResultPoints();\n            return new Result(buffer.toString(), null, 0, [leftPoints[0], leftPoints[1], rightPoints[0], rightPoints[1]], BarcodeFormat$1.RSS_14, new Date().getTime());\n        }\n        static checkChecksum(leftPair, rightPair) {\n            let checkValue = (leftPair.getChecksumPortion() + 16 * rightPair.getChecksumPortion()) % 79;\n            let targetCheckValue = 9 * leftPair.getFinderPattern().getValue() + rightPair.getFinderPattern().getValue();\n            if (targetCheckValue > 72) {\n                targetCheckValue--;\n            }\n            if (targetCheckValue > 8) {\n                targetCheckValue--;\n            }\n            return checkValue === targetCheckValue;\n        }\n        decodePair(row, right, rowNumber, hints) {\n            try {\n                let startEnd = this.findFinderPattern(row, right);\n                let pattern = this.parseFoundFinderPattern(row, rowNumber, right, startEnd);\n                let resultPointCallback = hints == null ? null : hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n                if (resultPointCallback != null) {\n                    let center = (startEnd[0] + startEnd[1]) / 2.0;\n                    if (right) {\n                        // row is actually reversed\n                        center = row.getSize() - 1 - center;\n                    }\n                    resultPointCallback.foundPossibleResultPoint(new ResultPoint(center, rowNumber));\n                }\n                let outside = this.decodeDataCharacter(row, pattern, true);\n                let inside = this.decodeDataCharacter(row, pattern, false);\n                return new Pair(1597 * outside.getValue() + inside.getValue(), outside.getChecksumPortion() + 4 * inside.getChecksumPortion(), pattern);\n            }\n            catch (err) {\n                return null;\n            }\n        }\n        decodeDataCharacter(row, pattern, outsideChar) {\n            let counters = this.getDataCharacterCounters();\n            for (let x = 0; x < counters.length; x++) {\n                counters[x] = 0;\n            }\n            if (outsideChar) {\n                OneDReader.recordPatternInReverse(row, pattern.getStartEnd()[0], counters);\n            }\n            else {\n                OneDReader.recordPattern(row, pattern.getStartEnd()[1] + 1, counters);\n                // reverse it\n                for (let i = 0, j = counters.length - 1; i < j; i++, j--) {\n                    let temp = counters[i];\n                    counters[i] = counters[j];\n                    counters[j] = temp;\n                }\n            }\n            let numModules = outsideChar ? 16 : 15;\n            let elementWidth = MathUtils.sum(new Int32Array(counters)) / numModules;\n            let oddCounts = this.getOddCounts();\n            let evenCounts = this.getEvenCounts();\n            let oddRoundingErrors = this.getOddRoundingErrors();\n            let evenRoundingErrors = this.getEvenRoundingErrors();\n            for (let i = 0; i < counters.length; i++) {\n                let value = counters[i] / elementWidth;\n                let count = Math.floor(value + 0.5);\n                if (count < 1) {\n                    count = 1;\n                }\n                else if (count > 8) {\n                    count = 8;\n                }\n                let offset = Math.floor(i / 2);\n                if ((i & 0x01) === 0) {\n                    oddCounts[offset] = count;\n                    oddRoundingErrors[offset] = value - count;\n                }\n                else {\n                    evenCounts[offset] = count;\n                    evenRoundingErrors[offset] = value - count;\n                }\n            }\n            this.adjustOddEvenCounts(outsideChar, numModules);\n            let oddSum = 0;\n            let oddChecksumPortion = 0;\n            for (let i = oddCounts.length - 1; i >= 0; i--) {\n                oddChecksumPortion *= 9;\n                oddChecksumPortion += oddCounts[i];\n                oddSum += oddCounts[i];\n            }\n            let evenChecksumPortion = 0;\n            let evenSum = 0;\n            for (let i = evenCounts.length - 1; i >= 0; i--) {\n                evenChecksumPortion *= 9;\n                evenChecksumPortion += evenCounts[i];\n                evenSum += evenCounts[i];\n            }\n            let checksumPortion = oddChecksumPortion + 3 * evenChecksumPortion;\n            if (outsideChar) {\n                if ((oddSum & 0x01) !== 0 || oddSum > 12 || oddSum < 4) {\n                    throw new NotFoundException();\n                }\n                let group = (12 - oddSum) / 2;\n                let oddWidest = RSS14Reader.OUTSIDE_ODD_WIDEST[group];\n                let evenWidest = 9 - oddWidest;\n                let vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, false);\n                let vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, true);\n                let tEven = RSS14Reader.OUTSIDE_EVEN_TOTAL_SUBSET[group];\n                let gSum = RSS14Reader.OUTSIDE_GSUM[group];\n                return new DataCharacter(vOdd * tEven + vEven + gSum, checksumPortion);\n            }\n            else {\n                if ((evenSum & 0x01) !== 0 || evenSum > 10 || evenSum < 4) {\n                    throw new NotFoundException();\n                }\n                let group = (10 - evenSum) / 2;\n                let oddWidest = RSS14Reader.INSIDE_ODD_WIDEST[group];\n                let evenWidest = 9 - oddWidest;\n                let vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, true);\n                let vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, false);\n                let tOdd = RSS14Reader.INSIDE_ODD_TOTAL_SUBSET[group];\n                let gSum = RSS14Reader.INSIDE_GSUM[group];\n                return new DataCharacter(vEven * tOdd + vOdd + gSum, checksumPortion);\n            }\n        }\n        findFinderPattern(row, rightFinderPattern) {\n            let counters = this.getDecodeFinderCounters();\n            counters[0] = 0;\n            counters[1] = 0;\n            counters[2] = 0;\n            counters[3] = 0;\n            let width = row.getSize();\n            let isWhite = false;\n            let rowOffset = 0;\n            while (rowOffset < width) {\n                isWhite = !row.get(rowOffset);\n                if (rightFinderPattern === isWhite) {\n                    // Will encounter white first when searching for right finder pattern\n                    break;\n                }\n                rowOffset++;\n            }\n            let counterPosition = 0;\n            let patternStart = rowOffset;\n            for (let x = rowOffset; x < width; x++) {\n                if (row.get(x) !== isWhite) {\n                    counters[counterPosition]++;\n                }\n                else {\n                    if (counterPosition === 3) {\n                        if (AbstractRSSReader.isFinderPattern(counters)) {\n                            return [patternStart, x];\n                        }\n                        patternStart += counters[0] + counters[1];\n                        counters[0] = counters[2];\n                        counters[1] = counters[3];\n                        counters[2] = 0;\n                        counters[3] = 0;\n                        counterPosition--;\n                    }\n                    else {\n                        counterPosition++;\n                    }\n                    counters[counterPosition] = 1;\n                    isWhite = !isWhite;\n                }\n            }\n            throw new NotFoundException();\n        }\n        parseFoundFinderPattern(row, rowNumber, right, startEnd) {\n            // Actually we found elements 2-5\n            let firstIsBlack = row.get(startEnd[0]);\n            let firstElementStart = startEnd[0] - 1;\n            // Locate element 1\n            while (firstElementStart >= 0 && firstIsBlack !== row.get(firstElementStart)) {\n                firstElementStart--;\n            }\n            firstElementStart++;\n            const firstCounter = startEnd[0] - firstElementStart;\n            // Make 'counters' hold 1-4\n            const counters = this.getDecodeFinderCounters();\n            const copy = new Int32Array(counters.length);\n            System.arraycopy(counters, 0, copy, 1, counters.length - 1);\n            copy[0] = firstCounter;\n            const value = this.parseFinderValue(copy, RSS14Reader.FINDER_PATTERNS);\n            let start = firstElementStart;\n            let end = startEnd[1];\n            if (right) {\n                // row is actually reversed\n                start = row.getSize() - 1 - start;\n                end = row.getSize() - 1 - end;\n            }\n            return new FinderPattern(value, [firstElementStart, startEnd[1]], start, end, rowNumber);\n        }\n        adjustOddEvenCounts(outsideChar, numModules) {\n            let oddSum = MathUtils.sum(new Int32Array(this.getOddCounts()));\n            let evenSum = MathUtils.sum(new Int32Array(this.getEvenCounts()));\n            let incrementOdd = false;\n            let decrementOdd = false;\n            let incrementEven = false;\n            let decrementEven = false;\n            if (outsideChar) {\n                if (oddSum > 12) {\n                    decrementOdd = true;\n                }\n                else if (oddSum < 4) {\n                    incrementOdd = true;\n                }\n                if (evenSum > 12) {\n                    decrementEven = true;\n                }\n                else if (evenSum < 4) {\n                    incrementEven = true;\n                }\n            }\n            else {\n                if (oddSum > 11) {\n                    decrementOdd = true;\n                }\n                else if (oddSum < 5) {\n                    incrementOdd = true;\n                }\n                if (evenSum > 10) {\n                    decrementEven = true;\n                }\n                else if (evenSum < 4) {\n                    incrementEven = true;\n                }\n            }\n            let mismatch = oddSum + evenSum - numModules;\n            let oddParityBad = (oddSum & 0x01) === (outsideChar ? 1 : 0);\n            let evenParityBad = (evenSum & 0x01) === 1;\n            if (mismatch === 1) {\n                if (oddParityBad) {\n                    if (evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    decrementOdd = true;\n                }\n                else {\n                    if (!evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    decrementEven = true;\n                }\n            }\n            else if (mismatch === -1) {\n                if (oddParityBad) {\n                    if (evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    incrementOdd = true;\n                }\n                else {\n                    if (!evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    incrementEven = true;\n                }\n            }\n            else if (mismatch === 0) {\n                if (oddParityBad) {\n                    if (!evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    // Both bad\n                    if (oddSum < evenSum) {\n                        incrementOdd = true;\n                        decrementEven = true;\n                    }\n                    else {\n                        decrementOdd = true;\n                        incrementEven = true;\n                    }\n                }\n                else {\n                    if (evenParityBad) {\n                        throw new NotFoundException();\n                    }\n                    // Nothing to do!\n                }\n            }\n            else {\n                throw new NotFoundException();\n            }\n            if (incrementOdd) {\n                if (decrementOdd) {\n                    throw new NotFoundException();\n                }\n                AbstractRSSReader.increment(this.getOddCounts(), this.getOddRoundingErrors());\n            }\n            if (decrementOdd) {\n                AbstractRSSReader.decrement(this.getOddCounts(), this.getOddRoundingErrors());\n            }\n            if (incrementEven) {\n                if (decrementEven) {\n                    throw new NotFoundException();\n                }\n                AbstractRSSReader.increment(this.getEvenCounts(), this.getOddRoundingErrors());\n            }\n            if (decrementEven) {\n                AbstractRSSReader.decrement(this.getEvenCounts(), this.getEvenRoundingErrors());\n            }\n        }\n    }\n    RSS14Reader.OUTSIDE_EVEN_TOTAL_SUBSET = [1, 10, 34, 70, 126];\n    RSS14Reader.INSIDE_ODD_TOTAL_SUBSET = [4, 20, 48, 81];\n    RSS14Reader.OUTSIDE_GSUM = [0, 161, 961, 2015, 2715];\n    RSS14Reader.INSIDE_GSUM = [0, 336, 1036, 1516];\n    RSS14Reader.OUTSIDE_ODD_WIDEST = [8, 6, 4, 3, 1];\n    RSS14Reader.INSIDE_ODD_WIDEST = [2, 4, 6, 8];\n    RSS14Reader.FINDER_PATTERNS = [\n        Int32Array.from([3, 8, 2, 1]),\n        Int32Array.from([3, 5, 5, 1]),\n        Int32Array.from([3, 3, 7, 1]),\n        Int32Array.from([3, 1, 9, 1]),\n        Int32Array.from([2, 7, 4, 1]),\n        Int32Array.from([2, 5, 6, 1]),\n        Int32Array.from([2, 3, 8, 1]),\n        Int32Array.from([1, 5, 7, 1]),\n        Int32Array.from([1, 3, 9, 1]),\n    ];\n\n    /**\n     * @author Daniel Switkin <dswitkin@google.com>\n     * @author Sean Owen\n     */\n    class MultiFormatOneDReader extends OneDReader {\n        constructor(hints, verbose) {\n            super();\n            this.readers = [];\n            this.verbose = (verbose === true);\n            const possibleFormats = !hints ? null : hints.get(DecodeHintType$1.POSSIBLE_FORMATS);\n            const useCode39CheckDigit = hints && hints.get(DecodeHintType$1.ASSUME_CODE_39_CHECK_DIGIT) !== undefined;\n            if (possibleFormats) {\n                if (possibleFormats.includes(BarcodeFormat$1.EAN_13) ||\n                    possibleFormats.includes(BarcodeFormat$1.UPC_A) ||\n                    possibleFormats.includes(BarcodeFormat$1.EAN_8) ||\n                    possibleFormats.includes(BarcodeFormat$1.UPC_E)) {\n                    this.readers.push(new MultiFormatUPCEANReader(hints));\n                }\n                if (possibleFormats.includes(BarcodeFormat$1.CODE_39)) {\n                    this.readers.push(new Code39Reader(useCode39CheckDigit));\n                }\n                // if (possibleFormats.includes(BarcodeFormat.CODE_93)) {\n                //    this.readers.push(new Code93Reader());\n                // }\n                if (possibleFormats.includes(BarcodeFormat$1.CODE_128)) {\n                    this.readers.push(new Code128Reader());\n                }\n                if (possibleFormats.includes(BarcodeFormat$1.ITF)) {\n                    this.readers.push(new ITFReader());\n                }\n                // if (possibleFormats.includes(BarcodeFormat.CODABAR)) {\n                //    this.readers.push(new CodaBarReader());\n                // }\n                if (possibleFormats.includes(BarcodeFormat$1.RSS_14)) {\n                    this.readers.push(new RSS14Reader());\n                }\n                if (possibleFormats.includes(BarcodeFormat$1.RSS_EXPANDED)) {\n                    this.readers.push(new RSSExpandedReader(this.verbose));\n                }\n            } else {\n                // Case when no hints were provided -> add all.\n                this.readers.push(new MultiFormatUPCEANReader(hints));\n                this.readers.push(new Code39Reader());\n                // this.readers.push(new CodaBarReader());\n                // this.readers.push(new Code93Reader());\n                this.readers.push(new MultiFormatUPCEANReader(hints));\n                this.readers.push(new Code128Reader());\n                this.readers.push(new ITFReader());\n                this.readers.push(new RSS14Reader());\n                this.readers.push(new RSSExpandedReader(this.verbose));\n            }\n        }\n        // @Override\n        decodeRow(rowNumber, row, hints) {\n            for (let i = 0; i < this.readers.length; i++) {\n                try {\n                    return this.readers[i].decodeRow(rowNumber, row, hints);\n                }\n                catch (re) {\n                    // continue\n                }\n            }\n            throw new NotFoundException();\n        }\n        // @Override\n        reset() {\n            this.readers.forEach(reader => reader.reset());\n        }\n    }\n\n    /**\n     * @deprecated Moving to @zxing/browser\n     *\n     * Barcode reader reader to use from browser.\n     */\n    class BrowserBarcodeReader extends BrowserCodeReader {\n        /**\n         * Creates an instance of BrowserBarcodeReader.\n         * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n         * @param {Map<DecodeHintType, any>} hints\n         */\n        constructor(timeBetweenScansMillis = 500, hints) {\n            super(new MultiFormatOneDReader(hints), timeBetweenScansMillis, hints);\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will\n     * use blocks of differing sizes within one version, so, this encapsulates the parameters for\n     * each set of blocks. It also holds the number of error-correction codewords per block since it\n     * will be the same across all blocks within one version.</p>\n     */\n    class ECBlocks {\n        constructor(ecCodewords, ecBlocks1, ecBlocks2) {\n            this.ecCodewords = ecCodewords;\n            this.ecBlocks = [ecBlocks1];\n            ecBlocks2 && this.ecBlocks.push(ecBlocks2);\n        }\n        getECCodewords() {\n            return this.ecCodewords;\n        }\n        getECBlocks() {\n            return this.ecBlocks;\n        }\n    }\n    /**\n     * <p>Encapsulates the parameters for one error-correction block in one symbol version.\n     * This includes the number of data codewords, and the number of times a block with these\n     * parameters is used consecutively in the Data Matrix code version's format.</p>\n     */\n    class ECB {\n        constructor(count, dataCodewords) {\n            this.count = count;\n            this.dataCodewords = dataCodewords;\n        }\n        getCount() {\n            return this.count;\n        }\n        getDataCodewords() {\n            return this.dataCodewords;\n        }\n    }\n    /**\n     * The Version object encapsulates attributes about a particular\n     * size Data Matrix Code.\n     *\n     * @author bbrown@google.com (Brian Brown)\n     */\n    class Version {\n        constructor(versionNumber, symbolSizeRows, symbolSizeColumns, dataRegionSizeRows, dataRegionSizeColumns, ecBlocks) {\n            this.versionNumber = versionNumber;\n            this.symbolSizeRows = symbolSizeRows;\n            this.symbolSizeColumns = symbolSizeColumns;\n            this.dataRegionSizeRows = dataRegionSizeRows;\n            this.dataRegionSizeColumns = dataRegionSizeColumns;\n            this.ecBlocks = ecBlocks;\n            // Calculate the total number of codewords\n            let total = 0;\n            const ecCodewords = ecBlocks.getECCodewords();\n            const ecbArray = ecBlocks.getECBlocks();\n            for (let ecBlock of ecbArray) {\n                total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);\n            }\n            this.totalCodewords = total;\n        }\n        getVersionNumber() {\n            return this.versionNumber;\n        }\n        getSymbolSizeRows() {\n            return this.symbolSizeRows;\n        }\n        getSymbolSizeColumns() {\n            return this.symbolSizeColumns;\n        }\n        getDataRegionSizeRows() {\n            return this.dataRegionSizeRows;\n        }\n        getDataRegionSizeColumns() {\n            return this.dataRegionSizeColumns;\n        }\n        getTotalCodewords() {\n            return this.totalCodewords;\n        }\n        getECBlocks() {\n            return this.ecBlocks;\n        }\n        /**\n         * <p>Deduces version information from Data Matrix dimensions.</p>\n         *\n         * @param numRows Number of rows in modules\n         * @param numColumns Number of columns in modules\n         * @return Version for a Data Matrix Code of those dimensions\n         * @throws FormatException if dimensions do correspond to a valid Data Matrix size\n         */\n        static getVersionForDimensions(numRows, numColumns) {\n            if ((numRows & 0x01) !== 0 || (numColumns & 0x01) !== 0) {\n                throw new FormatException();\n            }\n            for (let version of Version.VERSIONS) {\n                if (version.symbolSizeRows === numRows && version.symbolSizeColumns === numColumns) {\n                    return version;\n                }\n            }\n            throw new FormatException();\n        }\n        //  @Override\n        toString() {\n            return '' + this.versionNumber;\n        }\n        /**\n         * See ISO 16022:2006 5.5.1 Table 7\n         */\n        static buildVersions() {\n            return [\n                new Version(1, 10, 10, 8, 8, new ECBlocks(5, new ECB(1, 3))),\n                new Version(2, 12, 12, 10, 10, new ECBlocks(7, new ECB(1, 5))),\n                new Version(3, 14, 14, 12, 12, new ECBlocks(10, new ECB(1, 8))),\n                new Version(4, 16, 16, 14, 14, new ECBlocks(12, new ECB(1, 12))),\n                new Version(5, 18, 18, 16, 16, new ECBlocks(14, new ECB(1, 18))),\n                new Version(6, 20, 20, 18, 18, new ECBlocks(18, new ECB(1, 22))),\n                new Version(7, 22, 22, 20, 20, new ECBlocks(20, new ECB(1, 30))),\n                new Version(8, 24, 24, 22, 22, new ECBlocks(24, new ECB(1, 36))),\n                new Version(9, 26, 26, 24, 24, new ECBlocks(28, new ECB(1, 44))),\n                new Version(10, 32, 32, 14, 14, new ECBlocks(36, new ECB(1, 62))),\n                new Version(11, 36, 36, 16, 16, new ECBlocks(42, new ECB(1, 86))),\n                new Version(12, 40, 40, 18, 18, new ECBlocks(48, new ECB(1, 114))),\n                new Version(13, 44, 44, 20, 20, new ECBlocks(56, new ECB(1, 144))),\n                new Version(14, 48, 48, 22, 22, new ECBlocks(68, new ECB(1, 174))),\n                new Version(15, 52, 52, 24, 24, new ECBlocks(42, new ECB(2, 102))),\n                new Version(16, 64, 64, 14, 14, new ECBlocks(56, new ECB(2, 140))),\n                new Version(17, 72, 72, 16, 16, new ECBlocks(36, new ECB(4, 92))),\n                new Version(18, 80, 80, 18, 18, new ECBlocks(48, new ECB(4, 114))),\n                new Version(19, 88, 88, 20, 20, new ECBlocks(56, new ECB(4, 144))),\n                new Version(20, 96, 96, 22, 22, new ECBlocks(68, new ECB(4, 174))),\n                new Version(21, 104, 104, 24, 24, new ECBlocks(56, new ECB(6, 136))),\n                new Version(22, 120, 120, 18, 18, new ECBlocks(68, new ECB(6, 175))),\n                new Version(23, 132, 132, 20, 20, new ECBlocks(62, new ECB(8, 163))),\n                new Version(24, 144, 144, 22, 22, new ECBlocks(62, new ECB(8, 156), new ECB(2, 155))),\n                new Version(25, 8, 18, 6, 16, new ECBlocks(7, new ECB(1, 5))),\n                new Version(26, 8, 32, 6, 14, new ECBlocks(11, new ECB(1, 10))),\n                new Version(27, 12, 26, 10, 24, new ECBlocks(14, new ECB(1, 16))),\n                new Version(28, 12, 36, 10, 16, new ECBlocks(18, new ECB(1, 22))),\n                new Version(29, 16, 36, 14, 16, new ECBlocks(24, new ECB(1, 32))),\n                new Version(30, 16, 48, 14, 22, new ECBlocks(28, new ECB(1, 49)))\n            ];\n        }\n    }\n    Version.VERSIONS = Version.buildVersions();\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * @author bbrown@google.com (Brian Brown)\n     */\n    class BitMatrixParser {\n        /**\n         * @param bitMatrix {@link BitMatrix} to parse\n         * @throws FormatException if dimension is < 8 or > 144 or not 0 mod 2\n         */\n        constructor(bitMatrix) {\n            const dimension = bitMatrix.getHeight();\n            if (dimension < 8 || dimension > 144 || (dimension & 0x01) !== 0) {\n                throw new FormatException();\n            }\n            this.version = BitMatrixParser.readVersion(bitMatrix);\n            this.mappingBitMatrix = this.extractDataRegion(bitMatrix);\n            this.readMappingMatrix = new BitMatrix(this.mappingBitMatrix.getWidth(), this.mappingBitMatrix.getHeight());\n        }\n        getVersion() {\n            return this.version;\n        }\n        /**\n         * <p>Creates the version object based on the dimension of the original bit matrix from\n         * the datamatrix code.</p>\n         *\n         * <p>See ISO 16022:2006 Table 7 - ECC 200 symbol attributes</p>\n         *\n         * @param bitMatrix Original {@link BitMatrix} including alignment patterns\n         * @return {@link Version} encapsulating the Data Matrix Code's \"version\"\n         * @throws FormatException if the dimensions of the mapping matrix are not valid\n         * Data Matrix dimensions.\n         */\n        static readVersion(bitMatrix) {\n            const numRows = bitMatrix.getHeight();\n            const numColumns = bitMatrix.getWidth();\n            return Version.getVersionForDimensions(numRows, numColumns);\n        }\n        /**\n         * <p>Reads the bits in the {@link BitMatrix} representing the mapping matrix (No alignment patterns)\n         * in the correct order in order to reconstitute the codewords bytes contained within the\n         * Data Matrix Code.</p>\n         *\n         * @return bytes encoded within the Data Matrix Code\n         * @throws FormatException if the exact number of bytes expected is not read\n         */\n        readCodewords() {\n            const result = new Int8Array(this.version.getTotalCodewords());\n            let resultOffset = 0;\n            let row = 4;\n            let column = 0;\n            const numRows = this.mappingBitMatrix.getHeight();\n            const numColumns = this.mappingBitMatrix.getWidth();\n            let corner1Read = false;\n            let corner2Read = false;\n            let corner3Read = false;\n            let corner4Read = false;\n            // Read all of the codewords\n            do {\n                // Check the four corner cases\n                if ((row === numRows) && (column === 0) && !corner1Read) {\n                    result[resultOffset++] = this.readCorner1(numRows, numColumns) & 0xff;\n                    row -= 2;\n                    column += 2;\n                    corner1Read = true;\n                }\n                else if ((row === numRows - 2) && (column === 0) && ((numColumns & 0x03) !== 0) && !corner2Read) {\n                    result[resultOffset++] = this.readCorner2(numRows, numColumns) & 0xff;\n                    row -= 2;\n                    column += 2;\n                    corner2Read = true;\n                }\n                else if ((row === numRows + 4) && (column === 2) && ((numColumns & 0x07) === 0) && !corner3Read) {\n                    result[resultOffset++] = this.readCorner3(numRows, numColumns) & 0xff;\n                    row -= 2;\n                    column += 2;\n                    corner3Read = true;\n                }\n                else if ((row === numRows - 2) && (column === 0) && ((numColumns & 0x07) === 4) && !corner4Read) {\n                    result[resultOffset++] = this.readCorner4(numRows, numColumns) & 0xff;\n                    row -= 2;\n                    column += 2;\n                    corner4Read = true;\n                }\n                else {\n                    // Sweep upward diagonally to the right\n                    do {\n                        if ((row < numRows) && (column >= 0) && !this.readMappingMatrix.get(column, row)) {\n                            result[resultOffset++] = this.readUtah(row, column, numRows, numColumns) & 0xff;\n                        }\n                        row -= 2;\n                        column += 2;\n                    } while ((row >= 0) && (column < numColumns));\n                    row += 1;\n                    column += 3;\n                    // Sweep downward diagonally to the left\n                    do {\n                        if ((row >= 0) && (column < numColumns) && !this.readMappingMatrix.get(column, row)) {\n                            result[resultOffset++] = this.readUtah(row, column, numRows, numColumns) & 0xff;\n                        }\n                        row += 2;\n                        column -= 2;\n                    } while ((row < numRows) && (column >= 0));\n                    row += 3;\n                    column += 1;\n                }\n            } while ((row < numRows) || (column < numColumns));\n            if (resultOffset !== this.version.getTotalCodewords()) {\n                throw new FormatException();\n            }\n            return result;\n        }\n        /**\n         * <p>Reads a bit of the mapping matrix accounting for boundary wrapping.</p>\n         *\n         * @param row Row to read in the mapping matrix\n         * @param column Column to read in the mapping matrix\n         * @param numRows Number of rows in the mapping matrix\n         * @param numColumns Number of columns in the mapping matrix\n         * @return value of the given bit in the mapping matrix\n         */\n        readModule(row, column, numRows, numColumns) {\n            // Adjust the row and column indices based on boundary wrapping\n            if (row < 0) {\n                row += numRows;\n                column += 4 - ((numRows + 4) & 0x07);\n            }\n            if (column < 0) {\n                column += numColumns;\n                row += 4 - ((numColumns + 4) & 0x07);\n            }\n            this.readMappingMatrix.set(column, row);\n            return this.mappingBitMatrix.get(column, row);\n        }\n        /**\n         * <p>Reads the 8 bits of the standard Utah-shaped pattern.</p>\n         *\n         * <p>See ISO 16022:2006, 5.8.1 Figure 6</p>\n         *\n         * @param row Current row in the mapping matrix, anchored at the 8th bit (LSB) of the pattern\n         * @param column Current column in the mapping matrix, anchored at the 8th bit (LSB) of the pattern\n         * @param numRows Number of rows in the mapping matrix\n         * @param numColumns Number of columns in the mapping matrix\n         * @return byte from the utah shape\n         */\n        readUtah(row, column, numRows, numColumns) {\n            let currentByte = 0;\n            if (this.readModule(row - 2, column - 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(row - 2, column - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(row - 1, column - 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(row - 1, column - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(row - 1, column, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(row, column - 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(row, column - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(row, column, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            return currentByte;\n        }\n        /**\n         * <p>Reads the 8 bits of the special corner condition 1.</p>\n         *\n         * <p>See ISO 16022:2006, Figure F.3</p>\n         *\n         * @param numRows Number of rows in the mapping matrix\n         * @param numColumns Number of columns in the mapping matrix\n         * @return byte from the Corner condition 1\n         */\n        readCorner1(numRows, numColumns) {\n            let currentByte = 0;\n            if (this.readModule(numRows - 1, 0, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(numRows - 1, 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(numRows - 1, 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(1, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(2, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(3, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            return currentByte;\n        }\n        /**\n         * <p>Reads the 8 bits of the special corner condition 2.</p>\n         *\n         * <p>See ISO 16022:2006, Figure F.4</p>\n         *\n         * @param numRows Number of rows in the mapping matrix\n         * @param numColumns Number of columns in the mapping matrix\n         * @return byte from the Corner condition 2\n         */\n        readCorner2(numRows, numColumns) {\n            let currentByte = 0;\n            if (this.readModule(numRows - 3, 0, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(numRows - 2, 0, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(numRows - 1, 0, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 4, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 3, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(1, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            return currentByte;\n        }\n        /**\n         * <p>Reads the 8 bits of the special corner condition 3.</p>\n         *\n         * <p>See ISO 16022:2006, Figure F.5</p>\n         *\n         * @param numRows Number of rows in the mapping matrix\n         * @param numColumns Number of columns in the mapping matrix\n         * @return byte from the Corner condition 3\n         */\n        readCorner3(numRows, numColumns) {\n            let currentByte = 0;\n            if (this.readModule(numRows - 1, 0, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(numRows - 1, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 3, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(1, numColumns - 3, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(1, numColumns - 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(1, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            return currentByte;\n        }\n        /**\n         * <p>Reads the 8 bits of the special corner condition 4.</p>\n         *\n         * <p>See ISO 16022:2006, Figure F.6</p>\n         *\n         * @param numRows Number of rows in the mapping matrix\n         * @param numColumns Number of columns in the mapping matrix\n         * @return byte from the Corner condition 4\n         */\n        readCorner4(numRows, numColumns) {\n            let currentByte = 0;\n            if (this.readModule(numRows - 3, 0, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(numRows - 2, 0, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(numRows - 1, 0, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 2, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(0, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(1, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(2, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            currentByte <<= 1;\n            if (this.readModule(3, numColumns - 1, numRows, numColumns)) {\n                currentByte |= 1;\n            }\n            return currentByte;\n        }\n        /**\n         * <p>Extracts the data region from a {@link BitMatrix} that contains\n         * alignment patterns.</p>\n         *\n         * @param bitMatrix Original {@link BitMatrix} with alignment patterns\n         * @return BitMatrix that has the alignment patterns removed\n         */\n        extractDataRegion(bitMatrix) {\n            const symbolSizeRows = this.version.getSymbolSizeRows();\n            const symbolSizeColumns = this.version.getSymbolSizeColumns();\n            if (bitMatrix.getHeight() !== symbolSizeRows) {\n                throw new IllegalArgumentException('Dimension of bitMatrix must match the version size');\n            }\n            const dataRegionSizeRows = this.version.getDataRegionSizeRows();\n            const dataRegionSizeColumns = this.version.getDataRegionSizeColumns();\n            const numDataRegionsRow = symbolSizeRows / dataRegionSizeRows | 0;\n            const numDataRegionsColumn = symbolSizeColumns / dataRegionSizeColumns | 0;\n            const sizeDataRegionRow = numDataRegionsRow * dataRegionSizeRows;\n            const sizeDataRegionColumn = numDataRegionsColumn * dataRegionSizeColumns;\n            const bitMatrixWithoutAlignment = new BitMatrix(sizeDataRegionColumn, sizeDataRegionRow);\n            for (let dataRegionRow = 0; dataRegionRow < numDataRegionsRow; ++dataRegionRow) {\n                const dataRegionRowOffset = dataRegionRow * dataRegionSizeRows;\n                for (let dataRegionColumn = 0; dataRegionColumn < numDataRegionsColumn; ++dataRegionColumn) {\n                    const dataRegionColumnOffset = dataRegionColumn * dataRegionSizeColumns;\n                    for (let i = 0; i < dataRegionSizeRows; ++i) {\n                        const readRowOffset = dataRegionRow * (dataRegionSizeRows + 2) + 1 + i;\n                        const writeRowOffset = dataRegionRowOffset + i;\n                        for (let j = 0; j < dataRegionSizeColumns; ++j) {\n                            const readColumnOffset = dataRegionColumn * (dataRegionSizeColumns + 2) + 1 + j;\n                            if (bitMatrix.get(readColumnOffset, readRowOffset)) {\n                                const writeColumnOffset = dataRegionColumnOffset + j;\n                                bitMatrixWithoutAlignment.set(writeColumnOffset, writeRowOffset);\n                            }\n                        }\n                    }\n                }\n            }\n            return bitMatrixWithoutAlignment;\n        }\n    }\n\n    /**\n     * <p>Encapsulates a block of data within a Data Matrix Code. Data Matrix Codes may split their data into\n     * multiple blocks, each of which is a unit of data and error-correction codewords. Each\n     * is represented by an instance of this class.</p>\n     *\n     * @author bbrown@google.com (Brian Brown)\n     */\n    class DataBlock {\n        constructor(numDataCodewords, codewords) {\n            this.numDataCodewords = numDataCodewords;\n            this.codewords = codewords;\n        }\n        /**\n         * <p>When Data Matrix Codes use multiple data blocks, they actually interleave the bytes of each of them.\n         * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This\n         * method will separate the data into original blocks.</p>\n         *\n         * @param rawCodewords bytes as read directly from the Data Matrix Code\n         * @param version version of the Data Matrix Code\n         * @return DataBlocks containing original bytes, \"de-interleaved\" from representation in the\n         *         Data Matrix Code\n         */\n        static getDataBlocks(rawCodewords, version) {\n            // Figure out the number and size of data blocks used by this version\n            const ecBlocks = version.getECBlocks();\n            // First count the total number of data blocks\n            let totalBlocks = 0;\n            const ecBlockArray = ecBlocks.getECBlocks();\n            for (let ecBlock of ecBlockArray) {\n                totalBlocks += ecBlock.getCount();\n            }\n            // Now establish DataBlocks of the appropriate size and number of data codewords\n            const result = new Array(totalBlocks);\n            let numResultBlocks = 0;\n            for (let ecBlock of ecBlockArray) {\n                for (let i = 0; i < ecBlock.getCount(); i++) {\n                    const numDataCodewords = ecBlock.getDataCodewords();\n                    const numBlockCodewords = ecBlocks.getECCodewords() + numDataCodewords;\n                    result[numResultBlocks++] = new DataBlock(numDataCodewords, new Uint8Array(numBlockCodewords));\n                }\n            }\n            // All blocks have the same amount of data, except that the last n\n            // (where n may be 0) have 1 less byte. Figure out where these start.\n            // TODO(bbrown): There is only one case where there is a difference for Data Matrix for size 144\n            const longerBlocksTotalCodewords = result[0].codewords.length;\n            // int shorterBlocksTotalCodewords = longerBlocksTotalCodewords - 1;\n            const longerBlocksNumDataCodewords = longerBlocksTotalCodewords - ecBlocks.getECCodewords();\n            const shorterBlocksNumDataCodewords = longerBlocksNumDataCodewords - 1;\n            // The last elements of result may be 1 element shorter for 144 matrix\n            // first fill out as many elements as all of them have minus 1\n            let rawCodewordsOffset = 0;\n            for (let i = 0; i < shorterBlocksNumDataCodewords; i++) {\n                for (let j = 0; j < numResultBlocks; j++) {\n                    result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];\n                }\n            }\n            // Fill out the last data block in the longer ones\n            const specialVersion = version.getVersionNumber() === 24;\n            const numLongerBlocks = specialVersion ? 8 : numResultBlocks;\n            for (let j = 0; j < numLongerBlocks; j++) {\n                result[j].codewords[longerBlocksNumDataCodewords - 1] = rawCodewords[rawCodewordsOffset++];\n            }\n            // Now add in error correction blocks\n            const max = result[0].codewords.length;\n            for (let i = longerBlocksNumDataCodewords; i < max; i++) {\n                for (let j = 0; j < numResultBlocks; j++) {\n                    const jOffset = specialVersion ? (j + 8) % numResultBlocks : j;\n                    const iOffset = specialVersion && jOffset > 7 ? i - 1 : i;\n                    result[jOffset].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];\n                }\n            }\n            if (rawCodewordsOffset !== rawCodewords.length) {\n                throw new IllegalArgumentException();\n            }\n            return result;\n        }\n        getNumDataCodewords() {\n            return this.numDataCodewords;\n        }\n        getCodewords() {\n            return this.codewords;\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>This provides an easy abstraction to read bits at a time from a sequence of bytes, where the\n     * number of bits read is not often a multiple of 8.</p>\n     *\n     * <p>This class is thread-safe but not reentrant -- unless the caller modifies the bytes array\n     * it passed in, in which case all bets are off.</p>\n     *\n     * @author Sean Owen\n     */\n    class BitSource {\n        /**\n         * @param bytes bytes from which this will read bits. Bits will be read from the first byte first.\n         * Bits are read within a byte from most-significant to least-significant bit.\n         */\n        constructor(bytes) {\n            this.bytes = bytes;\n            this.byteOffset = 0;\n            this.bitOffset = 0;\n        }\n        /**\n         * @return index of next bit in current byte which would be read by the next call to {@link #readBits(int)}.\n         */\n        getBitOffset() {\n            return this.bitOffset;\n        }\n        /**\n         * @return index of next byte in input byte array which would be read by the next call to {@link #readBits(int)}.\n         */\n        getByteOffset() {\n            return this.byteOffset;\n        }\n        /**\n         * @param numBits number of bits to read\n         * @return int representing the bits read. The bits will appear as the least-significant\n         *         bits of the int\n         * @throws IllegalArgumentException if numBits isn't in [1,32] or more than is available\n         */\n        readBits(numBits /*int*/) {\n            if (numBits < 1 || numBits > 32 || numBits > this.available()) {\n                throw new IllegalArgumentException('' + numBits);\n            }\n            let result = 0;\n            let bitOffset = this.bitOffset;\n            let byteOffset = this.byteOffset;\n            const bytes = this.bytes;\n            // First, read remainder from current byte\n            if (bitOffset > 0) {\n                const bitsLeft = 8 - bitOffset;\n                const toRead = numBits < bitsLeft ? numBits : bitsLeft;\n                const bitsToNotRead = bitsLeft - toRead;\n                const mask = (0xFF >> (8 - toRead)) << bitsToNotRead;\n                result = (bytes[byteOffset] & mask) >> bitsToNotRead;\n                numBits -= toRead;\n                bitOffset += toRead;\n                if (bitOffset === 8) {\n                    bitOffset = 0;\n                    byteOffset++;\n                }\n            }\n            // Next read whole bytes\n            if (numBits > 0) {\n                while (numBits >= 8) {\n                    result = (result << 8) | (bytes[byteOffset] & 0xFF);\n                    byteOffset++;\n                    numBits -= 8;\n                }\n                // Finally read a partial byte\n                if (numBits > 0) {\n                    const bitsToNotRead = 8 - numBits;\n                    const mask = (0xFF >> bitsToNotRead) << bitsToNotRead;\n                    result = (result << numBits) | ((bytes[byteOffset] & mask) >> bitsToNotRead);\n                    bitOffset += numBits;\n                }\n            }\n            this.bitOffset = bitOffset;\n            this.byteOffset = byteOffset;\n            return result;\n        }\n        /**\n         * @return number of bits that can be read successfully\n         */\n        available() {\n            return 8 * (this.bytes.length - this.byteOffset) - this.bitOffset;\n        }\n    }\n\n    var Mode;\n    (function (Mode) {\n        Mode[Mode[\"PAD_ENCODE\"] = 0] = \"PAD_ENCODE\";\n        Mode[Mode[\"ASCII_ENCODE\"] = 1] = \"ASCII_ENCODE\";\n        Mode[Mode[\"C40_ENCODE\"] = 2] = \"C40_ENCODE\";\n        Mode[Mode[\"TEXT_ENCODE\"] = 3] = \"TEXT_ENCODE\";\n        Mode[Mode[\"ANSIX12_ENCODE\"] = 4] = \"ANSIX12_ENCODE\";\n        Mode[Mode[\"EDIFACT_ENCODE\"] = 5] = \"EDIFACT_ENCODE\";\n        Mode[Mode[\"BASE256_ENCODE\"] = 6] = \"BASE256_ENCODE\";\n    })(Mode || (Mode = {}));\n    /**\n     * <p>Data Matrix Codes can encode text as bits in one of several modes, and can use multiple modes\n     * in one Data Matrix Code. This class decodes the bits back into text.</p>\n     *\n     * <p>See ISO 16022:2006, 5.2.1 - 5.2.9.2</p>\n     *\n     * @author bbrown@google.com (Brian Brown)\n     * @author Sean Owen\n     */\n    class DecodedBitStreamParser {\n        static decode(bytes) {\n            const bits = new BitSource(bytes);\n            const result = new StringBuilder();\n            const resultTrailer = new StringBuilder();\n            const byteSegments = new Array();\n            let mode = Mode.ASCII_ENCODE;\n            do {\n                if (mode === Mode.ASCII_ENCODE) {\n                    mode = this.decodeAsciiSegment(bits, result, resultTrailer);\n                }\n                else {\n                    switch (mode) {\n                        case Mode.C40_ENCODE:\n                            this.decodeC40Segment(bits, result);\n                            break;\n                        case Mode.TEXT_ENCODE:\n                            this.decodeTextSegment(bits, result);\n                            break;\n                        case Mode.ANSIX12_ENCODE:\n                            this.decodeAnsiX12Segment(bits, result);\n                            break;\n                        case Mode.EDIFACT_ENCODE:\n                            this.decodeEdifactSegment(bits, result);\n                            break;\n                        case Mode.BASE256_ENCODE:\n                            this.decodeBase256Segment(bits, result, byteSegments);\n                            break;\n                        default:\n                            throw new FormatException();\n                    }\n                    mode = Mode.ASCII_ENCODE;\n                }\n            } while (mode !== Mode.PAD_ENCODE && bits.available() > 0);\n            if (resultTrailer.length() > 0) {\n                result.append(resultTrailer.toString());\n            }\n            return new DecoderResult(bytes, result.toString(), byteSegments.length === 0 ? null : byteSegments, null);\n        }\n        /**\n         * See ISO 16022:2006, 5.2.3 and Annex C, Table C.2\n         */\n        static decodeAsciiSegment(bits, result, resultTrailer) {\n            let upperShift = false;\n            do {\n                let oneByte = bits.readBits(8);\n                if (oneByte === 0) {\n                    throw new FormatException();\n                }\n                else if (oneByte <= 128) { // ASCII data (ASCII value + 1)\n                    if (upperShift) {\n                        oneByte += 128;\n                        // upperShift = false;\n                    }\n                    result.append(String.fromCharCode(oneByte - 1));\n                    return Mode.ASCII_ENCODE;\n                }\n                else if (oneByte === 129) { // Pad\n                    return Mode.PAD_ENCODE;\n                }\n                else if (oneByte <= 229) { // 2-digit data 00-99 (Numeric Value + 130)\n                    const value = oneByte - 130;\n                    if (value < 10) { // pad with '0' for single digit values\n                        result.append('0');\n                    }\n                    result.append('' + value);\n                }\n                else {\n                    switch (oneByte) {\n                        case 230: // Latch to C40 encodation\n                            return Mode.C40_ENCODE;\n                        case 231: // Latch to Base 256 encodation\n                            return Mode.BASE256_ENCODE;\n                        case 232: // FNC1\n                            result.append(String.fromCharCode(29)); // translate as ASCII 29\n                            break;\n                        case 233: // Structured Append\n                        case 234: // Reader Programming\n                            // Ignore these symbols for now\n                            // throw ReaderException.getInstance();\n                            break;\n                        case 235: // Upper Shift (shift to Extended ASCII)\n                            upperShift = true;\n                            break;\n                        case 236: // 05 Macro\n                            result.append('[)>\\u001E05\\u001D');\n                            resultTrailer.insert(0, '\\u001E\\u0004');\n                            break;\n                        case 237: // 06 Macro\n                            result.append('[)>\\u001E06\\u001D');\n                            resultTrailer.insert(0, '\\u001E\\u0004');\n                            break;\n                        case 238: // Latch to ANSI X12 encodation\n                            return Mode.ANSIX12_ENCODE;\n                        case 239: // Latch to Text encodation\n                            return Mode.TEXT_ENCODE;\n                        case 240: // Latch to EDIFACT encodation\n                            return Mode.EDIFACT_ENCODE;\n                        case 241: // ECI Character\n                            // TODO(bbrown): I think we need to support ECI\n                            // throw ReaderException.getInstance();\n                            // Ignore this symbol for now\n                            break;\n                        default:\n                            // Not to be used in ASCII encodation\n                            // but work around encoders that end with 254, latch back to ASCII\n                            if (oneByte !== 254 || bits.available() !== 0) {\n                                throw new FormatException();\n                            }\n                            break;\n                    }\n                }\n            } while (bits.available() > 0);\n            return Mode.ASCII_ENCODE;\n        }\n        /**\n         * See ISO 16022:2006, 5.2.5 and Annex C, Table C.1\n         */\n        static decodeC40Segment(bits, result) {\n            // Three C40 values are encoded in a 16-bit value as\n            // (1600 * C1) + (40 * C2) + C3 + 1\n            // TODO(bbrown): The Upper Shift with C40 doesn't work in the 4 value scenario all the time\n            let upperShift = false;\n            const cValues = [];\n            let shift = 0;\n            do {\n                // If there is only one byte left then it will be encoded as ASCII\n                if (bits.available() === 8) {\n                    return;\n                }\n                const firstByte = bits.readBits(8);\n                if (firstByte === 254) { // Unlatch codeword\n                    return;\n                }\n                this.parseTwoBytes(firstByte, bits.readBits(8), cValues);\n                for (let i = 0; i < 3; i++) {\n                    const cValue = cValues[i];\n                    switch (shift) {\n                        case 0:\n                            if (cValue < 3) {\n                                shift = cValue + 1;\n                            }\n                            else if (cValue < this.C40_BASIC_SET_CHARS.length) {\n                                const c40char = this.C40_BASIC_SET_CHARS[cValue];\n                                if (upperShift) {\n                                    result.append(String.fromCharCode(c40char.charCodeAt(0) + 128));\n                                    upperShift = false;\n                                }\n                                else {\n                                    result.append(c40char);\n                                }\n                            }\n                            else {\n                                throw new FormatException();\n                            }\n                            break;\n                        case 1:\n                            if (upperShift) {\n                                result.append(String.fromCharCode(cValue + 128));\n                                upperShift = false;\n                            }\n                            else {\n                                result.append(String.fromCharCode(cValue));\n                            }\n                            shift = 0;\n                            break;\n                        case 2:\n                            if (cValue < this.C40_SHIFT2_SET_CHARS.length) {\n                                const c40char = this.C40_SHIFT2_SET_CHARS[cValue];\n                                if (upperShift) {\n                                    result.append(String.fromCharCode(c40char.charCodeAt(0) + 128));\n                                    upperShift = false;\n                                }\n                                else {\n                                    result.append(c40char);\n                                }\n                            }\n                            else {\n                                switch (cValue) {\n                                    case 27: // FNC1\n                                        result.append(String.fromCharCode(29)); // translate as ASCII 29\n                                        break;\n                                    case 30: // Upper Shift\n                                        upperShift = true;\n                                        break;\n                                    default:\n                                        throw new FormatException();\n                                }\n                            }\n                            shift = 0;\n                            break;\n                        case 3:\n                            if (upperShift) {\n                                result.append(String.fromCharCode(cValue + 224));\n                                upperShift = false;\n                            }\n                            else {\n                                result.append(String.fromCharCode(cValue + 96));\n                            }\n                            shift = 0;\n                            break;\n                        default:\n                            throw new FormatException();\n                    }\n                }\n            } while (bits.available() > 0);\n        }\n        /**\n         * See ISO 16022:2006, 5.2.6 and Annex C, Table C.2\n         */\n        static decodeTextSegment(bits, result) {\n            // Three Text values are encoded in a 16-bit value as\n            // (1600 * C1) + (40 * C2) + C3 + 1\n            // TODO(bbrown): The Upper Shift with Text doesn't work in the 4 value scenario all the time\n            let upperShift = false;\n            let cValues = [];\n            let shift = 0;\n            do {\n                // If there is only one byte left then it will be encoded as ASCII\n                if (bits.available() === 8) {\n                    return;\n                }\n                const firstByte = bits.readBits(8);\n                if (firstByte === 254) { // Unlatch codeword\n                    return;\n                }\n                this.parseTwoBytes(firstByte, bits.readBits(8), cValues);\n                for (let i = 0; i < 3; i++) {\n                    const cValue = cValues[i];\n                    switch (shift) {\n                        case 0:\n                            if (cValue < 3) {\n                                shift = cValue + 1;\n                            }\n                            else if (cValue < this.TEXT_BASIC_SET_CHARS.length) {\n                                const textChar = this.TEXT_BASIC_SET_CHARS[cValue];\n                                if (upperShift) {\n                                    result.append(String.fromCharCode(textChar.charCodeAt(0) + 128));\n                                    upperShift = false;\n                                }\n                                else {\n                                    result.append(textChar);\n                                }\n                            }\n                            else {\n                                throw new FormatException();\n                            }\n                            break;\n                        case 1:\n                            if (upperShift) {\n                                result.append(String.fromCharCode(cValue + 128));\n                                upperShift = false;\n                            }\n                            else {\n                                result.append(String.fromCharCode(cValue));\n                            }\n                            shift = 0;\n                            break;\n                        case 2:\n                            // Shift 2 for Text is the same encoding as C40\n                            if (cValue < this.TEXT_SHIFT2_SET_CHARS.length) {\n                                const textChar = this.TEXT_SHIFT2_SET_CHARS[cValue];\n                                if (upperShift) {\n                                    result.append(String.fromCharCode(textChar.charCodeAt(0) + 128));\n                                    upperShift = false;\n                                }\n                                else {\n                                    result.append(textChar);\n                                }\n                            }\n                            else {\n                                switch (cValue) {\n                                    case 27: // FNC1\n                                        result.append(String.fromCharCode(29)); // translate as ASCII 29\n                                        break;\n                                    case 30: // Upper Shift\n                                        upperShift = true;\n                                        break;\n                                    default:\n                                        throw new FormatException();\n                                }\n                            }\n                            shift = 0;\n                            break;\n                        case 3:\n                            if (cValue < this.TEXT_SHIFT3_SET_CHARS.length) {\n                                const textChar = this.TEXT_SHIFT3_SET_CHARS[cValue];\n                                if (upperShift) {\n                                    result.append(String.fromCharCode(textChar.charCodeAt(0) + 128));\n                                    upperShift = false;\n                                }\n                                else {\n                                    result.append(textChar);\n                                }\n                                shift = 0;\n                            }\n                            else {\n                                throw new FormatException();\n                            }\n                            break;\n                        default:\n                            throw new FormatException();\n                    }\n                }\n            } while (bits.available() > 0);\n        }\n        /**\n         * See ISO 16022:2006, 5.2.7\n         */\n        static decodeAnsiX12Segment(bits, result) {\n            // Three ANSI X12 values are encoded in a 16-bit value as\n            // (1600 * C1) + (40 * C2) + C3 + 1\n            const cValues = [];\n            do {\n                // If there is only one byte left then it will be encoded as ASCII\n                if (bits.available() === 8) {\n                    return;\n                }\n                const firstByte = bits.readBits(8);\n                if (firstByte === 254) { // Unlatch codeword\n                    return;\n                }\n                this.parseTwoBytes(firstByte, bits.readBits(8), cValues);\n                for (let i = 0; i < 3; i++) {\n                    const cValue = cValues[i];\n                    switch (cValue) {\n                        case 0: // X12 segment terminator <CR>\n                            result.append('\\r');\n                            break;\n                        case 1: // X12 segment separator *\n                            result.append('*');\n                            break;\n                        case 2: // X12 sub-element separator >\n                            result.append('>');\n                            break;\n                        case 3: // space\n                            result.append(' ');\n                            break;\n                        default:\n                            if (cValue < 14) { // 0 - 9\n                                result.append(String.fromCharCode(cValue + 44));\n                            }\n                            else if (cValue < 40) { // A - Z\n                                result.append(String.fromCharCode(cValue + 51));\n                            }\n                            else {\n                                throw new FormatException();\n                            }\n                            break;\n                    }\n                }\n            } while (bits.available() > 0);\n        }\n        static parseTwoBytes(firstByte, secondByte, result) {\n            let fullBitValue = (firstByte << 8) + secondByte - 1;\n            let temp = Math.floor(fullBitValue / 1600);\n            result[0] = temp;\n            fullBitValue -= temp * 1600;\n            temp = Math.floor(fullBitValue / 40);\n            result[1] = temp;\n            result[2] = fullBitValue - temp * 40;\n        }\n        /**\n         * See ISO 16022:2006, 5.2.8 and Annex C Table C.3\n         */\n        static decodeEdifactSegment(bits, result) {\n            do {\n                // If there is only two or less bytes left then it will be encoded as ASCII\n                if (bits.available() <= 16) {\n                    return;\n                }\n                for (let i = 0; i < 4; i++) {\n                    let edifactValue = bits.readBits(6);\n                    // Check for the unlatch character\n                    if (edifactValue === 0x1F) { // 011111\n                        // Read rest of byte, which should be 0, and stop\n                        const bitsLeft = 8 - bits.getBitOffset();\n                        if (bitsLeft !== 8) {\n                            bits.readBits(bitsLeft);\n                        }\n                        return;\n                    }\n                    if ((edifactValue & 0x20) === 0) { // no 1 in the leading (6th) bit\n                        edifactValue |= 0x40; // Add a leading 01 to the 6 bit binary value\n                    }\n                    result.append(String.fromCharCode(edifactValue));\n                }\n            } while (bits.available() > 0);\n        }\n        /**\n         * See ISO 16022:2006, 5.2.9 and Annex B, B.2\n         */\n        static decodeBase256Segment(bits, result, byteSegments) {\n            // Figure out how long the Base 256 Segment is.\n            let codewordPosition = 1 + bits.getByteOffset(); // position is 1-indexed\n            const d1 = this.unrandomize255State(bits.readBits(8), codewordPosition++);\n            let count;\n            if (d1 === 0) { // Read the remainder of the symbol\n                count = bits.available() / 8 | 0;\n            }\n            else if (d1 < 250) {\n                count = d1;\n            }\n            else {\n                count = 250 * (d1 - 249) + this.unrandomize255State(bits.readBits(8), codewordPosition++);\n            }\n            // We're seeing NegativeArraySizeException errors from users.\n            if (count < 0) {\n                throw new FormatException();\n            }\n            const bytes = new Uint8Array(count);\n            for (let i = 0; i < count; i++) {\n                // Have seen this particular error in the wild, such as at\n                // http://www.bcgen.com/demo/IDAutomationStreamingDataMatrix.aspx?MODE=3&D=Fred&PFMT=3&PT=F&X=0.3&O=0&LM=0.2\n                if (bits.available() < 8) {\n                    throw new FormatException();\n                }\n                bytes[i] = this.unrandomize255State(bits.readBits(8), codewordPosition++);\n            }\n            byteSegments.push(bytes);\n            try {\n                result.append(StringEncoding.decode(bytes, StringUtils.ISO88591));\n            }\n            catch (uee) {\n                throw new IllegalStateException('Platform does not support required encoding: ' + uee.message);\n            }\n        }\n        /**\n         * See ISO 16022:2006, Annex B, B.2\n         */\n        static unrandomize255State(randomizedBase256Codeword, base256CodewordPosition) {\n            const pseudoRandomNumber = ((149 * base256CodewordPosition) % 255) + 1;\n            const tempVariable = randomizedBase256Codeword - pseudoRandomNumber;\n            return tempVariable >= 0 ? tempVariable : tempVariable + 256;\n        }\n    }\n    /**\n     * See ISO 16022:2006, Annex C Table C.1\n     * The C40 Basic Character Set (*'s used for placeholders for the shift values)\n     */\n    DecodedBitStreamParser.C40_BASIC_SET_CHARS = [\n        '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',\n        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',\n        'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'\n    ];\n    DecodedBitStreamParser.C40_SHIFT2_SET_CHARS = [\n        '!', '\"', '#', '$', '%', '&', '\\'', '(', ')', '*', '+', ',', '-', '.',\n        '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\\\', ']', '^', '_'\n    ];\n    /**\n     * See ISO 16022:2006, Annex C Table C.2\n     * The Text Basic Character Set (*'s used for placeholders for the shift values)\n     */\n    DecodedBitStreamParser.TEXT_BASIC_SET_CHARS = [\n        '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',\n        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',\n        'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'\n    ];\n    // Shift 2 for Text is the same encoding as C40\n    DecodedBitStreamParser.TEXT_SHIFT2_SET_CHARS = DecodedBitStreamParser.C40_SHIFT2_SET_CHARS;\n    DecodedBitStreamParser.TEXT_SHIFT3_SET_CHARS = [\n        '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',\n        'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', String.fromCharCode(127)\n    ];\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>The main class which implements Data Matrix Code decoding -- as opposed to locating and extracting\n     * the Data Matrix Code from an image.</p>\n     *\n     * @author bbrown@google.com (Brian Brown)\n     */\n    class Decoder$1 {\n        constructor() {\n            this.rsDecoder = new ReedSolomonDecoder(GenericGF.DATA_MATRIX_FIELD_256);\n        }\n        /**\n         * <p>Decodes a Data Matrix Code represented as a {@link BitMatrix}. A 1 or \"true\" is taken\n         * to mean a black module.</p>\n         *\n         * @param bits booleans representing white/black Data Matrix Code modules\n         * @return text and bytes encoded within the Data Matrix Code\n         * @throws FormatException if the Data Matrix Code cannot be decoded\n         * @throws ChecksumException if error correction fails\n         */\n        decode(bits) {\n            // Construct a parser and read version, error-correction level\n            const parser = new BitMatrixParser(bits);\n            const version = parser.getVersion();\n            // Read codewords\n            const codewords = parser.readCodewords();\n            // Separate into data blocks\n            const dataBlocks = DataBlock.getDataBlocks(codewords, version);\n            // Count total number of data bytes\n            let totalBytes = 0;\n            for (let db of dataBlocks) {\n                totalBytes += db.getNumDataCodewords();\n            }\n            const resultBytes = new Uint8Array(totalBytes);\n            const dataBlocksCount = dataBlocks.length;\n            // Error-correct and copy data blocks together into a stream of bytes\n            for (let j = 0; j < dataBlocksCount; j++) {\n                const dataBlock = dataBlocks[j];\n                const codewordBytes = dataBlock.getCodewords();\n                const numDataCodewords = dataBlock.getNumDataCodewords();\n                this.correctErrors(codewordBytes, numDataCodewords);\n                for (let i = 0; i < numDataCodewords; i++) {\n                    // De-interlace data blocks.\n                    resultBytes[i * dataBlocksCount + j] = codewordBytes[i];\n                }\n            }\n            // Decode the contents of that stream of bytes\n            return DecodedBitStreamParser.decode(resultBytes);\n        }\n        /**\n         * <p>Given data and error-correction codewords received, possibly corrupted by errors, attempts to\n         * correct the errors in-place using Reed-Solomon error correction.</p>\n         *\n         * @param codewordBytes data and error correction codewords\n         * @param numDataCodewords number of codewords that are data bytes\n         * @throws ChecksumException if error correction fails\n         */\n        correctErrors(codewordBytes, numDataCodewords) {\n            // const numCodewords = codewordBytes.length;\n            // First read into an array of ints\n            const codewordsInts = new Int32Array(codewordBytes);\n            // for (let i = 0; i < numCodewords; i++) {\n            //   codewordsInts[i] = codewordBytes[i] & 0xFF;\n            // }\n            try {\n                this.rsDecoder.decode(codewordsInts, codewordBytes.length - numDataCodewords);\n            }\n            catch (ignored /* ReedSolomonException */) {\n                throw new ChecksumException();\n            }\n            // Copy back into array of bytes -- only need to worry about the bytes that were data\n            // We don't care about errors in the error-correction codewords\n            for (let i = 0; i < numDataCodewords; i++) {\n                codewordBytes[i] = codewordsInts[i];\n            }\n        }\n    }\n\n    /**\n     * <p>Encapsulates logic that can detect a Data Matrix Code in an image, even if the Data Matrix Code\n     * is rotated or skewed, or partially obscured.</p>\n     *\n     * @author Sean Owen\n     */\n    class Detector$1 {\n        constructor(image) {\n            this.image = image;\n            this.rectangleDetector = new WhiteRectangleDetector(this.image);\n        }\n        /**\n         * <p>Detects a Data Matrix Code in an image.</p>\n         *\n         * @return {@link DetectorResult} encapsulating results of detecting a Data Matrix Code\n         * @throws NotFoundException if no Data Matrix Code can be found\n         */\n        detect() {\n            const cornerPoints = this.rectangleDetector.detect();\n            let points = this.detectSolid1(cornerPoints);\n            points = this.detectSolid2(points);\n            points[3] = this.correctTopRight(points);\n            if (!points[3]) {\n                throw new NotFoundException();\n            }\n            points = this.shiftToModuleCenter(points);\n            const topLeft = points[0];\n            const bottomLeft = points[1];\n            const bottomRight = points[2];\n            const topRight = points[3];\n            let dimensionTop = this.transitionsBetween(topLeft, topRight) + 1;\n            let dimensionRight = this.transitionsBetween(bottomRight, topRight) + 1;\n            if ((dimensionTop & 0x01) === 1) {\n                dimensionTop += 1;\n            }\n            if ((dimensionRight & 0x01) === 1) {\n                dimensionRight += 1;\n            }\n            if (4 * dimensionTop < 7 * dimensionRight && 4 * dimensionRight < 7 * dimensionTop) {\n                // The matrix is square\n                dimensionTop = dimensionRight = Math.max(dimensionTop, dimensionRight);\n            }\n            let bits = Detector$1.sampleGrid(this.image, topLeft, bottomLeft, bottomRight, topRight, dimensionTop, dimensionRight);\n            return new DetectorResult(bits, [topLeft, bottomLeft, bottomRight, topRight]);\n        }\n        static shiftPoint(point, to, div) {\n            let x = (to.getX() - point.getX()) / (div + 1);\n            let y = (to.getY() - point.getY()) / (div + 1);\n            return new ResultPoint(point.getX() + x, point.getY() + y);\n        }\n        static moveAway(point, fromX, fromY) {\n            let x = point.getX();\n            let y = point.getY();\n            if (x < fromX) {\n                x -= 1;\n            }\n            else {\n                x += 1;\n            }\n            if (y < fromY) {\n                y -= 1;\n            }\n            else {\n                y += 1;\n            }\n            return new ResultPoint(x, y);\n        }\n        /**\n         * Detect a solid side which has minimum transition.\n         */\n        detectSolid1(cornerPoints) {\n            // 0  2\n            // 1  3\n            let pointA = cornerPoints[0];\n            let pointB = cornerPoints[1];\n            let pointC = cornerPoints[3];\n            let pointD = cornerPoints[2];\n            let trAB = this.transitionsBetween(pointA, pointB);\n            let trBC = this.transitionsBetween(pointB, pointC);\n            let trCD = this.transitionsBetween(pointC, pointD);\n            let trDA = this.transitionsBetween(pointD, pointA);\n            // 0..3\n            // :  :\n            // 1--2\n            let min = trAB;\n            let points = [pointD, pointA, pointB, pointC];\n            if (min > trBC) {\n                min = trBC;\n                points[0] = pointA;\n                points[1] = pointB;\n                points[2] = pointC;\n                points[3] = pointD;\n            }\n            if (min > trCD) {\n                min = trCD;\n                points[0] = pointB;\n                points[1] = pointC;\n                points[2] = pointD;\n                points[3] = pointA;\n            }\n            if (min > trDA) {\n                points[0] = pointC;\n                points[1] = pointD;\n                points[2] = pointA;\n                points[3] = pointB;\n            }\n            return points;\n        }\n        /**\n         * Detect a second solid side next to first solid side.\n         */\n        detectSolid2(points) {\n            // A..D\n            // :  :\n            // B--C\n            let pointA = points[0];\n            let pointB = points[1];\n            let pointC = points[2];\n            let pointD = points[3];\n            // Transition detection on the edge is not stable.\n            // To safely detect, shift the points to the module center.\n            let tr = this.transitionsBetween(pointA, pointD);\n            let pointBs = Detector$1.shiftPoint(pointB, pointC, (tr + 1) * 4);\n            let pointCs = Detector$1.shiftPoint(pointC, pointB, (tr + 1) * 4);\n            let trBA = this.transitionsBetween(pointBs, pointA);\n            let trCD = this.transitionsBetween(pointCs, pointD);\n            // 0..3\n            // |  :\n            // 1--2\n            if (trBA < trCD) {\n                // solid sides: A-B-C\n                points[0] = pointA;\n                points[1] = pointB;\n                points[2] = pointC;\n                points[3] = pointD;\n            }\n            else {\n                // solid sides: B-C-D\n                points[0] = pointB;\n                points[1] = pointC;\n                points[2] = pointD;\n                points[3] = pointA;\n            }\n            return points;\n        }\n        /**\n         * Calculates the corner position of the white top right module.\n         */\n        correctTopRight(points) {\n            // A..D\n            // |  :\n            // B--C\n            let pointA = points[0];\n            let pointB = points[1];\n            let pointC = points[2];\n            let pointD = points[3];\n            // shift points for safe transition detection.\n            let trTop = this.transitionsBetween(pointA, pointD);\n            let trRight = this.transitionsBetween(pointB, pointD);\n            let pointAs = Detector$1.shiftPoint(pointA, pointB, (trRight + 1) * 4);\n            let pointCs = Detector$1.shiftPoint(pointC, pointB, (trTop + 1) * 4);\n            trTop = this.transitionsBetween(pointAs, pointD);\n            trRight = this.transitionsBetween(pointCs, pointD);\n            let candidate1 = new ResultPoint(pointD.getX() + (pointC.getX() - pointB.getX()) / (trTop + 1), pointD.getY() + (pointC.getY() - pointB.getY()) / (trTop + 1));\n            let candidate2 = new ResultPoint(pointD.getX() + (pointA.getX() - pointB.getX()) / (trRight + 1), pointD.getY() + (pointA.getY() - pointB.getY()) / (trRight + 1));\n            if (!this.isValid(candidate1)) {\n                if (this.isValid(candidate2)) {\n                    return candidate2;\n                }\n                return null;\n            }\n            if (!this.isValid(candidate2)) {\n                return candidate1;\n            }\n            let sumc1 = this.transitionsBetween(pointAs, candidate1) + this.transitionsBetween(pointCs, candidate1);\n            let sumc2 = this.transitionsBetween(pointAs, candidate2) + this.transitionsBetween(pointCs, candidate2);\n            if (sumc1 > sumc2) {\n                return candidate1;\n            }\n            else {\n                return candidate2;\n            }\n        }\n        /**\n         * Shift the edge points to the module center.\n         */\n        shiftToModuleCenter(points) {\n            // A..D\n            // |  :\n            // B--C\n            let pointA = points[0];\n            let pointB = points[1];\n            let pointC = points[2];\n            let pointD = points[3];\n            // calculate pseudo dimensions\n            let dimH = this.transitionsBetween(pointA, pointD) + 1;\n            let dimV = this.transitionsBetween(pointC, pointD) + 1;\n            // shift points for safe dimension detection\n            let pointAs = Detector$1.shiftPoint(pointA, pointB, dimV * 4);\n            let pointCs = Detector$1.shiftPoint(pointC, pointB, dimH * 4);\n            //  calculate more precise dimensions\n            dimH = this.transitionsBetween(pointAs, pointD) + 1;\n            dimV = this.transitionsBetween(pointCs, pointD) + 1;\n            if ((dimH & 0x01) === 1) {\n                dimH += 1;\n            }\n            if ((dimV & 0x01) === 1) {\n                dimV += 1;\n            }\n            // WhiteRectangleDetector returns points inside of the rectangle.\n            // I want points on the edges.\n            let centerX = (pointA.getX() + pointB.getX() + pointC.getX() + pointD.getX()) / 4;\n            let centerY = (pointA.getY() + pointB.getY() + pointC.getY() + pointD.getY()) / 4;\n            pointA = Detector$1.moveAway(pointA, centerX, centerY);\n            pointB = Detector$1.moveAway(pointB, centerX, centerY);\n            pointC = Detector$1.moveAway(pointC, centerX, centerY);\n            pointD = Detector$1.moveAway(pointD, centerX, centerY);\n            let pointBs;\n            let pointDs;\n            // shift points to the center of each modules\n            pointAs = Detector$1.shiftPoint(pointA, pointB, dimV * 4);\n            pointAs = Detector$1.shiftPoint(pointAs, pointD, dimH * 4);\n            pointBs = Detector$1.shiftPoint(pointB, pointA, dimV * 4);\n            pointBs = Detector$1.shiftPoint(pointBs, pointC, dimH * 4);\n            pointCs = Detector$1.shiftPoint(pointC, pointD, dimV * 4);\n            pointCs = Detector$1.shiftPoint(pointCs, pointB, dimH * 4);\n            pointDs = Detector$1.shiftPoint(pointD, pointC, dimV * 4);\n            pointDs = Detector$1.shiftPoint(pointDs, pointA, dimH * 4);\n            return [pointAs, pointBs, pointCs, pointDs];\n        }\n        isValid(p) {\n            return p.getX() >= 0 && p.getX() < this.image.getWidth() && p.getY() > 0 && p.getY() < this.image.getHeight();\n        }\n        static sampleGrid(image, topLeft, bottomLeft, bottomRight, topRight, dimensionX, dimensionY) {\n            const sampler = GridSamplerInstance.getInstance();\n            return sampler.sampleGrid(image, dimensionX, dimensionY, 0.5, 0.5, dimensionX - 0.5, 0.5, dimensionX - 0.5, dimensionY - 0.5, 0.5, dimensionY - 0.5, topLeft.getX(), topLeft.getY(), topRight.getX(), topRight.getY(), bottomRight.getX(), bottomRight.getY(), bottomLeft.getX(), bottomLeft.getY());\n        }\n        /**\n         * Counts the number of black/white transitions between two points, using something like Bresenham's algorithm.\n         */\n        transitionsBetween(from, to) {\n            // See QR Code Detector, sizeOfBlackWhiteBlackRun()\n            let fromX = Math.trunc(from.getX());\n            let fromY = Math.trunc(from.getY());\n            let toX = Math.trunc(to.getX());\n            let toY = Math.trunc(to.getY());\n            let steep = Math.abs(toY - fromY) > Math.abs(toX - fromX);\n            if (steep) {\n                let temp = fromX;\n                fromX = fromY;\n                fromY = temp;\n                temp = toX;\n                toX = toY;\n                toY = temp;\n            }\n            let dx = Math.abs(toX - fromX);\n            let dy = Math.abs(toY - fromY);\n            let error = -dx / 2;\n            let ystep = fromY < toY ? 1 : -1;\n            let xstep = fromX < toX ? 1 : -1;\n            let transitions = 0;\n            let inBlack = this.image.get(steep ? fromY : fromX, steep ? fromX : fromY);\n            for (let x = fromX, y = fromY; x !== toX; x += xstep) {\n                let isBlack = this.image.get(steep ? y : x, steep ? x : y);\n                if (isBlack !== inBlack) {\n                    transitions++;\n                    inBlack = isBlack;\n                }\n                error += dy;\n                if (error > 0) {\n                    if (y === toY) {\n                        break;\n                    }\n                    y += ystep;\n                    error -= dx;\n                }\n            }\n            return transitions;\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * This implementation can detect and decode Data Matrix codes in an image.\n     *\n     * @author bbrown@google.com (Brian Brown)\n     */\n    class DataMatrixReader {\n        constructor() {\n            this.decoder = new Decoder$1();\n        }\n        /**\n         * Locates and decodes a Data Matrix code in an image.\n         *\n         * @return a String representing the content encoded by the Data Matrix code\n         * @throws NotFoundException if a Data Matrix code cannot be found\n         * @throws FormatException if a Data Matrix code cannot be decoded\n         * @throws ChecksumException if error correction fails\n         */\n        // @Override\n        // public Result decode(BinaryBitmap image) throws NotFoundException, ChecksumException, FormatException {\n        //   return decode(image, null);\n        // }\n        // @Override\n        decode(image, hints = null) {\n            let decoderResult;\n            let points;\n            if (hints != null && hints.has(DecodeHintType$1.PURE_BARCODE)) {\n                const bits = DataMatrixReader.extractPureBits(image.getBlackMatrix());\n                decoderResult = this.decoder.decode(bits);\n                points = DataMatrixReader.NO_POINTS;\n            }\n            else {\n                const detectorResult = new Detector$1(image.getBlackMatrix()).detect();\n                decoderResult = this.decoder.decode(detectorResult.getBits());\n                points = detectorResult.getPoints();\n            }\n            const rawBytes = decoderResult.getRawBytes();\n            const result = new Result(decoderResult.getText(), rawBytes, 8 * rawBytes.length, points, BarcodeFormat$1.DATA_MATRIX, System.currentTimeMillis());\n            const byteSegments = decoderResult.getByteSegments();\n            if (byteSegments != null) {\n                result.putMetadata(ResultMetadataType$1.BYTE_SEGMENTS, byteSegments);\n            }\n            const ecLevel = decoderResult.getECLevel();\n            if (ecLevel != null) {\n                result.putMetadata(ResultMetadataType$1.ERROR_CORRECTION_LEVEL, ecLevel);\n            }\n            return result;\n        }\n        // @Override\n        reset() {\n            // do nothing\n        }\n        /**\n         * This method detects a code in a \"pure\" image -- that is, pure monochrome image\n         * which contains only an unrotated, unskewed, image of a code, with some white border\n         * around it. This is a specialized method that works exceptionally fast in this special\n         * case.\n         *\n         * @see com.google.zxing.qrcode.QRCodeReader#extractPureBits(BitMatrix)\n         */\n        static extractPureBits(image) {\n            const leftTopBlack = image.getTopLeftOnBit();\n            const rightBottomBlack = image.getBottomRightOnBit();\n            if (leftTopBlack == null || rightBottomBlack == null) {\n                throw new NotFoundException();\n            }\n            const moduleSize = this.moduleSize(leftTopBlack, image);\n            let top = leftTopBlack[1];\n            const bottom = rightBottomBlack[1];\n            let left = leftTopBlack[0];\n            const right = rightBottomBlack[0];\n            const matrixWidth = (right - left + 1) / moduleSize;\n            const matrixHeight = (bottom - top + 1) / moduleSize;\n            if (matrixWidth <= 0 || matrixHeight <= 0) {\n                throw new NotFoundException();\n            }\n            // Push in the \"border\" by half the module width so that we start\n            // sampling in the middle of the module. Just in case the image is a\n            // little off, this will help recover.\n            const nudge = moduleSize / 2;\n            top += nudge;\n            left += nudge;\n            // Now just read off the bits\n            const bits = new BitMatrix(matrixWidth, matrixHeight);\n            for (let y = 0; y < matrixHeight; y++) {\n                const iOffset = top + y * moduleSize;\n                for (let x = 0; x < matrixWidth; x++) {\n                    if (image.get(left + x * moduleSize, iOffset)) {\n                        bits.set(x, y);\n                    }\n                }\n            }\n            return bits;\n        }\n        static moduleSize(leftTopBlack, image) {\n            const width = image.getWidth();\n            let x = leftTopBlack[0];\n            const y = leftTopBlack[1];\n            while (x < width && image.get(x, y)) {\n                x++;\n            }\n            if (x === width) {\n                throw new NotFoundException();\n            }\n            const moduleSize = x - leftTopBlack[0];\n            if (moduleSize === 0) {\n                throw new NotFoundException();\n            }\n            return moduleSize;\n        }\n    }\n    DataMatrixReader.NO_POINTS = [];\n\n    /**\n     * @deprecated Moving to @zxing/browser\n     *\n     * QR Code reader to use from browser.\n     */\n    class BrowserDatamatrixCodeReader extends BrowserCodeReader {\n        /**\n         * Creates an instance of BrowserQRCodeReader.\n         * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n         */\n        constructor(timeBetweenScansMillis = 500) {\n            super(new DataMatrixReader(), timeBetweenScansMillis);\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    var ErrorCorrectionLevelValues;\n    (function (ErrorCorrectionLevelValues) {\n        ErrorCorrectionLevelValues[ErrorCorrectionLevelValues[\"L\"] = 0] = \"L\";\n        ErrorCorrectionLevelValues[ErrorCorrectionLevelValues[\"M\"] = 1] = \"M\";\n        ErrorCorrectionLevelValues[ErrorCorrectionLevelValues[\"Q\"] = 2] = \"Q\";\n        ErrorCorrectionLevelValues[ErrorCorrectionLevelValues[\"H\"] = 3] = \"H\";\n    })(ErrorCorrectionLevelValues || (ErrorCorrectionLevelValues = {}));\n    /**\n     * <p>See ISO 18004:2006, 6.5.1. This enum encapsulates the four error correction levels\n     * defined by the QR code standard.</p>\n     *\n     * @author Sean Owen\n     */\n    class ErrorCorrectionLevel {\n        constructor(value, stringValue, bits /*int*/) {\n            this.value = value;\n            this.stringValue = stringValue;\n            this.bits = bits;\n            ErrorCorrectionLevel.FOR_BITS.set(bits, this);\n            ErrorCorrectionLevel.FOR_VALUE.set(value, this);\n        }\n        getValue() {\n            return this.value;\n        }\n        getBits() {\n            return this.bits;\n        }\n        static fromString(s) {\n            switch (s) {\n                case 'L': return ErrorCorrectionLevel.L;\n                case 'M': return ErrorCorrectionLevel.M;\n                case 'Q': return ErrorCorrectionLevel.Q;\n                case 'H': return ErrorCorrectionLevel.H;\n                default: throw new ArgumentException(s + 'not available');\n            }\n        }\n        toString() {\n            return this.stringValue;\n        }\n        equals(o) {\n            if (!(o instanceof ErrorCorrectionLevel)) {\n                return false;\n            }\n            const other = o;\n            return this.value === other.value;\n        }\n        /**\n         * @param bits int containing the two bits encoding a QR Code's error correction level\n         * @return ErrorCorrectionLevel representing the encoded error correction level\n         */\n        static forBits(bits /*int*/) {\n            if (bits < 0 || bits >= ErrorCorrectionLevel.FOR_BITS.size) {\n                throw new IllegalArgumentException();\n            }\n            return ErrorCorrectionLevel.FOR_BITS.get(bits);\n        }\n    }\n    ErrorCorrectionLevel.FOR_BITS = new Map();\n    ErrorCorrectionLevel.FOR_VALUE = new Map();\n    /** L = ~7% correction */\n    ErrorCorrectionLevel.L = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.L, 'L', 0x01);\n    /** M = ~15% correction */\n    ErrorCorrectionLevel.M = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.M, 'M', 0x00);\n    /** Q = ~25% correction */\n    ErrorCorrectionLevel.Q = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.Q, 'Q', 0x03);\n    /** H = ~30% correction */\n    ErrorCorrectionLevel.H = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.H, 'H', 0x02);\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates a QR Code's format information, including the data mask used and\n     * error correction level.</p>\n     *\n     * @author Sean Owen\n     * @see DataMask\n     * @see ErrorCorrectionLevel\n     */\n    class FormatInformation {\n        constructor(formatInfo /*int*/) {\n            // Bits 3,4\n            this.errorCorrectionLevel = ErrorCorrectionLevel.forBits((formatInfo >> 3) & 0x03);\n            // Bottom 3 bits\n            this.dataMask = /*(byte) */ (formatInfo & 0x07);\n        }\n        static numBitsDiffering(a /*int*/, b /*int*/) {\n            return Integer.bitCount(a ^ b);\n        }\n        /**\n         * @param maskedFormatInfo1 format info indicator, with mask still applied\n         * @param maskedFormatInfo2 second copy of same info; both are checked at the same time\n         *  to establish best match\n         * @return information about the format it specifies, or {@code null}\n         *  if doesn't seem to match any known pattern\n         */\n        static decodeFormatInformation(maskedFormatInfo1 /*int*/, maskedFormatInfo2 /*int*/) {\n            const formatInfo = FormatInformation.doDecodeFormatInformation(maskedFormatInfo1, maskedFormatInfo2);\n            if (formatInfo !== null) {\n                return formatInfo;\n            }\n            // Should return null, but, some QR codes apparently\n            // do not mask this info. Try again by actually masking the pattern\n            // first\n            return FormatInformation.doDecodeFormatInformation(maskedFormatInfo1 ^ FormatInformation.FORMAT_INFO_MASK_QR, maskedFormatInfo2 ^ FormatInformation.FORMAT_INFO_MASK_QR);\n        }\n        static doDecodeFormatInformation(maskedFormatInfo1 /*int*/, maskedFormatInfo2 /*int*/) {\n            // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing\n            let bestDifference = Number.MAX_SAFE_INTEGER;\n            let bestFormatInfo = 0;\n            for (const decodeInfo of FormatInformation.FORMAT_INFO_DECODE_LOOKUP) {\n                const targetInfo = decodeInfo[0];\n                if (targetInfo === maskedFormatInfo1 || targetInfo === maskedFormatInfo2) {\n                    // Found an exact match\n                    return new FormatInformation(decodeInfo[1]);\n                }\n                let bitsDifference = FormatInformation.numBitsDiffering(maskedFormatInfo1, targetInfo);\n                if (bitsDifference < bestDifference) {\n                    bestFormatInfo = decodeInfo[1];\n                    bestDifference = bitsDifference;\n                }\n                if (maskedFormatInfo1 !== maskedFormatInfo2) {\n                    // also try the other option\n                    bitsDifference = FormatInformation.numBitsDiffering(maskedFormatInfo2, targetInfo);\n                    if (bitsDifference < bestDifference) {\n                        bestFormatInfo = decodeInfo[1];\n                        bestDifference = bitsDifference;\n                    }\n                }\n            }\n            // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits\n            // differing means we found a match\n            if (bestDifference <= 3) {\n                return new FormatInformation(bestFormatInfo);\n            }\n            return null;\n        }\n        getErrorCorrectionLevel() {\n            return this.errorCorrectionLevel;\n        }\n        getDataMask() {\n            return this.dataMask;\n        }\n        /*@Override*/\n        hashCode() {\n            return (this.errorCorrectionLevel.getBits() << 3) | this.dataMask;\n        }\n        /*@Override*/\n        equals(o) {\n            if (!(o instanceof FormatInformation)) {\n                return false;\n            }\n            const other = o;\n            return this.errorCorrectionLevel === other.errorCorrectionLevel &&\n                this.dataMask === other.dataMask;\n        }\n    }\n    FormatInformation.FORMAT_INFO_MASK_QR = 0x5412;\n    /**\n     * See ISO 18004:2006, Annex C, Table C.1\n     */\n    FormatInformation.FORMAT_INFO_DECODE_LOOKUP = [\n        Int32Array.from([0x5412, 0x00]),\n        Int32Array.from([0x5125, 0x01]),\n        Int32Array.from([0x5E7C, 0x02]),\n        Int32Array.from([0x5B4B, 0x03]),\n        Int32Array.from([0x45F9, 0x04]),\n        Int32Array.from([0x40CE, 0x05]),\n        Int32Array.from([0x4F97, 0x06]),\n        Int32Array.from([0x4AA0, 0x07]),\n        Int32Array.from([0x77C4, 0x08]),\n        Int32Array.from([0x72F3, 0x09]),\n        Int32Array.from([0x7DAA, 0x0A]),\n        Int32Array.from([0x789D, 0x0B]),\n        Int32Array.from([0x662F, 0x0C]),\n        Int32Array.from([0x6318, 0x0D]),\n        Int32Array.from([0x6C41, 0x0E]),\n        Int32Array.from([0x6976, 0x0F]),\n        Int32Array.from([0x1689, 0x10]),\n        Int32Array.from([0x13BE, 0x11]),\n        Int32Array.from([0x1CE7, 0x12]),\n        Int32Array.from([0x19D0, 0x13]),\n        Int32Array.from([0x0762, 0x14]),\n        Int32Array.from([0x0255, 0x15]),\n        Int32Array.from([0x0D0C, 0x16]),\n        Int32Array.from([0x083B, 0x17]),\n        Int32Array.from([0x355F, 0x18]),\n        Int32Array.from([0x3068, 0x19]),\n        Int32Array.from([0x3F31, 0x1A]),\n        Int32Array.from([0x3A06, 0x1B]),\n        Int32Array.from([0x24B4, 0x1C]),\n        Int32Array.from([0x2183, 0x1D]),\n        Int32Array.from([0x2EDA, 0x1E]),\n        Int32Array.from([0x2BED, 0x1F]),\n    ];\n\n    /**\n     * <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will\n     * use blocks of differing sizes within one version, so, this encapsulates the parameters for\n     * each set of blocks. It also holds the number of error-correction codewords per block since it\n     * will be the same across all blocks within one version.</p>\n     */\n    class ECBlocks$1 {\n        constructor(ecCodewordsPerBlock /*int*/, ...ecBlocks) {\n            this.ecCodewordsPerBlock = ecCodewordsPerBlock;\n            this.ecBlocks = ecBlocks;\n        }\n        getECCodewordsPerBlock() {\n            return this.ecCodewordsPerBlock;\n        }\n        getNumBlocks() {\n            let total = 0;\n            const ecBlocks = this.ecBlocks;\n            for (const ecBlock of ecBlocks) {\n                total += ecBlock.getCount();\n            }\n            return total;\n        }\n        getTotalECCodewords() {\n            return this.ecCodewordsPerBlock * this.getNumBlocks();\n        }\n        getECBlocks() {\n            return this.ecBlocks;\n        }\n    }\n\n    /**\n     * <p>Encapsulates the parameters for one error-correction block in one symbol version.\n     * This includes the number of data codewords, and the number of times a block with these\n     * parameters is used consecutively in the QR code version's format.</p>\n     */\n    class ECB$1 {\n        constructor(count /*int*/, dataCodewords /*int*/) {\n            this.count = count;\n            this.dataCodewords = dataCodewords;\n        }\n        getCount() {\n            return this.count;\n        }\n        getDataCodewords() {\n            return this.dataCodewords;\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * See ISO 18004:2006 Annex D\n     *\n     * @author Sean Owen\n     */\n    class Version$1 {\n        constructor(versionNumber /*int*/, alignmentPatternCenters, ...ecBlocks) {\n            this.versionNumber = versionNumber;\n            this.alignmentPatternCenters = alignmentPatternCenters;\n            this.ecBlocks = ecBlocks;\n            let total = 0;\n            const ecCodewords = ecBlocks[0].getECCodewordsPerBlock();\n            const ecbArray = ecBlocks[0].getECBlocks();\n            for (const ecBlock of ecbArray) {\n                total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);\n            }\n            this.totalCodewords = total;\n        }\n        getVersionNumber() {\n            return this.versionNumber;\n        }\n        getAlignmentPatternCenters() {\n            return this.alignmentPatternCenters;\n        }\n        getTotalCodewords() {\n            return this.totalCodewords;\n        }\n        getDimensionForVersion() {\n            return 17 + 4 * this.versionNumber;\n        }\n        getECBlocksForLevel(ecLevel) {\n            return this.ecBlocks[ecLevel.getValue()];\n            // TYPESCRIPTPORT: original was using ordinal, and using the order of levels as defined in ErrorCorrectionLevel enum (LMQH)\n            // I will use the direct value from ErrorCorrectionLevelValues enum which in typescript goes to a number\n        }\n        /**\n         * <p>Deduces version information purely from QR Code dimensions.</p>\n         *\n         * @param dimension dimension in modules\n         * @return Version for a QR Code of that dimension\n         * @throws FormatException if dimension is not 1 mod 4\n         */\n        static getProvisionalVersionForDimension(dimension /*int*/) {\n            if (dimension % 4 !== 1) {\n                throw new FormatException();\n            }\n            try {\n                return this.getVersionForNumber((dimension - 17) / 4);\n            }\n            catch (ignored /*: IllegalArgumentException*/) {\n                throw new FormatException();\n            }\n        }\n        static getVersionForNumber(versionNumber /*int*/) {\n            if (versionNumber < 1 || versionNumber > 40) {\n                throw new IllegalArgumentException();\n            }\n            return Version$1.VERSIONS[versionNumber - 1];\n        }\n        static decodeVersionInformation(versionBits /*int*/) {\n            let bestDifference = Number.MAX_SAFE_INTEGER;\n            let bestVersion = 0;\n            for (let i = 0; i < Version$1.VERSION_DECODE_INFO.length; i++) {\n                const targetVersion = Version$1.VERSION_DECODE_INFO[i];\n                // Do the version info bits match exactly? done.\n                if (targetVersion === versionBits) {\n                    return Version$1.getVersionForNumber(i + 7);\n                }\n                // Otherwise see if this is the closest to a real version info bit string\n                // we have seen so far\n                const bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion);\n                if (bitsDifference < bestDifference) {\n                    bestVersion = i + 7;\n                    bestDifference = bitsDifference;\n                }\n            }\n            // We can tolerate up to 3 bits of error since no two version info codewords will\n            // differ in less than 8 bits.\n            if (bestDifference <= 3) {\n                return Version$1.getVersionForNumber(bestVersion);\n            }\n            // If we didn't find a close enough match, fail\n            return null;\n        }\n        /**\n         * See ISO 18004:2006 Annex E\n         */\n        buildFunctionPattern() {\n            const dimension = this.getDimensionForVersion();\n            const bitMatrix = new BitMatrix(dimension);\n            // Top left finder pattern + separator + format\n            bitMatrix.setRegion(0, 0, 9, 9);\n            // Top right finder pattern + separator + format\n            bitMatrix.setRegion(dimension - 8, 0, 8, 9);\n            // Bottom left finder pattern + separator + format\n            bitMatrix.setRegion(0, dimension - 8, 9, 8);\n            // Alignment patterns\n            const max = this.alignmentPatternCenters.length;\n            for (let x = 0; x < max; x++) {\n                const i = this.alignmentPatternCenters[x] - 2;\n                for (let y = 0; y < max; y++) {\n                    if ((x === 0 && (y === 0 || y === max - 1)) || (x === max - 1 && y === 0)) {\n                        // No alignment patterns near the three finder patterns\n                        continue;\n                    }\n                    bitMatrix.setRegion(this.alignmentPatternCenters[y] - 2, i, 5, 5);\n                }\n            }\n            // Vertical timing pattern\n            bitMatrix.setRegion(6, 9, 1, dimension - 17);\n            // Horizontal timing pattern\n            bitMatrix.setRegion(9, 6, dimension - 17, 1);\n            if (this.versionNumber > 6) {\n                // Version info, top right\n                bitMatrix.setRegion(dimension - 11, 0, 3, 6);\n                // Version info, bottom left\n                bitMatrix.setRegion(0, dimension - 11, 6, 3);\n            }\n            return bitMatrix;\n        }\n        /*@Override*/\n        toString() {\n            return '' + this.versionNumber;\n        }\n    }\n    /**\n       * See ISO 18004:2006 Annex D.\n       * Element i represents the raw version bits that specify version i + 7\n       */\n    Version$1.VERSION_DECODE_INFO = Int32Array.from([\n        0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6,\n        0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78,\n        0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683,\n        0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB,\n        0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250,\n        0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B,\n        0x2542E, 0x26A64, 0x27541, 0x28C69\n    ]);\n    /**\n       * See ISO 18004:2006 6.5.1 Table 9\n       */\n    Version$1.VERSIONS = [\n        new Version$1(1, new Int32Array(0), new ECBlocks$1(7, new ECB$1(1, 19)), new ECBlocks$1(10, new ECB$1(1, 16)), new ECBlocks$1(13, new ECB$1(1, 13)), new ECBlocks$1(17, new ECB$1(1, 9))),\n        new Version$1(2, Int32Array.from([6, 18]), new ECBlocks$1(10, new ECB$1(1, 34)), new ECBlocks$1(16, new ECB$1(1, 28)), new ECBlocks$1(22, new ECB$1(1, 22)), new ECBlocks$1(28, new ECB$1(1, 16))),\n        new Version$1(3, Int32Array.from([6, 22]), new ECBlocks$1(15, new ECB$1(1, 55)), new ECBlocks$1(26, new ECB$1(1, 44)), new ECBlocks$1(18, new ECB$1(2, 17)), new ECBlocks$1(22, new ECB$1(2, 13))),\n        new Version$1(4, Int32Array.from([6, 26]), new ECBlocks$1(20, new ECB$1(1, 80)), new ECBlocks$1(18, new ECB$1(2, 32)), new ECBlocks$1(26, new ECB$1(2, 24)), new ECBlocks$1(16, new ECB$1(4, 9))),\n        new Version$1(5, Int32Array.from([6, 30]), new ECBlocks$1(26, new ECB$1(1, 108)), new ECBlocks$1(24, new ECB$1(2, 43)), new ECBlocks$1(18, new ECB$1(2, 15), new ECB$1(2, 16)), new ECBlocks$1(22, new ECB$1(2, 11), new ECB$1(2, 12))),\n        new Version$1(6, Int32Array.from([6, 34]), new ECBlocks$1(18, new ECB$1(2, 68)), new ECBlocks$1(16, new ECB$1(4, 27)), new ECBlocks$1(24, new ECB$1(4, 19)), new ECBlocks$1(28, new ECB$1(4, 15))),\n        new Version$1(7, Int32Array.from([6, 22, 38]), new ECBlocks$1(20, new ECB$1(2, 78)), new ECBlocks$1(18, new ECB$1(4, 31)), new ECBlocks$1(18, new ECB$1(2, 14), new ECB$1(4, 15)), new ECBlocks$1(26, new ECB$1(4, 13), new ECB$1(1, 14))),\n        new Version$1(8, Int32Array.from([6, 24, 42]), new ECBlocks$1(24, new ECB$1(2, 97)), new ECBlocks$1(22, new ECB$1(2, 38), new ECB$1(2, 39)), new ECBlocks$1(22, new ECB$1(4, 18), new ECB$1(2, 19)), new ECBlocks$1(26, new ECB$1(4, 14), new ECB$1(2, 15))),\n        new Version$1(9, Int32Array.from([6, 26, 46]), new ECBlocks$1(30, new ECB$1(2, 116)), new ECBlocks$1(22, new ECB$1(3, 36), new ECB$1(2, 37)), new ECBlocks$1(20, new ECB$1(4, 16), new ECB$1(4, 17)), new ECBlocks$1(24, new ECB$1(4, 12), new ECB$1(4, 13))),\n        new Version$1(10, Int32Array.from([6, 28, 50]), new ECBlocks$1(18, new ECB$1(2, 68), new ECB$1(2, 69)), new ECBlocks$1(26, new ECB$1(4, 43), new ECB$1(1, 44)), new ECBlocks$1(24, new ECB$1(6, 19), new ECB$1(2, 20)), new ECBlocks$1(28, new ECB$1(6, 15), new ECB$1(2, 16))),\n        new Version$1(11, Int32Array.from([6, 30, 54]), new ECBlocks$1(20, new ECB$1(4, 81)), new ECBlocks$1(30, new ECB$1(1, 50), new ECB$1(4, 51)), new ECBlocks$1(28, new ECB$1(4, 22), new ECB$1(4, 23)), new ECBlocks$1(24, new ECB$1(3, 12), new ECB$1(8, 13))),\n        new Version$1(12, Int32Array.from([6, 32, 58]), new ECBlocks$1(24, new ECB$1(2, 92), new ECB$1(2, 93)), new ECBlocks$1(22, new ECB$1(6, 36), new ECB$1(2, 37)), new ECBlocks$1(26, new ECB$1(4, 20), new ECB$1(6, 21)), new ECBlocks$1(28, new ECB$1(7, 14), new ECB$1(4, 15))),\n        new Version$1(13, Int32Array.from([6, 34, 62]), new ECBlocks$1(26, new ECB$1(4, 107)), new ECBlocks$1(22, new ECB$1(8, 37), new ECB$1(1, 38)), new ECBlocks$1(24, new ECB$1(8, 20), new ECB$1(4, 21)), new ECBlocks$1(22, new ECB$1(12, 11), new ECB$1(4, 12))),\n        new Version$1(14, Int32Array.from([6, 26, 46, 66]), new ECBlocks$1(30, new ECB$1(3, 115), new ECB$1(1, 116)), new ECBlocks$1(24, new ECB$1(4, 40), new ECB$1(5, 41)), new ECBlocks$1(20, new ECB$1(11, 16), new ECB$1(5, 17)), new ECBlocks$1(24, new ECB$1(11, 12), new ECB$1(5, 13))),\n        new Version$1(15, Int32Array.from([6, 26, 48, 70]), new ECBlocks$1(22, new ECB$1(5, 87), new ECB$1(1, 88)), new ECBlocks$1(24, new ECB$1(5, 41), new ECB$1(5, 42)), new ECBlocks$1(30, new ECB$1(5, 24), new ECB$1(7, 25)), new ECBlocks$1(24, new ECB$1(11, 12), new ECB$1(7, 13))),\n        new Version$1(16, Int32Array.from([6, 26, 50, 74]), new ECBlocks$1(24, new ECB$1(5, 98), new ECB$1(1, 99)), new ECBlocks$1(28, new ECB$1(7, 45), new ECB$1(3, 46)), new ECBlocks$1(24, new ECB$1(15, 19), new ECB$1(2, 20)), new ECBlocks$1(30, new ECB$1(3, 15), new ECB$1(13, 16))),\n        new Version$1(17, Int32Array.from([6, 30, 54, 78]), new ECBlocks$1(28, new ECB$1(1, 107), new ECB$1(5, 108)), new ECBlocks$1(28, new ECB$1(10, 46), new ECB$1(1, 47)), new ECBlocks$1(28, new ECB$1(1, 22), new ECB$1(15, 23)), new ECBlocks$1(28, new ECB$1(2, 14), new ECB$1(17, 15))),\n        new Version$1(18, Int32Array.from([6, 30, 56, 82]), new ECBlocks$1(30, new ECB$1(5, 120), new ECB$1(1, 121)), new ECBlocks$1(26, new ECB$1(9, 43), new ECB$1(4, 44)), new ECBlocks$1(28, new ECB$1(17, 22), new ECB$1(1, 23)), new ECBlocks$1(28, new ECB$1(2, 14), new ECB$1(19, 15))),\n        new Version$1(19, Int32Array.from([6, 30, 58, 86]), new ECBlocks$1(28, new ECB$1(3, 113), new ECB$1(4, 114)), new ECBlocks$1(26, new ECB$1(3, 44), new ECB$1(11, 45)), new ECBlocks$1(26, new ECB$1(17, 21), new ECB$1(4, 22)), new ECBlocks$1(26, new ECB$1(9, 13), new ECB$1(16, 14))),\n        new Version$1(20, Int32Array.from([6, 34, 62, 90]), new ECBlocks$1(28, new ECB$1(3, 107), new ECB$1(5, 108)), new ECBlocks$1(26, new ECB$1(3, 41), new ECB$1(13, 42)), new ECBlocks$1(30, new ECB$1(15, 24), new ECB$1(5, 25)), new ECBlocks$1(28, new ECB$1(15, 15), new ECB$1(10, 16))),\n        new Version$1(21, Int32Array.from([6, 28, 50, 72, 94]), new ECBlocks$1(28, new ECB$1(4, 116), new ECB$1(4, 117)), new ECBlocks$1(26, new ECB$1(17, 42)), new ECBlocks$1(28, new ECB$1(17, 22), new ECB$1(6, 23)), new ECBlocks$1(30, new ECB$1(19, 16), new ECB$1(6, 17))),\n        new Version$1(22, Int32Array.from([6, 26, 50, 74, 98]), new ECBlocks$1(28, new ECB$1(2, 111), new ECB$1(7, 112)), new ECBlocks$1(28, new ECB$1(17, 46)), new ECBlocks$1(30, new ECB$1(7, 24), new ECB$1(16, 25)), new ECBlocks$1(24, new ECB$1(34, 13))),\n        new Version$1(23, Int32Array.from([6, 30, 54, 78, 102]), new ECBlocks$1(30, new ECB$1(4, 121), new ECB$1(5, 122)), new ECBlocks$1(28, new ECB$1(4, 47), new ECB$1(14, 48)), new ECBlocks$1(30, new ECB$1(11, 24), new ECB$1(14, 25)), new ECBlocks$1(30, new ECB$1(16, 15), new ECB$1(14, 16))),\n        new Version$1(24, Int32Array.from([6, 28, 54, 80, 106]), new ECBlocks$1(30, new ECB$1(6, 117), new ECB$1(4, 118)), new ECBlocks$1(28, new ECB$1(6, 45), new ECB$1(14, 46)), new ECBlocks$1(30, new ECB$1(11, 24), new ECB$1(16, 25)), new ECBlocks$1(30, new ECB$1(30, 16), new ECB$1(2, 17))),\n        new Version$1(25, Int32Array.from([6, 32, 58, 84, 110]), new ECBlocks$1(26, new ECB$1(8, 106), new ECB$1(4, 107)), new ECBlocks$1(28, new ECB$1(8, 47), new ECB$1(13, 48)), new ECBlocks$1(30, new ECB$1(7, 24), new ECB$1(22, 25)), new ECBlocks$1(30, new ECB$1(22, 15), new ECB$1(13, 16))),\n        new Version$1(26, Int32Array.from([6, 30, 58, 86, 114]), new ECBlocks$1(28, new ECB$1(10, 114), new ECB$1(2, 115)), new ECBlocks$1(28, new ECB$1(19, 46), new ECB$1(4, 47)), new ECBlocks$1(28, new ECB$1(28, 22), new ECB$1(6, 23)), new ECBlocks$1(30, new ECB$1(33, 16), new ECB$1(4, 17))),\n        new Version$1(27, Int32Array.from([6, 34, 62, 90, 118]), new ECBlocks$1(30, new ECB$1(8, 122), new ECB$1(4, 123)), new ECBlocks$1(28, new ECB$1(22, 45), new ECB$1(3, 46)), new ECBlocks$1(30, new ECB$1(8, 23), new ECB$1(26, 24)), new ECBlocks$1(30, new ECB$1(12, 15), new ECB$1(28, 16))),\n        new Version$1(28, Int32Array.from([6, 26, 50, 74, 98, 122]), new ECBlocks$1(30, new ECB$1(3, 117), new ECB$1(10, 118)), new ECBlocks$1(28, new ECB$1(3, 45), new ECB$1(23, 46)), new ECBlocks$1(30, new ECB$1(4, 24), new ECB$1(31, 25)), new ECBlocks$1(30, new ECB$1(11, 15), new ECB$1(31, 16))),\n        new Version$1(29, Int32Array.from([6, 30, 54, 78, 102, 126]), new ECBlocks$1(30, new ECB$1(7, 116), new ECB$1(7, 117)), new ECBlocks$1(28, new ECB$1(21, 45), new ECB$1(7, 46)), new ECBlocks$1(30, new ECB$1(1, 23), new ECB$1(37, 24)), new ECBlocks$1(30, new ECB$1(19, 15), new ECB$1(26, 16))),\n        new Version$1(30, Int32Array.from([6, 26, 52, 78, 104, 130]), new ECBlocks$1(30, new ECB$1(5, 115), new ECB$1(10, 116)), new ECBlocks$1(28, new ECB$1(19, 47), new ECB$1(10, 48)), new ECBlocks$1(30, new ECB$1(15, 24), new ECB$1(25, 25)), new ECBlocks$1(30, new ECB$1(23, 15), new ECB$1(25, 16))),\n        new Version$1(31, Int32Array.from([6, 30, 56, 82, 108, 134]), new ECBlocks$1(30, new ECB$1(13, 115), new ECB$1(3, 116)), new ECBlocks$1(28, new ECB$1(2, 46), new ECB$1(29, 47)), new ECBlocks$1(30, new ECB$1(42, 24), new ECB$1(1, 25)), new ECBlocks$1(30, new ECB$1(23, 15), new ECB$1(28, 16))),\n        new Version$1(32, Int32Array.from([6, 34, 60, 86, 112, 138]), new ECBlocks$1(30, new ECB$1(17, 115)), new ECBlocks$1(28, new ECB$1(10, 46), new ECB$1(23, 47)), new ECBlocks$1(30, new ECB$1(10, 24), new ECB$1(35, 25)), new ECBlocks$1(30, new ECB$1(19, 15), new ECB$1(35, 16))),\n        new Version$1(33, Int32Array.from([6, 30, 58, 86, 114, 142]), new ECBlocks$1(30, new ECB$1(17, 115), new ECB$1(1, 116)), new ECBlocks$1(28, new ECB$1(14, 46), new ECB$1(21, 47)), new ECBlocks$1(30, new ECB$1(29, 24), new ECB$1(19, 25)), new ECBlocks$1(30, new ECB$1(11, 15), new ECB$1(46, 16))),\n        new Version$1(34, Int32Array.from([6, 34, 62, 90, 118, 146]), new ECBlocks$1(30, new ECB$1(13, 115), new ECB$1(6, 116)), new ECBlocks$1(28, new ECB$1(14, 46), new ECB$1(23, 47)), new ECBlocks$1(30, new ECB$1(44, 24), new ECB$1(7, 25)), new ECBlocks$1(30, new ECB$1(59, 16), new ECB$1(1, 17))),\n        new Version$1(35, Int32Array.from([6, 30, 54, 78, 102, 126, 150]), new ECBlocks$1(30, new ECB$1(12, 121), new ECB$1(7, 122)), new ECBlocks$1(28, new ECB$1(12, 47), new ECB$1(26, 48)), new ECBlocks$1(30, new ECB$1(39, 24), new ECB$1(14, 25)), new ECBlocks$1(30, new ECB$1(22, 15), new ECB$1(41, 16))),\n        new Version$1(36, Int32Array.from([6, 24, 50, 76, 102, 128, 154]), new ECBlocks$1(30, new ECB$1(6, 121), new ECB$1(14, 122)), new ECBlocks$1(28, new ECB$1(6, 47), new ECB$1(34, 48)), new ECBlocks$1(30, new ECB$1(46, 24), new ECB$1(10, 25)), new ECBlocks$1(30, new ECB$1(2, 15), new ECB$1(64, 16))),\n        new Version$1(37, Int32Array.from([6, 28, 54, 80, 106, 132, 158]), new ECBlocks$1(30, new ECB$1(17, 122), new ECB$1(4, 123)), new ECBlocks$1(28, new ECB$1(29, 46), new ECB$1(14, 47)), new ECBlocks$1(30, new ECB$1(49, 24), new ECB$1(10, 25)), new ECBlocks$1(30, new ECB$1(24, 15), new ECB$1(46, 16))),\n        new Version$1(38, Int32Array.from([6, 32, 58, 84, 110, 136, 162]), new ECBlocks$1(30, new ECB$1(4, 122), new ECB$1(18, 123)), new ECBlocks$1(28, new ECB$1(13, 46), new ECB$1(32, 47)), new ECBlocks$1(30, new ECB$1(48, 24), new ECB$1(14, 25)), new ECBlocks$1(30, new ECB$1(42, 15), new ECB$1(32, 16))),\n        new Version$1(39, Int32Array.from([6, 26, 54, 82, 110, 138, 166]), new ECBlocks$1(30, new ECB$1(20, 117), new ECB$1(4, 118)), new ECBlocks$1(28, new ECB$1(40, 47), new ECB$1(7, 48)), new ECBlocks$1(30, new ECB$1(43, 24), new ECB$1(22, 25)), new ECBlocks$1(30, new ECB$1(10, 15), new ECB$1(67, 16))),\n        new Version$1(40, Int32Array.from([6, 30, 58, 86, 114, 142, 170]), new ECBlocks$1(30, new ECB$1(19, 118), new ECB$1(6, 119)), new ECBlocks$1(28, new ECB$1(18, 47), new ECB$1(31, 48)), new ECBlocks$1(30, new ECB$1(34, 24), new ECB$1(34, 25)), new ECBlocks$1(30, new ECB$1(20, 15), new ECB$1(61, 16)))\n    ];\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    var DataMaskValues;\n    (function (DataMaskValues) {\n        DataMaskValues[DataMaskValues[\"DATA_MASK_000\"] = 0] = \"DATA_MASK_000\";\n        DataMaskValues[DataMaskValues[\"DATA_MASK_001\"] = 1] = \"DATA_MASK_001\";\n        DataMaskValues[DataMaskValues[\"DATA_MASK_010\"] = 2] = \"DATA_MASK_010\";\n        DataMaskValues[DataMaskValues[\"DATA_MASK_011\"] = 3] = \"DATA_MASK_011\";\n        DataMaskValues[DataMaskValues[\"DATA_MASK_100\"] = 4] = \"DATA_MASK_100\";\n        DataMaskValues[DataMaskValues[\"DATA_MASK_101\"] = 5] = \"DATA_MASK_101\";\n        DataMaskValues[DataMaskValues[\"DATA_MASK_110\"] = 6] = \"DATA_MASK_110\";\n        DataMaskValues[DataMaskValues[\"DATA_MASK_111\"] = 7] = \"DATA_MASK_111\";\n    })(DataMaskValues || (DataMaskValues = {}));\n    /**\n     * <p>Encapsulates data masks for the data bits in a QR code, per ISO 18004:2006 6.8. Implementations\n     * of this class can un-mask a raw BitMatrix. For simplicity, they will unmask the entire BitMatrix,\n     * including areas used for finder patterns, timing patterns, etc. These areas should be unused\n     * after the point they are unmasked anyway.</p>\n     *\n     * <p>Note that the diagram in section 6.8.1 is misleading since it indicates that i is column position\n     * and j is row position. In fact, as the text says, i is row position and j is column position.</p>\n     *\n     * @author Sean Owen\n     */\n    class DataMask {\n        // See ISO 18004:2006 6.8.1\n        constructor(value, isMasked) {\n            this.value = value;\n            this.isMasked = isMasked;\n        }\n        // End of enum constants.\n        /**\n         * <p>Implementations of this method reverse the data masking process applied to a QR Code and\n         * make its bits ready to read.</p>\n         *\n         * @param bits representation of QR Code bits\n         * @param dimension dimension of QR Code, represented by bits, being unmasked\n         */\n        unmaskBitMatrix(bits, dimension /*int*/) {\n            for (let i = 0; i < dimension; i++) {\n                for (let j = 0; j < dimension; j++) {\n                    if (this.isMasked(i, j)) {\n                        bits.flip(j, i);\n                    }\n                }\n            }\n        }\n    }\n    DataMask.values = new Map([\n        /**\n         * 000: mask bits for which (x + y) mod 2 == 0\n         */\n        [DataMaskValues.DATA_MASK_000, new DataMask(DataMaskValues.DATA_MASK_000, (i /*int*/, j /*int*/) => { return ((i + j) & 0x01) === 0; })],\n        /**\n         * 001: mask bits for which x mod 2 == 0\n         */\n        [DataMaskValues.DATA_MASK_001, new DataMask(DataMaskValues.DATA_MASK_001, (i /*int*/, j /*int*/) => { return (i & 0x01) === 0; })],\n        /**\n         * 010: mask bits for which y mod 3 == 0\n         */\n        [DataMaskValues.DATA_MASK_010, new DataMask(DataMaskValues.DATA_MASK_010, (i /*int*/, j /*int*/) => { return j % 3 === 0; })],\n        /**\n         * 011: mask bits for which (x + y) mod 3 == 0\n         */\n        [DataMaskValues.DATA_MASK_011, new DataMask(DataMaskValues.DATA_MASK_011, (i /*int*/, j /*int*/) => { return (i + j) % 3 === 0; })],\n        /**\n         * 100: mask bits for which (x/2 + y/3) mod 2 == 0\n         */\n        [DataMaskValues.DATA_MASK_100, new DataMask(DataMaskValues.DATA_MASK_100, (i /*int*/, j /*int*/) => { return ((Math.floor(i / 2) + Math.floor(j / 3)) & 0x01) === 0; })],\n        /**\n         * 101: mask bits for which xy mod 2 + xy mod 3 == 0\n         * equivalently, such that xy mod 6 == 0\n         */\n        [DataMaskValues.DATA_MASK_101, new DataMask(DataMaskValues.DATA_MASK_101, (i /*int*/, j /*int*/) => { return (i * j) % 6 === 0; })],\n        /**\n         * 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0\n         * equivalently, such that xy mod 6 < 3\n         */\n        [DataMaskValues.DATA_MASK_110, new DataMask(DataMaskValues.DATA_MASK_110, (i /*int*/, j /*int*/) => { return ((i * j) % 6) < 3; })],\n        /**\n         * 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0\n         * equivalently, such that (x + y + xy mod 3) mod 2 == 0\n         */\n        [DataMaskValues.DATA_MASK_111, new DataMask(DataMaskValues.DATA_MASK_111, (i /*int*/, j /*int*/) => { return ((i + j + ((i * j) % 3)) & 0x01) === 0; })],\n    ]);\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * @author Sean Owen\n     */\n    class BitMatrixParser$1 {\n        /**\n         * @param bitMatrix {@link BitMatrix} to parse\n         * @throws FormatException if dimension is not >= 21 and 1 mod 4\n         */\n        constructor(bitMatrix) {\n            const dimension = bitMatrix.getHeight();\n            if (dimension < 21 || (dimension & 0x03) !== 1) {\n                throw new FormatException();\n            }\n            this.bitMatrix = bitMatrix;\n        }\n        /**\n         * <p>Reads format information from one of its two locations within the QR Code.</p>\n         *\n         * @return {@link FormatInformation} encapsulating the QR Code's format info\n         * @throws FormatException if both format information locations cannot be parsed as\n         * the valid encoding of format information\n         */\n        readFormatInformation() {\n            if (this.parsedFormatInfo !== null && this.parsedFormatInfo !== undefined) {\n                return this.parsedFormatInfo;\n            }\n            // Read top-left format info bits\n            let formatInfoBits1 = 0;\n            for (let i = 0; i < 6; i++) {\n                formatInfoBits1 = this.copyBit(i, 8, formatInfoBits1);\n            }\n            // .. and skip a bit in the timing pattern ...\n            formatInfoBits1 = this.copyBit(7, 8, formatInfoBits1);\n            formatInfoBits1 = this.copyBit(8, 8, formatInfoBits1);\n            formatInfoBits1 = this.copyBit(8, 7, formatInfoBits1);\n            // .. and skip a bit in the timing pattern ...\n            for (let j = 5; j >= 0; j--) {\n                formatInfoBits1 = this.copyBit(8, j, formatInfoBits1);\n            }\n            // Read the top-right/bottom-left pattern too\n            const dimension = this.bitMatrix.getHeight();\n            let formatInfoBits2 = 0;\n            const jMin = dimension - 7;\n            for (let j = dimension - 1; j >= jMin; j--) {\n                formatInfoBits2 = this.copyBit(8, j, formatInfoBits2);\n            }\n            for (let i = dimension - 8; i < dimension; i++) {\n                formatInfoBits2 = this.copyBit(i, 8, formatInfoBits2);\n            }\n            this.parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits1, formatInfoBits2);\n            if (this.parsedFormatInfo !== null) {\n                return this.parsedFormatInfo;\n            }\n            throw new FormatException();\n        }\n        /**\n         * <p>Reads version information from one of its two locations within the QR Code.</p>\n         *\n         * @return {@link Version} encapsulating the QR Code's version\n         * @throws FormatException if both version information locations cannot be parsed as\n         * the valid encoding of version information\n         */\n        readVersion() {\n            if (this.parsedVersion !== null && this.parsedVersion !== undefined) {\n                return this.parsedVersion;\n            }\n            const dimension = this.bitMatrix.getHeight();\n            const provisionalVersion = Math.floor((dimension - 17) / 4);\n            if (provisionalVersion <= 6) {\n                return Version$1.getVersionForNumber(provisionalVersion);\n            }\n            // Read top-right version info: 3 wide by 6 tall\n            let versionBits = 0;\n            const ijMin = dimension - 11;\n            for (let j = 5; j >= 0; j--) {\n                for (let i = dimension - 9; i >= ijMin; i--) {\n                    versionBits = this.copyBit(i, j, versionBits);\n                }\n            }\n            let theParsedVersion = Version$1.decodeVersionInformation(versionBits);\n            if (theParsedVersion !== null && theParsedVersion.getDimensionForVersion() === dimension) {\n                this.parsedVersion = theParsedVersion;\n                return theParsedVersion;\n            }\n            // Hmm, failed. Try bottom left: 6 wide by 3 tall\n            versionBits = 0;\n            for (let i = 5; i >= 0; i--) {\n                for (let j = dimension - 9; j >= ijMin; j--) {\n                    versionBits = this.copyBit(i, j, versionBits);\n                }\n            }\n            theParsedVersion = Version$1.decodeVersionInformation(versionBits);\n            if (theParsedVersion !== null && theParsedVersion.getDimensionForVersion() === dimension) {\n                this.parsedVersion = theParsedVersion;\n                return theParsedVersion;\n            }\n            throw new FormatException();\n        }\n        copyBit(i /*int*/, j /*int*/, versionBits /*int*/) {\n            const bit = this.isMirror ? this.bitMatrix.get(j, i) : this.bitMatrix.get(i, j);\n            return bit ? (versionBits << 1) | 0x1 : versionBits << 1;\n        }\n        /**\n         * <p>Reads the bits in the {@link BitMatrix} representing the finder pattern in the\n         * correct order in order to reconstruct the codewords bytes contained within the\n         * QR Code.</p>\n         *\n         * @return bytes encoded within the QR Code\n         * @throws FormatException if the exact number of bytes expected is not read\n         */\n        readCodewords() {\n            const formatInfo = this.readFormatInformation();\n            const version = this.readVersion();\n            // Get the data mask for the format used in this QR Code. This will exclude\n            // some bits from reading as we wind through the bit matrix.\n            const dataMask = DataMask.values.get(formatInfo.getDataMask());\n            const dimension = this.bitMatrix.getHeight();\n            dataMask.unmaskBitMatrix(this.bitMatrix, dimension);\n            const functionPattern = version.buildFunctionPattern();\n            let readingUp = true;\n            const result = new Uint8Array(version.getTotalCodewords());\n            let resultOffset = 0;\n            let currentByte = 0;\n            let bitsRead = 0;\n            // Read columns in pairs, from right to left\n            for (let j = dimension - 1; j > 0; j -= 2) {\n                if (j === 6) {\n                    // Skip whole column with vertical alignment pattern\n                    // saves time and makes the other code proceed more cleanly\n                    j--;\n                }\n                // Read alternatingly from bottom to top then top to bottom\n                for (let count = 0; count < dimension; count++) {\n                    const i = readingUp ? dimension - 1 - count : count;\n                    for (let col = 0; col < 2; col++) {\n                        // Ignore bits covered by the function pattern\n                        if (!functionPattern.get(j - col, i)) {\n                            // Read a bit\n                            bitsRead++;\n                            currentByte <<= 1;\n                            if (this.bitMatrix.get(j - col, i)) {\n                                currentByte |= 1;\n                            }\n                            // If we've made a whole byte, save it off\n                            if (bitsRead === 8) {\n                                result[resultOffset++] = /*(byte) */ currentByte;\n                                bitsRead = 0;\n                                currentByte = 0;\n                            }\n                        }\n                    }\n                }\n                readingUp = !readingUp; // readingUp ^= true; // readingUp = !readingUp; // switch directions\n            }\n            if (resultOffset !== version.getTotalCodewords()) {\n                throw new FormatException();\n            }\n            return result;\n        }\n        /**\n         * Revert the mask removal done while reading the code words. The bit matrix should revert to its original state.\n         */\n        remask() {\n            if (this.parsedFormatInfo === null) {\n                return; // We have no format information, and have no data mask\n            }\n            const dataMask = DataMask.values[this.parsedFormatInfo.getDataMask()];\n            const dimension = this.bitMatrix.getHeight();\n            dataMask.unmaskBitMatrix(this.bitMatrix, dimension);\n        }\n        /**\n         * Prepare the parser for a mirrored operation.\n         * This flag has effect only on the {@link #readFormatInformation()} and the\n         * {@link #readVersion()}. Before proceeding with {@link #readCodewords()} the\n         * {@link #mirror()} method should be called.\n         *\n         * @param mirror Whether to read version and format information mirrored.\n         */\n        setMirror(isMirror) {\n            this.parsedVersion = null;\n            this.parsedFormatInfo = null;\n            this.isMirror = isMirror;\n        }\n        /** Mirror the bit matrix in order to attempt a second reading. */\n        mirror() {\n            const bitMatrix = this.bitMatrix;\n            for (let x = 0, width = bitMatrix.getWidth(); x < width; x++) {\n                for (let y = x + 1, height = bitMatrix.getHeight(); y < height; y++) {\n                    if (bitMatrix.get(x, y) !== bitMatrix.get(y, x)) {\n                        bitMatrix.flip(y, x);\n                        bitMatrix.flip(x, y);\n                    }\n                }\n            }\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates a block of data within a QR Code. QR Codes may split their data into\n     * multiple blocks, each of which is a unit of data and error-correction codewords. Each\n     * is represented by an instance of this class.</p>\n     *\n     * @author Sean Owen\n     */\n    class DataBlock$1 {\n        constructor(numDataCodewords /*int*/, codewords) {\n            this.numDataCodewords = numDataCodewords;\n            this.codewords = codewords;\n        }\n        /**\n         * <p>When QR Codes use multiple data blocks, they are actually interleaved.\n         * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This\n         * method will separate the data into original blocks.</p>\n         *\n         * @param rawCodewords bytes as read directly from the QR Code\n         * @param version version of the QR Code\n         * @param ecLevel error-correction level of the QR Code\n         * @return DataBlocks containing original bytes, \"de-interleaved\" from representation in the\n         *         QR Code\n         */\n        static getDataBlocks(rawCodewords, version, ecLevel) {\n            if (rawCodewords.length !== version.getTotalCodewords()) {\n                throw new IllegalArgumentException();\n            }\n            // Figure out the number and size of data blocks used by this version and\n            // error correction level\n            const ecBlocks = version.getECBlocksForLevel(ecLevel);\n            // First count the total number of data blocks\n            let totalBlocks = 0;\n            const ecBlockArray = ecBlocks.getECBlocks();\n            for (const ecBlock of ecBlockArray) {\n                totalBlocks += ecBlock.getCount();\n            }\n            // Now establish DataBlocks of the appropriate size and number of data codewords\n            const result = new Array(totalBlocks);\n            let numResultBlocks = 0;\n            for (const ecBlock of ecBlockArray) {\n                for (let i = 0; i < ecBlock.getCount(); i++) {\n                    const numDataCodewords = ecBlock.getDataCodewords();\n                    const numBlockCodewords = ecBlocks.getECCodewordsPerBlock() + numDataCodewords;\n                    result[numResultBlocks++] = new DataBlock$1(numDataCodewords, new Uint8Array(numBlockCodewords));\n                }\n            }\n            // All blocks have the same amount of data, except that the last n\n            // (where n may be 0) have 1 more byte. Figure out where these start.\n            const shorterBlocksTotalCodewords = result[0].codewords.length;\n            let longerBlocksStartAt = result.length - 1;\n            // TYPESCRIPTPORT: check length is correct here\n            while (longerBlocksStartAt >= 0) {\n                const numCodewords = result[longerBlocksStartAt].codewords.length;\n                if (numCodewords === shorterBlocksTotalCodewords) {\n                    break;\n                }\n                longerBlocksStartAt--;\n            }\n            longerBlocksStartAt++;\n            const shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.getECCodewordsPerBlock();\n            // The last elements of result may be 1 element longer\n            // first fill out as many elements as all of them have\n            let rawCodewordsOffset = 0;\n            for (let i = 0; i < shorterBlocksNumDataCodewords; i++) {\n                for (let j = 0; j < numResultBlocks; j++) {\n                    result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];\n                }\n            }\n            // Fill out the last data block in the longer ones\n            for (let j = longerBlocksStartAt; j < numResultBlocks; j++) {\n                result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++];\n            }\n            // Now add in error correction blocks\n            const max = result[0].codewords.length;\n            for (let i = shorterBlocksNumDataCodewords; i < max; i++) {\n                for (let j = 0; j < numResultBlocks; j++) {\n                    const iOffset = j < longerBlocksStartAt ? i : i + 1;\n                    result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];\n                }\n            }\n            return result;\n        }\n        getNumDataCodewords() {\n            return this.numDataCodewords;\n        }\n        getCodewords() {\n            return this.codewords;\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    var ModeValues;\n    (function (ModeValues) {\n        ModeValues[ModeValues[\"TERMINATOR\"] = 0] = \"TERMINATOR\";\n        ModeValues[ModeValues[\"NUMERIC\"] = 1] = \"NUMERIC\";\n        ModeValues[ModeValues[\"ALPHANUMERIC\"] = 2] = \"ALPHANUMERIC\";\n        ModeValues[ModeValues[\"STRUCTURED_APPEND\"] = 3] = \"STRUCTURED_APPEND\";\n        ModeValues[ModeValues[\"BYTE\"] = 4] = \"BYTE\";\n        ModeValues[ModeValues[\"ECI\"] = 5] = \"ECI\";\n        ModeValues[ModeValues[\"KANJI\"] = 6] = \"KANJI\";\n        ModeValues[ModeValues[\"FNC1_FIRST_POSITION\"] = 7] = \"FNC1_FIRST_POSITION\";\n        ModeValues[ModeValues[\"FNC1_SECOND_POSITION\"] = 8] = \"FNC1_SECOND_POSITION\";\n        /** See GBT 18284-2000; \"Hanzi\" is a transliteration of this mode name. */\n        ModeValues[ModeValues[\"HANZI\"] = 9] = \"HANZI\";\n    })(ModeValues || (ModeValues = {}));\n    /**\n     * <p>See ISO 18004:2006, 6.4.1, Tables 2 and 3. This enum encapsulates the various modes in which\n     * data can be encoded to bits in the QR code standard.</p>\n     *\n     * @author Sean Owen\n     */\n    class Mode$1 {\n        constructor(value, stringValue, characterCountBitsForVersions, bits /*int*/) {\n            this.value = value;\n            this.stringValue = stringValue;\n            this.characterCountBitsForVersions = characterCountBitsForVersions;\n            this.bits = bits;\n            Mode$1.FOR_BITS.set(bits, this);\n            Mode$1.FOR_VALUE.set(value, this);\n        }\n        /**\n         * @param bits four bits encoding a QR Code data mode\n         * @return Mode encoded by these bits\n         * @throws IllegalArgumentException if bits do not correspond to a known mode\n         */\n        static forBits(bits /*int*/) {\n            const mode = Mode$1.FOR_BITS.get(bits);\n            if (undefined === mode) {\n                throw new IllegalArgumentException();\n            }\n            return mode;\n        }\n        /**\n         * @param version version in question\n         * @return number of bits used, in this QR Code symbol {@link Version}, to encode the\n         *         count of characters that will follow encoded in this Mode\n         */\n        getCharacterCountBits(version) {\n            const versionNumber = version.getVersionNumber();\n            let offset;\n            if (versionNumber <= 9) {\n                offset = 0;\n            }\n            else if (versionNumber <= 26) {\n                offset = 1;\n            }\n            else {\n                offset = 2;\n            }\n            return this.characterCountBitsForVersions[offset];\n        }\n        getValue() {\n            return this.value;\n        }\n        getBits() {\n            return this.bits;\n        }\n        equals(o) {\n            if (!(o instanceof Mode$1)) {\n                return false;\n            }\n            const other = o;\n            return this.value === other.value;\n        }\n        toString() {\n            return this.stringValue;\n        }\n    }\n    Mode$1.FOR_BITS = new Map();\n    Mode$1.FOR_VALUE = new Map();\n    Mode$1.TERMINATOR = new Mode$1(ModeValues.TERMINATOR, 'TERMINATOR', Int32Array.from([0, 0, 0]), 0x00); // Not really a mode...\n    Mode$1.NUMERIC = new Mode$1(ModeValues.NUMERIC, 'NUMERIC', Int32Array.from([10, 12, 14]), 0x01);\n    Mode$1.ALPHANUMERIC = new Mode$1(ModeValues.ALPHANUMERIC, 'ALPHANUMERIC', Int32Array.from([9, 11, 13]), 0x02);\n    Mode$1.STRUCTURED_APPEND = new Mode$1(ModeValues.STRUCTURED_APPEND, 'STRUCTURED_APPEND', Int32Array.from([0, 0, 0]), 0x03); // Not supported\n    Mode$1.BYTE = new Mode$1(ModeValues.BYTE, 'BYTE', Int32Array.from([8, 16, 16]), 0x04);\n    Mode$1.ECI = new Mode$1(ModeValues.ECI, 'ECI', Int32Array.from([0, 0, 0]), 0x07); // character counts don't apply\n    Mode$1.KANJI = new Mode$1(ModeValues.KANJI, 'KANJI', Int32Array.from([8, 10, 12]), 0x08);\n    Mode$1.FNC1_FIRST_POSITION = new Mode$1(ModeValues.FNC1_FIRST_POSITION, 'FNC1_FIRST_POSITION', Int32Array.from([0, 0, 0]), 0x05);\n    Mode$1.FNC1_SECOND_POSITION = new Mode$1(ModeValues.FNC1_SECOND_POSITION, 'FNC1_SECOND_POSITION', Int32Array.from([0, 0, 0]), 0x09);\n    /** See GBT 18284-2000; \"Hanzi\" is a transliteration of this mode name. */\n    Mode$1.HANZI = new Mode$1(ModeValues.HANZI, 'HANZI', Int32Array.from([8, 10, 12]), 0x0D);\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*import java.io.UnsupportedEncodingException;*/\n    /*import java.util.ArrayList;*/\n    /*import java.util.Collection;*/\n    /*import java.util.List;*/\n    /*import java.util.Map;*/\n    /**\n     * <p>QR Codes can encode text as bits in one of several modes, and can use multiple modes\n     * in one QR Code. This class decodes the bits back into text.</p>\n     *\n     * <p>See ISO 18004:2006, 6.4.3 - 6.4.7</p>\n     *\n     * @author Sean Owen\n     */\n    class DecodedBitStreamParser$1 {\n        static decode(bytes, version, ecLevel, hints) {\n            const bits = new BitSource(bytes);\n            let result = new StringBuilder();\n            const byteSegments = new Array(); // 1\n            // TYPESCRIPTPORT: I do not use constructor with size 1 as in original Java means capacity and the array length is checked below\n            let symbolSequence = -1;\n            let parityData = -1;\n            try {\n                let currentCharacterSetECI = null;\n                let fc1InEffect = false;\n                let mode;\n                do {\n                    // While still another segment to read...\n                    if (bits.available() < 4) {\n                        // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here\n                        mode = Mode$1.TERMINATOR;\n                    }\n                    else {\n                        const modeBits = bits.readBits(4);\n                        mode = Mode$1.forBits(modeBits); // mode is encoded by 4 bits\n                    }\n                    switch (mode) {\n                        case Mode$1.TERMINATOR:\n                            break;\n                        case Mode$1.FNC1_FIRST_POSITION:\n                        case Mode$1.FNC1_SECOND_POSITION:\n                            // We do little with FNC1 except alter the parsed result a bit according to the spec\n                            fc1InEffect = true;\n                            break;\n                        case Mode$1.STRUCTURED_APPEND:\n                            if (bits.available() < 16) {\n                                throw new FormatException();\n                            }\n                            // sequence number and parity is added later to the result metadata\n                            // Read next 8 bits (symbol sequence #) and 8 bits (data: parity), then continue\n                            symbolSequence = bits.readBits(8);\n                            parityData = bits.readBits(8);\n                            break;\n                        case Mode$1.ECI:\n                            // Count doesn't apply to ECI\n                            const value = DecodedBitStreamParser$1.parseECIValue(bits);\n                            currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value);\n                            if (currentCharacterSetECI === null) {\n                                throw new FormatException();\n                            }\n                            break;\n                        case Mode$1.HANZI:\n                            // First handle Hanzi mode which does not start with character count\n                            // Chinese mode contains a sub set indicator right after mode indicator\n                            const subset = bits.readBits(4);\n                            const countHanzi = bits.readBits(mode.getCharacterCountBits(version));\n                            if (subset === DecodedBitStreamParser$1.GB2312_SUBSET) {\n                                DecodedBitStreamParser$1.decodeHanziSegment(bits, result, countHanzi);\n                            }\n                            break;\n                        default:\n                            // \"Normal\" QR code modes:\n                            // How many characters will follow, encoded in this mode?\n                            const count = bits.readBits(mode.getCharacterCountBits(version));\n                            switch (mode) {\n                                case Mode$1.NUMERIC:\n                                    DecodedBitStreamParser$1.decodeNumericSegment(bits, result, count);\n                                    break;\n                                case Mode$1.ALPHANUMERIC:\n                                    DecodedBitStreamParser$1.decodeAlphanumericSegment(bits, result, count, fc1InEffect);\n                                    break;\n                                case Mode$1.BYTE:\n                                    DecodedBitStreamParser$1.decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints);\n                                    break;\n                                case Mode$1.KANJI:\n                                    DecodedBitStreamParser$1.decodeKanjiSegment(bits, result, count);\n                                    break;\n                                default:\n                                    throw new FormatException();\n                            }\n                            break;\n                    }\n                } while (mode !== Mode$1.TERMINATOR);\n            }\n            catch (iae /*: IllegalArgumentException*/) {\n                // from readBits() calls\n                throw new FormatException();\n            }\n            return new DecoderResult(bytes, result.toString(), byteSegments.length === 0 ? null : byteSegments, ecLevel === null ? null : ecLevel.toString(), symbolSequence, parityData);\n        }\n        /**\n         * See specification GBT 18284-2000\n         */\n        static decodeHanziSegment(bits, result, count /*int*/) {\n            // Don't crash trying to read more bits than we have available.\n            if (count * 13 > bits.available()) {\n                throw new FormatException();\n            }\n            // Each character will require 2 bytes. Read the characters as 2-byte pairs\n            // and decode as GB2312 afterwards\n            const buffer = new Uint8Array(2 * count);\n            let offset = 0;\n            while (count > 0) {\n                // Each 13 bits encodes a 2-byte character\n                const twoBytes = bits.readBits(13);\n                let assembledTwoBytes = (((twoBytes / 0x060) << 8) & 0xFFFFFFFF) | (twoBytes % 0x060);\n                if (assembledTwoBytes < 0x003BF) {\n                    // In the 0xA1A1 to 0xAAFE range\n                    assembledTwoBytes += 0x0A1A1;\n                }\n                else {\n                    // In the 0xB0A1 to 0xFAFE range\n                    assembledTwoBytes += 0x0A6A1;\n                }\n                buffer[offset] = /*(byte) */ ((assembledTwoBytes >> 8) & 0xFF);\n                buffer[offset + 1] = /*(byte) */ (assembledTwoBytes & 0xFF);\n                offset += 2;\n                count--;\n            }\n            try {\n                result.append(StringEncoding.decode(buffer, StringUtils.GB2312));\n                // TYPESCRIPTPORT: TODO: implement GB2312 decode. StringView from MDN could be a starting point\n            }\n            catch (ignored /*: UnsupportedEncodingException*/) {\n                throw new FormatException(ignored);\n            }\n        }\n        static decodeKanjiSegment(bits, result, count /*int*/) {\n            // Don't crash trying to read more bits than we have available.\n            if (count * 13 > bits.available()) {\n                throw new FormatException();\n            }\n            // Each character will require 2 bytes. Read the characters as 2-byte pairs\n            // and decode as Shift_JIS afterwards\n            const buffer = new Uint8Array(2 * count);\n            let offset = 0;\n            while (count > 0) {\n                // Each 13 bits encodes a 2-byte character\n                const twoBytes = bits.readBits(13);\n                let assembledTwoBytes = (((twoBytes / 0x0C0) << 8) & 0xFFFFFFFF) | (twoBytes % 0x0C0);\n                if (assembledTwoBytes < 0x01F00) {\n                    // In the 0x8140 to 0x9FFC range\n                    assembledTwoBytes += 0x08140;\n                }\n                else {\n                    // In the 0xE040 to 0xEBBF range\n                    assembledTwoBytes += 0x0C140;\n                }\n                buffer[offset] = /*(byte) */ (assembledTwoBytes >> 8);\n                buffer[offset + 1] = /*(byte) */ assembledTwoBytes;\n                offset += 2;\n                count--;\n            }\n            // Shift_JIS may not be supported in some environments:\n            try {\n                result.append(StringEncoding.decode(buffer, StringUtils.SHIFT_JIS));\n                // TYPESCRIPTPORT: TODO: implement SHIFT_JIS decode. StringView from MDN could be a starting point\n            }\n            catch (ignored /*: UnsupportedEncodingException*/) {\n                throw new FormatException(ignored);\n            }\n        }\n        static decodeByteSegment(bits, result, count /*int*/, currentCharacterSetECI, byteSegments, hints) {\n            // Don't crash trying to read more bits than we have available.\n            if (8 * count > bits.available()) {\n                throw new FormatException();\n            }\n            const readBytes = new Uint8Array(count);\n            for (let i = 0; i < count; i++) {\n                readBytes[i] = /*(byte) */ bits.readBits(8);\n            }\n            let encoding;\n            if (currentCharacterSetECI === null) {\n                // The spec isn't clear on this mode; see\n                // section 6.4.5: t does not say which encoding to assuming\n                // upon decoding. I have seen ISO-8859-1 used as well as\n                // Shift_JIS -- without anything like an ECI designator to\n                // give a hint.\n                encoding = StringUtils.guessEncoding(readBytes, hints);\n            }\n            else {\n                encoding = currentCharacterSetECI.getName();\n            }\n            try {\n                result.append(StringEncoding.decode(readBytes, encoding));\n            }\n            catch (ignored /*: UnsupportedEncodingException*/) {\n                throw new FormatException(ignored);\n            }\n            byteSegments.push(readBytes);\n        }\n        static toAlphaNumericChar(value /*int*/) {\n            if (value >= DecodedBitStreamParser$1.ALPHANUMERIC_CHARS.length) {\n                throw new FormatException();\n            }\n            return DecodedBitStreamParser$1.ALPHANUMERIC_CHARS[value];\n        }\n        static decodeAlphanumericSegment(bits, result, count /*int*/, fc1InEffect) {\n            // Read two characters at a time\n            const start = result.length();\n            while (count > 1) {\n                if (bits.available() < 11) {\n                    throw new FormatException();\n                }\n                const nextTwoCharsBits = bits.readBits(11);\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(Math.floor(nextTwoCharsBits / 45)));\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(nextTwoCharsBits % 45));\n                count -= 2;\n            }\n            if (count === 1) {\n                // special case: one character left\n                if (bits.available() < 6) {\n                    throw new FormatException();\n                }\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(bits.readBits(6)));\n            }\n            // See section 6.4.8.1, 6.4.8.2\n            if (fc1InEffect) {\n                // We need to massage the result a bit if in an FNC1 mode:\n                for (let i = start; i < result.length(); i++) {\n                    if (result.charAt(i) === '%') {\n                        if (i < result.length() - 1 && result.charAt(i + 1) === '%') {\n                            // %% is rendered as %\n                            result.deleteCharAt(i + 1);\n                        }\n                        else {\n                            // In alpha mode, % should be converted to FNC1 separator 0x1D\n                            result.setCharAt(i, String.fromCharCode(0x1D));\n                        }\n                    }\n                }\n            }\n        }\n        static decodeNumericSegment(bits, result, count /*int*/) {\n            // Read three digits at a time\n            while (count >= 3) {\n                // Each 10 bits encodes three digits\n                if (bits.available() < 10) {\n                    throw new FormatException();\n                }\n                const threeDigitsBits = bits.readBits(10);\n                if (threeDigitsBits >= 1000) {\n                    throw new FormatException();\n                }\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(Math.floor(threeDigitsBits / 100)));\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(Math.floor(threeDigitsBits / 10) % 10));\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(threeDigitsBits % 10));\n                count -= 3;\n            }\n            if (count === 2) {\n                // Two digits left over to read, encoded in 7 bits\n                if (bits.available() < 7) {\n                    throw new FormatException();\n                }\n                const twoDigitsBits = bits.readBits(7);\n                if (twoDigitsBits >= 100) {\n                    throw new FormatException();\n                }\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(Math.floor(twoDigitsBits / 10)));\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(twoDigitsBits % 10));\n            }\n            else if (count === 1) {\n                // One digit left over to read\n                if (bits.available() < 4) {\n                    throw new FormatException();\n                }\n                const digitBits = bits.readBits(4);\n                if (digitBits >= 10) {\n                    throw new FormatException();\n                }\n                result.append(DecodedBitStreamParser$1.toAlphaNumericChar(digitBits));\n            }\n        }\n        static parseECIValue(bits) {\n            const firstByte = bits.readBits(8);\n            if ((firstByte & 0x80) === 0) {\n                // just one byte\n                return firstByte & 0x7F;\n            }\n            if ((firstByte & 0xC0) === 0x80) {\n                // two bytes\n                const secondByte = bits.readBits(8);\n                return (((firstByte & 0x3F) << 8) & 0xFFFFFFFF) | secondByte;\n            }\n            if ((firstByte & 0xE0) === 0xC0) {\n                // three bytes\n                const secondThirdBytes = bits.readBits(16);\n                return (((firstByte & 0x1F) << 16) & 0xFFFFFFFF) | secondThirdBytes;\n            }\n            throw new FormatException();\n        }\n    }\n    /**\n     * See ISO 18004:2006, 6.4.4 Table 5\n     */\n    DecodedBitStreamParser$1.ALPHANUMERIC_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:';\n    DecodedBitStreamParser$1.GB2312_SUBSET = 1;\n    // function Uint8ArrayToString(a: Uint8Array): string {\n    //     const CHUNK_SZ = 0x8000;\n    //     const c = new StringBuilder();\n    //     for (let i = 0, length = a.length; i < length; i += CHUNK_SZ) {\n    //         c.append(String.fromCharCode.apply(null, a.subarray(i, i + CHUNK_SZ)));\n    //     }\n    //     return c.toString();\n    // }\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * Meta-data container for QR Code decoding. Instances of this class may be used to convey information back to the\n     * decoding caller. Callers are expected to process this.\n     *\n     * @see com.google.zxing.common.DecoderResult#getOther()\n     */\n    class QRCodeDecoderMetaData {\n        constructor(mirrored) {\n            this.mirrored = mirrored;\n        }\n        /**\n         * @return true if the QR Code was mirrored.\n         */\n        isMirrored() {\n            return this.mirrored;\n        }\n        /**\n         * Apply the result points' order correction due to mirroring.\n         *\n         * @param points Array of points to apply mirror correction to.\n         */\n        applyMirroredCorrection(points) {\n            if (!this.mirrored || points === null || points.length < 3) {\n                return;\n            }\n            const bottomLeft = points[0];\n            points[0] = points[2];\n            points[2] = bottomLeft;\n            // No need to 'fix' top-left and alignment pattern.\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*import java.util.Map;*/\n    /**\n     * <p>The main class which implements QR Code decoding -- as opposed to locating and extracting\n     * the QR Code from an image.</p>\n     *\n     * @author Sean Owen\n     */\n    class Decoder$2 {\n        constructor() {\n            this.rsDecoder = new ReedSolomonDecoder(GenericGF.QR_CODE_FIELD_256);\n        }\n        // public decode(image: boolean[][]): DecoderResult /*throws ChecksumException, FormatException*/ {\n        //   return decode(image, null)\n        // }\n        /**\n         * <p>Convenience method that can decode a QR Code represented as a 2D array of booleans.\n         * \"true\" is taken to mean a black module.</p>\n         *\n         * @param image booleans representing white/black QR Code modules\n         * @param hints decoding hints that should be used to influence decoding\n         * @return text and bytes encoded within the QR Code\n         * @throws FormatException if the QR Code cannot be decoded\n         * @throws ChecksumException if error correction fails\n         */\n        decodeBooleanArray(image, hints) {\n            return this.decodeBitMatrix(BitMatrix.parseFromBooleanArray(image), hints);\n        }\n        // public decodeBitMatrix(bits: BitMatrix): DecoderResult /*throws ChecksumException, FormatException*/ {\n        //   return decode(bits, null)\n        // }\n        /**\n         * <p>Decodes a QR Code represented as a {@link BitMatrix}. A 1 or \"true\" is taken to mean a black module.</p>\n         *\n         * @param bits booleans representing white/black QR Code modules\n         * @param hints decoding hints that should be used to influence decoding\n         * @return text and bytes encoded within the QR Code\n         * @throws FormatException if the QR Code cannot be decoded\n         * @throws ChecksumException if error correction fails\n         */\n        decodeBitMatrix(bits, hints) {\n            // Construct a parser and read version, error-correction level\n            const parser = new BitMatrixParser$1(bits);\n            let ex = null;\n            try {\n                return this.decodeBitMatrixParser(parser, hints);\n            }\n            catch (e /*: FormatException, ChecksumException*/) {\n                ex = e;\n            }\n            try {\n                // Revert the bit matrix\n                parser.remask();\n                // Will be attempting a mirrored reading of the version and format info.\n                parser.setMirror(true);\n                // Preemptively read the version.\n                parser.readVersion();\n                // Preemptively read the format information.\n                parser.readFormatInformation();\n                /*\n                 * Since we're here, this means we have successfully detected some kind\n                 * of version and format information when mirrored. This is a good sign,\n                 * that the QR code may be mirrored, and we should try once more with a\n                 * mirrored content.\n                 */\n                // Prepare for a mirrored reading.\n                parser.mirror();\n                const result = this.decodeBitMatrixParser(parser, hints);\n                // Success! Notify the caller that the code was mirrored.\n                result.setOther(new QRCodeDecoderMetaData(true));\n                return result;\n            }\n            catch (e /*FormatException | ChecksumException*/) {\n                // Throw the exception from the original reading\n                if (ex !== null) {\n                    throw ex;\n                }\n                throw e;\n            }\n        }\n        decodeBitMatrixParser(parser, hints) {\n            const version = parser.readVersion();\n            const ecLevel = parser.readFormatInformation().getErrorCorrectionLevel();\n            // Read codewords\n            const codewords = parser.readCodewords();\n            // Separate into data blocks\n            const dataBlocks = DataBlock$1.getDataBlocks(codewords, version, ecLevel);\n            // Count total number of data bytes\n            let totalBytes = 0;\n            for (const dataBlock of dataBlocks) {\n                totalBytes += dataBlock.getNumDataCodewords();\n            }\n            const resultBytes = new Uint8Array(totalBytes);\n            let resultOffset = 0;\n            // Error-correct and copy data blocks together into a stream of bytes\n            for (const dataBlock of dataBlocks) {\n                const codewordBytes = dataBlock.getCodewords();\n                const numDataCodewords = dataBlock.getNumDataCodewords();\n                this.correctErrors(codewordBytes, numDataCodewords);\n                for (let i = 0; i < numDataCodewords; i++) {\n                    resultBytes[resultOffset++] = codewordBytes[i];\n                }\n            }\n            // Decode the contents of that stream of bytes\n            return DecodedBitStreamParser$1.decode(resultBytes, version, ecLevel, hints);\n        }\n        /**\n         * <p>Given data and error-correction codewords received, possibly corrupted by errors, attempts to\n         * correct the errors in-place using Reed-Solomon error correction.</p>\n         *\n         * @param codewordBytes data and error correction codewords\n         * @param numDataCodewords number of codewords that are data bytes\n         * @throws ChecksumException if error correction fails\n         */\n        correctErrors(codewordBytes, numDataCodewords /*int*/) {\n            // const numCodewords = codewordBytes.length;\n            // First read into an array of ints\n            const codewordsInts = new Int32Array(codewordBytes);\n            // TYPESCRIPTPORT: not realy necessary to transform to ints? could redesign everything to work with unsigned bytes?\n            // const codewordsInts = new Int32Array(numCodewords)\n            // for (let i = 0; i < numCodewords; i++) {\n            //   codewordsInts[i] = codewordBytes[i] & 0xFF\n            // }\n            try {\n                this.rsDecoder.decode(codewordsInts, codewordBytes.length - numDataCodewords);\n            }\n            catch (ignored /*: ReedSolomonException*/) {\n                throw new ChecksumException();\n            }\n            // Copy back into array of bytes -- only need to worry about the bytes that were data\n            // We don't care about errors in the error-correction codewords\n            for (let i = 0; i < numDataCodewords; i++) {\n                codewordBytes[i] = /*(byte) */ codewordsInts[i];\n            }\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates an alignment pattern, which are the smaller square patterns found in\n     * all but the simplest QR Codes.</p>\n     *\n     * @author Sean Owen\n     */\n    class AlignmentPattern extends ResultPoint {\n        constructor(posX /*float*/, posY /*float*/, estimatedModuleSize /*float*/) {\n            super(posX, posY);\n            this.estimatedModuleSize = estimatedModuleSize;\n        }\n        /**\n         * <p>Determines if this alignment pattern \"about equals\" an alignment pattern at the stated\n         * position and size -- meaning, it is at nearly the same center with nearly the same size.</p>\n         */\n        aboutEquals(moduleSize /*float*/, i /*float*/, j /*float*/) {\n            if (Math.abs(i - this.getY()) <= moduleSize && Math.abs(j - this.getX()) <= moduleSize) {\n                const moduleSizeDiff = Math.abs(moduleSize - this.estimatedModuleSize);\n                return moduleSizeDiff <= 1.0 || moduleSizeDiff <= this.estimatedModuleSize;\n            }\n            return false;\n        }\n        /**\n         * Combines this object's current estimate of a finder pattern position and module size\n         * with a new estimate. It returns a new {@code FinderPattern} containing an average of the two.\n         */\n        combineEstimate(i /*float*/, j /*float*/, newModuleSize /*float*/) {\n            const combinedX = (this.getX() + j) / 2.0;\n            const combinedY = (this.getY() + i) / 2.0;\n            const combinedModuleSize = (this.estimatedModuleSize + newModuleSize) / 2.0;\n            return new AlignmentPattern(combinedX, combinedY, combinedModuleSize);\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*import java.util.ArrayList;*/\n    /*import java.util.List;*/\n    /**\n     * <p>This class attempts to find alignment patterns in a QR Code. Alignment patterns look like finder\n     * patterns but are smaller and appear at regular intervals throughout the image.</p>\n     *\n     * <p>At the moment this only looks for the bottom-right alignment pattern.</p>\n     *\n     * <p>This is mostly a simplified copy of {@link FinderPatternFinder}. It is copied,\n     * pasted and stripped down here for maximum performance but does unfortunately duplicate\n     * some code.</p>\n     *\n     * <p>This class is thread-safe but not reentrant. Each thread must allocate its own object.</p>\n     *\n     * @author Sean Owen\n     */\n    class AlignmentPatternFinder {\n        /**\n         * <p>Creates a finder that will look in a portion of the whole image.</p>\n         *\n         * @param image image to search\n         * @param startX left column from which to start searching\n         * @param startY top row from which to start searching\n         * @param width width of region to search\n         * @param height height of region to search\n         * @param moduleSize estimated module size so far\n         */\n        constructor(image, startX /*int*/, startY /*int*/, width /*int*/, height /*int*/, moduleSize /*float*/, resultPointCallback) {\n            this.image = image;\n            this.startX = startX;\n            this.startY = startY;\n            this.width = width;\n            this.height = height;\n            this.moduleSize = moduleSize;\n            this.resultPointCallback = resultPointCallback;\n            this.possibleCenters = []; // new Array<any>(5))\n            // TYPESCRIPTPORT: array initialization without size as the length is checked below\n            this.crossCheckStateCount = new Int32Array(3);\n        }\n        /**\n         * <p>This method attempts to find the bottom-right alignment pattern in the image. It is a bit messy since\n         * it's pretty performance-critical and so is written to be fast foremost.</p>\n         *\n         * @return {@link AlignmentPattern} if found\n         * @throws NotFoundException if not found\n         */\n        find() {\n            const startX = this.startX;\n            const height = this.height;\n            const width = this.width;\n            const maxJ = startX + width;\n            const middleI = this.startY + (height / 2);\n            // We are looking for black/white/black modules in 1:1:1 ratio\n            // this tracks the number of black/white/black modules seen so far\n            const stateCount = new Int32Array(3);\n            const image = this.image;\n            for (let iGen = 0; iGen < height; iGen++) {\n                // Search from middle outwards\n                const i = middleI + ((iGen & 0x01) === 0 ? Math.floor((iGen + 1) / 2) : -Math.floor((iGen + 1) / 2));\n                stateCount[0] = 0;\n                stateCount[1] = 0;\n                stateCount[2] = 0;\n                let j = startX;\n                // Burn off leading white pixels before anything else; if we start in the middle of\n                // a white run, it doesn't make sense to count its length, since we don't know if the\n                // white run continued to the left of the start point\n                while (j < maxJ && !image.get(j, i)) {\n                    j++;\n                }\n                let currentState = 0;\n                while (j < maxJ) {\n                    if (image.get(j, i)) {\n                        // Black pixel\n                        if (currentState === 1) { // Counting black pixels\n                            stateCount[1]++;\n                        }\n                        else { // Counting white pixels\n                            if (currentState === 2) { // A winner?\n                                if (this.foundPatternCross(stateCount)) { // Yes\n                                    const confirmed = this.handlePossibleCenter(stateCount, i, j);\n                                    if (confirmed !== null) {\n                                        return confirmed;\n                                    }\n                                }\n                                stateCount[0] = stateCount[2];\n                                stateCount[1] = 1;\n                                stateCount[2] = 0;\n                                currentState = 1;\n                            }\n                            else {\n                                stateCount[++currentState]++;\n                            }\n                        }\n                    }\n                    else { // White pixel\n                        if (currentState === 1) { // Counting black pixels\n                            currentState++;\n                        }\n                        stateCount[currentState]++;\n                    }\n                    j++;\n                }\n                if (this.foundPatternCross(stateCount)) {\n                    const confirmed = this.handlePossibleCenter(stateCount, i, maxJ);\n                    if (confirmed !== null) {\n                        return confirmed;\n                    }\n                }\n            }\n            // Hmm, nothing we saw was observed and confirmed twice. If we had\n            // any guess at all, return it.\n            if (this.possibleCenters.length !== 0) {\n                return this.possibleCenters[0];\n            }\n            throw new NotFoundException();\n        }\n        /**\n         * Given a count of black/white/black pixels just seen and an end position,\n         * figures the location of the center of this black/white/black run.\n         */\n        static centerFromEnd(stateCount, end /*int*/) {\n            return (end - stateCount[2]) - stateCount[1] / 2.0;\n        }\n        /**\n         * @param stateCount count of black/white/black pixels just read\n         * @return true iff the proportions of the counts is close enough to the 1/1/1 ratios\n         *         used by alignment patterns to be considered a match\n         */\n        foundPatternCross(stateCount) {\n            const moduleSize = this.moduleSize;\n            const maxVariance = moduleSize / 2.0;\n            for (let i = 0; i < 3; i++) {\n                if (Math.abs(moduleSize - stateCount[i]) >= maxVariance) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        /**\n         * <p>After a horizontal scan finds a potential alignment pattern, this method\n         * \"cross-checks\" by scanning down vertically through the center of the possible\n         * alignment pattern to see if the same proportion is detected.</p>\n         *\n         * @param startI row where an alignment pattern was detected\n         * @param centerJ center of the section that appears to cross an alignment pattern\n         * @param maxCount maximum reasonable number of modules that should be\n         * observed in any reading state, based on the results of the horizontal scan\n         * @return vertical center of alignment pattern, or {@link Float#NaN} if not found\n         */\n        crossCheckVertical(startI /*int*/, centerJ /*int*/, maxCount /*int*/, originalStateCountTotal /*int*/) {\n            const image = this.image;\n            const maxI = image.getHeight();\n            const stateCount = this.crossCheckStateCount;\n            stateCount[0] = 0;\n            stateCount[1] = 0;\n            stateCount[2] = 0;\n            // Start counting up from center\n            let i = startI;\n            while (i >= 0 && image.get(centerJ, i) && stateCount[1] <= maxCount) {\n                stateCount[1]++;\n                i--;\n            }\n            // If already too many modules in this state or ran off the edge:\n            if (i < 0 || stateCount[1] > maxCount) {\n                return NaN;\n            }\n            while (i >= 0 && !image.get(centerJ, i) && stateCount[0] <= maxCount) {\n                stateCount[0]++;\n                i--;\n            }\n            if (stateCount[0] > maxCount) {\n                return NaN;\n            }\n            // Now also count down from center\n            i = startI + 1;\n            while (i < maxI && image.get(centerJ, i) && stateCount[1] <= maxCount) {\n                stateCount[1]++;\n                i++;\n            }\n            if (i === maxI || stateCount[1] > maxCount) {\n                return NaN;\n            }\n            while (i < maxI && !image.get(centerJ, i) && stateCount[2] <= maxCount) {\n                stateCount[2]++;\n                i++;\n            }\n            if (stateCount[2] > maxCount) {\n                return NaN;\n            }\n            const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];\n            if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {\n                return NaN;\n            }\n            return this.foundPatternCross(stateCount) ? AlignmentPatternFinder.centerFromEnd(stateCount, i) : NaN;\n        }\n        /**\n         * <p>This is called when a horizontal scan finds a possible alignment pattern. It will\n         * cross check with a vertical scan, and if successful, will see if this pattern had been\n         * found on a previous horizontal scan. If so, we consider it confirmed and conclude we have\n         * found the alignment pattern.</p>\n         *\n         * @param stateCount reading state module counts from horizontal scan\n         * @param i row where alignment pattern may be found\n         * @param j end of possible alignment pattern in row\n         * @return {@link AlignmentPattern} if we have found the same pattern twice, or null if not\n         */\n        handlePossibleCenter(stateCount, i /*int*/, j /*int*/) {\n            const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];\n            const centerJ = AlignmentPatternFinder.centerFromEnd(stateCount, j);\n            const centerI = this.crossCheckVertical(i, /*(int) */ centerJ, 2 * stateCount[1], stateCountTotal);\n            if (!isNaN(centerI)) {\n                const estimatedModuleSize = (stateCount[0] + stateCount[1] + stateCount[2]) / 3.0;\n                for (const center of this.possibleCenters) {\n                    // Look for about the same center and module size:\n                    if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {\n                        return center.combineEstimate(centerI, centerJ, estimatedModuleSize);\n                    }\n                }\n                // Hadn't found this before; save it\n                const point = new AlignmentPattern(centerJ, centerI, estimatedModuleSize);\n                this.possibleCenters.push(point);\n                if (this.resultPointCallback !== null && this.resultPointCallback !== undefined) {\n                    this.resultPointCallback.foundPossibleResultPoint(point);\n                }\n            }\n            return null;\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates a finder pattern, which are the three square patterns found in\n     * the corners of QR Codes. It also encapsulates a count of similar finder patterns,\n     * as a convenience to the finder's bookkeeping.</p>\n     *\n     * @author Sean Owen\n     */\n    class FinderPattern$1 extends ResultPoint {\n        // FinderPattern(posX: number/*float*/, posY: number/*float*/, estimatedModuleSize: number/*float*/) {\n        //   this(posX, posY, estimatedModuleSize, 1)\n        // }\n        constructor(posX /*float*/, posY /*float*/, estimatedModuleSize /*float*/, count /*int*/) {\n            super(posX, posY);\n            this.estimatedModuleSize = estimatedModuleSize;\n            this.count = count;\n            if (undefined === count) {\n                this.count = 1;\n            }\n        }\n        getEstimatedModuleSize() {\n            return this.estimatedModuleSize;\n        }\n        getCount() {\n            return this.count;\n        }\n        /*\n        void incrementCount() {\n          this.count++\n        }\n         */\n        /**\n         * <p>Determines if this finder pattern \"about equals\" a finder pattern at the stated\n         * position and size -- meaning, it is at nearly the same center with nearly the same size.</p>\n         */\n        aboutEquals(moduleSize /*float*/, i /*float*/, j /*float*/) {\n            if (Math.abs(i - this.getY()) <= moduleSize && Math.abs(j - this.getX()) <= moduleSize) {\n                const moduleSizeDiff = Math.abs(moduleSize - this.estimatedModuleSize);\n                return moduleSizeDiff <= 1.0 || moduleSizeDiff <= this.estimatedModuleSize;\n            }\n            return false;\n        }\n        /**\n         * Combines this object's current estimate of a finder pattern position and module size\n         * with a new estimate. It returns a new {@code FinderPattern} containing a weighted average\n         * based on count.\n         */\n        combineEstimate(i /*float*/, j /*float*/, newModuleSize /*float*/) {\n            const combinedCount = this.count + 1;\n            const combinedX = (this.count * this.getX() + j) / combinedCount;\n            const combinedY = (this.count * this.getY() + i) / combinedCount;\n            const combinedModuleSize = (this.count * this.estimatedModuleSize + newModuleSize) / combinedCount;\n            return new FinderPattern$1(combinedX, combinedY, combinedModuleSize, combinedCount);\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>Encapsulates information about finder patterns in an image, including the location of\n     * the three finder patterns, and their estimated module size.</p>\n     *\n     * @author Sean Owen\n     */\n    class FinderPatternInfo {\n        constructor(patternCenters) {\n            this.bottomLeft = patternCenters[0];\n            this.topLeft = patternCenters[1];\n            this.topRight = patternCenters[2];\n        }\n        getBottomLeft() {\n            return this.bottomLeft;\n        }\n        getTopLeft() {\n            return this.topLeft;\n        }\n        getTopRight() {\n            return this.topRight;\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*import java.io.Serializable;*/\n    /*import java.util.ArrayList;*/\n    /*import java.util.Collections;*/\n    /*import java.util.Comparator;*/\n    /*import java.util.List;*/\n    /*import java.util.Map;*/\n    /**\n     * <p>This class attempts to find finder patterns in a QR Code. Finder patterns are the square\n     * markers at three corners of a QR Code.</p>\n     *\n     * <p>This class is thread-safe but not reentrant. Each thread must allocate its own object.\n     *\n     * @author Sean Owen\n     */\n    class FinderPatternFinder {\n        /**\n         * <p>Creates a finder that will search the image for three finder patterns.</p>\n         *\n         * @param image image to search\n         */\n        // public constructor(image: BitMatrix) {\n        //   this(image, null)\n        // }\n        constructor(image, resultPointCallback) {\n            this.image = image;\n            this.resultPointCallback = resultPointCallback;\n            this.possibleCenters = [];\n            this.crossCheckStateCount = new Int32Array(5);\n            this.resultPointCallback = resultPointCallback;\n        }\n        getImage() {\n            return this.image;\n        }\n        getPossibleCenters() {\n            return this.possibleCenters;\n        }\n        find(hints) {\n            const tryHarder = (hints !== null && hints !== undefined) && undefined !== hints.get(DecodeHintType$1.TRY_HARDER);\n            const pureBarcode = (hints !== null && hints !== undefined) && undefined !== hints.get(DecodeHintType$1.PURE_BARCODE);\n            const image = this.image;\n            const maxI = image.getHeight();\n            const maxJ = image.getWidth();\n            // We are looking for black/white/black/white/black modules in\n            // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far\n            // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the\n            // image, and then account for the center being 3 modules in size. This gives the smallest\n            // number of pixels the center could be, so skip this often. When trying harder, look for all\n            // QR versions regardless of how dense they are.\n            let iSkip = Math.floor((3 * maxI) / (4 * FinderPatternFinder.MAX_MODULES));\n            if (iSkip < FinderPatternFinder.MIN_SKIP || tryHarder) {\n                iSkip = FinderPatternFinder.MIN_SKIP;\n            }\n            let done = false;\n            const stateCount = new Int32Array(5);\n            for (let i = iSkip - 1; i < maxI && !done; i += iSkip) {\n                // Get a row of black/white values\n                stateCount[0] = 0;\n                stateCount[1] = 0;\n                stateCount[2] = 0;\n                stateCount[3] = 0;\n                stateCount[4] = 0;\n                let currentState = 0;\n                for (let j = 0; j < maxJ; j++) {\n                    if (image.get(j, i)) {\n                        // Black pixel\n                        if ((currentState & 1) === 1) { // Counting white pixels\n                            currentState++;\n                        }\n                        stateCount[currentState]++;\n                    }\n                    else { // White pixel\n                        if ((currentState & 1) === 0) { // Counting black pixels\n                            if (currentState === 4) { // A winner?\n                                if (FinderPatternFinder.foundPatternCross(stateCount)) { // Yes\n                                    const confirmed = this.handlePossibleCenter(stateCount, i, j, pureBarcode);\n                                    if (confirmed === true) {\n                                        // Start examining every other line. Checking each line turned out to be too\n                                        // expensive and didn't improve performance.\n                                        iSkip = 2;\n                                        if (this.hasSkipped === true) {\n                                            done = this.haveMultiplyConfirmedCenters();\n                                        }\n                                        else {\n                                            const rowSkip = this.findRowSkip();\n                                            if (rowSkip > stateCount[2]) {\n                                                // Skip rows between row of lower confirmed center\n                                                // and top of presumed third confirmed center\n                                                // but back up a bit to get a full chance of detecting\n                                                // it, entire width of center of finder pattern\n                                                // Skip by rowSkip, but back off by stateCount[2] (size of last center\n                                                // of pattern we saw) to be conservative, and also back off by iSkip which\n                                                // is about to be re-added\n                                                i += rowSkip - stateCount[2] - iSkip;\n                                                j = maxJ - 1;\n                                            }\n                                        }\n                                    }\n                                    else {\n                                        stateCount[0] = stateCount[2];\n                                        stateCount[1] = stateCount[3];\n                                        stateCount[2] = stateCount[4];\n                                        stateCount[3] = 1;\n                                        stateCount[4] = 0;\n                                        currentState = 3;\n                                        continue;\n                                    }\n                                    // Clear state to start looking again\n                                    currentState = 0;\n                                    stateCount[0] = 0;\n                                    stateCount[1] = 0;\n                                    stateCount[2] = 0;\n                                    stateCount[3] = 0;\n                                    stateCount[4] = 0;\n                                }\n                                else { // No, shift counts back by two\n                                    stateCount[0] = stateCount[2];\n                                    stateCount[1] = stateCount[3];\n                                    stateCount[2] = stateCount[4];\n                                    stateCount[3] = 1;\n                                    stateCount[4] = 0;\n                                    currentState = 3;\n                                }\n                            }\n                            else {\n                                stateCount[++currentState]++;\n                            }\n                        }\n                        else { // Counting white pixels\n                            stateCount[currentState]++;\n                        }\n                    }\n                }\n                if (FinderPatternFinder.foundPatternCross(stateCount)) {\n                    const confirmed = this.handlePossibleCenter(stateCount, i, maxJ, pureBarcode);\n                    if (confirmed === true) {\n                        iSkip = stateCount[0];\n                        if (this.hasSkipped) {\n                            // Found a third one\n                            done = this.haveMultiplyConfirmedCenters();\n                        }\n                    }\n                }\n            }\n            const patternInfo = this.selectBestPatterns();\n            ResultPoint.orderBestPatterns(patternInfo);\n            return new FinderPatternInfo(patternInfo);\n        }\n        /**\n         * Given a count of black/white/black/white/black pixels just seen and an end position,\n         * figures the location of the center of this run.\n         */\n        static centerFromEnd(stateCount, end /*int*/) {\n            return (end - stateCount[4] - stateCount[3]) - stateCount[2] / 2.0;\n        }\n        /**\n         * @param stateCount count of black/white/black/white/black pixels just read\n         * @return true iff the proportions of the counts is close enough to the 1/1/3/1/1 ratios\n         *         used by finder patterns to be considered a match\n         */\n        static foundPatternCross(stateCount) {\n            let totalModuleSize = 0;\n            for (let i = 0; i < 5; i++) {\n                const count = stateCount[i];\n                if (count === 0) {\n                    return false;\n                }\n                totalModuleSize += count;\n            }\n            if (totalModuleSize < 7) {\n                return false;\n            }\n            const moduleSize = totalModuleSize / 7.0;\n            const maxVariance = moduleSize / 2.0;\n            // Allow less than 50% variance from 1-1-3-1-1 proportions\n            return Math.abs(moduleSize - stateCount[0]) < maxVariance &&\n                Math.abs(moduleSize - stateCount[1]) < maxVariance &&\n                Math.abs(3.0 * moduleSize - stateCount[2]) < 3 * maxVariance &&\n                Math.abs(moduleSize - stateCount[3]) < maxVariance &&\n                Math.abs(moduleSize - stateCount[4]) < maxVariance;\n        }\n        getCrossCheckStateCount() {\n            const crossCheckStateCount = this.crossCheckStateCount;\n            crossCheckStateCount[0] = 0;\n            crossCheckStateCount[1] = 0;\n            crossCheckStateCount[2] = 0;\n            crossCheckStateCount[3] = 0;\n            crossCheckStateCount[4] = 0;\n            return crossCheckStateCount;\n        }\n        /**\n         * After a vertical and horizontal scan finds a potential finder pattern, this method\n         * \"cross-cross-cross-checks\" by scanning down diagonally through the center of the possible\n         * finder pattern to see if the same proportion is detected.\n         *\n         * @param startI row where a finder pattern was detected\n         * @param centerJ center of the section that appears to cross a finder pattern\n         * @param maxCount maximum reasonable number of modules that should be\n         *  observed in any reading state, based on the results of the horizontal scan\n         * @param originalStateCountTotal The original state count total.\n         * @return true if proportions are withing expected limits\n         */\n        crossCheckDiagonal(startI /*int*/, centerJ /*int*/, maxCount /*int*/, originalStateCountTotal /*int*/) {\n            const stateCount = this.getCrossCheckStateCount();\n            // Start counting up, left from center finding black center mass\n            let i = 0;\n            const image = this.image;\n            while (startI >= i && centerJ >= i && image.get(centerJ - i, startI - i)) {\n                stateCount[2]++;\n                i++;\n            }\n            if (startI < i || centerJ < i) {\n                return false;\n            }\n            // Continue up, left finding white space\n            while (startI >= i && centerJ >= i && !image.get(centerJ - i, startI - i) &&\n                stateCount[1] <= maxCount) {\n                stateCount[1]++;\n                i++;\n            }\n            // If already too many modules in this state or ran off the edge:\n            if (startI < i || centerJ < i || stateCount[1] > maxCount) {\n                return false;\n            }\n            // Continue up, left finding black border\n            while (startI >= i && centerJ >= i && image.get(centerJ - i, startI - i) &&\n                stateCount[0] <= maxCount) {\n                stateCount[0]++;\n                i++;\n            }\n            if (stateCount[0] > maxCount) {\n                return false;\n            }\n            const maxI = image.getHeight();\n            const maxJ = image.getWidth();\n            // Now also count down, right from center\n            i = 1;\n            while (startI + i < maxI && centerJ + i < maxJ && image.get(centerJ + i, startI + i)) {\n                stateCount[2]++;\n                i++;\n            }\n            // Ran off the edge?\n            if (startI + i >= maxI || centerJ + i >= maxJ) {\n                return false;\n            }\n            while (startI + i < maxI && centerJ + i < maxJ && !image.get(centerJ + i, startI + i) &&\n                stateCount[3] < maxCount) {\n                stateCount[3]++;\n                i++;\n            }\n            if (startI + i >= maxI || centerJ + i >= maxJ || stateCount[3] >= maxCount) {\n                return false;\n            }\n            while (startI + i < maxI && centerJ + i < maxJ && image.get(centerJ + i, startI + i) &&\n                stateCount[4] < maxCount) {\n                stateCount[4]++;\n                i++;\n            }\n            if (stateCount[4] >= maxCount) {\n                return false;\n            }\n            // If we found a finder-pattern-like section, but its size is more than 100% different than\n            // the original, assume it's a false positive\n            const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4];\n            return Math.abs(stateCountTotal - originalStateCountTotal) < 2 * originalStateCountTotal &&\n                FinderPatternFinder.foundPatternCross(stateCount);\n        }\n        /**\n         * <p>After a horizontal scan finds a potential finder pattern, this method\n         * \"cross-checks\" by scanning down vertically through the center of the possible\n         * finder pattern to see if the same proportion is detected.</p>\n         *\n         * @param startI row where a finder pattern was detected\n         * @param centerJ center of the section that appears to cross a finder pattern\n         * @param maxCount maximum reasonable number of modules that should be\n         * observed in any reading state, based on the results of the horizontal scan\n         * @return vertical center of finder pattern, or {@link Float#NaN} if not found\n         */\n        crossCheckVertical(startI /*int*/, centerJ /*int*/, maxCount /*int*/, originalStateCountTotal /*int*/) {\n            const image = this.image;\n            const maxI = image.getHeight();\n            const stateCount = this.getCrossCheckStateCount();\n            // Start counting up from center\n            let i = startI;\n            while (i >= 0 && image.get(centerJ, i)) {\n                stateCount[2]++;\n                i--;\n            }\n            if (i < 0) {\n                return NaN;\n            }\n            while (i >= 0 && !image.get(centerJ, i) && stateCount[1] <= maxCount) {\n                stateCount[1]++;\n                i--;\n            }\n            // If already too many modules in this state or ran off the edge:\n            if (i < 0 || stateCount[1] > maxCount) {\n                return NaN;\n            }\n            while (i >= 0 && image.get(centerJ, i) && stateCount[0] <= maxCount) {\n                stateCount[0]++;\n                i--;\n            }\n            if (stateCount[0] > maxCount) {\n                return NaN;\n            }\n            // Now also count down from center\n            i = startI + 1;\n            while (i < maxI && image.get(centerJ, i)) {\n                stateCount[2]++;\n                i++;\n            }\n            if (i === maxI) {\n                return NaN;\n            }\n            while (i < maxI && !image.get(centerJ, i) && stateCount[3] < maxCount) {\n                stateCount[3]++;\n                i++;\n            }\n            if (i === maxI || stateCount[3] >= maxCount) {\n                return NaN;\n            }\n            while (i < maxI && image.get(centerJ, i) && stateCount[4] < maxCount) {\n                stateCount[4]++;\n                i++;\n            }\n            if (stateCount[4] >= maxCount) {\n                return NaN;\n            }\n            // If we found a finder-pattern-like section, but its size is more than 40% different than\n            // the original, assume it's a false positive\n            const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +\n                stateCount[4];\n            if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {\n                return NaN;\n            }\n            return FinderPatternFinder.foundPatternCross(stateCount) ? FinderPatternFinder.centerFromEnd(stateCount, i) : NaN;\n        }\n        /**\n         * <p>Like {@link #crossCheckVertical(int, int, int, int)}, and in fact is basically identical,\n         * except it reads horizontally instead of vertically. This is used to cross-cross\n         * check a vertical cross check and locate the real center of the alignment pattern.</p>\n         */\n        crossCheckHorizontal(startJ /*int*/, centerI /*int*/, maxCount /*int*/, originalStateCountTotal /*int*/) {\n            const image = this.image;\n            const maxJ = image.getWidth();\n            const stateCount = this.getCrossCheckStateCount();\n            let j = startJ;\n            while (j >= 0 && image.get(j, centerI)) {\n                stateCount[2]++;\n                j--;\n            }\n            if (j < 0) {\n                return NaN;\n            }\n            while (j >= 0 && !image.get(j, centerI) && stateCount[1] <= maxCount) {\n                stateCount[1]++;\n                j--;\n            }\n            if (j < 0 || stateCount[1] > maxCount) {\n                return NaN;\n            }\n            while (j >= 0 && image.get(j, centerI) && stateCount[0] <= maxCount) {\n                stateCount[0]++;\n                j--;\n            }\n            if (stateCount[0] > maxCount) {\n                return NaN;\n            }\n            j = startJ + 1;\n            while (j < maxJ && image.get(j, centerI)) {\n                stateCount[2]++;\n                j++;\n            }\n            if (j === maxJ) {\n                return NaN;\n            }\n            while (j < maxJ && !image.get(j, centerI) && stateCount[3] < maxCount) {\n                stateCount[3]++;\n                j++;\n            }\n            if (j === maxJ || stateCount[3] >= maxCount) {\n                return NaN;\n            }\n            while (j < maxJ && image.get(j, centerI) && stateCount[4] < maxCount) {\n                stateCount[4]++;\n                j++;\n            }\n            if (stateCount[4] >= maxCount) {\n                return NaN;\n            }\n            // If we found a finder-pattern-like section, but its size is significantly different than\n            // the original, assume it's a false positive\n            const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +\n                stateCount[4];\n            if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) {\n                return NaN;\n            }\n            return FinderPatternFinder.foundPatternCross(stateCount) ? FinderPatternFinder.centerFromEnd(stateCount, j) : NaN;\n        }\n        /**\n         * <p>This is called when a horizontal scan finds a possible alignment pattern. It will\n         * cross check with a vertical scan, and if successful, will, ah, cross-cross-check\n         * with another horizontal scan. This is needed primarily to locate the real horizontal\n         * center of the pattern in cases of extreme skew.\n         * And then we cross-cross-cross check with another diagonal scan.</p>\n         *\n         * <p>If that succeeds the finder pattern location is added to a list that tracks\n         * the number of times each location has been nearly-matched as a finder pattern.\n         * Each additional find is more evidence that the location is in fact a finder\n         * pattern center\n         *\n         * @param stateCount reading state module counts from horizontal scan\n         * @param i row where finder pattern may be found\n         * @param j end of possible finder pattern in row\n         * @param pureBarcode true if in \"pure barcode\" mode\n         * @return true if a finder pattern candidate was found this time\n         */\n        handlePossibleCenter(stateCount, i /*int*/, j /*int*/, pureBarcode) {\n            const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +\n                stateCount[4];\n            let centerJ = FinderPatternFinder.centerFromEnd(stateCount, j);\n            let centerI = this.crossCheckVertical(i, /*(int) */ Math.floor(centerJ), stateCount[2], stateCountTotal);\n            if (!isNaN(centerI)) {\n                // Re-cross check\n                centerJ = this.crossCheckHorizontal(/*(int) */ Math.floor(centerJ), /*(int) */ Math.floor(centerI), stateCount[2], stateCountTotal);\n                if (!isNaN(centerJ) &&\n                    (!pureBarcode || this.crossCheckDiagonal(/*(int) */ Math.floor(centerI), /*(int) */ Math.floor(centerJ), stateCount[2], stateCountTotal))) {\n                    const estimatedModuleSize = stateCountTotal / 7.0;\n                    let found = false;\n                    const possibleCenters = this.possibleCenters;\n                    for (let index = 0, length = possibleCenters.length; index < length; index++) {\n                        const center = possibleCenters[index];\n                        // Look for about the same center and module size:\n                        if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {\n                            possibleCenters[index] = center.combineEstimate(centerI, centerJ, estimatedModuleSize);\n                            found = true;\n                            break;\n                        }\n                    }\n                    if (!found) {\n                        const point = new FinderPattern$1(centerJ, centerI, estimatedModuleSize);\n                        possibleCenters.push(point);\n                        if (this.resultPointCallback !== null && this.resultPointCallback !== undefined) {\n                            this.resultPointCallback.foundPossibleResultPoint(point);\n                        }\n                    }\n                    return true;\n                }\n            }\n            return false;\n        }\n        /**\n         * @return number of rows we could safely skip during scanning, based on the first\n         *         two finder patterns that have been located. In some cases their position will\n         *         allow us to infer that the third pattern must lie below a certain point farther\n         *         down in the image.\n         */\n        findRowSkip() {\n            const max = this.possibleCenters.length;\n            if (max <= 1) {\n                return 0;\n            }\n            let firstConfirmedCenter = null;\n            for (const center of this.possibleCenters) {\n                if (center.getCount() >= FinderPatternFinder.CENTER_QUORUM) {\n                    if (firstConfirmedCenter == null) {\n                        firstConfirmedCenter = center;\n                    }\n                    else {\n                        // We have two confirmed centers\n                        // How far down can we skip before resuming looking for the next\n                        // pattern? In the worst case, only the difference between the\n                        // difference in the x / y coordinates of the two centers.\n                        // This is the case where you find top left last.\n                        this.hasSkipped = true;\n                        return /*(int) */ Math.floor((Math.abs(firstConfirmedCenter.getX() - center.getX()) -\n                            Math.abs(firstConfirmedCenter.getY() - center.getY())) / 2);\n                    }\n                }\n            }\n            return 0;\n        }\n        /**\n         * @return true iff we have found at least 3 finder patterns that have been detected\n         *         at least {@link #CENTER_QUORUM} times each, and, the estimated module size of the\n         *         candidates is \"pretty similar\"\n         */\n        haveMultiplyConfirmedCenters() {\n            let confirmedCount = 0;\n            let totalModuleSize = 0.0;\n            const max = this.possibleCenters.length;\n            for (const pattern of this.possibleCenters) {\n                if (pattern.getCount() >= FinderPatternFinder.CENTER_QUORUM) {\n                    confirmedCount++;\n                    totalModuleSize += pattern.getEstimatedModuleSize();\n                }\n            }\n            if (confirmedCount < 3) {\n                return false;\n            }\n            // OK, we have at least 3 confirmed centers, but, it's possible that one is a \"false positive\"\n            // and that we need to keep looking. We detect this by asking if the estimated module sizes\n            // vary too much. We arbitrarily say that when the total deviation from average exceeds\n            // 5% of the total module size estimates, it's too much.\n            const average = totalModuleSize / max;\n            let totalDeviation = 0.0;\n            for (const pattern of this.possibleCenters) {\n                totalDeviation += Math.abs(pattern.getEstimatedModuleSize() - average);\n            }\n            return totalDeviation <= 0.05 * totalModuleSize;\n        }\n        /**\n         * @return the 3 best {@link FinderPattern}s from our list of candidates. The \"best\" are\n         *         those that have been detected at least {@link #CENTER_QUORUM} times, and whose module\n         *         size differs from the average among those patterns the least\n         * @throws NotFoundException if 3 such finder patterns do not exist\n         */\n        selectBestPatterns() {\n            const startSize = this.possibleCenters.length;\n            if (startSize < 3) {\n                // Couldn't find enough finder patterns\n                throw new NotFoundException();\n            }\n            const possibleCenters = this.possibleCenters;\n            let average;\n            // Filter outlier possibilities whose module size is too different\n            if (startSize > 3) {\n                // But we can only afford to do so if we have at least 4 possibilities to choose from\n                let totalModuleSize = 0.0;\n                let square = 0.0;\n                for (const center of this.possibleCenters) {\n                    const size = center.getEstimatedModuleSize();\n                    totalModuleSize += size;\n                    square += size * size;\n                }\n                average = totalModuleSize / startSize;\n                let stdDev = Math.sqrt(square / startSize - average * average);\n                possibleCenters.sort(\n                /**\n                 * <p>Orders by furthest from average</p>\n                 */\n                // FurthestFromAverageComparator implements Comparator<FinderPattern>\n                (center1, center2) => {\n                    const dA = Math.abs(center2.getEstimatedModuleSize() - average);\n                    const dB = Math.abs(center1.getEstimatedModuleSize() - average);\n                    return dA < dB ? -1 : dA > dB ? 1 : 0;\n                });\n                const limit = Math.max(0.2 * average, stdDev);\n                for (let i = 0; i < possibleCenters.length && possibleCenters.length > 3; i++) {\n                    const pattern = possibleCenters[i];\n                    if (Math.abs(pattern.getEstimatedModuleSize() - average) > limit) {\n                        possibleCenters.splice(i, 1);\n                        i--;\n                    }\n                }\n            }\n            if (possibleCenters.length > 3) {\n                // Throw away all but those first size candidate points we found.\n                let totalModuleSize = 0.0;\n                for (const possibleCenter of possibleCenters) {\n                    totalModuleSize += possibleCenter.getEstimatedModuleSize();\n                }\n                average = totalModuleSize / possibleCenters.length;\n                possibleCenters.sort(\n                /**\n                 * <p>Orders by {@link FinderPattern#getCount()}, descending.</p>\n                 */\n                // CenterComparator implements Comparator<FinderPattern>\n                (center1, center2) => {\n                    if (center2.getCount() === center1.getCount()) {\n                        const dA = Math.abs(center2.getEstimatedModuleSize() - average);\n                        const dB = Math.abs(center1.getEstimatedModuleSize() - average);\n                        return dA < dB ? 1 : dA > dB ? -1 : 0;\n                    }\n                    else {\n                        return center2.getCount() - center1.getCount();\n                    }\n                });\n                possibleCenters.splice(3); // this is not realy necessary as we only return first 3 anyway\n            }\n            return [\n                possibleCenters[0],\n                possibleCenters[1],\n                possibleCenters[2]\n            ];\n        }\n    }\n    FinderPatternFinder.CENTER_QUORUM = 2;\n    FinderPatternFinder.MIN_SKIP = 3; // 1 pixel/module times 3 modules/center\n    FinderPatternFinder.MAX_MODULES = 57; // support up to version 10 for mobile clients\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*import java.util.Map;*/\n    /**\n     * <p>Encapsulates logic that can detect a QR Code in an image, even if the QR Code\n     * is rotated or skewed, or partially obscured.</p>\n     *\n     * @author Sean Owen\n     */\n    class Detector$2 {\n        constructor(image) {\n            this.image = image;\n        }\n        getImage() {\n            return this.image;\n        }\n        getResultPointCallback() {\n            return this.resultPointCallback;\n        }\n        /**\n         * <p>Detects a QR Code in an image.</p>\n         *\n         * @return {@link DetectorResult} encapsulating results of detecting a QR Code\n         * @throws NotFoundException if QR Code cannot be found\n         * @throws FormatException if a QR Code cannot be decoded\n         */\n        // public detect(): DetectorResult /*throws NotFoundException, FormatException*/ {\n        //   return detect(null)\n        // }\n        /**\n         * <p>Detects a QR Code in an image.</p>\n         *\n         * @param hints optional hints to detector\n         * @return {@link DetectorResult} encapsulating results of detecting a QR Code\n         * @throws NotFoundException if QR Code cannot be found\n         * @throws FormatException if a QR Code cannot be decoded\n         */\n        detect(hints) {\n            this.resultPointCallback = (hints === null || hints === undefined) ? null :\n                /*(ResultPointCallback) */ hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n            const finder = new FinderPatternFinder(this.image, this.resultPointCallback);\n            const info = finder.find(hints);\n            return this.processFinderPatternInfo(info);\n        }\n        processFinderPatternInfo(info) {\n            const topLeft = info.getTopLeft();\n            const topRight = info.getTopRight();\n            const bottomLeft = info.getBottomLeft();\n            const moduleSize = this.calculateModuleSize(topLeft, topRight, bottomLeft);\n            if (moduleSize < 1.0) {\n                throw new NotFoundException('No pattern found in proccess finder.');\n            }\n            const dimension = Detector$2.computeDimension(topLeft, topRight, bottomLeft, moduleSize);\n            const provisionalVersion = Version$1.getProvisionalVersionForDimension(dimension);\n            const modulesBetweenFPCenters = provisionalVersion.getDimensionForVersion() - 7;\n            let alignmentPattern = null;\n            // Anything above version 1 has an alignment pattern\n            if (provisionalVersion.getAlignmentPatternCenters().length > 0) {\n                // Guess where a \"bottom right\" finder pattern would have been\n                const bottomRightX = topRight.getX() - topLeft.getX() + bottomLeft.getX();\n                const bottomRightY = topRight.getY() - topLeft.getY() + bottomLeft.getY();\n                // Estimate that alignment pattern is closer by 3 modules\n                // from \"bottom right\" to known top left location\n                const correctionToTopLeft = 1.0 - 3.0 / modulesBetweenFPCenters;\n                const estAlignmentX = /*(int) */ Math.floor(topLeft.getX() + correctionToTopLeft * (bottomRightX - topLeft.getX()));\n                const estAlignmentY = /*(int) */ Math.floor(topLeft.getY() + correctionToTopLeft * (bottomRightY - topLeft.getY()));\n                // Kind of arbitrary -- expand search radius before giving up\n                for (let i = 4; i <= 16; i <<= 1) {\n                    try {\n                        alignmentPattern = this.findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, i);\n                        break;\n                    }\n                    catch (re /*NotFoundException*/) {\n                        if (!(re instanceof NotFoundException)) {\n                            throw re;\n                        }\n                        // try next round\n                    }\n                }\n                // If we didn't find alignment pattern... well try anyway without it\n            }\n            const transform = Detector$2.createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);\n            const bits = Detector$2.sampleGrid(this.image, transform, dimension);\n            let points;\n            if (alignmentPattern === null) {\n                points = [bottomLeft, topLeft, topRight];\n            }\n            else {\n                points = [bottomLeft, topLeft, topRight, alignmentPattern];\n            }\n            return new DetectorResult(bits, points);\n        }\n        static createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension /*int*/) {\n            const dimMinusThree = dimension - 3.5;\n            let bottomRightX; /*float*/\n            let bottomRightY; /*float*/\n            let sourceBottomRightX; /*float*/\n            let sourceBottomRightY; /*float*/\n            if (alignmentPattern !== null) {\n                bottomRightX = alignmentPattern.getX();\n                bottomRightY = alignmentPattern.getY();\n                sourceBottomRightX = dimMinusThree - 3.0;\n                sourceBottomRightY = sourceBottomRightX;\n            }\n            else {\n                // Don't have an alignment pattern, just make up the bottom-right point\n                bottomRightX = (topRight.getX() - topLeft.getX()) + bottomLeft.getX();\n                bottomRightY = (topRight.getY() - topLeft.getY()) + bottomLeft.getY();\n                sourceBottomRightX = dimMinusThree;\n                sourceBottomRightY = dimMinusThree;\n            }\n            return PerspectiveTransform.quadrilateralToQuadrilateral(3.5, 3.5, dimMinusThree, 3.5, sourceBottomRightX, sourceBottomRightY, 3.5, dimMinusThree, topLeft.getX(), topLeft.getY(), topRight.getX(), topRight.getY(), bottomRightX, bottomRightY, bottomLeft.getX(), bottomLeft.getY());\n        }\n        static sampleGrid(image, transform, dimension /*int*/) {\n            const sampler = GridSamplerInstance.getInstance();\n            return sampler.sampleGridWithTransform(image, dimension, dimension, transform);\n        }\n        /**\n         * <p>Computes the dimension (number of modules on a size) of the QR Code based on the position\n         * of the finder patterns and estimated module size.</p>\n         */\n        static computeDimension(topLeft, topRight, bottomLeft, moduleSize /*float*/) {\n            const tltrCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, topRight) / moduleSize);\n            const tlblCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize);\n            let dimension = Math.floor((tltrCentersDimension + tlblCentersDimension) / 2) + 7;\n            switch (dimension & 0x03) { // mod 4\n                case 0:\n                    dimension++;\n                    break;\n                // 1? do nothing\n                case 2:\n                    dimension--;\n                    break;\n                case 3:\n                    throw new NotFoundException('Dimensions could be not found.');\n            }\n            return dimension;\n        }\n        /**\n         * <p>Computes an average estimated module size based on estimated derived from the positions\n         * of the three finder patterns.</p>\n         *\n         * @param topLeft detected top-left finder pattern center\n         * @param topRight detected top-right finder pattern center\n         * @param bottomLeft detected bottom-left finder pattern center\n         * @return estimated module size\n         */\n        calculateModuleSize(topLeft, topRight, bottomLeft) {\n            // Take the average\n            return (this.calculateModuleSizeOneWay(topLeft, topRight) +\n                this.calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0;\n        }\n        /**\n         * <p>Estimates module size based on two finder patterns -- it uses\n         * {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the\n         * width of each, measuring along the axis between their centers.</p>\n         */\n        calculateModuleSizeOneWay(pattern, otherPattern) {\n            const moduleSizeEst1 = this.sizeOfBlackWhiteBlackRunBothWays(/*(int) */ Math.floor(pattern.getX()), \n            /*(int) */ Math.floor(pattern.getY()), \n            /*(int) */ Math.floor(otherPattern.getX()), \n            /*(int) */ Math.floor(otherPattern.getY()));\n            const moduleSizeEst2 = this.sizeOfBlackWhiteBlackRunBothWays(/*(int) */ Math.floor(otherPattern.getX()), \n            /*(int) */ Math.floor(otherPattern.getY()), \n            /*(int) */ Math.floor(pattern.getX()), \n            /*(int) */ Math.floor(pattern.getY()));\n            if (isNaN(moduleSizeEst1)) {\n                return moduleSizeEst2 / 7.0;\n            }\n            if (isNaN(moduleSizeEst2)) {\n                return moduleSizeEst1 / 7.0;\n            }\n            // Average them, and divide by 7 since we've counted the width of 3 black modules,\n            // and 1 white and 1 black module on either side. Ergo, divide sum by 14.\n            return (moduleSizeEst1 + moduleSizeEst2) / 14.0;\n        }\n        /**\n         * See {@link #sizeOfBlackWhiteBlackRun(int, int, int, int)}; computes the total width of\n         * a finder pattern by looking for a black-white-black run from the center in the direction\n         * of another point (another finder pattern center), and in the opposite direction too.\n         */\n        sizeOfBlackWhiteBlackRunBothWays(fromX /*int*/, fromY /*int*/, toX /*int*/, toY /*int*/) {\n            let result = this.sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY);\n            // Now count other way -- don't run off image though of course\n            let scale = 1.0;\n            let otherToX = fromX - (toX - fromX);\n            if (otherToX < 0) {\n                scale = fromX / /*(float) */ (fromX - otherToX);\n                otherToX = 0;\n            }\n            else if (otherToX >= this.image.getWidth()) {\n                scale = (this.image.getWidth() - 1 - fromX) / /*(float) */ (otherToX - fromX);\n                otherToX = this.image.getWidth() - 1;\n            }\n            let otherToY = /*(int) */ Math.floor(fromY - (toY - fromY) * scale);\n            scale = 1.0;\n            if (otherToY < 0) {\n                scale = fromY / /*(float) */ (fromY - otherToY);\n                otherToY = 0;\n            }\n            else if (otherToY >= this.image.getHeight()) {\n                scale = (this.image.getHeight() - 1 - fromY) / /*(float) */ (otherToY - fromY);\n                otherToY = this.image.getHeight() - 1;\n            }\n            otherToX = /*(int) */ Math.floor(fromX + (otherToX - fromX) * scale);\n            result += this.sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY);\n            // Middle pixel is double-counted this way; subtract 1\n            return result - 1.0;\n        }\n        /**\n         * <p>This method traces a line from a point in the image, in the direction towards another point.\n         * It begins in a black region, and keeps going until it finds white, then black, then white again.\n         * It reports the distance from the start to this point.</p>\n         *\n         * <p>This is used when figuring out how wide a finder pattern is, when the finder pattern\n         * may be skewed or rotated.</p>\n         */\n        sizeOfBlackWhiteBlackRun(fromX /*int*/, fromY /*int*/, toX /*int*/, toY /*int*/) {\n            // Mild variant of Bresenham's algorithm\n            // see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm\n            const steep = Math.abs(toY - fromY) > Math.abs(toX - fromX);\n            if (steep) {\n                let temp = fromX;\n                fromX = fromY;\n                fromY = temp;\n                temp = toX;\n                toX = toY;\n                toY = temp;\n            }\n            const dx = Math.abs(toX - fromX);\n            const dy = Math.abs(toY - fromY);\n            let error = -dx / 2;\n            const xstep = fromX < toX ? 1 : -1;\n            const ystep = fromY < toY ? 1 : -1;\n            // In black pixels, looking for white, first or second time.\n            let state = 0;\n            // Loop up until x == toX, but not beyond\n            const xLimit = toX + xstep;\n            for (let x = fromX, y = fromY; x !== xLimit; x += xstep) {\n                const realX = steep ? y : x;\n                const realY = steep ? x : y;\n                // Does current pixel mean we have moved white to black or vice versa?\n                // Scanning black in state 0,2 and white in state 1, so if we find the wrong\n                // color, advance to next state or end if we are in state 2 already\n                if ((state === 1) === this.image.get(realX, realY)) {\n                    if (state === 2) {\n                        return MathUtils.distance(x, y, fromX, fromY);\n                    }\n                    state++;\n                }\n                error += dy;\n                if (error > 0) {\n                    if (y === toY) {\n                        break;\n                    }\n                    y += ystep;\n                    error -= dx;\n                }\n            }\n            // Found black-white-black; give the benefit of the doubt that the next pixel outside the image\n            // is \"white\" so this last point at (toX+xStep,toY) is the right ending. This is really a\n            // small approximation; (toX+xStep,toY+yStep) might be really correct. Ignore this.\n            if (state === 2) {\n                return MathUtils.distance(toX + xstep, toY, fromX, fromY);\n            }\n            // else we didn't find even black-white-black; no estimate is really possible\n            return NaN;\n        }\n        /**\n         * <p>Attempts to locate an alignment pattern in a limited region of the image, which is\n         * guessed to contain it. This method uses {@link AlignmentPattern}.</p>\n         *\n         * @param overallEstModuleSize estimated module size so far\n         * @param estAlignmentX x coordinate of center of area probably containing alignment pattern\n         * @param estAlignmentY y coordinate of above\n         * @param allowanceFactor number of pixels in all directions to search from the center\n         * @return {@link AlignmentPattern} if found, or null otherwise\n         * @throws NotFoundException if an unexpected error occurs during detection\n         */\n        findAlignmentInRegion(overallEstModuleSize /*float*/, estAlignmentX /*int*/, estAlignmentY /*int*/, allowanceFactor /*float*/) {\n            // Look for an alignment pattern (3 modules in size) around where it\n            // should be\n            const allowance = /*(int) */ Math.floor(allowanceFactor * overallEstModuleSize);\n            const alignmentAreaLeftX = Math.max(0, estAlignmentX - allowance);\n            const alignmentAreaRightX = Math.min(this.image.getWidth() - 1, estAlignmentX + allowance);\n            if (alignmentAreaRightX - alignmentAreaLeftX < overallEstModuleSize * 3) {\n                throw new NotFoundException('Alignment top exceeds estimated module size.');\n            }\n            const alignmentAreaTopY = Math.max(0, estAlignmentY - allowance);\n            const alignmentAreaBottomY = Math.min(this.image.getHeight() - 1, estAlignmentY + allowance);\n            if (alignmentAreaBottomY - alignmentAreaTopY < overallEstModuleSize * 3) {\n                throw new NotFoundException('Alignment bottom exceeds estimated module size.');\n            }\n            const alignmentFinder = new AlignmentPatternFinder(this.image, alignmentAreaLeftX, alignmentAreaTopY, alignmentAreaRightX - alignmentAreaLeftX, alignmentAreaBottomY - alignmentAreaTopY, overallEstModuleSize, this.resultPointCallback);\n            return alignmentFinder.find();\n        }\n    }\n\n    /*\n     * Copyright 2007 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*import java.util.List;*/\n    /*import java.util.Map;*/\n    /**\n     * This implementation can detect and decode QR Codes in an image.\n     *\n     * @author Sean Owen\n     */\n    class QRCodeReader {\n        constructor() {\n            this.decoder = new Decoder$2();\n        }\n        getDecoder() {\n            return this.decoder;\n        }\n        /**\n         * Locates and decodes a QR code in an image.\n         *\n         * @return a representing: string the content encoded by the QR code\n         * @throws NotFoundException if a QR code cannot be found\n         * @throws FormatException if a QR code cannot be decoded\n         * @throws ChecksumException if error correction fails\n         */\n        /*@Override*/\n        // public decode(image: BinaryBitmap): Result /*throws NotFoundException, ChecksumException, FormatException */ {\n        //   return this.decode(image, null)\n        // }\n        /*@Override*/\n        decode(image, hints) {\n            let decoderResult;\n            let points;\n            if (hints !== undefined && hints !== null && undefined !== hints.get(DecodeHintType$1.PURE_BARCODE)) {\n                const bits = QRCodeReader.extractPureBits(image.getBlackMatrix());\n                decoderResult = this.decoder.decodeBitMatrix(bits, hints);\n                points = QRCodeReader.NO_POINTS;\n            }\n            else {\n                const detectorResult = new Detector$2(image.getBlackMatrix()).detect(hints);\n                decoderResult = this.decoder.decodeBitMatrix(detectorResult.getBits(), hints);\n                points = detectorResult.getPoints();\n            }\n            // If the code was mirrored: swap the bottom-left and the top-right points.\n            if (decoderResult.getOther() instanceof QRCodeDecoderMetaData) {\n                decoderResult.getOther().applyMirroredCorrection(points);\n            }\n            const result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), undefined, points, BarcodeFormat$1.QR_CODE, undefined);\n            const byteSegments = decoderResult.getByteSegments();\n            if (byteSegments !== null) {\n                result.putMetadata(ResultMetadataType$1.BYTE_SEGMENTS, byteSegments);\n            }\n            const ecLevel = decoderResult.getECLevel();\n            if (ecLevel !== null) {\n                result.putMetadata(ResultMetadataType$1.ERROR_CORRECTION_LEVEL, ecLevel);\n            }\n            if (decoderResult.hasStructuredAppend()) {\n                result.putMetadata(ResultMetadataType$1.STRUCTURED_APPEND_SEQUENCE, decoderResult.getStructuredAppendSequenceNumber());\n                result.putMetadata(ResultMetadataType$1.STRUCTURED_APPEND_PARITY, decoderResult.getStructuredAppendParity());\n            }\n            return result;\n        }\n        /*@Override*/\n        reset() {\n            // do nothing\n        }\n        /**\n         * This method detects a code in a \"pure\" image -- that is, pure monochrome image\n         * which contains only an unrotated, unskewed, image of a code, with some white border\n         * around it. This is a specialized method that works exceptionally fast in this special\n         * case.\n         *\n         * @see com.google.zxing.datamatrix.DataMatrixReader#extractPureBits(BitMatrix)\n         */\n        static extractPureBits(image) {\n            const leftTopBlack = image.getTopLeftOnBit();\n            const rightBottomBlack = image.getBottomRightOnBit();\n            if (leftTopBlack === null || rightBottomBlack === null) {\n                throw new NotFoundException();\n            }\n            const moduleSize = this.moduleSize(leftTopBlack, image);\n            let top = leftTopBlack[1];\n            let bottom = rightBottomBlack[1];\n            let left = leftTopBlack[0];\n            let right = rightBottomBlack[0];\n            // Sanity check!\n            if (left >= right || top >= bottom) {\n                throw new NotFoundException();\n            }\n            if (bottom - top !== right - left) {\n                // Special case, where bottom-right module wasn't black so we found something else in the last row\n                // Assume it's a square, so use height as the width\n                right = left + (bottom - top);\n                if (right >= image.getWidth()) {\n                    // Abort if that would not make sense -- off image\n                    throw new NotFoundException();\n                }\n            }\n            const matrixWidth = Math.round((right - left + 1) / moduleSize);\n            const matrixHeight = Math.round((bottom - top + 1) / moduleSize);\n            if (matrixWidth <= 0 || matrixHeight <= 0) {\n                throw new NotFoundException();\n            }\n            if (matrixHeight !== matrixWidth) {\n                // Only possibly decode square regions\n                throw new NotFoundException();\n            }\n            // Push in the \"border\" by half the module width so that we start\n            // sampling in the middle of the module. Just in case the image is a\n            // little off, this will help recover.\n            const nudge = /*(int) */ Math.floor(moduleSize / 2.0);\n            top += nudge;\n            left += nudge;\n            // But careful that this does not sample off the edge\n            // \"right\" is the farthest-right valid pixel location -- right+1 is not necessarily\n            // This is positive by how much the inner x loop below would be too large\n            const nudgedTooFarRight = left + /*(int) */ Math.floor((matrixWidth - 1) * moduleSize) - right;\n            if (nudgedTooFarRight > 0) {\n                if (nudgedTooFarRight > nudge) {\n                    // Neither way fits; abort\n                    throw new NotFoundException();\n                }\n                left -= nudgedTooFarRight;\n            }\n            // See logic above\n            const nudgedTooFarDown = top + /*(int) */ Math.floor((matrixHeight - 1) * moduleSize) - bottom;\n            if (nudgedTooFarDown > 0) {\n                if (nudgedTooFarDown > nudge) {\n                    // Neither way fits; abort\n                    throw new NotFoundException();\n                }\n                top -= nudgedTooFarDown;\n            }\n            // Now just read off the bits\n            const bits = new BitMatrix(matrixWidth, matrixHeight);\n            for (let y = 0; y < matrixHeight; y++) {\n                const iOffset = top + /*(int) */ Math.floor(y * moduleSize);\n                for (let x = 0; x < matrixWidth; x++) {\n                    if (image.get(left + /*(int) */ Math.floor(x * moduleSize), iOffset)) {\n                        bits.set(x, y);\n                    }\n                }\n            }\n            return bits;\n        }\n        static moduleSize(leftTopBlack, image) {\n            const height = image.getHeight();\n            const width = image.getWidth();\n            let x = leftTopBlack[0];\n            let y = leftTopBlack[1];\n            let inBlack = true;\n            let transitions = 0;\n            while (x < width && y < height) {\n                if (inBlack !== image.get(x, y)) {\n                    if (++transitions === 5) {\n                        break;\n                    }\n                    inBlack = !inBlack;\n                }\n                x++;\n                y++;\n            }\n            if (x === width || y === height) {\n                throw new NotFoundException();\n            }\n            return (x - leftTopBlack[0]) / 7.0;\n        }\n    }\n    QRCodeReader.NO_POINTS = new Array();\n\n    /*\n    * Copyright 2009 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /**\n     * @author SITA Lab (kevin.osullivan@sita.aero)\n     * @author Guenther Grau\n     */\n    /*public final*/ class PDF417Common {\n        PDF417Common() {\n        }\n        /**\n         * @param moduleBitCount values to sum\n         * @return sum of values\n         * @deprecated call {@link MathUtils#sum(int[])}\n         */\n        // @Deprecated\n        static getBitCountSum(moduleBitCount) {\n            return MathUtils.sum(moduleBitCount);\n        }\n        static toIntArray(list) {\n            if (list == null || !list.length) {\n                return PDF417Common.EMPTY_INT_ARRAY;\n            }\n            const result = new Int32Array(list.length);\n            let i = 0;\n            for (const integer of list) {\n                result[i++] = integer;\n            }\n            return result;\n        }\n        /**\n         * @param symbol encoded symbol to translate to a codeword\n         * @return the codeword corresponding to the symbol.\n         */\n        static getCodeword(symbol /*int*/) {\n            const i = Arrays.binarySearch(PDF417Common.SYMBOL_TABLE, symbol & 0x3FFFF);\n            if (i < 0) {\n                return -1;\n            }\n            return (PDF417Common.CODEWORD_TABLE[i] - 1) % PDF417Common.NUMBER_OF_CODEWORDS;\n        }\n    }\n    PDF417Common.NUMBER_OF_CODEWORDS = 929;\n    // Maximum Codewords (Data + Error).\n    PDF417Common.MAX_CODEWORDS_IN_BARCODE = PDF417Common.NUMBER_OF_CODEWORDS - 1;\n    PDF417Common.MIN_ROWS_IN_BARCODE = 3;\n    PDF417Common.MAX_ROWS_IN_BARCODE = 90;\n    // One left row indication column + max 30 data columns + one right row indicator column\n    // public static /*final*/ MAX_CODEWORDS_IN_ROW: /*int*/ number = 32;\n    PDF417Common.MODULES_IN_CODEWORD = 17;\n    PDF417Common.MODULES_IN_STOP_PATTERN = 18;\n    PDF417Common.BARS_IN_MODULE = 8;\n    PDF417Common.EMPTY_INT_ARRAY = new Int32Array([]);\n    /**\n     * The sorted table of all possible symbols. Extracted from the PDF417\n     * specification. The index of a symbol in this table corresponds to the\n     * index into the codeword table.\n     */\n    PDF417Common.SYMBOL_TABLE = Int32Array.from([\n        0x1025e, 0x1027a, 0x1029e, 0x102bc, 0x102f2, 0x102f4, 0x1032e, 0x1034e, 0x1035c, 0x10396, 0x103a6, 0x103ac,\n        0x10422, 0x10428, 0x10436, 0x10442, 0x10444, 0x10448, 0x10450, 0x1045e, 0x10466, 0x1046c, 0x1047a, 0x10482,\n        0x1049e, 0x104a0, 0x104bc, 0x104c6, 0x104d8, 0x104ee, 0x104f2, 0x104f4, 0x10504, 0x10508, 0x10510, 0x1051e,\n        0x10520, 0x1053c, 0x10540, 0x10578, 0x10586, 0x1058c, 0x10598, 0x105b0, 0x105be, 0x105ce, 0x105dc, 0x105e2,\n        0x105e4, 0x105e8, 0x105f6, 0x1062e, 0x1064e, 0x1065c, 0x1068e, 0x1069c, 0x106b8, 0x106de, 0x106fa, 0x10716,\n        0x10726, 0x1072c, 0x10746, 0x1074c, 0x10758, 0x1076e, 0x10792, 0x10794, 0x107a2, 0x107a4, 0x107a8, 0x107b6,\n        0x10822, 0x10828, 0x10842, 0x10848, 0x10850, 0x1085e, 0x10866, 0x1086c, 0x1087a, 0x10882, 0x10884, 0x10890,\n        0x1089e, 0x108a0, 0x108bc, 0x108c6, 0x108cc, 0x108d8, 0x108ee, 0x108f2, 0x108f4, 0x10902, 0x10908, 0x1091e,\n        0x10920, 0x1093c, 0x10940, 0x10978, 0x10986, 0x10998, 0x109b0, 0x109be, 0x109ce, 0x109dc, 0x109e2, 0x109e4,\n        0x109e8, 0x109f6, 0x10a08, 0x10a10, 0x10a1e, 0x10a20, 0x10a3c, 0x10a40, 0x10a78, 0x10af0, 0x10b06, 0x10b0c,\n        0x10b18, 0x10b30, 0x10b3e, 0x10b60, 0x10b7c, 0x10b8e, 0x10b9c, 0x10bb8, 0x10bc2, 0x10bc4, 0x10bc8, 0x10bd0,\n        0x10bde, 0x10be6, 0x10bec, 0x10c2e, 0x10c4e, 0x10c5c, 0x10c62, 0x10c64, 0x10c68, 0x10c76, 0x10c8e, 0x10c9c,\n        0x10cb8, 0x10cc2, 0x10cc4, 0x10cc8, 0x10cd0, 0x10cde, 0x10ce6, 0x10cec, 0x10cfa, 0x10d0e, 0x10d1c, 0x10d38,\n        0x10d70, 0x10d7e, 0x10d82, 0x10d84, 0x10d88, 0x10d90, 0x10d9e, 0x10da0, 0x10dbc, 0x10dc6, 0x10dcc, 0x10dd8,\n        0x10dee, 0x10df2, 0x10df4, 0x10e16, 0x10e26, 0x10e2c, 0x10e46, 0x10e58, 0x10e6e, 0x10e86, 0x10e8c, 0x10e98,\n        0x10eb0, 0x10ebe, 0x10ece, 0x10edc, 0x10f0a, 0x10f12, 0x10f14, 0x10f22, 0x10f28, 0x10f36, 0x10f42, 0x10f44,\n        0x10f48, 0x10f50, 0x10f5e, 0x10f66, 0x10f6c, 0x10fb2, 0x10fb4, 0x11022, 0x11028, 0x11042, 0x11048, 0x11050,\n        0x1105e, 0x1107a, 0x11082, 0x11084, 0x11090, 0x1109e, 0x110a0, 0x110bc, 0x110c6, 0x110cc, 0x110d8, 0x110ee,\n        0x110f2, 0x110f4, 0x11102, 0x1111e, 0x11120, 0x1113c, 0x11140, 0x11178, 0x11186, 0x11198, 0x111b0, 0x111be,\n        0x111ce, 0x111dc, 0x111e2, 0x111e4, 0x111e8, 0x111f6, 0x11208, 0x1121e, 0x11220, 0x11278, 0x112f0, 0x1130c,\n        0x11330, 0x1133e, 0x11360, 0x1137c, 0x1138e, 0x1139c, 0x113b8, 0x113c2, 0x113c8, 0x113d0, 0x113de, 0x113e6,\n        0x113ec, 0x11408, 0x11410, 0x1141e, 0x11420, 0x1143c, 0x11440, 0x11478, 0x114f0, 0x115e0, 0x1160c, 0x11618,\n        0x11630, 0x1163e, 0x11660, 0x1167c, 0x116c0, 0x116f8, 0x1171c, 0x11738, 0x11770, 0x1177e, 0x11782, 0x11784,\n        0x11788, 0x11790, 0x1179e, 0x117a0, 0x117bc, 0x117c6, 0x117cc, 0x117d8, 0x117ee, 0x1182e, 0x11834, 0x1184e,\n        0x1185c, 0x11862, 0x11864, 0x11868, 0x11876, 0x1188e, 0x1189c, 0x118b8, 0x118c2, 0x118c8, 0x118d0, 0x118de,\n        0x118e6, 0x118ec, 0x118fa, 0x1190e, 0x1191c, 0x11938, 0x11970, 0x1197e, 0x11982, 0x11984, 0x11990, 0x1199e,\n        0x119a0, 0x119bc, 0x119c6, 0x119cc, 0x119d8, 0x119ee, 0x119f2, 0x119f4, 0x11a0e, 0x11a1c, 0x11a38, 0x11a70,\n        0x11a7e, 0x11ae0, 0x11afc, 0x11b08, 0x11b10, 0x11b1e, 0x11b20, 0x11b3c, 0x11b40, 0x11b78, 0x11b8c, 0x11b98,\n        0x11bb0, 0x11bbe, 0x11bce, 0x11bdc, 0x11be2, 0x11be4, 0x11be8, 0x11bf6, 0x11c16, 0x11c26, 0x11c2c, 0x11c46,\n        0x11c4c, 0x11c58, 0x11c6e, 0x11c86, 0x11c98, 0x11cb0, 0x11cbe, 0x11cce, 0x11cdc, 0x11ce2, 0x11ce4, 0x11ce8,\n        0x11cf6, 0x11d06, 0x11d0c, 0x11d18, 0x11d30, 0x11d3e, 0x11d60, 0x11d7c, 0x11d8e, 0x11d9c, 0x11db8, 0x11dc4,\n        0x11dc8, 0x11dd0, 0x11dde, 0x11de6, 0x11dec, 0x11dfa, 0x11e0a, 0x11e12, 0x11e14, 0x11e22, 0x11e24, 0x11e28,\n        0x11e36, 0x11e42, 0x11e44, 0x11e50, 0x11e5e, 0x11e66, 0x11e6c, 0x11e82, 0x11e84, 0x11e88, 0x11e90, 0x11e9e,\n        0x11ea0, 0x11ebc, 0x11ec6, 0x11ecc, 0x11ed8, 0x11eee, 0x11f1a, 0x11f2e, 0x11f32, 0x11f34, 0x11f4e, 0x11f5c,\n        0x11f62, 0x11f64, 0x11f68, 0x11f76, 0x12048, 0x1205e, 0x12082, 0x12084, 0x12090, 0x1209e, 0x120a0, 0x120bc,\n        0x120d8, 0x120f2, 0x120f4, 0x12108, 0x1211e, 0x12120, 0x1213c, 0x12140, 0x12178, 0x12186, 0x12198, 0x121b0,\n        0x121be, 0x121e2, 0x121e4, 0x121e8, 0x121f6, 0x12204, 0x12210, 0x1221e, 0x12220, 0x12278, 0x122f0, 0x12306,\n        0x1230c, 0x12330, 0x1233e, 0x12360, 0x1237c, 0x1238e, 0x1239c, 0x123b8, 0x123c2, 0x123c8, 0x123d0, 0x123e6,\n        0x123ec, 0x1241e, 0x12420, 0x1243c, 0x124f0, 0x125e0, 0x12618, 0x1263e, 0x12660, 0x1267c, 0x126c0, 0x126f8,\n        0x12738, 0x12770, 0x1277e, 0x12782, 0x12784, 0x12790, 0x1279e, 0x127a0, 0x127bc, 0x127c6, 0x127cc, 0x127d8,\n        0x127ee, 0x12820, 0x1283c, 0x12840, 0x12878, 0x128f0, 0x129e0, 0x12bc0, 0x12c18, 0x12c30, 0x12c3e, 0x12c60,\n        0x12c7c, 0x12cc0, 0x12cf8, 0x12df0, 0x12e1c, 0x12e38, 0x12e70, 0x12e7e, 0x12ee0, 0x12efc, 0x12f04, 0x12f08,\n        0x12f10, 0x12f20, 0x12f3c, 0x12f40, 0x12f78, 0x12f86, 0x12f8c, 0x12f98, 0x12fb0, 0x12fbe, 0x12fce, 0x12fdc,\n        0x1302e, 0x1304e, 0x1305c, 0x13062, 0x13068, 0x1308e, 0x1309c, 0x130b8, 0x130c2, 0x130c8, 0x130d0, 0x130de,\n        0x130ec, 0x130fa, 0x1310e, 0x13138, 0x13170, 0x1317e, 0x13182, 0x13184, 0x13190, 0x1319e, 0x131a0, 0x131bc,\n        0x131c6, 0x131cc, 0x131d8, 0x131f2, 0x131f4, 0x1320e, 0x1321c, 0x13270, 0x1327e, 0x132e0, 0x132fc, 0x13308,\n        0x1331e, 0x13320, 0x1333c, 0x13340, 0x13378, 0x13386, 0x13398, 0x133b0, 0x133be, 0x133ce, 0x133dc, 0x133e2,\n        0x133e4, 0x133e8, 0x133f6, 0x1340e, 0x1341c, 0x13438, 0x13470, 0x1347e, 0x134e0, 0x134fc, 0x135c0, 0x135f8,\n        0x13608, 0x13610, 0x1361e, 0x13620, 0x1363c, 0x13640, 0x13678, 0x136f0, 0x1370c, 0x13718, 0x13730, 0x1373e,\n        0x13760, 0x1377c, 0x1379c, 0x137b8, 0x137c2, 0x137c4, 0x137c8, 0x137d0, 0x137de, 0x137e6, 0x137ec, 0x13816,\n        0x13826, 0x1382c, 0x13846, 0x1384c, 0x13858, 0x1386e, 0x13874, 0x13886, 0x13898, 0x138b0, 0x138be, 0x138ce,\n        0x138dc, 0x138e2, 0x138e4, 0x138e8, 0x13906, 0x1390c, 0x13930, 0x1393e, 0x13960, 0x1397c, 0x1398e, 0x1399c,\n        0x139b8, 0x139c8, 0x139d0, 0x139de, 0x139e6, 0x139ec, 0x139fa, 0x13a06, 0x13a0c, 0x13a18, 0x13a30, 0x13a3e,\n        0x13a60, 0x13a7c, 0x13ac0, 0x13af8, 0x13b0e, 0x13b1c, 0x13b38, 0x13b70, 0x13b7e, 0x13b88, 0x13b90, 0x13b9e,\n        0x13ba0, 0x13bbc, 0x13bcc, 0x13bd8, 0x13bee, 0x13bf2, 0x13bf4, 0x13c12, 0x13c14, 0x13c22, 0x13c24, 0x13c28,\n        0x13c36, 0x13c42, 0x13c48, 0x13c50, 0x13c5e, 0x13c66, 0x13c6c, 0x13c82, 0x13c84, 0x13c90, 0x13c9e, 0x13ca0,\n        0x13cbc, 0x13cc6, 0x13ccc, 0x13cd8, 0x13cee, 0x13d02, 0x13d04, 0x13d08, 0x13d10, 0x13d1e, 0x13d20, 0x13d3c,\n        0x13d40, 0x13d78, 0x13d86, 0x13d8c, 0x13d98, 0x13db0, 0x13dbe, 0x13dce, 0x13ddc, 0x13de4, 0x13de8, 0x13df6,\n        0x13e1a, 0x13e2e, 0x13e32, 0x13e34, 0x13e4e, 0x13e5c, 0x13e62, 0x13e64, 0x13e68, 0x13e76, 0x13e8e, 0x13e9c,\n        0x13eb8, 0x13ec2, 0x13ec4, 0x13ec8, 0x13ed0, 0x13ede, 0x13ee6, 0x13eec, 0x13f26, 0x13f2c, 0x13f3a, 0x13f46,\n        0x13f4c, 0x13f58, 0x13f6e, 0x13f72, 0x13f74, 0x14082, 0x1409e, 0x140a0, 0x140bc, 0x14104, 0x14108, 0x14110,\n        0x1411e, 0x14120, 0x1413c, 0x14140, 0x14178, 0x1418c, 0x14198, 0x141b0, 0x141be, 0x141e2, 0x141e4, 0x141e8,\n        0x14208, 0x14210, 0x1421e, 0x14220, 0x1423c, 0x14240, 0x14278, 0x142f0, 0x14306, 0x1430c, 0x14318, 0x14330,\n        0x1433e, 0x14360, 0x1437c, 0x1438e, 0x143c2, 0x143c4, 0x143c8, 0x143d0, 0x143e6, 0x143ec, 0x14408, 0x14410,\n        0x1441e, 0x14420, 0x1443c, 0x14440, 0x14478, 0x144f0, 0x145e0, 0x1460c, 0x14618, 0x14630, 0x1463e, 0x14660,\n        0x1467c, 0x146c0, 0x146f8, 0x1471c, 0x14738, 0x14770, 0x1477e, 0x14782, 0x14784, 0x14788, 0x14790, 0x147a0,\n        0x147bc, 0x147c6, 0x147cc, 0x147d8, 0x147ee, 0x14810, 0x14820, 0x1483c, 0x14840, 0x14878, 0x148f0, 0x149e0,\n        0x14bc0, 0x14c30, 0x14c3e, 0x14c60, 0x14c7c, 0x14cc0, 0x14cf8, 0x14df0, 0x14e38, 0x14e70, 0x14e7e, 0x14ee0,\n        0x14efc, 0x14f04, 0x14f08, 0x14f10, 0x14f1e, 0x14f20, 0x14f3c, 0x14f40, 0x14f78, 0x14f86, 0x14f8c, 0x14f98,\n        0x14fb0, 0x14fce, 0x14fdc, 0x15020, 0x15040, 0x15078, 0x150f0, 0x151e0, 0x153c0, 0x15860, 0x1587c, 0x158c0,\n        0x158f8, 0x159f0, 0x15be0, 0x15c70, 0x15c7e, 0x15ce0, 0x15cfc, 0x15dc0, 0x15df8, 0x15e08, 0x15e10, 0x15e20,\n        0x15e40, 0x15e78, 0x15ef0, 0x15f0c, 0x15f18, 0x15f30, 0x15f60, 0x15f7c, 0x15f8e, 0x15f9c, 0x15fb8, 0x1604e,\n        0x1605c, 0x1608e, 0x1609c, 0x160b8, 0x160c2, 0x160c4, 0x160c8, 0x160de, 0x1610e, 0x1611c, 0x16138, 0x16170,\n        0x1617e, 0x16184, 0x16188, 0x16190, 0x1619e, 0x161a0, 0x161bc, 0x161c6, 0x161cc, 0x161d8, 0x161f2, 0x161f4,\n        0x1620e, 0x1621c, 0x16238, 0x16270, 0x1627e, 0x162e0, 0x162fc, 0x16304, 0x16308, 0x16310, 0x1631e, 0x16320,\n        0x1633c, 0x16340, 0x16378, 0x16386, 0x1638c, 0x16398, 0x163b0, 0x163be, 0x163ce, 0x163dc, 0x163e2, 0x163e4,\n        0x163e8, 0x163f6, 0x1640e, 0x1641c, 0x16438, 0x16470, 0x1647e, 0x164e0, 0x164fc, 0x165c0, 0x165f8, 0x16610,\n        0x1661e, 0x16620, 0x1663c, 0x16640, 0x16678, 0x166f0, 0x16718, 0x16730, 0x1673e, 0x16760, 0x1677c, 0x1678e,\n        0x1679c, 0x167b8, 0x167c2, 0x167c4, 0x167c8, 0x167d0, 0x167de, 0x167e6, 0x167ec, 0x1681c, 0x16838, 0x16870,\n        0x168e0, 0x168fc, 0x169c0, 0x169f8, 0x16bf0, 0x16c10, 0x16c1e, 0x16c20, 0x16c3c, 0x16c40, 0x16c78, 0x16cf0,\n        0x16de0, 0x16e18, 0x16e30, 0x16e3e, 0x16e60, 0x16e7c, 0x16ec0, 0x16ef8, 0x16f1c, 0x16f38, 0x16f70, 0x16f7e,\n        0x16f84, 0x16f88, 0x16f90, 0x16f9e, 0x16fa0, 0x16fbc, 0x16fc6, 0x16fcc, 0x16fd8, 0x17026, 0x1702c, 0x17046,\n        0x1704c, 0x17058, 0x1706e, 0x17086, 0x1708c, 0x17098, 0x170b0, 0x170be, 0x170ce, 0x170dc, 0x170e8, 0x17106,\n        0x1710c, 0x17118, 0x17130, 0x1713e, 0x17160, 0x1717c, 0x1718e, 0x1719c, 0x171b8, 0x171c2, 0x171c4, 0x171c8,\n        0x171d0, 0x171de, 0x171e6, 0x171ec, 0x171fa, 0x17206, 0x1720c, 0x17218, 0x17230, 0x1723e, 0x17260, 0x1727c,\n        0x172c0, 0x172f8, 0x1730e, 0x1731c, 0x17338, 0x17370, 0x1737e, 0x17388, 0x17390, 0x1739e, 0x173a0, 0x173bc,\n        0x173cc, 0x173d8, 0x173ee, 0x173f2, 0x173f4, 0x1740c, 0x17418, 0x17430, 0x1743e, 0x17460, 0x1747c, 0x174c0,\n        0x174f8, 0x175f0, 0x1760e, 0x1761c, 0x17638, 0x17670, 0x1767e, 0x176e0, 0x176fc, 0x17708, 0x17710, 0x1771e,\n        0x17720, 0x1773c, 0x17740, 0x17778, 0x17798, 0x177b0, 0x177be, 0x177dc, 0x177e2, 0x177e4, 0x177e8, 0x17822,\n        0x17824, 0x17828, 0x17836, 0x17842, 0x17844, 0x17848, 0x17850, 0x1785e, 0x17866, 0x1786c, 0x17882, 0x17884,\n        0x17888, 0x17890, 0x1789e, 0x178a0, 0x178bc, 0x178c6, 0x178cc, 0x178d8, 0x178ee, 0x178f2, 0x178f4, 0x17902,\n        0x17904, 0x17908, 0x17910, 0x1791e, 0x17920, 0x1793c, 0x17940, 0x17978, 0x17986, 0x1798c, 0x17998, 0x179b0,\n        0x179be, 0x179ce, 0x179dc, 0x179e2, 0x179e4, 0x179e8, 0x179f6, 0x17a04, 0x17a08, 0x17a10, 0x17a1e, 0x17a20,\n        0x17a3c, 0x17a40, 0x17a78, 0x17af0, 0x17b06, 0x17b0c, 0x17b18, 0x17b30, 0x17b3e, 0x17b60, 0x17b7c, 0x17b8e,\n        0x17b9c, 0x17bb8, 0x17bc4, 0x17bc8, 0x17bd0, 0x17bde, 0x17be6, 0x17bec, 0x17c2e, 0x17c32, 0x17c34, 0x17c4e,\n        0x17c5c, 0x17c62, 0x17c64, 0x17c68, 0x17c76, 0x17c8e, 0x17c9c, 0x17cb8, 0x17cc2, 0x17cc4, 0x17cc8, 0x17cd0,\n        0x17cde, 0x17ce6, 0x17cec, 0x17d0e, 0x17d1c, 0x17d38, 0x17d70, 0x17d82, 0x17d84, 0x17d88, 0x17d90, 0x17d9e,\n        0x17da0, 0x17dbc, 0x17dc6, 0x17dcc, 0x17dd8, 0x17dee, 0x17e26, 0x17e2c, 0x17e3a, 0x17e46, 0x17e4c, 0x17e58,\n        0x17e6e, 0x17e72, 0x17e74, 0x17e86, 0x17e8c, 0x17e98, 0x17eb0, 0x17ece, 0x17edc, 0x17ee2, 0x17ee4, 0x17ee8,\n        0x17ef6, 0x1813a, 0x18172, 0x18174, 0x18216, 0x18226, 0x1823a, 0x1824c, 0x18258, 0x1826e, 0x18272, 0x18274,\n        0x18298, 0x182be, 0x182e2, 0x182e4, 0x182e8, 0x182f6, 0x1835e, 0x1837a, 0x183ae, 0x183d6, 0x18416, 0x18426,\n        0x1842c, 0x1843a, 0x18446, 0x18458, 0x1846e, 0x18472, 0x18474, 0x18486, 0x184b0, 0x184be, 0x184ce, 0x184dc,\n        0x184e2, 0x184e4, 0x184e8, 0x184f6, 0x18506, 0x1850c, 0x18518, 0x18530, 0x1853e, 0x18560, 0x1857c, 0x1858e,\n        0x1859c, 0x185b8, 0x185c2, 0x185c4, 0x185c8, 0x185d0, 0x185de, 0x185e6, 0x185ec, 0x185fa, 0x18612, 0x18614,\n        0x18622, 0x18628, 0x18636, 0x18642, 0x18650, 0x1865e, 0x1867a, 0x18682, 0x18684, 0x18688, 0x18690, 0x1869e,\n        0x186a0, 0x186bc, 0x186c6, 0x186cc, 0x186d8, 0x186ee, 0x186f2, 0x186f4, 0x1872e, 0x1874e, 0x1875c, 0x18796,\n        0x187a6, 0x187ac, 0x187d2, 0x187d4, 0x18826, 0x1882c, 0x1883a, 0x18846, 0x1884c, 0x18858, 0x1886e, 0x18872,\n        0x18874, 0x18886, 0x18898, 0x188b0, 0x188be, 0x188ce, 0x188dc, 0x188e2, 0x188e4, 0x188e8, 0x188f6, 0x1890c,\n        0x18930, 0x1893e, 0x18960, 0x1897c, 0x1898e, 0x189b8, 0x189c2, 0x189c8, 0x189d0, 0x189de, 0x189e6, 0x189ec,\n        0x189fa, 0x18a18, 0x18a30, 0x18a3e, 0x18a60, 0x18a7c, 0x18ac0, 0x18af8, 0x18b1c, 0x18b38, 0x18b70, 0x18b7e,\n        0x18b82, 0x18b84, 0x18b88, 0x18b90, 0x18b9e, 0x18ba0, 0x18bbc, 0x18bc6, 0x18bcc, 0x18bd8, 0x18bee, 0x18bf2,\n        0x18bf4, 0x18c22, 0x18c24, 0x18c28, 0x18c36, 0x18c42, 0x18c48, 0x18c50, 0x18c5e, 0x18c66, 0x18c7a, 0x18c82,\n        0x18c84, 0x18c90, 0x18c9e, 0x18ca0, 0x18cbc, 0x18ccc, 0x18cf2, 0x18cf4, 0x18d04, 0x18d08, 0x18d10, 0x18d1e,\n        0x18d20, 0x18d3c, 0x18d40, 0x18d78, 0x18d86, 0x18d98, 0x18dce, 0x18de2, 0x18de4, 0x18de8, 0x18e2e, 0x18e32,\n        0x18e34, 0x18e4e, 0x18e5c, 0x18e62, 0x18e64, 0x18e68, 0x18e8e, 0x18e9c, 0x18eb8, 0x18ec2, 0x18ec4, 0x18ec8,\n        0x18ed0, 0x18efa, 0x18f16, 0x18f26, 0x18f2c, 0x18f46, 0x18f4c, 0x18f58, 0x18f6e, 0x18f8a, 0x18f92, 0x18f94,\n        0x18fa2, 0x18fa4, 0x18fa8, 0x18fb6, 0x1902c, 0x1903a, 0x19046, 0x1904c, 0x19058, 0x19072, 0x19074, 0x19086,\n        0x19098, 0x190b0, 0x190be, 0x190ce, 0x190dc, 0x190e2, 0x190e8, 0x190f6, 0x19106, 0x1910c, 0x19130, 0x1913e,\n        0x19160, 0x1917c, 0x1918e, 0x1919c, 0x191b8, 0x191c2, 0x191c8, 0x191d0, 0x191de, 0x191e6, 0x191ec, 0x191fa,\n        0x19218, 0x1923e, 0x19260, 0x1927c, 0x192c0, 0x192f8, 0x19338, 0x19370, 0x1937e, 0x19382, 0x19384, 0x19390,\n        0x1939e, 0x193a0, 0x193bc, 0x193c6, 0x193cc, 0x193d8, 0x193ee, 0x193f2, 0x193f4, 0x19430, 0x1943e, 0x19460,\n        0x1947c, 0x194c0, 0x194f8, 0x195f0, 0x19638, 0x19670, 0x1967e, 0x196e0, 0x196fc, 0x19702, 0x19704, 0x19708,\n        0x19710, 0x19720, 0x1973c, 0x19740, 0x19778, 0x19786, 0x1978c, 0x19798, 0x197b0, 0x197be, 0x197ce, 0x197dc,\n        0x197e2, 0x197e4, 0x197e8, 0x19822, 0x19824, 0x19842, 0x19848, 0x19850, 0x1985e, 0x19866, 0x1987a, 0x19882,\n        0x19884, 0x19890, 0x1989e, 0x198a0, 0x198bc, 0x198cc, 0x198f2, 0x198f4, 0x19902, 0x19908, 0x1991e, 0x19920,\n        0x1993c, 0x19940, 0x19978, 0x19986, 0x19998, 0x199ce, 0x199e2, 0x199e4, 0x199e8, 0x19a08, 0x19a10, 0x19a1e,\n        0x19a20, 0x19a3c, 0x19a40, 0x19a78, 0x19af0, 0x19b18, 0x19b3e, 0x19b60, 0x19b9c, 0x19bc2, 0x19bc4, 0x19bc8,\n        0x19bd0, 0x19be6, 0x19c2e, 0x19c34, 0x19c4e, 0x19c5c, 0x19c62, 0x19c64, 0x19c68, 0x19c8e, 0x19c9c, 0x19cb8,\n        0x19cc2, 0x19cc8, 0x19cd0, 0x19ce6, 0x19cfa, 0x19d0e, 0x19d1c, 0x19d38, 0x19d70, 0x19d7e, 0x19d82, 0x19d84,\n        0x19d88, 0x19d90, 0x19da0, 0x19dcc, 0x19df2, 0x19df4, 0x19e16, 0x19e26, 0x19e2c, 0x19e46, 0x19e4c, 0x19e58,\n        0x19e74, 0x19e86, 0x19e8c, 0x19e98, 0x19eb0, 0x19ebe, 0x19ece, 0x19ee2, 0x19ee4, 0x19ee8, 0x19f0a, 0x19f12,\n        0x19f14, 0x19f22, 0x19f24, 0x19f28, 0x19f42, 0x19f44, 0x19f48, 0x19f50, 0x19f5e, 0x19f6c, 0x19f9a, 0x19fae,\n        0x19fb2, 0x19fb4, 0x1a046, 0x1a04c, 0x1a072, 0x1a074, 0x1a086, 0x1a08c, 0x1a098, 0x1a0b0, 0x1a0be, 0x1a0e2,\n        0x1a0e4, 0x1a0e8, 0x1a0f6, 0x1a106, 0x1a10c, 0x1a118, 0x1a130, 0x1a13e, 0x1a160, 0x1a17c, 0x1a18e, 0x1a19c,\n        0x1a1b8, 0x1a1c2, 0x1a1c4, 0x1a1c8, 0x1a1d0, 0x1a1de, 0x1a1e6, 0x1a1ec, 0x1a218, 0x1a230, 0x1a23e, 0x1a260,\n        0x1a27c, 0x1a2c0, 0x1a2f8, 0x1a31c, 0x1a338, 0x1a370, 0x1a37e, 0x1a382, 0x1a384, 0x1a388, 0x1a390, 0x1a39e,\n        0x1a3a0, 0x1a3bc, 0x1a3c6, 0x1a3cc, 0x1a3d8, 0x1a3ee, 0x1a3f2, 0x1a3f4, 0x1a418, 0x1a430, 0x1a43e, 0x1a460,\n        0x1a47c, 0x1a4c0, 0x1a4f8, 0x1a5f0, 0x1a61c, 0x1a638, 0x1a670, 0x1a67e, 0x1a6e0, 0x1a6fc, 0x1a702, 0x1a704,\n        0x1a708, 0x1a710, 0x1a71e, 0x1a720, 0x1a73c, 0x1a740, 0x1a778, 0x1a786, 0x1a78c, 0x1a798, 0x1a7b0, 0x1a7be,\n        0x1a7ce, 0x1a7dc, 0x1a7e2, 0x1a7e4, 0x1a7e8, 0x1a830, 0x1a860, 0x1a87c, 0x1a8c0, 0x1a8f8, 0x1a9f0, 0x1abe0,\n        0x1ac70, 0x1ac7e, 0x1ace0, 0x1acfc, 0x1adc0, 0x1adf8, 0x1ae04, 0x1ae08, 0x1ae10, 0x1ae20, 0x1ae3c, 0x1ae40,\n        0x1ae78, 0x1aef0, 0x1af06, 0x1af0c, 0x1af18, 0x1af30, 0x1af3e, 0x1af60, 0x1af7c, 0x1af8e, 0x1af9c, 0x1afb8,\n        0x1afc4, 0x1afc8, 0x1afd0, 0x1afde, 0x1b042, 0x1b05e, 0x1b07a, 0x1b082, 0x1b084, 0x1b088, 0x1b090, 0x1b09e,\n        0x1b0a0, 0x1b0bc, 0x1b0cc, 0x1b0f2, 0x1b0f4, 0x1b102, 0x1b104, 0x1b108, 0x1b110, 0x1b11e, 0x1b120, 0x1b13c,\n        0x1b140, 0x1b178, 0x1b186, 0x1b198, 0x1b1ce, 0x1b1e2, 0x1b1e4, 0x1b1e8, 0x1b204, 0x1b208, 0x1b210, 0x1b21e,\n        0x1b220, 0x1b23c, 0x1b240, 0x1b278, 0x1b2f0, 0x1b30c, 0x1b33e, 0x1b360, 0x1b39c, 0x1b3c2, 0x1b3c4, 0x1b3c8,\n        0x1b3d0, 0x1b3e6, 0x1b410, 0x1b41e, 0x1b420, 0x1b43c, 0x1b440, 0x1b478, 0x1b4f0, 0x1b5e0, 0x1b618, 0x1b660,\n        0x1b67c, 0x1b6c0, 0x1b738, 0x1b782, 0x1b784, 0x1b788, 0x1b790, 0x1b79e, 0x1b7a0, 0x1b7cc, 0x1b82e, 0x1b84e,\n        0x1b85c, 0x1b88e, 0x1b89c, 0x1b8b8, 0x1b8c2, 0x1b8c4, 0x1b8c8, 0x1b8d0, 0x1b8e6, 0x1b8fa, 0x1b90e, 0x1b91c,\n        0x1b938, 0x1b970, 0x1b97e, 0x1b982, 0x1b984, 0x1b988, 0x1b990, 0x1b99e, 0x1b9a0, 0x1b9cc, 0x1b9f2, 0x1b9f4,\n        0x1ba0e, 0x1ba1c, 0x1ba38, 0x1ba70, 0x1ba7e, 0x1bae0, 0x1bafc, 0x1bb08, 0x1bb10, 0x1bb20, 0x1bb3c, 0x1bb40,\n        0x1bb98, 0x1bbce, 0x1bbe2, 0x1bbe4, 0x1bbe8, 0x1bc16, 0x1bc26, 0x1bc2c, 0x1bc46, 0x1bc4c, 0x1bc58, 0x1bc72,\n        0x1bc74, 0x1bc86, 0x1bc8c, 0x1bc98, 0x1bcb0, 0x1bcbe, 0x1bcce, 0x1bce2, 0x1bce4, 0x1bce8, 0x1bd06, 0x1bd0c,\n        0x1bd18, 0x1bd30, 0x1bd3e, 0x1bd60, 0x1bd7c, 0x1bd9c, 0x1bdc2, 0x1bdc4, 0x1bdc8, 0x1bdd0, 0x1bde6, 0x1bdfa,\n        0x1be12, 0x1be14, 0x1be22, 0x1be24, 0x1be28, 0x1be42, 0x1be44, 0x1be48, 0x1be50, 0x1be5e, 0x1be66, 0x1be82,\n        0x1be84, 0x1be88, 0x1be90, 0x1be9e, 0x1bea0, 0x1bebc, 0x1becc, 0x1bef4, 0x1bf1a, 0x1bf2e, 0x1bf32, 0x1bf34,\n        0x1bf4e, 0x1bf5c, 0x1bf62, 0x1bf64, 0x1bf68, 0x1c09a, 0x1c0b2, 0x1c0b4, 0x1c11a, 0x1c132, 0x1c134, 0x1c162,\n        0x1c164, 0x1c168, 0x1c176, 0x1c1ba, 0x1c21a, 0x1c232, 0x1c234, 0x1c24e, 0x1c25c, 0x1c262, 0x1c264, 0x1c268,\n        0x1c276, 0x1c28e, 0x1c2c2, 0x1c2c4, 0x1c2c8, 0x1c2d0, 0x1c2de, 0x1c2e6, 0x1c2ec, 0x1c2fa, 0x1c316, 0x1c326,\n        0x1c33a, 0x1c346, 0x1c34c, 0x1c372, 0x1c374, 0x1c41a, 0x1c42e, 0x1c432, 0x1c434, 0x1c44e, 0x1c45c, 0x1c462,\n        0x1c464, 0x1c468, 0x1c476, 0x1c48e, 0x1c49c, 0x1c4b8, 0x1c4c2, 0x1c4c8, 0x1c4d0, 0x1c4de, 0x1c4e6, 0x1c4ec,\n        0x1c4fa, 0x1c51c, 0x1c538, 0x1c570, 0x1c57e, 0x1c582, 0x1c584, 0x1c588, 0x1c590, 0x1c59e, 0x1c5a0, 0x1c5bc,\n        0x1c5c6, 0x1c5cc, 0x1c5d8, 0x1c5ee, 0x1c5f2, 0x1c5f4, 0x1c616, 0x1c626, 0x1c62c, 0x1c63a, 0x1c646, 0x1c64c,\n        0x1c658, 0x1c66e, 0x1c672, 0x1c674, 0x1c686, 0x1c68c, 0x1c698, 0x1c6b0, 0x1c6be, 0x1c6ce, 0x1c6dc, 0x1c6e2,\n        0x1c6e4, 0x1c6e8, 0x1c712, 0x1c714, 0x1c722, 0x1c728, 0x1c736, 0x1c742, 0x1c744, 0x1c748, 0x1c750, 0x1c75e,\n        0x1c766, 0x1c76c, 0x1c77a, 0x1c7ae, 0x1c7d6, 0x1c7ea, 0x1c81a, 0x1c82e, 0x1c832, 0x1c834, 0x1c84e, 0x1c85c,\n        0x1c862, 0x1c864, 0x1c868, 0x1c876, 0x1c88e, 0x1c89c, 0x1c8b8, 0x1c8c2, 0x1c8c8, 0x1c8d0, 0x1c8de, 0x1c8e6,\n        0x1c8ec, 0x1c8fa, 0x1c90e, 0x1c938, 0x1c970, 0x1c97e, 0x1c982, 0x1c984, 0x1c990, 0x1c99e, 0x1c9a0, 0x1c9bc,\n        0x1c9c6, 0x1c9cc, 0x1c9d8, 0x1c9ee, 0x1c9f2, 0x1c9f4, 0x1ca38, 0x1ca70, 0x1ca7e, 0x1cae0, 0x1cafc, 0x1cb02,\n        0x1cb04, 0x1cb08, 0x1cb10, 0x1cb20, 0x1cb3c, 0x1cb40, 0x1cb78, 0x1cb86, 0x1cb8c, 0x1cb98, 0x1cbb0, 0x1cbbe,\n        0x1cbce, 0x1cbdc, 0x1cbe2, 0x1cbe4, 0x1cbe8, 0x1cbf6, 0x1cc16, 0x1cc26, 0x1cc2c, 0x1cc3a, 0x1cc46, 0x1cc58,\n        0x1cc72, 0x1cc74, 0x1cc86, 0x1ccb0, 0x1ccbe, 0x1ccce, 0x1cce2, 0x1cce4, 0x1cce8, 0x1cd06, 0x1cd0c, 0x1cd18,\n        0x1cd30, 0x1cd3e, 0x1cd60, 0x1cd7c, 0x1cd9c, 0x1cdc2, 0x1cdc4, 0x1cdc8, 0x1cdd0, 0x1cdde, 0x1cde6, 0x1cdfa,\n        0x1ce22, 0x1ce28, 0x1ce42, 0x1ce50, 0x1ce5e, 0x1ce66, 0x1ce7a, 0x1ce82, 0x1ce84, 0x1ce88, 0x1ce90, 0x1ce9e,\n        0x1cea0, 0x1cebc, 0x1cecc, 0x1cef2, 0x1cef4, 0x1cf2e, 0x1cf32, 0x1cf34, 0x1cf4e, 0x1cf5c, 0x1cf62, 0x1cf64,\n        0x1cf68, 0x1cf96, 0x1cfa6, 0x1cfac, 0x1cfca, 0x1cfd2, 0x1cfd4, 0x1d02e, 0x1d032, 0x1d034, 0x1d04e, 0x1d05c,\n        0x1d062, 0x1d064, 0x1d068, 0x1d076, 0x1d08e, 0x1d09c, 0x1d0b8, 0x1d0c2, 0x1d0c4, 0x1d0c8, 0x1d0d0, 0x1d0de,\n        0x1d0e6, 0x1d0ec, 0x1d0fa, 0x1d11c, 0x1d138, 0x1d170, 0x1d17e, 0x1d182, 0x1d184, 0x1d188, 0x1d190, 0x1d19e,\n        0x1d1a0, 0x1d1bc, 0x1d1c6, 0x1d1cc, 0x1d1d8, 0x1d1ee, 0x1d1f2, 0x1d1f4, 0x1d21c, 0x1d238, 0x1d270, 0x1d27e,\n        0x1d2e0, 0x1d2fc, 0x1d302, 0x1d304, 0x1d308, 0x1d310, 0x1d31e, 0x1d320, 0x1d33c, 0x1d340, 0x1d378, 0x1d386,\n        0x1d38c, 0x1d398, 0x1d3b0, 0x1d3be, 0x1d3ce, 0x1d3dc, 0x1d3e2, 0x1d3e4, 0x1d3e8, 0x1d3f6, 0x1d470, 0x1d47e,\n        0x1d4e0, 0x1d4fc, 0x1d5c0, 0x1d5f8, 0x1d604, 0x1d608, 0x1d610, 0x1d620, 0x1d640, 0x1d678, 0x1d6f0, 0x1d706,\n        0x1d70c, 0x1d718, 0x1d730, 0x1d73e, 0x1d760, 0x1d77c, 0x1d78e, 0x1d79c, 0x1d7b8, 0x1d7c2, 0x1d7c4, 0x1d7c8,\n        0x1d7d0, 0x1d7de, 0x1d7e6, 0x1d7ec, 0x1d826, 0x1d82c, 0x1d83a, 0x1d846, 0x1d84c, 0x1d858, 0x1d872, 0x1d874,\n        0x1d886, 0x1d88c, 0x1d898, 0x1d8b0, 0x1d8be, 0x1d8ce, 0x1d8e2, 0x1d8e4, 0x1d8e8, 0x1d8f6, 0x1d90c, 0x1d918,\n        0x1d930, 0x1d93e, 0x1d960, 0x1d97c, 0x1d99c, 0x1d9c2, 0x1d9c4, 0x1d9c8, 0x1d9d0, 0x1d9e6, 0x1d9fa, 0x1da0c,\n        0x1da18, 0x1da30, 0x1da3e, 0x1da60, 0x1da7c, 0x1dac0, 0x1daf8, 0x1db38, 0x1db82, 0x1db84, 0x1db88, 0x1db90,\n        0x1db9e, 0x1dba0, 0x1dbcc, 0x1dbf2, 0x1dbf4, 0x1dc22, 0x1dc42, 0x1dc44, 0x1dc48, 0x1dc50, 0x1dc5e, 0x1dc66,\n        0x1dc7a, 0x1dc82, 0x1dc84, 0x1dc88, 0x1dc90, 0x1dc9e, 0x1dca0, 0x1dcbc, 0x1dccc, 0x1dcf2, 0x1dcf4, 0x1dd04,\n        0x1dd08, 0x1dd10, 0x1dd1e, 0x1dd20, 0x1dd3c, 0x1dd40, 0x1dd78, 0x1dd86, 0x1dd98, 0x1ddce, 0x1dde2, 0x1dde4,\n        0x1dde8, 0x1de2e, 0x1de32, 0x1de34, 0x1de4e, 0x1de5c, 0x1de62, 0x1de64, 0x1de68, 0x1de8e, 0x1de9c, 0x1deb8,\n        0x1dec2, 0x1dec4, 0x1dec8, 0x1ded0, 0x1dee6, 0x1defa, 0x1df16, 0x1df26, 0x1df2c, 0x1df46, 0x1df4c, 0x1df58,\n        0x1df72, 0x1df74, 0x1df8a, 0x1df92, 0x1df94, 0x1dfa2, 0x1dfa4, 0x1dfa8, 0x1e08a, 0x1e092, 0x1e094, 0x1e0a2,\n        0x1e0a4, 0x1e0a8, 0x1e0b6, 0x1e0da, 0x1e10a, 0x1e112, 0x1e114, 0x1e122, 0x1e124, 0x1e128, 0x1e136, 0x1e142,\n        0x1e144, 0x1e148, 0x1e150, 0x1e166, 0x1e16c, 0x1e17a, 0x1e19a, 0x1e1b2, 0x1e1b4, 0x1e20a, 0x1e212, 0x1e214,\n        0x1e222, 0x1e224, 0x1e228, 0x1e236, 0x1e242, 0x1e248, 0x1e250, 0x1e25e, 0x1e266, 0x1e26c, 0x1e27a, 0x1e282,\n        0x1e284, 0x1e288, 0x1e290, 0x1e2a0, 0x1e2bc, 0x1e2c6, 0x1e2cc, 0x1e2d8, 0x1e2ee, 0x1e2f2, 0x1e2f4, 0x1e31a,\n        0x1e332, 0x1e334, 0x1e35c, 0x1e362, 0x1e364, 0x1e368, 0x1e3ba, 0x1e40a, 0x1e412, 0x1e414, 0x1e422, 0x1e428,\n        0x1e436, 0x1e442, 0x1e448, 0x1e450, 0x1e45e, 0x1e466, 0x1e46c, 0x1e47a, 0x1e482, 0x1e484, 0x1e490, 0x1e49e,\n        0x1e4a0, 0x1e4bc, 0x1e4c6, 0x1e4cc, 0x1e4d8, 0x1e4ee, 0x1e4f2, 0x1e4f4, 0x1e502, 0x1e504, 0x1e508, 0x1e510,\n        0x1e51e, 0x1e520, 0x1e53c, 0x1e540, 0x1e578, 0x1e586, 0x1e58c, 0x1e598, 0x1e5b0, 0x1e5be, 0x1e5ce, 0x1e5dc,\n        0x1e5e2, 0x1e5e4, 0x1e5e8, 0x1e5f6, 0x1e61a, 0x1e62e, 0x1e632, 0x1e634, 0x1e64e, 0x1e65c, 0x1e662, 0x1e668,\n        0x1e68e, 0x1e69c, 0x1e6b8, 0x1e6c2, 0x1e6c4, 0x1e6c8, 0x1e6d0, 0x1e6e6, 0x1e6fa, 0x1e716, 0x1e726, 0x1e72c,\n        0x1e73a, 0x1e746, 0x1e74c, 0x1e758, 0x1e772, 0x1e774, 0x1e792, 0x1e794, 0x1e7a2, 0x1e7a4, 0x1e7a8, 0x1e7b6,\n        0x1e812, 0x1e814, 0x1e822, 0x1e824, 0x1e828, 0x1e836, 0x1e842, 0x1e844, 0x1e848, 0x1e850, 0x1e85e, 0x1e866,\n        0x1e86c, 0x1e87a, 0x1e882, 0x1e884, 0x1e888, 0x1e890, 0x1e89e, 0x1e8a0, 0x1e8bc, 0x1e8c6, 0x1e8cc, 0x1e8d8,\n        0x1e8ee, 0x1e8f2, 0x1e8f4, 0x1e902, 0x1e904, 0x1e908, 0x1e910, 0x1e920, 0x1e93c, 0x1e940, 0x1e978, 0x1e986,\n        0x1e98c, 0x1e998, 0x1e9b0, 0x1e9be, 0x1e9ce, 0x1e9dc, 0x1e9e2, 0x1e9e4, 0x1e9e8, 0x1e9f6, 0x1ea04, 0x1ea08,\n        0x1ea10, 0x1ea20, 0x1ea40, 0x1ea78, 0x1eaf0, 0x1eb06, 0x1eb0c, 0x1eb18, 0x1eb30, 0x1eb3e, 0x1eb60, 0x1eb7c,\n        0x1eb8e, 0x1eb9c, 0x1ebb8, 0x1ebc2, 0x1ebc4, 0x1ebc8, 0x1ebd0, 0x1ebde, 0x1ebe6, 0x1ebec, 0x1ec1a, 0x1ec2e,\n        0x1ec32, 0x1ec34, 0x1ec4e, 0x1ec5c, 0x1ec62, 0x1ec64, 0x1ec68, 0x1ec8e, 0x1ec9c, 0x1ecb8, 0x1ecc2, 0x1ecc4,\n        0x1ecc8, 0x1ecd0, 0x1ece6, 0x1ecfa, 0x1ed0e, 0x1ed1c, 0x1ed38, 0x1ed70, 0x1ed7e, 0x1ed82, 0x1ed84, 0x1ed88,\n        0x1ed90, 0x1ed9e, 0x1eda0, 0x1edcc, 0x1edf2, 0x1edf4, 0x1ee16, 0x1ee26, 0x1ee2c, 0x1ee3a, 0x1ee46, 0x1ee4c,\n        0x1ee58, 0x1ee6e, 0x1ee72, 0x1ee74, 0x1ee86, 0x1ee8c, 0x1ee98, 0x1eeb0, 0x1eebe, 0x1eece, 0x1eedc, 0x1eee2,\n        0x1eee4, 0x1eee8, 0x1ef12, 0x1ef22, 0x1ef24, 0x1ef28, 0x1ef36, 0x1ef42, 0x1ef44, 0x1ef48, 0x1ef50, 0x1ef5e,\n        0x1ef66, 0x1ef6c, 0x1ef7a, 0x1efae, 0x1efb2, 0x1efb4, 0x1efd6, 0x1f096, 0x1f0a6, 0x1f0ac, 0x1f0ba, 0x1f0ca,\n        0x1f0d2, 0x1f0d4, 0x1f116, 0x1f126, 0x1f12c, 0x1f13a, 0x1f146, 0x1f14c, 0x1f158, 0x1f16e, 0x1f172, 0x1f174,\n        0x1f18a, 0x1f192, 0x1f194, 0x1f1a2, 0x1f1a4, 0x1f1a8, 0x1f1da, 0x1f216, 0x1f226, 0x1f22c, 0x1f23a, 0x1f246,\n        0x1f258, 0x1f26e, 0x1f272, 0x1f274, 0x1f286, 0x1f28c, 0x1f298, 0x1f2b0, 0x1f2be, 0x1f2ce, 0x1f2dc, 0x1f2e2,\n        0x1f2e4, 0x1f2e8, 0x1f2f6, 0x1f30a, 0x1f312, 0x1f314, 0x1f322, 0x1f328, 0x1f342, 0x1f344, 0x1f348, 0x1f350,\n        0x1f35e, 0x1f366, 0x1f37a, 0x1f39a, 0x1f3ae, 0x1f3b2, 0x1f3b4, 0x1f416, 0x1f426, 0x1f42c, 0x1f43a, 0x1f446,\n        0x1f44c, 0x1f458, 0x1f46e, 0x1f472, 0x1f474, 0x1f486, 0x1f48c, 0x1f498, 0x1f4b0, 0x1f4be, 0x1f4ce, 0x1f4dc,\n        0x1f4e2, 0x1f4e4, 0x1f4e8, 0x1f4f6, 0x1f506, 0x1f50c, 0x1f518, 0x1f530, 0x1f53e, 0x1f560, 0x1f57c, 0x1f58e,\n        0x1f59c, 0x1f5b8, 0x1f5c2, 0x1f5c4, 0x1f5c8, 0x1f5d0, 0x1f5de, 0x1f5e6, 0x1f5ec, 0x1f5fa, 0x1f60a, 0x1f612,\n        0x1f614, 0x1f622, 0x1f624, 0x1f628, 0x1f636, 0x1f642, 0x1f644, 0x1f648, 0x1f650, 0x1f65e, 0x1f666, 0x1f67a,\n        0x1f682, 0x1f684, 0x1f688, 0x1f690, 0x1f69e, 0x1f6a0, 0x1f6bc, 0x1f6cc, 0x1f6f2, 0x1f6f4, 0x1f71a, 0x1f72e,\n        0x1f732, 0x1f734, 0x1f74e, 0x1f75c, 0x1f762, 0x1f764, 0x1f768, 0x1f776, 0x1f796, 0x1f7a6, 0x1f7ac, 0x1f7ba,\n        0x1f7d2, 0x1f7d4, 0x1f89a, 0x1f8ae, 0x1f8b2, 0x1f8b4, 0x1f8d6, 0x1f8ea, 0x1f91a, 0x1f92e, 0x1f932, 0x1f934,\n        0x1f94e, 0x1f95c, 0x1f962, 0x1f964, 0x1f968, 0x1f976, 0x1f996, 0x1f9a6, 0x1f9ac, 0x1f9ba, 0x1f9ca, 0x1f9d2,\n        0x1f9d4, 0x1fa1a, 0x1fa2e, 0x1fa32, 0x1fa34, 0x1fa4e, 0x1fa5c, 0x1fa62, 0x1fa64, 0x1fa68, 0x1fa76, 0x1fa8e,\n        0x1fa9c, 0x1fab8, 0x1fac2, 0x1fac4, 0x1fac8, 0x1fad0, 0x1fade, 0x1fae6, 0x1faec, 0x1fb16, 0x1fb26, 0x1fb2c,\n        0x1fb3a, 0x1fb46, 0x1fb4c, 0x1fb58, 0x1fb6e, 0x1fb72, 0x1fb74, 0x1fb8a, 0x1fb92, 0x1fb94, 0x1fba2, 0x1fba4,\n        0x1fba8, 0x1fbb6, 0x1fbda\n    ]);\n    /**\n     * This table contains to codewords for all symbols.\n     */\n    PDF417Common.CODEWORD_TABLE = Int32Array.from([\n        2627, 1819, 2622, 2621, 1813, 1812, 2729, 2724, 2723, 2779, 2774, 2773, 902, 896, 908, 868, 865, 861, 859, 2511,\n        873, 871, 1780, 835, 2493, 825, 2491, 842, 837, 844, 1764, 1762, 811, 810, 809, 2483, 807, 2482, 806, 2480, 815,\n        814, 813, 812, 2484, 817, 816, 1745, 1744, 1742, 1746, 2655, 2637, 2635, 2626, 2625, 2623, 2628, 1820, 2752,\n        2739, 2737, 2728, 2727, 2725, 2730, 2785, 2783, 2778, 2777, 2775, 2780, 787, 781, 747, 739, 736, 2413, 754, 752,\n        1719, 692, 689, 681, 2371, 678, 2369, 700, 697, 694, 703, 1688, 1686, 642, 638, 2343, 631, 2341, 627, 2338, 651,\n        646, 643, 2345, 654, 652, 1652, 1650, 1647, 1654, 601, 599, 2322, 596, 2321, 594, 2319, 2317, 611, 610, 608, 606,\n        2324, 603, 2323, 615, 614, 612, 1617, 1616, 1614, 1612, 616, 1619, 1618, 2575, 2538, 2536, 905, 901, 898, 909,\n        2509, 2507, 2504, 870, 867, 864, 860, 2512, 875, 872, 1781, 2490, 2489, 2487, 2485, 1748, 836, 834, 832, 830,\n        2494, 827, 2492, 843, 841, 839, 845, 1765, 1763, 2701, 2676, 2674, 2653, 2648, 2656, 2634, 2633, 2631, 2629,\n        1821, 2638, 2636, 2770, 2763, 2761, 2750, 2745, 2753, 2736, 2735, 2733, 2731, 1848, 2740, 2738, 2786, 2784, 591,\n        588, 576, 569, 566, 2296, 1590, 537, 534, 526, 2276, 522, 2274, 545, 542, 539, 548, 1572, 1570, 481, 2245, 466,\n        2242, 462, 2239, 492, 485, 482, 2249, 496, 494, 1534, 1531, 1528, 1538, 413, 2196, 406, 2191, 2188, 425, 419,\n        2202, 415, 2199, 432, 430, 427, 1472, 1467, 1464, 433, 1476, 1474, 368, 367, 2160, 365, 2159, 362, 2157, 2155,\n        2152, 378, 377, 375, 2166, 372, 2165, 369, 2162, 383, 381, 379, 2168, 1419, 1418, 1416, 1414, 385, 1411, 384,\n        1423, 1422, 1420, 1424, 2461, 802, 2441, 2439, 790, 786, 783, 794, 2409, 2406, 2403, 750, 742, 738, 2414, 756,\n        753, 1720, 2367, 2365, 2362, 2359, 1663, 693, 691, 684, 2373, 680, 2370, 702, 699, 696, 704, 1690, 1687, 2337,\n        2336, 2334, 2332, 1624, 2329, 1622, 640, 637, 2344, 634, 2342, 630, 2340, 650, 648, 645, 2346, 655, 653, 1653,\n        1651, 1649, 1655, 2612, 2597, 2595, 2571, 2568, 2565, 2576, 2534, 2529, 2526, 1787, 2540, 2537, 907, 904, 900,\n        910, 2503, 2502, 2500, 2498, 1768, 2495, 1767, 2510, 2508, 2506, 869, 866, 863, 2513, 876, 874, 1782, 2720, 2713,\n        2711, 2697, 2694, 2691, 2702, 2672, 2670, 2664, 1828, 2678, 2675, 2647, 2646, 2644, 2642, 1823, 2639, 1822, 2654,\n        2652, 2650, 2657, 2771, 1855, 2765, 2762, 1850, 1849, 2751, 2749, 2747, 2754, 353, 2148, 344, 342, 336, 2142,\n        332, 2140, 345, 1375, 1373, 306, 2130, 299, 2128, 295, 2125, 319, 314, 311, 2132, 1354, 1352, 1349, 1356, 262,\n        257, 2101, 253, 2096, 2093, 274, 273, 267, 2107, 263, 2104, 280, 278, 275, 1316, 1311, 1308, 1320, 1318, 2052,\n        202, 2050, 2044, 2040, 219, 2063, 212, 2060, 208, 2055, 224, 221, 2066, 1260, 1258, 1252, 231, 1248, 229, 1266,\n        1264, 1261, 1268, 155, 1998, 153, 1996, 1994, 1991, 1988, 165, 164, 2007, 162, 2006, 159, 2003, 2000, 172, 171,\n        169, 2012, 166, 2010, 1186, 1184, 1182, 1179, 175, 1176, 173, 1192, 1191, 1189, 1187, 176, 1194, 1193, 2313,\n        2307, 2305, 592, 589, 2294, 2292, 2289, 578, 572, 568, 2297, 580, 1591, 2272, 2267, 2264, 1547, 538, 536, 529,\n        2278, 525, 2275, 547, 544, 541, 1574, 1571, 2237, 2235, 2229, 1493, 2225, 1489, 478, 2247, 470, 2244, 465, 2241,\n        493, 488, 484, 2250, 498, 495, 1536, 1533, 1530, 1539, 2187, 2186, 2184, 2182, 1432, 2179, 1430, 2176, 1427, 414,\n        412, 2197, 409, 2195, 405, 2193, 2190, 426, 424, 421, 2203, 418, 2201, 431, 429, 1473, 1471, 1469, 1466, 434,\n        1477, 1475, 2478, 2472, 2470, 2459, 2457, 2454, 2462, 803, 2437, 2432, 2429, 1726, 2443, 2440, 792, 789, 785,\n        2401, 2399, 2393, 1702, 2389, 1699, 2411, 2408, 2405, 745, 741, 2415, 758, 755, 1721, 2358, 2357, 2355, 2353,\n        1661, 2350, 1660, 2347, 1657, 2368, 2366, 2364, 2361, 1666, 690, 687, 2374, 683, 2372, 701, 698, 705, 1691, 1689,\n        2619, 2617, 2610, 2608, 2605, 2613, 2593, 2588, 2585, 1803, 2599, 2596, 2563, 2561, 2555, 1797, 2551, 1795, 2573,\n        2570, 2567, 2577, 2525, 2524, 2522, 2520, 1786, 2517, 1785, 2514, 1783, 2535, 2533, 2531, 2528, 1788, 2541, 2539,\n        906, 903, 911, 2721, 1844, 2715, 2712, 1838, 1836, 2699, 2696, 2693, 2703, 1827, 1826, 1824, 2673, 2671, 2669,\n        2666, 1829, 2679, 2677, 1858, 1857, 2772, 1854, 1853, 1851, 1856, 2766, 2764, 143, 1987, 139, 1986, 135, 133,\n        131, 1984, 128, 1983, 125, 1981, 138, 137, 136, 1985, 1133, 1132, 1130, 112, 110, 1974, 107, 1973, 104, 1971,\n        1969, 122, 121, 119, 117, 1977, 114, 1976, 124, 1115, 1114, 1112, 1110, 1117, 1116, 84, 83, 1953, 81, 1952, 78,\n        1950, 1948, 1945, 94, 93, 91, 1959, 88, 1958, 85, 1955, 99, 97, 95, 1961, 1086, 1085, 1083, 1081, 1078, 100,\n        1090, 1089, 1087, 1091, 49, 47, 1917, 44, 1915, 1913, 1910, 1907, 59, 1926, 56, 1925, 53, 1922, 1919, 66, 64,\n        1931, 61, 1929, 1042, 1040, 1038, 71, 1035, 70, 1032, 68, 1048, 1047, 1045, 1043, 1050, 1049, 12, 10, 1869, 1867,\n        1864, 1861, 21, 1880, 19, 1877, 1874, 1871, 28, 1888, 25, 1886, 22, 1883, 982, 980, 977, 974, 32, 30, 991, 989,\n        987, 984, 34, 995, 994, 992, 2151, 2150, 2147, 2146, 2144, 356, 355, 354, 2149, 2139, 2138, 2136, 2134, 1359,\n        343, 341, 338, 2143, 335, 2141, 348, 347, 346, 1376, 1374, 2124, 2123, 2121, 2119, 1326, 2116, 1324, 310, 308,\n        305, 2131, 302, 2129, 298, 2127, 320, 318, 316, 313, 2133, 322, 321, 1355, 1353, 1351, 1357, 2092, 2091, 2089,\n        2087, 1276, 2084, 1274, 2081, 1271, 259, 2102, 256, 2100, 252, 2098, 2095, 272, 269, 2108, 266, 2106, 281, 279,\n        277, 1317, 1315, 1313, 1310, 282, 1321, 1319, 2039, 2037, 2035, 2032, 1203, 2029, 1200, 1197, 207, 2053, 205,\n        2051, 201, 2049, 2046, 2043, 220, 218, 2064, 215, 2062, 211, 2059, 228, 226, 223, 2069, 1259, 1257, 1254, 232,\n        1251, 230, 1267, 1265, 1263, 2316, 2315, 2312, 2311, 2309, 2314, 2304, 2303, 2301, 2299, 1593, 2308, 2306, 590,\n        2288, 2287, 2285, 2283, 1578, 2280, 1577, 2295, 2293, 2291, 579, 577, 574, 571, 2298, 582, 581, 1592, 2263, 2262,\n        2260, 2258, 1545, 2255, 1544, 2252, 1541, 2273, 2271, 2269, 2266, 1550, 535, 532, 2279, 528, 2277, 546, 543, 549,\n        1575, 1573, 2224, 2222, 2220, 1486, 2217, 1485, 2214, 1482, 1479, 2238, 2236, 2234, 2231, 1496, 2228, 1492, 480,\n        477, 2248, 473, 2246, 469, 2243, 490, 487, 2251, 497, 1537, 1535, 1532, 2477, 2476, 2474, 2479, 2469, 2468, 2466,\n        2464, 1730, 2473, 2471, 2453, 2452, 2450, 2448, 1729, 2445, 1728, 2460, 2458, 2456, 2463, 805, 804, 2428, 2427,\n        2425, 2423, 1725, 2420, 1724, 2417, 1722, 2438, 2436, 2434, 2431, 1727, 2444, 2442, 793, 791, 788, 795, 2388,\n        2386, 2384, 1697, 2381, 1696, 2378, 1694, 1692, 2402, 2400, 2398, 2395, 1703, 2392, 1701, 2412, 2410, 2407, 751,\n        748, 744, 2416, 759, 757, 1807, 2620, 2618, 1806, 1805, 2611, 2609, 2607, 2614, 1802, 1801, 1799, 2594, 2592,\n        2590, 2587, 1804, 2600, 2598, 1794, 1793, 1791, 1789, 2564, 2562, 2560, 2557, 1798, 2554, 1796, 2574, 2572, 2569,\n        2578, 1847, 1846, 2722, 1843, 1842, 1840, 1845, 2716, 2714, 1835, 1834, 1832, 1830, 1839, 1837, 2700, 2698, 2695,\n        2704, 1817, 1811, 1810, 897, 862, 1777, 829, 826, 838, 1760, 1758, 808, 2481, 1741, 1740, 1738, 1743, 2624, 1818,\n        2726, 2776, 782, 740, 737, 1715, 686, 679, 695, 1682, 1680, 639, 628, 2339, 647, 644, 1645, 1643, 1640, 1648,\n        602, 600, 597, 595, 2320, 593, 2318, 609, 607, 604, 1611, 1610, 1608, 1606, 613, 1615, 1613, 2328, 926, 924, 892,\n        886, 899, 857, 850, 2505, 1778, 824, 823, 821, 819, 2488, 818, 2486, 833, 831, 828, 840, 1761, 1759, 2649, 2632,\n        2630, 2746, 2734, 2732, 2782, 2781, 570, 567, 1587, 531, 527, 523, 540, 1566, 1564, 476, 467, 463, 2240, 486,\n        483, 1524, 1521, 1518, 1529, 411, 403, 2192, 399, 2189, 423, 416, 1462, 1457, 1454, 428, 1468, 1465, 2210, 366,\n        363, 2158, 360, 2156, 357, 2153, 376, 373, 370, 2163, 1410, 1409, 1407, 1405, 382, 1402, 380, 1417, 1415, 1412,\n        1421, 2175, 2174, 777, 774, 771, 784, 732, 725, 722, 2404, 743, 1716, 676, 674, 668, 2363, 665, 2360, 685, 1684,\n        1681, 626, 624, 622, 2335, 620, 2333, 617, 2330, 641, 635, 649, 1646, 1644, 1642, 2566, 928, 925, 2530, 2527,\n        894, 891, 888, 2501, 2499, 2496, 858, 856, 854, 851, 1779, 2692, 2668, 2665, 2645, 2643, 2640, 2651, 2768, 2759,\n        2757, 2744, 2743, 2741, 2748, 352, 1382, 340, 337, 333, 1371, 1369, 307, 300, 296, 2126, 315, 312, 1347, 1342,\n        1350, 261, 258, 250, 2097, 246, 2094, 271, 268, 264, 1306, 1301, 1298, 276, 1312, 1309, 2115, 203, 2048, 195,\n        2045, 191, 2041, 213, 209, 2056, 1246, 1244, 1238, 225, 1234, 222, 1256, 1253, 1249, 1262, 2080, 2079, 154, 1997,\n        150, 1995, 147, 1992, 1989, 163, 160, 2004, 156, 2001, 1175, 1174, 1172, 1170, 1167, 170, 1164, 167, 1185, 1183,\n        1180, 1177, 174, 1190, 1188, 2025, 2024, 2022, 587, 586, 564, 559, 556, 2290, 573, 1588, 520, 518, 512, 2268,\n        508, 2265, 530, 1568, 1565, 461, 457, 2233, 450, 2230, 446, 2226, 479, 471, 489, 1526, 1523, 1520, 397, 395,\n        2185, 392, 2183, 389, 2180, 2177, 410, 2194, 402, 422, 1463, 1461, 1459, 1456, 1470, 2455, 799, 2433, 2430, 779,\n        776, 773, 2397, 2394, 2390, 734, 728, 724, 746, 1717, 2356, 2354, 2351, 2348, 1658, 677, 675, 673, 670, 667, 688,\n        1685, 1683, 2606, 2589, 2586, 2559, 2556, 2552, 927, 2523, 2521, 2518, 2515, 1784, 2532, 895, 893, 890, 2718,\n        2709, 2707, 2689, 2687, 2684, 2663, 2662, 2660, 2658, 1825, 2667, 2769, 1852, 2760, 2758, 142, 141, 1139, 1138,\n        134, 132, 129, 126, 1982, 1129, 1128, 1126, 1131, 113, 111, 108, 105, 1972, 101, 1970, 120, 118, 115, 1109, 1108,\n        1106, 1104, 123, 1113, 1111, 82, 79, 1951, 75, 1949, 72, 1946, 92, 89, 86, 1956, 1077, 1076, 1074, 1072, 98,\n        1069, 96, 1084, 1082, 1079, 1088, 1968, 1967, 48, 45, 1916, 42, 1914, 39, 1911, 1908, 60, 57, 54, 1923, 50, 1920,\n        1031, 1030, 1028, 1026, 67, 1023, 65, 1020, 62, 1041, 1039, 1036, 1033, 69, 1046, 1044, 1944, 1943, 1941, 11, 9,\n        1868, 7, 1865, 1862, 1859, 20, 1878, 16, 1875, 13, 1872, 970, 968, 966, 963, 29, 960, 26, 23, 983, 981, 978, 975,\n        33, 971, 31, 990, 988, 985, 1906, 1904, 1902, 993, 351, 2145, 1383, 331, 330, 328, 326, 2137, 323, 2135, 339,\n        1372, 1370, 294, 293, 291, 289, 2122, 286, 2120, 283, 2117, 309, 303, 317, 1348, 1346, 1344, 245, 244, 242, 2090,\n        239, 2088, 236, 2085, 2082, 260, 2099, 249, 270, 1307, 1305, 1303, 1300, 1314, 189, 2038, 186, 2036, 183, 2033,\n        2030, 2026, 206, 198, 2047, 194, 216, 1247, 1245, 1243, 1240, 227, 1237, 1255, 2310, 2302, 2300, 2286, 2284,\n        2281, 565, 563, 561, 558, 575, 1589, 2261, 2259, 2256, 2253, 1542, 521, 519, 517, 514, 2270, 511, 533, 1569,\n        1567, 2223, 2221, 2218, 2215, 1483, 2211, 1480, 459, 456, 453, 2232, 449, 474, 491, 1527, 1525, 1522, 2475, 2467,\n        2465, 2451, 2449, 2446, 801, 800, 2426, 2424, 2421, 2418, 1723, 2435, 780, 778, 775, 2387, 2385, 2382, 2379,\n        1695, 2375, 1693, 2396, 735, 733, 730, 727, 749, 1718, 2616, 2615, 2604, 2603, 2601, 2584, 2583, 2581, 2579,\n        1800, 2591, 2550, 2549, 2547, 2545, 1792, 2542, 1790, 2558, 929, 2719, 1841, 2710, 2708, 1833, 1831, 2690, 2688,\n        2686, 1815, 1809, 1808, 1774, 1756, 1754, 1737, 1736, 1734, 1739, 1816, 1711, 1676, 1674, 633, 629, 1638, 1636,\n        1633, 1641, 598, 1605, 1604, 1602, 1600, 605, 1609, 1607, 2327, 887, 853, 1775, 822, 820, 1757, 1755, 1584, 524,\n        1560, 1558, 468, 464, 1514, 1511, 1508, 1519, 408, 404, 400, 1452, 1447, 1444, 417, 1458, 1455, 2208, 364, 361,\n        358, 2154, 1401, 1400, 1398, 1396, 374, 1393, 371, 1408, 1406, 1403, 1413, 2173, 2172, 772, 726, 723, 1712, 672,\n        669, 666, 682, 1678, 1675, 625, 623, 621, 618, 2331, 636, 632, 1639, 1637, 1635, 920, 918, 884, 880, 889, 849,\n        848, 847, 846, 2497, 855, 852, 1776, 2641, 2742, 2787, 1380, 334, 1367, 1365, 301, 297, 1340, 1338, 1335, 1343,\n        255, 251, 247, 1296, 1291, 1288, 265, 1302, 1299, 2113, 204, 196, 192, 2042, 1232, 1230, 1224, 214, 1220, 210,\n        1242, 1239, 1235, 1250, 2077, 2075, 151, 148, 1993, 144, 1990, 1163, 1162, 1160, 1158, 1155, 161, 1152, 157,\n        1173, 1171, 1168, 1165, 168, 1181, 1178, 2021, 2020, 2018, 2023, 585, 560, 557, 1585, 516, 509, 1562, 1559, 458,\n        447, 2227, 472, 1516, 1513, 1510, 398, 396, 393, 390, 2181, 386, 2178, 407, 1453, 1451, 1449, 1446, 420, 1460,\n        2209, 769, 764, 720, 712, 2391, 729, 1713, 664, 663, 661, 659, 2352, 656, 2349, 671, 1679, 1677, 2553, 922, 919,\n        2519, 2516, 885, 883, 881, 2685, 2661, 2659, 2767, 2756, 2755, 140, 1137, 1136, 130, 127, 1125, 1124, 1122, 1127,\n        109, 106, 102, 1103, 1102, 1100, 1098, 116, 1107, 1105, 1980, 80, 76, 73, 1947, 1068, 1067, 1065, 1063, 90, 1060,\n        87, 1075, 1073, 1070, 1080, 1966, 1965, 46, 43, 40, 1912, 36, 1909, 1019, 1018, 1016, 1014, 58, 1011, 55, 1008,\n        51, 1029, 1027, 1024, 1021, 63, 1037, 1034, 1940, 1939, 1937, 1942, 8, 1866, 4, 1863, 1, 1860, 956, 954, 952,\n        949, 946, 17, 14, 969, 967, 964, 961, 27, 957, 24, 979, 976, 972, 1901, 1900, 1898, 1896, 986, 1905, 1903, 350,\n        349, 1381, 329, 327, 324, 1368, 1366, 292, 290, 287, 284, 2118, 304, 1341, 1339, 1337, 1345, 243, 240, 237, 2086,\n        233, 2083, 254, 1297, 1295, 1293, 1290, 1304, 2114, 190, 187, 184, 2034, 180, 2031, 177, 2027, 199, 1233, 1231,\n        1229, 1226, 217, 1223, 1241, 2078, 2076, 584, 555, 554, 552, 550, 2282, 562, 1586, 507, 506, 504, 502, 2257, 499,\n        2254, 515, 1563, 1561, 445, 443, 441, 2219, 438, 2216, 435, 2212, 460, 454, 475, 1517, 1515, 1512, 2447, 798,\n        797, 2422, 2419, 770, 768, 766, 2383, 2380, 2376, 721, 719, 717, 714, 731, 1714, 2602, 2582, 2580, 2548, 2546,\n        2543, 923, 921, 2717, 2706, 2705, 2683, 2682, 2680, 1771, 1752, 1750, 1733, 1732, 1731, 1735, 1814, 1707, 1670,\n        1668, 1631, 1629, 1626, 1634, 1599, 1598, 1596, 1594, 1603, 1601, 2326, 1772, 1753, 1751, 1581, 1554, 1552, 1504,\n        1501, 1498, 1509, 1442, 1437, 1434, 401, 1448, 1445, 2206, 1392, 1391, 1389, 1387, 1384, 359, 1399, 1397, 1394,\n        1404, 2171, 2170, 1708, 1672, 1669, 619, 1632, 1630, 1628, 1773, 1378, 1363, 1361, 1333, 1328, 1336, 1286, 1281,\n        1278, 248, 1292, 1289, 2111, 1218, 1216, 1210, 197, 1206, 193, 1228, 1225, 1221, 1236, 2073, 2071, 1151, 1150,\n        1148, 1146, 152, 1143, 149, 1140, 145, 1161, 1159, 1156, 1153, 158, 1169, 1166, 2017, 2016, 2014, 2019, 1582,\n        510, 1556, 1553, 452, 448, 1506, 1500, 394, 391, 387, 1443, 1441, 1439, 1436, 1450, 2207, 765, 716, 713, 1709,\n        662, 660, 657, 1673, 1671, 916, 914, 879, 878, 877, 882, 1135, 1134, 1121, 1120, 1118, 1123, 1097, 1096, 1094,\n        1092, 103, 1101, 1099, 1979, 1059, 1058, 1056, 1054, 77, 1051, 74, 1066, 1064, 1061, 1071, 1964, 1963, 1007,\n        1006, 1004, 1002, 999, 41, 996, 37, 1017, 1015, 1012, 1009, 52, 1025, 1022, 1936, 1935, 1933, 1938, 942, 940,\n        938, 935, 932, 5, 2, 955, 953, 950, 947, 18, 943, 15, 965, 962, 958, 1895, 1894, 1892, 1890, 973, 1899, 1897,\n        1379, 325, 1364, 1362, 288, 285, 1334, 1332, 1330, 241, 238, 234, 1287, 1285, 1283, 1280, 1294, 2112, 188, 185,\n        181, 178, 2028, 1219, 1217, 1215, 1212, 200, 1209, 1227, 2074, 2072, 583, 553, 551, 1583, 505, 503, 500, 513,\n        1557, 1555, 444, 442, 439, 436, 2213, 455, 451, 1507, 1505, 1502, 796, 763, 762, 760, 767, 711, 710, 708, 706,\n        2377, 718, 715, 1710, 2544, 917, 915, 2681, 1627, 1597, 1595, 2325, 1769, 1749, 1747, 1499, 1438, 1435, 2204,\n        1390, 1388, 1385, 1395, 2169, 2167, 1704, 1665, 1662, 1625, 1623, 1620, 1770, 1329, 1282, 1279, 2109, 1214, 1207,\n        1222, 2068, 2065, 1149, 1147, 1144, 1141, 146, 1157, 1154, 2013, 2011, 2008, 2015, 1579, 1549, 1546, 1495, 1487,\n        1433, 1431, 1428, 1425, 388, 1440, 2205, 1705, 658, 1667, 1664, 1119, 1095, 1093, 1978, 1057, 1055, 1052, 1062,\n        1962, 1960, 1005, 1003, 1000, 997, 38, 1013, 1010, 1932, 1930, 1927, 1934, 941, 939, 936, 933, 6, 930, 3, 951,\n        948, 944, 1889, 1887, 1884, 1881, 959, 1893, 1891, 35, 1377, 1360, 1358, 1327, 1325, 1322, 1331, 1277, 1275,\n        1272, 1269, 235, 1284, 2110, 1205, 1204, 1201, 1198, 182, 1195, 179, 1213, 2070, 2067, 1580, 501, 1551, 1548,\n        440, 437, 1497, 1494, 1490, 1503, 761, 709, 707, 1706, 913, 912, 2198, 1386, 2164, 2161, 1621, 1766, 2103, 1208,\n        2058, 2054, 1145, 1142, 2005, 2002, 1999, 2009, 1488, 1429, 1426, 2200, 1698, 1659, 1656, 1975, 1053, 1957, 1954,\n        1001, 998, 1924, 1921, 1918, 1928, 937, 934, 931, 1879, 1876, 1873, 1870, 945, 1885, 1882, 1323, 1273, 1270,\n        2105, 1202, 1199, 1196, 1211, 2061, 2057, 1576, 1543, 1540, 1484, 1481, 1478, 1491, 1700\n    ]);\n\n    /*\n    * Copyright 2007 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    // import java.util.List;\n    /**\n     * @author Guenther Grau\n     */\n    /*public final*/ class PDF417DetectorResult {\n        constructor(bits, points) {\n            this.bits = bits;\n            this.points = points;\n        }\n        getBits() {\n            return this.bits;\n        }\n        getPoints() {\n            return this.points;\n        }\n    }\n\n    /*\n    * Copyright 2009 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    // import java.util.ArrayList;\n    // import java.util.Arrays;\n    // import java.util.List;\n    // import java.util.Map;\n    /**\n     * <p>Encapsulates logic that can detect a PDF417 Code in an image, even if the\n     * PDF417 Code is rotated or skewed, or partially obscured.</p>\n     *\n     * @author SITA Lab (kevin.osullivan@sita.aero)\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @author Guenther Grau\n     */\n    /*public*/ /*final*/ class Detector$3 {\n        /**\n         * <p>Detects a PDF417 Code in an image. Only checks 0 and 180 degree rotations.</p>\n         *\n         * @param image barcode image to decode\n         * @param hints optional hints to detector\n         * @param multiple if true, then the image is searched for multiple codes. If false, then at most one code will\n         * be found and returned\n         * @return {@link PDF417DetectorResult} encapsulating results of detecting a PDF417 code\n         * @throws NotFoundException if no PDF417 Code can be found\n         */\n        static detectMultiple(image, hints, multiple) {\n            // TODO detection improvement, tryHarder could try several different luminance thresholds/blackpoints or even\n            // different binarizers\n            // boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);\n            let bitMatrix = image.getBlackMatrix();\n            let barcodeCoordinates = Detector$3.detect(multiple, bitMatrix);\n            if (!barcodeCoordinates.length) {\n                bitMatrix = bitMatrix.clone();\n                bitMatrix.rotate180();\n                barcodeCoordinates = Detector$3.detect(multiple, bitMatrix);\n            }\n            return new PDF417DetectorResult(bitMatrix, barcodeCoordinates);\n        }\n        /**\n         * Detects PDF417 codes in an image. Only checks 0 degree rotation\n         * @param multiple if true, then the image is searched for multiple codes. If false, then at most one code will\n         * be found and returned\n         * @param bitMatrix bit matrix to detect barcodes in\n         * @return List of ResultPoint arrays containing the coordinates of found barcodes\n         */\n        static detect(multiple, bitMatrix) {\n            const barcodeCoordinates = new Array();\n            let row = 0;\n            let column = 0;\n            let foundBarcodeInRow = false;\n            while (row < bitMatrix.getHeight()) {\n                const vertices = Detector$3.findVertices(bitMatrix, row, column);\n                if (vertices[0] == null && vertices[3] == null) {\n                    if (!foundBarcodeInRow) {\n                        // we didn't find any barcode so that's the end of searching\n                        break;\n                    }\n                    // we didn't find a barcode starting at the given column and row. Try again from the first column and slightly\n                    // below the lowest barcode we found so far.\n                    foundBarcodeInRow = false;\n                    column = 0;\n                    for (const barcodeCoordinate of barcodeCoordinates) {\n                        if (barcodeCoordinate[1] != null) {\n                            row = Math.trunc(Math.max(row, barcodeCoordinate[1].getY()));\n                        }\n                        if (barcodeCoordinate[3] != null) {\n                            row = Math.max(row, Math.trunc(barcodeCoordinate[3].getY()));\n                        }\n                    }\n                    row += Detector$3.ROW_STEP;\n                    continue;\n                }\n                foundBarcodeInRow = true;\n                barcodeCoordinates.push(vertices);\n                if (!multiple) {\n                    break;\n                }\n                // if we didn't find a right row indicator column, then continue the search for the next barcode after the\n                // start pattern of the barcode just found.\n                if (vertices[2] != null) {\n                    column = Math.trunc(vertices[2].getX());\n                    row = Math.trunc(vertices[2].getY());\n                }\n                else {\n                    column = Math.trunc(vertices[4].getX());\n                    row = Math.trunc(vertices[4].getY());\n                }\n            }\n            return barcodeCoordinates;\n        }\n        /**\n         * Locate the vertices and the codewords area of a black blob using the Start\n         * and Stop patterns as locators.\n         *\n         * @param matrix the scanned barcode image.\n         * @return an array containing the vertices:\n         *           vertices[0] x, y top left barcode\n         *           vertices[1] x, y bottom left barcode\n         *           vertices[2] x, y top right barcode\n         *           vertices[3] x, y bottom right barcode\n         *           vertices[4] x, y top left codeword area\n         *           vertices[5] x, y bottom left codeword area\n         *           vertices[6] x, y top right codeword area\n         *           vertices[7] x, y bottom right codeword area\n         */\n        static findVertices(matrix, startRow, startColumn) {\n            const height = matrix.getHeight();\n            const width = matrix.getWidth();\n            // const result = new ResultPoint[8];\n            const result = new Array(8);\n            Detector$3.copyToResult(result, Detector$3.findRowsWithPattern(matrix, height, width, startRow, startColumn, Detector$3.START_PATTERN), Detector$3.INDEXES_START_PATTERN);\n            if (result[4] != null) {\n                startColumn = Math.trunc(result[4].getX());\n                startRow = Math.trunc(result[4].getY());\n            }\n            Detector$3.copyToResult(result, Detector$3.findRowsWithPattern(matrix, height, width, startRow, startColumn, Detector$3.STOP_PATTERN), Detector$3.INDEXES_STOP_PATTERN);\n            return result;\n        }\n        static copyToResult(result, tmpResult, destinationIndexes) {\n            for (let i = 0; i < destinationIndexes.length; i++) {\n                result[destinationIndexes[i]] = tmpResult[i];\n            }\n        }\n        static findRowsWithPattern(matrix, height, width, startRow, startColumn, pattern) {\n            // const result = new ResultPoint[4];\n            const result = new Array(4);\n            let found = false;\n            const counters = new Int32Array(pattern.length);\n            for (; startRow < height; startRow += Detector$3.ROW_STEP) {\n                let loc = Detector$3.findGuardPattern(matrix, startColumn, startRow, width, false, pattern, counters);\n                if (loc != null) {\n                    while (startRow > 0) {\n                        const previousRowLoc = Detector$3.findGuardPattern(matrix, startColumn, --startRow, width, false, pattern, counters);\n                        if (previousRowLoc != null) {\n                            loc = previousRowLoc;\n                        }\n                        else {\n                            startRow++;\n                            break;\n                        }\n                    }\n                    result[0] = new ResultPoint(loc[0], startRow);\n                    result[1] = new ResultPoint(loc[1], startRow);\n                    found = true;\n                    break;\n                }\n            }\n            let stopRow = startRow + 1;\n            // Last row of the current symbol that contains pattern\n            if (found) {\n                let skippedRowCount = 0;\n                let previousRowLoc = Int32Array.from([Math.trunc(result[0].getX()), Math.trunc(result[1].getX())]);\n                for (; stopRow < height; stopRow++) {\n                    const loc = Detector$3.findGuardPattern(matrix, previousRowLoc[0], stopRow, width, false, pattern, counters);\n                    // a found pattern is only considered to belong to the same barcode if the start and end positions\n                    // don't differ too much. Pattern drift should be not bigger than two for consecutive rows. With\n                    // a higher number of skipped rows drift could be larger. To keep it simple for now, we allow a slightly\n                    // larger drift and don't check for skipped rows.\n                    if (loc != null &&\n                        Math.abs(previousRowLoc[0] - loc[0]) < Detector$3.MAX_PATTERN_DRIFT &&\n                        Math.abs(previousRowLoc[1] - loc[1]) < Detector$3.MAX_PATTERN_DRIFT) {\n                        previousRowLoc = loc;\n                        skippedRowCount = 0;\n                    }\n                    else {\n                        if (skippedRowCount > Detector$3.SKIPPED_ROW_COUNT_MAX) {\n                            break;\n                        }\n                        else {\n                            skippedRowCount++;\n                        }\n                    }\n                }\n                stopRow -= skippedRowCount + 1;\n                result[2] = new ResultPoint(previousRowLoc[0], stopRow);\n                result[3] = new ResultPoint(previousRowLoc[1], stopRow);\n            }\n            if (stopRow - startRow < Detector$3.BARCODE_MIN_HEIGHT) {\n                Arrays.fill(result, null);\n            }\n            return result;\n        }\n        /**\n         * @param matrix row of black/white values to search\n         * @param column x position to start search\n         * @param row y position to start search\n         * @param width the number of pixels to search on this row\n         * @param pattern pattern of counts of number of black and white pixels that are\n         *                 being searched for as a pattern\n         * @param counters array of counters, as long as pattern, to re-use\n         * @return start/end horizontal offset of guard pattern, as an array of two ints.\n         */\n        static findGuardPattern(matrix, column, row, width, whiteFirst, pattern, counters) {\n            Arrays.fillWithin(counters, 0, counters.length, 0);\n            let patternStart = column;\n            let pixelDrift = 0;\n            // if there are black pixels left of the current pixel shift to the left, but only for MAX_PIXEL_DRIFT pixels\n            while (matrix.get(patternStart, row) && patternStart > 0 && pixelDrift++ < Detector$3.MAX_PIXEL_DRIFT) {\n                patternStart--;\n            }\n            let x = patternStart;\n            let counterPosition = 0;\n            let patternLength = pattern.length;\n            for (let isWhite = whiteFirst; x < width; x++) {\n                let pixel = matrix.get(x, row);\n                if (pixel !== isWhite) {\n                    counters[counterPosition]++;\n                }\n                else {\n                    if (counterPosition === patternLength - 1) {\n                        if (Detector$3.patternMatchVariance(counters, pattern, Detector$3.MAX_INDIVIDUAL_VARIANCE) < Detector$3.MAX_AVG_VARIANCE) {\n                            return new Int32Array([patternStart, x]);\n                        }\n                        patternStart += counters[0] + counters[1];\n                        System.arraycopy(counters, 2, counters, 0, counterPosition - 1);\n                        counters[counterPosition - 1] = 0;\n                        counters[counterPosition] = 0;\n                        counterPosition--;\n                    }\n                    else {\n                        counterPosition++;\n                    }\n                    counters[counterPosition] = 1;\n                    isWhite = !isWhite;\n                }\n            }\n            if (counterPosition === patternLength - 1 &&\n                Detector$3.patternMatchVariance(counters, pattern, Detector$3.MAX_INDIVIDUAL_VARIANCE) < Detector$3.MAX_AVG_VARIANCE) {\n                return new Int32Array([patternStart, x - 1]);\n            }\n            return null;\n        }\n        /**\n         * Determines how closely a set of observed counts of runs of black/white\n         * values matches a given target pattern. This is reported as the ratio of\n         * the total variance from the expected pattern proportions across all\n         * pattern elements, to the length of the pattern.\n         *\n         * @param counters observed counters\n         * @param pattern expected pattern\n         * @param maxIndividualVariance The most any counter can differ before we give up\n         * @return ratio of total variance between counters and pattern compared to total pattern size\n         */\n        static patternMatchVariance(counters, pattern, maxIndividualVariance) {\n            let numCounters = counters.length;\n            let total = 0;\n            let patternLength = 0;\n            for (let i = 0; i < numCounters; i++) {\n                total += counters[i];\n                patternLength += pattern[i];\n            }\n            if (total < patternLength) {\n                // If we don't even have one pixel per unit of bar width, assume this\n                // is too small to reliably match, so fail:\n                return /*Float.POSITIVE_INFINITY*/ Infinity;\n            }\n            // We're going to fake floating-point math in integers. We just need to use more bits.\n            // Scale up patternLength so that intermediate values below like scaledCounter will have\n            // more \"significant digits\".\n            let unitBarWidth = total / patternLength;\n            maxIndividualVariance *= unitBarWidth;\n            let totalVariance = 0.0;\n            for (let x = 0; x < numCounters; x++) {\n                let counter = counters[x];\n                let scaledPattern = pattern[x] * unitBarWidth;\n                let variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter;\n                if (variance > maxIndividualVariance) {\n                    return /*Float.POSITIVE_INFINITY*/ Infinity;\n                }\n                totalVariance += variance;\n            }\n            return totalVariance / total;\n        }\n    }\n    Detector$3.INDEXES_START_PATTERN = Int32Array.from([0, 4, 1, 5]);\n    Detector$3.INDEXES_STOP_PATTERN = Int32Array.from([6, 2, 7, 3]);\n    Detector$3.MAX_AVG_VARIANCE = 0.42;\n    Detector$3.MAX_INDIVIDUAL_VARIANCE = 0.8;\n    // B S B S B S B S Bar/Space pattern\n    // 11111111 0 1 0 1 0 1 000\n    Detector$3.START_PATTERN = Int32Array.from([8, 1, 1, 1, 1, 1, 1, 3]);\n    // 1111111 0 1 000 1 0 1 00 1\n    Detector$3.STOP_PATTERN = Int32Array.from([7, 1, 1, 3, 1, 1, 1, 2, 1]);\n    Detector$3.MAX_PIXEL_DRIFT = 3;\n    Detector$3.MAX_PATTERN_DRIFT = 5;\n    // if we set the value too low, then we don't detect the correct height of the bar if the start patterns are damaged.\n    // if we set the value too high, then we might detect the start pattern from a neighbor barcode.\n    Detector$3.SKIPPED_ROW_COUNT_MAX = 25;\n    // A PDF471 barcode should have at least 3 rows, with each row being >= 3 times the module width. Therefore it should be at least\n    // 9 pixels tall. To be conservative, we use about half the size to ensure we don't miss it.\n    Detector$3.ROW_STEP = 5;\n    Detector$3.BARCODE_MIN_HEIGHT = 10;\n\n    /*\n    * Copyright 2012 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /**\n     * @author Sean Owen\n     * @see com.google.zxing.common.reedsolomon.GenericGFPoly\n     */\n    /*final*/ class ModulusPoly {\n        constructor(field, coefficients) {\n            if (coefficients.length === 0) {\n                throw new IllegalArgumentException();\n            }\n            this.field = field;\n            let coefficientsLength = /*int*/ coefficients.length;\n            if (coefficientsLength > 1 && coefficients[0] === 0) {\n                // Leading term must be non-zero for anything except the constant polynomial \"0\"\n                let firstNonZero = /*int*/ 1;\n                while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) {\n                    firstNonZero++;\n                }\n                if (firstNonZero === coefficientsLength) {\n                    this.coefficients = new Int32Array([0]);\n                }\n                else {\n                    this.coefficients = new Int32Array(coefficientsLength - firstNonZero);\n                    System.arraycopy(coefficients, firstNonZero, this.coefficients, 0, this.coefficients.length);\n                }\n            }\n            else {\n                this.coefficients = coefficients;\n            }\n        }\n        getCoefficients() {\n            return this.coefficients;\n        }\n        /**\n         * @return degree of this polynomial\n         */\n        getDegree() {\n            return this.coefficients.length - 1;\n        }\n        /**\n         * @return true iff this polynomial is the monomial \"0\"\n         */\n        isZero() {\n            return this.coefficients[0] === 0;\n        }\n        /**\n         * @return coefficient of x^degree term in this polynomial\n         */\n        getCoefficient(degree) {\n            return this.coefficients[this.coefficients.length - 1 - degree];\n        }\n        /**\n         * @return evaluation of this polynomial at a given point\n         */\n        evaluateAt(a) {\n            if (a === 0) {\n                // Just return the x^0 coefficient\n                return this.getCoefficient(0);\n            }\n            if (a === 1) {\n                // Just the sum of the coefficients\n                let sum = /*int*/ 0;\n                for (let coefficient /*int*/ of this.coefficients) {\n                    sum = this.field.add(sum, coefficient);\n                }\n                return sum;\n            }\n            let result = /*int*/ this.coefficients[0];\n            let size = /*int*/ this.coefficients.length;\n            for (let i /*int*/ = 1; i < size; i++) {\n                result = this.field.add(this.field.multiply(a, result), this.coefficients[i]);\n            }\n            return result;\n        }\n        add(other) {\n            if (!this.field.equals(other.field)) {\n                throw new IllegalArgumentException('ModulusPolys do not have same ModulusGF field');\n            }\n            if (this.isZero()) {\n                return other;\n            }\n            if (other.isZero()) {\n                return this;\n            }\n            let smallerCoefficients = this.coefficients;\n            let largerCoefficients = other.coefficients;\n            if (smallerCoefficients.length > largerCoefficients.length) {\n                let temp = smallerCoefficients;\n                smallerCoefficients = largerCoefficients;\n                largerCoefficients = temp;\n            }\n            let sumDiff = new Int32Array(largerCoefficients.length);\n            let lengthDiff = /*int*/ largerCoefficients.length - smallerCoefficients.length;\n            // Copy high-order terms only found in higher-degree polynomial's coefficients\n            System.arraycopy(largerCoefficients, 0, sumDiff, 0, lengthDiff);\n            for (let i /*int*/ = lengthDiff; i < largerCoefficients.length; i++) {\n                sumDiff[i] = this.field.add(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);\n            }\n            return new ModulusPoly(this.field, sumDiff);\n        }\n        subtract(other) {\n            if (!this.field.equals(other.field)) {\n                throw new IllegalArgumentException('ModulusPolys do not have same ModulusGF field');\n            }\n            if (other.isZero()) {\n                return this;\n            }\n            return this.add(other.negative());\n        }\n        multiply(other) {\n            if (other instanceof ModulusPoly) {\n                return this.multiplyOther(other);\n            }\n            return this.multiplyScalar(other);\n        }\n        multiplyOther(other) {\n            if (!this.field.equals(other.field)) {\n                throw new IllegalArgumentException('ModulusPolys do not have same ModulusGF field');\n            }\n            if (this.isZero() || other.isZero()) {\n                // return this.field.getZero();\n                return new ModulusPoly(this.field, new Int32Array([0]));\n            }\n            let aCoefficients = this.coefficients;\n            let aLength = /*int*/ aCoefficients.length;\n            let bCoefficients = other.coefficients;\n            let bLength = /*int*/ bCoefficients.length;\n            let product = new Int32Array(aLength + bLength - 1);\n            for (let i /*int*/ = 0; i < aLength; i++) {\n                let aCoeff = /*int*/ aCoefficients[i];\n                for (let j /*int*/ = 0; j < bLength; j++) {\n                    product[i + j] = this.field.add(product[i + j], this.field.multiply(aCoeff, bCoefficients[j]));\n                }\n            }\n            return new ModulusPoly(this.field, product);\n        }\n        negative() {\n            let size = /*int*/ this.coefficients.length;\n            let negativeCoefficients = new Int32Array(size);\n            for (let i /*int*/ = 0; i < size; i++) {\n                negativeCoefficients[i] = this.field.subtract(0, this.coefficients[i]);\n            }\n            return new ModulusPoly(this.field, negativeCoefficients);\n        }\n        multiplyScalar(scalar) {\n            if (scalar === 0) {\n                return new ModulusPoly(this.field, new Int32Array([0]));\n            }\n            if (scalar === 1) {\n                return this;\n            }\n            let size = /*int*/ this.coefficients.length;\n            let product = new Int32Array(size);\n            for (let i /*int*/ = 0; i < size; i++) {\n                product[i] = this.field.multiply(this.coefficients[i], scalar);\n            }\n            return new ModulusPoly(this.field, product);\n        }\n        multiplyByMonomial(degree, coefficient) {\n            if (degree < 0) {\n                throw new IllegalArgumentException();\n            }\n            if (coefficient === 0) {\n                return new ModulusPoly(this.field, new Int32Array([0]));\n            }\n            let size = /*int*/ this.coefficients.length;\n            let product = new Int32Array(size + degree);\n            for (let i /*int*/ = 0; i < size; i++) {\n                product[i] = this.field.multiply(this.coefficients[i], coefficient);\n            }\n            return new ModulusPoly(this.field, product);\n        }\n        /*\n        ModulusPoly[] divide(other: ModulusPoly) {\n          if (!field.equals(other.field)) {\n            throw new IllegalArgumentException(\"ModulusPolys do not have same ModulusGF field\");\n          }\n          if (other.isZero()) {\n            throw new IllegalArgumentException(\"Divide by 0\");\n          }\n      \n          let quotient: ModulusPoly = field.getZero();\n          let remainder: ModulusPoly = this;\n      \n          let denominatorLeadingTerm: /*int/ number = other.getCoefficient(other.getDegree());\n          let inverseDenominatorLeadingTerm: /*int/ number = field.inverse(denominatorLeadingTerm);\n      \n          while (remainder.getDegree() >= other.getDegree() && !remainder.isZero()) {\n            let degreeDifference: /*int/ number = remainder.getDegree() - other.getDegree();\n            let scale: /*int/ number = field.multiply(remainder.getCoefficient(remainder.getDegree()), inverseDenominatorLeadingTerm);\n            let term: ModulusPoly = other.multiplyByMonomial(degreeDifference, scale);\n            let iterationQuotient: ModulusPoly = field.buildMonomial(degreeDifference, scale);\n            quotient = quotient.add(iterationQuotient);\n            remainder = remainder.subtract(term);\n          }\n      \n          return new ModulusPoly[] { quotient, remainder };\n        }\n        */\n        // @Override\n        toString() {\n            let result = new StringBuilder( /*8 * this.getDegree()*/); // dynamic string size in JS\n            for (let degree /*int*/ = this.getDegree(); degree >= 0; degree--) {\n                let coefficient = /*int*/ this.getCoefficient(degree);\n                if (coefficient !== 0) {\n                    if (coefficient < 0) {\n                        result.append(' - ');\n                        coefficient = -coefficient;\n                    }\n                    else {\n                        if (result.length() > 0) {\n                            result.append(' + ');\n                        }\n                    }\n                    if (degree === 0 || coefficient !== 1) {\n                        result.append(coefficient);\n                    }\n                    if (degree !== 0) {\n                        if (degree === 1) {\n                            result.append('x');\n                        }\n                        else {\n                            result.append('x^');\n                            result.append(degree);\n                        }\n                    }\n                }\n            }\n            return result.toString();\n        }\n    }\n\n    class ModulusBase {\n        add(a, b) {\n            return (a + b) % this.modulus;\n        }\n        subtract(a, b) {\n            return (this.modulus + a - b) % this.modulus;\n        }\n        exp(a) {\n            return this.expTable[a];\n        }\n        log(a) {\n            if (a === 0) {\n                throw new IllegalArgumentException();\n            }\n            return this.logTable[a];\n        }\n        inverse(a) {\n            if (a === 0) {\n                throw new ArithmeticException();\n            }\n            return this.expTable[this.modulus - this.logTable[a] - 1];\n        }\n        multiply(a, b) {\n            if (a === 0 || b === 0) {\n                return 0;\n            }\n            return this.expTable[(this.logTable[a] + this.logTable[b]) % (this.modulus - 1)];\n        }\n        getSize() {\n            return this.modulus;\n        }\n        equals(o) {\n            return o === this;\n        }\n    }\n\n    /*\n     * Copyright 2012 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * <p>A field based on powers of a generator integer, modulo some modulus.</p>\n     *\n     * @author Sean Owen\n     * @see com.google.zxing.common.reedsolomon.GenericGF\n     */\n    /*public final*/ class ModulusGF extends ModulusBase {\n        // private /*final*/ modulus: /*int*/ number;\n        constructor(modulus, generator) {\n            super();\n            this.modulus = modulus;\n            this.expTable = new Int32Array(modulus);\n            this.logTable = new Int32Array(modulus);\n            let x = /*int*/ 1;\n            for (let i /*int*/ = 0; i < modulus; i++) {\n                this.expTable[i] = x;\n                x = (x * generator) % modulus;\n            }\n            for (let i /*int*/ = 0; i < modulus - 1; i++) {\n                this.logTable[this.expTable[i]] = i;\n            }\n            // logTable[0] == 0 but this should never be used\n            this.zero = new ModulusPoly(this, new Int32Array([0]));\n            this.one = new ModulusPoly(this, new Int32Array([1]));\n        }\n        getZero() {\n            return this.zero;\n        }\n        getOne() {\n            return this.one;\n        }\n        buildMonomial(degree, coefficient) {\n            if (degree < 0) {\n                throw new IllegalArgumentException();\n            }\n            if (coefficient === 0) {\n                return this.zero;\n            }\n            let coefficients = new Int32Array(degree + 1);\n            coefficients[0] = coefficient;\n            return new ModulusPoly(this, coefficients);\n        }\n    }\n    ModulusGF.PDF417_GF = new ModulusGF(PDF417Common.NUMBER_OF_CODEWORDS, 3);\n\n    /*\n    * Copyright 2012 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /**\n     * <p>PDF417 error correction implementation.</p>\n     *\n     * <p>This <a href=\"http://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction#Example\">example</a>\n     * is quite useful in understanding the algorithm.</p>\n     *\n     * @author Sean Owen\n     * @see com.google.zxing.common.reedsolomon.ReedSolomonDecoder\n     */\n    /*public final*/ class ErrorCorrection {\n        constructor() {\n            this.field = ModulusGF.PDF417_GF;\n        }\n        /**\n         * @param received received codewords\n         * @param numECCodewords number of those codewords used for EC\n         * @param erasures location of erasures\n         * @return number of errors\n         * @throws ChecksumException if errors cannot be corrected, maybe because of too many errors\n         */\n        decode(received, numECCodewords, erasures) {\n            let poly = new ModulusPoly(this.field, received);\n            let S = new Int32Array(numECCodewords);\n            let error = false;\n            for (let i /*int*/ = numECCodewords; i > 0; i--) {\n                let evaluation = poly.evaluateAt(this.field.exp(i));\n                S[numECCodewords - i] = evaluation;\n                if (evaluation !== 0) {\n                    error = true;\n                }\n            }\n            if (!error) {\n                return 0;\n            }\n            let knownErrors = this.field.getOne();\n            if (erasures != null) {\n                for (const erasure of erasures) {\n                    let b = this.field.exp(received.length - 1 - erasure);\n                    // Add (1 - bx) term:\n                    let term = new ModulusPoly(this.field, new Int32Array([this.field.subtract(0, b), 1]));\n                    knownErrors = knownErrors.multiply(term);\n                }\n            }\n            let syndrome = new ModulusPoly(this.field, S);\n            // syndrome = syndrome.multiply(knownErrors);\n            let sigmaOmega = this.runEuclideanAlgorithm(this.field.buildMonomial(numECCodewords, 1), syndrome, numECCodewords);\n            let sigma = sigmaOmega[0];\n            let omega = sigmaOmega[1];\n            // sigma = sigma.multiply(knownErrors);\n            let errorLocations = this.findErrorLocations(sigma);\n            let errorMagnitudes = this.findErrorMagnitudes(omega, sigma, errorLocations);\n            for (let i /*int*/ = 0; i < errorLocations.length; i++) {\n                let position = received.length - 1 - this.field.log(errorLocations[i]);\n                if (position < 0) {\n                    throw ChecksumException.getChecksumInstance();\n                }\n                received[position] = this.field.subtract(received[position], errorMagnitudes[i]);\n            }\n            return errorLocations.length;\n        }\n        /**\n         *\n         * @param ModulusPoly\n         * @param a\n         * @param ModulusPoly\n         * @param b\n         * @param int\n         * @param R\n         * @throws ChecksumException\n         */\n        runEuclideanAlgorithm(a, b, R) {\n            // Assume a's degree is >= b's\n            if (a.getDegree() < b.getDegree()) {\n                let temp = a;\n                a = b;\n                b = temp;\n            }\n            let rLast = a;\n            let r = b;\n            let tLast = this.field.getZero();\n            let t = this.field.getOne();\n            // Run Euclidean algorithm until r's degree is less than R/2\n            while (r.getDegree() >= Math.round(R / 2)) {\n                let rLastLast = rLast;\n                let tLastLast = tLast;\n                rLast = r;\n                tLast = t;\n                // Divide rLastLast by rLast, with quotient in q and remainder in r\n                if (rLast.isZero()) {\n                    // Oops, Euclidean algorithm already terminated?\n                    throw ChecksumException.getChecksumInstance();\n                }\n                r = rLastLast;\n                let q = this.field.getZero();\n                let denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree());\n                let dltInverse = this.field.inverse(denominatorLeadingTerm);\n                while (r.getDegree() >= rLast.getDegree() && !r.isZero()) {\n                    let degreeDiff = r.getDegree() - rLast.getDegree();\n                    let scale = this.field.multiply(r.getCoefficient(r.getDegree()), dltInverse);\n                    q = q.add(this.field.buildMonomial(degreeDiff, scale));\n                    r = r.subtract(rLast.multiplyByMonomial(degreeDiff, scale));\n                }\n                t = q.multiply(tLast).subtract(tLastLast).negative();\n            }\n            let sigmaTildeAtZero = t.getCoefficient(0);\n            if (sigmaTildeAtZero === 0) {\n                throw ChecksumException.getChecksumInstance();\n            }\n            let inverse = this.field.inverse(sigmaTildeAtZero);\n            let sigma = t.multiply(inverse);\n            let omega = r.multiply(inverse);\n            return [sigma, omega];\n        }\n        /**\n         *\n         * @param errorLocator\n         * @throws ChecksumException\n         */\n        findErrorLocations(errorLocator) {\n            // This is a direct application of Chien's search\n            let numErrors = errorLocator.getDegree();\n            let result = new Int32Array(numErrors);\n            let e = 0;\n            for (let i /*int*/ = 1; i < this.field.getSize() && e < numErrors; i++) {\n                if (errorLocator.evaluateAt(i) === 0) {\n                    result[e] = this.field.inverse(i);\n                    e++;\n                }\n            }\n            if (e !== numErrors) {\n                throw ChecksumException.getChecksumInstance();\n            }\n            return result;\n        }\n        findErrorMagnitudes(errorEvaluator, errorLocator, errorLocations) {\n            let errorLocatorDegree = errorLocator.getDegree();\n            let formalDerivativeCoefficients = new Int32Array(errorLocatorDegree);\n            for (let i /*int*/ = 1; i <= errorLocatorDegree; i++) {\n                formalDerivativeCoefficients[errorLocatorDegree - i] =\n                    this.field.multiply(i, errorLocator.getCoefficient(i));\n            }\n            let formalDerivative = new ModulusPoly(this.field, formalDerivativeCoefficients);\n            // This is directly applying Forney's Formula\n            let s = errorLocations.length;\n            let result = new Int32Array(s);\n            for (let i /*int*/ = 0; i < s; i++) {\n                let xiInverse = this.field.inverse(errorLocations[i]);\n                let numerator = this.field.subtract(0, errorEvaluator.evaluateAt(xiInverse));\n                let denominator = this.field.inverse(formalDerivative.evaluateAt(xiInverse));\n                result[i] = this.field.multiply(numerator, denominator);\n            }\n            return result;\n        }\n    }\n\n    /*\n    * Copyright 2013 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /**\n     * @author Guenther Grau\n     */\n    /*final*/ class BoundingBox {\n        constructor(image, topLeft, bottomLeft, topRight, bottomRight) {\n            if (image instanceof BoundingBox) {\n                this.constructor_2(image);\n            }\n            else {\n                this.constructor_1(image, topLeft, bottomLeft, topRight, bottomRight);\n            }\n        }\n        /**\n         *\n         * @param image\n         * @param topLeft\n         * @param bottomLeft\n         * @param topRight\n         * @param bottomRight\n         *\n         * @throws NotFoundException\n         */\n        constructor_1(image, topLeft, bottomLeft, topRight, bottomRight) {\n            const leftUnspecified = topLeft == null || bottomLeft == null;\n            const rightUnspecified = topRight == null || bottomRight == null;\n            if (leftUnspecified && rightUnspecified) {\n                throw new NotFoundException();\n            }\n            if (leftUnspecified) {\n                topLeft = new ResultPoint(0, topRight.getY());\n                bottomLeft = new ResultPoint(0, bottomRight.getY());\n            }\n            else if (rightUnspecified) {\n                topRight = new ResultPoint(image.getWidth() - 1, topLeft.getY());\n                bottomRight = new ResultPoint(image.getWidth() - 1, bottomLeft.getY());\n            }\n            this.image = image;\n            this.topLeft = topLeft;\n            this.bottomLeft = bottomLeft;\n            this.topRight = topRight;\n            this.bottomRight = bottomRight;\n            this.minX = Math.trunc(Math.min(topLeft.getX(), bottomLeft.getX()));\n            this.maxX = Math.trunc(Math.max(topRight.getX(), bottomRight.getX()));\n            this.minY = Math.trunc(Math.min(topLeft.getY(), topRight.getY()));\n            this.maxY = Math.trunc(Math.max(bottomLeft.getY(), bottomRight.getY()));\n        }\n        constructor_2(boundingBox) {\n            this.image = boundingBox.image;\n            this.topLeft = boundingBox.getTopLeft();\n            this.bottomLeft = boundingBox.getBottomLeft();\n            this.topRight = boundingBox.getTopRight();\n            this.bottomRight = boundingBox.getBottomRight();\n            this.minX = boundingBox.getMinX();\n            this.maxX = boundingBox.getMaxX();\n            this.minY = boundingBox.getMinY();\n            this.maxY = boundingBox.getMaxY();\n        }\n        /**\n         * @throws NotFoundException\n         */\n        static merge(leftBox, rightBox) {\n            if (leftBox == null) {\n                return rightBox;\n            }\n            if (rightBox == null) {\n                return leftBox;\n            }\n            return new BoundingBox(leftBox.image, leftBox.topLeft, leftBox.bottomLeft, rightBox.topRight, rightBox.bottomRight);\n        }\n        /**\n         * @throws NotFoundException\n         */\n        addMissingRows(missingStartRows, missingEndRows, isLeft) {\n            let newTopLeft = this.topLeft;\n            let newBottomLeft = this.bottomLeft;\n            let newTopRight = this.topRight;\n            let newBottomRight = this.bottomRight;\n            if (missingStartRows > 0) {\n                let top = isLeft ? this.topLeft : this.topRight;\n                let newMinY = Math.trunc(top.getY() - missingStartRows);\n                if (newMinY < 0) {\n                    newMinY = 0;\n                }\n                let newTop = new ResultPoint(top.getX(), newMinY);\n                if (isLeft) {\n                    newTopLeft = newTop;\n                }\n                else {\n                    newTopRight = newTop;\n                }\n            }\n            if (missingEndRows > 0) {\n                let bottom = isLeft ? this.bottomLeft : this.bottomRight;\n                let newMaxY = Math.trunc(bottom.getY() + missingEndRows);\n                if (newMaxY >= this.image.getHeight()) {\n                    newMaxY = this.image.getHeight() - 1;\n                }\n                let newBottom = new ResultPoint(bottom.getX(), newMaxY);\n                if (isLeft) {\n                    newBottomLeft = newBottom;\n                }\n                else {\n                    newBottomRight = newBottom;\n                }\n            }\n            return new BoundingBox(this.image, newTopLeft, newBottomLeft, newTopRight, newBottomRight);\n        }\n        getMinX() {\n            return this.minX;\n        }\n        getMaxX() {\n            return this.maxX;\n        }\n        getMinY() {\n            return this.minY;\n        }\n        getMaxY() {\n            return this.maxY;\n        }\n        getTopLeft() {\n            return this.topLeft;\n        }\n        getTopRight() {\n            return this.topRight;\n        }\n        getBottomLeft() {\n            return this.bottomLeft;\n        }\n        getBottomRight() {\n            return this.bottomRight;\n        }\n    }\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    // package com.google.zxing.pdf417.decoder;\n    /**\n     * @author Guenther Grau\n     */\n    /*final*/ class BarcodeMetadata {\n        constructor(columnCount, rowCountUpperPart, rowCountLowerPart, errorCorrectionLevel) {\n            this.columnCount = columnCount;\n            this.errorCorrectionLevel = errorCorrectionLevel;\n            this.rowCountUpperPart = rowCountUpperPart;\n            this.rowCountLowerPart = rowCountLowerPart;\n            this.rowCount = rowCountUpperPart + rowCountLowerPart;\n        }\n        getColumnCount() {\n            return this.columnCount;\n        }\n        getErrorCorrectionLevel() {\n            return this.errorCorrectionLevel;\n        }\n        getRowCount() {\n            return this.rowCount;\n        }\n        getRowCountUpperPart() {\n            return this.rowCountUpperPart;\n        }\n        getRowCountLowerPart() {\n            return this.rowCountLowerPart;\n        }\n    }\n\n    /**\n     * Java Formatter class polyfill that works in the JS way.\n     */\n    class Formatter {\n        constructor() {\n            this.buffer = '';\n        }\n        /**\n         *\n         * @see https://stackoverflow.com/a/13439711/4367683\n         *\n         * @param str\n         * @param arr\n         */\n        static form(str, arr) {\n            let i = -1;\n            function callback(exp, p0, p1, p2, p3, p4) {\n                if (exp === '%%')\n                    return '%';\n                if (arr[++i] === undefined)\n                    return undefined;\n                exp = p2 ? parseInt(p2.substr(1)) : undefined;\n                let base = p3 ? parseInt(p3.substr(1)) : undefined;\n                let val;\n                switch (p4) {\n                    case 's':\n                        val = arr[i];\n                        break;\n                    case 'c':\n                        val = arr[i][0];\n                        break;\n                    case 'f':\n                        val = parseFloat(arr[i]).toFixed(exp);\n                        break;\n                    case 'p':\n                        val = parseFloat(arr[i]).toPrecision(exp);\n                        break;\n                    case 'e':\n                        val = parseFloat(arr[i]).toExponential(exp);\n                        break;\n                    case 'x':\n                        val = parseInt(arr[i]).toString(base ? base : 16);\n                        break;\n                    case 'd':\n                        val = parseFloat(parseInt(arr[i], base ? base : 10).toPrecision(exp)).toFixed(0);\n                        break;\n                }\n                val = typeof val === 'object' ? JSON.stringify(val) : (+val).toString(base);\n                let size = parseInt(p1); /* padding size */\n                let ch = p1 && (p1[0] + '') === '0' ? '0' : ' '; /* isnull? */\n                while (val.length < size)\n                    val = p0 !== undefined ? val + ch : ch + val; /* isminus? */\n                return val;\n            }\n            let regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g;\n            return str.replace(regex, callback);\n        }\n        /**\n         *\n         * @param append The new string to append.\n         * @param args Argumets values to be formated.\n         */\n        format(append, ...args) {\n            this.buffer += Formatter.form(append, args);\n        }\n        /**\n         * Returns the Formatter string value.\n         */\n        toString() {\n            return this.buffer;\n        }\n    }\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * @author Guenther Grau\n     */\n    class DetectionResultColumn {\n        constructor(boundingBox) {\n            this.boundingBox = new BoundingBox(boundingBox);\n            // this.codewords = new Codeword[boundingBox.getMaxY() - boundingBox.getMinY() + 1];\n            this.codewords = new Array(boundingBox.getMaxY() - boundingBox.getMinY() + 1);\n        }\n        /*final*/ getCodewordNearby(imageRow) {\n            let codeword = this.getCodeword(imageRow);\n            if (codeword != null) {\n                return codeword;\n            }\n            for (let i = 1; i < DetectionResultColumn.MAX_NEARBY_DISTANCE; i++) {\n                let nearImageRow = this.imageRowToCodewordIndex(imageRow) - i;\n                if (nearImageRow >= 0) {\n                    codeword = this.codewords[nearImageRow];\n                    if (codeword != null) {\n                        return codeword;\n                    }\n                }\n                nearImageRow = this.imageRowToCodewordIndex(imageRow) + i;\n                if (nearImageRow < this.codewords.length) {\n                    codeword = this.codewords[nearImageRow];\n                    if (codeword != null) {\n                        return codeword;\n                    }\n                }\n            }\n            return null;\n        }\n        /*final int*/ imageRowToCodewordIndex(imageRow) {\n            return imageRow - this.boundingBox.getMinY();\n        }\n        /*final void*/ setCodeword(imageRow, codeword) {\n            this.codewords[this.imageRowToCodewordIndex(imageRow)] = codeword;\n        }\n        /*final*/ getCodeword(imageRow) {\n            return this.codewords[this.imageRowToCodewordIndex(imageRow)];\n        }\n        /*final*/ getBoundingBox() {\n            return this.boundingBox;\n        }\n        /*final*/ getCodewords() {\n            return this.codewords;\n        }\n        // @Override\n        toString() {\n            const formatter = new Formatter();\n            let row = 0;\n            for (const codeword of this.codewords) {\n                if (codeword == null) {\n                    formatter.format('%3d:    |   %n', row++);\n                    continue;\n                }\n                formatter.format('%3d: %3d|%3d%n', row++, codeword.getRowNumber(), codeword.getValue());\n            }\n            return formatter.toString();\n        }\n    }\n    DetectionResultColumn.MAX_NEARBY_DISTANCE = 5;\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    // import java.util.ArrayList;\n    // import java.util.Collection;\n    // import java.util.HashMap;\n    // import java.util.Map;\n    // import java.util.Map.Entry;\n    /**\n     * @author Guenther Grau\n     */\n    /*final*/ class BarcodeValue {\n        constructor() {\n            this.values = new Map();\n        }\n        /**\n         * Add an occurrence of a value\n         */\n        setValue(value) {\n            value = Math.trunc(value);\n            let confidence = this.values.get(value);\n            if (confidence == null) {\n                confidence = 0;\n            }\n            confidence++;\n            this.values.set(value, confidence);\n        }\n        /**\n         * Determines the maximum occurrence of a set value and returns all values which were set with this occurrence.\n         * @return an array of int, containing the values with the highest occurrence, or null, if no value was set\n         */\n        getValue() {\n            let maxConfidence = -1;\n            let result = new Array();\n            for (const [key, value] of this.values.entries()) {\n                const entry = {\n                    getKey: () => key,\n                    getValue: () => value,\n                };\n                if (entry.getValue() > maxConfidence) {\n                    maxConfidence = entry.getValue();\n                    result = [];\n                    result.push(entry.getKey());\n                }\n                else if (entry.getValue() === maxConfidence) {\n                    result.push(entry.getKey());\n                }\n            }\n            return PDF417Common.toIntArray(result);\n        }\n        getConfidence(value) {\n            return this.values.get(value);\n        }\n    }\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * @author Guenther Grau\n     */\n    /*final*/ class DetectionResultRowIndicatorColumn extends DetectionResultColumn {\n        constructor(boundingBox, isLeft) {\n            super(boundingBox);\n            this._isLeft = isLeft;\n        }\n        setRowNumbers() {\n            for (let codeword /*Codeword*/ of this.getCodewords()) {\n                if (codeword != null) {\n                    codeword.setRowNumberAsRowIndicatorColumn();\n                }\n            }\n        }\n        // TODO implement properly\n        // TODO maybe we should add missing codewords to store the correct row number to make\n        // finding row numbers for other columns easier\n        // use row height count to make detection of invalid row numbers more reliable\n        adjustCompleteIndicatorColumnRowNumbers(barcodeMetadata) {\n            let codewords = this.getCodewords();\n            this.setRowNumbers();\n            this.removeIncorrectCodewords(codewords, barcodeMetadata);\n            let boundingBox = this.getBoundingBox();\n            let top = this._isLeft ? boundingBox.getTopLeft() : boundingBox.getTopRight();\n            let bottom = this._isLeft ? boundingBox.getBottomLeft() : boundingBox.getBottomRight();\n            let firstRow = this.imageRowToCodewordIndex(Math.trunc(top.getY()));\n            let lastRow = this.imageRowToCodewordIndex(Math.trunc(bottom.getY()));\n            // We need to be careful using the average row height. Barcode could be skewed so that we have smaller and\n            // taller rows\n            // float averageRowHeight = (lastRow - firstRow) / /*(float)*/ barcodeMetadata.getRowCount();\n            let barcodeRow = -1;\n            let maxRowHeight = 1;\n            let currentRowHeight = 0;\n            for (let codewordsRow /*int*/ = firstRow; codewordsRow < lastRow; codewordsRow++) {\n                if (codewords[codewordsRow] == null) {\n                    continue;\n                }\n                let codeword = codewords[codewordsRow];\n                //      float expectedRowNumber = (codewordsRow - firstRow) / averageRowHeight;\n                //      if (Math.abs(codeword.getRowNumber() - expectedRowNumber) > 2) {\n                //        SimpleLog.log(LEVEL.WARNING,\n                //            \"Removing codeword, rowNumberSkew too high, codeword[\" + codewordsRow + \"]: Expected Row: \" +\n                //                expectedRowNumber + \", RealRow: \" + codeword.getRowNumber() + \", value: \" + codeword.getValue());\n                //        codewords[codewordsRow] = null;\n                //      }\n                let rowDifference = codeword.getRowNumber() - barcodeRow;\n                // TODO improve handling with case where first row indicator doesn't start with 0\n                if (rowDifference === 0) {\n                    currentRowHeight++;\n                }\n                else if (rowDifference === 1) {\n                    maxRowHeight = Math.max(maxRowHeight, currentRowHeight);\n                    currentRowHeight = 1;\n                    barcodeRow = codeword.getRowNumber();\n                }\n                else if (rowDifference < 0 ||\n                    codeword.getRowNumber() >= barcodeMetadata.getRowCount() ||\n                    rowDifference > codewordsRow) {\n                    codewords[codewordsRow] = null;\n                }\n                else {\n                    let checkedRows;\n                    if (maxRowHeight > 2) {\n                        checkedRows = (maxRowHeight - 2) * rowDifference;\n                    }\n                    else {\n                        checkedRows = rowDifference;\n                    }\n                    let closePreviousCodewordFound = checkedRows >= codewordsRow;\n                    for (let i /*int*/ = 1; i <= checkedRows && !closePreviousCodewordFound; i++) {\n                        // there must be (height * rowDifference) number of codewords missing. For now we assume height = 1.\n                        // This should hopefully get rid of most problems already.\n                        closePreviousCodewordFound = codewords[codewordsRow - i] != null;\n                    }\n                    if (closePreviousCodewordFound) {\n                        codewords[codewordsRow] = null;\n                    }\n                    else {\n                        barcodeRow = codeword.getRowNumber();\n                        currentRowHeight = 1;\n                    }\n                }\n            }\n            // return (int) (averageRowHeight + 0.5);\n        }\n        getRowHeights() {\n            let barcodeMetadata = this.getBarcodeMetadata();\n            if (barcodeMetadata == null) {\n                return null;\n            }\n            this.adjustIncompleteIndicatorColumnRowNumbers(barcodeMetadata);\n            let result = new Int32Array(barcodeMetadata.getRowCount());\n            for (let codeword /*Codeword*/ of this.getCodewords()) {\n                if (codeword != null) {\n                    let rowNumber = codeword.getRowNumber();\n                    if (rowNumber >= result.length) {\n                        // We have more rows than the barcode metadata allows for, ignore them.\n                        continue;\n                    }\n                    result[rowNumber]++;\n                } // else throw exception?\n            }\n            return result;\n        }\n        // TODO maybe we should add missing codewords to store the correct row number to make\n        // finding row numbers for other columns easier\n        // use row height count to make detection of invalid row numbers more reliable\n        adjustIncompleteIndicatorColumnRowNumbers(barcodeMetadata) {\n            let boundingBox = this.getBoundingBox();\n            let top = this._isLeft ? boundingBox.getTopLeft() : boundingBox.getTopRight();\n            let bottom = this._isLeft ? boundingBox.getBottomLeft() : boundingBox.getBottomRight();\n            let firstRow = this.imageRowToCodewordIndex(Math.trunc(top.getY()));\n            let lastRow = this.imageRowToCodewordIndex(Math.trunc(bottom.getY()));\n            // float averageRowHeight = (lastRow - firstRow) / /*(float)*/ barcodeMetadata.getRowCount();\n            let codewords = this.getCodewords();\n            let barcodeRow = -1;\n            for (let codewordsRow /*int*/ = firstRow; codewordsRow < lastRow; codewordsRow++) {\n                if (codewords[codewordsRow] == null) {\n                    continue;\n                }\n                let codeword = codewords[codewordsRow];\n                codeword.setRowNumberAsRowIndicatorColumn();\n                let rowDifference = codeword.getRowNumber() - barcodeRow;\n                // TODO improve handling with case where first row indicator doesn't start with 0\n                if (rowDifference === 0) ;\n                else if (rowDifference === 1) {\n                    barcodeRow = codeword.getRowNumber();\n                }\n                else if (codeword.getRowNumber() >= barcodeMetadata.getRowCount()) {\n                    codewords[codewordsRow] = null;\n                }\n                else {\n                    barcodeRow = codeword.getRowNumber();\n                }\n            }\n            // return (int) (averageRowHeight + 0.5);\n        }\n        getBarcodeMetadata() {\n            let codewords = this.getCodewords();\n            let barcodeColumnCount = new BarcodeValue();\n            let barcodeRowCountUpperPart = new BarcodeValue();\n            let barcodeRowCountLowerPart = new BarcodeValue();\n            let barcodeECLevel = new BarcodeValue();\n            for (let codeword /*Codeword*/ of codewords) {\n                if (codeword == null) {\n                    continue;\n                }\n                codeword.setRowNumberAsRowIndicatorColumn();\n                let rowIndicatorValue = codeword.getValue() % 30;\n                let codewordRowNumber = codeword.getRowNumber();\n                if (!this._isLeft) {\n                    codewordRowNumber += 2;\n                }\n                switch (codewordRowNumber % 3) {\n                    case 0:\n                        barcodeRowCountUpperPart.setValue(rowIndicatorValue * 3 + 1);\n                        break;\n                    case 1:\n                        barcodeECLevel.setValue(rowIndicatorValue / 3);\n                        barcodeRowCountLowerPart.setValue(rowIndicatorValue % 3);\n                        break;\n                    case 2:\n                        barcodeColumnCount.setValue(rowIndicatorValue + 1);\n                        break;\n                }\n            }\n            // Maybe we should check if we have ambiguous values?\n            if ((barcodeColumnCount.getValue().length === 0) ||\n                (barcodeRowCountUpperPart.getValue().length === 0) ||\n                (barcodeRowCountLowerPart.getValue().length === 0) ||\n                (barcodeECLevel.getValue().length === 0) ||\n                barcodeColumnCount.getValue()[0] < 1 ||\n                barcodeRowCountUpperPart.getValue()[0] + barcodeRowCountLowerPart.getValue()[0] < PDF417Common.MIN_ROWS_IN_BARCODE ||\n                barcodeRowCountUpperPart.getValue()[0] + barcodeRowCountLowerPart.getValue()[0] > PDF417Common.MAX_ROWS_IN_BARCODE) {\n                return null;\n            }\n            let barcodeMetadata = new BarcodeMetadata(barcodeColumnCount.getValue()[0], barcodeRowCountUpperPart.getValue()[0], barcodeRowCountLowerPart.getValue()[0], barcodeECLevel.getValue()[0]);\n            this.removeIncorrectCodewords(codewords, barcodeMetadata);\n            return barcodeMetadata;\n        }\n        removeIncorrectCodewords(codewords, barcodeMetadata) {\n            // Remove codewords which do not match the metadata\n            // TODO Maybe we should keep the incorrect codewords for the start and end positions?\n            for (let codewordRow /*int*/ = 0; codewordRow < codewords.length; codewordRow++) {\n                let codeword = codewords[codewordRow];\n                if (codewords[codewordRow] == null) {\n                    continue;\n                }\n                let rowIndicatorValue = codeword.getValue() % 30;\n                let codewordRowNumber = codeword.getRowNumber();\n                if (codewordRowNumber > barcodeMetadata.getRowCount()) {\n                    codewords[codewordRow] = null;\n                    continue;\n                }\n                if (!this._isLeft) {\n                    codewordRowNumber += 2;\n                }\n                switch (codewordRowNumber % 3) {\n                    case 0:\n                        if (rowIndicatorValue * 3 + 1 !== barcodeMetadata.getRowCountUpperPart()) {\n                            codewords[codewordRow] = null;\n                        }\n                        break;\n                    case 1:\n                        if (Math.trunc(rowIndicatorValue / 3) !== barcodeMetadata.getErrorCorrectionLevel() ||\n                            rowIndicatorValue % 3 !== barcodeMetadata.getRowCountLowerPart()) {\n                            codewords[codewordRow] = null;\n                        }\n                        break;\n                    case 2:\n                        if (rowIndicatorValue + 1 !== barcodeMetadata.getColumnCount()) {\n                            codewords[codewordRow] = null;\n                        }\n                        break;\n                }\n            }\n        }\n        isLeft() {\n            return this._isLeft;\n        }\n        // @Override\n        toString() {\n            return 'IsLeft: ' + this._isLeft + '\\n' + super.toString();\n        }\n    }\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * @author Guenther Grau\n     */\n    /*final*/ class DetectionResult {\n        constructor(barcodeMetadata, boundingBox) {\n            /*final*/ this.ADJUST_ROW_NUMBER_SKIP = 2;\n            this.barcodeMetadata = barcodeMetadata;\n            this.barcodeColumnCount = barcodeMetadata.getColumnCount();\n            this.boundingBox = boundingBox;\n            // this.detectionResultColumns = new DetectionResultColumn[this.barcodeColumnCount + 2];\n            this.detectionResultColumns = new Array(this.barcodeColumnCount + 2);\n        }\n        getDetectionResultColumns() {\n            this.adjustIndicatorColumnRowNumbers(this.detectionResultColumns[0]);\n            this.adjustIndicatorColumnRowNumbers(this.detectionResultColumns[this.barcodeColumnCount + 1]);\n            let unadjustedCodewordCount = PDF417Common.MAX_CODEWORDS_IN_BARCODE;\n            let previousUnadjustedCount;\n            do {\n                previousUnadjustedCount = unadjustedCodewordCount;\n                unadjustedCodewordCount = this.adjustRowNumbersAndGetCount();\n            } while (unadjustedCodewordCount > 0 && unadjustedCodewordCount < previousUnadjustedCount);\n            return this.detectionResultColumns;\n        }\n        adjustIndicatorColumnRowNumbers(detectionResultColumn) {\n            if (detectionResultColumn != null) {\n                detectionResultColumn\n                    .adjustCompleteIndicatorColumnRowNumbers(this.barcodeMetadata);\n            }\n        }\n        // TODO ensure that no detected codewords with unknown row number are left\n        // we should be able to estimate the row height and use it as a hint for the row number\n        // we should also fill the rows top to bottom and bottom to top\n        /**\n         * @return number of codewords which don't have a valid row number. Note that the count is not accurate as codewords\n         * will be counted several times. It just serves as an indicator to see when we can stop adjusting row numbers\n         */\n        adjustRowNumbersAndGetCount() {\n            let unadjustedCount = this.adjustRowNumbersByRow();\n            if (unadjustedCount === 0) {\n                return 0;\n            }\n            for (let barcodeColumn /*int*/ = 1; barcodeColumn < this.barcodeColumnCount + 1; barcodeColumn++) {\n                let codewords = this.detectionResultColumns[barcodeColumn].getCodewords();\n                for (let codewordsRow /*int*/ = 0; codewordsRow < codewords.length; codewordsRow++) {\n                    if (codewords[codewordsRow] == null) {\n                        continue;\n                    }\n                    if (!codewords[codewordsRow].hasValidRowNumber()) {\n                        this.adjustRowNumbers(barcodeColumn, codewordsRow, codewords);\n                    }\n                }\n            }\n            return unadjustedCount;\n        }\n        adjustRowNumbersByRow() {\n            this.adjustRowNumbersFromBothRI();\n            // TODO we should only do full row adjustments if row numbers of left and right row indicator column match.\n            // Maybe it's even better to calculated the height (rows: d) and divide it by the number of barcode\n            // rows. This, together with the LRI and RRI row numbers should allow us to get a good estimate where a row\n            // number starts and ends.\n            let unadjustedCount = this.adjustRowNumbersFromLRI();\n            return unadjustedCount + this.adjustRowNumbersFromRRI();\n        }\n        adjustRowNumbersFromBothRI() {\n            if (this.detectionResultColumns[0] == null || this.detectionResultColumns[this.barcodeColumnCount + 1] == null) {\n                return;\n            }\n            let LRIcodewords = this.detectionResultColumns[0].getCodewords();\n            let RRIcodewords = this.detectionResultColumns[this.barcodeColumnCount + 1].getCodewords();\n            for (let codewordsRow /*int*/ = 0; codewordsRow < LRIcodewords.length; codewordsRow++) {\n                if (LRIcodewords[codewordsRow] != null &&\n                    RRIcodewords[codewordsRow] != null &&\n                    LRIcodewords[codewordsRow].getRowNumber() === RRIcodewords[codewordsRow].getRowNumber()) {\n                    for (let barcodeColumn /*int*/ = 1; barcodeColumn <= this.barcodeColumnCount; barcodeColumn++) {\n                        let codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow];\n                        if (codeword == null) {\n                            continue;\n                        }\n                        codeword.setRowNumber(LRIcodewords[codewordsRow].getRowNumber());\n                        if (!codeword.hasValidRowNumber()) {\n                            this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow] = null;\n                        }\n                    }\n                }\n            }\n        }\n        adjustRowNumbersFromRRI() {\n            if (this.detectionResultColumns[this.barcodeColumnCount + 1] == null) {\n                return 0;\n            }\n            let unadjustedCount = 0;\n            let codewords = this.detectionResultColumns[this.barcodeColumnCount + 1].getCodewords();\n            for (let codewordsRow /*int*/ = 0; codewordsRow < codewords.length; codewordsRow++) {\n                if (codewords[codewordsRow] == null) {\n                    continue;\n                }\n                let rowIndicatorRowNumber = codewords[codewordsRow].getRowNumber();\n                let invalidRowCounts = 0;\n                for (let barcodeColumn /*int*/ = this.barcodeColumnCount + 1; barcodeColumn > 0 && invalidRowCounts < this.ADJUST_ROW_NUMBER_SKIP; barcodeColumn--) {\n                    let codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow];\n                    if (codeword != null) {\n                        invalidRowCounts = DetectionResult.adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword);\n                        if (!codeword.hasValidRowNumber()) {\n                            unadjustedCount++;\n                        }\n                    }\n                }\n            }\n            return unadjustedCount;\n        }\n        adjustRowNumbersFromLRI() {\n            if (this.detectionResultColumns[0] == null) {\n                return 0;\n            }\n            let unadjustedCount = 0;\n            let codewords = this.detectionResultColumns[0].getCodewords();\n            for (let codewordsRow /*int*/ = 0; codewordsRow < codewords.length; codewordsRow++) {\n                if (codewords[codewordsRow] == null) {\n                    continue;\n                }\n                let rowIndicatorRowNumber = codewords[codewordsRow].getRowNumber();\n                let invalidRowCounts = 0;\n                for (let barcodeColumn /*int*/ = 1; barcodeColumn < this.barcodeColumnCount + 1 && invalidRowCounts < this.ADJUST_ROW_NUMBER_SKIP; barcodeColumn++) {\n                    let codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow];\n                    if (codeword != null) {\n                        invalidRowCounts = DetectionResult.adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword);\n                        if (!codeword.hasValidRowNumber()) {\n                            unadjustedCount++;\n                        }\n                    }\n                }\n            }\n            return unadjustedCount;\n        }\n        static adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword) {\n            if (codeword == null) {\n                return invalidRowCounts;\n            }\n            if (!codeword.hasValidRowNumber()) {\n                if (codeword.isValidRowNumber(rowIndicatorRowNumber)) {\n                    codeword.setRowNumber(rowIndicatorRowNumber);\n                    invalidRowCounts = 0;\n                }\n                else {\n                    ++invalidRowCounts;\n                }\n            }\n            return invalidRowCounts;\n        }\n        adjustRowNumbers(barcodeColumn, codewordsRow, codewords) {\n            if (!this.detectionResultColumns[barcodeColumn - 1]) {\n                return;\n            }\n            let codeword = codewords[codewordsRow];\n            let previousColumnCodewords = this.detectionResultColumns[barcodeColumn - 1].getCodewords();\n            let nextColumnCodewords = previousColumnCodewords;\n            if (this.detectionResultColumns[barcodeColumn + 1] != null) {\n                nextColumnCodewords = this.detectionResultColumns[barcodeColumn + 1].getCodewords();\n            }\n            // let otherCodewords: Codeword[] = new Codeword[14];\n            let otherCodewords = new Array(14);\n            otherCodewords[2] = previousColumnCodewords[codewordsRow];\n            otherCodewords[3] = nextColumnCodewords[codewordsRow];\n            if (codewordsRow > 0) {\n                otherCodewords[0] = codewords[codewordsRow - 1];\n                otherCodewords[4] = previousColumnCodewords[codewordsRow - 1];\n                otherCodewords[5] = nextColumnCodewords[codewordsRow - 1];\n            }\n            if (codewordsRow > 1) {\n                otherCodewords[8] = codewords[codewordsRow - 2];\n                otherCodewords[10] = previousColumnCodewords[codewordsRow - 2];\n                otherCodewords[11] = nextColumnCodewords[codewordsRow - 2];\n            }\n            if (codewordsRow < codewords.length - 1) {\n                otherCodewords[1] = codewords[codewordsRow + 1];\n                otherCodewords[6] = previousColumnCodewords[codewordsRow + 1];\n                otherCodewords[7] = nextColumnCodewords[codewordsRow + 1];\n            }\n            if (codewordsRow < codewords.length - 2) {\n                otherCodewords[9] = codewords[codewordsRow + 2];\n                otherCodewords[12] = previousColumnCodewords[codewordsRow + 2];\n                otherCodewords[13] = nextColumnCodewords[codewordsRow + 2];\n            }\n            for (let otherCodeword of otherCodewords) {\n                if (DetectionResult.adjustRowNumber(codeword, otherCodeword)) {\n                    return;\n                }\n            }\n        }\n        /**\n         * @return true, if row number was adjusted, false otherwise\n         */\n        static adjustRowNumber(codeword, otherCodeword) {\n            if (otherCodeword == null) {\n                return false;\n            }\n            if (otherCodeword.hasValidRowNumber() && otherCodeword.getBucket() === codeword.getBucket()) {\n                codeword.setRowNumber(otherCodeword.getRowNumber());\n                return true;\n            }\n            return false;\n        }\n        getBarcodeColumnCount() {\n            return this.barcodeColumnCount;\n        }\n        getBarcodeRowCount() {\n            return this.barcodeMetadata.getRowCount();\n        }\n        getBarcodeECLevel() {\n            return this.barcodeMetadata.getErrorCorrectionLevel();\n        }\n        setBoundingBox(boundingBox) {\n            this.boundingBox = boundingBox;\n        }\n        getBoundingBox() {\n            return this.boundingBox;\n        }\n        setDetectionResultColumn(barcodeColumn, detectionResultColumn) {\n            this.detectionResultColumns[barcodeColumn] = detectionResultColumn;\n        }\n        getDetectionResultColumn(barcodeColumn) {\n            return this.detectionResultColumns[barcodeColumn];\n        }\n        // @Override\n        toString() {\n            let rowIndicatorColumn = this.detectionResultColumns[0];\n            if (rowIndicatorColumn == null) {\n                rowIndicatorColumn = this.detectionResultColumns[this.barcodeColumnCount + 1];\n            }\n            // try (\n            let formatter = new Formatter();\n            // ) {\n            for (let codewordsRow /*int*/ = 0; codewordsRow < rowIndicatorColumn.getCodewords().length; codewordsRow++) {\n                formatter.format('CW %3d:', codewordsRow);\n                for (let barcodeColumn /*int*/ = 0; barcodeColumn < this.barcodeColumnCount + 2; barcodeColumn++) {\n                    if (this.detectionResultColumns[barcodeColumn] == null) {\n                        formatter.format('    |   ');\n                        continue;\n                    }\n                    let codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow];\n                    if (codeword == null) {\n                        formatter.format('    |   ');\n                        continue;\n                    }\n                    formatter.format(' %3d|%3d', codeword.getRowNumber(), codeword.getValue());\n                }\n                formatter.format('%n');\n            }\n            return formatter.toString();\n            // }\n        }\n    }\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    // package com.google.zxing.pdf417.decoder;\n    /**\n     * @author Guenther Grau\n     */\n    /*final*/ class Codeword {\n        constructor(startX, endX, bucket, value) {\n            this.rowNumber = Codeword.BARCODE_ROW_UNKNOWN;\n            this.startX = Math.trunc(startX);\n            this.endX = Math.trunc(endX);\n            this.bucket = Math.trunc(bucket);\n            this.value = Math.trunc(value);\n        }\n        hasValidRowNumber() {\n            return this.isValidRowNumber(this.rowNumber);\n        }\n        isValidRowNumber(rowNumber) {\n            return rowNumber !== Codeword.BARCODE_ROW_UNKNOWN && this.bucket === (rowNumber % 3) * 3;\n        }\n        setRowNumberAsRowIndicatorColumn() {\n            this.rowNumber = Math.trunc((Math.trunc(this.value / 30)) * 3 + Math.trunc(this.bucket / 3));\n        }\n        getWidth() {\n            return this.endX - this.startX;\n        }\n        getStartX() {\n            return this.startX;\n        }\n        getEndX() {\n            return this.endX;\n        }\n        getBucket() {\n            return this.bucket;\n        }\n        getValue() {\n            return this.value;\n        }\n        getRowNumber() {\n            return this.rowNumber;\n        }\n        setRowNumber(rowNumber) {\n            this.rowNumber = rowNumber;\n        }\n        //   @Override\n        toString() {\n            return this.rowNumber + '|' + this.value;\n        }\n    }\n    Codeword.BARCODE_ROW_UNKNOWN = -1;\n\n    /*\n    * Copyright 2013 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /**\n     * @author Guenther Grau\n     * @author creatale GmbH (christoph.schulz@creatale.de)\n     */\n    /*final*/ class PDF417CodewordDecoder {\n        /* @note\n         * this action have to be performed before first use of class\n         * - static constructor\n         * working with 32bit float (based from Java logic)\n        */\n        static initialize() {\n            // Pre-computes the symbol ratio table.\n            for ( /*int*/let i = 0; i < PDF417Common.SYMBOL_TABLE.length; i++) {\n                let currentSymbol = PDF417Common.SYMBOL_TABLE[i];\n                let currentBit = currentSymbol & 0x1;\n                for ( /*int*/let j = 0; j < PDF417Common.BARS_IN_MODULE; j++) {\n                    let size = 0.0;\n                    while ((currentSymbol & 0x1) === currentBit) {\n                        size += 1.0;\n                        currentSymbol >>= 1;\n                    }\n                    currentBit = currentSymbol & 0x1;\n                    if (!PDF417CodewordDecoder.RATIOS_TABLE[i]) {\n                        PDF417CodewordDecoder.RATIOS_TABLE[i] = new Array(PDF417Common.BARS_IN_MODULE);\n                    }\n                    PDF417CodewordDecoder.RATIOS_TABLE[i][PDF417Common.BARS_IN_MODULE - j - 1] = Math.fround(size / PDF417Common.MODULES_IN_CODEWORD);\n                }\n            }\n            this.bSymbolTableReady = true;\n        }\n        static getDecodedValue(moduleBitCount) {\n            let decodedValue = PDF417CodewordDecoder.getDecodedCodewordValue(PDF417CodewordDecoder.sampleBitCounts(moduleBitCount));\n            if (decodedValue !== -1) {\n                return decodedValue;\n            }\n            return PDF417CodewordDecoder.getClosestDecodedValue(moduleBitCount);\n        }\n        static sampleBitCounts(moduleBitCount) {\n            let bitCountSum = MathUtils.sum(moduleBitCount);\n            let result = new Int32Array(PDF417Common.BARS_IN_MODULE);\n            let bitCountIndex = 0;\n            let sumPreviousBits = 0;\n            for ( /*int*/let i = 0; i < PDF417Common.MODULES_IN_CODEWORD; i++) {\n                let sampleIndex = bitCountSum / (2 * PDF417Common.MODULES_IN_CODEWORD) +\n                    (i * bitCountSum) / PDF417Common.MODULES_IN_CODEWORD;\n                if (sumPreviousBits + moduleBitCount[bitCountIndex] <= sampleIndex) {\n                    sumPreviousBits += moduleBitCount[bitCountIndex];\n                    bitCountIndex++;\n                }\n                result[bitCountIndex]++;\n            }\n            return result;\n        }\n        static getDecodedCodewordValue(moduleBitCount) {\n            let decodedValue = PDF417CodewordDecoder.getBitValue(moduleBitCount);\n            return PDF417Common.getCodeword(decodedValue) === -1 ? -1 : decodedValue;\n        }\n        static getBitValue(moduleBitCount) {\n            let result = /*long*/ 0;\n            for (let /*int*/ i = 0; i < moduleBitCount.length; i++) {\n                for ( /*int*/let bit = 0; bit < moduleBitCount[i]; bit++) {\n                    result = (result << 1) | (i % 2 === 0 ? 1 : 0);\n                }\n            }\n            return Math.trunc(result);\n        }\n        // working with 32bit float (as in Java)\n        static getClosestDecodedValue(moduleBitCount) {\n            let bitCountSum = MathUtils.sum(moduleBitCount);\n            let bitCountRatios = new Array(PDF417Common.BARS_IN_MODULE);\n            if (bitCountSum > 1) {\n                for (let /*int*/ i = 0; i < bitCountRatios.length; i++) {\n                    bitCountRatios[i] = Math.fround(moduleBitCount[i] / bitCountSum);\n                }\n            }\n            let bestMatchError = Float.MAX_VALUE;\n            let bestMatch = -1;\n            if (!this.bSymbolTableReady) {\n                PDF417CodewordDecoder.initialize();\n            }\n            for ( /*int*/let j = 0; j < PDF417CodewordDecoder.RATIOS_TABLE.length; j++) {\n                let error = 0.0;\n                let ratioTableRow = PDF417CodewordDecoder.RATIOS_TABLE[j];\n                for ( /*int*/let k = 0; k < PDF417Common.BARS_IN_MODULE; k++) {\n                    let diff = Math.fround(ratioTableRow[k] - bitCountRatios[k]);\n                    error += Math.fround(diff * diff);\n                    if (error >= bestMatchError) {\n                        break;\n                    }\n                }\n                if (error < bestMatchError) {\n                    bestMatchError = error;\n                    bestMatch = PDF417Common.SYMBOL_TABLE[j];\n                }\n            }\n            return bestMatch;\n        }\n    }\n    // flag that the table is ready for use\n    PDF417CodewordDecoder.bSymbolTableReady = false;\n    PDF417CodewordDecoder.RATIOS_TABLE = new Array(PDF417Common.SYMBOL_TABLE.length).map(x => x = new Array(PDF417Common.BARS_IN_MODULE));\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    // package com.google.zxing.pdf417;\n    /**\n     * @author Guenther Grau\n     */\n    /*public final*/ class PDF417ResultMetadata {\n        constructor() {\n            this.segmentCount = -1;\n            this.fileSize = -1;\n            this.timestamp = -1;\n            this.checksum = -1;\n        }\n        /**\n         * The Segment ID represents the segment of the whole file distributed over different symbols.\n         *\n         * @return File segment index\n         */\n        getSegmentIndex() {\n            return this.segmentIndex;\n        }\n        setSegmentIndex(segmentIndex) {\n            this.segmentIndex = segmentIndex;\n        }\n        /**\n         * Is the same for each related PDF417 symbol\n         *\n         * @return File ID\n         */\n        getFileId() {\n            return this.fileId;\n        }\n        setFileId(fileId) {\n            this.fileId = fileId;\n        }\n        /**\n         * @return always null\n         * @deprecated use dedicated already parsed fields\n         */\n        //   @Deprecated\n        getOptionalData() {\n            return this.optionalData;\n        }\n        /**\n         * @param optionalData old optional data format as int array\n         * @deprecated parse and use new fields\n         */\n        //   @Deprecated\n        setOptionalData(optionalData) {\n            this.optionalData = optionalData;\n        }\n        /**\n         * @return true if it is the last segment\n         */\n        isLastSegment() {\n            return this.lastSegment;\n        }\n        setLastSegment(lastSegment) {\n            this.lastSegment = lastSegment;\n        }\n        /**\n         * @return count of segments, -1 if not set\n         */\n        getSegmentCount() {\n            return this.segmentCount;\n        }\n        setSegmentCount(segmentCount /*int*/) {\n            this.segmentCount = segmentCount;\n        }\n        getSender() {\n            return this.sender || null;\n        }\n        setSender(sender) {\n            this.sender = sender;\n        }\n        getAddressee() {\n            return this.addressee || null;\n        }\n        setAddressee(addressee) {\n            this.addressee = addressee;\n        }\n        /**\n         * Filename of the encoded file\n         *\n         * @return filename\n         */\n        getFileName() {\n            return this.fileName;\n        }\n        setFileName(fileName) {\n            this.fileName = fileName;\n        }\n        /**\n         * filesize in bytes of the encoded file\n         *\n         * @return filesize in bytes, -1 if not set\n         */\n        getFileSize() {\n            return this.fileSize;\n        }\n        setFileSize(fileSize /*long*/) {\n            this.fileSize = fileSize;\n        }\n        /**\n         * 16-bit CRC checksum using CCITT-16\n         *\n         * @return crc checksum, -1 if not set\n         */\n        getChecksum() {\n            return this.checksum;\n        }\n        setChecksum(checksum /*int*/) {\n            this.checksum = checksum;\n        }\n        /**\n         * unix epock timestamp, elapsed seconds since 1970-01-01\n         *\n         * @return elapsed seconds, -1 if not set\n         */\n        getTimestamp() {\n            return this.timestamp;\n        }\n        setTimestamp(timestamp /*long*/) {\n            this.timestamp = timestamp;\n        }\n    }\n\n    /**\n     * Ponyfill for Java's Long class.\n     */\n    class Long {\n        /**\n         * Parses a string to a number, since JS has no really Int64.\n         *\n         * @param num Numeric string.\n         * @param radix Destination radix.\n         */\n        static parseLong(num, radix = undefined) {\n            return parseInt(num, radix);\n        }\n    }\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class NullPointerException extends Exception {\n    }\n    NullPointerException.kind = 'NullPointerException';\n\n    /*\n     * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.\n     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n     *\n     * This code is free software; you can redistribute it and/or modify it\n     * under the terms of the GNU General Public License version 2 only, as\n     * published by the Free Software Foundation.  Oracle designates this\n     * particular file as subject to the \"Classpath\" exception as provided\n     * by Oracle in the LICENSE file that accompanied this code.\n     *\n     * This code is distributed in the hope that it will be useful, but WITHOUT\n     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n     * version 2 for more details (a copy is included in the LICENSE file that\n     * accompanied this code).\n     *\n     * You should have received a copy of the GNU General Public License version\n     * 2 along with this work; if not, write to the Free Software Foundation,\n     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n     *\n     * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n     * or visit www.oracle.com if you need additional information or have any\n     * questions.\n     */\n    // package java.io;\n    /**\n     * This abstract class is the superclass of all classes representing\n     * an output stream of bytes. An output stream accepts output bytes\n     * and sends them to some sink.\n     * <p>\n     * Applications that need to define a subclass of\n     * <code>OutputStream</code> must always provide at least a method\n     * that writes one byte of output.\n     *\n     * @author  Arthur van Hoff\n     * @see     java.io.BufferedOutputStream\n     * @see     java.io.ByteArrayOutputStream\n     * @see     java.io.DataOutputStream\n     * @see     java.io.FilterOutputStream\n     * @see     java.io.InputStream\n     * @see     java.io.OutputStream#write(int)\n     * @since   JDK1.0\n     */\n    /*public*/ class OutputStream /*implements Closeable, Flushable*/ {\n        /**\n         * Writes <code>b.length</code> bytes from the specified byte array\n         * to this output stream. The general contract for <code>write(b)</code>\n         * is that it should have exactly the same effect as the call\n         * <code>write(b, 0, b.length)</code>.\n         *\n         * @param      b   the data.\n         * @exception  IOException  if an I/O error occurs.\n         * @see        java.io.OutputStream#write(byte[], int, int)\n         */\n        writeBytes(b) {\n            this.writeBytesOffset(b, 0, b.length);\n        }\n        /**\n         * Writes <code>len</code> bytes from the specified byte array\n         * starting at offset <code>off</code> to this output stream.\n         * The general contract for <code>write(b, off, len)</code> is that\n         * some of the bytes in the array <code>b</code> are written to the\n         * output stream in order; element <code>b[off]</code> is the first\n         * byte written and <code>b[off+len-1]</code> is the last byte written\n         * by this operation.\n         * <p>\n         * The <code>write</code> method of <code>OutputStream</code> calls\n         * the write method of one argument on each of the bytes to be\n         * written out. Subclasses are encouraged to override this method and\n         * provide a more efficient implementation.\n         * <p>\n         * If <code>b</code> is <code>null</code>, a\n         * <code>NullPointerException</code> is thrown.\n         * <p>\n         * If <code>off</code> is negative, or <code>len</code> is negative, or\n         * <code>off+len</code> is greater than the length of the array\n         * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown.\n         *\n         * @param      b     the data.\n         * @param      off   the start offset in the data.\n         * @param      len   the number of bytes to write.\n         * @exception  IOException  if an I/O error occurs. In particular,\n         *             an <code>IOException</code> is thrown if the output\n         *             stream is closed.\n         */\n        writeBytesOffset(b, off, len) {\n            if (b == null) {\n                throw new NullPointerException();\n            }\n            else if ((off < 0) || (off > b.length) || (len < 0) ||\n                ((off + len) > b.length) || ((off + len) < 0)) {\n                throw new IndexOutOfBoundsException();\n            }\n            else if (len === 0) {\n                return;\n            }\n            for (let i = 0; i < len; i++) {\n                this.write(b[off + i]);\n            }\n        }\n        /**\n         * Flushes this output stream and forces any buffered output bytes\n         * to be written out. The general contract of <code>flush</code> is\n         * that calling it is an indication that, if any bytes previously\n         * written have been buffered by the implementation of the output\n         * stream, such bytes should immediately be written to their\n         * intended destination.\n         * <p>\n         * If the intended destination of this stream is an abstraction provided by\n         * the underlying operating system, for example a file, then flushing the\n         * stream guarantees only that bytes previously written to the stream are\n         * passed to the operating system for writing; it does not guarantee that\n         * they are actually written to a physical device such as a disk drive.\n         * <p>\n         * The <code>flush</code> method of <code>OutputStream</code> does nothing.\n         *\n         * @exception  IOException  if an I/O error occurs.\n         */\n        flush() {\n        }\n        /**\n         * Closes this output stream and releases any system resources\n         * associated with this stream. The general contract of <code>close</code>\n         * is that it closes the output stream. A closed stream cannot perform\n         * output operations and cannot be reopened.\n         * <p>\n         * The <code>close</code> method of <code>OutputStream</code> does nothing.\n         *\n         * @exception  IOException  if an I/O error occurs.\n         */\n        close() {\n        }\n    }\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class OutOfMemoryError extends Exception {\n    }\n\n    /*\n     * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.\n     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n     *\n     * This code is free software; you can redistribute it and/or modify it\n     * under the terms of the GNU General Public License version 2 only, as\n     * published by the Free Software Foundation.  Oracle designates this\n     * particular file as subject to the \"Classpath\" exception as provided\n     * by Oracle in the LICENSE file that accompanied this code.\n     *\n     * This code is distributed in the hope that it will be useful, but WITHOUT\n     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n     * version 2 for more details (a copy is included in the LICENSE file that\n     * accompanied this code).\n     *\n     * You should have received a copy of the GNU General Public License version\n     * 2 along with this work; if not, write to the Free Software Foundation,\n     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n     *\n     * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n     * or visit www.oracle.com if you need additional information or have any\n     * questions.\n     */\n    /**\n     * This class implements an output stream in which the data is\n     * written into a byte array. The buffer automatically grows as data\n     * is written to it.\n     * The data can be retrieved using <code>toByteArray()</code> and\n     * <code>toString()</code>.\n     * <p>\n     * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in\n     * this class can be called after the stream has been closed without\n     * generating an <tt>IOException</tt>.\n     *\n     * @author  Arthur van Hoff\n     * @since   JDK1.0\n     */\n    /*public*/ class ByteArrayOutputStream extends OutputStream {\n        /**\n         * Creates a new byte array output stream. The buffer capacity is\n         * initially 32 bytes, though its size increases if necessary.\n         */\n        // public constructor() {\n        //     this(32);\n        // }\n        /**\n         * Creates a new byte array output stream, with a buffer capacity of\n         * the specified size, in bytes.\n         *\n         * @param   size   the initial size.\n         * @exception  IllegalArgumentException if size is negative.\n         */\n        constructor(size = 32) {\n            super();\n            /**\n             * The number of valid bytes in the buffer.\n             */\n            this.count = 0;\n            if (size < 0) {\n                throw new IllegalArgumentException('Negative initial size: '\n                    + size);\n            }\n            this.buf = new Uint8Array(size);\n        }\n        /**\n         * Increases the capacity if necessary to ensure that it can hold\n         * at least the number of elements specified by the minimum\n         * capacity argument.\n         *\n         * @param minCapacity the desired minimum capacity\n         * @throws OutOfMemoryError if {@code minCapacity < 0}.  This is\n         * interpreted as a request for the unsatisfiably large capacity\n         * {@code (long) Integer.MAX_VALUE + (minCapacity - Integer.MAX_VALUE)}.\n         */\n        ensureCapacity(minCapacity) {\n            // overflow-conscious code\n            if (minCapacity - this.buf.length > 0)\n                this.grow(minCapacity);\n        }\n        /**\n         * Increases the capacity to ensure that it can hold at least the\n         * number of elements specified by the minimum capacity argument.\n         *\n         * @param minCapacity the desired minimum capacity\n         */\n        grow(minCapacity) {\n            // overflow-conscious code\n            let oldCapacity = this.buf.length;\n            let newCapacity = oldCapacity << 1;\n            if (newCapacity - minCapacity < 0)\n                newCapacity = minCapacity;\n            if (newCapacity < 0) {\n                if (minCapacity < 0) // overflow\n                    throw new OutOfMemoryError();\n                newCapacity = Integer.MAX_VALUE;\n            }\n            this.buf = Arrays.copyOfUint8Array(this.buf, newCapacity);\n        }\n        /**\n         * Writes the specified byte to this byte array output stream.\n         *\n         * @param   b   the byte to be written.\n         */\n        write(b) {\n            this.ensureCapacity(this.count + 1);\n            this.buf[this.count] = /*(byte)*/ b;\n            this.count += 1;\n        }\n        /**\n         * Writes <code>len</code> bytes from the specified byte array\n         * starting at offset <code>off</code> to this byte array output stream.\n         *\n         * @param   b     the data.\n         * @param   off   the start offset in the data.\n         * @param   len   the number of bytes to write.\n         */\n        writeBytesOffset(b, off, len) {\n            if ((off < 0) || (off > b.length) || (len < 0) ||\n                ((off + len) - b.length > 0)) {\n                throw new IndexOutOfBoundsException();\n            }\n            this.ensureCapacity(this.count + len);\n            System.arraycopy(b, off, this.buf, this.count, len);\n            this.count += len;\n        }\n        /**\n         * Writes the complete contents of this byte array output stream to\n         * the specified output stream argument, as if by calling the output\n         * stream's write method using <code>out.write(buf, 0, count)</code>.\n         *\n         * @param      out   the output stream to which to write the data.\n         * @exception  IOException  if an I/O error occurs.\n         */\n        writeTo(out) {\n            out.writeBytesOffset(this.buf, 0, this.count);\n        }\n        /**\n         * Resets the <code>count</code> field of this byte array output\n         * stream to zero, so that all currently accumulated output in the\n         * output stream is discarded. The output stream can be used again,\n         * reusing the already allocated buffer space.\n         *\n         * @see     java.io.ByteArrayInputStream#count\n         */\n        reset() {\n            this.count = 0;\n        }\n        /**\n         * Creates a newly allocated byte array. Its size is the current\n         * size of this output stream and the valid contents of the buffer\n         * have been copied into it.\n         *\n         * @return  the current contents of this output stream, as a byte array.\n         * @see     java.io.ByteArrayOutputStream#size()\n         */\n        toByteArray() {\n            return Arrays.copyOfUint8Array(this.buf, this.count);\n        }\n        /**\n         * Returns the current size of the buffer.\n         *\n         * @return  the value of the <code>count</code> field, which is the number\n         *          of valid bytes in this output stream.\n         * @see     java.io.ByteArrayOutputStream#count\n         */\n        size() {\n            return this.count;\n        }\n        toString(param) {\n            if (!param) {\n                return this.toString_void();\n            }\n            if (typeof param === 'string') {\n                return this.toString_string(param);\n            }\n            return this.toString_number(param);\n        }\n        /**\n         * Converts the buffer's contents into a string decoding bytes using the\n         * platform's default character set. The length of the new <tt>String</tt>\n         * is a function of the character set, and hence may not be equal to the\n         * size of the buffer.\n         *\n         * <p> This method always replaces malformed-input and unmappable-character\n         * sequences with the default replacement string for the platform's\n         * default character set. The {@linkplain java.nio.charset.CharsetDecoder}\n         * class should be used when more control over the decoding process is\n         * required.\n         *\n         * @return String decoded from the buffer's contents.\n         * @since  JDK1.1\n         */\n        toString_void() {\n            return new String(this.buf /*, 0, this.count*/).toString();\n        }\n        /**\n         * Converts the buffer's contents into a string by decoding the bytes using\n         * the specified {@link java.nio.charset.Charset charsetName}. The length of\n         * the new <tt>String</tt> is a function of the charset, and hence may not be\n         * equal to the length of the byte array.\n         *\n         * <p> This method always replaces malformed-input and unmappable-character\n         * sequences with this charset's default replacement string. The {@link\n         * java.nio.charset.CharsetDecoder} class should be used when more control\n         * over the decoding process is required.\n         *\n         * @param  charsetName  the name of a supported\n         *              {@linkplain java.nio.charset.Charset </code>charset<code>}\n         * @return String decoded from the buffer's contents.\n         * @exception  UnsupportedEncodingException\n         *             If the named charset is not supported\n         * @since   JDK1.1\n         */\n        toString_string(charsetName) {\n            return new String(this.buf /*, 0, this.count, charsetName*/).toString();\n        }\n        /**\n         * Creates a newly allocated string. Its size is the current size of\n         * the output stream and the valid contents of the buffer have been\n         * copied into it. Each character <i>c</i> in the resulting string is\n         * constructed from the corresponding element <i>b</i> in the byte\n         * array such that:\n         * <blockquote><pre>\n         *     c == (char)(((hibyte &amp; 0xff) &lt;&lt; 8) | (b &amp; 0xff))\n         * </pre></blockquote>\n         *\n         * @deprecated This method does not properly convert bytes into characters.\n         * As of JDK&nbsp;1.1, the preferred way to do this is via the\n         * <code>toString(String enc)</code> method, which takes an encoding-name\n         * argument, or the <code>toString()</code> method, which uses the\n         * platform's default character encoding.\n         *\n         * @param      hibyte    the high byte of each resulting Unicode character.\n         * @return     the current contents of the output stream, as a string.\n         * @see        java.io.ByteArrayOutputStream#size()\n         * @see        java.io.ByteArrayOutputStream#toString(String)\n         * @see        java.io.ByteArrayOutputStream#toString()\n         */\n        // @Deprecated\n        toString_number(hibyte) {\n            return new String(this.buf /*, hibyte, 0, this.count*/).toString();\n        }\n        /**\n         * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in\n         * this class can be called after the stream has been closed without\n         * generating an <tt>IOException</tt>.\n         * <p>\n         *\n         * @throws IOException\n         */\n        close() {\n        }\n    }\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*private*/ var Mode$2;\n    (function (Mode) {\n        Mode[Mode[\"ALPHA\"] = 0] = \"ALPHA\";\n        Mode[Mode[\"LOWER\"] = 1] = \"LOWER\";\n        Mode[Mode[\"MIXED\"] = 2] = \"MIXED\";\n        Mode[Mode[\"PUNCT\"] = 3] = \"PUNCT\";\n        Mode[Mode[\"ALPHA_SHIFT\"] = 4] = \"ALPHA_SHIFT\";\n        Mode[Mode[\"PUNCT_SHIFT\"] = 5] = \"PUNCT_SHIFT\";\n    })(Mode$2 || (Mode$2 = {}));\n    /**\n     * Indirectly access the global BigInt constructor, it\n     * allows browsers that doesn't support BigInt to run\n     * the library without breaking due to \"undefined BigInt\"\n     * errors.\n     */\n    function getBigIntConstructor() {\n        if (typeof window !== 'undefined') {\n            return window['BigInt'] || null;\n        }\n        if (typeof __webpack_require__.g !== 'undefined') {\n            return __webpack_require__.g['BigInt'] || null;\n        }\n        if (typeof self !== 'undefined') {\n            return self['BigInt'] || null;\n        }\n        throw new Error('Can\\'t search globals for BigInt!');\n    }\n    /**\n     * Used to store the BigInt constructor.\n     */\n    let BigInteger;\n    /**\n     * This function creates a bigint value. It allows browsers\n     * that doesn't support BigInt to run the rest of the library\n     * by not directly accessing the BigInt constructor.\n     */\n    function createBigInt(num) {\n        if (typeof BigInteger === 'undefined') {\n            BigInteger = getBigIntConstructor();\n        }\n        if (BigInteger === null) {\n            throw new Error('BigInt is not supported!');\n        }\n        return BigInteger(num);\n    }\n    function getEXP900() {\n        // in Java - array with length = 16\n        let EXP900 = [];\n        EXP900[0] = createBigInt(1);\n        let nineHundred = createBigInt(900);\n        EXP900[1] = nineHundred;\n        // in Java - array with length = 16\n        for (let i /*int*/ = 2; i < 16; i++) {\n            EXP900[i] = EXP900[i - 1] * nineHundred;\n        }\n        return EXP900;\n    }\n    /**\n     * <p>This class contains the methods for decoding the PDF417 codewords.</p>\n     *\n     * @author SITA Lab (kevin.osullivan@sita.aero)\n     * @author Guenther Grau\n     */\n    /*final*/ class DecodedBitStreamParser$2 {\n        //   private DecodedBitStreamParser() {\n        // }\n        /**\n         *\n         * @param codewords\n         * @param ecLevel\n         *\n         * @throws FormatException\n         */\n        static decode(codewords, ecLevel) {\n            // pass encoding to result (will be used for decode symbols in byte mode)\n            let result = new StringBuilder('');\n            // let encoding: Charset = StandardCharsets.ISO_8859_1;\n            let encoding = CharacterSetECI.ISO8859_1;\n            /**\n             * @note the next command is specific from this TypeScript library\n             * because TS can't properly cast some values to char and\n             * convert it to string later correctly due to encoding\n             * differences from Java version. As reported here:\n             * https://github.com/zxing-js/library/pull/264/files#r382831593\n             */\n            result.enableDecoding(encoding);\n            // Get compaction mode\n            let codeIndex = 1;\n            let code = codewords[codeIndex++];\n            let resultMetadata = new PDF417ResultMetadata();\n            while (codeIndex < codewords[0]) {\n                switch (code) {\n                    case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                        codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex, result);\n                        break;\n                    case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n                    case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n                        codeIndex = DecodedBitStreamParser$2.byteCompaction(code, codewords, encoding, codeIndex, result);\n                        break;\n                    case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n                        result.append(/*(char)*/ codewords[codeIndex++]);\n                        break;\n                    case DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH:\n                        codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex, result);\n                        break;\n                    case DecodedBitStreamParser$2.ECI_CHARSET:\n                        let charsetECI = CharacterSetECI.getCharacterSetECIByValue(codewords[codeIndex++]);\n                        // encoding = Charset.forName(charsetECI.getName());\n                        break;\n                    case DecodedBitStreamParser$2.ECI_GENERAL_PURPOSE:\n                        // Can't do anything with generic ECI; skip its 2 characters\n                        codeIndex += 2;\n                        break;\n                    case DecodedBitStreamParser$2.ECI_USER_DEFINED:\n                        // Can't do anything with user ECI; skip its 1 character\n                        codeIndex++;\n                        break;\n                    case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n                        codeIndex = DecodedBitStreamParser$2.decodeMacroBlock(codewords, codeIndex, resultMetadata);\n                        break;\n                    case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n                    case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n                        // Should not see these outside a macro block\n                        throw new FormatException();\n                    default:\n                        // Default to text compaction. During testing numerous barcodes\n                        // appeared to be missing the starting mode. In these cases defaulting\n                        // to text compaction seems to work.\n                        codeIndex--;\n                        codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex, result);\n                        break;\n                }\n                if (codeIndex < codewords.length) {\n                    code = codewords[codeIndex++];\n                }\n                else {\n                    throw FormatException.getFormatInstance();\n                }\n            }\n            if (result.length() === 0) {\n                throw FormatException.getFormatInstance();\n            }\n            let decoderResult = new DecoderResult(null, result.toString(), null, ecLevel);\n            decoderResult.setOther(resultMetadata);\n            return decoderResult;\n        }\n        /**\n         *\n         * @param int\n         * @param param1\n         * @param codewords\n         * @param int\n         * @param codeIndex\n         * @param PDF417ResultMetadata\n         * @param resultMetadata\n         *\n         * @throws FormatException\n         */\n        // @SuppressWarnings(\"deprecation\")\n        static decodeMacroBlock(codewords, codeIndex, resultMetadata) {\n            if (codeIndex + DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS > codewords[0]) {\n                // we must have at least two bytes left for the segment index\n                throw FormatException.getFormatInstance();\n            }\n            let segmentIndexArray = new Int32Array(DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS);\n            for (let i /*int*/ = 0; i < DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS; i++, codeIndex++) {\n                segmentIndexArray[i] = codewords[codeIndex];\n            }\n            resultMetadata.setSegmentIndex(Integer.parseInt(DecodedBitStreamParser$2.decodeBase900toBase10(segmentIndexArray, DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS)));\n            let fileId = new StringBuilder();\n            codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex, fileId);\n            resultMetadata.setFileId(fileId.toString());\n            let optionalFieldsStart = -1;\n            if (codewords[codeIndex] === DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD) {\n                optionalFieldsStart = codeIndex + 1;\n            }\n            while (codeIndex < codewords[0]) {\n                switch (codewords[codeIndex]) {\n                    case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n                        codeIndex++;\n                        switch (codewords[codeIndex]) {\n                            case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME:\n                                let fileName = new StringBuilder();\n                                codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex + 1, fileName);\n                                resultMetadata.setFileName(fileName.toString());\n                                break;\n                            case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_SENDER:\n                                let sender = new StringBuilder();\n                                codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex + 1, sender);\n                                resultMetadata.setSender(sender.toString());\n                                break;\n                            case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE:\n                                let addressee = new StringBuilder();\n                                codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex + 1, addressee);\n                                resultMetadata.setAddressee(addressee.toString());\n                                break;\n                            case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT:\n                                let segmentCount = new StringBuilder();\n                                codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex + 1, segmentCount);\n                                resultMetadata.setSegmentCount(Integer.parseInt(segmentCount.toString()));\n                                break;\n                            case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP:\n                                let timestamp = new StringBuilder();\n                                codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex + 1, timestamp);\n                                resultMetadata.setTimestamp(Long.parseLong(timestamp.toString()));\n                                break;\n                            case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM:\n                                let checksum = new StringBuilder();\n                                codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex + 1, checksum);\n                                resultMetadata.setChecksum(Integer.parseInt(checksum.toString()));\n                                break;\n                            case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE:\n                                let fileSize = new StringBuilder();\n                                codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex + 1, fileSize);\n                                resultMetadata.setFileSize(Long.parseLong(fileSize.toString()));\n                                break;\n                            default:\n                                throw FormatException.getFormatInstance();\n                        }\n                        break;\n                    case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n                        codeIndex++;\n                        resultMetadata.setLastSegment(true);\n                        break;\n                    default:\n                        throw FormatException.getFormatInstance();\n                }\n            }\n            // copy optional fields to additional options\n            if (optionalFieldsStart !== -1) {\n                let optionalFieldsLength = codeIndex - optionalFieldsStart;\n                if (resultMetadata.isLastSegment()) {\n                    // do not include terminator\n                    optionalFieldsLength--;\n                }\n                resultMetadata.setOptionalData(Arrays.copyOfRange(codewords, optionalFieldsStart, optionalFieldsStart + optionalFieldsLength));\n            }\n            return codeIndex;\n        }\n        /**\n         * Text Compaction mode (see 5.4.1.5) permits all printable ASCII characters to be\n         * encoded, i.e. values 32 - 126 inclusive in accordance with ISO/IEC 646 (IRV), as\n         * well as selected control characters.\n         *\n         * @param codewords The array of codewords (data + error)\n         * @param codeIndex The current index into the codeword array.\n         * @param result    The decoded data is appended to the result.\n         * @return The next index into the codeword array.\n         */\n        static textCompaction(codewords, codeIndex, result) {\n            // 2 character per codeword\n            let textCompactionData = new Int32Array((codewords[0] - codeIndex) * 2);\n            // Used to hold the byte compaction value if there is a mode shift\n            let byteCompactionData = new Int32Array((codewords[0] - codeIndex) * 2);\n            let index = 0;\n            let end = false;\n            while ((codeIndex < codewords[0]) && !end) {\n                let code = codewords[codeIndex++];\n                if (code < DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH) {\n                    textCompactionData[index] = code / 30;\n                    textCompactionData[index + 1] = code % 30;\n                    index += 2;\n                }\n                else {\n                    switch (code) {\n                        case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                            // reinitialize text compaction mode to alpha sub mode\n                            textCompactionData[index++] = DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH;\n                            break;\n                        case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n                        case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n                        case DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH:\n                        case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n                        case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n                        case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n                            codeIndex--;\n                            end = true;\n                            break;\n                        case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n                            // The Mode Shift codeword 913 shall cause a temporary\n                            // switch from Text Compaction mode to Byte Compaction mode.\n                            // This switch shall be in effect for only the next codeword,\n                            // after which the mode shall revert to the prevailing sub-mode\n                            // of the Text Compaction mode. Codeword 913 is only available\n                            // in Text Compaction mode; its use is described in 5.4.2.4.\n                            textCompactionData[index] = DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE;\n                            code = codewords[codeIndex++];\n                            byteCompactionData[index] = code;\n                            index++;\n                            break;\n                    }\n                }\n            }\n            DecodedBitStreamParser$2.decodeTextCompaction(textCompactionData, byteCompactionData, index, result);\n            return codeIndex;\n        }\n        /**\n         * The Text Compaction mode includes all the printable ASCII characters\n         * (i.e. values from 32 to 126) and three ASCII control characters: HT or tab\n         * (9: e), LF or line feed (10: e), and CR or carriage\n         * return (13: e). The Text Compaction mode also includes various latch\n         * and shift characters which are used exclusively within the mode. The Text\n         * Compaction mode encodes up to 2 characters per codeword. The compaction rules\n         * for converting data into PDF417 codewords are defined in 5.4.2.2. The sub-mode\n         * switches are defined in 5.4.2.3.\n         *\n         * @param textCompactionData The text compaction data.\n         * @param byteCompactionData The byte compaction data if there\n         *                           was a mode shift.\n         * @param length             The size of the text compaction and byte compaction data.\n         * @param result             The decoded data is appended to the result.\n         */\n        static decodeTextCompaction(textCompactionData, byteCompactionData, length, result) {\n            // Beginning from an initial state of the Alpha sub-mode\n            // The default compaction mode for PDF417 in effect at the start of each symbol shall always be Text\n            // Compaction mode Alpha sub-mode (alphabetic: uppercase). A latch codeword from another mode to the Text\n            // Compaction mode shall always switch to the Text Compaction Alpha sub-mode.\n            let subMode = Mode$2.ALPHA;\n            let priorToShiftMode = Mode$2.ALPHA;\n            let i = 0;\n            while (i < length) {\n                let subModeCh = textCompactionData[i];\n                let ch = /*char*/ '';\n                switch (subMode) {\n                    case Mode$2.ALPHA:\n                        // Alpha (alphabetic: uppercase)\n                        if (subModeCh < 26) {\n                            // Upper case Alpha Character\n                            // Note: 65 = 'A' ASCII -> there is byte code of symbol\n                            ch = /*(char)('A' + subModeCh) */ String.fromCharCode(65 + subModeCh);\n                        }\n                        else {\n                            switch (subModeCh) {\n                                case 26:\n                                    ch = ' ';\n                                    break;\n                                case DecodedBitStreamParser$2.LL:\n                                    subMode = Mode$2.LOWER;\n                                    break;\n                                case DecodedBitStreamParser$2.ML:\n                                    subMode = Mode$2.MIXED;\n                                    break;\n                                case DecodedBitStreamParser$2.PS:\n                                    // Shift to punctuation\n                                    priorToShiftMode = subMode;\n                                    subMode = Mode$2.PUNCT_SHIFT;\n                                    break;\n                                case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n                                    result.append(/*(char)*/ byteCompactionData[i]);\n                                    break;\n                                case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                            }\n                        }\n                        break;\n                    case Mode$2.LOWER:\n                        // Lower (alphabetic: lowercase)\n                        if (subModeCh < 26) {\n                            ch = /*(char)('a' + subModeCh)*/ String.fromCharCode(97 + subModeCh);\n                        }\n                        else {\n                            switch (subModeCh) {\n                                case 26:\n                                    ch = ' ';\n                                    break;\n                                case DecodedBitStreamParser$2.AS:\n                                    // Shift to alpha\n                                    priorToShiftMode = subMode;\n                                    subMode = Mode$2.ALPHA_SHIFT;\n                                    break;\n                                case DecodedBitStreamParser$2.ML:\n                                    subMode = Mode$2.MIXED;\n                                    break;\n                                case DecodedBitStreamParser$2.PS:\n                                    // Shift to punctuation\n                                    priorToShiftMode = subMode;\n                                    subMode = Mode$2.PUNCT_SHIFT;\n                                    break;\n                                case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n                                    // TODO Does this need to use the current character encoding? See other occurrences below\n                                    result.append(/*(char)*/ byteCompactionData[i]);\n                                    break;\n                                case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                            }\n                        }\n                        break;\n                    case Mode$2.MIXED:\n                        // Mixed (punctuation: e)\n                        if (subModeCh < DecodedBitStreamParser$2.PL) {\n                            ch = DecodedBitStreamParser$2.MIXED_CHARS[subModeCh];\n                        }\n                        else {\n                            switch (subModeCh) {\n                                case DecodedBitStreamParser$2.PL:\n                                    subMode = Mode$2.PUNCT;\n                                    break;\n                                case 26:\n                                    ch = ' ';\n                                    break;\n                                case DecodedBitStreamParser$2.LL:\n                                    subMode = Mode$2.LOWER;\n                                    break;\n                                case DecodedBitStreamParser$2.AL:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                                case DecodedBitStreamParser$2.PS:\n                                    // Shift to punctuation\n                                    priorToShiftMode = subMode;\n                                    subMode = Mode$2.PUNCT_SHIFT;\n                                    break;\n                                case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n                                    result.append(/*(char)*/ byteCompactionData[i]);\n                                    break;\n                                case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                            }\n                        }\n                        break;\n                    case Mode$2.PUNCT:\n                        // Punctuation\n                        if (subModeCh < DecodedBitStreamParser$2.PAL) {\n                            ch = DecodedBitStreamParser$2.PUNCT_CHARS[subModeCh];\n                        }\n                        else {\n                            switch (subModeCh) {\n                                case DecodedBitStreamParser$2.PAL:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                                case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n                                    result.append(/*(char)*/ byteCompactionData[i]);\n                                    break;\n                                case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                            }\n                        }\n                        break;\n                    case Mode$2.ALPHA_SHIFT:\n                        // Restore sub-mode\n                        subMode = priorToShiftMode;\n                        if (subModeCh < 26) {\n                            ch = /*(char)('A' + subModeCh)*/ String.fromCharCode(65 + subModeCh);\n                        }\n                        else {\n                            switch (subModeCh) {\n                                case 26:\n                                    ch = ' ';\n                                    break;\n                                case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                            }\n                        }\n                        break;\n                    case Mode$2.PUNCT_SHIFT:\n                        // Restore sub-mode\n                        subMode = priorToShiftMode;\n                        if (subModeCh < DecodedBitStreamParser$2.PAL) {\n                            ch = DecodedBitStreamParser$2.PUNCT_CHARS[subModeCh];\n                        }\n                        else {\n                            switch (subModeCh) {\n                                case DecodedBitStreamParser$2.PAL:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                                case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n                                    // PS before Shift-to-Byte is used as a padding character,\n                                    // see 5.4.2.4 of the specification\n                                    result.append(/*(char)*/ byteCompactionData[i]);\n                                    break;\n                                case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                                    subMode = Mode$2.ALPHA;\n                                    break;\n                            }\n                        }\n                        break;\n                }\n                // if (ch !== 0) {\n                if (ch !== '') {\n                    // Append decoded character to result\n                    result.append(ch);\n                }\n                i++;\n            }\n        }\n        /**\n         * Byte Compaction mode (see 5.4.3) permits all 256 possible 8-bit byte values to be encoded.\n         * This includes all ASCII characters value 0 to 127 inclusive and provides for international\n         * character set support.\n         *\n         * @param mode      The byte compaction mode i.e. 901 or 924\n         * @param codewords The array of codewords (data + error)\n         * @param encoding  Currently active character encoding\n         * @param codeIndex The current index into the codeword array.\n         * @param result    The decoded data is appended to the result.\n         * @return The next index into the codeword array.\n         */\n        static /*int*/ byteCompaction(mode, codewords, encoding, codeIndex, result) {\n            let decodedBytes = new ByteArrayOutputStream();\n            let count = 0;\n            let value = /*long*/ 0;\n            let end = false;\n            switch (mode) {\n                case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n                    // Total number of Byte Compaction characters to be encoded\n                    // is not a multiple of 6\n                    let byteCompactedCodewords = new Int32Array(6);\n                    let nextCode = codewords[codeIndex++];\n                    while ((codeIndex < codewords[0]) && !end) {\n                        byteCompactedCodewords[count++] = nextCode;\n                        // Base 900\n                        value = 900 * value + nextCode;\n                        nextCode = codewords[codeIndex++];\n                        // perhaps it should be ok to check only nextCode >= TEXT_COMPACTION_MODE_LATCH\n                        switch (nextCode) {\n                            case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                            case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n                            case DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH:\n                            case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n                            case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n                            case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n                            case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n                                codeIndex--;\n                                end = true;\n                                break;\n                            default:\n                                if ((count % 5 === 0) && (count > 0)) {\n                                    // Decode every 5 codewords\n                                    // Convert to Base 256\n                                    for (let j /*int*/ = 0; j < 6; ++j) {\n                                        /* @note\n                                         * JavaScript stores numbers as 64 bits floating point numbers, but all bitwise operations are performed on 32 bits binary numbers.\n                                         * So the next bitwise operation could not be done with simple numbers\n                                         */\n                                        decodedBytes.write(/*(byte)*/ Number(createBigInt(value) >> createBigInt(8 * (5 - j))));\n                                    }\n                                    value = 0;\n                                    count = 0;\n                                }\n                                break;\n                        }\n                    }\n                    // if the end of all codewords is reached the last codeword needs to be added\n                    if (codeIndex === codewords[0] && nextCode < DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH) {\n                        byteCompactedCodewords[count++] = nextCode;\n                    }\n                    // If Byte Compaction mode is invoked with codeword 901,\n                    // the last group of codewords is interpreted directly\n                    // as one byte per codeword, without compaction.\n                    for (let i /*int*/ = 0; i < count; i++) {\n                        decodedBytes.write(/*(byte)*/ byteCompactedCodewords[i]);\n                    }\n                    break;\n                case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n                    // Total number of Byte Compaction characters to be encoded\n                    // is an integer multiple of 6\n                    while (codeIndex < codewords[0] && !end) {\n                        let code = codewords[codeIndex++];\n                        if (code < DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH) {\n                            count++;\n                            // Base 900\n                            value = 900 * value + code;\n                        }\n                        else {\n                            switch (code) {\n                                case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                                case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n                                case DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH:\n                                case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n                                case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n                                case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n                                case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n                                    codeIndex--;\n                                    end = true;\n                                    break;\n                            }\n                        }\n                        if ((count % 5 === 0) && (count > 0)) {\n                            // Decode every 5 codewords\n                            // Convert to Base 256\n                            /* @note\n                             * JavaScript stores numbers as 64 bits floating point numbers, but all bitwise operations are performed on 32 bits binary numbers.\n                             * So the next bitwise operation could not be done with simple numbers\n                            */\n                            for (let j /*int*/ = 0; j < 6; ++j) {\n                                decodedBytes.write(/*(byte)*/ Number(createBigInt(value) >> createBigInt(8 * (5 - j))));\n                            }\n                            value = 0;\n                            count = 0;\n                        }\n                    }\n                    break;\n            }\n            result.append(StringEncoding.decode(decodedBytes.toByteArray(), encoding));\n            return codeIndex;\n        }\n        /**\n         * Numeric Compaction mode (see 5.4.4) permits efficient encoding of numeric data strings.\n         *\n         * @param codewords The array of codewords (data + error)\n         * @param codeIndex The current index into the codeword array.\n         * @param result    The decoded data is appended to the result.\n         * @return The next index into the codeword array.\n         *\n         * @throws FormatException\n         */\n        static numericCompaction(codewords, codeIndex /*int*/, result) {\n            let count = 0;\n            let end = false;\n            let numericCodewords = new Int32Array(DecodedBitStreamParser$2.MAX_NUMERIC_CODEWORDS);\n            while (codeIndex < codewords[0] && !end) {\n                let code = codewords[codeIndex++];\n                if (codeIndex === codewords[0]) {\n                    end = true;\n                }\n                if (code < DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH) {\n                    numericCodewords[count] = code;\n                    count++;\n                }\n                else {\n                    switch (code) {\n                        case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n                        case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n                        case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n                        case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n                        case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n                        case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n                            codeIndex--;\n                            end = true;\n                            break;\n                    }\n                }\n                if ((count % DecodedBitStreamParser$2.MAX_NUMERIC_CODEWORDS === 0 || code === DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH || end) && count > 0) {\n                    // Re-invoking Numeric Compaction mode (by using codeword 902\n                    // while in Numeric Compaction mode) serves  to terminate the\n                    // current Numeric Compaction mode grouping as described in 5.4.4.2,\n                    // and then to start a new one grouping.\n                    result.append(DecodedBitStreamParser$2.decodeBase900toBase10(numericCodewords, count));\n                    count = 0;\n                }\n            }\n            return codeIndex;\n        }\n        /**\n         * Convert a list of Numeric Compacted codewords from Base 900 to Base 10.\n         *\n         * @param codewords The array of codewords\n         * @param count     The number of codewords\n         * @return The decoded string representing the Numeric data.\n         *\n         * EXAMPLE\n         * Encode the fifteen digit numeric string 000213298174000\n         * Prefix the numeric string with a 1 and set the initial value of\n         * t = 1 000 213 298 174 000\n         * Calculate codeword 0\n         * d0 = 1 000 213 298 174 000 mod 900 = 200\n         *\n         * t = 1 000 213 298 174 000 div 900 = 1 111 348 109 082\n         * Calculate codeword 1\n         * d1 = 1 111 348 109 082 mod 900 = 282\n         *\n         * t = 1 111 348 109 082 div 900 = 1 234 831 232\n         * Calculate codeword 2\n         * d2 = 1 234 831 232 mod 900 = 632\n         *\n         * t = 1 234 831 232 div 900 = 1 372 034\n         * Calculate codeword 3\n         * d3 = 1 372 034 mod 900 = 434\n         *\n         * t = 1 372 034 div 900 = 1 524\n         * Calculate codeword 4\n         * d4 = 1 524 mod 900 = 624\n         *\n         * t = 1 524 div 900 = 1\n         * Calculate codeword 5\n         * d5 = 1 mod 900 = 1\n         * t = 1 div 900 = 0\n         * Codeword sequence is: 1, 624, 434, 632, 282, 200\n         *\n         * Decode the above codewords involves\n         *   1 x 900 power of 5 + 624 x 900 power of 4 + 434 x 900 power of 3 +\n         * 632 x 900 power of 2 + 282 x 900 power of 1 + 200 x 900 power of 0 = 1000213298174000\n         *\n         * Remove leading 1 =>  Result is 000213298174000\n         *\n         * @throws FormatException\n         */\n        static decodeBase900toBase10(codewords, count) {\n            let result = createBigInt(0);\n            for (let i /*int*/ = 0; i < count; i++) {\n                result += DecodedBitStreamParser$2.EXP900[count - i - 1] * createBigInt(codewords[i]);\n            }\n            let resultString = result.toString();\n            if (resultString.charAt(0) !== '1') {\n                throw new FormatException();\n            }\n            return resultString.substring(1);\n        }\n    }\n    DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH = 900;\n    DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH = 901;\n    DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH = 902;\n    DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6 = 924;\n    DecodedBitStreamParser$2.ECI_USER_DEFINED = 925;\n    DecodedBitStreamParser$2.ECI_GENERAL_PURPOSE = 926;\n    DecodedBitStreamParser$2.ECI_CHARSET = 927;\n    DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK = 928;\n    DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD = 923;\n    DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR = 922;\n    DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE = 913;\n    DecodedBitStreamParser$2.MAX_NUMERIC_CODEWORDS = 15;\n    DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME = 0;\n    DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT = 1;\n    DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP = 2;\n    DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_SENDER = 3;\n    DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE = 4;\n    DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE = 5;\n    DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM = 6;\n    DecodedBitStreamParser$2.PL = 25;\n    DecodedBitStreamParser$2.LL = 27;\n    DecodedBitStreamParser$2.AS = 27;\n    DecodedBitStreamParser$2.ML = 28;\n    DecodedBitStreamParser$2.AL = 28;\n    DecodedBitStreamParser$2.PS = 29;\n    DecodedBitStreamParser$2.PAL = 29;\n    DecodedBitStreamParser$2.PUNCT_CHARS = ';<>@[\\\\]_`~!\\r\\t,:\\n-.$/\"|*()?{}\\'';\n    DecodedBitStreamParser$2.MIXED_CHARS = '0123456789&\\r\\t,:#-.$/+%*=^';\n    /**\n     * Table containing values for the exponent of 900.\n     * This is used in the numeric compaction decode algorithm.\n     */\n    DecodedBitStreamParser$2.EXP900 = getBigIntConstructor() ? getEXP900() : [];\n    DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS = 2;\n\n    /*\n    * Copyright 2013 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    // import java.util.ArrayList;\n    // import java.util.Collection;\n    // import java.util.Formatter;\n    // import java.util.List;\n    /**\n     * @author Guenther Grau\n     */\n    /*public final*/ class PDF417ScanningDecoder {\n        constructor() { }\n        /**\n         * @TODO don't pass in minCodewordWidth and maxCodewordWidth, pass in barcode columns for start and stop pattern\n         *\n         * columns. That way width can be deducted from the pattern column.\n         * This approach also allows to detect more details about the barcode, e.g. if a bar type (white or black) is wider\n         * than it should be. This can happen if the scanner used a bad blackpoint.\n         *\n         * @param BitMatrix\n         * @param image\n         * @param ResultPoint\n         * @param imageTopLeft\n         * @param ResultPoint\n         * @param imageBottomLeft\n         * @param ResultPoint\n         * @param imageTopRight\n         * @param ResultPoint\n         * @param imageBottomRight\n         * @param int\n         * @param minCodewordWidth\n         * @param int\n         * @param maxCodewordWidth\n         *\n         * @throws NotFoundException\n         * @throws FormatException\n         * @throws ChecksumException\n         */\n        static decode(image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight, minCodewordWidth, maxCodewordWidth) {\n            let boundingBox = new BoundingBox(image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight);\n            let leftRowIndicatorColumn = null;\n            let rightRowIndicatorColumn = null;\n            let detectionResult;\n            for (let firstPass /*boolean*/ = true;; firstPass = false) {\n                if (imageTopLeft != null) {\n                    leftRowIndicatorColumn = PDF417ScanningDecoder.getRowIndicatorColumn(image, boundingBox, imageTopLeft, true, minCodewordWidth, maxCodewordWidth);\n                }\n                if (imageTopRight != null) {\n                    rightRowIndicatorColumn = PDF417ScanningDecoder.getRowIndicatorColumn(image, boundingBox, imageTopRight, false, minCodewordWidth, maxCodewordWidth);\n                }\n                detectionResult = PDF417ScanningDecoder.merge(leftRowIndicatorColumn, rightRowIndicatorColumn);\n                if (detectionResult == null) {\n                    throw NotFoundException.getNotFoundInstance();\n                }\n                let resultBox = detectionResult.getBoundingBox();\n                if (firstPass && resultBox != null &&\n                    (resultBox.getMinY() < boundingBox.getMinY() || resultBox.getMaxY() > boundingBox.getMaxY())) {\n                    boundingBox = resultBox;\n                }\n                else {\n                    break;\n                }\n            }\n            detectionResult.setBoundingBox(boundingBox);\n            let maxBarcodeColumn = detectionResult.getBarcodeColumnCount() + 1;\n            detectionResult.setDetectionResultColumn(0, leftRowIndicatorColumn);\n            detectionResult.setDetectionResultColumn(maxBarcodeColumn, rightRowIndicatorColumn);\n            let leftToRight = leftRowIndicatorColumn != null;\n            for (let barcodeColumnCount /*int*/ = 1; barcodeColumnCount <= maxBarcodeColumn; barcodeColumnCount++) {\n                let barcodeColumn = leftToRight ? barcodeColumnCount : maxBarcodeColumn - barcodeColumnCount;\n                if (detectionResult.getDetectionResultColumn(barcodeColumn) !== /* null */ undefined) {\n                    // This will be the case for the opposite row indicator column, which doesn't need to be decoded again.\n                    continue;\n                }\n                let detectionResultColumn;\n                if (barcodeColumn === 0 || barcodeColumn === maxBarcodeColumn) {\n                    detectionResultColumn = new DetectionResultRowIndicatorColumn(boundingBox, barcodeColumn === 0);\n                }\n                else {\n                    detectionResultColumn = new DetectionResultColumn(boundingBox);\n                }\n                detectionResult.setDetectionResultColumn(barcodeColumn, detectionResultColumn);\n                let startColumn = -1;\n                let previousStartColumn = startColumn;\n                // TODO start at a row for which we know the start position, then detect upwards and downwards from there.\n                for (let imageRow /*int*/ = boundingBox.getMinY(); imageRow <= boundingBox.getMaxY(); imageRow++) {\n                    startColumn = PDF417ScanningDecoder.getStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight);\n                    if (startColumn < 0 || startColumn > boundingBox.getMaxX()) {\n                        if (previousStartColumn === -1) {\n                            continue;\n                        }\n                        startColumn = previousStartColumn;\n                    }\n                    let codeword = PDF417ScanningDecoder.detectCodeword(image, boundingBox.getMinX(), boundingBox.getMaxX(), leftToRight, startColumn, imageRow, minCodewordWidth, maxCodewordWidth);\n                    if (codeword != null) {\n                        detectionResultColumn.setCodeword(imageRow, codeword);\n                        previousStartColumn = startColumn;\n                        minCodewordWidth = Math.min(minCodewordWidth, codeword.getWidth());\n                        maxCodewordWidth = Math.max(maxCodewordWidth, codeword.getWidth());\n                    }\n                }\n            }\n            return PDF417ScanningDecoder.createDecoderResult(detectionResult);\n        }\n        /**\n         *\n         * @param leftRowIndicatorColumn\n         * @param rightRowIndicatorColumn\n         *\n         * @throws NotFoundException\n         */\n        static merge(leftRowIndicatorColumn, rightRowIndicatorColumn) {\n            if (leftRowIndicatorColumn == null && rightRowIndicatorColumn == null) {\n                return null;\n            }\n            let barcodeMetadata = PDF417ScanningDecoder.getBarcodeMetadata(leftRowIndicatorColumn, rightRowIndicatorColumn);\n            if (barcodeMetadata == null) {\n                return null;\n            }\n            let boundingBox = BoundingBox.merge(PDF417ScanningDecoder.adjustBoundingBox(leftRowIndicatorColumn), PDF417ScanningDecoder.adjustBoundingBox(rightRowIndicatorColumn));\n            return new DetectionResult(barcodeMetadata, boundingBox);\n        }\n        /**\n         *\n         * @param rowIndicatorColumn\n         *\n         * @throws NotFoundException\n         */\n        static adjustBoundingBox(rowIndicatorColumn) {\n            if (rowIndicatorColumn == null) {\n                return null;\n            }\n            let rowHeights = rowIndicatorColumn.getRowHeights();\n            if (rowHeights == null) {\n                return null;\n            }\n            let maxRowHeight = PDF417ScanningDecoder.getMax(rowHeights);\n            let missingStartRows = 0;\n            for (let rowHeight /*int*/ of rowHeights) {\n                missingStartRows += maxRowHeight - rowHeight;\n                if (rowHeight > 0) {\n                    break;\n                }\n            }\n            let codewords = rowIndicatorColumn.getCodewords();\n            for (let row /*int*/ = 0; missingStartRows > 0 && codewords[row] == null; row++) {\n                missingStartRows--;\n            }\n            let missingEndRows = 0;\n            for (let row /*int*/ = rowHeights.length - 1; row >= 0; row--) {\n                missingEndRows += maxRowHeight - rowHeights[row];\n                if (rowHeights[row] > 0) {\n                    break;\n                }\n            }\n            for (let row /*int*/ = codewords.length - 1; missingEndRows > 0 && codewords[row] == null; row--) {\n                missingEndRows--;\n            }\n            return rowIndicatorColumn.getBoundingBox().addMissingRows(missingStartRows, missingEndRows, rowIndicatorColumn.isLeft());\n        }\n        static getMax(values) {\n            let maxValue = -1;\n            for (let value /*int*/ of values) {\n                maxValue = Math.max(maxValue, value);\n            }\n            return maxValue;\n        }\n        static getBarcodeMetadata(leftRowIndicatorColumn, rightRowIndicatorColumn) {\n            let leftBarcodeMetadata;\n            if (leftRowIndicatorColumn == null ||\n                (leftBarcodeMetadata = leftRowIndicatorColumn.getBarcodeMetadata()) == null) {\n                return rightRowIndicatorColumn == null ? null : rightRowIndicatorColumn.getBarcodeMetadata();\n            }\n            let rightBarcodeMetadata;\n            if (rightRowIndicatorColumn == null ||\n                (rightBarcodeMetadata = rightRowIndicatorColumn.getBarcodeMetadata()) == null) {\n                return leftBarcodeMetadata;\n            }\n            if (leftBarcodeMetadata.getColumnCount() !== rightBarcodeMetadata.getColumnCount() &&\n                leftBarcodeMetadata.getErrorCorrectionLevel() !== rightBarcodeMetadata.getErrorCorrectionLevel() &&\n                leftBarcodeMetadata.getRowCount() !== rightBarcodeMetadata.getRowCount()) {\n                return null;\n            }\n            return leftBarcodeMetadata;\n        }\n        static getRowIndicatorColumn(image, boundingBox, startPoint, leftToRight, minCodewordWidth, maxCodewordWidth) {\n            let rowIndicatorColumn = new DetectionResultRowIndicatorColumn(boundingBox, leftToRight);\n            for (let i /*int*/ = 0; i < 2; i++) {\n                let increment = i === 0 ? 1 : -1;\n                let startColumn = Math.trunc(Math.trunc(startPoint.getX()));\n                for (let imageRow /*int*/ = Math.trunc(Math.trunc(startPoint.getY())); imageRow <= boundingBox.getMaxY() &&\n                    imageRow >= boundingBox.getMinY(); imageRow += increment) {\n                    let codeword = PDF417ScanningDecoder.detectCodeword(image, 0, image.getWidth(), leftToRight, startColumn, imageRow, minCodewordWidth, maxCodewordWidth);\n                    if (codeword != null) {\n                        rowIndicatorColumn.setCodeword(imageRow, codeword);\n                        if (leftToRight) {\n                            startColumn = codeword.getStartX();\n                        }\n                        else {\n                            startColumn = codeword.getEndX();\n                        }\n                    }\n                }\n            }\n            return rowIndicatorColumn;\n        }\n        /**\n         *\n         * @param detectionResult\n         * @param BarcodeValue\n         * @param param2\n         * @param param3\n         * @param barcodeMatrix\n         *\n         * @throws NotFoundException\n         */\n        static adjustCodewordCount(detectionResult, barcodeMatrix) {\n            let barcodeMatrix01 = barcodeMatrix[0][1];\n            let numberOfCodewords = barcodeMatrix01.getValue();\n            let calculatedNumberOfCodewords = detectionResult.getBarcodeColumnCount() *\n                detectionResult.getBarcodeRowCount() -\n                PDF417ScanningDecoder.getNumberOfECCodeWords(detectionResult.getBarcodeECLevel());\n            if (numberOfCodewords.length === 0) {\n                if (calculatedNumberOfCodewords < 1 || calculatedNumberOfCodewords > PDF417Common.MAX_CODEWORDS_IN_BARCODE) {\n                    throw NotFoundException.getNotFoundInstance();\n                }\n                barcodeMatrix01.setValue(calculatedNumberOfCodewords);\n            }\n            else if (numberOfCodewords[0] !== calculatedNumberOfCodewords) {\n                // The calculated one is more reliable as it is derived from the row indicator columns\n                barcodeMatrix01.setValue(calculatedNumberOfCodewords);\n            }\n        }\n        /**\n         *\n         * @param detectionResult\n         *\n         * @throws FormatException\n         * @throws ChecksumException\n         * @throws NotFoundException\n         */\n        static createDecoderResult(detectionResult) {\n            let barcodeMatrix = PDF417ScanningDecoder.createBarcodeMatrix(detectionResult);\n            PDF417ScanningDecoder.adjustCodewordCount(detectionResult, barcodeMatrix);\n            let erasures /*Collection<Integer>*/ = new Array();\n            let codewords = new Int32Array(detectionResult.getBarcodeRowCount() * detectionResult.getBarcodeColumnCount());\n            let ambiguousIndexValuesList = /*List<int[]>*/ [];\n            let ambiguousIndexesList = /*Collection<Integer>*/ new Array();\n            for (let row /*int*/ = 0; row < detectionResult.getBarcodeRowCount(); row++) {\n                for (let column /*int*/ = 0; column < detectionResult.getBarcodeColumnCount(); column++) {\n                    let values = barcodeMatrix[row][column + 1].getValue();\n                    let codewordIndex = row * detectionResult.getBarcodeColumnCount() + column;\n                    if (values.length === 0) {\n                        erasures.push(codewordIndex);\n                    }\n                    else if (values.length === 1) {\n                        codewords[codewordIndex] = values[0];\n                    }\n                    else {\n                        ambiguousIndexesList.push(codewordIndex);\n                        ambiguousIndexValuesList.push(values);\n                    }\n                }\n            }\n            let ambiguousIndexValues = new Array(ambiguousIndexValuesList.length);\n            for (let i /*int*/ = 0; i < ambiguousIndexValues.length; i++) {\n                ambiguousIndexValues[i] = ambiguousIndexValuesList[i];\n            }\n            return PDF417ScanningDecoder.createDecoderResultFromAmbiguousValues(detectionResult.getBarcodeECLevel(), codewords, PDF417Common.toIntArray(erasures), PDF417Common.toIntArray(ambiguousIndexesList), ambiguousIndexValues);\n        }\n        /**\n         * This method deals with the fact, that the decoding process doesn't always yield a single most likely value. The\n         * current error correction implementation doesn't deal with erasures very well, so it's better to provide a value\n         * for these ambiguous codewords instead of treating it as an erasure. The problem is that we don't know which of\n         * the ambiguous values to choose. We try decode using the first value, and if that fails, we use another of the\n         * ambiguous values and try to decode again. This usually only happens on very hard to read and decode barcodes,\n         * so decoding the normal barcodes is not affected by this.\n         *\n         * @param erasureArray contains the indexes of erasures\n         * @param ambiguousIndexes array with the indexes that have more than one most likely value\n         * @param ambiguousIndexValues two dimensional array that contains the ambiguous values. The first dimension must\n         * be the same length as the ambiguousIndexes array\n         *\n         * @throws FormatException\n         * @throws ChecksumException\n         */\n        static createDecoderResultFromAmbiguousValues(ecLevel, codewords, erasureArray, ambiguousIndexes, ambiguousIndexValues) {\n            let ambiguousIndexCount = new Int32Array(ambiguousIndexes.length);\n            let tries = 100;\n            while (tries-- > 0) {\n                for (let i /*int*/ = 0; i < ambiguousIndexCount.length; i++) {\n                    codewords[ambiguousIndexes[i]] = ambiguousIndexValues[i][ambiguousIndexCount[i]];\n                }\n                try {\n                    return PDF417ScanningDecoder.decodeCodewords(codewords, ecLevel, erasureArray);\n                }\n                catch (err) {\n                    let ignored = err instanceof ChecksumException;\n                    if (!ignored) {\n                        throw err;\n                    }\n                }\n                if (ambiguousIndexCount.length === 0) {\n                    throw ChecksumException.getChecksumInstance();\n                }\n                for (let i /*int*/ = 0; i < ambiguousIndexCount.length; i++) {\n                    if (ambiguousIndexCount[i] < ambiguousIndexValues[i].length - 1) {\n                        ambiguousIndexCount[i]++;\n                        break;\n                    }\n                    else {\n                        ambiguousIndexCount[i] = 0;\n                        if (i === ambiguousIndexCount.length - 1) {\n                            throw ChecksumException.getChecksumInstance();\n                        }\n                    }\n                }\n            }\n            throw ChecksumException.getChecksumInstance();\n        }\n        static createBarcodeMatrix(detectionResult) {\n            // let barcodeMatrix: BarcodeValue[][] =\n            // new BarcodeValue[detectionResult.getBarcodeRowCount()][detectionResult.getBarcodeColumnCount() + 2];\n            let barcodeMatrix = Array.from({ length: detectionResult.getBarcodeRowCount() }, () => new Array(detectionResult.getBarcodeColumnCount() + 2));\n            for (let row /*int*/ = 0; row < barcodeMatrix.length; row++) {\n                for (let column /*int*/ = 0; column < barcodeMatrix[row].length; column++) {\n                    barcodeMatrix[row][column] = new BarcodeValue();\n                }\n            }\n            let column = 0;\n            for (let detectionResultColumn /*DetectionResultColumn*/ of detectionResult.getDetectionResultColumns()) {\n                if (detectionResultColumn != null) {\n                    for (let codeword /*Codeword*/ of detectionResultColumn.getCodewords()) {\n                        if (codeword != null) {\n                            let rowNumber = codeword.getRowNumber();\n                            if (rowNumber >= 0) {\n                                if (rowNumber >= barcodeMatrix.length) {\n                                    // We have more rows than the barcode metadata allows for, ignore them.\n                                    continue;\n                                }\n                                barcodeMatrix[rowNumber][column].setValue(codeword.getValue());\n                            }\n                        }\n                    }\n                }\n                column++;\n            }\n            return barcodeMatrix;\n        }\n        static isValidBarcodeColumn(detectionResult, barcodeColumn) {\n            return barcodeColumn >= 0 && barcodeColumn <= detectionResult.getBarcodeColumnCount() + 1;\n        }\n        static getStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight) {\n            let offset = leftToRight ? 1 : -1;\n            let codeword = null;\n            if (PDF417ScanningDecoder.isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) {\n                codeword = detectionResult.getDetectionResultColumn(barcodeColumn - offset).getCodeword(imageRow);\n            }\n            if (codeword != null) {\n                return leftToRight ? codeword.getEndX() : codeword.getStartX();\n            }\n            codeword = detectionResult.getDetectionResultColumn(barcodeColumn).getCodewordNearby(imageRow);\n            if (codeword != null) {\n                return leftToRight ? codeword.getStartX() : codeword.getEndX();\n            }\n            if (PDF417ScanningDecoder.isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) {\n                codeword = detectionResult.getDetectionResultColumn(barcodeColumn - offset).getCodewordNearby(imageRow);\n            }\n            if (codeword != null) {\n                return leftToRight ? codeword.getEndX() : codeword.getStartX();\n            }\n            let skippedColumns = 0;\n            while (PDF417ScanningDecoder.isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) {\n                barcodeColumn -= offset;\n                for (let previousRowCodeword /*Codeword*/ of detectionResult.getDetectionResultColumn(barcodeColumn).getCodewords()) {\n                    if (previousRowCodeword != null) {\n                        return (leftToRight ? previousRowCodeword.getEndX() : previousRowCodeword.getStartX()) +\n                            offset *\n                                skippedColumns *\n                                (previousRowCodeword.getEndX() - previousRowCodeword.getStartX());\n                    }\n                }\n                skippedColumns++;\n            }\n            return leftToRight ? detectionResult.getBoundingBox().getMinX() : detectionResult.getBoundingBox().getMaxX();\n        }\n        static detectCodeword(image, minColumn, maxColumn, leftToRight, startColumn, imageRow, minCodewordWidth, maxCodewordWidth) {\n            startColumn = PDF417ScanningDecoder.adjustCodewordStartColumn(image, minColumn, maxColumn, leftToRight, startColumn, imageRow);\n            // we usually know fairly exact now how long a codeword is. We should provide minimum and maximum expected length\n            // and try to adjust the read pixels, e.g. remove single pixel errors or try to cut off exceeding pixels.\n            // min and maxCodewordWidth should not be used as they are calculated for the whole barcode an can be inaccurate\n            // for the current position\n            let moduleBitCount = PDF417ScanningDecoder.getModuleBitCount(image, minColumn, maxColumn, leftToRight, startColumn, imageRow);\n            if (moduleBitCount == null) {\n                return null;\n            }\n            let endColumn;\n            let codewordBitCount = MathUtils.sum(moduleBitCount);\n            if (leftToRight) {\n                endColumn = startColumn + codewordBitCount;\n            }\n            else {\n                for (let i /*int*/ = 0; i < moduleBitCount.length / 2; i++) {\n                    let tmpCount = moduleBitCount[i];\n                    moduleBitCount[i] = moduleBitCount[moduleBitCount.length - 1 - i];\n                    moduleBitCount[moduleBitCount.length - 1 - i] = tmpCount;\n                }\n                endColumn = startColumn;\n                startColumn = endColumn - codewordBitCount;\n            }\n            // TODO implement check for width and correction of black and white bars\n            // use start (and maybe stop pattern) to determine if black bars are wider than white bars. If so, adjust.\n            // should probably done only for codewords with a lot more than 17 bits.\n            // The following fixes 10-1.png, which has wide black bars and small white bars\n            //    for (let i /*int*/ = 0; i < moduleBitCount.length; i++) {\n            //      if (i % 2 === 0) {\n            //        moduleBitCount[i]--;\n            //      } else {\n            //        moduleBitCount[i]++;\n            //      }\n            //    }\n            // We could also use the width of surrounding codewords for more accurate results, but this seems\n            // sufficient for now\n            if (!PDF417ScanningDecoder.checkCodewordSkew(codewordBitCount, minCodewordWidth, maxCodewordWidth)) {\n                // We could try to use the startX and endX position of the codeword in the same column in the previous row,\n                // create the bit count from it and normalize it to 8. This would help with single pixel errors.\n                return null;\n            }\n            let decodedValue = PDF417CodewordDecoder.getDecodedValue(moduleBitCount);\n            let codeword = PDF417Common.getCodeword(decodedValue);\n            if (codeword === -1) {\n                return null;\n            }\n            return new Codeword(startColumn, endColumn, PDF417ScanningDecoder.getCodewordBucketNumber(decodedValue), codeword);\n        }\n        static getModuleBitCount(image, minColumn, maxColumn, leftToRight, startColumn, imageRow) {\n            let imageColumn = startColumn;\n            let moduleBitCount = new Int32Array(8);\n            let moduleNumber = 0;\n            let increment = leftToRight ? 1 : -1;\n            let previousPixelValue = leftToRight;\n            while ((leftToRight ? imageColumn < maxColumn : imageColumn >= minColumn) &&\n                moduleNumber < moduleBitCount.length) {\n                if (image.get(imageColumn, imageRow) === previousPixelValue) {\n                    moduleBitCount[moduleNumber]++;\n                    imageColumn += increment;\n                }\n                else {\n                    moduleNumber++;\n                    previousPixelValue = !previousPixelValue;\n                }\n            }\n            if (moduleNumber === moduleBitCount.length ||\n                ((imageColumn === (leftToRight ? maxColumn : minColumn)) &&\n                    moduleNumber === moduleBitCount.length - 1)) {\n                return moduleBitCount;\n            }\n            return null;\n        }\n        static getNumberOfECCodeWords(barcodeECLevel) {\n            return 2 << barcodeECLevel;\n        }\n        static adjustCodewordStartColumn(image, minColumn, maxColumn, leftToRight, codewordStartColumn, imageRow) {\n            let correctedStartColumn = codewordStartColumn;\n            let increment = leftToRight ? -1 : 1;\n            // there should be no black pixels before the start column. If there are, then we need to start earlier.\n            for (let i /*int*/ = 0; i < 2; i++) {\n                while ((leftToRight ? correctedStartColumn >= minColumn : correctedStartColumn < maxColumn) &&\n                    leftToRight === image.get(correctedStartColumn, imageRow)) {\n                    if (Math.abs(codewordStartColumn - correctedStartColumn) > PDF417ScanningDecoder.CODEWORD_SKEW_SIZE) {\n                        return codewordStartColumn;\n                    }\n                    correctedStartColumn += increment;\n                }\n                increment = -increment;\n                leftToRight = !leftToRight;\n            }\n            return correctedStartColumn;\n        }\n        static checkCodewordSkew(codewordSize, minCodewordWidth, maxCodewordWidth) {\n            return minCodewordWidth - PDF417ScanningDecoder.CODEWORD_SKEW_SIZE <= codewordSize &&\n                codewordSize <= maxCodewordWidth + PDF417ScanningDecoder.CODEWORD_SKEW_SIZE;\n        }\n        /**\n         * @throws FormatException,\n         * @throws ChecksumException\n         */\n        static decodeCodewords(codewords, ecLevel, erasures) {\n            if (codewords.length === 0) {\n                throw FormatException.getFormatInstance();\n            }\n            let numECCodewords = 1 << (ecLevel + 1);\n            let correctedErrorsCount = PDF417ScanningDecoder.correctErrors(codewords, erasures, numECCodewords);\n            PDF417ScanningDecoder.verifyCodewordCount(codewords, numECCodewords);\n            // Decode the codewords\n            let decoderResult = DecodedBitStreamParser$2.decode(codewords, '' + ecLevel);\n            decoderResult.setErrorsCorrected(correctedErrorsCount);\n            decoderResult.setErasures(erasures.length);\n            return decoderResult;\n        }\n        /**\n         * <p>Given data and error-correction codewords received, possibly corrupted by errors, attempts to\n         * correct the errors in-place.</p>\n         *\n         * @param codewords   data and error correction codewords\n         * @param erasures positions of any known erasures\n         * @param numECCodewords number of error correction codewords that are available in codewords\n         * @throws ChecksumException if error correction fails\n         */\n        static correctErrors(codewords, erasures, numECCodewords) {\n            if (erasures != null &&\n                erasures.length > numECCodewords / 2 + PDF417ScanningDecoder.MAX_ERRORS ||\n                numECCodewords < 0 ||\n                numECCodewords > PDF417ScanningDecoder.MAX_EC_CODEWORDS) {\n                // Too many errors or EC Codewords is corrupted\n                throw ChecksumException.getChecksumInstance();\n            }\n            return PDF417ScanningDecoder.errorCorrection.decode(codewords, numECCodewords, erasures);\n        }\n        /**\n         * Verify that all is OK with the codeword array.\n         * @throws FormatException\n         */\n        static verifyCodewordCount(codewords, numECCodewords) {\n            if (codewords.length < 4) {\n                // Codeword array size should be at least 4 allowing for\n                // Count CW, At least one Data CW, Error Correction CW, Error Correction CW\n                throw FormatException.getFormatInstance();\n            }\n            // The first codeword, the Symbol Length Descriptor, shall always encode the total number of data\n            // codewords in the symbol, including the Symbol Length Descriptor itself, data codewords and pad\n            // codewords, but excluding the number of error correction codewords.\n            let numberOfCodewords = codewords[0];\n            if (numberOfCodewords > codewords.length) {\n                throw FormatException.getFormatInstance();\n            }\n            if (numberOfCodewords === 0) {\n                // Reset to the length of the array - 8 (Allow for at least level 3 Error Correction (8 Error Codewords)\n                if (numECCodewords < codewords.length) {\n                    codewords[0] = codewords.length - numECCodewords;\n                }\n                else {\n                    throw FormatException.getFormatInstance();\n                }\n            }\n        }\n        static getBitCountForCodeword(codeword) {\n            let result = new Int32Array(8);\n            let previousValue = 0;\n            let i = result.length - 1;\n            while (true) {\n                if ((codeword & 0x1) !== previousValue) {\n                    previousValue = codeword & 0x1;\n                    i--;\n                    if (i < 0) {\n                        break;\n                    }\n                }\n                result[i]++;\n                codeword >>= 1;\n            }\n            return result;\n        }\n        static getCodewordBucketNumber(codeword) {\n            if (codeword instanceof Int32Array) {\n                return this.getCodewordBucketNumber_Int32Array(codeword);\n            }\n            return this.getCodewordBucketNumber_number(codeword);\n        }\n        static getCodewordBucketNumber_number(codeword) {\n            return PDF417ScanningDecoder.getCodewordBucketNumber(PDF417ScanningDecoder.getBitCountForCodeword(codeword));\n        }\n        static getCodewordBucketNumber_Int32Array(moduleBitCount) {\n            return (moduleBitCount[0] - moduleBitCount[2] + moduleBitCount[4] - moduleBitCount[6] + 9) % 9;\n        }\n        static toString(barcodeMatrix) {\n            let formatter = new Formatter();\n            // try (let formatter = new Formatter()) {\n            for (let row /*int*/ = 0; row < barcodeMatrix.length; row++) {\n                formatter.format('Row %2d: ', row);\n                for (let column /*int*/ = 0; column < barcodeMatrix[row].length; column++) {\n                    let barcodeValue = barcodeMatrix[row][column];\n                    if (barcodeValue.getValue().length === 0) {\n                        formatter.format('        ', null);\n                    }\n                    else {\n                        formatter.format('%4d(%2d)', barcodeValue.getValue()[0], barcodeValue.getConfidence(barcodeValue.getValue()[0]));\n                    }\n                }\n                formatter.format('%n');\n            }\n            return formatter.toString();\n            // }\n        }\n    }\n    /*final*/ PDF417ScanningDecoder.CODEWORD_SKEW_SIZE = 2;\n    /*final*/ PDF417ScanningDecoder.MAX_ERRORS = 3;\n    /*final*/ PDF417ScanningDecoder.MAX_EC_CODEWORDS = 512;\n    /*final*/ PDF417ScanningDecoder.errorCorrection = new ErrorCorrection();\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    // import java.util.ArrayList;\n    // import java.util.List;\n    // import java.util.Map;\n    /**\n     * This implementation can detect and decode PDF417 codes in an image.\n     *\n     * @author Guenther Grau\n     */\n    /*public final*/ class PDF417Reader {\n        // private static /*final Result[]*/ EMPTY_RESULT_ARRAY: Result[] = new Result([0]);\n        /**\n         * Locates and decodes a PDF417 code in an image.\n         *\n         * @return a String representing the content encoded by the PDF417 code\n         * @throws NotFoundException if a PDF417 code cannot be found,\n         * @throws FormatException if a PDF417 cannot be decoded\n         * @throws ChecksumException\n         */\n        // @Override\n        decode(image, hints = null) {\n            let result = PDF417Reader.decode(image, hints, false);\n            if (result == null || result.length === 0 || result[0] == null) {\n                throw NotFoundException.getNotFoundInstance();\n            }\n            return result[0];\n        }\n        /**\n         *\n         * @param BinaryBitmap\n         * @param image\n         * @throws NotFoundException\n         */\n        //   @Override\n        decodeMultiple(image, hints = null) {\n            try {\n                return PDF417Reader.decode(image, hints, true);\n            }\n            catch (ignored) {\n                if (ignored instanceof FormatException || ignored instanceof ChecksumException) {\n                    throw NotFoundException.getNotFoundInstance();\n                }\n                throw ignored;\n            }\n        }\n        /**\n         *\n         * @param image\n         * @param hints\n         * @param multiple\n         *\n         * @throws NotFoundException\n         * @throws FormatExceptionß\n         * @throws ChecksumException\n         */\n        static decode(image, hints, multiple) {\n            const results = new Array();\n            const detectorResult = Detector$3.detectMultiple(image, hints, multiple);\n            for (const points of detectorResult.getPoints()) {\n                const decoderResult = PDF417ScanningDecoder.decode(detectorResult.getBits(), points[4], points[5], points[6], points[7], PDF417Reader.getMinCodewordWidth(points), PDF417Reader.getMaxCodewordWidth(points));\n                const result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), undefined, points, BarcodeFormat$1.PDF_417);\n                result.putMetadata(ResultMetadataType$1.ERROR_CORRECTION_LEVEL, decoderResult.getECLevel());\n                const pdf417ResultMetadata = decoderResult.getOther();\n                if (pdf417ResultMetadata != null) {\n                    result.putMetadata(ResultMetadataType$1.PDF417_EXTRA_METADATA, pdf417ResultMetadata);\n                }\n                results.push(result);\n            }\n            return results.map(x => x);\n        }\n        static getMaxWidth(p1, p2) {\n            if (p1 == null || p2 == null) {\n                return 0;\n            }\n            return Math.trunc(Math.abs(p1.getX() - p2.getX()));\n        }\n        static getMinWidth(p1, p2) {\n            if (p1 == null || p2 == null) {\n                return Integer.MAX_VALUE;\n            }\n            return Math.trunc(Math.abs(p1.getX() - p2.getX()));\n        }\n        static getMaxCodewordWidth(p) {\n            return Math.floor(Math.max(Math.max(PDF417Reader.getMaxWidth(p[0], p[4]), PDF417Reader.getMaxWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD /\n                PDF417Common.MODULES_IN_STOP_PATTERN), Math.max(PDF417Reader.getMaxWidth(p[1], p[5]), PDF417Reader.getMaxWidth(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD /\n                PDF417Common.MODULES_IN_STOP_PATTERN)));\n        }\n        static getMinCodewordWidth(p) {\n            return Math.floor(Math.min(Math.min(PDF417Reader.getMinWidth(p[0], p[4]), PDF417Reader.getMinWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD /\n                PDF417Common.MODULES_IN_STOP_PATTERN), Math.min(PDF417Reader.getMinWidth(p[1], p[5]), PDF417Reader.getMinWidth(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD /\n                PDF417Common.MODULES_IN_STOP_PATTERN)));\n        }\n        // @Override\n        reset() {\n            // nothing needs to be reset\n        }\n    }\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class ReaderException extends Exception {\n    }\n    ReaderException.kind = 'ReaderException';\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing {*/\n    /**\n     * MultiFormatReader is a convenience class and the main entry point into the library for most uses.\n     * By default it attempts to decode all barcode formats that the library supports. Optionally, you\n     * can provide a hints object to request different behavior, for example only decoding QR codes.\n     *\n     * @author Sean Owen\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class MultiFormatReader {\n        /**\n         * Creates an instance of this class\n         * \n         * @param {Boolean} verbose if 'true' logs will be dumped to console, otherwise hidden.\n         * @param hints The hints to use, clearing the previous state.\n         */\n        constructor(verbose, hints) {\n            this.verbose = (verbose === true);\n            if (hints) {\n                this.setHints(hints);\n            }\n        }\n        /**\n         * This version of decode honors the intent of Reader.decode(BinaryBitmap) in that it\n         * passes null as a hint to the decoders. However, that makes it inefficient to call repeatedly.\n         * Use setHints() followed by decodeWithState() for continuous scan applications.\n         *\n         * @param image The pixel data to decode\n         * @return The contents of the image\n         *\n         * @throws NotFoundException Any errors which occurred\n         */\n        /*@Override*/\n        // public decode(image: BinaryBitmap): Result {\n        //   setHints(null)\n        //   return decodeInternal(image)\n        // }\n        /**\n         * Decode an image using the hints provided. Does not honor existing state.\n         *\n         * @param image The pixel data to decode\n         * @param hints The hints to use, clearing the previous state.\n         * @return The contents of the image\n         *\n         * @throws NotFoundException Any errors which occurred\n         */\n        /*@Override*/\n        decode(image, hints) {\n            if (hints) {\n                this.setHints(hints);\n            }\n            return this.decodeInternal(image);\n        }\n        /**\n         * Decode an image using the state set up by calling setHints() previously. Continuous scan\n         * clients will get a <b>large</b> speed increase by using this instead of decode().\n         *\n         * @param image The pixel data to decode\n         * @return The contents of the image\n         *\n         * @throws NotFoundException Any errors which occurred\n         */\n        decodeWithState(image) {\n            // Make sure to set up the default state so we don't crash\n            if (this.readers === null || this.readers === undefined) {\n                this.setHints(null);\n            }\n            return this.decodeInternal(image);\n        }\n        /**\n         * This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls\n         * to decodeWithState(image) can reuse the same set of readers without reallocating memory. This\n         * is important for performance in continuous scan clients.\n         *\n         * @param hints The set of hints to use for subsequent calls to decode(image)\n         */\n        setHints(hints) {\n            this.hints = hints;\n            const tryHarder = !isNullOrUndefined(hints)\n                && hints.get(DecodeHintType$1.TRY_HARDER) === true;\n            const formats = isNullOrUndefined(hints) ? null : hints.get(DecodeHintType$1.POSSIBLE_FORMATS);\n            const readers = new Array();\n            if (!isNullOrUndefined(formats)) {\n                const addOneDReader = formats.some(f => {\n                    return (\n                        f === BarcodeFormat$1.UPC_A ||\n                        f === BarcodeFormat$1.UPC_E ||\n                        f === BarcodeFormat$1.EAN_13 ||\n                        f === BarcodeFormat$1.EAN_8 ||\n                        f === BarcodeFormat$1.CODABAR ||\n                        f === BarcodeFormat$1.CODE_39 ||\n                        f === BarcodeFormat$1.CODE_93 ||\n                        f === BarcodeFormat$1.CODE_128 ||\n                        f === BarcodeFormat$1.ITF ||\n                        f === BarcodeFormat$1.RSS_14 ||\n                        f === BarcodeFormat$1.RSS_EXPANDED);\n                });\n                // Put 1D readers upfront in \"normal\" mode\n                if (addOneDReader && !tryHarder) {\n                    readers.push(new MultiFormatOneDReader(hints, this.verbose));\n                }\n                if (formats.includes(BarcodeFormat$1.QR_CODE)) {\n                    readers.push(new QRCodeReader());\n                }\n                if (formats.includes(BarcodeFormat$1.DATA_MATRIX)) {\n                    readers.push(new DataMatrixReader());\n                }\n                if (formats.includes(BarcodeFormat$1.AZTEC)) {\n                    readers.push(new AztecReader());\n                }\n                if (formats.includes(BarcodeFormat$1.PDF_417)) {\n                    readers.push(new PDF417Reader());\n                }\n                // if (formats.includes(BarcodeFormat.MAXICODE)) {\n                //    readers.push(new MaxiCodeReader())\n                // }\n                // At end in \"try harder\" mode\n                if (addOneDReader && tryHarder) {\n                    readers.push(new MultiFormatOneDReader(hints, this.verbose));\n                }\n            }\n            if (readers.length === 0) {\n                if (!tryHarder) {\n                    readers.push(new MultiFormatOneDReader(hints, this.verbose));\n                }\n                readers.push(new QRCodeReader());\n                readers.push(new DataMatrixReader());\n                readers.push(new AztecReader());\n                readers.push(new PDF417Reader());\n                // readers.push(new MaxiCodeReader())\n                if (tryHarder) {\n                    readers.push(new MultiFormatOneDReader(hints, this.verbose));\n                }\n            }\n            this.readers = readers; // .toArray(new Reader[readers.size()])\n        }\n        /*@Override*/\n        reset() {\n            if (this.readers !== null) {\n                for (const reader of this.readers) {\n                    reader.reset();\n                }\n            }\n        }\n        /**\n         * @throws NotFoundException\n         */\n        decodeInternal(image) {\n            if (this.readers === null) {\n                throw new ReaderException('No readers where selected, nothing can be read.');\n            }\n            for (const reader of this.readers) {\n                // Trying to decode with ${reader} reader.\n                try {\n                    return reader.decode(image, this.hints);\n                }\n                catch (ex) {\n                    if (ex instanceof ReaderException) {\n                        continue;\n                    }\n                    // Bad Exception.\n                }\n            }\n            throw new NotFoundException('No MultiFormat Readers were able to detect the code.');\n        }\n    }\n\n    class BrowserMultiFormatReader extends BrowserCodeReader {\n        constructor(hints = null, timeBetweenScansMillis = 500) {\n            const reader = new MultiFormatReader();\n            reader.setHints(hints);\n            super(reader, timeBetweenScansMillis);\n        }\n        /**\n         * Overwrite decodeBitmap to call decodeWithState, which will pay\n         * attention to the hints set in the constructor function\n         */\n        decodeBitmap(binaryBitmap) {\n            return this.reader.decodeWithState(binaryBitmap);\n        }\n    }\n\n    /**\n     * @deprecated Moving to @zxing/browser\n     *\n     * QR Code reader to use from browser.\n     */\n    class BrowserPDF417Reader extends BrowserCodeReader {\n        /**\n         * Creates an instance of BrowserPDF417Reader.\n         * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n         */\n        constructor(timeBetweenScansMillis = 500) {\n            super(new PDF417Reader(), timeBetweenScansMillis);\n        }\n    }\n\n    /**\n     * @deprecated Moving to @zxing/browser\n     *\n     * QR Code reader to use from browser.\n     */\n    class BrowserQRCodeReader extends BrowserCodeReader {\n        /**\n         * Creates an instance of BrowserQRCodeReader.\n         * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n         */\n        constructor(timeBetweenScansMillis = 500) {\n            super(new QRCodeReader(), timeBetweenScansMillis);\n        }\n    }\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /*namespace com.google.zxing {*/\n    /**\n     * These are a set of hints that you may pass to Writers to specify their behavior.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    var EncodeHintType;\n    (function (EncodeHintType) {\n        /**\n         * Specifies what degree of error correction to use, for example in QR Codes.\n         * Type depends on the encoder. For example for QR codes it's type\n         * {@link com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ErrorCorrectionLevel}.\n         * For Aztec it is of type {@link Integer}, representing the minimal percentage of error correction words.\n         * For PDF417 it is of type {@link Integer}, valid values being 0 to 8.\n         * In all cases, it can also be a {@link String} representation of the desired value as well.\n         * Note: an Aztec symbol should have a minimum of 25% EC words.\n         */\n        EncodeHintType[EncodeHintType[\"ERROR_CORRECTION\"] = 0] = \"ERROR_CORRECTION\";\n        /**\n         * Specifies what character encoding to use where applicable (type {@link String})\n         */\n        EncodeHintType[EncodeHintType[\"CHARACTER_SET\"] = 1] = \"CHARACTER_SET\";\n        /**\n         * Specifies the matrix shape for Data Matrix (type {@link com.google.zxing.datamatrix.encoder.SymbolShapeHint})\n         */\n        EncodeHintType[EncodeHintType[\"DATA_MATRIX_SHAPE\"] = 2] = \"DATA_MATRIX_SHAPE\";\n        /**\n         * Specifies a minimum barcode size (type {@link Dimension}). Only applicable to Data Matrix now.\n         *\n         * @deprecated use width/height params in\n         * {@link com.google.zxing.datamatrix.DataMatrixWriter#encode(String, BarcodeFormat, int, int)}\n         */\n        /*@Deprecated*/\n        EncodeHintType[EncodeHintType[\"MIN_SIZE\"] = 3] = \"MIN_SIZE\";\n        /**\n         * Specifies a maximum barcode size (type {@link Dimension}). Only applicable to Data Matrix now.\n         *\n         * @deprecated without replacement\n         */\n        /*@Deprecated*/\n        EncodeHintType[EncodeHintType[\"MAX_SIZE\"] = 4] = \"MAX_SIZE\";\n        /**\n         * Specifies margin, in pixels, to use when generating the barcode. The meaning can vary\n         * by format; for example it controls margin before and after the barcode horizontally for\n         * most 1D formats. (Type {@link Integer}, or {@link String} representation of the integer value).\n         */\n        EncodeHintType[EncodeHintType[\"MARGIN\"] = 5] = \"MARGIN\";\n        /**\n         * Specifies whether to use compact mode for PDF417 (type {@link Boolean}, or \"true\" or \"false\"\n         * {@link String} value).\n         */\n        EncodeHintType[EncodeHintType[\"PDF417_COMPACT\"] = 6] = \"PDF417_COMPACT\";\n        /**\n         * Specifies what compaction mode to use for PDF417 (type\n         * {@link com.google.zxing.pdf417.encoder.Compaction Compaction} or {@link String} value of one of its\n         * enum values).\n         */\n        EncodeHintType[EncodeHintType[\"PDF417_COMPACTION\"] = 7] = \"PDF417_COMPACTION\";\n        /**\n         * Specifies the minimum and maximum number of rows and columns for PDF417 (type\n         * {@link com.google.zxing.pdf417.encoder.Dimensions Dimensions}).\n         */\n        EncodeHintType[EncodeHintType[\"PDF417_DIMENSIONS\"] = 8] = \"PDF417_DIMENSIONS\";\n        /**\n         * Specifies the required number of layers for an Aztec code.\n         * A negative number (-1, -2, -3, -4) specifies a compact Aztec code.\n         * 0 indicates to use the minimum number of layers (the default).\n         * A positive number (1, 2, .. 32) specifies a normal (non-compact) Aztec code.\n         * (Type {@link Integer}, or {@link String} representation of the integer value).\n         */\n        EncodeHintType[EncodeHintType[\"AZTEC_LAYERS\"] = 9] = \"AZTEC_LAYERS\";\n        /**\n         * Specifies the exact version of QR code to be encoded.\n         * (Type {@link Integer}, or {@link String} representation of the integer value).\n         */\n        EncodeHintType[EncodeHintType[\"QR_VERSION\"] = 10] = \"QR_VERSION\";\n    })(EncodeHintType || (EncodeHintType = {}));\n    var EncodeHintType$1 = EncodeHintType;\n\n    /**\n     * <p>Implements Reed-Solomon encoding, as the name implies.</p>\n     *\n     * @author Sean Owen\n     * @author William Rucklidge\n     */\n    class ReedSolomonEncoder {\n        /**\n         * A reed solomon error-correcting encoding constructor is created by\n         * passing as Galois Field with of size equal to the number of code\n         * words (symbols) in the alphabet (the number of values in each\n         * element of arrays that are encoded/decoded).\n         * @param field A galois field with a number of elements equal to the size\n         * of the alphabet of symbols to encode.\n         */\n        constructor(field) {\n            this.field = field;\n            this.cachedGenerators = [];\n            this.cachedGenerators.push(new GenericGFPoly(field, Int32Array.from([1])));\n        }\n        buildGenerator(degree /*int*/) {\n            const cachedGenerators = this.cachedGenerators;\n            if (degree >= cachedGenerators.length) {\n                let lastGenerator = cachedGenerators[cachedGenerators.length - 1];\n                const field = this.field;\n                for (let d = cachedGenerators.length; d <= degree; d++) {\n                    const nextGenerator = lastGenerator.multiply(new GenericGFPoly(field, Int32Array.from([1, field.exp(d - 1 + field.getGeneratorBase())])));\n                    cachedGenerators.push(nextGenerator);\n                    lastGenerator = nextGenerator;\n                }\n            }\n            return cachedGenerators[degree];\n        }\n        /**\n         * <p>Encode a sequence of code words (symbols) using Reed-Solomon to allow decoders\n         * to detect and correct errors that may have been introduced when the resulting\n         * data is stored or transmitted.</p>\n         *\n         * @param toEncode array used for both and output. Caller initializes the array with\n         * the code words (symbols) to be encoded followed by empty elements allocated to make\n         * space for error-correction code words in the encoded output. The array contains\n         * the encdoded output when encode returns. Code words are encoded as numbers from\n         * 0 to n-1, where n is the number of possible code words (symbols), as determined\n         * by the size of the Galois Field passed in the constructor of this object.\n         * @param ecBytes the number of elements reserved in the array (first parameter)\n         * to store error-correction code words. Thus, the number of code words (symbols)\n         * to encode in the first parameter is thus toEncode.length - ecBytes.\n         * Note, the use of \"bytes\" in the name of this parameter is misleading, as there may\n         * be more or fewer than 256 symbols being encoded, as determined by the number of\n         * elements in the Galois Field passed as a constructor to this object.\n         * @throws IllegalArgumentException thrown in response to validation errros.\n         */\n        encode(toEncode, ecBytes /*int*/) {\n            if (ecBytes === 0) {\n                throw new IllegalArgumentException('No error correction bytes');\n            }\n            const dataBytes = toEncode.length - ecBytes;\n            if (dataBytes <= 0) {\n                throw new IllegalArgumentException('No data bytes provided');\n            }\n            const generator = this.buildGenerator(ecBytes);\n            const infoCoefficients = new Int32Array(dataBytes);\n            System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes);\n            let info = new GenericGFPoly(this.field, infoCoefficients);\n            info = info.multiplyByMonomial(ecBytes, 1);\n            const remainder = info.divide(generator)[1];\n            const coefficients = remainder.getCoefficients();\n            const numZeroCoefficients = ecBytes - coefficients.length;\n            for (let i = 0; i < numZeroCoefficients; i++) {\n                toEncode[dataBytes + i] = 0;\n            }\n            System.arraycopy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.length);\n        }\n    }\n\n    /**\n     * @author Satoru Takabayashi\n     * @author Daniel Switkin\n     * @author Sean Owen\n     */\n    class MaskUtil {\n        constructor() {\n            // do nothing\n        }\n        /**\n         * Apply mask penalty rule 1 and return the penalty. Find repetitive cells with the same color and\n         * give penalty to them. Example: 00000 or 11111.\n         */\n        static applyMaskPenaltyRule1(matrix) {\n            return MaskUtil.applyMaskPenaltyRule1Internal(matrix, true) + MaskUtil.applyMaskPenaltyRule1Internal(matrix, false);\n        }\n        /**\n         * Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give\n         * penalty to them. This is actually equivalent to the spec's rule, which is to find MxN blocks and give a\n         * penalty proportional to (M-1)x(N-1), because this is the number of 2x2 blocks inside such a block.\n         */\n        static applyMaskPenaltyRule2(matrix) {\n            let penalty = 0;\n            const array = matrix.getArray();\n            const width = matrix.getWidth();\n            const height = matrix.getHeight();\n            for (let y = 0; y < height - 1; y++) {\n                const arrayY = array[y];\n                for (let x = 0; x < width - 1; x++) {\n                    const value = arrayY[x];\n                    if (value === arrayY[x + 1] && value === array[y + 1][x] && value === array[y + 1][x + 1]) {\n                        penalty++;\n                    }\n                }\n            }\n            return MaskUtil.N2 * penalty;\n        }\n        /**\n         * Apply mask penalty rule 3 and return the penalty. Find consecutive runs of 1:1:3:1:1:4\n         * starting with black, or 4:1:1:3:1:1 starting with white, and give penalty to them.  If we\n         * find patterns like 000010111010000, we give penalty once.\n         */\n        static applyMaskPenaltyRule3(matrix) {\n            let numPenalties = 0;\n            const array = matrix.getArray();\n            const width = matrix.getWidth();\n            const height = matrix.getHeight();\n            for (let y = 0; y < height; y++) {\n                for (let x = 0; x < width; x++) {\n                    const arrayY = array[y]; // We can at least optimize this access\n                    if (x + 6 < width &&\n                        arrayY[x] === 1 &&\n                        arrayY[x + 1] === 0 &&\n                        arrayY[x + 2] === 1 &&\n                        arrayY[x + 3] === 1 &&\n                        arrayY[x + 4] === 1 &&\n                        arrayY[x + 5] === 0 &&\n                        arrayY[x + 6] === 1 &&\n                        (MaskUtil.isWhiteHorizontal(arrayY, x - 4, x) || MaskUtil.isWhiteHorizontal(arrayY, x + 7, x + 11))) {\n                        numPenalties++;\n                    }\n                    if (y + 6 < height &&\n                        array[y][x] === 1 &&\n                        array[y + 1][x] === 0 &&\n                        array[y + 2][x] === 1 &&\n                        array[y + 3][x] === 1 &&\n                        array[y + 4][x] === 1 &&\n                        array[y + 5][x] === 0 &&\n                        array[y + 6][x] === 1 &&\n                        (MaskUtil.isWhiteVertical(array, x, y - 4, y) || MaskUtil.isWhiteVertical(array, x, y + 7, y + 11))) {\n                        numPenalties++;\n                    }\n                }\n            }\n            return numPenalties * MaskUtil.N3;\n        }\n        static isWhiteHorizontal(rowArray, from /*int*/, to /*int*/) {\n            from = Math.max(from, 0);\n            to = Math.min(to, rowArray.length);\n            for (let i = from; i < to; i++) {\n                if (rowArray[i] === 1) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        static isWhiteVertical(array, col /*int*/, from /*int*/, to /*int*/) {\n            from = Math.max(from, 0);\n            to = Math.min(to, array.length);\n            for (let i = from; i < to; i++) {\n                if (array[i][col] === 1) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        /**\n         * Apply mask penalty rule 4 and return the penalty. Calculate the ratio of dark cells and give\n         * penalty if the ratio is far from 50%. It gives 10 penalty for 5% distance.\n         */\n        static applyMaskPenaltyRule4(matrix) {\n            let numDarkCells = 0;\n            const array = matrix.getArray();\n            const width = matrix.getWidth();\n            const height = matrix.getHeight();\n            for (let y = 0; y < height; y++) {\n                const arrayY = array[y];\n                for (let x = 0; x < width; x++) {\n                    if (arrayY[x] === 1) {\n                        numDarkCells++;\n                    }\n                }\n            }\n            const numTotalCells = matrix.getHeight() * matrix.getWidth();\n            const fivePercentVariances = Math.floor(Math.abs(numDarkCells * 2 - numTotalCells) * 10 / numTotalCells);\n            return fivePercentVariances * MaskUtil.N4;\n        }\n        /**\n         * Return the mask bit for \"getMaskPattern\" at \"x\" and \"y\". See 8.8 of JISX0510:2004 for mask\n         * pattern conditions.\n         */\n        static getDataMaskBit(maskPattern /*int*/, x /*int*/, y /*int*/) {\n            let intermediate; /*int*/\n            let temp; /*int*/\n            switch (maskPattern) {\n                case 0:\n                    intermediate = (y + x) & 0x1;\n                    break;\n                case 1:\n                    intermediate = y & 0x1;\n                    break;\n                case 2:\n                    intermediate = x % 3;\n                    break;\n                case 3:\n                    intermediate = (y + x) % 3;\n                    break;\n                case 4:\n                    intermediate = (Math.floor(y / 2) + Math.floor(x / 3)) & 0x1;\n                    break;\n                case 5:\n                    temp = y * x;\n                    intermediate = (temp & 0x1) + (temp % 3);\n                    break;\n                case 6:\n                    temp = y * x;\n                    intermediate = ((temp & 0x1) + (temp % 3)) & 0x1;\n                    break;\n                case 7:\n                    temp = y * x;\n                    intermediate = ((temp % 3) + ((y + x) & 0x1)) & 0x1;\n                    break;\n                default:\n                    throw new IllegalArgumentException('Invalid mask pattern: ' + maskPattern);\n            }\n            return intermediate === 0;\n        }\n        /**\n         * Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both\n         * vertical and horizontal orders respectively.\n         */\n        static applyMaskPenaltyRule1Internal(matrix, isHorizontal) {\n            let penalty = 0;\n            const iLimit = isHorizontal ? matrix.getHeight() : matrix.getWidth();\n            const jLimit = isHorizontal ? matrix.getWidth() : matrix.getHeight();\n            const array = matrix.getArray();\n            for (let i = 0; i < iLimit; i++) {\n                let numSameBitCells = 0;\n                let prevBit = -1;\n                for (let j = 0; j < jLimit; j++) {\n                    const bit = isHorizontal ? array[i][j] : array[j][i];\n                    if (bit === prevBit) {\n                        numSameBitCells++;\n                    }\n                    else {\n                        if (numSameBitCells >= 5) {\n                            penalty += MaskUtil.N1 + (numSameBitCells - 5);\n                        }\n                        numSameBitCells = 1; // Include the cell itself.\n                        prevBit = bit;\n                    }\n                }\n                if (numSameBitCells >= 5) {\n                    penalty += MaskUtil.N1 + (numSameBitCells - 5);\n                }\n            }\n            return penalty;\n        }\n    }\n    // Penalty weights from section 6.8.2.1\n    MaskUtil.N1 = 3;\n    MaskUtil.N2 = 3;\n    MaskUtil.N3 = 40;\n    MaskUtil.N4 = 10;\n\n    /**\n     * JAVAPORT: The original code was a 2D array of ints, but since it only ever gets assigned\n     * -1, 0, and 1, I'm going to use less memory and go with bytes.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class ByteMatrix {\n        constructor(width /*int*/, height /*int*/) {\n            this.width = width;\n            this.height = height;\n            const bytes = new Array(height); // [height][width]\n            for (let i = 0; i !== height; i++) {\n                bytes[i] = new Uint8Array(width);\n            }\n            this.bytes = bytes;\n        }\n        getHeight() {\n            return this.height;\n        }\n        getWidth() {\n            return this.width;\n        }\n        get(x /*int*/, y /*int*/) {\n            return this.bytes[y][x];\n        }\n        /**\n         * @return an internal representation as bytes, in row-major order. array[y][x] represents point (x,y)\n         */\n        getArray() {\n            return this.bytes;\n        }\n        // TYPESCRIPTPORT: preffer to let two methods instead of override to avoid type comparison inside\n        setNumber(x /*int*/, y /*int*/, value /*byte|int*/) {\n            this.bytes[y][x] = value;\n        }\n        // public set(x: number /*int*/, y: number /*int*/, value: number /*int*/): void {\n        //   bytes[y][x] = (byte) value\n        // }\n        setBoolean(x /*int*/, y /*int*/, value) {\n            this.bytes[y][x] = /*(byte) */ (value ? 1 : 0);\n        }\n        clear(value /*byte*/) {\n            for (const aByte of this.bytes) {\n                Arrays.fill(aByte, value);\n            }\n        }\n        equals(o) {\n            if (!(o instanceof ByteMatrix)) {\n                return false;\n            }\n            const other = o;\n            if (this.width !== other.width) {\n                return false;\n            }\n            if (this.height !== other.height) {\n                return false;\n            }\n            for (let y = 0, height = this.height; y < height; ++y) {\n                const bytesY = this.bytes[y];\n                const otherBytesY = other.bytes[y];\n                for (let x = 0, width = this.width; x < width; ++x) {\n                    if (bytesY[x] !== otherBytesY[x]) {\n                        return false;\n                    }\n                }\n            }\n            return true;\n        }\n        /*@Override*/\n        toString() {\n            const result = new StringBuilder(); // (2 * width * height + 2)\n            for (let y = 0, height = this.height; y < height; ++y) {\n                const bytesY = this.bytes[y];\n                for (let x = 0, width = this.width; x < width; ++x) {\n                    switch (bytesY[x]) {\n                        case 0:\n                            result.append(' 0');\n                            break;\n                        case 1:\n                            result.append(' 1');\n                            break;\n                        default:\n                            result.append('  ');\n                            break;\n                    }\n                }\n                result.append('\\n');\n            }\n            return result.toString();\n        }\n    }\n\n    /**\n     * @author satorux@google.com (Satoru Takabayashi) - creator\n     * @author dswitkin@google.com (Daniel Switkin) - ported from C++\n     */\n    class QRCode {\n        constructor() {\n            this.maskPattern = -1;\n        }\n        getMode() {\n            return this.mode;\n        }\n        getECLevel() {\n            return this.ecLevel;\n        }\n        getVersion() {\n            return this.version;\n        }\n        getMaskPattern() {\n            return this.maskPattern;\n        }\n        getMatrix() {\n            return this.matrix;\n        }\n        /*@Override*/\n        toString() {\n            const result = new StringBuilder(); // (200)\n            result.append('<<\\n');\n            result.append(' mode: ');\n            result.append(this.mode ? this.mode.toString() : 'null');\n            result.append('\\n ecLevel: ');\n            result.append(this.ecLevel ? this.ecLevel.toString() : 'null');\n            result.append('\\n version: ');\n            result.append(this.version ? this.version.toString() : 'null');\n            result.append('\\n maskPattern: ');\n            result.append(this.maskPattern.toString());\n            if (this.matrix) {\n                result.append('\\n matrix:\\n');\n                result.append(this.matrix.toString());\n            }\n            else {\n                result.append('\\n matrix: null\\n');\n            }\n            result.append('>>\\n');\n            return result.toString();\n        }\n        setMode(value) {\n            this.mode = value;\n        }\n        setECLevel(value) {\n            this.ecLevel = value;\n        }\n        setVersion(version) {\n            this.version = version;\n        }\n        setMaskPattern(value /*int*/) {\n            this.maskPattern = value;\n        }\n        setMatrix(value) {\n            this.matrix = value;\n        }\n        // Check if \"mask_pattern\" is valid.\n        static isValidMaskPattern(maskPattern /*int*/) {\n            return maskPattern >= 0 && maskPattern < QRCode.NUM_MASK_PATTERNS;\n        }\n    }\n    QRCode.NUM_MASK_PATTERNS = 8;\n\n    /**\n     * Custom Error class of type Exception.\n     */\n    class WriterException extends Exception {\n    }\n    WriterException.kind = 'WriterException';\n\n    /**\n     * @author satorux@google.com (Satoru Takabayashi) - creator\n     * @author dswitkin@google.com (Daniel Switkin) - ported from C++\n     */\n    class MatrixUtil {\n        constructor() {\n            // do nothing\n        }\n        // Set all cells to -1 (TYPESCRIPTPORT: 255).  -1 (TYPESCRIPTPORT: 255) means that the cell is empty (not set yet).\n        //\n        // JAVAPORT: We shouldn't need to do this at all. The code should be rewritten to begin encoding\n        // with the ByteMatrix initialized all to zero.\n        static clearMatrix(matrix) {\n            // TYPESCRIPTPORT: we use UintArray se changed here from -1 to 255\n            matrix.clear(/*(byte) */ /*-1*/ 255);\n        }\n        // Build 2D matrix of QR Code from \"dataBits\" with \"ecLevel\", \"version\" and \"getMaskPattern\". On\n        // success, store the result in \"matrix\" and return true.\n        static buildMatrix(dataBits, ecLevel, version, maskPattern /*int*/, matrix) {\n            MatrixUtil.clearMatrix(matrix);\n            MatrixUtil.embedBasicPatterns(version, matrix);\n            // Type information appear with any version.\n            MatrixUtil.embedTypeInfo(ecLevel, maskPattern, matrix);\n            // Version info appear if version >= 7.\n            MatrixUtil.maybeEmbedVersionInfo(version, matrix);\n            // Data should be embedded at end.\n            MatrixUtil.embedDataBits(dataBits, maskPattern, matrix);\n        }\n        // Embed basic patterns. On success, modify the matrix and return true.\n        // The basic patterns are:\n        // - Position detection patterns\n        // - Timing patterns\n        // - Dark dot at the left bottom corner\n        // - Position adjustment patterns, if need be\n        static embedBasicPatterns(version, matrix) {\n            // Let's get started with embedding big squares at corners.\n            MatrixUtil.embedPositionDetectionPatternsAndSeparators(matrix);\n            // Then, embed the dark dot at the left bottom corner.\n            MatrixUtil.embedDarkDotAtLeftBottomCorner(matrix);\n            // Position adjustment patterns appear if version >= 2.\n            MatrixUtil.maybeEmbedPositionAdjustmentPatterns(version, matrix);\n            // Timing patterns should be embedded after position adj. patterns.\n            MatrixUtil.embedTimingPatterns(matrix);\n        }\n        // Embed type information. On success, modify the matrix.\n        static embedTypeInfo(ecLevel, maskPattern /*int*/, matrix) {\n            const typeInfoBits = new BitArray();\n            MatrixUtil.makeTypeInfoBits(ecLevel, maskPattern, typeInfoBits);\n            for (let i = 0, size = typeInfoBits.getSize(); i < size; ++i) {\n                // Place bits in LSB to MSB order.  LSB (least significant bit) is the last value in\n                // \"typeInfoBits\".\n                const bit = typeInfoBits.get(typeInfoBits.getSize() - 1 - i);\n                // Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46).\n                const coordinates = MatrixUtil.TYPE_INFO_COORDINATES[i];\n                const x1 = coordinates[0];\n                const y1 = coordinates[1];\n                matrix.setBoolean(x1, y1, bit);\n                if (i < 8) {\n                    // Right top corner.\n                    const x2 = matrix.getWidth() - i - 1;\n                    const y2 = 8;\n                    matrix.setBoolean(x2, y2, bit);\n                }\n                else {\n                    // Left bottom corner.\n                    const x2 = 8;\n                    const y2 = matrix.getHeight() - 7 + (i - 8);\n                    matrix.setBoolean(x2, y2, bit);\n                }\n            }\n        }\n        // Embed version information if need be. On success, modify the matrix and return true.\n        // See 8.10 of JISX0510:2004 (p.47) for how to embed version information.\n        static maybeEmbedVersionInfo(version, matrix) {\n            if (version.getVersionNumber() < 7) { // Version info is necessary if version >= 7.\n                return; // Don't need version info.\n            }\n            const versionInfoBits = new BitArray();\n            MatrixUtil.makeVersionInfoBits(version, versionInfoBits);\n            let bitIndex = 6 * 3 - 1; // It will decrease from 17 to 0.\n            for (let i = 0; i < 6; ++i) {\n                for (let j = 0; j < 3; ++j) {\n                    // Place bits in LSB (least significant bit) to MSB order.\n                    const bit = versionInfoBits.get(bitIndex);\n                    bitIndex--;\n                    // Left bottom corner.\n                    matrix.setBoolean(i, matrix.getHeight() - 11 + j, bit);\n                    // Right bottom corner.\n                    matrix.setBoolean(matrix.getHeight() - 11 + j, i, bit);\n                }\n            }\n        }\n        // Embed \"dataBits\" using \"getMaskPattern\". On success, modify the matrix and return true.\n        // For debugging purposes, it skips masking process if \"getMaskPattern\" is -1(TYPESCRIPTPORT: 255).\n        // See 8.7 of JISX0510:2004 (p.38) for how to embed data bits.\n        static embedDataBits(dataBits, maskPattern /*int*/, matrix) {\n            let bitIndex = 0;\n            let direction = -1;\n            // Start from the right bottom cell.\n            let x = matrix.getWidth() - 1;\n            let y = matrix.getHeight() - 1;\n            while (x > 0) {\n                // Skip the vertical timing pattern.\n                if (x === 6) {\n                    x -= 1;\n                }\n                while (y >= 0 && y < matrix.getHeight()) {\n                    for (let i = 0; i < 2; ++i) {\n                        const xx = x - i;\n                        // Skip the cell if it's not empty.\n                        if (!MatrixUtil.isEmpty(matrix.get(xx, y))) {\n                            continue;\n                        }\n                        let bit;\n                        if (bitIndex < dataBits.getSize()) {\n                            bit = dataBits.get(bitIndex);\n                            ++bitIndex;\n                        }\n                        else {\n                            // Padding bit. If there is no bit left, we'll fill the left cells with 0, as described\n                            // in 8.4.9 of JISX0510:2004 (p. 24).\n                            bit = false;\n                        }\n                        // Skip masking if mask_pattern is -1 (TYPESCRIPTPORT: 255).\n                        if (maskPattern !== 255 && MaskUtil.getDataMaskBit(maskPattern, xx, y)) {\n                            bit = !bit;\n                        }\n                        matrix.setBoolean(xx, y, bit);\n                    }\n                    y += direction;\n                }\n                direction = -direction; // Reverse the direction.\n                y += direction;\n                x -= 2; // Move to the left.\n            }\n            // All bits should be consumed.\n            if (bitIndex !== dataBits.getSize()) {\n                throw new WriterException('Not all bits consumed: ' + bitIndex + '/' + dataBits.getSize());\n            }\n        }\n        // Return the position of the most significant bit set (one: to) in the \"value\". The most\n        // significant bit is position 32. If there is no bit set, return 0. Examples:\n        // - findMSBSet(0) => 0\n        // - findMSBSet(1) => 1\n        // - findMSBSet(255) => 8\n        static findMSBSet(value /*int*/) {\n            return 32 - Integer.numberOfLeadingZeros(value);\n        }\n        // Calculate BCH (Bose-Chaudhuri-Hocquenghem) code for \"value\" using polynomial \"poly\". The BCH\n        // code is used for encoding type information and version information.\n        // Example: Calculation of version information of 7.\n        // f(x) is created from 7.\n        //   - 7 = 000111 in 6 bits\n        //   - f(x) = x^2 + x^1 + x^0\n        // g(x) is given by the standard (p. 67)\n        //   - g(x) = x^12 + x^11 + x^10 + x^9 + x^8 + x^5 + x^2 + 1\n        // Multiply f(x) by x^(18 - 6)\n        //   - f'(x) = f(x) * x^(18 - 6)\n        //   - f'(x) = x^14 + x^13 + x^12\n        // Calculate the remainder of f'(x) / g(x)\n        //         x^2\n        //         __________________________________________________\n        //   g(x) )x^14 + x^13 + x^12\n        //         x^14 + x^13 + x^12 + x^11 + x^10 + x^7 + x^4 + x^2\n        //         --------------------------------------------------\n        //                              x^11 + x^10 + x^7 + x^4 + x^2\n        //\n        // The remainder is x^11 + x^10 + x^7 + x^4 + x^2\n        // Encode it in binary: 110010010100\n        // The return value is 0xc94 (1100 1001 0100)\n        //\n        // Since all coefficients in the polynomials are 1 or 0, we can do the calculation by bit\n        // operations. We don't care if coefficients are positive or negative.\n        static calculateBCHCode(value /*int*/, poly /*int*/) {\n            if (poly === 0) {\n                throw new IllegalArgumentException('0 polynomial');\n            }\n            // If poly is \"1 1111 0010 0101\" (version info poly), msbSetInPoly is 13. We'll subtract 1\n            // from 13 to make it 12.\n            const msbSetInPoly = MatrixUtil.findMSBSet(poly);\n            value <<= msbSetInPoly - 1;\n            // Do the division business using exclusive-or operations.\n            while (MatrixUtil.findMSBSet(value) >= msbSetInPoly) {\n                value ^= poly << (MatrixUtil.findMSBSet(value) - msbSetInPoly);\n            }\n            // Now the \"value\" is the remainder (i.e. the BCH code)\n            return value;\n        }\n        // Make bit vector of type information. On success, store the result in \"bits\" and return true.\n        // Encode error correction level and mask pattern. See 8.9 of\n        // JISX0510:2004 (p.45) for details.\n        static makeTypeInfoBits(ecLevel, maskPattern /*int*/, bits) {\n            if (!QRCode.isValidMaskPattern(maskPattern)) {\n                throw new WriterException('Invalid mask pattern');\n            }\n            const typeInfo = (ecLevel.getBits() << 3) | maskPattern;\n            bits.appendBits(typeInfo, 5);\n            const bchCode = MatrixUtil.calculateBCHCode(typeInfo, MatrixUtil.TYPE_INFO_POLY);\n            bits.appendBits(bchCode, 10);\n            const maskBits = new BitArray();\n            maskBits.appendBits(MatrixUtil.TYPE_INFO_MASK_PATTERN, 15);\n            bits.xor(maskBits);\n            if (bits.getSize() !== 15) { // Just in case.\n                throw new WriterException('should not happen but we got: ' + bits.getSize());\n            }\n        }\n        // Make bit vector of version information. On success, store the result in \"bits\" and return true.\n        // See 8.10 of JISX0510:2004 (p.45) for details.\n        static makeVersionInfoBits(version, bits) {\n            bits.appendBits(version.getVersionNumber(), 6);\n            const bchCode = MatrixUtil.calculateBCHCode(version.getVersionNumber(), MatrixUtil.VERSION_INFO_POLY);\n            bits.appendBits(bchCode, 12);\n            if (bits.getSize() !== 18) { // Just in case.\n                throw new WriterException('should not happen but we got: ' + bits.getSize());\n            }\n        }\n        // Check if \"value\" is empty.\n        static isEmpty(value /*int*/) {\n            return value === 255; // -1\n        }\n        static embedTimingPatterns(matrix) {\n            // -8 is for skipping position detection patterns (7: size), and two horizontal/vertical\n            // separation patterns (1: size). Thus, 8 = 7 + 1.\n            for (let i = 8; i < matrix.getWidth() - 8; ++i) {\n                const bit = (i + 1) % 2;\n                // Horizontal line.\n                if (MatrixUtil.isEmpty(matrix.get(i, 6))) {\n                    matrix.setNumber(i, 6, bit);\n                }\n                // Vertical line.\n                if (MatrixUtil.isEmpty(matrix.get(6, i))) {\n                    matrix.setNumber(6, i, bit);\n                }\n            }\n        }\n        // Embed the lonely dark dot at left bottom corner. JISX0510:2004 (p.46)\n        static embedDarkDotAtLeftBottomCorner(matrix) {\n            if (matrix.get(8, matrix.getHeight() - 8) === 0) {\n                throw new WriterException();\n            }\n            matrix.setNumber(8, matrix.getHeight() - 8, 1);\n        }\n        static embedHorizontalSeparationPattern(xStart /*int*/, yStart /*int*/, matrix) {\n            for (let x = 0; x < 8; ++x) {\n                if (!MatrixUtil.isEmpty(matrix.get(xStart + x, yStart))) {\n                    throw new WriterException();\n                }\n                matrix.setNumber(xStart + x, yStart, 0);\n            }\n        }\n        static embedVerticalSeparationPattern(xStart /*int*/, yStart /*int*/, matrix) {\n            for (let y = 0; y < 7; ++y) {\n                if (!MatrixUtil.isEmpty(matrix.get(xStart, yStart + y))) {\n                    throw new WriterException();\n                }\n                matrix.setNumber(xStart, yStart + y, 0);\n            }\n        }\n        static embedPositionAdjustmentPattern(xStart /*int*/, yStart /*int*/, matrix) {\n            for (let y = 0; y < 5; ++y) {\n                const patternY = MatrixUtil.POSITION_ADJUSTMENT_PATTERN[y];\n                for (let x = 0; x < 5; ++x) {\n                    matrix.setNumber(xStart + x, yStart + y, patternY[x]);\n                }\n            }\n        }\n        static embedPositionDetectionPattern(xStart /*int*/, yStart /*int*/, matrix) {\n            for (let y = 0; y < 7; ++y) {\n                const patternY = MatrixUtil.POSITION_DETECTION_PATTERN[y];\n                for (let x = 0; x < 7; ++x) {\n                    matrix.setNumber(xStart + x, yStart + y, patternY[x]);\n                }\n            }\n        }\n        // Embed position detection patterns and surrounding vertical/horizontal separators.\n        static embedPositionDetectionPatternsAndSeparators(matrix) {\n            // Embed three big squares at corners.\n            const pdpWidth = MatrixUtil.POSITION_DETECTION_PATTERN[0].length;\n            // Left top corner.\n            MatrixUtil.embedPositionDetectionPattern(0, 0, matrix);\n            // Right top corner.\n            MatrixUtil.embedPositionDetectionPattern(matrix.getWidth() - pdpWidth, 0, matrix);\n            // Left bottom corner.\n            MatrixUtil.embedPositionDetectionPattern(0, matrix.getWidth() - pdpWidth, matrix);\n            // Embed horizontal separation patterns around the squares.\n            const hspWidth = 8;\n            // Left top corner.\n            MatrixUtil.embedHorizontalSeparationPattern(0, hspWidth - 1, matrix);\n            // Right top corner.\n            MatrixUtil.embedHorizontalSeparationPattern(matrix.getWidth() - hspWidth, hspWidth - 1, matrix);\n            // Left bottom corner.\n            MatrixUtil.embedHorizontalSeparationPattern(0, matrix.getWidth() - hspWidth, matrix);\n            // Embed vertical separation patterns around the squares.\n            const vspSize = 7;\n            // Left top corner.\n            MatrixUtil.embedVerticalSeparationPattern(vspSize, 0, matrix);\n            // Right top corner.\n            MatrixUtil.embedVerticalSeparationPattern(matrix.getHeight() - vspSize - 1, 0, matrix);\n            // Left bottom corner.\n            MatrixUtil.embedVerticalSeparationPattern(vspSize, matrix.getHeight() - vspSize, matrix);\n        }\n        // Embed position adjustment patterns if need be.\n        static maybeEmbedPositionAdjustmentPatterns(version, matrix) {\n            if (version.getVersionNumber() < 2) { // The patterns appear if version >= 2\n                return;\n            }\n            const index = version.getVersionNumber() - 1;\n            const coordinates = MatrixUtil.POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index];\n            for (let i = 0, length = coordinates.length; i !== length; i++) {\n                const y = coordinates[i];\n                if (y >= 0) {\n                    for (let j = 0; j !== length; j++) {\n                        const x = coordinates[j];\n                        if (x >= 0 && MatrixUtil.isEmpty(matrix.get(x, y))) {\n                            // If the cell is unset, we embed the position adjustment pattern here.\n                            // -2 is necessary since the x/y coordinates point to the center of the pattern, not the\n                            // left top corner.\n                            MatrixUtil.embedPositionAdjustmentPattern(x - 2, y - 2, matrix);\n                        }\n                    }\n                }\n            }\n        }\n    }\n    MatrixUtil.POSITION_DETECTION_PATTERN = Array.from([\n        Int32Array.from([1, 1, 1, 1, 1, 1, 1]),\n        Int32Array.from([1, 0, 0, 0, 0, 0, 1]),\n        Int32Array.from([1, 0, 1, 1, 1, 0, 1]),\n        Int32Array.from([1, 0, 1, 1, 1, 0, 1]),\n        Int32Array.from([1, 0, 1, 1, 1, 0, 1]),\n        Int32Array.from([1, 0, 0, 0, 0, 0, 1]),\n        Int32Array.from([1, 1, 1, 1, 1, 1, 1]),\n    ]);\n    MatrixUtil.POSITION_ADJUSTMENT_PATTERN = Array.from([\n        Int32Array.from([1, 1, 1, 1, 1]),\n        Int32Array.from([1, 0, 0, 0, 1]),\n        Int32Array.from([1, 0, 1, 0, 1]),\n        Int32Array.from([1, 0, 0, 0, 1]),\n        Int32Array.from([1, 1, 1, 1, 1]),\n    ]);\n    // From Appendix E. Table 1, JIS0510X:2004 (71: p). The table was double-checked by komatsu.\n    MatrixUtil.POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE = Array.from([\n        Int32Array.from([-1, -1, -1, -1, -1, -1, -1]),\n        Int32Array.from([6, 18, -1, -1, -1, -1, -1]),\n        Int32Array.from([6, 22, -1, -1, -1, -1, -1]),\n        Int32Array.from([6, 26, -1, -1, -1, -1, -1]),\n        Int32Array.from([6, 30, -1, -1, -1, -1, -1]),\n        Int32Array.from([6, 34, -1, -1, -1, -1, -1]),\n        Int32Array.from([6, 22, 38, -1, -1, -1, -1]),\n        Int32Array.from([6, 24, 42, -1, -1, -1, -1]),\n        Int32Array.from([6, 26, 46, -1, -1, -1, -1]),\n        Int32Array.from([6, 28, 50, -1, -1, -1, -1]),\n        Int32Array.from([6, 30, 54, -1, -1, -1, -1]),\n        Int32Array.from([6, 32, 58, -1, -1, -1, -1]),\n        Int32Array.from([6, 34, 62, -1, -1, -1, -1]),\n        Int32Array.from([6, 26, 46, 66, -1, -1, -1]),\n        Int32Array.from([6, 26, 48, 70, -1, -1, -1]),\n        Int32Array.from([6, 26, 50, 74, -1, -1, -1]),\n        Int32Array.from([6, 30, 54, 78, -1, -1, -1]),\n        Int32Array.from([6, 30, 56, 82, -1, -1, -1]),\n        Int32Array.from([6, 30, 58, 86, -1, -1, -1]),\n        Int32Array.from([6, 34, 62, 90, -1, -1, -1]),\n        Int32Array.from([6, 28, 50, 72, 94, -1, -1]),\n        Int32Array.from([6, 26, 50, 74, 98, -1, -1]),\n        Int32Array.from([6, 30, 54, 78, 102, -1, -1]),\n        Int32Array.from([6, 28, 54, 80, 106, -1, -1]),\n        Int32Array.from([6, 32, 58, 84, 110, -1, -1]),\n        Int32Array.from([6, 30, 58, 86, 114, -1, -1]),\n        Int32Array.from([6, 34, 62, 90, 118, -1, -1]),\n        Int32Array.from([6, 26, 50, 74, 98, 122, -1]),\n        Int32Array.from([6, 30, 54, 78, 102, 126, -1]),\n        Int32Array.from([6, 26, 52, 78, 104, 130, -1]),\n        Int32Array.from([6, 30, 56, 82, 108, 134, -1]),\n        Int32Array.from([6, 34, 60, 86, 112, 138, -1]),\n        Int32Array.from([6, 30, 58, 86, 114, 142, -1]),\n        Int32Array.from([6, 34, 62, 90, 118, 146, -1]),\n        Int32Array.from([6, 30, 54, 78, 102, 126, 150]),\n        Int32Array.from([6, 24, 50, 76, 102, 128, 154]),\n        Int32Array.from([6, 28, 54, 80, 106, 132, 158]),\n        Int32Array.from([6, 32, 58, 84, 110, 136, 162]),\n        Int32Array.from([6, 26, 54, 82, 110, 138, 166]),\n        Int32Array.from([6, 30, 58, 86, 114, 142, 170]),\n    ]);\n    // Type info cells at the left top corner.\n    MatrixUtil.TYPE_INFO_COORDINATES = Array.from([\n        Int32Array.from([8, 0]),\n        Int32Array.from([8, 1]),\n        Int32Array.from([8, 2]),\n        Int32Array.from([8, 3]),\n        Int32Array.from([8, 4]),\n        Int32Array.from([8, 5]),\n        Int32Array.from([8, 7]),\n        Int32Array.from([8, 8]),\n        Int32Array.from([7, 8]),\n        Int32Array.from([5, 8]),\n        Int32Array.from([4, 8]),\n        Int32Array.from([3, 8]),\n        Int32Array.from([2, 8]),\n        Int32Array.from([1, 8]),\n        Int32Array.from([0, 8]),\n    ]);\n    // From Appendix D in JISX0510:2004 (p. 67)\n    MatrixUtil.VERSION_INFO_POLY = 0x1f25; // 1 1111 0010 0101\n    // From Appendix C in JISX0510:2004 (p.65).\n    MatrixUtil.TYPE_INFO_POLY = 0x537;\n    MatrixUtil.TYPE_INFO_MASK_PATTERN = 0x5412;\n\n    /*namespace com.google.zxing.qrcode.encoder {*/\n    class BlockPair {\n        constructor(dataBytes, errorCorrectionBytes) {\n            this.dataBytes = dataBytes;\n            this.errorCorrectionBytes = errorCorrectionBytes;\n        }\n        getDataBytes() {\n            return this.dataBytes;\n        }\n        getErrorCorrectionBytes() {\n            return this.errorCorrectionBytes;\n        }\n    }\n\n    /*import java.io.UnsupportedEncodingException;*/\n    /*import java.util.ArrayList;*/\n    /*import java.util.Collection;*/\n    /*import java.util.Map;*/\n    /**\n     * @author satorux@google.com (Satoru Takabayashi) - creator\n     * @author dswitkin@google.com (Daniel Switkin) - ported from C++\n     */\n    class Encoder {\n        // TYPESCRIPTPORT: changed to UTF8, the default for js\n        constructor() { }\n        // The mask penalty calculation is complicated.  See Table 21 of JISX0510:2004 (p.45) for details.\n        // Basically it applies four rules and summate all penalties.\n        static calculateMaskPenalty(matrix) {\n            return MaskUtil.applyMaskPenaltyRule1(matrix)\n                + MaskUtil.applyMaskPenaltyRule2(matrix)\n                + MaskUtil.applyMaskPenaltyRule3(matrix)\n                + MaskUtil.applyMaskPenaltyRule4(matrix);\n        }\n        /**\n         * @param content text to encode\n         * @param ecLevel error correction level to use\n         * @return {@link QRCode} representing the encoded QR code\n         * @throws WriterException if encoding can't succeed, because of for example invalid content\n         *   or configuration\n         */\n        // public static encode(content: string, ecLevel: ErrorCorrectionLevel): QRCode /*throws WriterException*/ {\n        //   return encode(content, ecLevel, null)\n        // }\n        static encode(content, ecLevel, hints = null) {\n            // Determine what character encoding has been specified by the caller, if any\n            let encoding = Encoder.DEFAULT_BYTE_MODE_ENCODING;\n            const hasEncodingHint = hints !== null && undefined !== hints.get(EncodeHintType$1.CHARACTER_SET);\n            if (hasEncodingHint) {\n                encoding = hints.get(EncodeHintType$1.CHARACTER_SET).toString();\n            }\n            // Pick an encoding mode appropriate for the content. Note that this will not attempt to use\n            // multiple modes / segments even if that were more efficient. Twould be nice.\n            const mode = this.chooseMode(content, encoding);\n            // This will store the header information, like mode and\n            // length, as well as \"header\" segments like an ECI segment.\n            const headerBits = new BitArray();\n            // Append ECI segment if applicable\n            if (mode === Mode$1.BYTE && (hasEncodingHint || Encoder.DEFAULT_BYTE_MODE_ENCODING !== encoding)) {\n                const eci = CharacterSetECI.getCharacterSetECIByName(encoding);\n                if (eci !== undefined) {\n                    this.appendECI(eci, headerBits);\n                }\n            }\n            // (With ECI in place,) Write the mode marker\n            this.appendModeInfo(mode, headerBits);\n            // Collect data within the main segment, separately, to count its size if needed. Don't add it to\n            // main payload yet.\n            const dataBits = new BitArray();\n            this.appendBytes(content, mode, dataBits, encoding);\n            let version;\n            if (hints !== null && undefined !== hints.get(EncodeHintType$1.QR_VERSION)) {\n                const versionNumber = Number.parseInt(hints.get(EncodeHintType$1.QR_VERSION).toString(), 10);\n                version = Version$1.getVersionForNumber(versionNumber);\n                const bitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, version);\n                if (!this.willFit(bitsNeeded, version, ecLevel)) {\n                    throw new WriterException('Data too big for requested version');\n                }\n            }\n            else {\n                version = this.recommendVersion(ecLevel, mode, headerBits, dataBits);\n            }\n            const headerAndDataBits = new BitArray();\n            headerAndDataBits.appendBitArray(headerBits);\n            // Find \"length\" of main segment and write it\n            const numLetters = mode === Mode$1.BYTE ? dataBits.getSizeInBytes() : content.length;\n            this.appendLengthInfo(numLetters, version, mode, headerAndDataBits);\n            // Put data together into the overall payload\n            headerAndDataBits.appendBitArray(dataBits);\n            const ecBlocks = version.getECBlocksForLevel(ecLevel);\n            const numDataBytes = version.getTotalCodewords() - ecBlocks.getTotalECCodewords();\n            // Terminate the bits properly.\n            this.terminateBits(numDataBytes, headerAndDataBits);\n            // Interleave data bits with error correction code.\n            const finalBits = this.interleaveWithECBytes(headerAndDataBits, version.getTotalCodewords(), numDataBytes, ecBlocks.getNumBlocks());\n            const qrCode = new QRCode();\n            qrCode.setECLevel(ecLevel);\n            qrCode.setMode(mode);\n            qrCode.setVersion(version);\n            //  Choose the mask pattern and set to \"qrCode\".\n            const dimension = version.getDimensionForVersion();\n            const matrix = new ByteMatrix(dimension, dimension);\n            const maskPattern = this.chooseMaskPattern(finalBits, ecLevel, version, matrix);\n            qrCode.setMaskPattern(maskPattern);\n            // Build the matrix and set it to \"qrCode\".\n            MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix);\n            qrCode.setMatrix(matrix);\n            return qrCode;\n        }\n        /**\n         * Decides the smallest version of QR code that will contain all of the provided data.\n         *\n         * @throws WriterException if the data cannot fit in any version\n         */\n        static recommendVersion(ecLevel, mode, headerBits, dataBits) {\n            // Hard part: need to know version to know how many bits length takes. But need to know how many\n            // bits it takes to know version. First we take a guess at version by assuming version will be\n            // the minimum, 1:\n            const provisionalBitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, Version$1.getVersionForNumber(1));\n            const provisionalVersion = this.chooseVersion(provisionalBitsNeeded, ecLevel);\n            // Use that guess to calculate the right version. I am still not sure this works in 100% of cases.\n            const bitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, provisionalVersion);\n            return this.chooseVersion(bitsNeeded, ecLevel);\n        }\n        static calculateBitsNeeded(mode, headerBits, dataBits, version) {\n            return headerBits.getSize() + mode.getCharacterCountBits(version) + dataBits.getSize();\n        }\n        /**\n         * @return the code point of the table used in alphanumeric mode or\n         *  -1 if there is no corresponding code in the table.\n         */\n        static getAlphanumericCode(code /*int*/) {\n            if (code < Encoder.ALPHANUMERIC_TABLE.length) {\n                return Encoder.ALPHANUMERIC_TABLE[code];\n            }\n            return -1;\n        }\n        // public static chooseMode(content: string): Mode {\n        //   return chooseMode(content, null);\n        // }\n        /**\n         * Choose the best mode by examining the content. Note that 'encoding' is used as a hint;\n         * if it is Shift_JIS, and the input is only double-byte Kanji, then we return {@link Mode#KANJI}.\n         */\n        static chooseMode(content, encoding = null) {\n            if (CharacterSetECI.SJIS.getName() === encoding && this.isOnlyDoubleByteKanji(content)) {\n                // Choose Kanji mode if all input are double-byte characters\n                return Mode$1.KANJI;\n            }\n            let hasNumeric = false;\n            let hasAlphanumeric = false;\n            for (let i = 0, length = content.length; i < length; ++i) {\n                const c = content.charAt(i);\n                if (Encoder.isDigit(c)) {\n                    hasNumeric = true;\n                }\n                else if (this.getAlphanumericCode(c.charCodeAt(0)) !== -1) {\n                    hasAlphanumeric = true;\n                }\n                else {\n                    return Mode$1.BYTE;\n                }\n            }\n            if (hasAlphanumeric) {\n                return Mode$1.ALPHANUMERIC;\n            }\n            if (hasNumeric) {\n                return Mode$1.NUMERIC;\n            }\n            return Mode$1.BYTE;\n        }\n        static isOnlyDoubleByteKanji(content) {\n            let bytes;\n            try {\n                bytes = StringEncoding.encode(content, CharacterSetECI.SJIS); // content.getBytes(\"Shift_JIS\"))\n            }\n            catch (ignored /*: UnsupportedEncodingException*/) {\n                return false;\n            }\n            const length = bytes.length;\n            if (length % 2 !== 0) {\n                return false;\n            }\n            for (let i = 0; i < length; i += 2) {\n                const byte1 = bytes[i] & 0xFF;\n                if ((byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB)) {\n                    return false;\n                }\n            }\n            return true;\n        }\n        static chooseMaskPattern(bits, ecLevel, version, matrix) {\n            let minPenalty = Number.MAX_SAFE_INTEGER; // Lower penalty is better.\n            let bestMaskPattern = -1;\n            // We try all mask patterns to choose the best one.\n            for (let maskPattern = 0; maskPattern < QRCode.NUM_MASK_PATTERNS; maskPattern++) {\n                MatrixUtil.buildMatrix(bits, ecLevel, version, maskPattern, matrix);\n                let penalty = this.calculateMaskPenalty(matrix);\n                if (penalty < minPenalty) {\n                    minPenalty = penalty;\n                    bestMaskPattern = maskPattern;\n                }\n            }\n            return bestMaskPattern;\n        }\n        static chooseVersion(numInputBits /*int*/, ecLevel) {\n            for (let versionNum = 1; versionNum <= 40; versionNum++) {\n                const version = Version$1.getVersionForNumber(versionNum);\n                if (Encoder.willFit(numInputBits, version, ecLevel)) {\n                    return version;\n                }\n            }\n            throw new WriterException('Data too big');\n        }\n        /**\n         * @return true if the number of input bits will fit in a code with the specified version and\n         * error correction level.\n         */\n        static willFit(numInputBits /*int*/, version, ecLevel) {\n            // In the following comments, we use numbers of Version 7-H.\n            // numBytes = 196\n            const numBytes = version.getTotalCodewords();\n            // getNumECBytes = 130\n            const ecBlocks = version.getECBlocksForLevel(ecLevel);\n            const numEcBytes = ecBlocks.getTotalECCodewords();\n            // getNumDataBytes = 196 - 130 = 66\n            const numDataBytes = numBytes - numEcBytes;\n            const totalInputBytes = (numInputBits + 7) / 8;\n            return numDataBytes >= totalInputBytes;\n        }\n        /**\n         * Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24).\n         */\n        static terminateBits(numDataBytes /*int*/, bits) {\n            const capacity = numDataBytes * 8;\n            if (bits.getSize() > capacity) {\n                throw new WriterException('data bits cannot fit in the QR Code' + bits.getSize() + ' > ' +\n                    capacity);\n            }\n            for (let i = 0; i < 4 && bits.getSize() < capacity; ++i) {\n                bits.appendBit(false);\n            }\n            // Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details.\n            // If the last byte isn't 8-bit aligned, we'll add padding bits.\n            const numBitsInLastByte = bits.getSize() & 0x07;\n            if (numBitsInLastByte > 0) {\n                for (let i = numBitsInLastByte; i < 8; i++) {\n                    bits.appendBit(false);\n                }\n            }\n            // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24).\n            const numPaddingBytes = numDataBytes - bits.getSizeInBytes();\n            for (let i = 0; i < numPaddingBytes; ++i) {\n                bits.appendBits((i & 0x01) === 0 ? 0xEC : 0x11, 8);\n            }\n            if (bits.getSize() !== capacity) {\n                throw new WriterException('Bits size does not equal capacity');\n            }\n        }\n        /**\n         * Get number of data bytes and number of error correction bytes for block id \"blockID\". Store\n         * the result in \"numDataBytesInBlock\", and \"numECBytesInBlock\". See table 12 in 8.5.1 of\n         * JISX0510:2004 (p.30)\n         */\n        static getNumDataBytesAndNumECBytesForBlockID(numTotalBytes /*int*/, numDataBytes /*int*/, numRSBlocks /*int*/, blockID /*int*/, numDataBytesInBlock, numECBytesInBlock) {\n            if (blockID >= numRSBlocks) {\n                throw new WriterException('Block ID too large');\n            }\n            // numRsBlocksInGroup2 = 196 % 5 = 1\n            const numRsBlocksInGroup2 = numTotalBytes % numRSBlocks;\n            // numRsBlocksInGroup1 = 5 - 1 = 4\n            const numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2;\n            // numTotalBytesInGroup1 = 196 / 5 = 39\n            const numTotalBytesInGroup1 = Math.floor(numTotalBytes / numRSBlocks);\n            // numTotalBytesInGroup2 = 39 + 1 = 40\n            const numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1;\n            // numDataBytesInGroup1 = 66 / 5 = 13\n            const numDataBytesInGroup1 = Math.floor(numDataBytes / numRSBlocks);\n            // numDataBytesInGroup2 = 13 + 1 = 14\n            const numDataBytesInGroup2 = numDataBytesInGroup1 + 1;\n            // numEcBytesInGroup1 = 39 - 13 = 26\n            const numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1;\n            // numEcBytesInGroup2 = 40 - 14 = 26\n            const numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2;\n            // Sanity checks.\n            // 26 = 26\n            if (numEcBytesInGroup1 !== numEcBytesInGroup2) {\n                throw new WriterException('EC bytes mismatch');\n            }\n            // 5 = 4 + 1.\n            if (numRSBlocks !== numRsBlocksInGroup1 + numRsBlocksInGroup2) {\n                throw new WriterException('RS blocks mismatch');\n            }\n            // 196 = (13 + 26) * 4 + (14 + 26) * 1\n            if (numTotalBytes !==\n                ((numDataBytesInGroup1 + numEcBytesInGroup1) *\n                    numRsBlocksInGroup1) +\n                    ((numDataBytesInGroup2 + numEcBytesInGroup2) *\n                        numRsBlocksInGroup2)) {\n                throw new WriterException('Total bytes mismatch');\n            }\n            if (blockID < numRsBlocksInGroup1) {\n                numDataBytesInBlock[0] = numDataBytesInGroup1;\n                numECBytesInBlock[0] = numEcBytesInGroup1;\n            }\n            else {\n                numDataBytesInBlock[0] = numDataBytesInGroup2;\n                numECBytesInBlock[0] = numEcBytesInGroup2;\n            }\n        }\n        /**\n         * Interleave \"bits\" with corresponding error correction bytes. On success, store the result in\n         * \"result\". The interleave rule is complicated. See 8.6 of JISX0510:2004 (p.37) for details.\n         */\n        static interleaveWithECBytes(bits, numTotalBytes /*int*/, numDataBytes /*int*/, numRSBlocks /*int*/) {\n            // \"bits\" must have \"getNumDataBytes\" bytes of data.\n            if (bits.getSizeInBytes() !== numDataBytes) {\n                throw new WriterException('Number of bits and data bytes does not match');\n            }\n            // Step 1.  Divide data bytes into blocks and generate error correction bytes for them. We'll\n            // store the divided data bytes blocks and error correction bytes blocks into \"blocks\".\n            let dataBytesOffset = 0;\n            let maxNumDataBytes = 0;\n            let maxNumEcBytes = 0;\n            // Since, we know the number of reedsolmon blocks, we can initialize the vector with the number.\n            const blocks = new Array(); // new Array<BlockPair>(numRSBlocks)\n            for (let i = 0; i < numRSBlocks; ++i) {\n                const numDataBytesInBlock = new Int32Array(1);\n                const numEcBytesInBlock = new Int32Array(1);\n                Encoder.getNumDataBytesAndNumECBytesForBlockID(numTotalBytes, numDataBytes, numRSBlocks, i, numDataBytesInBlock, numEcBytesInBlock);\n                const size = numDataBytesInBlock[0];\n                const dataBytes = new Uint8Array(size);\n                bits.toBytes(8 * dataBytesOffset, dataBytes, 0, size);\n                const ecBytes = Encoder.generateECBytes(dataBytes, numEcBytesInBlock[0]);\n                blocks.push(new BlockPair(dataBytes, ecBytes));\n                maxNumDataBytes = Math.max(maxNumDataBytes, size);\n                maxNumEcBytes = Math.max(maxNumEcBytes, ecBytes.length);\n                dataBytesOffset += numDataBytesInBlock[0];\n            }\n            if (numDataBytes !== dataBytesOffset) {\n                throw new WriterException('Data bytes does not match offset');\n            }\n            const result = new BitArray();\n            // First, place data blocks.\n            for (let i = 0; i < maxNumDataBytes; ++i) {\n                for (const block of blocks) {\n                    const dataBytes = block.getDataBytes();\n                    if (i < dataBytes.length) {\n                        result.appendBits(dataBytes[i], 8);\n                    }\n                }\n            }\n            // Then, place error correction blocks.\n            for (let i = 0; i < maxNumEcBytes; ++i) {\n                for (const block of blocks) {\n                    const ecBytes = block.getErrorCorrectionBytes();\n                    if (i < ecBytes.length) {\n                        result.appendBits(ecBytes[i], 8);\n                    }\n                }\n            }\n            if (numTotalBytes !== result.getSizeInBytes()) { // Should be same.\n                throw new WriterException('Interleaving error: ' + numTotalBytes + ' and ' +\n                    result.getSizeInBytes() + ' differ.');\n            }\n            return result;\n        }\n        static generateECBytes(dataBytes, numEcBytesInBlock /*int*/) {\n            const numDataBytes = dataBytes.length;\n            const toEncode = new Int32Array(numDataBytes + numEcBytesInBlock); // int[numDataBytes + numEcBytesInBlock]\n            for (let i = 0; i < numDataBytes; i++) {\n                toEncode[i] = dataBytes[i] & 0xFF;\n            }\n            new ReedSolomonEncoder(GenericGF.QR_CODE_FIELD_256).encode(toEncode, numEcBytesInBlock);\n            const ecBytes = new Uint8Array(numEcBytesInBlock);\n            for (let i = 0; i < numEcBytesInBlock; i++) {\n                ecBytes[i] = /*(byte) */ toEncode[numDataBytes + i];\n            }\n            return ecBytes;\n        }\n        /**\n         * Append mode info. On success, store the result in \"bits\".\n         */\n        static appendModeInfo(mode, bits) {\n            bits.appendBits(mode.getBits(), 4);\n        }\n        /**\n         * Append length info. On success, store the result in \"bits\".\n         */\n        static appendLengthInfo(numLetters /*int*/, version, mode, bits) {\n            const numBits = mode.getCharacterCountBits(version);\n            if (numLetters >= (1 << numBits)) {\n                throw new WriterException(numLetters + ' is bigger than ' + ((1 << numBits) - 1));\n            }\n            bits.appendBits(numLetters, numBits);\n        }\n        /**\n         * Append \"bytes\" in \"mode\" mode (encoding) into \"bits\". On success, store the result in \"bits\".\n         */\n        static appendBytes(content, mode, bits, encoding) {\n            switch (mode) {\n                case Mode$1.NUMERIC:\n                    Encoder.appendNumericBytes(content, bits);\n                    break;\n                case Mode$1.ALPHANUMERIC:\n                    Encoder.appendAlphanumericBytes(content, bits);\n                    break;\n                case Mode$1.BYTE:\n                    Encoder.append8BitBytes(content, bits, encoding);\n                    break;\n                case Mode$1.KANJI:\n                    Encoder.appendKanjiBytes(content, bits);\n                    break;\n                default:\n                    throw new WriterException('Invalid mode: ' + mode);\n            }\n        }\n        static getDigit(singleCharacter) {\n            return singleCharacter.charCodeAt(0) - 48;\n        }\n        static isDigit(singleCharacter) {\n            const cn = Encoder.getDigit(singleCharacter);\n            return cn >= 0 && cn <= 9;\n        }\n        static appendNumericBytes(content, bits) {\n            const length = content.length;\n            let i = 0;\n            while (i < length) {\n                const num1 = Encoder.getDigit(content.charAt(i));\n                if (i + 2 < length) {\n                    // Encode three numeric letters in ten bits.\n                    const num2 = Encoder.getDigit(content.charAt(i + 1));\n                    const num3 = Encoder.getDigit(content.charAt(i + 2));\n                    bits.appendBits(num1 * 100 + num2 * 10 + num3, 10);\n                    i += 3;\n                }\n                else if (i + 1 < length) {\n                    // Encode two numeric letters in seven bits.\n                    const num2 = Encoder.getDigit(content.charAt(i + 1));\n                    bits.appendBits(num1 * 10 + num2, 7);\n                    i += 2;\n                }\n                else {\n                    // Encode one numeric letter in four bits.\n                    bits.appendBits(num1, 4);\n                    i++;\n                }\n            }\n        }\n        static appendAlphanumericBytes(content, bits) {\n            const length = content.length;\n            let i = 0;\n            while (i < length) {\n                const code1 = Encoder.getAlphanumericCode(content.charCodeAt(i));\n                if (code1 === -1) {\n                    throw new WriterException();\n                }\n                if (i + 1 < length) {\n                    const code2 = Encoder.getAlphanumericCode(content.charCodeAt(i + 1));\n                    if (code2 === -1) {\n                        throw new WriterException();\n                    }\n                    // Encode two alphanumeric letters in 11 bits.\n                    bits.appendBits(code1 * 45 + code2, 11);\n                    i += 2;\n                }\n                else {\n                    // Encode one alphanumeric letter in six bits.\n                    bits.appendBits(code1, 6);\n                    i++;\n                }\n            }\n        }\n        static append8BitBytes(content, bits, encoding) {\n            let bytes;\n            try {\n                bytes = StringEncoding.encode(content, encoding);\n            }\n            catch (uee /*: UnsupportedEncodingException*/) {\n                throw new WriterException(uee);\n            }\n            for (let i = 0, length = bytes.length; i !== length; i++) {\n                const b = bytes[i];\n                bits.appendBits(b, 8);\n            }\n        }\n        /**\n         * @throws WriterException\n         */\n        static appendKanjiBytes(content, bits) {\n            let bytes;\n            try {\n                bytes = StringEncoding.encode(content, CharacterSetECI.SJIS);\n            }\n            catch (uee /*: UnsupportedEncodingException*/) {\n                throw new WriterException(uee);\n            }\n            const length = bytes.length;\n            for (let i = 0; i < length; i += 2) {\n                const byte1 = bytes[i] & 0xFF;\n                const byte2 = bytes[i + 1] & 0xFF;\n                const code = ((byte1 << 8) & 0xFFFFFFFF) | byte2;\n                let subtracted = -1;\n                if (code >= 0x8140 && code <= 0x9ffc) {\n                    subtracted = code - 0x8140;\n                }\n                else if (code >= 0xe040 && code <= 0xebbf) {\n                    subtracted = code - 0xc140;\n                }\n                if (subtracted === -1) {\n                    throw new WriterException('Invalid byte sequence');\n                }\n                const encoded = ((subtracted >> 8) * 0xc0) + (subtracted & 0xff);\n                bits.appendBits(encoded, 13);\n            }\n        }\n        static appendECI(eci, bits) {\n            bits.appendBits(Mode$1.ECI.getBits(), 4);\n            // This is correct for values up to 127, which is all we need now.\n            bits.appendBits(eci.getValue(), 8);\n        }\n    }\n    // The original table is defined in the table 5 of JISX0510:2004 (p.19).\n    Encoder.ALPHANUMERIC_TABLE = Int32Array.from([\n        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n        36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,\n        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1,\n        -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n        25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,\n    ]);\n    Encoder.DEFAULT_BYTE_MODE_ENCODING = CharacterSetECI.UTF8.getName(); // \"ISO-8859-1\"\n\n    /**\n     * @deprecated Moving to @zxing/browser\n     */\n    class BrowserQRCodeSvgWriter {\n        /**\n         * Writes and renders a QRCode SVG element.\n         *\n         * @param contents\n         * @param width\n         * @param height\n         * @param hints\n         */\n        write(contents, width, height, hints = null) {\n            if (contents.length === 0) {\n                throw new IllegalArgumentException('Found empty contents');\n            }\n            // if (format != BarcodeFormat.QR_CODE) {\n            //   throw new IllegalArgumentException(\"Can only encode QR_CODE, but got \" + format)\n            // }\n            if (width < 0 || height < 0) {\n                throw new IllegalArgumentException('Requested dimensions are too small: ' + width + 'x' + height);\n            }\n            let errorCorrectionLevel = ErrorCorrectionLevel.L;\n            let quietZone = BrowserQRCodeSvgWriter.QUIET_ZONE_SIZE;\n            if (hints !== null) {\n                if (undefined !== hints.get(EncodeHintType$1.ERROR_CORRECTION)) {\n                    errorCorrectionLevel = ErrorCorrectionLevel.fromString(hints.get(EncodeHintType$1.ERROR_CORRECTION).toString());\n                }\n                if (undefined !== hints.get(EncodeHintType$1.MARGIN)) {\n                    quietZone = Number.parseInt(hints.get(EncodeHintType$1.MARGIN).toString(), 10);\n                }\n            }\n            const code = Encoder.encode(contents, errorCorrectionLevel, hints);\n            return this.renderResult(code, width, height, quietZone);\n        }\n        /**\n         * Renders the result and then appends it to the DOM.\n         */\n        writeToDom(containerElement, contents, width, height, hints = null) {\n            if (typeof containerElement === 'string') {\n                containerElement = document.querySelector(containerElement);\n            }\n            const svgElement = this.write(contents, width, height, hints);\n            if (containerElement)\n                containerElement.appendChild(svgElement);\n        }\n        /**\n         * Note that the input matrix uses 0 == white, 1 == black.\n         * The output matrix uses 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).\n         */\n        renderResult(code, width /*int*/, height /*int*/, quietZone /*int*/) {\n            const input = code.getMatrix();\n            if (input === null) {\n                throw new IllegalStateException();\n            }\n            const inputWidth = input.getWidth();\n            const inputHeight = input.getHeight();\n            const qrWidth = inputWidth + (quietZone * 2);\n            const qrHeight = inputHeight + (quietZone * 2);\n            const outputWidth = Math.max(width, qrWidth);\n            const outputHeight = Math.max(height, qrHeight);\n            const multiple = Math.min(Math.floor(outputWidth / qrWidth), Math.floor(outputHeight / qrHeight));\n            // Padding includes both the quiet zone and the extra white pixels to accommodate the requested\n            // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone.\n            // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will\n            // handle all the padding from 100x100 (the actual QR) up to 200x160.\n            const leftPadding = Math.floor((outputWidth - (inputWidth * multiple)) / 2);\n            const topPadding = Math.floor((outputHeight - (inputHeight * multiple)) / 2);\n            const svgElement = this.createSVGElement(outputWidth, outputHeight);\n            for (let inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {\n                // Write the contents of this row of the barcode\n                for (let inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {\n                    if (input.get(inputX, inputY) === 1) {\n                        const svgRectElement = this.createSvgRectElement(outputX, outputY, multiple, multiple);\n                        svgElement.appendChild(svgRectElement);\n                    }\n                }\n            }\n            return svgElement;\n        }\n        /**\n         * Creates a SVG element.\n         *\n         * @param w SVG's width attribute\n         * @param h SVG's height attribute\n         */\n        createSVGElement(w, h) {\n            const svgElement = document.createElementNS(BrowserQRCodeSvgWriter.SVG_NS, 'svg');\n            svgElement.setAttributeNS(null, 'height', w.toString());\n            svgElement.setAttributeNS(null, 'width', h.toString());\n            return svgElement;\n        }\n        /**\n         * Creates a SVG rect element.\n         *\n         * @param x Element's x coordinate\n         * @param y Element's y coordinate\n         * @param w Element's width attribute\n         * @param h Element's height attribute\n         */\n        createSvgRectElement(x, y, w, h) {\n            const rect = document.createElementNS(BrowserQRCodeSvgWriter.SVG_NS, 'rect');\n            rect.setAttributeNS(null, 'x', x.toString());\n            rect.setAttributeNS(null, 'y', y.toString());\n            rect.setAttributeNS(null, 'height', w.toString());\n            rect.setAttributeNS(null, 'width', h.toString());\n            rect.setAttributeNS(null, 'fill', '#000000');\n            return rect;\n        }\n    }\n    BrowserQRCodeSvgWriter.QUIET_ZONE_SIZE = 4;\n    /**\n     * SVG markup NameSpace\n     */\n    BrowserQRCodeSvgWriter.SVG_NS = 'http://www.w3.org/2000/svg';\n\n    /*import java.util.Map;*/\n    /**\n     * This object renders a QR Code as a BitMatrix 2D array of greyscale values.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class QRCodeWriter {\n        /*@Override*/\n        // public encode(contents: string, format: BarcodeFormat, width: number /*int*/, height: number /*int*/): BitMatrix\n        //     /*throws WriterException */ {\n        //   return encode(contents, format, width, height, null)\n        // }\n        /*@Override*/\n        encode(contents, format, width /*int*/, height /*int*/, hints) {\n            if (contents.length === 0) {\n                throw new IllegalArgumentException('Found empty contents');\n            }\n            if (format !== BarcodeFormat$1.QR_CODE) {\n                throw new IllegalArgumentException('Can only encode QR_CODE, but got ' + format);\n            }\n            if (width < 0 || height < 0) {\n                throw new IllegalArgumentException(`Requested dimensions are too small: ${width}x${height}`);\n            }\n            let errorCorrectionLevel = ErrorCorrectionLevel.L;\n            let quietZone = QRCodeWriter.QUIET_ZONE_SIZE;\n            if (hints !== null) {\n                if (undefined !== hints.get(EncodeHintType$1.ERROR_CORRECTION)) {\n                    errorCorrectionLevel = ErrorCorrectionLevel.fromString(hints.get(EncodeHintType$1.ERROR_CORRECTION).toString());\n                }\n                if (undefined !== hints.get(EncodeHintType$1.MARGIN)) {\n                    quietZone = Number.parseInt(hints.get(EncodeHintType$1.MARGIN).toString(), 10);\n                }\n            }\n            const code = Encoder.encode(contents, errorCorrectionLevel, hints);\n            return QRCodeWriter.renderResult(code, width, height, quietZone);\n        }\n        // Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses\n        // 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).\n        static renderResult(code, width /*int*/, height /*int*/, quietZone /*int*/) {\n            const input = code.getMatrix();\n            if (input === null) {\n                throw new IllegalStateException();\n            }\n            const inputWidth = input.getWidth();\n            const inputHeight = input.getHeight();\n            const qrWidth = inputWidth + (quietZone * 2);\n            const qrHeight = inputHeight + (quietZone * 2);\n            const outputWidth = Math.max(width, qrWidth);\n            const outputHeight = Math.max(height, qrHeight);\n            const multiple = Math.min(Math.floor(outputWidth / qrWidth), Math.floor(outputHeight / qrHeight));\n            // Padding includes both the quiet zone and the extra white pixels to accommodate the requested\n            // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone.\n            // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will\n            // handle all the padding from 100x100 (the actual QR) up to 200x160.\n            const leftPadding = Math.floor((outputWidth - (inputWidth * multiple)) / 2);\n            const topPadding = Math.floor((outputHeight - (inputHeight * multiple)) / 2);\n            const output = new BitMatrix(outputWidth, outputHeight);\n            for (let inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {\n                // Write the contents of this row of the barcode\n                for (let inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {\n                    if (input.get(inputX, inputY) === 1) {\n                        output.setRegion(outputX, outputY, multiple, multiple);\n                    }\n                }\n            }\n            return output;\n        }\n    }\n    QRCodeWriter.QUIET_ZONE_SIZE = 4;\n\n    /*import java.util.Map;*/\n    /**\n     * This is a factory class which finds the appropriate Writer subclass for the BarcodeFormat\n     * requested and encodes the barcode with the supplied contents.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class MultiFormatWriter {\n        /*@Override*/\n        // public encode(contents: string,\n        //                         format: BarcodeFormat,\n        //                         width: number /*int*/,\n        //                         height: number /*int*/): BitMatrix /*throws WriterException */ {\n        //   return encode(contents, format, width, height, null)\n        // }\n        /*@Override*/\n        encode(contents, format, width /*int*/, height /*int*/, hints) {\n            let writer;\n            switch (format) {\n                // case BarcodeFormat.EAN_8:\n                //   writer = new EAN8Writer()\n                //   break\n                // case BarcodeFormat.UPC_E:\n                //   writer = new UPCEWriter()\n                //   break\n                // case BarcodeFormat.EAN_13:\n                //   writer = new EAN13Writer()\n                //   break\n                // case BarcodeFormat.UPC_A:\n                //   writer = new UPCAWriter()\n                //   break\n                case BarcodeFormat$1.QR_CODE:\n                    writer = new QRCodeWriter();\n                    break;\n                // case BarcodeFormat.CODE_39:\n                //   writer = new Code39Writer()\n                //   break\n                // case BarcodeFormat.CODE_93:\n                //   writer = new Code93Writer()\n                //   break\n                // case BarcodeFormat.CODE_128:\n                //   writer = new Code128Writer()\n                //   break\n                // case BarcodeFormat.ITF:\n                //   writer = new ITFWriter()\n                //   break\n                // case BarcodeFormat.PDF_417:\n                //   writer = new PDF417Writer()\n                //   break\n                // case BarcodeFormat.CODABAR:\n                //   writer = new CodaBarWriter()\n                //   break\n                // case BarcodeFormat.DATA_MATRIX:\n                //   writer = new DataMatrixWriter()\n                //   break\n                // case BarcodeFormat.AZTEC:\n                //   writer = new AztecWriter()\n                //   break\n                default:\n                    throw new IllegalArgumentException('No encoder available for format ' + format);\n            }\n            return writer.encode(contents, format, width, height, hints);\n        }\n    }\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * This object extends LuminanceSource around an array of YUV data returned from the camera driver,\n     * with the option to crop to a rectangle within the full data. This can be used to exclude\n     * superfluous pixels around the perimeter and speed up decoding.\n     *\n     * It works for any pixel format where the Y channel is planar and appears first, including\n     * YCbCr_420_SP and YCbCr_422_SP.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     */\n    class PlanarYUVLuminanceSource extends LuminanceSource {\n        constructor(yuvData, dataWidth /*int*/, dataHeight /*int*/, left /*int*/, top /*int*/, width /*int*/, height /*int*/, reverseHorizontal) {\n            super(width, height);\n            this.yuvData = yuvData;\n            this.dataWidth = dataWidth;\n            this.dataHeight = dataHeight;\n            this.left = left;\n            this.top = top;\n            if (left + width > dataWidth || top + height > dataHeight) {\n                throw new IllegalArgumentException('Crop rectangle does not fit within image data.');\n            }\n            if (reverseHorizontal) {\n                this.reverseHorizontal(width, height);\n            }\n        }\n        /*@Override*/\n        getRow(y /*int*/, row) {\n            if (y < 0 || y >= this.getHeight()) {\n                throw new IllegalArgumentException('Requested row is outside the image: ' + y);\n            }\n            const width = this.getWidth();\n            if (row === null || row === undefined || row.length < width) {\n                row = new Uint8ClampedArray(width);\n            }\n            const offset = (y + this.top) * this.dataWidth + this.left;\n            System.arraycopy(this.yuvData, offset, row, 0, width);\n            return row;\n        }\n        /*@Override*/\n        getMatrix() {\n            const width = this.getWidth();\n            const height = this.getHeight();\n            // If the caller asks for the entire underlying image, save the copy and give them the\n            // original data. The docs specifically warn that result.length must be ignored.\n            if (width === this.dataWidth && height === this.dataHeight) {\n                return this.yuvData;\n            }\n            const area = width * height;\n            const matrix = new Uint8ClampedArray(area);\n            let inputOffset = this.top * this.dataWidth + this.left;\n            // If the width matches the full width of the underlying data, perform a single copy.\n            if (width === this.dataWidth) {\n                System.arraycopy(this.yuvData, inputOffset, matrix, 0, area);\n                return matrix;\n            }\n            // Otherwise copy one cropped row at a time.\n            for (let y = 0; y < height; y++) {\n                const outputOffset = y * width;\n                System.arraycopy(this.yuvData, inputOffset, matrix, outputOffset, width);\n                inputOffset += this.dataWidth;\n            }\n            return matrix;\n        }\n        /*@Override*/\n        isCropSupported() {\n            return true;\n        }\n        /*@Override*/\n        crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n            return new PlanarYUVLuminanceSource(this.yuvData, this.dataWidth, this.dataHeight, this.left + left, this.top + top, width, height, false);\n        }\n        renderThumbnail() {\n            const width = this.getWidth() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n            const height = this.getHeight() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n            const pixels = new Int32Array(width * height);\n            const yuv = this.yuvData;\n            let inputOffset = this.top * this.dataWidth + this.left;\n            for (let y = 0; y < height; y++) {\n                const outputOffset = y * width;\n                for (let x = 0; x < width; x++) {\n                    const grey = yuv[inputOffset + x * PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR] & 0xff;\n                    pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101);\n                }\n                inputOffset += this.dataWidth * PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n            }\n            return pixels;\n        }\n        /**\n         * @return width of image from {@link #renderThumbnail()}\n         */\n        getThumbnailWidth() {\n            return this.getWidth() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n        }\n        /**\n         * @return height of image from {@link #renderThumbnail()}\n         */\n        getThumbnailHeight() {\n            return this.getHeight() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n        }\n        reverseHorizontal(width /*int*/, height /*int*/) {\n            const yuvData = this.yuvData;\n            for (let y = 0, rowStart = this.top * this.dataWidth + this.left; y < height; y++, rowStart += this.dataWidth) {\n                const middle = rowStart + width / 2;\n                for (let x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) {\n                    const temp = yuvData[x1];\n                    yuvData[x1] = yuvData[x2];\n                    yuvData[x2] = temp;\n                }\n            }\n        }\n        invert() {\n            return new InvertedLuminanceSource(this);\n        }\n    }\n    PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR = 2;\n\n    /*\n     * Copyright 2009 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * This class is used to help decode images from files which arrive as RGB data from\n     * an ARGB pixel array. It does not support rotation.\n     *\n     * @author dswitkin@google.com (Daniel Switkin)\n     * @author Betaminos\n     */\n    class RGBLuminanceSource extends LuminanceSource {\n        constructor(luminances, width /*int*/, height /*int*/, dataWidth /*int*/, dataHeight /*int*/, left /*int*/, top /*int*/) {\n            super(width, height);\n            this.dataWidth = dataWidth;\n            this.dataHeight = dataHeight;\n            this.left = left;\n            this.top = top;\n            if (luminances.BYTES_PER_ELEMENT === 4) { // Int32Array\n                const size = width * height;\n                const luminancesUint8Array = new Uint8ClampedArray(size);\n                for (let offset = 0; offset < size; offset++) {\n                    const pixel = luminances[offset];\n                    const r = (pixel >> 16) & 0xff; // red\n                    const g2 = (pixel >> 7) & 0x1fe; // 2 * green\n                    const b = pixel & 0xff; // blue\n                    // Calculate green-favouring average cheaply\n                    luminancesUint8Array[offset] = /*(byte) */ ((r + g2 + b) / 4) & 0xFF;\n                }\n                this.luminances = luminancesUint8Array;\n            }\n            else {\n                this.luminances = luminances;\n            }\n            if (undefined === dataWidth) {\n                this.dataWidth = width;\n            }\n            if (undefined === dataHeight) {\n                this.dataHeight = height;\n            }\n            if (undefined === left) {\n                this.left = 0;\n            }\n            if (undefined === top) {\n                this.top = 0;\n            }\n            if (this.left + width > this.dataWidth || this.top + height > this.dataHeight) {\n                throw new IllegalArgumentException('Crop rectangle does not fit within image data.');\n            }\n        }\n        /*@Override*/\n        getRow(y /*int*/, row) {\n            if (y < 0 || y >= this.getHeight()) {\n                throw new IllegalArgumentException('Requested row is outside the image: ' + y);\n            }\n            const width = this.getWidth();\n            if (row === null || row === undefined || row.length < width) {\n                row = new Uint8ClampedArray(width);\n            }\n            const offset = (y + this.top) * this.dataWidth + this.left;\n            System.arraycopy(this.luminances, offset, row, 0, width);\n            return row;\n        }\n        /*@Override*/\n        getMatrix() {\n            const width = this.getWidth();\n            const height = this.getHeight();\n            // If the caller asks for the entire underlying image, save the copy and give them the\n            // original data. The docs specifically warn that result.length must be ignored.\n            if (width === this.dataWidth && height === this.dataHeight) {\n                return this.luminances;\n            }\n            const area = width * height;\n            const matrix = new Uint8ClampedArray(area);\n            let inputOffset = this.top * this.dataWidth + this.left;\n            // If the width matches the full width of the underlying data, perform a single copy.\n            if (width === this.dataWidth) {\n                System.arraycopy(this.luminances, inputOffset, matrix, 0, area);\n                return matrix;\n            }\n            // Otherwise copy one cropped row at a time.\n            for (let y = 0; y < height; y++) {\n                const outputOffset = y * width;\n                System.arraycopy(this.luminances, inputOffset, matrix, outputOffset, width);\n                inputOffset += this.dataWidth;\n            }\n            return matrix;\n        }\n        /*@Override*/\n        isCropSupported() {\n            return true;\n        }\n        /*@Override*/\n        crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n            return new RGBLuminanceSource(this.luminances, width, height, this.dataWidth, this.dataHeight, this.left + left, this.top + top);\n        }\n        invert() {\n            return new InvertedLuminanceSource(this);\n        }\n    }\n\n    /**\n     * Just to make a shortcut between Java code and TS code.\n     */\n    class Charset extends CharacterSetECI {\n        static forName(name) {\n            return this.getCharacterSetECIByName(name);\n        }\n    }\n\n    /**\n     * Just to make a shortcut between Java code and TS code.\n     */\n    class StandardCharsets {\n    }\n    StandardCharsets.ISO_8859_1 = CharacterSetECI.ISO8859_1;\n\n    /*\n    * Copyright 2013 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /**\n     * Aztec 2D code representation\n     *\n     * @author Rustam Abdullaev\n     */\n    /*public final*/ class AztecCode {\n        /**\n         * @return {@code true} if compact instead of full mode\n         */\n        isCompact() {\n            return this.compact;\n        }\n        setCompact(compact) {\n            this.compact = compact;\n        }\n        /**\n         * @return size in pixels (width and height)\n         */\n        getSize() {\n            return this.size;\n        }\n        setSize(size) {\n            this.size = size;\n        }\n        /**\n         * @return number of levels\n         */\n        getLayers() {\n            return this.layers;\n        }\n        setLayers(layers) {\n            this.layers = layers;\n        }\n        /**\n         * @return number of data codewords\n         */\n        getCodeWords() {\n            return this.codeWords;\n        }\n        setCodeWords(codeWords) {\n            this.codeWords = codeWords;\n        }\n        /**\n         * @return the symbol image\n         */\n        getMatrix() {\n            return this.matrix;\n        }\n        setMatrix(matrix) {\n            this.matrix = matrix;\n        }\n    }\n\n    class Collections {\n        /**\n         * The singletonList(T) method is used to return an immutable list containing only the specified object.\n         */\n        static singletonList(item) {\n            return [item];\n        }\n        /**\n         * The min(Collection<? extends T>, Comparator<? super T>) method is used to return the minimum element of the given collection, according to the order induced by the specified comparator.\n         */\n        static min(collection, comparator) {\n            return collection.sort(comparator)[0];\n        }\n    }\n\n    /*\n    * Copyright 2013 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    class Token {\n        constructor(previous) {\n            this.previous = previous;\n        }\n        getPrevious() {\n            return this.previous;\n        }\n    }\n\n    /*\n    * Copyright 2013 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /*final*/ class SimpleToken extends Token {\n        constructor(previous, value, bitCount) {\n            super(previous);\n            this.value = value;\n            this.bitCount = bitCount;\n        }\n        /**\n         * @Override\n         */\n        appendTo(bitArray, text) {\n            bitArray.appendBits(this.value, this.bitCount);\n        }\n        add(value, bitCount) {\n            return new SimpleToken(this, value, bitCount);\n        }\n        addBinaryShift(start, byteCount) {\n            // no-op can't binary shift a simple token\n            console.warn('addBinaryShift on SimpleToken, this simply returns a copy of this token');\n            return new SimpleToken(this, start, byteCount);\n        }\n        /**\n         * @Override\n         */\n        toString() {\n            let value = this.value & ((1 << this.bitCount) - 1);\n            value |= 1 << this.bitCount;\n            return '<' + Integer.toBinaryString(value | (1 << this.bitCount)).substring(1) + '>';\n        }\n    }\n\n    /*\n    * Copyright 2013 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /*final*/ class BinaryShiftToken extends SimpleToken {\n        constructor(previous, binaryShiftStart, binaryShiftByteCount) {\n            super(previous, 0, 0);\n            this.binaryShiftStart = binaryShiftStart;\n            this.binaryShiftByteCount = binaryShiftByteCount;\n        }\n        /**\n         * @Override\n         */\n        appendTo(bitArray, text) {\n            for (let i = 0; i < this.binaryShiftByteCount; i++) {\n                if (i === 0 || (i === 31 && this.binaryShiftByteCount <= 62)) {\n                    // We need a header before the first character, and before\n                    // character 31 when the total byte code is <= 62\n                    bitArray.appendBits(31, 5); // BINARY_SHIFT\n                    if (this.binaryShiftByteCount > 62) {\n                        bitArray.appendBits(this.binaryShiftByteCount - 31, 16);\n                    }\n                    else if (i === 0) {\n                        // 1 <= binaryShiftByteCode <= 62\n                        bitArray.appendBits(Math.min(this.binaryShiftByteCount, 31), 5);\n                    }\n                    else {\n                        // 32 <= binaryShiftCount <= 62 and i == 31\n                        bitArray.appendBits(this.binaryShiftByteCount - 31, 5);\n                    }\n                }\n                bitArray.appendBits(text[this.binaryShiftStart + i], 8);\n            }\n        }\n        addBinaryShift(start, byteCount) {\n            // int bitCount = (byteCount * 8) + (byteCount <= 31 ? 10 : byteCount <= 62 ? 20 : 21);\n            return new BinaryShiftToken(this, start, byteCount);\n        }\n        /**\n         * @Override\n         */\n        toString() {\n            return '<' + this.binaryShiftStart + '::' + (this.binaryShiftStart + this.binaryShiftByteCount - 1) + '>';\n        }\n    }\n\n    function addBinaryShift(token, start, byteCount) {\n        // int bitCount = (byteCount * 8) + (byteCount <= 31 ? 10 : byteCount <= 62 ? 20 : 21);\n        return new BinaryShiftToken(token, start, byteCount);\n    }\n    function add(token, value, bitCount) {\n        return new SimpleToken(token, value, bitCount);\n    }\n\n    const /*final*/ MODE_NAMES = [\n        'UPPER',\n        'LOWER',\n        'DIGIT',\n        'MIXED',\n        'PUNCT'\n    ];\n    const /*final*/ MODE_UPPER = 0; // 5 bits\n    const /*final*/ MODE_LOWER = 1; // 5 bits\n    const /*final*/ MODE_DIGIT = 2; // 4 bits\n    const /*final*/ MODE_MIXED = 3; // 5 bits\n    const /*final*/ MODE_PUNCT = 4; // 5 bits\n    const EMPTY_TOKEN = new SimpleToken(null, 0, 0);\n\n    // The Latch Table shows, for each pair of Modes, the optimal method for\n    // getting from one mode to another.  In the worst possible case, this can\n    // be up to 14 bits.  In the best possible case, we are already there!\n    // The high half-word of each entry gives the number of bits.\n    // The low half-word of each entry are the actual bits necessary to change\n    const LATCH_TABLE = [\n        Int32Array.from([\n            0,\n            (5 << 16) + 28,\n            (5 << 16) + 30,\n            (5 << 16) + 29,\n            (10 << 16) + (29 << 5) + 30 // UPPER -> MIXED -> PUNCT\n        ]),\n        Int32Array.from([\n            (9 << 16) + (30 << 4) + 14,\n            0,\n            (5 << 16) + 30,\n            (5 << 16) + 29,\n            (10 << 16) + (29 << 5) + 30 // LOWER -> MIXED -> PUNCT\n        ]),\n        Int32Array.from([\n            (4 << 16) + 14,\n            (9 << 16) + (14 << 5) + 28,\n            0,\n            (9 << 16) + (14 << 5) + 29,\n            (14 << 16) + (14 << 10) + (29 << 5) + 30\n            // DIGIT -> UPPER -> MIXED -> PUNCT\n        ]),\n        Int32Array.from([\n            (5 << 16) + 29,\n            (5 << 16) + 28,\n            (10 << 16) + (29 << 5) + 30,\n            0,\n            (5 << 16) + 30 // MIXED -> PUNCT\n        ]),\n        Int32Array.from([\n            (5 << 16) + 31,\n            (10 << 16) + (31 << 5) + 28,\n            (10 << 16) + (31 << 5) + 30,\n            (10 << 16) + (31 << 5) + 29,\n            0\n        ])\n    ];\n\n    function static_SHIFT_TABLE(SHIFT_TABLE) {\n        for (let table /*Int32Array*/ of SHIFT_TABLE) {\n            Arrays.fill(table, -1);\n        }\n        SHIFT_TABLE[MODE_UPPER][MODE_PUNCT] = 0;\n        SHIFT_TABLE[MODE_LOWER][MODE_PUNCT] = 0;\n        SHIFT_TABLE[MODE_LOWER][MODE_UPPER] = 28;\n        SHIFT_TABLE[MODE_MIXED][MODE_PUNCT] = 0;\n        SHIFT_TABLE[MODE_DIGIT][MODE_PUNCT] = 0;\n        SHIFT_TABLE[MODE_DIGIT][MODE_UPPER] = 15;\n        return SHIFT_TABLE;\n    }\n    const /*final*/ SHIFT_TABLE = static_SHIFT_TABLE(Arrays.createInt32Array(6, 6)); // mode shift codes, per table\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * State represents all information about a sequence necessary to generate the current output.\n     * Note that a state is immutable.\n     */\n    /*final*/ class State {\n        constructor(token, mode, binaryBytes, bitCount) {\n            this.token = token;\n            this.mode = mode;\n            this.binaryShiftByteCount = binaryBytes;\n            this.bitCount = bitCount;\n            // Make sure we match the token\n            // int binaryShiftBitCount = (binaryShiftByteCount * 8) +\n            //    (binaryShiftByteCount === 0 ? 0 :\n            //     binaryShiftByteCount <= 31 ? 10 :\n            //     binaryShiftByteCount <= 62 ? 20 : 21);\n            // assert this.bitCount === token.getTotalBitCount() + binaryShiftBitCount;\n        }\n        getMode() {\n            return this.mode;\n        }\n        getToken() {\n            return this.token;\n        }\n        getBinaryShiftByteCount() {\n            return this.binaryShiftByteCount;\n        }\n        getBitCount() {\n            return this.bitCount;\n        }\n        // Create a new state representing this state with a latch to a (not\n        // necessary different) mode, and then a code.\n        latchAndAppend(mode, value) {\n            // assert binaryShiftByteCount === 0;\n            let bitCount = this.bitCount;\n            let token = this.token;\n            if (mode !== this.mode) {\n                let latch = LATCH_TABLE[this.mode][mode];\n                token = add(token, latch & 0xffff, latch >> 16);\n                bitCount += latch >> 16;\n            }\n            let latchModeBitCount = mode === MODE_DIGIT ? 4 : 5;\n            token = add(token, value, latchModeBitCount);\n            return new State(token, mode, 0, bitCount + latchModeBitCount);\n        }\n        // Create a new state representing this state, with a temporary shift\n        // to a different mode to output a single value.\n        shiftAndAppend(mode, value) {\n            // assert binaryShiftByteCount === 0 && this.mode !== mode;\n            let token = this.token;\n            let thisModeBitCount = this.mode === MODE_DIGIT ? 4 : 5;\n            // Shifts exist only to UPPER and PUNCT, both with tokens size 5.\n            token = add(token, SHIFT_TABLE[this.mode][mode], thisModeBitCount);\n            token = add(token, value, 5);\n            return new State(token, this.mode, 0, this.bitCount + thisModeBitCount + 5);\n        }\n        // Create a new state representing this state, but an additional character\n        // output in Binary Shift mode.\n        addBinaryShiftChar(index) {\n            let token = this.token;\n            let mode = this.mode;\n            let bitCount = this.bitCount;\n            if (this.mode === MODE_PUNCT || this.mode === MODE_DIGIT) {\n                // assert binaryShiftByteCount === 0;\n                let latch = LATCH_TABLE[mode][MODE_UPPER];\n                token = add(token, latch & 0xffff, latch >> 16);\n                bitCount += latch >> 16;\n                mode = MODE_UPPER;\n            }\n            let deltaBitCount = this.binaryShiftByteCount === 0 || this.binaryShiftByteCount === 31\n                ? 18\n                : this.binaryShiftByteCount === 62\n                    ? 9\n                    : 8;\n            let result = new State(token, mode, this.binaryShiftByteCount + 1, bitCount + deltaBitCount);\n            if (result.binaryShiftByteCount === 2047 + 31) {\n                // The string is as long as it's allowed to be.  We should end it.\n                result = result.endBinaryShift(index + 1);\n            }\n            return result;\n        }\n        // Create the state identical to this one, but we are no longer in\n        // Binary Shift mode.\n        endBinaryShift(index) {\n            if (this.binaryShiftByteCount === 0) {\n                return this;\n            }\n            let token = this.token;\n            token = addBinaryShift(token, index - this.binaryShiftByteCount, this.binaryShiftByteCount);\n            // assert token.getTotalBitCount() === this.bitCount;\n            return new State(token, this.mode, 0, this.bitCount);\n        }\n        // Returns true if \"this\" state is better (equal: or) to be in than \"that\"\n        // state under all possible circumstances.\n        isBetterThanOrEqualTo(other) {\n            let newModeBitCount = this.bitCount + (LATCH_TABLE[this.mode][other.mode] >> 16);\n            if (this.binaryShiftByteCount < other.binaryShiftByteCount) {\n                // add additional B/S encoding cost of other, if any\n                newModeBitCount +=\n                    State.calculateBinaryShiftCost(other) -\n                        State.calculateBinaryShiftCost(this);\n            }\n            else if (this.binaryShiftByteCount > other.binaryShiftByteCount &&\n                other.binaryShiftByteCount > 0) {\n                // maximum possible additional cost (it: h)\n                newModeBitCount += 10;\n            }\n            return newModeBitCount <= other.bitCount;\n        }\n        toBitArray(text) {\n            // Reverse the tokens, so that they are in the order that they should\n            // be output\n            let symbols = [];\n            for (let token = this.endBinaryShift(text.length).token; token !== null; token = token.getPrevious()) {\n                symbols.unshift(token);\n            }\n            let bitArray = new BitArray();\n            // Add each token to the result.\n            for (const symbol of symbols) {\n                symbol.appendTo(bitArray, text);\n            }\n            // assert bitArray.getSize() === this.bitCount;\n            return bitArray;\n        }\n        /**\n         * @Override\n         */\n        toString() {\n            return StringUtils.format('%s bits=%d bytes=%d', MODE_NAMES[this.mode], this.bitCount, this.binaryShiftByteCount);\n        }\n        static calculateBinaryShiftCost(state) {\n            if (state.binaryShiftByteCount > 62) {\n                return 21; // B/S with extended length\n            }\n            if (state.binaryShiftByteCount > 31) {\n                return 20; // two B/S\n            }\n            if (state.binaryShiftByteCount > 0) {\n                return 10; // one B/S\n            }\n            return 0;\n        }\n    }\n    State.INITIAL_STATE = new State(EMPTY_TOKEN, MODE_UPPER, 0, 0);\n\n    function static_CHAR_MAP(CHAR_MAP) {\n        const spaceCharCode = StringUtils.getCharCode(' ');\n        const pointCharCode = StringUtils.getCharCode('.');\n        const commaCharCode = StringUtils.getCharCode(',');\n        CHAR_MAP[MODE_UPPER][spaceCharCode] = 1;\n        const zUpperCharCode = StringUtils.getCharCode('Z');\n        const aUpperCharCode = StringUtils.getCharCode('A');\n        for (let c = aUpperCharCode; c <= zUpperCharCode; c++) {\n            CHAR_MAP[MODE_UPPER][c] = c - aUpperCharCode + 2;\n        }\n        CHAR_MAP[MODE_LOWER][spaceCharCode] = 1;\n        const zLowerCharCode = StringUtils.getCharCode('z');\n        const aLowerCharCode = StringUtils.getCharCode('a');\n        for (let c = aLowerCharCode; c <= zLowerCharCode; c++) {\n            CHAR_MAP[MODE_LOWER][c] = c - aLowerCharCode + 2;\n        }\n        CHAR_MAP[MODE_DIGIT][spaceCharCode] = 1;\n        const nineCharCode = StringUtils.getCharCode('9');\n        const zeroCharCode = StringUtils.getCharCode('0');\n        for (let c = zeroCharCode; c <= nineCharCode; c++) {\n            CHAR_MAP[MODE_DIGIT][c] = c - zeroCharCode + 2;\n        }\n        CHAR_MAP[MODE_DIGIT][commaCharCode] = 12;\n        CHAR_MAP[MODE_DIGIT][pointCharCode] = 13;\n        const mixedTable = [\n            '\\x00',\n            ' ',\n            '\\x01',\n            '\\x02',\n            '\\x03',\n            '\\x04',\n            '\\x05',\n            '\\x06',\n            '\\x07',\n            '\\b',\n            '\\t',\n            '\\n',\n            '\\x0b',\n            '\\f',\n            '\\r',\n            '\\x1b',\n            '\\x1c',\n            '\\x1d',\n            '\\x1e',\n            '\\x1f',\n            '@',\n            '\\\\',\n            '^',\n            '_',\n            '`',\n            '|',\n            '~',\n            '\\x7f'\n        ];\n        for (let i = 0; i < mixedTable.length; i++) {\n            CHAR_MAP[MODE_MIXED][StringUtils.getCharCode(mixedTable[i])] = i;\n        }\n        const punctTable = [\n            '\\x00',\n            '\\r',\n            '\\x00',\n            '\\x00',\n            '\\x00',\n            '\\x00',\n            '!',\n            '\\'',\n            '#',\n            '$',\n            '%',\n            '&',\n            '\\'',\n            '(',\n            ')',\n            '*',\n            '+',\n            ',',\n            '-',\n            '.',\n            '/',\n            ':',\n            ';',\n            '<',\n            '=',\n            '>',\n            '?',\n            '[',\n            ']',\n            '{',\n            '}'\n        ];\n        for (let i = 0; i < punctTable.length; i++) {\n            if (StringUtils.getCharCode(punctTable[i]) > 0) {\n                CHAR_MAP[MODE_PUNCT][StringUtils.getCharCode(punctTable[i])] = i;\n            }\n        }\n        return CHAR_MAP;\n    }\n    const CHAR_MAP = static_CHAR_MAP(Arrays.createInt32Array(5, 256));\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    /**\n     * This produces nearly optimal encodings of text into the first-level of\n     * encoding used by Aztec code.\n     *\n     * It uses a dynamic algorithm.  For each prefix of the string, it determines\n     * a set of encodings that could lead to this prefix.  We repeatedly add a\n     * character and generate a new set of optimal encodings until we have read\n     * through the entire input.\n     *\n     * @author Frank Yellin\n     * @author Rustam Abdullaev\n     */\n    /*public final*/ class HighLevelEncoder {\n        constructor(text) {\n            this.text = text;\n        }\n        /**\n         * @return text represented by this encoder encoded as a {@link BitArray}\n         */\n        encode() {\n            const spaceCharCode = StringUtils.getCharCode(' ');\n            const lineBreakCharCode = StringUtils.getCharCode('\\n');\n            let states = Collections.singletonList(State.INITIAL_STATE);\n            for (let index = 0; index < this.text.length; index++) {\n                let pairCode;\n                let nextChar = index + 1 < this.text.length ? this.text[index + 1] : 0;\n                switch (this.text[index]) {\n                    case StringUtils.getCharCode('\\r'):\n                        pairCode = nextChar === lineBreakCharCode ? 2 : 0;\n                        break;\n                    case StringUtils.getCharCode('.'):\n                        pairCode = nextChar === spaceCharCode ? 3 : 0;\n                        break;\n                    case StringUtils.getCharCode(','):\n                        pairCode = nextChar === spaceCharCode ? 4 : 0;\n                        break;\n                    case StringUtils.getCharCode(':'):\n                        pairCode = nextChar === spaceCharCode ? 5 : 0;\n                        break;\n                    default:\n                        pairCode = 0;\n                }\n                if (pairCode > 0) {\n                    // We have one of the four special PUNCT pairs.  Treat them specially.\n                    // Get a new set of states for the two new characters.\n                    states = HighLevelEncoder.updateStateListForPair(states, index, pairCode);\n                    index++;\n                }\n                else {\n                    // Get a new set of states for the new character.\n                    states = this.updateStateListForChar(states, index);\n                }\n            }\n            // We are left with a set of states.  Find the shortest one.\n            const minState = Collections.min(states, (a, b) => {\n                return a.getBitCount() - b.getBitCount();\n            });\n            // Convert it to a bit array, and return.\n            return minState.toBitArray(this.text);\n        }\n        // We update a set of states for a new character by updating each state\n        // for the new character, merging the results, and then removing the\n        // non-optimal states.\n        updateStateListForChar(states, index) {\n            const result = [];\n            for (let state /*State*/ of states) {\n                this.updateStateForChar(state, index, result);\n            }\n            return HighLevelEncoder.simplifyStates(result);\n        }\n        // Return a set of states that represent the possible ways of updating this\n        // state for the next character.  The resulting set of states are added to\n        // the \"result\" list.\n        updateStateForChar(state, index, result) {\n            let ch = (this.text[index] & 0xff);\n            let charInCurrentTable = CHAR_MAP[state.getMode()][ch] > 0;\n            let stateNoBinary = null;\n            for (let mode /*int*/ = 0; mode <= MODE_PUNCT; mode++) {\n                let charInMode = CHAR_MAP[mode][ch];\n                if (charInMode > 0) {\n                    if (stateNoBinary == null) {\n                        // Only create stateNoBinary the first time it's required.\n                        stateNoBinary = state.endBinaryShift(index);\n                    }\n                    // Try generating the character by latching to its mode\n                    if (!charInCurrentTable ||\n                        mode === state.getMode() ||\n                        mode === MODE_DIGIT) {\n                        // If the character is in the current table, we don't want to latch to\n                        // any other mode except possibly digit (which uses only 4 bits).  Any\n                        // other latch would be equally successful *after* this character, and\n                        // so wouldn't save any bits.\n                        const latchState = stateNoBinary.latchAndAppend(mode, charInMode);\n                        result.push(latchState);\n                    }\n                    // Try generating the character by switching to its mode.\n                    if (!charInCurrentTable &&\n                        SHIFT_TABLE[state.getMode()][mode] >= 0) {\n                        // It never makes sense to temporarily shift to another mode if the\n                        // character exists in the current mode.  That can never save bits.\n                        const shiftState = stateNoBinary.shiftAndAppend(mode, charInMode);\n                        result.push(shiftState);\n                    }\n                }\n            }\n            if (state.getBinaryShiftByteCount() > 0 ||\n                CHAR_MAP[state.getMode()][ch] === 0) {\n                // It's never worthwhile to go into binary shift mode if you're not already\n                // in binary shift mode, and the character exists in your current mode.\n                // That can never save bits over just outputting the char in the current mode.\n                let binaryState = state.addBinaryShiftChar(index);\n                result.push(binaryState);\n            }\n        }\n        static updateStateListForPair(states, index, pairCode) {\n            const result = [];\n            for (let state /*State*/ of states) {\n                this.updateStateForPair(state, index, pairCode, result);\n            }\n            return this.simplifyStates(result);\n        }\n        static updateStateForPair(state, index, pairCode, result) {\n            let stateNoBinary = state.endBinaryShift(index);\n            // Possibility 1.  Latch to C.MODE_PUNCT, and then append this code\n            result.push(stateNoBinary.latchAndAppend(MODE_PUNCT, pairCode));\n            if (state.getMode() !== MODE_PUNCT) {\n                // Possibility 2.  Shift to C.MODE_PUNCT, and then append this code.\n                // Every state except C.MODE_PUNCT (handled above) can shift\n                result.push(stateNoBinary.shiftAndAppend(MODE_PUNCT, pairCode));\n            }\n            if (pairCode === 3 || pairCode === 4) {\n                // both characters are in DIGITS.  Sometimes better to just add two digits\n                let digitState = stateNoBinary\n                    .latchAndAppend(MODE_DIGIT, 16 - pairCode) // period or comma in DIGIT\n                    .latchAndAppend(MODE_DIGIT, 1); // space in DIGIT\n                result.push(digitState);\n            }\n            if (state.getBinaryShiftByteCount() > 0) {\n                // It only makes sense to do the characters as binary if we're already\n                // in binary mode.\n                let binaryState = state\n                    .addBinaryShiftChar(index)\n                    .addBinaryShiftChar(index + 1);\n                result.push(binaryState);\n            }\n        }\n        static simplifyStates(states) {\n            let result = [];\n            for (const newState of states) {\n                let add = true;\n                for (const oldState of result) {\n                    if (oldState.isBetterThanOrEqualTo(newState)) {\n                        add = false;\n                        break;\n                    }\n                    if (newState.isBetterThanOrEqualTo(oldState)) {\n                        // iterator.remove();\n                        result = result.filter(x => x !== oldState); // remove old state\n                    }\n                }\n                if (add) {\n                    result.push(newState);\n                }\n            }\n            return result;\n        }\n    }\n\n    /*\n     * Copyright 2013 ZXing authors\n     *\n     * Licensed under the Apache License, Version 2.0 (the \"License\");\n     * you may not use this file except in compliance with the License.\n     * You may obtain a copy of the License at\n     *\n     *      http://www.apache.org/licenses/LICENSE-2.0\n     *\n     * Unless required by applicable law or agreed to in writing, software\n     * distributed under the License is distributed on an \"AS IS\" BASIS,\n     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     * See the License for the specific language governing permissions and\n     * limitations under the License.\n     */\n    // package com.google.zxing.aztec.encoder;\n    // import com.google.zxing.common.BitArray;\n    // import com.google.zxing.common.BitMatrix;\n    // import com.google.zxing.common.reedsolomon.GenericGF;\n    // import com.google.zxing.common.reedsolomon.ReedSolomonEncoder;\n    /**\n     * Generates Aztec 2D barcodes.\n     *\n     * @author Rustam Abdullaev\n     */\n    /*public final*/ class Encoder$1 {\n        constructor() {\n        }\n        /**\n         * Encodes the given binary content as an Aztec symbol\n         *\n         * @param data input data string\n         * @return Aztec symbol matrix with metadata\n         */\n        static encodeBytes(data) {\n            return Encoder$1.encode(data, Encoder$1.DEFAULT_EC_PERCENT, Encoder$1.DEFAULT_AZTEC_LAYERS);\n        }\n        /**\n         * Encodes the given binary content as an Aztec symbol\n         *\n         * @param data input data string\n         * @param minECCPercent minimal percentage of error check words (According to ISO/IEC 24778:2008,\n         *                      a minimum of 23% + 3 words is recommended)\n         * @param userSpecifiedLayers if non-zero, a user-specified value for the number of layers\n         * @return Aztec symbol matrix with metadata\n         */\n        static encode(data, minECCPercent, userSpecifiedLayers) {\n            // High-level encode\n            let bits = new HighLevelEncoder(data).encode();\n            // stuff bits and choose symbol size\n            let eccBits = Integer.truncDivision((bits.getSize() * minECCPercent), 100) + 11;\n            let totalSizeBits = bits.getSize() + eccBits;\n            let compact;\n            let layers;\n            let totalBitsInLayer;\n            let wordSize;\n            let stuffedBits;\n            if (userSpecifiedLayers !== Encoder$1.DEFAULT_AZTEC_LAYERS) {\n                compact = userSpecifiedLayers < 0;\n                layers = Math.abs(userSpecifiedLayers);\n                if (layers > (compact ? Encoder$1.MAX_NB_BITS_COMPACT : Encoder$1.MAX_NB_BITS)) {\n                    throw new IllegalArgumentException(StringUtils.format('Illegal value %s for layers', userSpecifiedLayers));\n                }\n                totalBitsInLayer = Encoder$1.totalBitsInLayer(layers, compact);\n                wordSize = Encoder$1.WORD_SIZE[layers];\n                let usableBitsInLayers = totalBitsInLayer - (totalBitsInLayer % wordSize);\n                stuffedBits = Encoder$1.stuffBits(bits, wordSize);\n                if (stuffedBits.getSize() + eccBits > usableBitsInLayers) {\n                    throw new IllegalArgumentException('Data to large for user specified layer');\n                }\n                if (compact && stuffedBits.getSize() > wordSize * 64) {\n                    // Compact format only allows 64 data words, though C4 can hold more words than that\n                    throw new IllegalArgumentException('Data to large for user specified layer');\n                }\n            }\n            else {\n                wordSize = 0;\n                stuffedBits = null;\n                // We look at the possible table sizes in the order Compact1, Compact2, Compact3,\n                // Compact4, Normal4,...  Normal(i) for i < 4 isn't typically used since Compact(i+1)\n                // is the same size, but has more data.\n                for (let i /*int*/ = 0;; i++) {\n                    if (i > Encoder$1.MAX_NB_BITS) {\n                        throw new IllegalArgumentException('Data too large for an Aztec code');\n                    }\n                    compact = i <= 3;\n                    layers = compact ? i + 1 : i;\n                    totalBitsInLayer = Encoder$1.totalBitsInLayer(layers, compact);\n                    if (totalSizeBits > totalBitsInLayer) {\n                        continue;\n                    }\n                    // [Re]stuff the bits if this is the first opportunity, or if the\n                    // wordSize has changed\n                    if (stuffedBits == null || wordSize !== Encoder$1.WORD_SIZE[layers]) {\n                        wordSize = Encoder$1.WORD_SIZE[layers];\n                        stuffedBits = Encoder$1.stuffBits(bits, wordSize);\n                    }\n                    let usableBitsInLayers = totalBitsInLayer - (totalBitsInLayer % wordSize);\n                    if (compact && stuffedBits.getSize() > wordSize * 64) {\n                        // Compact format only allows 64 data words, though C4 can hold more words than that\n                        continue;\n                    }\n                    if (stuffedBits.getSize() + eccBits <= usableBitsInLayers) {\n                        break;\n                    }\n                }\n            }\n            let messageBits = Encoder$1.generateCheckWords(stuffedBits, totalBitsInLayer, wordSize);\n            // generate mode message\n            let messageSizeInWords = stuffedBits.getSize() / wordSize;\n            let modeMessage = Encoder$1.generateModeMessage(compact, layers, messageSizeInWords);\n            // allocate symbol\n            let baseMatrixSize = (compact ? 11 : 14) + layers * 4; // not including alignment lines\n            let alignmentMap = new Int32Array(baseMatrixSize);\n            let matrixSize;\n            if (compact) {\n                // no alignment marks in compact mode, alignmentMap is a no-op\n                matrixSize = baseMatrixSize;\n                for (let i /*int*/ = 0; i < alignmentMap.length; i++) {\n                    alignmentMap[i] = i;\n                }\n            }\n            else {\n                matrixSize = baseMatrixSize + 1 + 2 * Integer.truncDivision((Integer.truncDivision(baseMatrixSize, 2) - 1), 15);\n                let origCenter = Integer.truncDivision(baseMatrixSize, 2);\n                let center = Integer.truncDivision(matrixSize, 2);\n                for (let i /*int*/ = 0; i < origCenter; i++) {\n                    let newOffset = i + Integer.truncDivision(i, 15);\n                    alignmentMap[origCenter - i - 1] = center - newOffset - 1;\n                    alignmentMap[origCenter + i] = center + newOffset + 1;\n                }\n            }\n            let matrix = new BitMatrix(matrixSize);\n            // draw data bits\n            for (let i /*int*/ = 0, rowOffset = 0; i < layers; i++) {\n                let rowSize = (layers - i) * 4 + (compact ? 9 : 12);\n                for (let j /*int*/ = 0; j < rowSize; j++) {\n                    let columnOffset = j * 2;\n                    for (let k /*int*/ = 0; k < 2; k++) {\n                        if (messageBits.get(rowOffset + columnOffset + k)) {\n                            matrix.set(alignmentMap[i * 2 + k], alignmentMap[i * 2 + j]);\n                        }\n                        if (messageBits.get(rowOffset + rowSize * 2 + columnOffset + k)) {\n                            matrix.set(alignmentMap[i * 2 + j], alignmentMap[baseMatrixSize - 1 - i * 2 - k]);\n                        }\n                        if (messageBits.get(rowOffset + rowSize * 4 + columnOffset + k)) {\n                            matrix.set(alignmentMap[baseMatrixSize - 1 - i * 2 - k], alignmentMap[baseMatrixSize - 1 - i * 2 - j]);\n                        }\n                        if (messageBits.get(rowOffset + rowSize * 6 + columnOffset + k)) {\n                            matrix.set(alignmentMap[baseMatrixSize - 1 - i * 2 - j], alignmentMap[i * 2 + k]);\n                        }\n                    }\n                }\n                rowOffset += rowSize * 8;\n            }\n            // draw mode message\n            Encoder$1.drawModeMessage(matrix, compact, matrixSize, modeMessage);\n            // draw alignment marks\n            if (compact) {\n                Encoder$1.drawBullsEye(matrix, Integer.truncDivision(matrixSize, 2), 5);\n            }\n            else {\n                Encoder$1.drawBullsEye(matrix, Integer.truncDivision(matrixSize, 2), 7);\n                for (let i /*int*/ = 0, j = 0; i < Integer.truncDivision(baseMatrixSize, 2) - 1; i += 15, j += 16) {\n                    for (let k /*int*/ = Integer.truncDivision(matrixSize, 2) & 1; k < matrixSize; k += 2) {\n                        matrix.set(Integer.truncDivision(matrixSize, 2) - j, k);\n                        matrix.set(Integer.truncDivision(matrixSize, 2) + j, k);\n                        matrix.set(k, Integer.truncDivision(matrixSize, 2) - j);\n                        matrix.set(k, Integer.truncDivision(matrixSize, 2) + j);\n                    }\n                }\n            }\n            let aztec = new AztecCode();\n            aztec.setCompact(compact);\n            aztec.setSize(matrixSize);\n            aztec.setLayers(layers);\n            aztec.setCodeWords(messageSizeInWords);\n            aztec.setMatrix(matrix);\n            return aztec;\n        }\n        static drawBullsEye(matrix, center, size) {\n            for (let i /*int*/ = 0; i < size; i += 2) {\n                for (let j /*int*/ = center - i; j <= center + i; j++) {\n                    matrix.set(j, center - i);\n                    matrix.set(j, center + i);\n                    matrix.set(center - i, j);\n                    matrix.set(center + i, j);\n                }\n            }\n            matrix.set(center - size, center - size);\n            matrix.set(center - size + 1, center - size);\n            matrix.set(center - size, center - size + 1);\n            matrix.set(center + size, center - size);\n            matrix.set(center + size, center - size + 1);\n            matrix.set(center + size, center + size - 1);\n        }\n        static generateModeMessage(compact, layers, messageSizeInWords) {\n            let modeMessage = new BitArray();\n            if (compact) {\n                modeMessage.appendBits(layers - 1, 2);\n                modeMessage.appendBits(messageSizeInWords - 1, 6);\n                modeMessage = Encoder$1.generateCheckWords(modeMessage, 28, 4);\n            }\n            else {\n                modeMessage.appendBits(layers - 1, 5);\n                modeMessage.appendBits(messageSizeInWords - 1, 11);\n                modeMessage = Encoder$1.generateCheckWords(modeMessage, 40, 4);\n            }\n            return modeMessage;\n        }\n        static drawModeMessage(matrix, compact, matrixSize, modeMessage) {\n            let center = Integer.truncDivision(matrixSize, 2);\n            if (compact) {\n                for (let i /*int*/ = 0; i < 7; i++) {\n                    let offset = center - 3 + i;\n                    if (modeMessage.get(i)) {\n                        matrix.set(offset, center - 5);\n                    }\n                    if (modeMessage.get(i + 7)) {\n                        matrix.set(center + 5, offset);\n                    }\n                    if (modeMessage.get(20 - i)) {\n                        matrix.set(offset, center + 5);\n                    }\n                    if (modeMessage.get(27 - i)) {\n                        matrix.set(center - 5, offset);\n                    }\n                }\n            }\n            else {\n                for (let i /*int*/ = 0; i < 10; i++) {\n                    let offset = center - 5 + i + Integer.truncDivision(i, 5);\n                    if (modeMessage.get(i)) {\n                        matrix.set(offset, center - 7);\n                    }\n                    if (modeMessage.get(i + 10)) {\n                        matrix.set(center + 7, offset);\n                    }\n                    if (modeMessage.get(29 - i)) {\n                        matrix.set(offset, center + 7);\n                    }\n                    if (modeMessage.get(39 - i)) {\n                        matrix.set(center - 7, offset);\n                    }\n                }\n            }\n        }\n        static generateCheckWords(bitArray, totalBits, wordSize) {\n            // bitArray is guaranteed to be a multiple of the wordSize, so no padding needed\n            let messageSizeInWords = bitArray.getSize() / wordSize;\n            let rs = new ReedSolomonEncoder(Encoder$1.getGF(wordSize));\n            let totalWords = Integer.truncDivision(totalBits, wordSize);\n            let messageWords = Encoder$1.bitsToWords(bitArray, wordSize, totalWords);\n            rs.encode(messageWords, totalWords - messageSizeInWords);\n            let startPad = totalBits % wordSize;\n            let messageBits = new BitArray();\n            messageBits.appendBits(0, startPad);\n            for (const messageWord /*: int*/ of Array.from(messageWords)) {\n                messageBits.appendBits(messageWord, wordSize);\n            }\n            return messageBits;\n        }\n        static bitsToWords(stuffedBits, wordSize, totalWords) {\n            let message = new Int32Array(totalWords);\n            let i;\n            let n;\n            for (i = 0, n = stuffedBits.getSize() / wordSize; i < n; i++) {\n                let value = 0;\n                for (let j /*int*/ = 0; j < wordSize; j++) {\n                    value |= stuffedBits.get(i * wordSize + j) ? (1 << wordSize - j - 1) : 0;\n                }\n                message[i] = value;\n            }\n            return message;\n        }\n        static getGF(wordSize) {\n            switch (wordSize) {\n                case 4:\n                    return GenericGF.AZTEC_PARAM;\n                case 6:\n                    return GenericGF.AZTEC_DATA_6;\n                case 8:\n                    return GenericGF.AZTEC_DATA_8;\n                case 10:\n                    return GenericGF.AZTEC_DATA_10;\n                case 12:\n                    return GenericGF.AZTEC_DATA_12;\n                default:\n                    throw new IllegalArgumentException('Unsupported word size ' + wordSize);\n            }\n        }\n        static stuffBits(bits, wordSize) {\n            let out = new BitArray();\n            let n = bits.getSize();\n            let mask = (1 << wordSize) - 2;\n            for (let i /*int*/ = 0; i < n; i += wordSize) {\n                let word = 0;\n                for (let j /*int*/ = 0; j < wordSize; j++) {\n                    if (i + j >= n || bits.get(i + j)) {\n                        word |= 1 << (wordSize - 1 - j);\n                    }\n                }\n                if ((word & mask) === mask) {\n                    out.appendBits(word & mask, wordSize);\n                    i--;\n                }\n                else if ((word & mask) === 0) {\n                    out.appendBits(word | 1, wordSize);\n                    i--;\n                }\n                else {\n                    out.appendBits(word, wordSize);\n                }\n            }\n            return out;\n        }\n        static totalBitsInLayer(layers, compact) {\n            return ((compact ? 88 : 112) + 16 * layers) * layers;\n        }\n    }\n    Encoder$1.DEFAULT_EC_PERCENT = 33; // default minimal percentage of error check words\n    Encoder$1.DEFAULT_AZTEC_LAYERS = 0;\n    Encoder$1.MAX_NB_BITS = 32;\n    Encoder$1.MAX_NB_BITS_COMPACT = 4;\n    Encoder$1.WORD_SIZE = Int32Array.from([\n        4, 6, 6, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,\n        12, 12, 12, 12, 12, 12, 12, 12, 12, 12\n    ]);\n\n    /*\n    * Copyright 2013 ZXing authors\n    *\n    * Licensed under the Apache License, Version 2.0 (the \"License\");\n    * you may not use this file except in compliance with the License.\n    * You may obtain a copy of the License at\n    *\n    *      http://www.apache.org/licenses/LICENSE-2.0\n    *\n    * Unless required by applicable law or agreed to in writing, software\n    * distributed under the License is distributed on an \"AS IS\" BASIS,\n    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    * See the License for the specific language governing permissions and\n    * limitations under the License.\n    */\n    /**\n     * Renders an Aztec code as a {@link BitMatrix}.\n     */\n    /*public final*/ class AztecWriter {\n        // @Override\n        encode(contents, format, width, height) {\n            return this.encodeWithHints(contents, format, width, height, null);\n        }\n        // @Override\n        encodeWithHints(contents, format, width, height, hints) {\n            let charset = StandardCharsets.ISO_8859_1;\n            let eccPercent = Encoder$1.DEFAULT_EC_PERCENT;\n            let layers = Encoder$1.DEFAULT_AZTEC_LAYERS;\n            if (hints != null) {\n                if (hints.has(EncodeHintType$1.CHARACTER_SET)) {\n                    charset = Charset.forName(hints.get(EncodeHintType$1.CHARACTER_SET).toString());\n                }\n                if (hints.has(EncodeHintType$1.ERROR_CORRECTION)) {\n                    eccPercent = Integer.parseInt(hints.get(EncodeHintType$1.ERROR_CORRECTION).toString());\n                }\n                if (hints.has(EncodeHintType$1.AZTEC_LAYERS)) {\n                    layers = Integer.parseInt(hints.get(EncodeHintType$1.AZTEC_LAYERS).toString());\n                }\n            }\n            return AztecWriter.encodeLayers(contents, format, width, height, charset, eccPercent, layers);\n        }\n        static encodeLayers(contents, format, width, height, charset, eccPercent, layers) {\n            if (format !== BarcodeFormat$1.AZTEC) {\n                throw new IllegalArgumentException('Can only encode AZTEC, but got ' + format);\n            }\n            let aztec = Encoder$1.encode(StringUtils.getBytes(contents, charset), eccPercent, layers);\n            return AztecWriter.renderResult(aztec, width, height);\n        }\n        static renderResult(code, width, height) {\n            let input = code.getMatrix();\n            if (input == null) {\n                throw new IllegalStateException();\n            }\n            let inputWidth = input.getWidth();\n            let inputHeight = input.getHeight();\n            let outputWidth = Math.max(width, inputWidth);\n            let outputHeight = Math.max(height, inputHeight);\n            let multiple = Math.min(outputWidth / inputWidth, outputHeight / inputHeight);\n            let leftPadding = (outputWidth - (inputWidth * multiple)) / 2;\n            let topPadding = (outputHeight - (inputHeight * multiple)) / 2;\n            let output = new BitMatrix(outputWidth, outputHeight);\n            for (let inputY /*int*/ = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {\n                // Write the contents of this row of the barcode\n                for (let inputX /*int*/ = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {\n                    if (input.get(inputX, inputY)) {\n                        output.setRegion(outputX, outputY, multiple, multiple);\n                    }\n                }\n            }\n            return output;\n        }\n    }\n\n    exports.AbstractExpandedDecoder = AbstractExpandedDecoder;\n    exports.ArgumentException = ArgumentException;\n    exports.ArithmeticException = ArithmeticException;\n    exports.AztecCode = AztecCode;\n    exports.AztecCodeReader = AztecReader;\n    exports.AztecCodeWriter = AztecWriter;\n    exports.AztecDecoder = Decoder;\n    exports.AztecDetector = Detector;\n    exports.AztecDetectorResult = AztecDetectorResult;\n    exports.AztecEncoder = Encoder$1;\n    exports.AztecHighLevelEncoder = HighLevelEncoder;\n    exports.AztecPoint = Point;\n    exports.BarcodeFormat = BarcodeFormat$1;\n    exports.Binarizer = Binarizer;\n    exports.BinaryBitmap = BinaryBitmap;\n    exports.BitArray = BitArray;\n    exports.BitMatrix = BitMatrix;\n    exports.BitSource = BitSource;\n    exports.BrowserAztecCodeReader = BrowserAztecCodeReader;\n    exports.BrowserBarcodeReader = BrowserBarcodeReader;\n    exports.BrowserCodeReader = BrowserCodeReader;\n    exports.BrowserDatamatrixCodeReader = BrowserDatamatrixCodeReader;\n    exports.BrowserMultiFormatReader = BrowserMultiFormatReader;\n    exports.BrowserPDF417Reader = BrowserPDF417Reader;\n    exports.BrowserQRCodeReader = BrowserQRCodeReader;\n    exports.BrowserQRCodeSvgWriter = BrowserQRCodeSvgWriter;\n    exports.CharacterSetECI = CharacterSetECI;\n    exports.ChecksumException = ChecksumException;\n    exports.Code128Reader = Code128Reader;\n    exports.Code39Reader = Code39Reader;\n    exports.DataMatrixDecodedBitStreamParser = DecodedBitStreamParser;\n    exports.DataMatrixReader = DataMatrixReader;\n    exports.DecodeHintType = DecodeHintType$1;\n    exports.DecoderResult = DecoderResult;\n    exports.DefaultGridSampler = DefaultGridSampler;\n    exports.DetectorResult = DetectorResult;\n    exports.EAN13Reader = EAN13Reader;\n    exports.EncodeHintType = EncodeHintType$1;\n    exports.Exception = Exception;\n    exports.FormatException = FormatException;\n    exports.GenericGF = GenericGF;\n    exports.GenericGFPoly = GenericGFPoly;\n    exports.GlobalHistogramBinarizer = GlobalHistogramBinarizer;\n    exports.GridSampler = GridSampler;\n    exports.GridSamplerInstance = GridSamplerInstance;\n    exports.HTMLCanvasElementLuminanceSource = HTMLCanvasElementLuminanceSource;\n    exports.HybridBinarizer = HybridBinarizer;\n    exports.ITFReader = ITFReader;\n    exports.IllegalArgumentException = IllegalArgumentException;\n    exports.IllegalStateException = IllegalStateException;\n    exports.InvertedLuminanceSource = InvertedLuminanceSource;\n    exports.LuminanceSource = LuminanceSource;\n    exports.MathUtils = MathUtils;\n    exports.MultiFormatOneDReader = MultiFormatOneDReader;\n    exports.MultiFormatReader = MultiFormatReader;\n    exports.MultiFormatWriter = MultiFormatWriter;\n    exports.NotFoundException = NotFoundException;\n    exports.OneDReader = OneDReader;\n    exports.PDF417DecodedBitStreamParser = DecodedBitStreamParser$2;\n    exports.PDF417DecoderErrorCorrection = ErrorCorrection;\n    exports.PDF417Reader = PDF417Reader;\n    exports.PDF417ResultMetadata = PDF417ResultMetadata;\n    exports.PerspectiveTransform = PerspectiveTransform;\n    exports.PlanarYUVLuminanceSource = PlanarYUVLuminanceSource;\n    exports.QRCodeByteMatrix = ByteMatrix;\n    exports.QRCodeDataMask = DataMask;\n    exports.QRCodeDecodedBitStreamParser = DecodedBitStreamParser$1;\n    exports.QRCodeDecoderErrorCorrectionLevel = ErrorCorrectionLevel;\n    exports.QRCodeDecoderFormatInformation = FormatInformation;\n    exports.QRCodeEncoder = Encoder;\n    exports.QRCodeEncoderQRCode = QRCode;\n    exports.QRCodeMaskUtil = MaskUtil;\n    exports.QRCodeMatrixUtil = MatrixUtil;\n    exports.QRCodeMode = Mode$1;\n    exports.QRCodeReader = QRCodeReader;\n    exports.QRCodeVersion = Version$1;\n    exports.QRCodeWriter = QRCodeWriter;\n    exports.RGBLuminanceSource = RGBLuminanceSource;\n    exports.RSS14Reader = RSS14Reader;\n    exports.RSSExpandedReader = RSSExpandedReader;\n    exports.ReaderException = ReaderException;\n    exports.ReedSolomonDecoder = ReedSolomonDecoder;\n    exports.ReedSolomonEncoder = ReedSolomonEncoder;\n    exports.ReedSolomonException = ReedSolomonException;\n    exports.Result = Result;\n    exports.ResultMetadataType = ResultMetadataType$1;\n    exports.ResultPoint = ResultPoint;\n    exports.StringUtils = StringUtils;\n    exports.UnsupportedOperationException = UnsupportedOperationException;\n    exports.VideoInputDevice = VideoInputDevice;\n    exports.WhiteRectangleDetector = WhiteRectangleDetector;\n    exports.WriterException = WriterException;\n    exports.ZXingArrays = Arrays;\n    exports.ZXingCharset = Charset;\n    exports.ZXingInteger = Integer;\n    exports.ZXingStandardCharsets = StandardCharsets;\n    exports.ZXingStringBuilder = StringBuilder;\n    exports.ZXingStringEncoding = StringEncoding;\n    exports.ZXingSystem = System;\n    exports.createAbstractExpandedDecoder = createDecoder;\n\n    Object.defineProperty(exports, '__esModule', { value: true });\n\n})));\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL3RoaXJkX3BhcnR5L3p4aW5nLWpzLnVtZC5qcy5qcyIsIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvdGhpcmRfcGFydHkvenhpbmctanMudW1kLmpzP2YzYTYiXSwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMpIDpcbiAgICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJ10sIGZhY3RvcnkpIDpcbiAgICAoZ2xvYmFsID0gdHlwZW9mIGdsb2JhbFRoaXMgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsVGhpcyA6IGdsb2JhbCB8fCBzZWxmLCBmYWN0b3J5KGdsb2JhbC5aWGluZyA9IHt9KSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbiAgICBmdW5jdGlvbiBpc051bGxPclVuZGVmaW5lZChvYmopIHtcbiAgICAgICAgcmV0dXJuIG9iaiA9PT0gbnVsbCB8fCBvYmogPT09IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA4IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXG5cbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuXG4gICAgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmaXhQcm90byh0YXJnZXQsIHByb3RvdHlwZSkge1xuICAgICAgICB2YXIgc2V0UHJvdG90eXBlT2YgPSBPYmplY3Quc2V0UHJvdG90eXBlT2Y7XG4gICAgICAgIHNldFByb3RvdHlwZU9mID8gc2V0UHJvdG90eXBlT2YodGFyZ2V0LCBwcm90b3R5cGUpIDogKHRhcmdldC5fX3Byb3RvX18gPSBwcm90b3R5cGUpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZpeFN0YWNrKHRhcmdldCwgZm4pIHtcbiAgICAgICAgaWYgKGZuID09PSB2b2lkIDApIHtcbiAgICAgICAgICAgIGZuID0gdGFyZ2V0LmNvbnN0cnVjdG9yO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjYXB0dXJlU3RhY2tUcmFjZSA9IEVycm9yLmNhcHR1cmVTdGFja1RyYWNlO1xuICAgICAgICBjYXB0dXJlU3RhY2tUcmFjZSAmJiBjYXB0dXJlU3RhY2tUcmFjZSh0YXJnZXQsIGZuKTtcbiAgICB9XG5cbiAgICB2YXIgQ3VzdG9tRXJyb3IgPSAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgICAgICBfX2V4dGVuZHMoQ3VzdG9tRXJyb3IsIF9zdXBlcik7XG4gICAgICAgIGZ1bmN0aW9uIEN1c3RvbUVycm9yKG1lc3NhZ2UpIHtcbiAgICAgICAgICAgIHZhciBfbmV3VGFyZ2V0ID0gdGhpcy5jb25zdHJ1Y3RvcjtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIG1lc3NhZ2UpIHx8IHRoaXM7XG4gICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX3RoaXMsICduYW1lJywge1xuICAgICAgICAgICAgICAgIHZhbHVlOiBfbmV3VGFyZ2V0Lm5hbWUsXG4gICAgICAgICAgICAgICAgZW51bWVyYWJsZTogZmFsc2VcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZml4UHJvdG8oX3RoaXMsIF9uZXdUYXJnZXQucHJvdG90eXBlKTtcbiAgICAgICAgICAgIGZpeFN0YWNrKF90aGlzKTtcbiAgICAgICAgICAgIHJldHVybiBfdGhpcztcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgcmV0dXJuIEN1c3RvbUVycm9yO1xuICAgIH0pKEVycm9yKTtcblxuICAgIC8qKlxuICAgICAqIEN1c3RvbSBFcnJvciBjbGFzcyBvZiB0eXBlIEV4Y2VwdGlvbi5cbiAgICAgKi9cbiAgICBjbGFzcyBFeGNlcHRpb24gZXh0ZW5kcyBDdXN0b21FcnJvciB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBbGxvd3MgRXhjZXB0aW9uIHRvIGJlIGNvbnN0cnVjdGVkIGRpcmVjdGx5XG4gICAgICAgICAqIHdpdGggc29tZSBtZXNzYWdlIGFuZCBwcm90b3R5cGUgZGVmaW5pdGlvbi5cbiAgICAgICAgICovXG4gICAgICAgIGNvbnN0cnVjdG9yKG1lc3NhZ2UgPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHN1cGVyKG1lc3NhZ2UpO1xuICAgICAgICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRLaW5kKCkge1xuICAgICAgICAgICAgY29uc3QgZXggPSB0aGlzLmNvbnN0cnVjdG9yO1xuICAgICAgICAgICAgcmV0dXJuIGV4LmtpbmQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogSXQncyB0eXBlZCBhcyBzdHJpbmcgc28gaXQgY2FuIGJlIGV4dGVuZGVkIGFuZCBvdmVycmlkZW4uXG4gICAgICovXG4gICAgRXhjZXB0aW9uLmtpbmQgPSAnRXhjZXB0aW9uJztcblxuICAgIC8qKlxuICAgICAqIEN1c3RvbSBFcnJvciBjbGFzcyBvZiB0eXBlIEV4Y2VwdGlvbi5cbiAgICAgKi9cbiAgICBjbGFzcyBBcmd1bWVudEV4Y2VwdGlvbiBleHRlbmRzIEV4Y2VwdGlvbiB7XG4gICAgfVxuICAgIEFyZ3VtZW50RXhjZXB0aW9uLmtpbmQgPSAnQXJndW1lbnRFeGNlcHRpb24nO1xuXG4gICAgLyoqXG4gICAgICogQ3VzdG9tIEVycm9yIGNsYXNzIG9mIHR5cGUgRXhjZXB0aW9uLlxuICAgICAqL1xuICAgIGNsYXNzIElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbiBleHRlbmRzIEV4Y2VwdGlvbiB7XG4gICAgfVxuICAgIElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbi5raW5kID0gJ0lsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbic7XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA5IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIGNsYXNzIEJpbmFyeUJpdG1hcCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGJpbmFyaXplcikge1xuICAgICAgICAgICAgdGhpcy5iaW5hcml6ZXIgPSBiaW5hcml6ZXI7XG4gICAgICAgICAgICBpZiAoYmluYXJpemVyID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignQmluYXJpemVyIG11c3QgYmUgbm9uLW51bGwuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gVGhlIHdpZHRoIG9mIHRoZSBiaXRtYXAuXG4gICAgICAgICAqL1xuICAgICAgICBnZXRXaWR0aCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJpbmFyaXplci5nZXRXaWR0aCgpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIFRoZSBoZWlnaHQgb2YgdGhlIGJpdG1hcC5cbiAgICAgICAgICovXG4gICAgICAgIGdldEhlaWdodCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJpbmFyaXplci5nZXRIZWlnaHQoKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ29udmVydHMgb25lIHJvdyBvZiBsdW1pbmFuY2UgZGF0YSB0byAxIGJpdCBkYXRhLiBNYXkgYWN0dWFsbHkgZG8gdGhlIGNvbnZlcnNpb24sIG9yIHJldHVyblxuICAgICAgICAgKiBjYWNoZWQgZGF0YS4gQ2FsbGVycyBzaG91bGQgYXNzdW1lIHRoaXMgbWV0aG9kIGlzIGV4cGVuc2l2ZSBhbmQgY2FsbCBpdCBhcyBzZWxkb20gYXMgcG9zc2libGUuXG4gICAgICAgICAqIFRoaXMgbWV0aG9kIGlzIGludGVuZGVkIGZvciBkZWNvZGluZyAxRCBiYXJjb2RlcyBhbmQgbWF5IGNob29zZSB0byBhcHBseSBzaGFycGVuaW5nLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0geSBUaGUgcm93IHRvIGZldGNoLCB3aGljaCBtdXN0IGJlIGluIFswLCBiaXRtYXAgaGVpZ2h0KVxuICAgICAgICAgKiBAcGFyYW0gcm93IEFuIG9wdGlvbmFsIHByZWFsbG9jYXRlZCBhcnJheS4gSWYgbnVsbCBvciB0b28gc21hbGwsIGl0IHdpbGwgYmUgaWdub3JlZC5cbiAgICAgICAgICogICAgICAgICAgICBJZiB1c2VkLCB0aGUgQmluYXJpemVyIHdpbGwgY2FsbCBCaXRBcnJheS5jbGVhcigpLiBBbHdheXMgdXNlIHRoZSByZXR1cm5lZCBvYmplY3QuXG4gICAgICAgICAqIEByZXR1cm4gVGhlIGFycmF5IG9mIGJpdHMgZm9yIHRoaXMgcm93ICh0cnVlIG1lYW5zIGJsYWNrKS5cbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBpZiByb3cgY2FuJ3QgYmUgYmluYXJpemVkXG4gICAgICAgICAqL1xuICAgICAgICBnZXRCbGFja1Jvdyh5IC8qaW50Ki8sIHJvdykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmluYXJpemVyLmdldEJsYWNrUm93KHksIHJvdyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnZlcnRzIGEgMkQgYXJyYXkgb2YgbHVtaW5hbmNlIGRhdGEgdG8gMSBiaXQuIEFzIGFib3ZlLCBhc3N1bWUgdGhpcyBtZXRob2QgaXMgZXhwZW5zaXZlXG4gICAgICAgICAqIGFuZCBkbyBub3QgY2FsbCBpdCByZXBlYXRlZGx5LiBUaGlzIG1ldGhvZCBpcyBpbnRlbmRlZCBmb3IgZGVjb2RpbmcgMkQgYmFyY29kZXMgYW5kIG1heSBvclxuICAgICAgICAgKiBtYXkgbm90IGFwcGx5IHNoYXJwZW5pbmcuIFRoZXJlZm9yZSwgYSByb3cgZnJvbSB0aGlzIG1hdHJpeCBtYXkgbm90IGJlIGlkZW50aWNhbCB0byBvbmVcbiAgICAgICAgICogZmV0Y2hlZCB1c2luZyBnZXRCbGFja1JvdygpLCBzbyBkb24ndCBtaXggYW5kIG1hdGNoIGJldHdlZW4gdGhlbS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiBUaGUgMkQgYXJyYXkgb2YgYml0cyBmb3IgdGhlIGltYWdlICh0cnVlIG1lYW5zIGJsYWNrKS5cbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBpZiBpbWFnZSBjYW4ndCBiZSBiaW5hcml6ZWQgdG8gbWFrZSBhIG1hdHJpeFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0QmxhY2tNYXRyaXgoKSB7XG4gICAgICAgICAgICAvLyBUaGUgbWF0cml4IGlzIGNyZWF0ZWQgb24gZGVtYW5kIHRoZSBmaXJzdCB0aW1lIGl0IGlzIHJlcXVlc3RlZCwgdGhlbiBjYWNoZWQuIFRoZXJlIGFyZSB0d29cbiAgICAgICAgICAgIC8vIHJlYXNvbnMgZm9yIHRoaXM6XG4gICAgICAgICAgICAvLyAxLiBUaGlzIHdvcmsgd2lsbCBuZXZlciBiZSBkb25lIGlmIHRoZSBjYWxsZXIgb25seSBpbnN0YWxscyAxRCBSZWFkZXIgb2JqZWN0cywgb3IgaWYgYVxuICAgICAgICAgICAgLy8gICAgMUQgUmVhZGVyIGZpbmRzIGEgYmFyY29kZSBiZWZvcmUgdGhlIDJEIFJlYWRlcnMgcnVuLlxuICAgICAgICAgICAgLy8gMi4gVGhpcyB3b3JrIHdpbGwgb25seSBiZSBkb25lIG9uY2UgZXZlbiBpZiB0aGUgY2FsbGVyIGluc3RhbGxzIG11bHRpcGxlIDJEIFJlYWRlcnMuXG4gICAgICAgICAgICBpZiAodGhpcy5tYXRyaXggPT09IG51bGwgfHwgdGhpcy5tYXRyaXggPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRoaXMubWF0cml4ID0gdGhpcy5iaW5hcml6ZXIuZ2V0QmxhY2tNYXRyaXgoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1hdHJpeDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoaXMgYml0bWFwIGNhbiBiZSBjcm9wcGVkLlxuICAgICAgICAgKi9cbiAgICAgICAgaXNDcm9wU3VwcG9ydGVkKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmluYXJpemVyLmdldEx1bWluYW5jZVNvdXJjZSgpLmlzQ3JvcFN1cHBvcnRlZCgpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXR1cm5zIGEgbmV3IG9iamVjdCB3aXRoIGNyb3BwZWQgaW1hZ2UgZGF0YS4gSW1wbGVtZW50YXRpb25zIG1heSBrZWVwIGEgcmVmZXJlbmNlIHRvIHRoZVxuICAgICAgICAgKiBvcmlnaW5hbCBkYXRhIHJhdGhlciB0aGFuIGEgY29weS4gT25seSBjYWxsYWJsZSBpZiBpc0Nyb3BTdXBwb3J0ZWQoKSBpcyB0cnVlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gbGVmdCBUaGUgbGVmdCBjb29yZGluYXRlLCB3aGljaCBtdXN0IGJlIGluIFswLGdldFdpZHRoKCkpXG4gICAgICAgICAqIEBwYXJhbSB0b3AgVGhlIHRvcCBjb29yZGluYXRlLCB3aGljaCBtdXN0IGJlIGluIFswLGdldEhlaWdodCgpKVxuICAgICAgICAgKiBAcGFyYW0gd2lkdGggVGhlIHdpZHRoIG9mIHRoZSByZWN0YW5nbGUgdG8gY3JvcC5cbiAgICAgICAgICogQHBhcmFtIGhlaWdodCBUaGUgaGVpZ2h0IG9mIHRoZSByZWN0YW5nbGUgdG8gY3JvcC5cbiAgICAgICAgICogQHJldHVybiBBIGNyb3BwZWQgdmVyc2lvbiBvZiB0aGlzIG9iamVjdC5cbiAgICAgICAgICovXG4gICAgICAgIGNyb3AobGVmdCAvKmludCovLCB0b3AgLyppbnQqLywgd2lkdGggLyppbnQqLywgaGVpZ2h0IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IG5ld1NvdXJjZSA9IHRoaXMuYmluYXJpemVyLmdldEx1bWluYW5jZVNvdXJjZSgpLmNyb3AobGVmdCwgdG9wLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgQmluYXJ5Qml0bWFwKHRoaXMuYmluYXJpemVyLmNyZWF0ZUJpbmFyaXplcihuZXdTb3VyY2UpKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBXaGV0aGVyIHRoaXMgYml0bWFwIHN1cHBvcnRzIGNvdW50ZXItY2xvY2t3aXNlIHJvdGF0aW9uLlxuICAgICAgICAgKi9cbiAgICAgICAgaXNSb3RhdGVTdXBwb3J0ZWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5iaW5hcml6ZXIuZ2V0THVtaW5hbmNlU291cmNlKCkuaXNSb3RhdGVTdXBwb3J0ZWQoKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogUmV0dXJucyBhIG5ldyBvYmplY3Qgd2l0aCByb3RhdGVkIGltYWdlIGRhdGEgYnkgOTAgZGVncmVlcyBjb3VudGVyY2xvY2t3aXNlLlxuICAgICAgICAgKiBPbmx5IGNhbGxhYmxlIGlmIHtAbGluayAjaXNSb3RhdGVTdXBwb3J0ZWQoKX0gaXMgdHJ1ZS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiBBIHJvdGF0ZWQgdmVyc2lvbiBvZiB0aGlzIG9iamVjdC5cbiAgICAgICAgICovXG4gICAgICAgIHJvdGF0ZUNvdW50ZXJDbG9ja3dpc2UoKSB7XG4gICAgICAgICAgICBjb25zdCBuZXdTb3VyY2UgPSB0aGlzLmJpbmFyaXplci5nZXRMdW1pbmFuY2VTb3VyY2UoKS5yb3RhdGVDb3VudGVyQ2xvY2t3aXNlKCk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEJpbmFyeUJpdG1hcCh0aGlzLmJpbmFyaXplci5jcmVhdGVCaW5hcml6ZXIobmV3U291cmNlKSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldHVybnMgYSBuZXcgb2JqZWN0IHdpdGggcm90YXRlZCBpbWFnZSBkYXRhIGJ5IDQ1IGRlZ3JlZXMgY291bnRlcmNsb2Nrd2lzZS5cbiAgICAgICAgICogT25seSBjYWxsYWJsZSBpZiB7QGxpbmsgI2lzUm90YXRlU3VwcG9ydGVkKCl9IGlzIHRydWUuXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gQSByb3RhdGVkIHZlcnNpb24gb2YgdGhpcyBvYmplY3QuXG4gICAgICAgICAqL1xuICAgICAgICByb3RhdGVDb3VudGVyQ2xvY2t3aXNlNDUoKSB7XG4gICAgICAgICAgICBjb25zdCBuZXdTb3VyY2UgPSB0aGlzLmJpbmFyaXplci5nZXRMdW1pbmFuY2VTb3VyY2UoKS5yb3RhdGVDb3VudGVyQ2xvY2t3aXNlNDUoKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgQmluYXJ5Qml0bWFwKHRoaXMuYmluYXJpemVyLmNyZWF0ZUJpbmFyaXplcihuZXdTb3VyY2UpKTtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRCbGFja01hdHJpeCgpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZSAvKjogTm90Rm91bmRFeGNlcHRpb24qLykge1xuICAgICAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEN1c3RvbSBFcnJvciBjbGFzcyBvZiB0eXBlIEV4Y2VwdGlvbi5cbiAgICAgKi9cbiAgICBjbGFzcyBDaGVja3N1bUV4Y2VwdGlvbiBleHRlbmRzIEV4Y2VwdGlvbiB7XG4gICAgICAgIHN0YXRpYyBnZXRDaGVja3N1bUluc3RhbmNlKCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBDaGVja3N1bUV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgfVxuICAgIENoZWNrc3VtRXhjZXB0aW9uLmtpbmQgPSAnQ2hlY2tzdW1FeGNlcHRpb24nO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwOSBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiBUaGlzIGNsYXNzIGhpZXJhcmNoeSBwcm92aWRlcyBhIHNldCBvZiBtZXRob2RzIHRvIGNvbnZlcnQgbHVtaW5hbmNlIGRhdGEgdG8gMSBiaXQgZGF0YS5cbiAgICAgKiBJdCBhbGxvd3MgdGhlIGFsZ29yaXRobSB0byB2YXJ5IHBvbHltb3JwaGljYWxseSwgZm9yIGV4YW1wbGUgYWxsb3dpbmcgYSB2ZXJ5IGV4cGVuc2l2ZVxuICAgICAqIHRocmVzaG9sZGluZyB0ZWNobmlxdWUgZm9yIHNlcnZlcnMgYW5kIGEgZmFzdCBvbmUgZm9yIG1vYmlsZS4gSXQgYWxzbyBwZXJtaXRzIHRoZSBpbXBsZW1lbnRhdGlvblxuICAgICAqIHRvIHZhcnksIGUuZy4gYSBKTkkgdmVyc2lvbiBmb3IgQW5kcm9pZCBhbmQgYSBKYXZhIGZhbGxiYWNrIHZlcnNpb24gZm9yIG90aGVyIHBsYXRmb3Jtcy5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pXG4gICAgICovXG4gICAgY2xhc3MgQmluYXJpemVyIHtcbiAgICAgICAgY29uc3RydWN0b3Ioc291cmNlKSB7XG4gICAgICAgICAgICB0aGlzLnNvdXJjZSA9IHNvdXJjZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRMdW1pbmFuY2VTb3VyY2UoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zb3VyY2U7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0V2lkdGgoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zb3VyY2UuZ2V0V2lkdGgoKTtcbiAgICAgICAgfVxuICAgICAgICBnZXRIZWlnaHQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zb3VyY2UuZ2V0SGVpZ2h0KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjbGFzcyBTeXN0ZW0ge1xuICAgICAgICAvLyBwdWJsaWMgc3RhdGljIHZvaWQgYXJyYXljb3B5KE9iamVjdCBzcmMsIGludCBzcmNQb3MsIE9iamVjdCBkZXN0LCBpbnQgZGVzdFBvcywgaW50IGxlbmd0aClcbiAgICAgICAgLyoqXG4gICAgICAgICAqIE1ha2VzIGEgY29weSBvZiBhIGFycmF5LlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGFycmF5Y29weShzcmMsIHNyY1BvcywgZGVzdCwgZGVzdFBvcywgbGVuZ3RoKSB7XG4gICAgICAgICAgICAvLyBUT0RPOiBiZXR0ZXIgdXNlIHNwbGl0IG9yIHNldD9cbiAgICAgICAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICAgICAgICAgIGRlc3RbZGVzdFBvcysrXSA9IHNyY1tzcmNQb3MrK107XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldHVybnMgdGhlIGN1cnJlbnQgdGltZSBpbiBtaWxsaXNlY29uZHMuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgY3VycmVudFRpbWVNaWxsaXMoKSB7XG4gICAgICAgICAgICByZXR1cm4gRGF0ZS5ub3coKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEN1c3RvbSBFcnJvciBjbGFzcyBvZiB0eXBlIEV4Y2VwdGlvbi5cbiAgICAgKi9cbiAgICBjbGFzcyBJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uIGV4dGVuZHMgRXhjZXB0aW9uIHtcbiAgICB9XG4gICAgSW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbi5raW5kID0gJ0luZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb24nO1xuXG4gICAgLyoqXG4gICAgICogQ3VzdG9tIEVycm9yIGNsYXNzIG9mIHR5cGUgRXhjZXB0aW9uLlxuICAgICAqL1xuICAgIGNsYXNzIEFycmF5SW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbiBleHRlbmRzIEluZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb24ge1xuICAgICAgICBjb25zdHJ1Y3RvcihpbmRleCA9IHVuZGVmaW5lZCwgbWVzc2FnZSA9IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgc3VwZXIobWVzc2FnZSk7XG4gICAgICAgICAgICB0aGlzLmluZGV4ID0gaW5kZXg7XG4gICAgICAgICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgICAgICB9XG4gICAgfVxuICAgIEFycmF5SW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbi5raW5kID0gJ0FycmF5SW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbic7XG5cbiAgICBjbGFzcyBBcnJheXMge1xuICAgICAgICAvKipcbiAgICAgICAgICogQXNzaWducyB0aGUgc3BlY2lmaWVkIGludCB2YWx1ZSB0byBlYWNoIGVsZW1lbnQgb2YgdGhlIHNwZWNpZmllZCBhcnJheVxuICAgICAgICAgKiBvZiBpbnRzLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gYSB0aGUgYXJyYXkgdG8gYmUgZmlsbGVkXG4gICAgICAgICAqIEBwYXJhbSB2YWwgdGhlIHZhbHVlIHRvIGJlIHN0b3JlZCBpbiBhbGwgZWxlbWVudHMgb2YgdGhlIGFycmF5XG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZmlsbChhLCB2YWwpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBsZW4gPSBhLmxlbmd0aDsgaSA8IGxlbjsgaSsrKVxuICAgICAgICAgICAgICAgIGFbaV0gPSB2YWw7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEFzc2lnbnMgdGhlIHNwZWNpZmllZCBpbnQgdmFsdWUgdG8gZWFjaCBlbGVtZW50IG9mIHRoZSBzcGVjaWZpZWRcbiAgICAgICAgICogcmFuZ2Ugb2YgdGhlIHNwZWNpZmllZCBhcnJheSBvZiBpbnRzLiAgVGhlIHJhbmdlIHRvIGJlIGZpbGxlZFxuICAgICAgICAgKiBleHRlbmRzIGZyb20gaW5kZXgge0Bjb2RlIGZyb21JbmRleH0sIGluY2x1c2l2ZSwgdG8gaW5kZXhcbiAgICAgICAgICoge0Bjb2RlIHRvSW5kZXh9LCBleGNsdXNpdmUuICAoSWYge0Bjb2RlIGZyb21JbmRleD09dG9JbmRleH0sIHRoZVxuICAgICAgICAgKiByYW5nZSB0byBiZSBmaWxsZWQgaXMgZW1wdHkuKVxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gYSB0aGUgYXJyYXkgdG8gYmUgZmlsbGVkXG4gICAgICAgICAqIEBwYXJhbSBmcm9tSW5kZXggdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBlbGVtZW50IChpbmNsdXNpdmUpIHRvIGJlXG4gICAgICAgICAqICAgICAgICBmaWxsZWQgd2l0aCB0aGUgc3BlY2lmaWVkIHZhbHVlXG4gICAgICAgICAqIEBwYXJhbSB0b0luZGV4IHRoZSBpbmRleCBvZiB0aGUgbGFzdCBlbGVtZW50IChleGNsdXNpdmUpIHRvIGJlXG4gICAgICAgICAqICAgICAgICBmaWxsZWQgd2l0aCB0aGUgc3BlY2lmaWVkIHZhbHVlXG4gICAgICAgICAqIEBwYXJhbSB2YWwgdGhlIHZhbHVlIHRvIGJlIHN0b3JlZCBpbiBhbGwgZWxlbWVudHMgb2YgdGhlIGFycmF5XG4gICAgICAgICAqIEB0aHJvd3MgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uIGlmIHtAY29kZSBmcm9tSW5kZXggPiB0b0luZGV4fVxuICAgICAgICAgKiBAdGhyb3dzIEFycmF5SW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbiBpZiB7QGNvZGUgZnJvbUluZGV4IDwgMH0gb3JcbiAgICAgICAgICogICAgICAgICB7QGNvZGUgdG9JbmRleCA+IGEubGVuZ3RofVxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGZpbGxXaXRoaW4oYSwgZnJvbUluZGV4LCB0b0luZGV4LCB2YWwpIHtcbiAgICAgICAgICAgIEFycmF5cy5yYW5nZUNoZWNrKGEubGVuZ3RoLCBmcm9tSW5kZXgsIHRvSW5kZXgpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGZyb21JbmRleDsgaSA8IHRvSW5kZXg7IGkrKylcbiAgICAgICAgICAgICAgICBhW2ldID0gdmFsO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDaGVja3MgdGhhdCB7QGNvZGUgZnJvbUluZGV4fSBhbmQge0Bjb2RlIHRvSW5kZXh9IGFyZSBpblxuICAgICAgICAgKiB0aGUgcmFuZ2UgYW5kIHRocm93cyBhbiBleGNlcHRpb24gaWYgdGhleSBhcmVuJ3QuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgcmFuZ2VDaGVjayhhcnJheUxlbmd0aCwgZnJvbUluZGV4LCB0b0luZGV4KSB7XG4gICAgICAgICAgICBpZiAoZnJvbUluZGV4ID4gdG9JbmRleCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ2Zyb21JbmRleCgnICsgZnJvbUluZGV4ICsgJykgPiB0b0luZGV4KCcgKyB0b0luZGV4ICsgJyknKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmcm9tSW5kZXggPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEFycmF5SW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbihmcm9tSW5kZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRvSW5kZXggPiBhcnJheUxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBBcnJheUluZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb24odG9JbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGFzTGlzdCguLi5hcmdzKSB7XG4gICAgICAgICAgICByZXR1cm4gYXJncztcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgY3JlYXRlKHJvd3MsIGNvbHMsIHZhbHVlKSB7XG4gICAgICAgICAgICBsZXQgYXJyID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogcm93cyB9KTtcbiAgICAgICAgICAgIHJldHVybiBhcnIubWFwKHggPT4gQXJyYXkuZnJvbSh7IGxlbmd0aDogY29scyB9KS5maWxsKHZhbHVlKSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGNyZWF0ZUludDMyQXJyYXkocm93cywgY29scywgdmFsdWUpIHtcbiAgICAgICAgICAgIGxldCBhcnIgPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiByb3dzIH0pO1xuICAgICAgICAgICAgcmV0dXJuIGFyci5tYXAoeCA9PiBJbnQzMkFycmF5LmZyb20oeyBsZW5ndGg6IGNvbHMgfSkuZmlsbCh2YWx1ZSkpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBlcXVhbHMoZmlyc3QsIHNlY29uZCkge1xuICAgICAgICAgICAgaWYgKCFmaXJzdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghc2Vjb25kKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFmaXJzdC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXNlY29uZC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZmlyc3QubGVuZ3RoICE9PSBzZWNvbmQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGxlbmd0aCA9IGZpcnN0Lmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGZpcnN0W2ldICE9PSBzZWNvbmRbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBoYXNoQ29kZShhKSB7XG4gICAgICAgICAgICBpZiAoYSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IDE7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgYSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IDMxICogcmVzdWx0ICsgZWxlbWVudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGZpbGxVaW50OEFycmF5KGEsIHZhbHVlKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSAhPT0gYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGFbaV0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgY29weU9mKG9yaWdpbmFsLCBuZXdMZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbC5zbGljZSgwLCBuZXdMZW5ndGgpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBjb3B5T2ZVaW50OEFycmF5KG9yaWdpbmFsLCBuZXdMZW5ndGgpIHtcbiAgICAgICAgICAgIGlmIChvcmlnaW5hbC5sZW5ndGggPD0gbmV3TGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbmV3QXJyYXkgPSBuZXcgVWludDhBcnJheShuZXdMZW5ndGgpO1xuICAgICAgICAgICAgICAgIG5ld0FycmF5LnNldChvcmlnaW5hbCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld0FycmF5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsLnNsaWNlKDAsIG5ld0xlbmd0aCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGNvcHlPZlJhbmdlKG9yaWdpbmFsLCBmcm9tLCB0bykge1xuICAgICAgICAgICAgY29uc3QgbmV3TGVuZ3RoID0gdG8gLSBmcm9tO1xuICAgICAgICAgICAgY29uc3QgY29weSA9IG5ldyBJbnQzMkFycmF5KG5ld0xlbmd0aCk7XG4gICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KG9yaWdpbmFsLCBmcm9tLCBjb3B5LCAwLCBuZXdMZW5ndGgpO1xuICAgICAgICAgICAgcmV0dXJuIGNvcHk7XG4gICAgICAgIH1cbiAgICAgICAgLypcbiAgICAgICAgKiBSZXR1cm5zIHRoZSBpbmRleCBvZiBvZiB0aGUgZWxlbWVudCBpbiBhIHNvcnRlZCBhcnJheSBvciAoLW4tMSkgd2hlcmUgbiBpcyB0aGUgaW5zZXJ0aW9uIHBvaW50XG4gICAgICAgICogZm9yIHRoZSBuZXcgZWxlbWVudC5cbiAgICAgICAgKiBQYXJhbWV0ZXJzOlxuICAgICAgICAqICAgICBhciAtIEEgc29ydGVkIGFycmF5XG4gICAgICAgICogICAgIGVsIC0gQW4gZWxlbWVudCB0byBzZWFyY2ggZm9yXG4gICAgICAgICogICAgIGNvbXBhcmF0b3IgLSBBIGNvbXBhcmF0b3IgZnVuY3Rpb24uIFRoZSBmdW5jdGlvbiB0YWtlcyB0d28gYXJndW1lbnRzOiAoYSwgYikgYW5kIHJldHVybnM6XG4gICAgICAgICogICAgICAgIGEgbmVnYXRpdmUgbnVtYmVyICBpZiBhIGlzIGxlc3MgdGhhbiBiO1xuICAgICAgICAqICAgICAgICAwIGlmIGEgaXMgZXF1YWwgdG8gYjtcbiAgICAgICAgKiAgICAgICAgYSBwb3NpdGl2ZSBudW1iZXIgb2YgYSBpcyBncmVhdGVyIHRoYW4gYi5cbiAgICAgICAgKiBUaGUgYXJyYXkgbWF5IGNvbnRhaW4gZHVwbGljYXRlIGVsZW1lbnRzLiBJZiB0aGVyZSBhcmUgbW9yZSB0aGFuIG9uZSBlcXVhbCBlbGVtZW50cyBpbiB0aGUgYXJyYXksXG4gICAgICAgICogdGhlIHJldHVybmVkIHZhbHVlIGNhbiBiZSB0aGUgaW5kZXggb2YgYW55IG9uZSBvZiB0aGUgZXF1YWwgZWxlbWVudHMuXG4gICAgICAgICpcbiAgICAgICAgKiBodHRwOi8vanNmaWRkbGUubmV0L2FyeXpob3YvcGtmc3Q1NTAvXG4gICAgICAgICovXG4gICAgICAgIHN0YXRpYyBiaW5hcnlTZWFyY2goYXIsIGVsLCBjb21wYXJhdG9yKSB7XG4gICAgICAgICAgICBpZiAodW5kZWZpbmVkID09PSBjb21wYXJhdG9yKSB7XG4gICAgICAgICAgICAgICAgY29tcGFyYXRvciA9IEFycmF5cy5udW1iZXJDb21wYXJhdG9yO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IG0gPSAwO1xuICAgICAgICAgICAgbGV0IG4gPSBhci5sZW5ndGggLSAxO1xuICAgICAgICAgICAgd2hpbGUgKG0gPD0gbikge1xuICAgICAgICAgICAgICAgIGNvbnN0IGsgPSAobiArIG0pID4+IDE7XG4gICAgICAgICAgICAgICAgY29uc3QgY21wID0gY29tcGFyYXRvcihlbCwgYXJba10pO1xuICAgICAgICAgICAgICAgIGlmIChjbXAgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG0gPSBrICsgMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoY21wIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICBuID0gayAtIDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gLW0gLSAxO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBudW1iZXJDb21wYXJhdG9yKGEsIGIpIHtcbiAgICAgICAgICAgIHJldHVybiBhIC0gYjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBvbnlmaWxsIGZvciBKYXZhJ3MgSW50ZWdlciBjbGFzcy5cbiAgICAgKi9cbiAgICBjbGFzcyBJbnRlZ2VyIHtcbiAgICAgICAgc3RhdGljIG51bWJlck9mVHJhaWxpbmdaZXJvcyhpKSB7XG4gICAgICAgICAgICBsZXQgeTtcbiAgICAgICAgICAgIGlmIChpID09PSAwKVxuICAgICAgICAgICAgICAgIHJldHVybiAzMjtcbiAgICAgICAgICAgIGxldCBuID0gMzE7XG4gICAgICAgICAgICB5ID0gaSA8PCAxNjtcbiAgICAgICAgICAgIGlmICh5ICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgbiAtPSAxNjtcbiAgICAgICAgICAgICAgICBpID0geTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHkgPSBpIDw8IDg7XG4gICAgICAgICAgICBpZiAoeSAhPT0gMCkge1xuICAgICAgICAgICAgICAgIG4gLT0gODtcbiAgICAgICAgICAgICAgICBpID0geTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHkgPSBpIDw8IDQ7XG4gICAgICAgICAgICBpZiAoeSAhPT0gMCkge1xuICAgICAgICAgICAgICAgIG4gLT0gNDtcbiAgICAgICAgICAgICAgICBpID0geTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHkgPSBpIDw8IDI7XG4gICAgICAgICAgICBpZiAoeSAhPT0gMCkge1xuICAgICAgICAgICAgICAgIG4gLT0gMjtcbiAgICAgICAgICAgICAgICBpID0geTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuIC0gKChpIDw8IDEpID4+PiAzMSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIG51bWJlck9mTGVhZGluZ1plcm9zKGkpIHtcbiAgICAgICAgICAgIC8vIEhELCBGaWd1cmUgNS02XG4gICAgICAgICAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAzMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBuID0gMTtcbiAgICAgICAgICAgIGlmIChpID4+PiAxNiA9PT0gMCkge1xuICAgICAgICAgICAgICAgIG4gKz0gMTY7XG4gICAgICAgICAgICAgICAgaSA8PD0gMTY7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaSA+Pj4gMjQgPT09IDApIHtcbiAgICAgICAgICAgICAgICBuICs9IDg7XG4gICAgICAgICAgICAgICAgaSA8PD0gODtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpID4+PiAyOCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIG4gKz0gNDtcbiAgICAgICAgICAgICAgICBpIDw8PSA0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGkgPj4+IDMwID09PSAwKSB7XG4gICAgICAgICAgICAgICAgbiArPSAyO1xuICAgICAgICAgICAgICAgIGkgPDw9IDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBuIC09IGkgPj4+IDMxO1xuICAgICAgICAgICAgcmV0dXJuIG47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHRvSGV4U3RyaW5nKGkpIHtcbiAgICAgICAgICAgIHJldHVybiBpLnRvU3RyaW5nKDE2KTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgdG9CaW5hcnlTdHJpbmcoaW50TnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4gU3RyaW5nKHBhcnNlSW50KFN0cmluZyhpbnROdW1iZXIpLCAyKSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmV0dXJucyB0aGUgbnVtYmVyIG9mIG9uZS1iaXRzIGluIHRoZSB0d28ncyBjb21wbGVtZW50IGJpbmFyeSByZXByZXNlbnRhdGlvbiBvZiB0aGUgc3BlY2lmaWVkIGludCB2YWx1ZS4gVGhpcyBmdW5jdGlvbiBpcyBzb21ldGltZXMgcmVmZXJyZWQgdG8gYXMgdGhlIHBvcHVsYXRpb24gY291bnQuXG4gICAgICAgIC8vIFJldHVybnM6XG4gICAgICAgIC8vIHRoZSBudW1iZXIgb2Ygb25lLWJpdHMgaW4gdGhlIHR3bydzIGNvbXBsZW1lbnQgYmluYXJ5IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBzcGVjaWZpZWQgaW50IHZhbHVlLlxuICAgICAgICBzdGF0aWMgYml0Q291bnQoaSkge1xuICAgICAgICAgICAgLy8gSEQsIEZpZ3VyZSA1LTJcbiAgICAgICAgICAgIGkgPSBpIC0gKChpID4+PiAxKSAmIDB4NTU1NTU1NTUpO1xuICAgICAgICAgICAgaSA9IChpICYgMHgzMzMzMzMzMykgKyAoKGkgPj4+IDIpICYgMHgzMzMzMzMzMyk7XG4gICAgICAgICAgICBpID0gKGkgKyAoaSA+Pj4gNCkpICYgMHgwZjBmMGYwZjtcbiAgICAgICAgICAgIGkgPSBpICsgKGkgPj4+IDgpO1xuICAgICAgICAgICAgaSA9IGkgKyAoaSA+Pj4gMTYpO1xuICAgICAgICAgICAgcmV0dXJuIGkgJiAweDNmO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyB0cnVuY0RpdmlzaW9uKGRpdmlkZW5kLCBkaXZpc29yKSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC50cnVuYyhkaXZpZGVuZCAvIGRpdmlzb3IpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb252ZXJ0cyBBIHN0cmluZyB0byBhbiBpbnRlZ2VyLlxuICAgICAgICAgKiBAcGFyYW0gcyBBIHN0cmluZyB0byBjb252ZXJ0IGludG8gYSBudW1iZXIuXG4gICAgICAgICAqIEBwYXJhbSByYWRpeCBBIHZhbHVlIGJldHdlZW4gMiBhbmQgMzYgdGhhdCBzcGVjaWZpZXMgdGhlIGJhc2Ugb2YgdGhlIG51bWJlciBpbiBudW1TdHJpbmcuIElmIHRoaXMgYXJndW1lbnQgaXMgbm90IHN1cHBsaWVkLCBzdHJpbmdzIHdpdGggYSBwcmVmaXggb2YgJzB4JyBhcmUgY29uc2lkZXJlZCBoZXhhZGVjaW1hbC4gQWxsIG90aGVyIHN0cmluZ3MgYXJlIGNvbnNpZGVyZWQgZGVjaW1hbC5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBwYXJzZUludChudW0sIHJhZGl4ID0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VJbnQobnVtLCByYWRpeCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgSW50ZWdlci5NSU5fVkFMVUVfMzJfQklUUyA9IC0yMTQ3NDgzNjQ4O1xuICAgIEludGVnZXIuTUFYX1ZBTFVFID0gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVI7XG5cbiAgICAvKipcbiAgICAgKiA8cD5BIHNpbXBsZSwgZmFzdCBhcnJheSBvZiBiaXRzLCByZXByZXNlbnRlZCBjb21wYWN0bHkgYnkgYW4gYXJyYXkgb2YgaW50cyBpbnRlcm5hbGx5LjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgQml0QXJyYXkgLyppbXBsZW1lbnRzIENsb25lYWJsZSovIHtcbiAgICAgICAgLy8gRm9yIHRlc3Rpbmcgb25seVxuICAgICAgICBjb25zdHJ1Y3RvcihzaXplIC8qaW50Ki8sIGJpdHMpIHtcbiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IHNpemUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNpemUgPSAwO1xuICAgICAgICAgICAgICAgIHRoaXMuYml0cyA9IG5ldyBJbnQzMkFycmF5KDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zaXplID0gc2l6ZTtcbiAgICAgICAgICAgICAgICBpZiAodW5kZWZpbmVkID09PSBiaXRzIHx8IG51bGwgPT09IGJpdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5iaXRzID0gQml0QXJyYXkubWFrZUFycmF5KHNpemUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5iaXRzID0gYml0cztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZ2V0U2l6ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNpemU7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0U2l6ZUluQnl0ZXMoKSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5mbG9vcigodGhpcy5zaXplICsgNykgLyA4KTtcbiAgICAgICAgfVxuICAgICAgICBlbnN1cmVDYXBhY2l0eShzaXplIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGlmIChzaXplID4gdGhpcy5iaXRzLmxlbmd0aCAqIDMyKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbmV3Qml0cyA9IEJpdEFycmF5Lm1ha2VBcnJheShzaXplKTtcbiAgICAgICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KHRoaXMuYml0cywgMCwgbmV3Qml0cywgMCwgdGhpcy5iaXRzLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgdGhpcy5iaXRzID0gbmV3Qml0cztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIGkgYml0IHRvIGdldFxuICAgICAgICAgKiBAcmV0dXJuIHRydWUgaWZmIGJpdCBpIGlzIHNldFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0KGkgLyppbnQqLykge1xuICAgICAgICAgICAgcmV0dXJuICh0aGlzLmJpdHNbTWF0aC5mbG9vcihpIC8gMzIpXSAmICgxIDw8IChpICYgMHgxRikpKSAhPT0gMDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogU2V0cyBiaXQgaS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGkgYml0IHRvIHNldFxuICAgICAgICAgKi9cbiAgICAgICAgc2V0KGkgLyppbnQqLykge1xuICAgICAgICAgICAgdGhpcy5iaXRzW01hdGguZmxvb3IoaSAvIDMyKV0gfD0gMSA8PCAoaSAmIDB4MUYpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBGbGlwcyBiaXQgaS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGkgYml0IHRvIHNldFxuICAgICAgICAgKi9cbiAgICAgICAgZmxpcChpIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHRoaXMuYml0c1tNYXRoLmZsb29yKGkgLyAzMildIF49IDEgPDwgKGkgJiAweDFGKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIGZyb20gZmlyc3QgYml0IHRvIGNoZWNrXG4gICAgICAgICAqIEByZXR1cm4gaW5kZXggb2YgZmlyc3QgYml0IHRoYXQgaXMgc2V0LCBzdGFydGluZyBmcm9tIHRoZSBnaXZlbiBpbmRleCwgb3Igc2l6ZSBpZiBub25lIGFyZSBzZXRcbiAgICAgICAgICogIGF0IG9yIGJleW9uZCB0aGlzIGdpdmVuIGluZGV4XG4gICAgICAgICAqIEBzZWUgI2dldE5leHRVbnNldChpbnQpXG4gICAgICAgICAqL1xuICAgICAgICBnZXROZXh0U2V0KGZyb20gLyppbnQqLykge1xuICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IHRoaXMuc2l6ZTtcbiAgICAgICAgICAgIGlmIChmcm9tID49IHNpemUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2l6ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGJpdHMgPSB0aGlzLmJpdHM7XG4gICAgICAgICAgICBsZXQgYml0c09mZnNldCA9IE1hdGguZmxvb3IoZnJvbSAvIDMyKTtcbiAgICAgICAgICAgIGxldCBjdXJyZW50Qml0cyA9IGJpdHNbYml0c09mZnNldF07XG4gICAgICAgICAgICAvLyBtYXNrIG9mZiBsZXNzZXIgYml0cyBmaXJzdFxuICAgICAgICAgICAgY3VycmVudEJpdHMgJj0gfigoMSA8PCAoZnJvbSAmIDB4MUYpKSAtIDEpO1xuICAgICAgICAgICAgY29uc3QgbGVuZ3RoID0gYml0cy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoY3VycmVudEJpdHMgPT09IDApIHtcbiAgICAgICAgICAgICAgICBpZiAoKytiaXRzT2Zmc2V0ID09PSBsZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNpemU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGN1cnJlbnRCaXRzID0gYml0c1tiaXRzT2Zmc2V0XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IChiaXRzT2Zmc2V0ICogMzIpICsgSW50ZWdlci5udW1iZXJPZlRyYWlsaW5nWmVyb3MoY3VycmVudEJpdHMpO1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCA+IHNpemUgPyBzaXplIDogcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gZnJvbSBpbmRleCB0byBzdGFydCBsb29raW5nIGZvciB1bnNldCBiaXRcbiAgICAgICAgICogQHJldHVybiBpbmRleCBvZiBuZXh0IHVuc2V0IGJpdCwgb3Ige0Bjb2RlIHNpemV9IGlmIG5vbmUgYXJlIHVuc2V0IHVudGlsIHRoZSBlbmRcbiAgICAgICAgICogQHNlZSAjZ2V0TmV4dFNldChpbnQpXG4gICAgICAgICAqL1xuICAgICAgICBnZXROZXh0VW5zZXQoZnJvbSAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBzaXplID0gdGhpcy5zaXplO1xuICAgICAgICAgICAgaWYgKGZyb20gPj0gc2l6ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzaXplO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYml0cyA9IHRoaXMuYml0cztcbiAgICAgICAgICAgIGxldCBiaXRzT2Zmc2V0ID0gTWF0aC5mbG9vcihmcm9tIC8gMzIpO1xuICAgICAgICAgICAgbGV0IGN1cnJlbnRCaXRzID0gfmJpdHNbYml0c09mZnNldF07XG4gICAgICAgICAgICAvLyBtYXNrIG9mZiBsZXNzZXIgYml0cyBmaXJzdFxuICAgICAgICAgICAgY3VycmVudEJpdHMgJj0gfigoMSA8PCAoZnJvbSAmIDB4MUYpKSAtIDEpO1xuICAgICAgICAgICAgY29uc3QgbGVuZ3RoID0gYml0cy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoY3VycmVudEJpdHMgPT09IDApIHtcbiAgICAgICAgICAgICAgICBpZiAoKytiaXRzT2Zmc2V0ID09PSBsZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNpemU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGN1cnJlbnRCaXRzID0gfmJpdHNbYml0c09mZnNldF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSAoYml0c09mZnNldCAqIDMyKSArIEludGVnZXIubnVtYmVyT2ZUcmFpbGluZ1plcm9zKGN1cnJlbnRCaXRzKTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQgPiBzaXplID8gc2l6ZSA6IHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogU2V0cyBhIGJsb2NrIG9mIDMyIGJpdHMsIHN0YXJ0aW5nIGF0IGJpdCBpLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gaSBmaXJzdCBiaXQgdG8gc2V0XG4gICAgICAgICAqIEBwYXJhbSBuZXdCaXRzIHRoZSBuZXcgdmFsdWUgb2YgdGhlIG5leHQgMzIgYml0cy4gTm90ZSBhZ2FpbiB0aGF0IHRoZSBsZWFzdC1zaWduaWZpY2FudCBiaXRcbiAgICAgICAgICogY29ycmVzcG9uZHMgdG8gYml0IGksIHRoZSBuZXh0LWxlYXN0LXNpZ25pZmljYW50IHRvIGkrMSwgYW5kIHNvIG9uLlxuICAgICAgICAgKi9cbiAgICAgICAgc2V0QnVsayhpIC8qaW50Ki8sIG5ld0JpdHMgLyppbnQqLykge1xuICAgICAgICAgICAgdGhpcy5iaXRzW01hdGguZmxvb3IoaSAvIDMyKV0gPSBuZXdCaXRzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZXRzIGEgcmFuZ2Ugb2YgYml0cy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHN0YXJ0IHN0YXJ0IG9mIHJhbmdlLCBpbmNsdXNpdmUuXG4gICAgICAgICAqIEBwYXJhbSBlbmQgZW5kIG9mIHJhbmdlLCBleGNsdXNpdmVcbiAgICAgICAgICovXG4gICAgICAgIHNldFJhbmdlKHN0YXJ0IC8qaW50Ki8sIGVuZCAvKmludCovKSB7XG4gICAgICAgICAgICBpZiAoZW5kIDwgc3RhcnQgfHwgc3RhcnQgPCAwIHx8IGVuZCA+IHRoaXMuc2l6ZSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChlbmQgPT09IHN0YXJ0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZW5kLS07IC8vIHdpbGwgYmUgZWFzaWVyIHRvIHRyZWF0IHRoaXMgYXMgdGhlIGxhc3QgYWN0dWFsbHkgc2V0IGJpdCAtLSBpbmNsdXNpdmVcbiAgICAgICAgICAgIGNvbnN0IGZpcnN0SW50ID0gTWF0aC5mbG9vcihzdGFydCAvIDMyKTtcbiAgICAgICAgICAgIGNvbnN0IGxhc3RJbnQgPSBNYXRoLmZsb29yKGVuZCAvIDMyKTtcbiAgICAgICAgICAgIGNvbnN0IGJpdHMgPSB0aGlzLmJpdHM7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gZmlyc3RJbnQ7IGkgPD0gbGFzdEludDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZmlyc3RCaXQgPSBpID4gZmlyc3RJbnQgPyAwIDogc3RhcnQgJiAweDFGO1xuICAgICAgICAgICAgICAgIGNvbnN0IGxhc3RCaXQgPSBpIDwgbGFzdEludCA/IDMxIDogZW5kICYgMHgxRjtcbiAgICAgICAgICAgICAgICAvLyBPbmVzIGZyb20gZmlyc3RCaXQgdG8gbGFzdEJpdCwgaW5jbHVzaXZlXG4gICAgICAgICAgICAgICAgY29uc3QgbWFzayA9ICgyIDw8IGxhc3RCaXQpIC0gKDEgPDwgZmlyc3RCaXQpO1xuICAgICAgICAgICAgICAgIGJpdHNbaV0gfD0gbWFzaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ2xlYXJzIGFsbCBiaXRzIChzZXRzIHRvIGZhbHNlKS5cbiAgICAgICAgICovXG4gICAgICAgIGNsZWFyKCkge1xuICAgICAgICAgICAgY29uc3QgbWF4ID0gdGhpcy5iaXRzLmxlbmd0aDtcbiAgICAgICAgICAgIGNvbnN0IGJpdHMgPSB0aGlzLmJpdHM7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1heDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgYml0c1tpXSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVmZmljaWVudCBtZXRob2QgdG8gY2hlY2sgaWYgYSByYW5nZSBvZiBiaXRzIGlzIHNldCwgb3Igbm90IHNldC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHN0YXJ0IHN0YXJ0IG9mIHJhbmdlLCBpbmNsdXNpdmUuXG4gICAgICAgICAqIEBwYXJhbSBlbmQgZW5kIG9mIHJhbmdlLCBleGNsdXNpdmVcbiAgICAgICAgICogQHBhcmFtIHZhbHVlIGlmIHRydWUsIGNoZWNrcyB0aGF0IGJpdHMgaW4gcmFuZ2UgYXJlIHNldCwgb3RoZXJ3aXNlIGNoZWNrcyB0aGF0IHRoZXkgYXJlIG5vdCBzZXRcbiAgICAgICAgICogXG4gICAgICAgICAqIEByZXR1cm4gdHJ1ZSBpZmYgYWxsIGJpdHMgYXJlIHNldCBvciBub3Qgc2V0IGluIHJhbmdlLCBhY2NvcmRpbmcgdG8gdmFsdWUgYXJndW1lbnRcbiAgICAgICAgICogQHRocm93cyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24gaWYgZW5kIGlzIGxlc3MgdGhhbiBzdGFydCBvciB0aGUgcmFuZ2UgaXMgbm90IGNvbnRhaW5lZCBpbiB0aGUgYXJyYXlcbiAgICAgICAgICovXG4gICAgICAgIGlzUmFuZ2Uoc3RhcnQgLyppbnQqLywgZW5kIC8qaW50Ki8sIHZhbHVlKSB7XG4gICAgICAgICAgICBpZiAoZW5kIDwgc3RhcnQgfHwgc3RhcnQgPCAwIHx8IGVuZCA+IHRoaXMuc2l6ZSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChlbmQgPT09IHN0YXJ0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7IC8vIGVtcHR5IHJhbmdlIG1hdGNoZXNcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVuZC0tOyAvLyB3aWxsIGJlIGVhc2llciB0byB0cmVhdCB0aGlzIGFzIHRoZSBsYXN0IGFjdHVhbGx5IHNldCBiaXQgLS0gaW5jbHVzaXZlXG4gICAgICAgICAgICBjb25zdCBmaXJzdEludCA9IE1hdGguZmxvb3Ioc3RhcnQgLyAzMik7XG4gICAgICAgICAgICBjb25zdCBsYXN0SW50ID0gTWF0aC5mbG9vcihlbmQgLyAzMik7XG4gICAgICAgICAgICBjb25zdCBiaXRzID0gdGhpcy5iaXRzO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGZpcnN0SW50OyBpIDw9IGxhc3RJbnQ7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpcnN0Qml0ID0gaSA+IGZpcnN0SW50ID8gMCA6IHN0YXJ0ICYgMHgxRjtcbiAgICAgICAgICAgICAgICBjb25zdCBsYXN0Qml0ID0gaSA8IGxhc3RJbnQgPyAzMSA6IGVuZCAmIDB4MUY7XG4gICAgICAgICAgICAgICAgLy8gT25lcyBmcm9tIGZpcnN0Qml0IHRvIGxhc3RCaXQsIGluY2x1c2l2ZVxuICAgICAgICAgICAgICAgIGNvbnN0IG1hc2sgPSAoMiA8PCBsYXN0Qml0KSAtICgxIDw8IGZpcnN0Qml0KSAmIDB4RkZGRkZGRkY7XG4gICAgICAgICAgICAgICAgLy8gVFlQRVNDUklQVFBPUlQ6ICYgMHhGRkZGRkZGRiBhZGRlZCB0byBkaXNjYXJkIGFueXRoaW5nIGFmdGVyIDMyIGJpdHMsIGFzIEVTIGhhcyA1MyBiaXRzXG4gICAgICAgICAgICAgICAgLy8gUmV0dXJuIGZhbHNlIGlmIHdlJ3JlIGxvb2tpbmcgZm9yIDFzIGFuZCB0aGUgbWFza2VkIGJpdHNbaV0gaXNuJ3QgYWxsIDFzIChpczogdGhhdCxcbiAgICAgICAgICAgICAgICAvLyBlcXVhbHMgdGhlIG1hc2ssIG9yIHdlJ3JlIGxvb2tpbmcgZm9yIDBzIGFuZCB0aGUgbWFza2VkIHBvcnRpb24gaXMgbm90IGFsbCAwc1xuICAgICAgICAgICAgICAgIGlmICgoYml0c1tpXSAmIG1hc2spICE9PSAodmFsdWUgPyBtYXNrIDogMCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGFwcGVuZEJpdChiaXQpIHtcbiAgICAgICAgICAgIHRoaXMuZW5zdXJlQ2FwYWNpdHkodGhpcy5zaXplICsgMSk7XG4gICAgICAgICAgICBpZiAoYml0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5iaXRzW01hdGguZmxvb3IodGhpcy5zaXplIC8gMzIpXSB8PSAxIDw8ICh0aGlzLnNpemUgJiAweDFGKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc2l6ZSsrO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBcHBlbmRzIHRoZSBsZWFzdC1zaWduaWZpY2FudCBiaXRzLCBmcm9tIHZhbHVlLCBpbiBvcmRlciBmcm9tIG1vc3Qtc2lnbmlmaWNhbnQgdG9cbiAgICAgICAgICogbGVhc3Qtc2lnbmlmaWNhbnQuIEZvciBleGFtcGxlLCBhcHBlbmRpbmcgNiBiaXRzIGZyb20gMHgwMDAwMDFFIHdpbGwgYXBwZW5kIHRoZSBiaXRzXG4gICAgICAgICAqIDAsIDEsIDEsIDEsIDEsIDAgaW4gdGhhdCBvcmRlci5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHZhbHVlIHtAY29kZSBpbnR9IGNvbnRhaW5pbmcgYml0cyB0byBhcHBlbmRcbiAgICAgICAgICogQHBhcmFtIG51bUJpdHMgYml0cyBmcm9tIHZhbHVlIHRvIGFwcGVuZFxuICAgICAgICAgKi9cbiAgICAgICAgYXBwZW5kQml0cyh2YWx1ZSAvKmludCovLCBudW1CaXRzIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGlmIChudW1CaXRzIDwgMCB8fCBudW1CaXRzID4gMzIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdOdW0gYml0cyBtdXN0IGJlIGJldHdlZW4gMCBhbmQgMzInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZW5zdXJlQ2FwYWNpdHkodGhpcy5zaXplICsgbnVtQml0cyk7XG4gICAgICAgICAgICAvLyBjb25zdCBhcHBlbmRCaXQgPSB0aGlzLmFwcGVuZEJpdDtcbiAgICAgICAgICAgIGZvciAobGV0IG51bUJpdHNMZWZ0ID0gbnVtQml0czsgbnVtQml0c0xlZnQgPiAwOyBudW1CaXRzTGVmdC0tKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hcHBlbmRCaXQoKCh2YWx1ZSA+PiAobnVtQml0c0xlZnQgLSAxKSkgJiAweDAxKSA9PT0gMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYXBwZW5kQml0QXJyYXkob3RoZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IG90aGVyU2l6ZSA9IG90aGVyLnNpemU7XG4gICAgICAgICAgICB0aGlzLmVuc3VyZUNhcGFjaXR5KHRoaXMuc2l6ZSArIG90aGVyU2l6ZSk7XG4gICAgICAgICAgICAvLyBjb25zdCBhcHBlbmRCaXQgPSB0aGlzLmFwcGVuZEJpdDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3RoZXJTaXplOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFwcGVuZEJpdChvdGhlci5nZXQoaSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHhvcihvdGhlcikge1xuICAgICAgICAgICAgaWYgKHRoaXMuc2l6ZSAhPT0gb3RoZXIuc2l6ZSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ1NpemVzIGRvblxcJ3QgbWF0Y2gnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGJpdHMgPSB0aGlzLmJpdHM7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgbGVuZ3RoID0gYml0cy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIC8vIFRoZSBsYXN0IGludCBjb3VsZCBiZSBpbmNvbXBsZXRlIChpLmUuIG5vdCBoYXZlIDMyIGJpdHMgaW5cbiAgICAgICAgICAgICAgICAvLyBpdCkgYnV0IHRoZXJlIGlzIG5vIHByb2JsZW0gc2luY2UgMCBYT1IgMCA9PSAwLlxuICAgICAgICAgICAgICAgIGJpdHNbaV0gXj0gb3RoZXIuYml0c1tpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGJpdE9mZnNldCBmaXJzdCBiaXQgdG8gc3RhcnQgd3JpdGluZ1xuICAgICAgICAgKiBAcGFyYW0gYXJyYXkgYXJyYXkgdG8gd3JpdGUgaW50by4gQnl0ZXMgYXJlIHdyaXR0ZW4gbW9zdC1zaWduaWZpY2FudCBieXRlIGZpcnN0LiBUaGlzIGlzIHRoZSBvcHBvc2l0ZVxuICAgICAgICAgKiAgb2YgdGhlIGludGVybmFsIHJlcHJlc2VudGF0aW9uLCB3aGljaCBpcyBleHBvc2VkIGJ5IHtAbGluayAjZ2V0Qml0QXJyYXkoKX1cbiAgICAgICAgICogQHBhcmFtIG9mZnNldCBwb3NpdGlvbiBpbiBhcnJheSB0byBzdGFydCB3cml0aW5nXG4gICAgICAgICAqIEBwYXJhbSBudW1CeXRlcyBob3cgbWFueSBieXRlcyB0byB3cml0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdG9CeXRlcyhiaXRPZmZzZXQgLyppbnQqLywgYXJyYXksIG9mZnNldCAvKmludCovLCBudW1CeXRlcyAvKmludCovKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUJ5dGVzOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgdGhlQnl0ZSA9IDA7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCA4OyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZ2V0KGJpdE9mZnNldCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoZUJ5dGUgfD0gMSA8PCAoNyAtIGopO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJpdE9mZnNldCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhcnJheVtvZmZzZXQgKyBpXSA9IC8qKGJ5dGUpKi8gdGhlQnl0ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB1bmRlcmx5aW5nIGFycmF5IG9mIGludHMuIFRoZSBmaXJzdCBlbGVtZW50IGhvbGRzIHRoZSBmaXJzdCAzMiBiaXRzLCBhbmQgdGhlIGxlYXN0XG4gICAgICAgICAqICAgICAgICAgc2lnbmlmaWNhbnQgYml0IGlzIGJpdCAwLlxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0Qml0QXJyYXkoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5iaXRzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXZlcnNlcyBhbGwgYml0cyBpbiB0aGUgYXJyYXkuXG4gICAgICAgICAqL1xuICAgICAgICByZXZlcnNlKCkge1xuICAgICAgICAgICAgY29uc3QgbmV3Qml0cyA9IG5ldyBJbnQzMkFycmF5KHRoaXMuYml0cy5sZW5ndGgpO1xuICAgICAgICAgICAgLy8gcmV2ZXJzZSBhbGwgaW50J3MgZmlyc3RcbiAgICAgICAgICAgIGNvbnN0IGxlbiA9IE1hdGguZmxvb3IoKHRoaXMuc2l6ZSAtIDEpIC8gMzIpO1xuICAgICAgICAgICAgY29uc3Qgb2xkQml0c0xlbiA9IGxlbiArIDE7XG4gICAgICAgICAgICBjb25zdCBiaXRzID0gdGhpcy5iaXRzO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvbGRCaXRzTGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgeCA9IGJpdHNbaV07XG4gICAgICAgICAgICAgICAgeCA9ICgoeCA+PiAxKSAmIDB4NTU1NTU1NTUpIHwgKCh4ICYgMHg1NTU1NTU1NSkgPDwgMSk7XG4gICAgICAgICAgICAgICAgeCA9ICgoeCA+PiAyKSAmIDB4MzMzMzMzMzMpIHwgKCh4ICYgMHgzMzMzMzMzMykgPDwgMik7XG4gICAgICAgICAgICAgICAgeCA9ICgoeCA+PiA0KSAmIDB4MGYwZjBmMGYpIHwgKCh4ICYgMHgwZjBmMGYwZikgPDwgNCk7XG4gICAgICAgICAgICAgICAgeCA9ICgoeCA+PiA4KSAmIDB4MDBmZjAwZmYpIHwgKCh4ICYgMHgwMGZmMDBmZikgPDwgOCk7XG4gICAgICAgICAgICAgICAgeCA9ICgoeCA+PiAxNikgJiAweDAwMDBmZmZmKSB8ICgoeCAmIDB4MDAwMGZmZmYpIDw8IDE2KTtcbiAgICAgICAgICAgICAgICBuZXdCaXRzW2xlbiAtIGldID0gLyooaW50KSovIHg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBub3cgY29ycmVjdCB0aGUgaW50J3MgaWYgdGhlIGJpdCBzaXplIGlzbid0IGEgbXVsdGlwbGUgb2YgMzJcbiAgICAgICAgICAgIGlmICh0aGlzLnNpemUgIT09IG9sZEJpdHNMZW4gKiAzMikge1xuICAgICAgICAgICAgICAgIGNvbnN0IGxlZnRPZmZzZXQgPSBvbGRCaXRzTGVuICogMzIgLSB0aGlzLnNpemU7XG4gICAgICAgICAgICAgICAgbGV0IGN1cnJlbnRJbnQgPSBuZXdCaXRzWzBdID4+PiBsZWZ0T2Zmc2V0O1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgb2xkQml0c0xlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5leHRJbnQgPSBuZXdCaXRzW2ldO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SW50IHw9IG5leHRJbnQgPDwgKDMyIC0gbGVmdE9mZnNldCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld0JpdHNbaSAtIDFdID0gY3VycmVudEludDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEludCA9IG5leHRJbnQgPj4+IGxlZnRPZmZzZXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG5ld0JpdHNbb2xkQml0c0xlbiAtIDFdID0gY3VycmVudEludDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuYml0cyA9IG5ld0JpdHM7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIG1ha2VBcnJheShzaXplIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgSW50MzJBcnJheShNYXRoLmZsb29yKChzaXplICsgMzEpIC8gMzIpKTtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGVxdWFscyhvKSB7XG4gICAgICAgICAgICBpZiAoIShvIGluc3RhbmNlb2YgQml0QXJyYXkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgb3RoZXIgPSBvO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2l6ZSA9PT0gb3RoZXIuc2l6ZSAmJiBBcnJheXMuZXF1YWxzKHRoaXMuYml0cywgb3RoZXIuYml0cyk7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBoYXNoQ29kZSgpIHtcbiAgICAgICAgICAgIHJldHVybiAzMSAqIHRoaXMuc2l6ZSArIEFycmF5cy5oYXNoQ29kZSh0aGlzLmJpdHMpO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gJyc7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgc2l6ZSA9IHRoaXMuc2l6ZTsgaSA8IHNpemU7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICgoaSAmIDB4MDcpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnICc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB0aGlzLmdldChpKSA/ICdYJyA6ICcuJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBjbG9uZSgpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgQml0QXJyYXkodGhpcy5zaXplLCB0aGlzLmJpdHMuc2xpY2UoKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA5IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qbmFtZXNwYWNlIGNvbS5nb29nbGUuenhpbmcgeyovXG4gICAgLyoqXG4gICAgICogRW5jYXBzdWxhdGVzIGEgdHlwZSBvZiBoaW50IHRoYXQgYSBjYWxsZXIgbWF5IHBhc3MgdG8gYSBiYXJjb2RlIHJlYWRlciB0byBoZWxwIGl0XG4gICAgICogbW9yZSBxdWlja2x5IG9yIGFjY3VyYXRlbHkgZGVjb2RlIGl0LiBJdCBpcyB1cCB0byBpbXBsZW1lbnRhdGlvbnMgdG8gZGVjaWRlIHdoYXQsXG4gICAgICogaWYgYW55dGhpbmcsIHRvIGRvIHdpdGggdGhlIGluZm9ybWF0aW9uIHRoYXQgaXMgc3VwcGxpZWQuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pXG4gICAgICogQHNlZSBSZWFkZXIjZGVjb2RlKEJpbmFyeUJpdG1hcCxqYXZhLnV0aWwuTWFwKVxuICAgICAqL1xuICAgIHZhciBEZWNvZGVIaW50VHlwZTtcbiAgICAoZnVuY3Rpb24gKERlY29kZUhpbnRUeXBlKSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBVbnNwZWNpZmllZCwgYXBwbGljYXRpb24tc3BlY2lmaWMgaGludC4gTWFwcyB0byBhbiB1bnNwZWNpZmllZCB7QGxpbmsgT2JqZWN0fS5cbiAgICAgICAgICovXG4gICAgICAgIERlY29kZUhpbnRUeXBlW0RlY29kZUhpbnRUeXBlW1wiT1RIRVJcIl0gPSAwXSA9IFwiT1RIRVJcIjsgLyooT2JqZWN0LmNsYXNzKSovXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJbWFnZSBpcyBhIHB1cmUgbW9ub2Nocm9tZSBpbWFnZSBvZiBhIGJhcmNvZGUuIERvZXNuJ3QgbWF0dGVyIHdoYXQgaXQgbWFwcyB0bztcbiAgICAgICAgICogdXNlIHtAbGluayBCb29sZWFuI1RSVUV9LlxuICAgICAgICAgKi9cbiAgICAgICAgRGVjb2RlSGludFR5cGVbRGVjb2RlSGludFR5cGVbXCJQVVJFX0JBUkNPREVcIl0gPSAxXSA9IFwiUFVSRV9CQVJDT0RFXCI7IC8qKFZvaWQuY2xhc3MpKi9cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEltYWdlIGlzIGtub3duIHRvIGJlIG9mIG9uZSBvZiBhIGZldyBwb3NzaWJsZSBmb3JtYXRzLlxuICAgICAgICAgKiBNYXBzIHRvIGEge0BsaW5rIExpc3R9IG9mIHtAbGluayBCYXJjb2RlRm9ybWF0fXMuXG4gICAgICAgICAqL1xuICAgICAgICBEZWNvZGVIaW50VHlwZVtEZWNvZGVIaW50VHlwZVtcIlBPU1NJQkxFX0ZPUk1BVFNcIl0gPSAyXSA9IFwiUE9TU0lCTEVfRk9STUFUU1wiOyAvKihMaXN0LmNsYXNzKSovXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTcGVuZCBtb3JlIHRpbWUgdG8gdHJ5IHRvIGZpbmQgYSBiYXJjb2RlOyBvcHRpbWl6ZSBmb3IgYWNjdXJhY3ksIG5vdCBzcGVlZC5cbiAgICAgICAgICogRG9lc24ndCBtYXR0ZXIgd2hhdCBpdCBtYXBzIHRvOyB1c2Uge0BsaW5rIEJvb2xlYW4jVFJVRX0uXG4gICAgICAgICAqL1xuICAgICAgICBEZWNvZGVIaW50VHlwZVtEZWNvZGVIaW50VHlwZVtcIlRSWV9IQVJERVJcIl0gPSAzXSA9IFwiVFJZX0hBUkRFUlwiOyAvKihWb2lkLmNsYXNzKSovXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTcGVjaWZpZXMgd2hhdCBjaGFyYWN0ZXIgZW5jb2RpbmcgdG8gdXNlIHdoZW4gZGVjb2RpbmcsIHdoZXJlIGFwcGxpY2FibGUgKHR5cGUgU3RyaW5nKVxuICAgICAgICAgKi9cbiAgICAgICAgRGVjb2RlSGludFR5cGVbRGVjb2RlSGludFR5cGVbXCJDSEFSQUNURVJfU0VUXCJdID0gNF0gPSBcIkNIQVJBQ1RFUl9TRVRcIjsgLyooU3RyaW5nLmNsYXNzKSovXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBbGxvd2VkIGxlbmd0aHMgb2YgZW5jb2RlZCBkYXRhIC0tIHJlamVjdCBhbnl0aGluZyBlbHNlLiBNYXBzIHRvIGFuIHtAY29kZSBJbnQzMkFycmF5fS5cbiAgICAgICAgICovXG4gICAgICAgIERlY29kZUhpbnRUeXBlW0RlY29kZUhpbnRUeXBlW1wiQUxMT1dFRF9MRU5HVEhTXCJdID0gNV0gPSBcIkFMTE9XRURfTEVOR1RIU1wiOyAvKihJbnQzMkFycmF5LmNsYXNzKSovXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBc3N1bWUgQ29kZSAzOSBjb2RlcyBlbXBsb3kgYSBjaGVjayBkaWdpdC4gRG9lc24ndCBtYXR0ZXIgd2hhdCBpdCBtYXBzIHRvO1xuICAgICAgICAgKiB1c2Uge0BsaW5rIEJvb2xlYW4jVFJVRX0uXG4gICAgICAgICAqL1xuICAgICAgICBEZWNvZGVIaW50VHlwZVtEZWNvZGVIaW50VHlwZVtcIkFTU1VNRV9DT0RFXzM5X0NIRUNLX0RJR0lUXCJdID0gNl0gPSBcIkFTU1VNRV9DT0RFXzM5X0NIRUNLX0RJR0lUXCI7IC8qKFZvaWQuY2xhc3MpKi9cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEFzc3VtZSB0aGUgYmFyY29kZSBpcyBiZWluZyBwcm9jZXNzZWQgYXMgYSBHUzEgYmFyY29kZSwgYW5kIG1vZGlmeSBiZWhhdmlvciBhcyBuZWVkZWQuXG4gICAgICAgICAqIEZvciBleGFtcGxlIHRoaXMgYWZmZWN0cyBGTkMxIGhhbmRsaW5nIGZvciBDb2RlIDEyOCAoYWthIEdTMS0xMjgpLiBEb2Vzbid0IG1hdHRlciB3aGF0IGl0IG1hcHMgdG87XG4gICAgICAgICAqIHVzZSB7QGxpbmsgQm9vbGVhbiNUUlVFfS5cbiAgICAgICAgICovXG4gICAgICAgIERlY29kZUhpbnRUeXBlW0RlY29kZUhpbnRUeXBlW1wiQVNTVU1FX0dTMVwiXSA9IDddID0gXCJBU1NVTUVfR1MxXCI7IC8qKFZvaWQuY2xhc3MpKi9cbiAgICAgICAgLyoqXG4gICAgICAgICAqIElmIHRydWUsIHJldHVybiB0aGUgc3RhcnQgYW5kIGVuZCBkaWdpdHMgaW4gYSBDb2RhYmFyIGJhcmNvZGUgaW5zdGVhZCBvZiBzdHJpcHBpbmcgdGhlbS4gVGhleVxuICAgICAgICAgKiBhcmUgYWxwaGEsIHdoZXJlYXMgdGhlIHJlc3QgYXJlIG51bWVyaWMuIEJ5IGRlZmF1bHQsIHRoZXkgYXJlIHN0cmlwcGVkLCBidXQgdGhpcyBjYXVzZXMgdGhlbVxuICAgICAgICAgKiB0byBub3QgYmUuIERvZXNuJ3QgbWF0dGVyIHdoYXQgaXQgbWFwcyB0bzsgdXNlIHtAbGluayBCb29sZWFuI1RSVUV9LlxuICAgICAgICAgKi9cbiAgICAgICAgRGVjb2RlSGludFR5cGVbRGVjb2RlSGludFR5cGVbXCJSRVRVUk5fQ09EQUJBUl9TVEFSVF9FTkRcIl0gPSA4XSA9IFwiUkVUVVJOX0NPREFCQVJfU1RBUlRfRU5EXCI7IC8qKFZvaWQuY2xhc3MpKi9cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoZSBjYWxsZXIgbmVlZHMgdG8gYmUgbm90aWZpZWQgdmlhIGNhbGxiYWNrIHdoZW4gYSBwb3NzaWJsZSB7QGxpbmsgUmVzdWx0UG9pbnR9XG4gICAgICAgICAqIGlzIGZvdW5kLiBNYXBzIHRvIGEge0BsaW5rIFJlc3VsdFBvaW50Q2FsbGJhY2t9LlxuICAgICAgICAgKi9cbiAgICAgICAgRGVjb2RlSGludFR5cGVbRGVjb2RlSGludFR5cGVbXCJORUVEX1JFU1VMVF9QT0lOVF9DQUxMQkFDS1wiXSA9IDldID0gXCJORUVEX1JFU1VMVF9QT0lOVF9DQUxMQkFDS1wiOyAvKihSZXN1bHRQb2ludENhbGxiYWNrLmNsYXNzKSovXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBbGxvd2VkIGV4dGVuc2lvbiBsZW5ndGhzIGZvciBFQU4gb3IgVVBDIGJhcmNvZGVzLiBPdGhlciBmb3JtYXRzIHdpbGwgaWdub3JlIHRoaXMuXG4gICAgICAgICAqIE1hcHMgdG8gYW4ge0Bjb2RlIEludDMyQXJyYXl9IG9mIHRoZSBhbGxvd2VkIGV4dGVuc2lvbiBsZW5ndGhzLCBmb3IgZXhhbXBsZSBbMl0sIFs1XSwgb3IgWzIsIDVdLlxuICAgICAgICAgKiBJZiBpdCBpcyBvcHRpb25hbCB0byBoYXZlIGFuIGV4dGVuc2lvbiwgZG8gbm90IHNldCB0aGlzIGhpbnQuIElmIHRoaXMgaXMgc2V0LFxuICAgICAgICAgKiBhbmQgYSBVUEMgb3IgRUFOIGJhcmNvZGUgaXMgZm91bmQgYnV0IGFuIGV4dGVuc2lvbiBpcyBub3QsIHRoZW4gbm8gcmVzdWx0IHdpbGwgYmUgcmV0dXJuZWRcbiAgICAgICAgICogYXQgYWxsLlxuICAgICAgICAgKi9cbiAgICAgICAgRGVjb2RlSGludFR5cGVbRGVjb2RlSGludFR5cGVbXCJBTExPV0VEX0VBTl9FWFRFTlNJT05TXCJdID0gMTBdID0gXCJBTExPV0VEX0VBTl9FWFRFTlNJT05TXCI7IC8qKEludDMyQXJyYXkuY2xhc3MpKi9cbiAgICAgICAgLy8gRW5kIG9mIGVudW1lcmF0aW9uIHZhbHVlcy5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERhdGEgdHlwZSB0aGUgaGludCBpcyBleHBlY3RpbmcuXG4gICAgICAgICAqIEFtb25nIHRoZSBwb3NzaWJsZSB2YWx1ZXMgdGhlIHtAbGluayBWb2lkfSBzdGFuZHMgb3V0IGFzIGJlaW5nIHVzZWQgZm9yXG4gICAgICAgICAqIGhpbnRzIHRoYXQgZG8gbm90IGV4cGVjdCBhIHZhbHVlIHRvIGJlIHN1cHBsaWVkIChmbGFnIGhpbnRzKS4gU3VjaCBoaW50c1xuICAgICAgICAgKiB3aWxsIHBvc3NpYmx5IGhhdmUgdGhlaXIgdmFsdWUgaWdub3JlZCwgb3IgcmVwbGFjZWQgYnkgYVxuICAgICAgICAgKiB7QGxpbmsgQm9vbGVhbiNUUlVFfS4gSGludCBzdXBwbGllcnMgc2hvdWxkIHByb2JhYmx5IHVzZVxuICAgICAgICAgKiB7QGxpbmsgQm9vbGVhbiNUUlVFfSBhcyBkaXJlY3RlZCBieSB0aGUgYWN0dWFsIGhpbnQgZG9jdW1lbnRhdGlvbi5cbiAgICAgICAgICovXG4gICAgICAgIC8vIHByaXZhdGUgdmFsdWVUeXBlOiBDbGFzczw/PlxuICAgICAgICAvLyBEZWNvZGVIaW50VHlwZSh2YWx1ZVR5cGU6IENsYXNzPD8+KSB7XG4gICAgICAgIC8vICAgdGhpcy52YWx1ZVR5cGUgPSB2YWx1ZVR5cGVcbiAgICAgICAgLy8gfVxuICAgICAgICAvLyBwdWJsaWMgZ2V0VmFsdWVUeXBlKCk6IENsYXNzPD8+IHtcbiAgICAgICAgLy8gICByZXR1cm4gdmFsdWVUeXBlXG4gICAgICAgIC8vIH1cbiAgICB9KShEZWNvZGVIaW50VHlwZSB8fCAoRGVjb2RlSGludFR5cGUgPSB7fSkpO1xuICAgIHZhciBEZWNvZGVIaW50VHlwZSQxID0gRGVjb2RlSGludFR5cGU7XG5cbiAgICAvKipcbiAgICAgKiBDdXN0b20gRXJyb3IgY2xhc3Mgb2YgdHlwZSBFeGNlcHRpb24uXG4gICAgICovXG4gICAgY2xhc3MgRm9ybWF0RXhjZXB0aW9uIGV4dGVuZHMgRXhjZXB0aW9uIHtcbiAgICAgICAgc3RhdGljIGdldEZvcm1hdEluc3RhbmNlKCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBGb3JtYXRFeGNlcHRpb24ua2luZCA9ICdGb3JtYXRFeGNlcHRpb24nO1xuXG4gICAgLyppbXBvcnQgamF2YS51dGlsLkhhc2hNYXA7Ki9cbiAgICAvKmltcG9ydCBqYXZhLnV0aWwuTWFwOyovXG4gICAgdmFyIENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnM7XG4gICAgKGZ1bmN0aW9uIChDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzKSB7XG4gICAgICAgIENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tcIkNwNDM3XCJdID0gMF0gPSBcIkNwNDM3XCI7XG4gICAgICAgIENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tcIklTTzg4NTlfMVwiXSA9IDFdID0gXCJJU084ODU5XzFcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiSVNPODg1OV8yXCJdID0gMl0gPSBcIklTTzg4NTlfMlwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJJU084ODU5XzNcIl0gPSAzXSA9IFwiSVNPODg1OV8zXCI7XG4gICAgICAgIENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tcIklTTzg4NTlfNFwiXSA9IDRdID0gXCJJU084ODU5XzRcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiSVNPODg1OV81XCJdID0gNV0gPSBcIklTTzg4NTlfNVwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJJU084ODU5XzZcIl0gPSA2XSA9IFwiSVNPODg1OV82XCI7XG4gICAgICAgIENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tcIklTTzg4NTlfN1wiXSA9IDddID0gXCJJU084ODU5XzdcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiSVNPODg1OV84XCJdID0gOF0gPSBcIklTTzg4NTlfOFwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJJU084ODU5XzlcIl0gPSA5XSA9IFwiSVNPODg1OV85XCI7XG4gICAgICAgIENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tcIklTTzg4NTlfMTBcIl0gPSAxMF0gPSBcIklTTzg4NTlfMTBcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiSVNPODg1OV8xMVwiXSA9IDExXSA9IFwiSVNPODg1OV8xMVwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJJU084ODU5XzEzXCJdID0gMTJdID0gXCJJU084ODU5XzEzXCI7XG4gICAgICAgIENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tcIklTTzg4NTlfMTRcIl0gPSAxM10gPSBcIklTTzg4NTlfMTRcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiSVNPODg1OV8xNVwiXSA9IDE0XSA9IFwiSVNPODg1OV8xNVwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJJU084ODU5XzE2XCJdID0gMTVdID0gXCJJU084ODU5XzE2XCI7XG4gICAgICAgIENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tcIlNKSVNcIl0gPSAxNl0gPSBcIlNKSVNcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiQ3AxMjUwXCJdID0gMTddID0gXCJDcDEyNTBcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiQ3AxMjUxXCJdID0gMThdID0gXCJDcDEyNTFcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiQ3AxMjUyXCJdID0gMTldID0gXCJDcDEyNTJcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiQ3AxMjU2XCJdID0gMjBdID0gXCJDcDEyNTZcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiVW5pY29kZUJpZ1VubWFya2VkXCJdID0gMjFdID0gXCJVbmljb2RlQmlnVW5tYXJrZWRcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiVVRGOFwiXSA9IDIyXSA9IFwiVVRGOFwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJBU0NJSVwiXSA9IDIzXSA9IFwiQVNDSUlcIjtcbiAgICAgICAgQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW1wiQmlnNVwiXSA9IDI0XSA9IFwiQmlnNVwiO1xuICAgICAgICBDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzW0NoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbXCJHQjE4MDMwXCJdID0gMjVdID0gXCJHQjE4MDMwXCI7XG4gICAgICAgIENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnNbQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVyc1tcIkVVQ19LUlwiXSA9IDI2XSA9IFwiRVVDX0tSXCI7XG4gICAgfSkoQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycyB8fCAoQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycyA9IHt9KSk7XG4gICAgLyoqXG4gICAgICogRW5jYXBzdWxhdGVzIGEgQ2hhcmFjdGVyIFNldCBFQ0ksIGFjY29yZGluZyB0byBcIkV4dGVuZGVkIENoYW5uZWwgSW50ZXJwcmV0YXRpb25zXCIgNS4zLjEuMVxuICAgICAqIG9mIElTTyAxODAwNC5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgQ2hhcmFjdGVyU2V0RUNJIHtcbiAgICAgICAgY29uc3RydWN0b3IodmFsdWVJZGVudGlmaWVyLCB2YWx1ZXNQYXJhbSwgbmFtZSwgLi4ub3RoZXJFbmNvZGluZ05hbWVzKSB7XG4gICAgICAgICAgICB0aGlzLnZhbHVlSWRlbnRpZmllciA9IHZhbHVlSWRlbnRpZmllcjtcbiAgICAgICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlc1BhcmFtID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgICAgIHRoaXMudmFsdWVzID0gSW50MzJBcnJheS5mcm9tKFt2YWx1ZXNQYXJhbV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZXMgPSB2YWx1ZXNQYXJhbTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMub3RoZXJFbmNvZGluZ05hbWVzID0gb3RoZXJFbmNvZGluZ05hbWVzO1xuICAgICAgICAgICAgQ2hhcmFjdGVyU2V0RUNJLlZBTFVFX0lERU5USUZJRVJfVE9fRUNJLnNldCh2YWx1ZUlkZW50aWZpZXIsIHRoaXMpO1xuICAgICAgICAgICAgQ2hhcmFjdGVyU2V0RUNJLk5BTUVfVE9fRUNJLnNldChuYW1lLCB0aGlzKTtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlcyA9IHRoaXMudmFsdWVzO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGxlbmd0aCA9IHZhbHVlcy5sZW5ndGg7IGkgIT09IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdiA9IHZhbHVlc1tpXTtcbiAgICAgICAgICAgICAgICBDaGFyYWN0ZXJTZXRFQ0kuVkFMVUVTX1RPX0VDSS5zZXQodiwgdGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGNvbnN0IG90aGVyTmFtZSBvZiBvdGhlckVuY29kaW5nTmFtZXMpIHtcbiAgICAgICAgICAgICAgICBDaGFyYWN0ZXJTZXRFQ0kuTkFNRV9UT19FQ0kuc2V0KG90aGVyTmFtZSwgdGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ2hhcmFjdGVyU2V0RUNJKHZhbHVlOiBudW1iZXIgLyppbnQqLykge1xuICAgICAgICAvLyAgIHRoaXMobmV3IEludDMyQXJyYXkge3ZhbHVlfSlcbiAgICAgICAgLy8gfVxuICAgICAgICAvLyBDaGFyYWN0ZXJTZXRFQ0kodmFsdWU6IG51bWJlciAvKmludCovLCBTdHJpbmcuLi4gb3RoZXJFbmNvZGluZ05hbWVzKSB7XG4gICAgICAgIC8vICAgdGhpcy52YWx1ZXMgPSBuZXcgSW50MzJBcnJheSB7dmFsdWV9XG4gICAgICAgIC8vICAgdGhpcy5vdGhlckVuY29kaW5nTmFtZXMgPSBvdGhlckVuY29kaW5nTmFtZXNcbiAgICAgICAgLy8gfVxuICAgICAgICAvLyBDaGFyYWN0ZXJTZXRFQ0kodmFsdWVzOiBJbnQzMkFycmF5LCBTdHJpbmcuLi4gb3RoZXJFbmNvZGluZ05hbWVzKSB7XG4gICAgICAgIC8vICAgdGhpcy52YWx1ZXMgPSB2YWx1ZXNcbiAgICAgICAgLy8gICB0aGlzLm90aGVyRW5jb2RpbmdOYW1lcyA9IG90aGVyRW5jb2RpbmdOYW1lc1xuICAgICAgICAvLyB9XG4gICAgICAgIGdldFZhbHVlSWRlbnRpZmllcigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlSWRlbnRpZmllcjtcbiAgICAgICAgfVxuICAgICAgICBnZXROYW1lKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubmFtZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRWYWx1ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlc1swXTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHZhbHVlIGNoYXJhY3RlciBzZXQgRUNJIHZhbHVlXG4gICAgICAgICAqIEByZXR1cm4ge0Bjb2RlIENoYXJhY3RlclNldEVDSX0gcmVwcmVzZW50aW5nIEVDSSBvZiBnaXZlbiB2YWx1ZSwgb3IgbnVsbCBpZiBpdCBpcyBsZWdhbCBidXRcbiAgICAgICAgICogICB1bnN1cHBvcnRlZFxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvbiBpZiBFQ0kgdmFsdWUgaXMgaW52YWxpZFxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGdldENoYXJhY3RlclNldEVDSUJ5VmFsdWUodmFsdWUgLyppbnQqLykge1xuICAgICAgICAgICAgaWYgKHZhbHVlIDwgMCB8fCB2YWx1ZSA+PSA5MDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCdpbmNvcmVjdCB2YWx1ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgY2hhcmFjdGVyU2V0ID0gQ2hhcmFjdGVyU2V0RUNJLlZBTFVFU19UT19FQ0kuZ2V0KHZhbHVlKTtcbiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IGNoYXJhY3RlclNldCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oJ2luY29yZWN0IHZhbHVlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY2hhcmFjdGVyU2V0O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gbmFtZSBjaGFyYWN0ZXIgc2V0IEVDSSBlbmNvZGluZyBuYW1lXG4gICAgICAgICAqIEByZXR1cm4gQ2hhcmFjdGVyU2V0RUNJIHJlcHJlc2VudGluZyBFQ0kgZm9yIGNoYXJhY3RlciBlbmNvZGluZywgb3IgbnVsbCBpZiBpdCBpcyBsZWdhbFxuICAgICAgICAgKiAgIGJ1dCB1bnN1cHBvcnRlZFxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGdldENoYXJhY3RlclNldEVDSUJ5TmFtZShuYW1lKSB7XG4gICAgICAgICAgICBjb25zdCBjaGFyYWN0ZXJTZXQgPSBDaGFyYWN0ZXJTZXRFQ0kuTkFNRV9UT19FQ0kuZ2V0KG5hbWUpO1xuICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCA9PT0gY2hhcmFjdGVyU2V0KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbignaW5jb3JlY3QgdmFsdWUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBjaGFyYWN0ZXJTZXQ7XG4gICAgICAgIH1cbiAgICAgICAgZXF1YWxzKG8pIHtcbiAgICAgICAgICAgIGlmICghKG8gaW5zdGFuY2VvZiBDaGFyYWN0ZXJTZXRFQ0kpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgb3RoZXIgPSBvO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TmFtZSgpID09PSBvdGhlci5nZXROYW1lKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgQ2hhcmFjdGVyU2V0RUNJLlZBTFVFX0lERU5USUZJRVJfVE9fRUNJID0gbmV3IE1hcCgpO1xuICAgIENoYXJhY3RlclNldEVDSS5WQUxVRVNfVE9fRUNJID0gbmV3IE1hcCgpO1xuICAgIENoYXJhY3RlclNldEVDSS5OQU1FX1RPX0VDSSA9IG5ldyBNYXAoKTtcbiAgICAvLyBFbnVtIG5hbWUgaXMgYSBKYXZhIGVuY29kaW5nIHZhbGlkIGZvciBqYXZhLmxhbmcgYW5kIGphdmEuaW9cbiAgICAvLyBUWVBFU0NSSVBUUE9SVDogY2hhbmdlZCB0aGUgbWFpbiBsYWJlbCBmb3IgSVNPIGFzIHRoZSBUZXh0RW5jb2RlciBkaWQgbm90IHJlY29nbml6ZWQgdGhlbSBpbiB0aGUgZm9ybSBmcm9tIGphdmFcbiAgICAvLyAoZWcgSVNPODg1OV8xIG11c3QgYmUgSVNPODg1OTEgb3IgSVNPODg1OS0xIG9yIElTTy04ODU5LTEpXG4gICAgLy8gbGF0ZXIgb246IHdlbGwsIGV4Y2VwdCAxNiB3aWNoIGRvZXMgbm90IHdvcmsgd2l0aCBJU084ODU5MTYgc28gdXNlZCBJU08tODg1OS0xIGZvcm0gZm9yIGRlZmF1bHRcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuQ3A0MzcgPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuQ3A0MzcsIEludDMyQXJyYXkuZnJvbShbMCwgMl0pLCAnQ3A0MzcnKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuSVNPODg1OV8xID0gbmV3IENoYXJhY3RlclNldEVDSShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzLklTTzg4NTlfMSwgSW50MzJBcnJheS5mcm9tKFsxLCAzXSksICdJU08tODg1OS0xJywgJ0lTTzg4NTkxJywgJ0lTTzg4NTlfMScpO1xuICAgIENoYXJhY3RlclNldEVDSS5JU084ODU5XzIgPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuSVNPODg1OV8yLCA0LCAnSVNPLTg4NTktMicsICdJU084ODU5MicsICdJU084ODU5XzInKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuSVNPODg1OV8zID0gbmV3IENoYXJhY3RlclNldEVDSShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzLklTTzg4NTlfMywgNSwgJ0lTTy04ODU5LTMnLCAnSVNPODg1OTMnLCAnSVNPODg1OV8zJyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLklTTzg4NTlfNCA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5JU084ODU5XzQsIDYsICdJU08tODg1OS00JywgJ0lTTzg4NTk0JywgJ0lTTzg4NTlfNCcpO1xuICAgIENoYXJhY3RlclNldEVDSS5JU084ODU5XzUgPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuSVNPODg1OV81LCA3LCAnSVNPLTg4NTktNScsICdJU084ODU5NScsICdJU084ODU5XzUnKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuSVNPODg1OV82ID0gbmV3IENoYXJhY3RlclNldEVDSShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzLklTTzg4NTlfNiwgOCwgJ0lTTy04ODU5LTYnLCAnSVNPODg1OTYnLCAnSVNPODg1OV82Jyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLklTTzg4NTlfNyA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5JU084ODU5XzcsIDksICdJU08tODg1OS03JywgJ0lTTzg4NTk3JywgJ0lTTzg4NTlfNycpO1xuICAgIENoYXJhY3RlclNldEVDSS5JU084ODU5XzggPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuSVNPODg1OV84LCAxMCwgJ0lTTy04ODU5LTgnLCAnSVNPODg1OTgnLCAnSVNPODg1OV84Jyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLklTTzg4NTlfOSA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5JU084ODU5XzksIDExLCAnSVNPLTg4NTktOScsICdJU084ODU5OScsICdJU084ODU5XzknKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuSVNPODg1OV8xMCA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5JU084ODU5XzEwLCAxMiwgJ0lTTy04ODU5LTEwJywgJ0lTTzg4NTkxMCcsICdJU084ODU5XzEwJyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLklTTzg4NTlfMTEgPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuSVNPODg1OV8xMSwgMTMsICdJU08tODg1OS0xMScsICdJU084ODU5MTEnLCAnSVNPODg1OV8xMScpO1xuICAgIENoYXJhY3RlclNldEVDSS5JU084ODU5XzEzID0gbmV3IENoYXJhY3RlclNldEVDSShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzLklTTzg4NTlfMTMsIDE1LCAnSVNPLTg4NTktMTMnLCAnSVNPODg1OTEzJywgJ0lTTzg4NTlfMTMnKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuSVNPODg1OV8xNCA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5JU084ODU5XzE0LCAxNiwgJ0lTTy04ODU5LTE0JywgJ0lTTzg4NTkxNCcsICdJU084ODU5XzE0Jyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLklTTzg4NTlfMTUgPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuSVNPODg1OV8xNSwgMTcsICdJU08tODg1OS0xNScsICdJU084ODU5MTUnLCAnSVNPODg1OV8xNScpO1xuICAgIENoYXJhY3RlclNldEVDSS5JU084ODU5XzE2ID0gbmV3IENoYXJhY3RlclNldEVDSShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzLklTTzg4NTlfMTYsIDE4LCAnSVNPLTg4NTktMTYnLCAnSVNPODg1OTE2JywgJ0lTTzg4NTlfMTYnKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuU0pJUyA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5TSklTLCAyMCwgJ1NKSVMnLCAnU2hpZnRfSklTJyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLkNwMTI1MCA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5DcDEyNTAsIDIxLCAnQ3AxMjUwJywgJ3dpbmRvd3MtMTI1MCcpO1xuICAgIENoYXJhY3RlclNldEVDSS5DcDEyNTEgPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuQ3AxMjUxLCAyMiwgJ0NwMTI1MScsICd3aW5kb3dzLTEyNTEnKTtcbiAgICBDaGFyYWN0ZXJTZXRFQ0kuQ3AxMjUyID0gbmV3IENoYXJhY3RlclNldEVDSShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzLkNwMTI1MiwgMjMsICdDcDEyNTInLCAnd2luZG93cy0xMjUyJyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLkNwMTI1NiA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5DcDEyNTYsIDI0LCAnQ3AxMjU2JywgJ3dpbmRvd3MtMTI1NicpO1xuICAgIENoYXJhY3RlclNldEVDSS5Vbmljb2RlQmlnVW5tYXJrZWQgPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuVW5pY29kZUJpZ1VubWFya2VkLCAyNSwgJ1VuaWNvZGVCaWdVbm1hcmtlZCcsICdVVEYtMTZCRScsICdVbmljb2RlQmlnJyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLlVURjggPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuVVRGOCwgMjYsICdVVEY4JywgJ1VURi04Jyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLkFTQ0lJID0gbmV3IENoYXJhY3RlclNldEVDSShDaGFyYWN0ZXJTZXRWYWx1ZUlkZW50aWZpZXJzLkFTQ0lJLCBJbnQzMkFycmF5LmZyb20oWzI3LCAxNzBdKSwgJ0FTQ0lJJywgJ1VTLUFTQ0lJJyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLkJpZzUgPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuQmlnNSwgMjgsICdCaWc1Jyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLkdCMTgwMzAgPSBuZXcgQ2hhcmFjdGVyU2V0RUNJKENoYXJhY3RlclNldFZhbHVlSWRlbnRpZmllcnMuR0IxODAzMCwgMjksICdHQjE4MDMwJywgJ0dCMjMxMicsICdFVUNfQ04nLCAnR0JLJyk7XG4gICAgQ2hhcmFjdGVyU2V0RUNJLkVVQ19LUiA9IG5ldyBDaGFyYWN0ZXJTZXRFQ0koQ2hhcmFjdGVyU2V0VmFsdWVJZGVudGlmaWVycy5FVUNfS1IsIDMwLCAnRVVDX0tSJywgJ0VVQy1LUicpO1xuXG4gICAgLyoqXG4gICAgICogQ3VzdG9tIEVycm9yIGNsYXNzIG9mIHR5cGUgRXhjZXB0aW9uLlxuICAgICAqL1xuICAgIGNsYXNzIFVuc3VwcG9ydGVkT3BlcmF0aW9uRXhjZXB0aW9uIGV4dGVuZHMgRXhjZXB0aW9uIHtcbiAgICB9XG4gICAgVW5zdXBwb3J0ZWRPcGVyYXRpb25FeGNlcHRpb24ua2luZCA9ICdVbnN1cHBvcnRlZE9wZXJhdGlvbkV4Y2VwdGlvbic7XG5cbiAgICAvKipcbiAgICAgKiBSZXNwb25zaWJsZSBmb3IgZW4vZGVjb2Rpbmcgc3RyaW5ncy5cbiAgICAgKi9cbiAgICBjbGFzcyBTdHJpbmdFbmNvZGluZyB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIHNvbWUgVWludDhBcnJheSB0byBhIHN0cmluZyBmb3JtYXQuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGVjb2RlKGJ5dGVzLCBlbmNvZGluZykge1xuICAgICAgICAgICAgY29uc3QgZW5jb2RpbmdOYW1lID0gdGhpcy5lbmNvZGluZ05hbWUoZW5jb2RpbmcpO1xuICAgICAgICAgICAgaWYgKHRoaXMuY3VzdG9tRGVjb2Rlcikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmN1c3RvbURlY29kZXIoYnl0ZXMsIGVuY29kaW5nTmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBJbmNyZWFzZXMgYnJvd3NlciBzdXBwb3J0LlxuICAgICAgICAgICAgaWYgKHR5cGVvZiBUZXh0RGVjb2RlciA9PT0gJ3VuZGVmaW5lZCcgfHwgdGhpcy5zaG91bGREZWNvZGVPbkZhbGxiYWNrKGVuY29kaW5nTmFtZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGVGYWxsYmFjayhieXRlcywgZW5jb2RpbmdOYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgVGV4dERlY29kZXIoZW5jb2RpbmdOYW1lKS5kZWNvZGUoYnl0ZXMpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDaGVja3MgaWYgdGhlIGRlY29kaW5nIG1ldGhvZCBzaG91bGQgdXNlIHRoZSBmYWxsYmFjayBmb3IgZGVjb2RpbmdcbiAgICAgICAgICogb25jZSBOb2RlIFRleHREZWNvZGVyIGRvZXNuJ3Qgc3VwcG9ydCBhbGwgZW5jb2RpbmcgZm9ybWF0cy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGVuY29kaW5nTmFtZVxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIHNob3VsZERlY29kZU9uRmFsbGJhY2soZW5jb2RpbmdOYW1lKSB7XG4gICAgICAgICAgICByZXR1cm4gIVN0cmluZ0VuY29kaW5nLmlzQnJvd3NlcigpICYmIGVuY29kaW5nTmFtZSA9PT0gJ0lTTy04ODU5LTEnO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbmNvZGVzIHNvbWUgc3RyaW5nIGludG8gYSBVaW50OEFycmF5LlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGVuY29kZShzLCBlbmNvZGluZykge1xuICAgICAgICAgICAgY29uc3QgZW5jb2RpbmdOYW1lID0gdGhpcy5lbmNvZGluZ05hbWUoZW5jb2RpbmcpO1xuICAgICAgICAgICAgaWYgKHRoaXMuY3VzdG9tRW5jb2Rlcikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmN1c3RvbUVuY29kZXIocywgZW5jb2RpbmdOYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEluY3JlYXNlcyBicm93c2VyIHN1cHBvcnQuXG4gICAgICAgICAgICBpZiAodHlwZW9mIFRleHRFbmNvZGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmVuY29kZUZhbGxiYWNrKHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gVGV4dEVuY29kZXIgb25seSBlbmNvZGVzIHRvIFVURjggYnkgZGVmYXVsdCBhcyBzcGVjaWZpZWQgYnkgZW5jb2Rpbmcuc3BlYy53aGF0d2cub3JnXG4gICAgICAgICAgICByZXR1cm4gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHMpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBpc0Jyb3dzZXIoKSB7XG4gICAgICAgICAgICByZXR1cm4gKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHt9LnRvU3RyaW5nLmNhbGwod2luZG93KSA9PT0gJ1tvYmplY3QgV2luZG93XScpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXR1cm5zIHRoZSBzdHJpbmcgdmFsdWUgZnJvbSBzb21lIGVuY29kaW5nIGNoYXJhY3RlciBzZXQuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZW5jb2RpbmdOYW1lKGVuY29kaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gdHlwZW9mIGVuY29kaW5nID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgICAgID8gZW5jb2RpbmdcbiAgICAgICAgICAgICAgICA6IGVuY29kaW5nLmdldE5hbWUoKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogUmV0dXJucyBjaGFyYWN0ZXIgc2V0IGZyb20gc29tZSBlbmNvZGluZyBjaGFyYWN0ZXIgc2V0LlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGVuY29kaW5nQ2hhcmFjdGVyU2V0KGVuY29kaW5nKSB7XG4gICAgICAgICAgICBpZiAoZW5jb2RpbmcgaW5zdGFuY2VvZiBDaGFyYWN0ZXJTZXRFQ0kpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZW5jb2Rpbmc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gQ2hhcmFjdGVyU2V0RUNJLmdldENoYXJhY3RlclNldEVDSUJ5TmFtZShlbmNvZGluZyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJ1bnMgYSBmYWxsYmFjayBmb3IgdGhlIG5hdGl2ZSBkZWNvZGluZyBmdW5jaW9uLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGRlY29kZUZhbGxiYWNrKGJ5dGVzLCBlbmNvZGluZykge1xuICAgICAgICAgICAgY29uc3QgY2hhcmFjdGVyU2V0ID0gdGhpcy5lbmNvZGluZ0NoYXJhY3RlclNldChlbmNvZGluZyk7XG4gICAgICAgICAgICBpZiAoU3RyaW5nRW5jb2RpbmcuaXNEZWNvZGVGYWxsYmFja1N1cHBvcnRlZChjaGFyYWN0ZXJTZXQpKSB7XG4gICAgICAgICAgICAgICAgbGV0IHMgPSAnJztcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgbGVuZ3RoID0gYnl0ZXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGggPSBieXRlc1tpXS50b1N0cmluZygxNik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChoLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGggPSAnMCcgKyBoO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHMgKz0gJyUnICsgaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjaGFyYWN0ZXJTZXQuZXF1YWxzKENoYXJhY3RlclNldEVDSS5Vbmljb2RlQmlnVW5tYXJrZWQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgbmV3IFVpbnQxNkFycmF5KGJ5dGVzLmJ1ZmZlcikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkT3BlcmF0aW9uRXhjZXB0aW9uKGBFbmNvZGluZyAke3RoaXMuZW5jb2RpbmdOYW1lKGVuY29kaW5nKX0gbm90IHN1cHBvcnRlZCBieSBmYWxsYmFjay5gKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgaXNEZWNvZGVGYWxsYmFja1N1cHBvcnRlZChjaGFyYWN0ZXJTZXQpIHtcbiAgICAgICAgICAgIHJldHVybiBjaGFyYWN0ZXJTZXQuZXF1YWxzKENoYXJhY3RlclNldEVDSS5VVEY4KSB8fFxuICAgICAgICAgICAgICAgIGNoYXJhY3RlclNldC5lcXVhbHMoQ2hhcmFjdGVyU2V0RUNJLklTTzg4NTlfMSkgfHxcbiAgICAgICAgICAgICAgICBjaGFyYWN0ZXJTZXQuZXF1YWxzKENoYXJhY3RlclNldEVDSS5BU0NJSSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJ1bnMgYSBmYWxsYmFjayBmb3IgdGhlIG5hdGl2ZSBlbmNvZGluZyBmdW5jaW9uLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAc2VlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8xNzE5Mjg0NS80MzY3NjgzXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZW5jb2RlRmFsbGJhY2socykge1xuICAgICAgICAgICAgY29uc3QgZW5jb2RlZFVSSXN0cmluZyA9IGJ0b2EodW5lc2NhcGUoZW5jb2RlVVJJQ29tcG9uZW50KHMpKSk7XG4gICAgICAgICAgICBjb25zdCBjaGFyTGlzdCA9IGVuY29kZWRVUklzdHJpbmcuc3BsaXQoJycpO1xuICAgICAgICAgICAgY29uc3QgdWludEFycmF5ID0gW107XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNoYXJMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdWludEFycmF5LnB1c2goY2hhckxpc3RbaV0uY2hhckNvZGVBdCgwKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkodWludEFycmF5KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IChDKSAyMDEwIFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIENvbW1vbiBzdHJpbmctcmVsYXRlZCBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqIEBhdXRob3IgQWxleCBEdXByZVxuICAgICAqL1xuICAgIGNsYXNzIFN0cmluZ1V0aWxzIHtcbiAgICAgICAgLy8gU0hJRlRfSklTLmVxdWFsc0lnbm9yZUNhc2UoUExBVEZPUk1fREVGQVVMVF9FTkNPRElORykgfHxcbiAgICAgICAgLy8gRVVDX0pQLmVxdWFsc0lnbm9yZUNhc2UoUExBVEZPUk1fREVGQVVMVF9FTkNPRElORyk7XG4gICAgICAgIHN0YXRpYyBjYXN0QXNOb25VdGY4Q2hhcihjb2RlLCBlbmNvZGluZyA9IG51bGwpIHtcbiAgICAgICAgICAgIC8vIElTTyA4ODU5LTEgaXMgdGhlIEphdmEgZGVmYXVsdCBhcyBVVEYtOCBpcyBKYXZhU2NyaXB0c1xuICAgICAgICAgICAgLy8geW91IGNhbiBzZWUgdGhpcyBtZXRob2QgYXMgYSBKYXZhIHZlcnNpb24gb2YgU3RyaW5nLmZyb21DaGFyQ29kZVxuICAgICAgICAgICAgY29uc3QgZSA9IGVuY29kaW5nID8gZW5jb2RpbmcuZ2V0TmFtZSgpIDogdGhpcy5JU084ODU5MTtcbiAgICAgICAgICAgIC8vIHVzZSBwYXNzZWQgZm9ybWF0IChmcm9tQ2hhckNvZGUgd2lsbCByZXR1cm4gVVRGOCBlbmNvZGluZylcbiAgICAgICAgICAgIHJldHVybiBTdHJpbmdFbmNvZGluZy5kZWNvZGUobmV3IFVpbnQ4QXJyYXkoW2NvZGVdKSwgZSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBieXRlcyBieXRlcyBlbmNvZGluZyBhIHN0cmluZywgd2hvc2UgZW5jb2Rpbmcgc2hvdWxkIGJlIGd1ZXNzZWRcbiAgICAgICAgICogQHBhcmFtIGhpbnRzIGRlY29kZSBoaW50cyBpZiBhcHBsaWNhYmxlXG4gICAgICAgICAqIEByZXR1cm4gbmFtZSBvZiBndWVzc2VkIGVuY29kaW5nOyBhdCB0aGUgbW9tZW50IHdpbGwgb25seSBndWVzcyBvbmUgb2Y6XG4gICAgICAgICAqICB7QGxpbmsgI1NISUZUX0pJU30sIHtAbGluayAjVVRGOH0sIHtAbGluayAjSVNPODg1OTF9LCBvciB0aGUgcGxhdGZvcm1cbiAgICAgICAgICogIGRlZmF1bHQgZW5jb2RpbmcgaWYgbm9uZSBvZiB0aGVzZSBjYW4gcG9zc2libHkgYmUgY29ycmVjdFxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGd1ZXNzRW5jb2RpbmcoYnl0ZXMsIGhpbnRzKSB7XG4gICAgICAgICAgICBpZiAoaGludHMgIT09IG51bGwgJiYgaGludHMgIT09IHVuZGVmaW5lZCAmJiB1bmRlZmluZWQgIT09IGhpbnRzLmdldChEZWNvZGVIaW50VHlwZSQxLkNIQVJBQ1RFUl9TRVQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhpbnRzLmdldChEZWNvZGVIaW50VHlwZSQxLkNIQVJBQ1RFUl9TRVQpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBGb3Igbm93LCBtZXJlbHkgdHJpZXMgdG8gZGlzdGluZ3Vpc2ggSVNPLTg4NTktMSwgVVRGLTggYW5kIFNoaWZ0X0pJUyxcbiAgICAgICAgICAgIC8vIHdoaWNoIHNob3VsZCBiZSBieSBmYXIgdGhlIG1vc3QgY29tbW9uIGVuY29kaW5ncy5cbiAgICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IGJ5dGVzLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBjYW5CZUlTTzg4NTkxID0gdHJ1ZTtcbiAgICAgICAgICAgIGxldCBjYW5CZVNoaWZ0SklTID0gdHJ1ZTtcbiAgICAgICAgICAgIGxldCBjYW5CZVVURjggPSB0cnVlO1xuICAgICAgICAgICAgbGV0IHV0ZjhCeXRlc0xlZnQgPSAwO1xuICAgICAgICAgICAgLy8gaW50IHV0ZjhMb3dDaGFycyA9IDBcbiAgICAgICAgICAgIGxldCB1dGYyQnl0ZXNDaGFycyA9IDA7XG4gICAgICAgICAgICBsZXQgdXRmM0J5dGVzQ2hhcnMgPSAwO1xuICAgICAgICAgICAgbGV0IHV0ZjRCeXRlc0NoYXJzID0gMDtcbiAgICAgICAgICAgIGxldCBzamlzQnl0ZXNMZWZ0ID0gMDtcbiAgICAgICAgICAgIC8vIGludCBzamlzTG93Q2hhcnMgPSAwXG4gICAgICAgICAgICBsZXQgc2ppc0thdGFrYW5hQ2hhcnMgPSAwO1xuICAgICAgICAgICAgLy8gaW50IHNqaXNEb3VibGVCeXRlc0NoYXJzID0gMFxuICAgICAgICAgICAgbGV0IHNqaXNDdXJLYXRha2FuYVdvcmRMZW5ndGggPSAwO1xuICAgICAgICAgICAgbGV0IHNqaXNDdXJEb3VibGVCeXRlc1dvcmRMZW5ndGggPSAwO1xuICAgICAgICAgICAgbGV0IHNqaXNNYXhLYXRha2FuYVdvcmRMZW5ndGggPSAwO1xuICAgICAgICAgICAgbGV0IHNqaXNNYXhEb3VibGVCeXRlc1dvcmRMZW5ndGggPSAwO1xuICAgICAgICAgICAgLy8gaW50IGlzb0xvd0NoYXJzID0gMFxuICAgICAgICAgICAgLy8gaW50IGlzb0hpZ2hDaGFycyA9IDBcbiAgICAgICAgICAgIGxldCBpc29IaWdoT3RoZXIgPSAwO1xuICAgICAgICAgICAgY29uc3QgdXRmOGJvbSA9IGJ5dGVzLmxlbmd0aCA+IDMgJiZcbiAgICAgICAgICAgICAgICBieXRlc1swXSA9PT0gLyooYnl0ZSkgKi8gMHhFRiAmJlxuICAgICAgICAgICAgICAgIGJ5dGVzWzFdID09PSAvKihieXRlKSAqLyAweEJCICYmXG4gICAgICAgICAgICAgICAgYnl0ZXNbMl0gPT09IC8qKGJ5dGUpICovIDB4QkY7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aCAmJiAoY2FuQmVJU084ODU5MSB8fCBjYW5CZVNoaWZ0SklTIHx8IGNhbkJlVVRGOCk7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gYnl0ZXNbaV0gJiAweEZGO1xuICAgICAgICAgICAgICAgIC8vIFVURi04IHN0dWZmXG4gICAgICAgICAgICAgICAgaWYgKGNhbkJlVVRGOCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodXRmOEJ5dGVzTGVmdCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgodmFsdWUgJiAweDgwKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbkJlVVRGOCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXRmOEJ5dGVzTGVmdC0tO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCh2YWx1ZSAmIDB4ODApICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoKHZhbHVlICYgMHg0MCkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYW5CZVVURjggPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHV0ZjhCeXRlc0xlZnQrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKHZhbHVlICYgMHgyMCkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXRmMkJ5dGVzQ2hhcnMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHV0ZjhCeXRlc0xlZnQrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCh2YWx1ZSAmIDB4MTApID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1dGYzQnl0ZXNDaGFycysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXRmOEJ5dGVzTGVmdCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCh2YWx1ZSAmIDB4MDgpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXRmNEJ5dGVzQ2hhcnMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbkJlVVRGOCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IC8vIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyB1dGY4TG93Q2hhcnMrK1xuICAgICAgICAgICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIElTTy04ODU5LTEgc3R1ZmZcbiAgICAgICAgICAgICAgICBpZiAoY2FuQmVJU084ODU5MSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUgPiAweDdGICYmIHZhbHVlIDwgMHhBMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FuQmVJU084ODU5MSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHZhbHVlID4gMHg5Rikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlIDwgMHhDMCB8fCB2YWx1ZSA9PT0gMHhENyB8fCB2YWx1ZSA9PT0gMHhGNykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzb0hpZ2hPdGhlcisrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSAvLyBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlzb0hpZ2hDaGFycysrXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICAgICAgICAgIH0gLy8gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGlzb0xvd0NoYXJzKytcbiAgICAgICAgICAgICAgICAgICAgLy8gfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBTaGlmdF9KSVMgc3R1ZmZcbiAgICAgICAgICAgICAgICBpZiAoY2FuQmVTaGlmdEpJUykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2ppc0J5dGVzTGVmdCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA8IDB4NDAgfHwgdmFsdWUgPT09IDB4N0YgfHwgdmFsdWUgPiAweEZDKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FuQmVTaGlmdEpJUyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ppc0J5dGVzTGVmdC0tO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHZhbHVlID09PSAweDgwIHx8IHZhbHVlID09PSAweEEwIHx8IHZhbHVlID4gMHhFRikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FuQmVTaGlmdEpJUyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHZhbHVlID4gMHhBMCAmJiB2YWx1ZSA8IDB4RTApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNqaXNLYXRha2FuYUNoYXJzKys7XG4gICAgICAgICAgICAgICAgICAgICAgICBzamlzQ3VyRG91YmxlQnl0ZXNXb3JkTGVuZ3RoID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNqaXNDdXJLYXRha2FuYVdvcmRMZW5ndGgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzamlzQ3VyS2F0YWthbmFXb3JkTGVuZ3RoID4gc2ppc01heEthdGFrYW5hV29yZExlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNqaXNNYXhLYXRha2FuYVdvcmRMZW5ndGggPSBzamlzQ3VyS2F0YWthbmFXb3JkTGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHZhbHVlID4gMHg3Rikge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ppc0J5dGVzTGVmdCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2ppc0RvdWJsZUJ5dGVzQ2hhcnMrK1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ppc0N1ckthdGFrYW5hV29yZExlbmd0aCA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBzamlzQ3VyRG91YmxlQnl0ZXNXb3JkTGVuZ3RoKys7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ppc0N1ckRvdWJsZUJ5dGVzV29yZExlbmd0aCA+IHNqaXNNYXhEb3VibGVCeXRlc1dvcmRMZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzamlzTWF4RG91YmxlQnl0ZXNXb3JkTGVuZ3RoID0gc2ppc0N1ckRvdWJsZUJ5dGVzV29yZExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNqaXNMb3dDaGFycysrXG4gICAgICAgICAgICAgICAgICAgICAgICBzamlzQ3VyS2F0YWthbmFXb3JkTGVuZ3RoID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNqaXNDdXJEb3VibGVCeXRlc1dvcmRMZW5ndGggPSAwO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNhbkJlVVRGOCAmJiB1dGY4Qnl0ZXNMZWZ0ID4gMCkge1xuICAgICAgICAgICAgICAgIGNhbkJlVVRGOCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNhbkJlU2hpZnRKSVMgJiYgc2ppc0J5dGVzTGVmdCA+IDApIHtcbiAgICAgICAgICAgICAgICBjYW5CZVNoaWZ0SklTID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBFYXN5IC0tIGlmIHRoZXJlIGlzIEJPTSBvciBhdCBsZWFzdCAxIHZhbGlkIG5vdC1zaW5nbGUgYnl0ZSBjaGFyYWN0ZXIgKGFuZCBubyBldmlkZW5jZSBpdCBjYW4ndCBiZSBVVEYtOCksIGRvbmVcbiAgICAgICAgICAgIGlmIChjYW5CZVVURjggJiYgKHV0Zjhib20gfHwgdXRmMkJ5dGVzQ2hhcnMgKyB1dGYzQnl0ZXNDaGFycyArIHV0ZjRCeXRlc0NoYXJzID4gMCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nVXRpbHMuVVRGODtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEVhc3kgLS0gaWYgYXNzdW1pbmcgU2hpZnRfSklTIG9yIGF0IGxlYXN0IDMgdmFsaWQgY29uc2VjdXRpdmUgbm90LWFzY2lpIGNoYXJhY3RlcnMgKGFuZCBubyBldmlkZW5jZSBpdCBjYW4ndCBiZSksIGRvbmVcbiAgICAgICAgICAgIGlmIChjYW5CZVNoaWZ0SklTICYmIChTdHJpbmdVdGlscy5BU1NVTUVfU0hJRlRfSklTIHx8IHNqaXNNYXhLYXRha2FuYVdvcmRMZW5ndGggPj0gMyB8fCBzamlzTWF4RG91YmxlQnl0ZXNXb3JkTGVuZ3RoID49IDMpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZ1V0aWxzLlNISUZUX0pJUztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIERpc3Rpbmd1aXNoaW5nIFNoaWZ0X0pJUyBhbmQgSVNPLTg4NTktMSBjYW4gYmUgYSBsaXR0bGUgdG91Z2ggZm9yIHNob3J0IHdvcmRzLiBUaGUgY3J1ZGUgaGV1cmlzdGljIGlzOlxuICAgICAgICAgICAgLy8gLSBJZiB3ZSBzYXdcbiAgICAgICAgICAgIC8vICAgLSBvbmx5IHR3byBjb25zZWN1dGl2ZSBrYXRha2FuYSBjaGFycyBpbiB0aGUgd2hvbGUgdGV4dCwgb3JcbiAgICAgICAgICAgIC8vICAgLSBhdCBsZWFzdCAxMCUgb2YgYnl0ZXMgdGhhdCBjb3VsZCBiZSBcInVwcGVyXCIgbm90LWFscGhhbnVtZXJpYyBMYXRpbjEsXG4gICAgICAgICAgICAvLyAtIHRoZW4gd2UgY29uY2x1ZGUgU2hpZnRfSklTLCBlbHNlIElTTy04ODU5LTFcbiAgICAgICAgICAgIGlmIChjYW5CZUlTTzg4NTkxICYmIGNhbkJlU2hpZnRKSVMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKHNqaXNNYXhLYXRha2FuYVdvcmRMZW5ndGggPT09IDIgJiYgc2ppc0thdGFrYW5hQ2hhcnMgPT09IDIpIHx8IGlzb0hpZ2hPdGhlciAqIDEwID49IGxlbmd0aFxuICAgICAgICAgICAgICAgICAgICA/IFN0cmluZ1V0aWxzLlNISUZUX0pJUyA6IFN0cmluZ1V0aWxzLklTTzg4NTkxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gT3RoZXJ3aXNlLCB0cnkgaW4gb3JkZXIgSVNPLTg4NTktMSwgU2hpZnQgSklTLCBVVEYtOCBhbmQgZmFsbCBiYWNrIHRvIGRlZmF1bHQgcGxhdGZvcm0gZW5jb2RpbmdcbiAgICAgICAgICAgIGlmIChjYW5CZUlTTzg4NTkxKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZ1V0aWxzLklTTzg4NTkxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNhbkJlU2hpZnRKSVMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nVXRpbHMuU0hJRlRfSklTO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNhbkJlVVRGOCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmdVdGlscy5VVEY4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gT3RoZXJ3aXNlLCB3ZSB0YWtlIGEgd2lsZCBndWVzcyB3aXRoIHBsYXRmb3JtIGVuY29kaW5nXG4gICAgICAgICAgICByZXR1cm4gU3RyaW5nVXRpbHMuUExBVEZPUk1fREVGQVVMVF9FTkNPRElORztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICpcbiAgICAgICAgICogQHNlZSBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMTM0Mzk3MTEvNDM2NzY4M1xuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gYXBwZW5kIFRoZSBuZXcgc3RyaW5nIHRvIGFwcGVuZC5cbiAgICAgICAgICogQHBhcmFtIGFyZ3MgQXJndW1ldHMgdmFsdWVzIHRvIGJlIGZvcm1hdGVkLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGZvcm1hdChhcHBlbmQsIC4uLmFyZ3MpIHtcbiAgICAgICAgICAgIGxldCBpID0gLTE7XG4gICAgICAgICAgICBmdW5jdGlvbiBjYWxsYmFjayhleHAsIHAwLCBwMSwgcDIsIHAzLCBwNCkge1xuICAgICAgICAgICAgICAgIGlmIChleHAgPT09ICclJScpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnJSc7XG4gICAgICAgICAgICAgICAgaWYgKGFyZ3NbKytpXSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGV4cCA9IHAyID8gcGFyc2VJbnQocDIuc3Vic3RyKDEpKSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICBsZXQgYmFzZSA9IHAzID8gcGFyc2VJbnQocDMuc3Vic3RyKDEpKSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICBsZXQgdmFsO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAocDQpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAncyc6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWwgPSBhcmdzW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2MnOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsID0gYXJnc1tpXVswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdmJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbCA9IHBhcnNlRmxvYXQoYXJnc1tpXSkudG9GaXhlZChleHApO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3AnOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsID0gcGFyc2VGbG9hdChhcmdzW2ldKS50b1ByZWNpc2lvbihleHApO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2UnOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsID0gcGFyc2VGbG9hdChhcmdzW2ldKS50b0V4cG9uZW50aWFsKGV4cCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAneCc6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWwgPSBwYXJzZUludChhcmdzW2ldKS50b1N0cmluZyhiYXNlID8gYmFzZSA6IDE2KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbCA9IHBhcnNlRmxvYXQocGFyc2VJbnQoYXJnc1tpXSwgYmFzZSA/IGJhc2UgOiAxMCkudG9QcmVjaXNpb24oZXhwKSkudG9GaXhlZCgwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YWwgPSB0eXBlb2YgdmFsID09PSAnb2JqZWN0JyA/IEpTT04uc3RyaW5naWZ5KHZhbCkgOiAoK3ZhbCkudG9TdHJpbmcoYmFzZSk7XG4gICAgICAgICAgICAgICAgbGV0IHNpemUgPSBwYXJzZUludChwMSk7IC8qIHBhZGRpbmcgc2l6ZSAqL1xuICAgICAgICAgICAgICAgIGxldCBjaCA9IHAxICYmIChwMVswXSArICcnKSA9PT0gJzAnID8gJzAnIDogJyAnOyAvKiBpc251bGw/ICovXG4gICAgICAgICAgICAgICAgd2hpbGUgKHZhbC5sZW5ndGggPCBzaXplKVxuICAgICAgICAgICAgICAgICAgICB2YWwgPSBwMCAhPT0gdW5kZWZpbmVkID8gdmFsICsgY2ggOiBjaCArIHZhbDsgLyogaXNtaW51cz8gKi9cbiAgICAgICAgICAgICAgICByZXR1cm4gdmFsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHJlZ2V4ID0gLyUoLSk/KDA/WzAtOV0rKT8oWy5dWzAtOV0rKT8oWyNdWzAtOV0rKT8oW3NjZnBleGQlXSkvZztcbiAgICAgICAgICAgIHJldHVybiBhcHBlbmQucmVwbGFjZShyZWdleCwgY2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGdldEJ5dGVzKHN0ciwgZW5jb2RpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBTdHJpbmdFbmNvZGluZy5lbmNvZGUoc3RyLCBlbmNvZGluZyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldHVybnMgdGhlIGNoYXJjb2RlIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXggb3IgYXQgaW5kZXggemVyby5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBnZXRDaGFyQ29kZShzdHIsIGluZGV4ID0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHN0ci5jaGFyQ29kZUF0KGluZGV4KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogUmV0dXJucyBjaGFyIGZvciBnaXZlbiBjaGFyY29kZVxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGdldENoYXJBdChjaGFyQ29kZSkge1xuICAgICAgICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoY2hhckNvZGUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIFN0cmluZ1V0aWxzLlNISUZUX0pJUyA9IENoYXJhY3RlclNldEVDSS5TSklTLmdldE5hbWUoKTsgLy8gXCJTSklTXCJcbiAgICBTdHJpbmdVdGlscy5HQjIzMTIgPSAnR0IyMzEyJztcbiAgICBTdHJpbmdVdGlscy5JU084ODU5MSA9IENoYXJhY3RlclNldEVDSS5JU084ODU5XzEuZ2V0TmFtZSgpOyAvLyBcIklTTzg4NTlfMVwiXG4gICAgU3RyaW5nVXRpbHMuRVVDX0pQID0gJ0VVQ19KUCc7XG4gICAgU3RyaW5nVXRpbHMuVVRGOCA9IENoYXJhY3RlclNldEVDSS5VVEY4LmdldE5hbWUoKTsgLy8gXCJVVEY4XCJcbiAgICBTdHJpbmdVdGlscy5QTEFURk9STV9ERUZBVUxUX0VOQ09ESU5HID0gU3RyaW5nVXRpbHMuVVRGODsgLy8gXCJVVEY4XCIvL0NoYXJzZXQuZGVmYXVsdENoYXJzZXQoKS5uYW1lKClcbiAgICBTdHJpbmdVdGlscy5BU1NVTUVfU0hJRlRfSklTID0gZmFsc2U7XG5cbiAgICBjbGFzcyBTdHJpbmdCdWlsZGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IodmFsdWUgPSAnJykge1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGVuYWJsZURlY29kaW5nKGVuY29kaW5nKSB7XG4gICAgICAgICAgICB0aGlzLmVuY29kaW5nID0gZW5jb2Rpbmc7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICBhcHBlbmQocykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBzID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgKz0gcy50b1N0cmluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5lbmNvZGluZykge1xuICAgICAgICAgICAgICAgIC8vIHVzZSBwYXNzZWQgZm9ybWF0IChmcm9tQ2hhckNvZGUgd2lsbCByZXR1cm4gVVRGOCBlbmNvZGluZylcbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlICs9IFN0cmluZ1V0aWxzLmNhc3RBc05vblV0ZjhDaGFyKHMsIHRoaXMuZW5jb2RpbmcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gY29ycmVjdGx5IGNvbnZlcnRzIGZyb20gVVRGLTgsIGJ1dCBub3Qgb3RoZXIgZW5jb2RpbmdzXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgYXBwZW5kQ2hhcnMoc3RyLCBvZmZzZXQsIGxlbikge1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IG9mZnNldDsgb2Zmc2V0IDwgb2Zmc2V0ICsgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFwcGVuZChzdHJbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgbGVuZ3RoKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWUubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIGNoYXJBdChuKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZS5jaGFyQXQobik7XG4gICAgICAgIH1cbiAgICAgICAgZGVsZXRlQ2hhckF0KG4pIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB0aGlzLnZhbHVlLnN1YnN0cigwLCBuKSArIHRoaXMudmFsdWUuc3Vic3RyaW5nKG4gKyAxKTtcbiAgICAgICAgfVxuICAgICAgICBzZXRDaGFyQXQobiwgYykge1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHRoaXMudmFsdWUuc3Vic3RyKDAsIG4pICsgYyArIHRoaXMudmFsdWUuc3Vic3RyKG4gKyAxKTtcbiAgICAgICAgfVxuICAgICAgICBzdWJzdHJpbmcoc3RhcnQsIGVuZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWUuc3Vic3RyaW5nKHN0YXJ0LCBlbmQpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAbm90ZSBoZWxwZXIgbWV0aG9kIGZvciBSU1MgRXhwYW5kZWRcbiAgICAgICAgICovXG4gICAgICAgIHNldExlbmd0aFRvWmVybygpIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSAnJztcbiAgICAgICAgfVxuICAgICAgICB0b1N0cmluZygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGluc2VydChuLCBjKSB7XG4gICAgICAgICAgICB0aGlzLnZhbHVlID0gdGhpcy52YWx1ZS5zdWJzdHIoMCwgbikgKyBjICsgdGhpcy52YWx1ZS5zdWJzdHIobiArIGMubGVuZ3RoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogPHA+UmVwcmVzZW50cyBhIDJEIG1hdHJpeCBvZiBiaXRzLiBJbiBmdW5jdGlvbiBhcmd1bWVudHMgYmVsb3csIGFuZCB0aHJvdWdob3V0IHRoZSBjb21tb25cbiAgICAgKiBtb2R1bGUsIHggaXMgdGhlIGNvbHVtbiBwb3NpdGlvbiwgYW5kIHkgaXMgdGhlIHJvdyBwb3NpdGlvbi4gVGhlIG9yZGVyaW5nIGlzIGFsd2F5cyB4LCB5LlxuICAgICAqIFRoZSBvcmlnaW4gaXMgYXQgdGhlIHRvcC1sZWZ0LjwvcD5cbiAgICAgKlxuICAgICAqIDxwPkludGVybmFsbHkgdGhlIGJpdHMgYXJlIHJlcHJlc2VudGVkIGluIGEgMS1EIGFycmF5IG9mIDMyLWJpdCBpbnRzLiBIb3dldmVyLCBlYWNoIHJvdyBiZWdpbnNcbiAgICAgKiB3aXRoIGEgbmV3IGludC4gVGhpcyBpcyBkb25lIGludGVudGlvbmFsbHkgc28gdGhhdCB3ZSBjYW4gY29weSBvdXQgYSByb3cgaW50byBhIEJpdEFycmF5IHZlcnlcbiAgICAgKiBlZmZpY2llbnRseS48L3A+XG4gICAgICpcbiAgICAgKiA8cD5UaGUgb3JkZXJpbmcgb2YgYml0cyBpcyByb3ctbWFqb3IuIFdpdGhpbiBlYWNoIGludCwgdGhlIGxlYXN0IHNpZ25pZmljYW50IGJpdHMgYXJlIHVzZWQgZmlyc3QsXG4gICAgICogbWVhbmluZyB0aGV5IHJlcHJlc2VudCBsb3dlciB4IHZhbHVlcy4gVGhpcyBpcyBjb21wYXRpYmxlIHdpdGggQml0QXJyYXkncyBpbXBsZW1lbnRhdGlvbi48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pXG4gICAgICovXG4gICAgY2xhc3MgQml0TWF0cml4IC8qaW1wbGVtZW50cyBDbG9uZWFibGUqLyB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGFuIGVtcHR5IHNxdWFyZSB7QGxpbmsgQml0TWF0cml4fS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGRpbWVuc2lvbiBoZWlnaHQgYW5kIHdpZHRoXG4gICAgICAgICAqL1xuICAgICAgICAvLyBwdWJsaWMgY29uc3RydWN0b3IoZGltZW5zaW9uOiBudW1iZXIgLyppbnQqLykge1xuICAgICAgICAvLyAgIHRoaXMoZGltZW5zaW9uLCBkaW1lbnNpb24pXG4gICAgICAgIC8vIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYW4gZW1wdHkge0BsaW5rIEJpdE1hdHJpeH0uXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB3aWR0aCBiaXQgbWF0cml4IHdpZHRoXG4gICAgICAgICAqIEBwYXJhbSBoZWlnaHQgYml0IG1hdHJpeCBoZWlnaHRcbiAgICAgICAgICovXG4gICAgICAgIC8vIHB1YmxpYyBjb25zdHJ1Y3Rvcih3aWR0aDogbnVtYmVyIC8qaW50Ki8sIGhlaWdodDogbnVtYmVyIC8qaW50Ki8pIHtcbiAgICAgICAgLy8gICBpZiAod2lkdGggPCAxIHx8IGhlaWdodCA8IDEpIHtcbiAgICAgICAgLy8gICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oXCJCb3RoIGRpbWVuc2lvbnMgbXVzdCBiZSBncmVhdGVyIHRoYW4gMFwiKVxuICAgICAgICAvLyAgIH1cbiAgICAgICAgLy8gICB0aGlzLndpZHRoID0gd2lkdGhcbiAgICAgICAgLy8gICB0aGlzLmhlaWdodCA9IGhlaWdodFxuICAgICAgICAvLyAgIHRoaXMucm93U2l6ZSA9ICh3aWR0aCArIDMxKSAvIDMyXG4gICAgICAgIC8vICAgYml0cyA9IG5ldyBpbnRbcm93U2l6ZSAqIGhlaWdodF07XG4gICAgICAgIC8vIH1cbiAgICAgICAgY29uc3RydWN0b3Iod2lkdGggLyppbnQqLywgaGVpZ2h0IC8qaW50Ki8sIHJvd1NpemUgLyppbnQqLywgYml0cykge1xuICAgICAgICAgICAgdGhpcy53aWR0aCA9IHdpZHRoO1xuICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgICAgICB0aGlzLnJvd1NpemUgPSByb3dTaXplO1xuICAgICAgICAgICAgdGhpcy5iaXRzID0gYml0cztcbiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IGhlaWdodCB8fCBudWxsID09PSBoZWlnaHQpIHtcbiAgICAgICAgICAgICAgICBoZWlnaHQgPSB3aWR0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICAgICAgaWYgKHdpZHRoIDwgMSB8fCBoZWlnaHQgPCAxKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignQm90aCBkaW1lbnNpb25zIG11c3QgYmUgZ3JlYXRlciB0aGFuIDAnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IHJvd1NpemUgfHwgbnVsbCA9PT0gcm93U2l6ZSkge1xuICAgICAgICAgICAgICAgIHJvd1NpemUgPSBNYXRoLmZsb29yKCh3aWR0aCArIDMxKSAvIDMyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucm93U2l6ZSA9IHJvd1NpemU7XG4gICAgICAgICAgICBpZiAodW5kZWZpbmVkID09PSBiaXRzIHx8IG51bGwgPT09IGJpdHMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmJpdHMgPSBuZXcgSW50MzJBcnJheSh0aGlzLnJvd1NpemUgKiB0aGlzLmhlaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEludGVycHJldHMgYSAyRCBhcnJheSBvZiBib29sZWFucyBhcyBhIHtAbGluayBCaXRNYXRyaXh9LCB3aGVyZSBcInRydWVcIiBtZWFucyBhbiBcIm9uXCIgYml0LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAZnVuY3Rpb24gcGFyc2VcbiAgICAgICAgICogQHBhcmFtIGltYWdlIGJpdHMgb2YgdGhlIGltYWdlLCBhcyBhIHJvdy1tYWpvciAyRCBhcnJheS4gRWxlbWVudHMgYXJlIGFycmF5cyByZXByZXNlbnRpbmcgcm93c1xuICAgICAgICAgKiBAcmV0dXJuIHtAbGluayBCaXRNYXRyaXh9IHJlcHJlc2VudGF0aW9uIG9mIGltYWdlXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgcGFyc2VGcm9tQm9vbGVhbkFycmF5KGltYWdlKSB7XG4gICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBpbWFnZS5sZW5ndGg7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IGltYWdlWzBdLmxlbmd0aDtcbiAgICAgICAgICAgIGNvbnN0IGJpdHMgPSBuZXcgQml0TWF0cml4KHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoZWlnaHQ7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGltYWdlSSA9IGltYWdlW2ldO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgd2lkdGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW1hZ2VJW2pdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBiaXRzLnNldChqLCBpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBiaXRzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKlxuICAgICAgICAgKiBAZnVuY3Rpb24gcGFyc2VcbiAgICAgICAgICogQHBhcmFtIHN0cmluZ1JlcHJlc2VudGF0aW9uXG4gICAgICAgICAqIEBwYXJhbSBzZXRTdHJpbmdcbiAgICAgICAgICogQHBhcmFtIHVuc2V0U3RyaW5nXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgcGFyc2VGcm9tU3RyaW5nKHN0cmluZ1JlcHJlc2VudGF0aW9uLCBzZXRTdHJpbmcsIHVuc2V0U3RyaW5nKSB7XG4gICAgICAgICAgICBpZiAoc3RyaW5nUmVwcmVzZW50YXRpb24gPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdzdHJpbmdSZXByZXNlbnRhdGlvbiBjYW5ub3QgYmUgbnVsbCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYml0cyA9IG5ldyBBcnJheShzdHJpbmdSZXByZXNlbnRhdGlvbi5sZW5ndGgpO1xuICAgICAgICAgICAgbGV0IGJpdHNQb3MgPSAwO1xuICAgICAgICAgICAgbGV0IHJvd1N0YXJ0UG9zID0gMDtcbiAgICAgICAgICAgIGxldCByb3dMZW5ndGggPSAtMTtcbiAgICAgICAgICAgIGxldCBuUm93cyA9IDA7XG4gICAgICAgICAgICBsZXQgcG9zID0gMDtcbiAgICAgICAgICAgIHdoaWxlIChwb3MgPCBzdHJpbmdSZXByZXNlbnRhdGlvbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBpZiAoc3RyaW5nUmVwcmVzZW50YXRpb24uY2hhckF0KHBvcykgPT09ICdcXG4nIHx8XG4gICAgICAgICAgICAgICAgICAgIHN0cmluZ1JlcHJlc2VudGF0aW9uLmNoYXJBdChwb3MpID09PSAnXFxyJykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoYml0c1BvcyA+IHJvd1N0YXJ0UG9zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocm93TGVuZ3RoID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvd0xlbmd0aCA9IGJpdHNQb3MgLSByb3dTdGFydFBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGJpdHNQb3MgLSByb3dTdGFydFBvcyAhPT0gcm93TGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigncm93IGxlbmd0aHMgZG8gbm90IG1hdGNoJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByb3dTdGFydFBvcyA9IGJpdHNQb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICBuUm93cysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHBvcysrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChzdHJpbmdSZXByZXNlbnRhdGlvbi5zdWJzdHJpbmcocG9zLCBwb3MgKyBzZXRTdHJpbmcubGVuZ3RoKSA9PT0gc2V0U3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvcyArPSBzZXRTdHJpbmcubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBiaXRzW2JpdHNQb3NdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYml0c1BvcysrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChzdHJpbmdSZXByZXNlbnRhdGlvbi5zdWJzdHJpbmcocG9zLCBwb3MgKyB1bnNldFN0cmluZy5sZW5ndGgpID09PSB1bnNldFN0cmluZykge1xuICAgICAgICAgICAgICAgICAgICBwb3MgKz0gdW5zZXRTdHJpbmcubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBiaXRzW2JpdHNQb3NdID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGJpdHNQb3MrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ2lsbGVnYWwgY2hhcmFjdGVyIGVuY291bnRlcmVkOiAnICsgc3RyaW5nUmVwcmVzZW50YXRpb24uc3Vic3RyaW5nKHBvcykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIG5vIEVPTCBhdCBlbmQ/XG4gICAgICAgICAgICBpZiAoYml0c1BvcyA+IHJvd1N0YXJ0UG9zKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJvd0xlbmd0aCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcm93TGVuZ3RoID0gYml0c1BvcyAtIHJvd1N0YXJ0UG9zO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChiaXRzUG9zIC0gcm93U3RhcnRQb3MgIT09IHJvd0xlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdyb3cgbGVuZ3RocyBkbyBub3QgbWF0Y2gnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgblJvd3MrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG1hdHJpeCA9IG5ldyBCaXRNYXRyaXgocm93TGVuZ3RoLCBuUm93cyk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJpdHNQb3M7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChiaXRzW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXQoTWF0aC5mbG9vcihpICUgcm93TGVuZ3RoKSwgTWF0aC5mbG9vcihpIC8gcm93TGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1hdHJpeDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+R2V0cyB0aGUgcmVxdWVzdGVkIGJpdCwgd2hlcmUgdHJ1ZSBtZWFucyBibGFjay48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB4IFRoZSBob3Jpem9udGFsIGNvbXBvbmVudCAoaS5lLiB3aGljaCBjb2x1bW4pXG4gICAgICAgICAqIEBwYXJhbSB5IFRoZSB2ZXJ0aWNhbCBjb21wb25lbnQgKGkuZS4gd2hpY2ggcm93KVxuICAgICAgICAgKiBAcmV0dXJuIHZhbHVlIG9mIGdpdmVuIGJpdCBpbiBtYXRyaXhcbiAgICAgICAgICovXG4gICAgICAgIGdldCh4IC8qaW50Ki8sIHkgLyppbnQqLykge1xuICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0geSAqIHRoaXMucm93U2l6ZSArIE1hdGguZmxvb3IoeCAvIDMyKTtcbiAgICAgICAgICAgIHJldHVybiAoKHRoaXMuYml0c1tvZmZzZXRdID4+PiAoeCAmIDB4MWYpKSAmIDEpICE9PSAwO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5TZXRzIHRoZSBnaXZlbiBiaXQgdG8gdHJ1ZS48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB4IFRoZSBob3Jpem9udGFsIGNvbXBvbmVudCAoaS5lLiB3aGljaCBjb2x1bW4pXG4gICAgICAgICAqIEBwYXJhbSB5IFRoZSB2ZXJ0aWNhbCBjb21wb25lbnQgKGkuZS4gd2hpY2ggcm93KVxuICAgICAgICAgKi9cbiAgICAgICAgc2V0KHggLyppbnQqLywgeSAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBvZmZzZXQgPSB5ICogdGhpcy5yb3dTaXplICsgTWF0aC5mbG9vcih4IC8gMzIpO1xuICAgICAgICAgICAgdGhpcy5iaXRzW29mZnNldF0gfD0gKDEgPDwgKHggJiAweDFmKSkgJiAweEZGRkZGRkZGO1xuICAgICAgICB9XG4gICAgICAgIHVuc2V0KHggLyppbnQqLywgeSAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBvZmZzZXQgPSB5ICogdGhpcy5yb3dTaXplICsgTWF0aC5mbG9vcih4IC8gMzIpO1xuICAgICAgICAgICAgdGhpcy5iaXRzW29mZnNldF0gJj0gfigoMSA8PCAoeCAmIDB4MWYpKSAmIDB4RkZGRkZGRkYpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5GbGlwcyB0aGUgZ2l2ZW4gYml0LjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHggVGhlIGhvcml6b250YWwgY29tcG9uZW50IChpLmUuIHdoaWNoIGNvbHVtbilcbiAgICAgICAgICogQHBhcmFtIHkgVGhlIHZlcnRpY2FsIGNvbXBvbmVudCAoaS5lLiB3aGljaCByb3cpXG4gICAgICAgICAqL1xuICAgICAgICBmbGlwKHggLyppbnQqLywgeSAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBvZmZzZXQgPSB5ICogdGhpcy5yb3dTaXplICsgTWF0aC5mbG9vcih4IC8gMzIpO1xuICAgICAgICAgICAgdGhpcy5iaXRzW29mZnNldF0gXj0gKCgxIDw8ICh4ICYgMHgxZikpICYgMHhGRkZGRkZGRik7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEV4Y2x1c2l2ZS1vciAoWE9SKTogRmxpcCB0aGUgYml0IGluIHRoaXMge0Bjb2RlIEJpdE1hdHJpeH0gaWYgdGhlIGNvcnJlc3BvbmRpbmdcbiAgICAgICAgICogbWFzayBiaXQgaXMgc2V0LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gbWFzayBYT1IgbWFza1xuICAgICAgICAgKi9cbiAgICAgICAgeG9yKG1hc2spIHtcbiAgICAgICAgICAgIGlmICh0aGlzLndpZHRoICE9PSBtYXNrLmdldFdpZHRoKCkgfHwgdGhpcy5oZWlnaHQgIT09IG1hc2suZ2V0SGVpZ2h0KClcbiAgICAgICAgICAgICAgICB8fCB0aGlzLnJvd1NpemUgIT09IG1hc2suZ2V0Um93U2l6ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignaW5wdXQgbWF0cml4IGRpbWVuc2lvbnMgZG8gbm90IG1hdGNoJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByb3dBcnJheSA9IG5ldyBCaXRBcnJheShNYXRoLmZsb29yKHRoaXMud2lkdGggLyAzMikgKyAxKTtcbiAgICAgICAgICAgIGNvbnN0IHJvd1NpemUgPSB0aGlzLnJvd1NpemU7XG4gICAgICAgICAgICBjb25zdCBiaXRzID0gdGhpcy5iaXRzO1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDAsIGhlaWdodCA9IHRoaXMuaGVpZ2h0OyB5IDwgaGVpZ2h0OyB5KyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBvZmZzZXQgPSB5ICogcm93U2l6ZTtcbiAgICAgICAgICAgICAgICBjb25zdCByb3cgPSBtYXNrLmdldFJvdyh5LCByb3dBcnJheSkuZ2V0Qml0QXJyYXkoKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IHJvd1NpemU7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICBiaXRzW29mZnNldCArIHhdIF49IHJvd1t4XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENsZWFycyBhbGwgYml0cyAoc2V0cyB0byBmYWxzZSkuXG4gICAgICAgICAqL1xuICAgICAgICBjbGVhcigpIHtcbiAgICAgICAgICAgIGNvbnN0IGJpdHMgPSB0aGlzLmJpdHM7XG4gICAgICAgICAgICBjb25zdCBtYXggPSBiaXRzLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbWF4OyBpKyspIHtcbiAgICAgICAgICAgICAgICBiaXRzW2ldID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+U2V0cyBhIHNxdWFyZSByZWdpb24gb2YgdGhlIGJpdCBtYXRyaXggdG8gdHJ1ZS48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBsZWZ0IFRoZSBob3Jpem9udGFsIHBvc2l0aW9uIHRvIGJlZ2luIGF0IChpbmNsdXNpdmUpXG4gICAgICAgICAqIEBwYXJhbSB0b3AgVGhlIHZlcnRpY2FsIHBvc2l0aW9uIHRvIGJlZ2luIGF0IChpbmNsdXNpdmUpXG4gICAgICAgICAqIEBwYXJhbSB3aWR0aCBUaGUgd2lkdGggb2YgdGhlIHJlZ2lvblxuICAgICAgICAgKiBAcGFyYW0gaGVpZ2h0IFRoZSBoZWlnaHQgb2YgdGhlIHJlZ2lvblxuICAgICAgICAgKi9cbiAgICAgICAgc2V0UmVnaW9uKGxlZnQgLyppbnQqLywgdG9wIC8qaW50Ki8sIHdpZHRoIC8qaW50Ki8sIGhlaWdodCAvKmludCovKSB7XG4gICAgICAgICAgICBpZiAodG9wIDwgMCB8fCBsZWZ0IDwgMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ0xlZnQgYW5kIHRvcCBtdXN0IGJlIG5vbm5lZ2F0aXZlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaGVpZ2h0IDwgMSB8fCB3aWR0aCA8IDEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdIZWlnaHQgYW5kIHdpZHRoIG11c3QgYmUgYXQgbGVhc3QgMScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmlnaHQgPSBsZWZ0ICsgd2lkdGg7XG4gICAgICAgICAgICBjb25zdCBib3R0b20gPSB0b3AgKyBoZWlnaHQ7XG4gICAgICAgICAgICBpZiAoYm90dG9tID4gdGhpcy5oZWlnaHQgfHwgcmlnaHQgPiB0aGlzLndpZHRoKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignVGhlIHJlZ2lvbiBtdXN0IGZpdCBpbnNpZGUgdGhlIG1hdHJpeCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgcm93U2l6ZSA9IHRoaXMucm93U2l6ZTtcbiAgICAgICAgICAgIGNvbnN0IGJpdHMgPSB0aGlzLmJpdHM7XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gdG9wOyB5IDwgYm90dG9tOyB5KyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBvZmZzZXQgPSB5ICogcm93U2l6ZTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB4ID0gbGVmdDsgeCA8IHJpZ2h0OyB4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgYml0c1tvZmZzZXQgKyBNYXRoLmZsb29yKHggLyAzMildIHw9ICgoMSA8PCAoeCAmIDB4MWYpKSAmIDB4RkZGRkZGRkYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQSBmYXN0IG1ldGhvZCB0byByZXRyaWV2ZSBvbmUgcm93IG9mIGRhdGEgZnJvbSB0aGUgbWF0cml4IGFzIGEgQml0QXJyYXkuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB5IFRoZSByb3cgdG8gcmV0cmlldmVcbiAgICAgICAgICogQHBhcmFtIHJvdyBBbiBvcHRpb25hbCBjYWxsZXItYWxsb2NhdGVkIEJpdEFycmF5LCB3aWxsIGJlIGFsbG9jYXRlZCBpZiBudWxsIG9yIHRvbyBzbWFsbFxuICAgICAgICAgKiBAcmV0dXJuIFRoZSByZXN1bHRpbmcgQml0QXJyYXkgLSB0aGlzIHJlZmVyZW5jZSBzaG91bGQgYWx3YXlzIGJlIHVzZWQgZXZlbiB3aGVuIHBhc3NpbmdcbiAgICAgICAgICogICAgICAgICB5b3VyIG93biByb3dcbiAgICAgICAgICovXG4gICAgICAgIGdldFJvdyh5IC8qaW50Ki8sIHJvdykge1xuICAgICAgICAgICAgaWYgKHJvdyA9PT0gbnVsbCB8fCByb3cgPT09IHVuZGVmaW5lZCB8fCByb3cuZ2V0U2l6ZSgpIDwgdGhpcy53aWR0aCkge1xuICAgICAgICAgICAgICAgIHJvdyA9IG5ldyBCaXRBcnJheSh0aGlzLndpZHRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJvdy5jbGVhcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgcm93U2l6ZSA9IHRoaXMucm93U2l6ZTtcbiAgICAgICAgICAgIGNvbnN0IGJpdHMgPSB0aGlzLmJpdHM7XG4gICAgICAgICAgICBjb25zdCBvZmZzZXQgPSB5ICogcm93U2l6ZTtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgcm93U2l6ZTsgeCsrKSB7XG4gICAgICAgICAgICAgICAgcm93LnNldEJ1bGsoeCAqIDMyLCBiaXRzW29mZnNldCArIHhdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByb3c7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB5IHJvdyB0byBzZXRcbiAgICAgICAgICogQHBhcmFtIHJvdyB7QGxpbmsgQml0QXJyYXl9IHRvIGNvcHkgZnJvbVxuICAgICAgICAgKi9cbiAgICAgICAgc2V0Um93KHkgLyppbnQqLywgcm93KSB7XG4gICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KHJvdy5nZXRCaXRBcnJheSgpLCAwLCB0aGlzLmJpdHMsIHkgKiB0aGlzLnJvd1NpemUsIHRoaXMucm93U2l6ZSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE1vZGlmaWVzIHRoaXMge0Bjb2RlIEJpdE1hdHJpeH0gdG8gcmVwcmVzZW50IHRoZSBzYW1lIGJ1dCByb3RhdGVkIDE4MCBkZWdyZWVzXG4gICAgICAgICAqL1xuICAgICAgICByb3RhdGUxODAoKSB7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMuZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICBsZXQgdG9wUm93ID0gbmV3IEJpdEFycmF5KHdpZHRoKTtcbiAgICAgICAgICAgIGxldCBib3R0b21Sb3cgPSBuZXcgQml0QXJyYXkod2lkdGgpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGxlbmd0aCA9IE1hdGguZmxvb3IoKGhlaWdodCArIDEpIC8gMik7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHRvcFJvdyA9IHRoaXMuZ2V0Um93KGksIHRvcFJvdyk7XG4gICAgICAgICAgICAgICAgYm90dG9tUm93ID0gdGhpcy5nZXRSb3coaGVpZ2h0IC0gMSAtIGksIGJvdHRvbVJvdyk7XG4gICAgICAgICAgICAgICAgdG9wUm93LnJldmVyc2UoKTtcbiAgICAgICAgICAgICAgICBib3R0b21Sb3cucmV2ZXJzZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0Um93KGksIGJvdHRvbVJvdyk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRSb3coaGVpZ2h0IC0gMSAtIGksIHRvcFJvdyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoaXMgaXMgdXNlZnVsIGluIGRldGVjdGluZyB0aGUgZW5jbG9zaW5nIHJlY3RhbmdsZSBvZiBhICdwdXJlJyBiYXJjb2RlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIHtAY29kZSBsZWZ0LHRvcCx3aWR0aCxoZWlnaHR9IGVuY2xvc2luZyByZWN0YW5nbGUgb2YgYWxsIDEgYml0cywgb3IgbnVsbCBpZiBpdCBpcyBhbGwgd2hpdGVcbiAgICAgICAgICovXG4gICAgICAgIGdldEVuY2xvc2luZ1JlY3RhbmdsZSgpIHtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy53aWR0aDtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuaGVpZ2h0O1xuICAgICAgICAgICAgY29uc3Qgcm93U2l6ZSA9IHRoaXMucm93U2l6ZTtcbiAgICAgICAgICAgIGNvbnN0IGJpdHMgPSB0aGlzLmJpdHM7XG4gICAgICAgICAgICBsZXQgbGVmdCA9IHdpZHRoO1xuICAgICAgICAgICAgbGV0IHRvcCA9IGhlaWdodDtcbiAgICAgICAgICAgIGxldCByaWdodCA9IC0xO1xuICAgICAgICAgICAgbGV0IGJvdHRvbSA9IC0xO1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHgzMiA9IDA7IHgzMiA8IHJvd1NpemU7IHgzMisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRoZUJpdHMgPSBiaXRzW3kgKiByb3dTaXplICsgeDMyXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoZUJpdHMgIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh5IDwgdG9wKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9wID0geTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh5ID4gYm90dG9tKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYm90dG9tID0geTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh4MzIgKiAzMiA8IGxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgYml0ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoKCh0aGVCaXRzIDw8ICgzMSAtIGJpdCkpICYgMHhGRkZGRkZGRikgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYml0Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoeDMyICogMzIgKyBiaXQpIDwgbGVmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWZ0ID0geDMyICogMzIgKyBiaXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHgzMiAqIDMyICsgMzEgPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBiaXQgPSAzMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoKHRoZUJpdHMgPj4+IGJpdCkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYml0LS07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoeDMyICogMzIgKyBiaXQpID4gcmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQgPSB4MzIgKiAzMiArIGJpdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmlnaHQgPCBsZWZ0IHx8IGJvdHRvbSA8IHRvcCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIEludDMyQXJyYXkuZnJvbShbbGVmdCwgdG9wLCByaWdodCAtIGxlZnQgKyAxLCBib3R0b20gLSB0b3AgKyAxXSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoaXMgaXMgdXNlZnVsIGluIGRldGVjdGluZyBhIGNvcm5lciBvZiBhICdwdXJlJyBiYXJjb2RlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIHtAY29kZSB4LHl9IGNvb3JkaW5hdGUgb2YgdG9wLWxlZnQtbW9zdCAxIGJpdCwgb3IgbnVsbCBpZiBpdCBpcyBhbGwgd2hpdGVcbiAgICAgICAgICovXG4gICAgICAgIGdldFRvcExlZnRPbkJpdCgpIHtcbiAgICAgICAgICAgIGNvbnN0IHJvd1NpemUgPSB0aGlzLnJvd1NpemU7XG4gICAgICAgICAgICBjb25zdCBiaXRzID0gdGhpcy5iaXRzO1xuICAgICAgICAgICAgbGV0IGJpdHNPZmZzZXQgPSAwO1xuICAgICAgICAgICAgd2hpbGUgKGJpdHNPZmZzZXQgPCBiaXRzLmxlbmd0aCAmJiBiaXRzW2JpdHNPZmZzZXRdID09PSAwKSB7XG4gICAgICAgICAgICAgICAgYml0c09mZnNldCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGJpdHNPZmZzZXQgPT09IGJpdHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCB5ID0gYml0c09mZnNldCAvIHJvd1NpemU7XG4gICAgICAgICAgICBsZXQgeCA9IChiaXRzT2Zmc2V0ICUgcm93U2l6ZSkgKiAzMjtcbiAgICAgICAgICAgIGNvbnN0IHRoZUJpdHMgPSBiaXRzW2JpdHNPZmZzZXRdO1xuICAgICAgICAgICAgbGV0IGJpdCA9IDA7XG4gICAgICAgICAgICB3aGlsZSAoKCh0aGVCaXRzIDw8ICgzMSAtIGJpdCkpICYgMHhGRkZGRkZGRikgPT09IDApIHtcbiAgICAgICAgICAgICAgICBiaXQrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHggKz0gYml0O1xuICAgICAgICAgICAgcmV0dXJuIEludDMyQXJyYXkuZnJvbShbeCwgeV0pO1xuICAgICAgICB9XG4gICAgICAgIGdldEJvdHRvbVJpZ2h0T25CaXQoKSB7XG4gICAgICAgICAgICBjb25zdCByb3dTaXplID0gdGhpcy5yb3dTaXplO1xuICAgICAgICAgICAgY29uc3QgYml0cyA9IHRoaXMuYml0cztcbiAgICAgICAgICAgIGxldCBiaXRzT2Zmc2V0ID0gYml0cy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgd2hpbGUgKGJpdHNPZmZzZXQgPj0gMCAmJiBiaXRzW2JpdHNPZmZzZXRdID09PSAwKSB7XG4gICAgICAgICAgICAgICAgYml0c09mZnNldC0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGJpdHNPZmZzZXQgPCAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCB5ID0gTWF0aC5mbG9vcihiaXRzT2Zmc2V0IC8gcm93U2l6ZSk7XG4gICAgICAgICAgICBsZXQgeCA9IE1hdGguZmxvb3IoYml0c09mZnNldCAlIHJvd1NpemUpICogMzI7XG4gICAgICAgICAgICBjb25zdCB0aGVCaXRzID0gYml0c1tiaXRzT2Zmc2V0XTtcbiAgICAgICAgICAgIGxldCBiaXQgPSAzMTtcbiAgICAgICAgICAgIHdoaWxlICgodGhlQml0cyA+Pj4gYml0KSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGJpdC0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgeCArPSBiaXQ7XG4gICAgICAgICAgICByZXR1cm4gSW50MzJBcnJheS5mcm9tKFt4LCB5XSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gVGhlIHdpZHRoIG9mIHRoZSBtYXRyaXhcbiAgICAgICAgICovXG4gICAgICAgIGdldFdpZHRoKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lkdGg7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gVGhlIGhlaWdodCBvZiB0aGUgbWF0cml4XG4gICAgICAgICAqL1xuICAgICAgICBnZXRIZWlnaHQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5oZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gVGhlIHJvdyBzaXplIG9mIHRoZSBtYXRyaXhcbiAgICAgICAgICovXG4gICAgICAgIGdldFJvd1NpemUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yb3dTaXplO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgZXF1YWxzKG8pIHtcbiAgICAgICAgICAgIGlmICghKG8gaW5zdGFuY2VvZiBCaXRNYXRyaXgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgb3RoZXIgPSBvO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lkdGggPT09IG90aGVyLndpZHRoICYmIHRoaXMuaGVpZ2h0ID09PSBvdGhlci5oZWlnaHQgJiYgdGhpcy5yb3dTaXplID09PSBvdGhlci5yb3dTaXplICYmXG4gICAgICAgICAgICAgICAgQXJyYXlzLmVxdWFscyh0aGlzLmJpdHMsIG90aGVyLmJpdHMpO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgaGFzaENvZGUoKSB7XG4gICAgICAgICAgICBsZXQgaGFzaCA9IHRoaXMud2lkdGg7XG4gICAgICAgICAgICBoYXNoID0gMzEgKiBoYXNoICsgdGhpcy53aWR0aDtcbiAgICAgICAgICAgIGhhc2ggPSAzMSAqIGhhc2ggKyB0aGlzLmhlaWdodDtcbiAgICAgICAgICAgIGhhc2ggPSAzMSAqIGhhc2ggKyB0aGlzLnJvd1NpemU7XG4gICAgICAgICAgICBoYXNoID0gMzEgKiBoYXNoICsgQXJyYXlzLmhhc2hDb2RlKHRoaXMuYml0cyk7XG4gICAgICAgICAgICByZXR1cm4gaGFzaDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBzdHJpbmcgcmVwcmVzZW50YXRpb24gdXNpbmcgXCJYXCIgZm9yIHNldCBhbmQgXCIgXCIgZm9yIHVuc2V0IGJpdHNcbiAgICAgICAgICovXG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgLy8gcHVibGljIHRvU3RyaW5nKCk6IHN0cmluZyB7XG4gICAgICAgIC8vICAgcmV0dXJuIHRvU3RyaW5nKFwiOiBcIlgsIFwiICBcIilcbiAgICAgICAgLy8gfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHNldFN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIHNldCBiaXRcbiAgICAgICAgICogQHBhcmFtIHVuc2V0U3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGFuIHVuc2V0IGJpdFxuICAgICAgICAgKiBAcmV0dXJuIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBlbnRpcmUgbWF0cml4IHV0aWxpemluZyBnaXZlbiBzdHJpbmdzXG4gICAgICAgICAqL1xuICAgICAgICAvLyBwdWJsaWMgdG9TdHJpbmcoc2V0U3RyaW5nOiBzdHJpbmcgPSBcIlggXCIsIHVuc2V0U3RyaW5nOiBzdHJpbmcgPSBcIiAgXCIpOiBzdHJpbmcge1xuICAgICAgICAvLyAgIHJldHVybiB0aGlzLmJ1aWxkVG9TdHJpbmcoc2V0U3RyaW5nLCB1bnNldFN0cmluZywgXCJcXG5cIilcbiAgICAgICAgLy8gfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHNldFN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIHNldCBiaXRcbiAgICAgICAgICogQHBhcmFtIHVuc2V0U3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGFuIHVuc2V0IGJpdFxuICAgICAgICAgKiBAcGFyYW0gbGluZVNlcGFyYXRvciBuZXdsaW5lIGNoYXJhY3RlciBpbiBzdHJpbmcgcmVwcmVzZW50YXRpb25cbiAgICAgICAgICogQHJldHVybiBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgZW50aXJlIG1hdHJpeCB1dGlsaXppbmcgZ2l2ZW4gc3RyaW5ncyBhbmQgbGluZSBzZXBhcmF0b3JcbiAgICAgICAgICogQGRlcHJlY2F0ZWQgY2FsbCB7QGxpbmsgI3RvU3RyaW5nKFN0cmluZyxTdHJpbmcpfSBvbmx5LCB3aGljaCB1c2VzIFxcbiBsaW5lIHNlcGFyYXRvciBhbHdheXNcbiAgICAgICAgICovXG4gICAgICAgIC8vIEBEZXByZWNhdGVkXG4gICAgICAgIHRvU3RyaW5nKHNldFN0cmluZyA9ICdYICcsIHVuc2V0U3RyaW5nID0gJyAgJywgbGluZVNlcGFyYXRvciA9ICdcXG4nKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5idWlsZFRvU3RyaW5nKHNldFN0cmluZywgdW5zZXRTdHJpbmcsIGxpbmVTZXBhcmF0b3IpO1xuICAgICAgICB9XG4gICAgICAgIGJ1aWxkVG9TdHJpbmcoc2V0U3RyaW5nLCB1bnNldFN0cmluZywgbGluZVNlcGFyYXRvcikge1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICAvLyByZXN1bHQuYXBwZW5kKGxpbmVTZXBhcmF0b3IpO1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDAsIGhlaWdodCA9IHRoaXMuaGVpZ2h0OyB5IDwgaGVpZ2h0OyB5KyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB4ID0gMCwgd2lkdGggPSB0aGlzLndpZHRoOyB4IDwgd2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKHRoaXMuZ2V0KHgsIHkpID8gc2V0U3RyaW5nIDogdW5zZXRTdHJpbmcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKGxpbmVTZXBhcmF0b3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC50b1N0cmluZygpO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgY2xvbmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEJpdE1hdHJpeCh0aGlzLndpZHRoLCB0aGlzLmhlaWdodCwgdGhpcy5yb3dTaXplLCB0aGlzLmJpdHMuc2xpY2UoKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDdXN0b20gRXJyb3IgY2xhc3Mgb2YgdHlwZSBFeGNlcHRpb24uXG4gICAgICovXG4gICAgY2xhc3MgTm90Rm91bmRFeGNlcHRpb24gZXh0ZW5kcyBFeGNlcHRpb24ge1xuICAgICAgICBzdGF0aWMgZ2V0Tm90Rm91bmRJbnN0YW5jZSgpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBOb3RGb3VuZEV4Y2VwdGlvbi5raW5kID0gJ05vdEZvdW5kRXhjZXB0aW9uJztcblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDkgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogVGhpcyBCaW5hcml6ZXIgaW1wbGVtZW50YXRpb24gdXNlcyB0aGUgb2xkIFpYaW5nIGdsb2JhbCBoaXN0b2dyYW0gYXBwcm9hY2guIEl0IGlzIHN1aXRhYmxlXG4gICAgICogZm9yIGxvdy1lbmQgbW9iaWxlIGRldmljZXMgd2hpY2ggZG9uJ3QgaGF2ZSBlbm91Z2ggQ1BVIG9yIG1lbW9yeSB0byB1c2UgYSBsb2NhbCB0aHJlc2hvbGRpbmdcbiAgICAgKiBhbGdvcml0aG0uIEhvd2V2ZXIsIGJlY2F1c2UgaXQgcGlja3MgYSBnbG9iYWwgYmxhY2sgcG9pbnQsIGl0IGNhbm5vdCBoYW5kbGUgZGlmZmljdWx0IHNoYWRvd3NcbiAgICAgKiBhbmQgZ3JhZGllbnRzLlxuICAgICAqXG4gICAgICogRmFzdGVyIG1vYmlsZSBkZXZpY2VzIGFuZCBhbGwgZGVza3RvcCBhcHBsaWNhdGlvbnMgc2hvdWxkIHByb2JhYmx5IHVzZSBIeWJyaWRCaW5hcml6ZXIgaW5zdGVhZC5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBHbG9iYWxIaXN0b2dyYW1CaW5hcml6ZXIgZXh0ZW5kcyBCaW5hcml6ZXIge1xuICAgICAgICBjb25zdHJ1Y3Rvcihzb3VyY2UpIHtcbiAgICAgICAgICAgIHN1cGVyKHNvdXJjZSk7XG4gICAgICAgICAgICB0aGlzLmx1bWluYW5jZXMgPSBHbG9iYWxIaXN0b2dyYW1CaW5hcml6ZXIuRU1QVFk7XG4gICAgICAgICAgICB0aGlzLmJ1Y2tldHMgPSBuZXcgSW50MzJBcnJheShHbG9iYWxIaXN0b2dyYW1CaW5hcml6ZXIuTFVNSU5BTkNFX0JVQ0tFVFMpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEFwcGxpZXMgc2ltcGxlIHNoYXJwZW5pbmcgdG8gdGhlIHJvdyBkYXRhIHRvIGltcHJvdmUgcGVyZm9ybWFuY2Ugb2YgdGhlIDFEIFJlYWRlcnMuXG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgZ2V0QmxhY2tSb3coeSAvKmludCovLCByb3cpIHtcbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZSA9IHRoaXMuZ2V0THVtaW5hbmNlU291cmNlKCk7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IHNvdXJjZS5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgaWYgKHJvdyA9PT0gdW5kZWZpbmVkIHx8IHJvdyA9PT0gbnVsbCB8fCByb3cuZ2V0U2l6ZSgpIDwgd2lkdGgpIHtcbiAgICAgICAgICAgICAgICByb3cgPSBuZXcgQml0QXJyYXkod2lkdGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcm93LmNsZWFyKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmluaXRBcnJheXMod2lkdGgpO1xuICAgICAgICAgICAgY29uc3QgbG9jYWxMdW1pbmFuY2VzID0gc291cmNlLmdldFJvdyh5LCB0aGlzLmx1bWluYW5jZXMpO1xuICAgICAgICAgICAgY29uc3QgbG9jYWxCdWNrZXRzID0gdGhpcy5idWNrZXRzO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgbG9jYWxCdWNrZXRzWyhsb2NhbEx1bWluYW5jZXNbeF0gJiAweGZmKSA+PiBHbG9iYWxIaXN0b2dyYW1CaW5hcml6ZXIuTFVNSU5BTkNFX1NISUZUXSsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYmxhY2tQb2ludCA9IEdsb2JhbEhpc3RvZ3JhbUJpbmFyaXplci5lc3RpbWF0ZUJsYWNrUG9pbnQobG9jYWxCdWNrZXRzKTtcbiAgICAgICAgICAgIGlmICh3aWR0aCA8IDMpIHtcbiAgICAgICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2UgZm9yIHZlcnkgc21hbGwgaW1hZ2VzXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICgobG9jYWxMdW1pbmFuY2VzW3hdICYgMHhmZikgPCBibGFja1BvaW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb3cuc2V0KHgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbGV0IGxlZnQgPSBsb2NhbEx1bWluYW5jZXNbMF0gJiAweGZmO1xuICAgICAgICAgICAgICAgIGxldCBjZW50ZXIgPSBsb2NhbEx1bWluYW5jZXNbMV0gJiAweGZmO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAxOyB4IDwgd2lkdGggLSAxOyB4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmlnaHQgPSBsb2NhbEx1bWluYW5jZXNbeCArIDFdICYgMHhmZjtcbiAgICAgICAgICAgICAgICAgICAgLy8gQSBzaW1wbGUgLTEgNCAtMSBib3ggZmlsdGVyIHdpdGggYSB3ZWlnaHQgb2YgMi5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCgoY2VudGVyICogNCkgLSBsZWZ0IC0gcmlnaHQpIC8gMiA8IGJsYWNrUG9pbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvdy5zZXQoeCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbGVmdCA9IGNlbnRlcjtcbiAgICAgICAgICAgICAgICAgICAgY2VudGVyID0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJvdztcbiAgICAgICAgfVxuICAgICAgICAvLyBEb2VzIG5vdCBzaGFycGVuIHRoZSBkYXRhLCBhcyB0aGlzIGNhbGwgaXMgaW50ZW5kZWQgdG8gb25seSBiZSB1c2VkIGJ5IDJEIFJlYWRlcnMuXG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgZ2V0QmxhY2tNYXRyaXgoKSB7XG4gICAgICAgICAgICBjb25zdCBzb3VyY2UgPSB0aGlzLmdldEx1bWluYW5jZVNvdXJjZSgpO1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBzb3VyY2UuZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHNvdXJjZS5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IG1hdHJpeCA9IG5ldyBCaXRNYXRyaXgod2lkdGgsIGhlaWdodCk7XG4gICAgICAgICAgICAvLyBRdWlja2x5IGNhbGN1bGF0ZXMgdGhlIGhpc3RvZ3JhbSBieSBzYW1wbGluZyBmb3VyIHJvd3MgZnJvbSB0aGUgaW1hZ2UuIFRoaXMgcHJvdmVkIHRvIGJlXG4gICAgICAgICAgICAvLyBtb3JlIHJvYnVzdCBvbiB0aGUgYmxhY2tib3ggdGVzdHMgdGhhbiBzYW1wbGluZyBhIGRpYWdvbmFsIGFzIHdlIHVzZWQgdG8gZG8uXG4gICAgICAgICAgICB0aGlzLmluaXRBcnJheXMod2lkdGgpO1xuICAgICAgICAgICAgY29uc3QgbG9jYWxCdWNrZXRzID0gdGhpcy5idWNrZXRzO1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDE7IHkgPCA1OyB5KyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCByb3cgPSBNYXRoLmZsb29yKChoZWlnaHQgKiB5KSAvIDUpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGxvY2FsTHVtaW5hbmNlcyA9IHNvdXJjZS5nZXRSb3cocm93LCB0aGlzLmx1bWluYW5jZXMpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJpZ2h0ID0gTWF0aC5mbG9vcigod2lkdGggKiA0KSAvIDUpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSBNYXRoLmZsb29yKHdpZHRoIC8gNSk7IHggPCByaWdodDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBpeGVsID0gbG9jYWxMdW1pbmFuY2VzW3hdICYgMHhmZjtcbiAgICAgICAgICAgICAgICAgICAgbG9jYWxCdWNrZXRzW3BpeGVsID4+IEdsb2JhbEhpc3RvZ3JhbUJpbmFyaXplci5MVU1JTkFOQ0VfU0hJRlRdKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYmxhY2tQb2ludCA9IEdsb2JhbEhpc3RvZ3JhbUJpbmFyaXplci5lc3RpbWF0ZUJsYWNrUG9pbnQobG9jYWxCdWNrZXRzKTtcbiAgICAgICAgICAgIC8vIFdlIGRlbGF5IHJlYWRpbmcgdGhlIGVudGlyZSBpbWFnZSBsdW1pbmFuY2UgdW50aWwgdGhlIGJsYWNrIHBvaW50IGVzdGltYXRpb24gc3VjY2VlZHMuXG4gICAgICAgICAgICAvLyBBbHRob3VnaCB3ZSBlbmQgdXAgcmVhZGluZyBmb3VyIHJvd3MgdHdpY2UsIGl0IGlzIGNvbnNpc3RlbnQgd2l0aCBvdXIgbW90dG8gb2ZcbiAgICAgICAgICAgIC8vIFwiZmFpbCBxdWlja2x5XCIgd2hpY2ggaXMgbmVjZXNzYXJ5IGZvciBjb250aW51b3VzIHNjYW5uaW5nLlxuICAgICAgICAgICAgY29uc3QgbG9jYWxMdW1pbmFuY2VzID0gc291cmNlLmdldE1hdHJpeCgpO1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHkgKiB3aWR0aDtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IHdpZHRoOyB4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGl4ZWwgPSBsb2NhbEx1bWluYW5jZXNbb2Zmc2V0ICsgeF0gJiAweGZmO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGl4ZWwgPCBibGFja1BvaW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KHgsIHkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1hdHJpeDtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGNyZWF0ZUJpbmFyaXplcihzb3VyY2UpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgR2xvYmFsSGlzdG9ncmFtQmluYXJpemVyKHNvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgICAgaW5pdEFycmF5cyhsdW1pbmFuY2VTaXplIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmx1bWluYW5jZXMubGVuZ3RoIDwgbHVtaW5hbmNlU2l6ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMubHVtaW5hbmNlcyA9IG5ldyBVaW50OENsYW1wZWRBcnJheShsdW1pbmFuY2VTaXplKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGJ1Y2tldHMgPSB0aGlzLmJ1Y2tldHM7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IEdsb2JhbEhpc3RvZ3JhbUJpbmFyaXplci5MVU1JTkFOQ0VfQlVDS0VUUzsgeCsrKSB7XG4gICAgICAgICAgICAgICAgYnVja2V0c1t4XSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGVzdGltYXRlQmxhY2tQb2ludChidWNrZXRzKSB7XG4gICAgICAgICAgICAvLyBGaW5kIHRoZSB0YWxsZXN0IHBlYWsgaW4gdGhlIGhpc3RvZ3JhbS5cbiAgICAgICAgICAgIGNvbnN0IG51bUJ1Y2tldHMgPSBidWNrZXRzLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBtYXhCdWNrZXRDb3VudCA9IDA7XG4gICAgICAgICAgICBsZXQgZmlyc3RQZWFrID0gMDtcbiAgICAgICAgICAgIGxldCBmaXJzdFBlYWtTaXplID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgbnVtQnVja2V0czsgeCsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGJ1Y2tldHNbeF0gPiBmaXJzdFBlYWtTaXplKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpcnN0UGVhayA9IHg7XG4gICAgICAgICAgICAgICAgICAgIGZpcnN0UGVha1NpemUgPSBidWNrZXRzW3hdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYnVja2V0c1t4XSA+IG1heEJ1Y2tldENvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgIG1heEJ1Y2tldENvdW50ID0gYnVja2V0c1t4XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBGaW5kIHRoZSBzZWNvbmQtdGFsbGVzdCBwZWFrIHdoaWNoIGlzIHNvbWV3aGF0IGZhciBmcm9tIHRoZSB0YWxsZXN0IHBlYWsuXG4gICAgICAgICAgICBsZXQgc2Vjb25kUGVhayA9IDA7XG4gICAgICAgICAgICBsZXQgc2Vjb25kUGVha1Njb3JlID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgbnVtQnVja2V0czsgeCsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGlzdGFuY2VUb0JpZ2dlc3QgPSB4IC0gZmlyc3RQZWFrO1xuICAgICAgICAgICAgICAgIC8vIEVuY291cmFnZSBtb3JlIGRpc3RhbnQgc2Vjb25kIHBlYWtzIGJ5IG11bHRpcGx5aW5nIGJ5IHNxdWFyZSBvZiBkaXN0YW5jZS5cbiAgICAgICAgICAgICAgICBjb25zdCBzY29yZSA9IGJ1Y2tldHNbeF0gKiBkaXN0YW5jZVRvQmlnZ2VzdCAqIGRpc3RhbmNlVG9CaWdnZXN0O1xuICAgICAgICAgICAgICAgIGlmIChzY29yZSA+IHNlY29uZFBlYWtTY29yZSkge1xuICAgICAgICAgICAgICAgICAgICBzZWNvbmRQZWFrID0geDtcbiAgICAgICAgICAgICAgICAgICAgc2Vjb25kUGVha1Njb3JlID0gc2NvcmU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIGZpcnN0UGVhayBjb3JyZXNwb25kcyB0byB0aGUgYmxhY2sgcGVhay5cbiAgICAgICAgICAgIGlmIChmaXJzdFBlYWsgPiBzZWNvbmRQZWFrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdGVtcCA9IGZpcnN0UGVhaztcbiAgICAgICAgICAgICAgICBmaXJzdFBlYWsgPSBzZWNvbmRQZWFrO1xuICAgICAgICAgICAgICAgIHNlY29uZFBlYWsgPSB0ZW1wO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSWYgdGhlcmUgaXMgdG9vIGxpdHRsZSBjb250cmFzdCBpbiB0aGUgaW1hZ2UgdG8gcGljayBhIG1lYW5pbmdmdWwgYmxhY2sgcG9pbnQsIHRocm93IHJhdGhlclxuICAgICAgICAgICAgLy8gdGhhbiB3YXN0ZSB0aW1lIHRyeWluZyB0byBkZWNvZGUgdGhlIGltYWdlLCBhbmQgcmlzayBmYWxzZSBwb3NpdGl2ZXMuXG4gICAgICAgICAgICBpZiAoc2Vjb25kUGVhayAtIGZpcnN0UGVhayA8PSBudW1CdWNrZXRzIC8gMTYpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEZpbmQgYSB2YWxsZXkgYmV0d2VlbiB0aGVtIHRoYXQgaXMgbG93IGFuZCBjbG9zZXIgdG8gdGhlIHdoaXRlIHBlYWsuXG4gICAgICAgICAgICBsZXQgYmVzdFZhbGxleSA9IHNlY29uZFBlYWsgLSAxO1xuICAgICAgICAgICAgbGV0IGJlc3RWYWxsZXlTY29yZSA9IC0xO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IHNlY29uZFBlYWsgLSAxOyB4ID4gZmlyc3RQZWFrOyB4LS0pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmcm9tRmlyc3QgPSB4IC0gZmlyc3RQZWFrO1xuICAgICAgICAgICAgICAgIGNvbnN0IHNjb3JlID0gZnJvbUZpcnN0ICogZnJvbUZpcnN0ICogKHNlY29uZFBlYWsgLSB4KSAqIChtYXhCdWNrZXRDb3VudCAtIGJ1Y2tldHNbeF0pO1xuICAgICAgICAgICAgICAgIGlmIChzY29yZSA+IGJlc3RWYWxsZXlTY29yZSkge1xuICAgICAgICAgICAgICAgICAgICBiZXN0VmFsbGV5ID0geDtcbiAgICAgICAgICAgICAgICAgICAgYmVzdFZhbGxleVNjb3JlID0gc2NvcmU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGJlc3RWYWxsZXkgPDwgR2xvYmFsSGlzdG9ncmFtQmluYXJpemVyLkxVTUlOQU5DRV9TSElGVDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBHbG9iYWxIaXN0b2dyYW1CaW5hcml6ZXIuTFVNSU5BTkNFX0JJVFMgPSA1O1xuICAgIEdsb2JhbEhpc3RvZ3JhbUJpbmFyaXplci5MVU1JTkFOQ0VfU0hJRlQgPSA4IC0gR2xvYmFsSGlzdG9ncmFtQmluYXJpemVyLkxVTUlOQU5DRV9CSVRTO1xuICAgIEdsb2JhbEhpc3RvZ3JhbUJpbmFyaXplci5MVU1JTkFOQ0VfQlVDS0VUUyA9IDEgPDwgR2xvYmFsSGlzdG9ncmFtQmluYXJpemVyLkxVTUlOQU5DRV9CSVRTO1xuICAgIEdsb2JhbEhpc3RvZ3JhbUJpbmFyaXplci5FTVBUWSA9IFVpbnQ4Q2xhbXBlZEFycmF5LmZyb20oWzBdKTtcblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDkgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogVGhpcyBjbGFzcyBpbXBsZW1lbnRzIGEgbG9jYWwgdGhyZXNob2xkaW5nIGFsZ29yaXRobSwgd2hpY2ggd2hpbGUgc2xvd2VyIHRoYW4gdGhlXG4gICAgICogR2xvYmFsSGlzdG9ncmFtQmluYXJpemVyLCBpcyBmYWlybHkgZWZmaWNpZW50IGZvciB3aGF0IGl0IGRvZXMuIEl0IGlzIGRlc2lnbmVkIGZvclxuICAgICAqIGhpZ2ggZnJlcXVlbmN5IGltYWdlcyBvZiBiYXJjb2RlcyB3aXRoIGJsYWNrIGRhdGEgb24gd2hpdGUgYmFja2dyb3VuZHMuIEZvciB0aGlzIGFwcGxpY2F0aW9uLFxuICAgICAqIGl0IGRvZXMgYSBtdWNoIGJldHRlciBqb2IgdGhhbiBhIGdsb2JhbCBibGFja3BvaW50IHdpdGggc2V2ZXJlIHNoYWRvd3MgYW5kIGdyYWRpZW50cy5cbiAgICAgKiBIb3dldmVyIGl0IHRlbmRzIHRvIHByb2R1Y2UgYXJ0aWZhY3RzIG9uIGxvd2VyIGZyZXF1ZW5jeSBpbWFnZXMgYW5kIGlzIHRoZXJlZm9yZSBub3RcbiAgICAgKiBhIGdvb2QgZ2VuZXJhbCBwdXJwb3NlIGJpbmFyaXplciBmb3IgdXNlcyBvdXRzaWRlIFpYaW5nLlxuICAgICAqXG4gICAgICogVGhpcyBjbGFzcyBleHRlbmRzIEdsb2JhbEhpc3RvZ3JhbUJpbmFyaXplciwgdXNpbmcgdGhlIG9sZGVyIGhpc3RvZ3JhbSBhcHByb2FjaCBmb3IgMUQgcmVhZGVycyxcbiAgICAgKiBhbmQgdGhlIG5ld2VyIGxvY2FsIGFwcHJvYWNoIGZvciAyRCByZWFkZXJzLiAxRCBkZWNvZGluZyB1c2luZyBhIHBlci1yb3cgaGlzdG9ncmFtIGlzIGFscmVhZHlcbiAgICAgKiBpbmhlcmVudGx5IGxvY2FsLCBhbmQgb25seSBmYWlscyBmb3IgaG9yaXpvbnRhbCBncmFkaWVudHMuIFdlIGNhbiByZXZpc2l0IHRoYXQgcHJvYmxlbSBsYXRlcixcbiAgICAgKiBidXQgZm9yIG5vdyBpdCB3YXMgbm90IGEgd2luIHRvIHVzZSBsb2NhbCBibG9ja3MgZm9yIDFELlxuICAgICAqXG4gICAgICogVGhpcyBCaW5hcml6ZXIgaXMgdGhlIGRlZmF1bHQgZm9yIHRoZSB1bml0IHRlc3RzIGFuZCB0aGUgcmVjb21tZW5kZWQgY2xhc3MgZm9yIGxpYnJhcnkgdXNlcnMuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIGRzd2l0a2luQGdvb2dsZS5jb20gKERhbmllbCBTd2l0a2luKVxuICAgICAqL1xuICAgIGNsYXNzIEh5YnJpZEJpbmFyaXplciBleHRlbmRzIEdsb2JhbEhpc3RvZ3JhbUJpbmFyaXplciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHNvdXJjZSkge1xuICAgICAgICAgICAgc3VwZXIoc291cmNlKTtcbiAgICAgICAgICAgIHRoaXMubWF0cml4ID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ2FsY3VsYXRlcyB0aGUgZmluYWwgQml0TWF0cml4IG9uY2UgZm9yIGFsbCByZXF1ZXN0cy4gVGhpcyBjb3VsZCBiZSBjYWxsZWQgb25jZSBmcm9tIHRoZVxuICAgICAgICAgKiBjb25zdHJ1Y3RvciBpbnN0ZWFkLCBidXQgdGhlcmUgYXJlIHNvbWUgYWR2YW50YWdlcyB0byBkb2luZyBpdCBsYXppbHksIHN1Y2ggYXMgbWFraW5nXG4gICAgICAgICAqIHByb2ZpbGluZyBlYXNpZXIsIGFuZCBub3QgZG9pbmcgaGVhdnkgbGlmdGluZyB3aGVuIGNhbGxlcnMgZG9uJ3QgZXhwZWN0IGl0LlxuICAgICAgICAgKi9cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBnZXRCbGFja01hdHJpeCgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLm1hdHJpeCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm1hdHJpeDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZSA9IHRoaXMuZ2V0THVtaW5hbmNlU291cmNlKCk7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IHNvdXJjZS5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gc291cmNlLmdldEhlaWdodCgpO1xuICAgICAgICAgICAgaWYgKHdpZHRoID49IEh5YnJpZEJpbmFyaXplci5NSU5JTVVNX0RJTUVOU0lPTiAmJiBoZWlnaHQgPj0gSHlicmlkQmluYXJpemVyLk1JTklNVU1fRElNRU5TSU9OKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbHVtaW5hbmNlcyA9IHNvdXJjZS5nZXRNYXRyaXgoKTtcbiAgICAgICAgICAgICAgICBsZXQgc3ViV2lkdGggPSB3aWR0aCA+PiBIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRV9QT1dFUjtcbiAgICAgICAgICAgICAgICBpZiAoKHdpZHRoICYgSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkVfTUFTSykgIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgc3ViV2lkdGgrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IHN1YkhlaWdodCA9IGhlaWdodCA+PiBIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRV9QT1dFUjtcbiAgICAgICAgICAgICAgICBpZiAoKGhlaWdodCAmIEh5YnJpZEJpbmFyaXplci5CTE9DS19TSVpFX01BU0spICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHN1YkhlaWdodCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBibGFja1BvaW50cyA9IEh5YnJpZEJpbmFyaXplci5jYWxjdWxhdGVCbGFja1BvaW50cyhsdW1pbmFuY2VzLCBzdWJXaWR0aCwgc3ViSGVpZ2h0LCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdNYXRyaXggPSBuZXcgQml0TWF0cml4KHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgICAgIEh5YnJpZEJpbmFyaXplci5jYWxjdWxhdGVUaHJlc2hvbGRGb3JCbG9jayhsdW1pbmFuY2VzLCBzdWJXaWR0aCwgc3ViSGVpZ2h0LCB3aWR0aCwgaGVpZ2h0LCBibGFja1BvaW50cywgbmV3TWF0cml4KTtcbiAgICAgICAgICAgICAgICB0aGlzLm1hdHJpeCA9IG5ld01hdHJpeDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBpbWFnZSBpcyB0b28gc21hbGwsIGZhbGwgYmFjayB0byB0aGUgZ2xvYmFsIGhpc3RvZ3JhbSBhcHByb2FjaC5cbiAgICAgICAgICAgICAgICB0aGlzLm1hdHJpeCA9IHN1cGVyLmdldEJsYWNrTWF0cml4KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXRyaXg7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBjcmVhdGVCaW5hcml6ZXIoc291cmNlKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEh5YnJpZEJpbmFyaXplcihzb3VyY2UpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBGb3IgZWFjaCBibG9jayBpbiB0aGUgaW1hZ2UsIGNhbGN1bGF0ZSB0aGUgYXZlcmFnZSBibGFjayBwb2ludCB1c2luZyBhIDV4NSBncmlkXG4gICAgICAgICAqIG9mIHRoZSBibG9ja3MgYXJvdW5kIGl0LiBBbHNvIGhhbmRsZXMgdGhlIGNvcm5lciBjYXNlcyAoZnJhY3Rpb25hbCBibG9ja3MgYXJlIGNvbXB1dGVkIGJhc2VkXG4gICAgICAgICAqIG9uIHRoZSBsYXN0IHBpeGVscyBpbiB0aGUgcm93L2NvbHVtbiB3aGljaCBhcmUgYWxzbyB1c2VkIGluIHRoZSBwcmV2aW91cyBibG9jaykuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgY2FsY3VsYXRlVGhyZXNob2xkRm9yQmxvY2sobHVtaW5hbmNlcywgc3ViV2lkdGggLyppbnQqLywgc3ViSGVpZ2h0IC8qaW50Ki8sIHdpZHRoIC8qaW50Ki8sIGhlaWdodCAvKmludCovLCBibGFja1BvaW50cywgbWF0cml4KSB7XG4gICAgICAgICAgICBjb25zdCBtYXhZT2Zmc2V0ID0gaGVpZ2h0IC0gSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkU7XG4gICAgICAgICAgICBjb25zdCBtYXhYT2Zmc2V0ID0gd2lkdGggLSBIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRTtcbiAgICAgICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgc3ViSGVpZ2h0OyB5KyspIHtcbiAgICAgICAgICAgICAgICBsZXQgeW9mZnNldCA9IHkgPDwgSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkVfUE9XRVI7XG4gICAgICAgICAgICAgICAgaWYgKHlvZmZzZXQgPiBtYXhZT2Zmc2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHlvZmZzZXQgPSBtYXhZT2Zmc2V0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCB0b3AgPSBIeWJyaWRCaW5hcml6ZXIuY2FwKHksIDIsIHN1YkhlaWdodCAtIDMpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgc3ViV2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgeG9mZnNldCA9IHggPDwgSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkVfUE9XRVI7XG4gICAgICAgICAgICAgICAgICAgIGlmICh4b2Zmc2V0ID4gbWF4WE9mZnNldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgeG9mZnNldCA9IG1heFhPZmZzZXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGVmdCA9IEh5YnJpZEJpbmFyaXplci5jYXAoeCwgMiwgc3ViV2lkdGggLSAzKTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHN1bSA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IHogPSAtMjsgeiA8PSAyOyB6KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJsYWNrUm93ID0gYmxhY2tQb2ludHNbdG9wICsgel07XG4gICAgICAgICAgICAgICAgICAgICAgICBzdW0gKz0gYmxhY2tSb3dbbGVmdCAtIDJdICsgYmxhY2tSb3dbbGVmdCAtIDFdICsgYmxhY2tSb3dbbGVmdF0gKyBibGFja1Jvd1tsZWZ0ICsgMV0gKyBibGFja1Jvd1tsZWZ0ICsgMl07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYXZlcmFnZSA9IHN1bSAvIDI1O1xuICAgICAgICAgICAgICAgICAgICBIeWJyaWRCaW5hcml6ZXIudGhyZXNob2xkQmxvY2sobHVtaW5hbmNlcywgeG9mZnNldCwgeW9mZnNldCwgYXZlcmFnZSwgd2lkdGgsIG1hdHJpeCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBjYXAodmFsdWUgLyppbnQqLywgbWluIC8qaW50Ki8sIG1heCAvKmludCovKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWUgPCBtaW4gPyBtaW4gOiB2YWx1ZSA+IG1heCA/IG1heCA6IHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBcHBsaWVzIGEgc2luZ2xlIHRocmVzaG9sZCB0byBhIGJsb2NrIG9mIHBpeGVscy5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyB0aHJlc2hvbGRCbG9jayhsdW1pbmFuY2VzLCB4b2Zmc2V0IC8qaW50Ki8sIHlvZmZzZXQgLyppbnQqLywgdGhyZXNob2xkIC8qaW50Ki8sIHN0cmlkZSAvKmludCovLCBtYXRyaXgpIHtcbiAgICAgICAgICAgIGZvciAobGV0IHkgPSAwLCBvZmZzZXQgPSB5b2Zmc2V0ICogc3RyaWRlICsgeG9mZnNldDsgeSA8IEh5YnJpZEJpbmFyaXplci5CTE9DS19TSVpFOyB5KyssIG9mZnNldCArPSBzdHJpZGUpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IEh5YnJpZEJpbmFyaXplci5CTE9DS19TSVpFOyB4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQ29tcGFyaXNvbiBuZWVkcyB0byBiZSA8PSBzbyB0aGF0IGJsYWNrID09IDAgcGl4ZWxzIGFyZSBibGFjayBldmVuIGlmIHRoZSB0aHJlc2hvbGQgaXMgMC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKChsdW1pbmFuY2VzW29mZnNldCArIHhdICYgMHhGRikgPD0gdGhyZXNob2xkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KHhvZmZzZXQgKyB4LCB5b2Zmc2V0ICsgeSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENhbGN1bGF0ZXMgYSBzaW5nbGUgYmxhY2sgcG9pbnQgZm9yIGVhY2ggYmxvY2sgb2YgcGl4ZWxzIGFuZCBzYXZlcyBpdCBhd2F5LlxuICAgICAgICAgKiBTZWUgdGhlIGZvbGxvd2luZyB0aHJlYWQgZm9yIGEgZGlzY3Vzc2lvbiBvZiB0aGlzIGFsZ29yaXRobTpcbiAgICAgICAgICogIGh0dHA6Ly9ncm91cHMuZ29vZ2xlLmNvbS9ncm91cC96eGluZy9icm93c2VfdGhyZWFkL3RocmVhZC9kMDZlZmEyYzM1YTdkZGMwXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgY2FsY3VsYXRlQmxhY2tQb2ludHMobHVtaW5hbmNlcywgc3ViV2lkdGggLyppbnQqLywgc3ViSGVpZ2h0IC8qaW50Ki8sIHdpZHRoIC8qaW50Ki8sIGhlaWdodCAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBtYXhZT2Zmc2V0ID0gaGVpZ2h0IC0gSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkU7XG4gICAgICAgICAgICBjb25zdCBtYXhYT2Zmc2V0ID0gd2lkdGggLSBIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRTtcbiAgICAgICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTp3aGl0ZXNwYWNlXG4gICAgICAgICAgICBjb25zdCBibGFja1BvaW50cyA9IG5ldyBBcnJheShzdWJIZWlnaHQpOyAvLyBzdWJXaWR0aFxuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCBzdWJIZWlnaHQ7IHkrKykge1xuICAgICAgICAgICAgICAgIGJsYWNrUG9pbnRzW3ldID0gbmV3IEludDMyQXJyYXkoc3ViV2lkdGgpO1xuICAgICAgICAgICAgICAgIGxldCB5b2Zmc2V0ID0geSA8PCBIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRV9QT1dFUjtcbiAgICAgICAgICAgICAgICBpZiAoeW9mZnNldCA+IG1heFlPZmZzZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgeW9mZnNldCA9IG1heFlPZmZzZXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgc3ViV2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgeG9mZnNldCA9IHggPDwgSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkVfUE9XRVI7XG4gICAgICAgICAgICAgICAgICAgIGlmICh4b2Zmc2V0ID4gbWF4WE9mZnNldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgeG9mZnNldCA9IG1heFhPZmZzZXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbGV0IHN1bSA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGxldCBtaW4gPSAweEZGO1xuICAgICAgICAgICAgICAgICAgICBsZXQgbWF4ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgeXkgPSAwLCBvZmZzZXQgPSB5b2Zmc2V0ICogd2lkdGggKyB4b2Zmc2V0OyB5eSA8IEh5YnJpZEJpbmFyaXplci5CTE9DS19TSVpFOyB5eSsrLCBvZmZzZXQgKz0gd2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IHh4ID0gMDsgeHggPCBIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRTsgeHgrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBpeGVsID0gbHVtaW5hbmNlc1tvZmZzZXQgKyB4eF0gJiAweEZGO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1bSArPSBwaXhlbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBzdGlsbCBsb29raW5nIGZvciBnb29kIGNvbnRyYXN0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBpeGVsIDwgbWluKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbiA9IHBpeGVsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocGl4ZWwgPiBtYXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4ID0gcGl4ZWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2hvcnQtY2lyY3VpdCBtaW4vbWF4IHRlc3RzIG9uY2UgZHluYW1pYyByYW5nZSBpcyBtZXRcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXggLSBtaW4gPiBIeWJyaWRCaW5hcml6ZXIuTUlOX0RZTkFNSUNfUkFOR0UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBmaW5pc2ggdGhlIHJlc3Qgb2YgdGhlIHJvd3MgcXVpY2tseVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoeXkrKywgb2Zmc2V0ICs9IHdpZHRoOyB5eSA8IEh5YnJpZEJpbmFyaXplci5CTE9DS19TSVpFOyB5eSsrLCBvZmZzZXQgKz0gd2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgeHggPSAwOyB4eCA8IEh5YnJpZEJpbmFyaXplci5CTE9DS19TSVpFOyB4eCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdW0gKz0gbHVtaW5hbmNlc1tvZmZzZXQgKyB4eF0gJiAweEZGO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSBkZWZhdWx0IGVzdGltYXRlIGlzIHRoZSBhdmVyYWdlIG9mIHRoZSB2YWx1ZXMgaW4gdGhlIGJsb2NrLlxuICAgICAgICAgICAgICAgICAgICBsZXQgYXZlcmFnZSA9IHN1bSA+PiAoSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkVfUE9XRVIgKiAyKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1heCAtIG1pbiA8PSBIeWJyaWRCaW5hcml6ZXIuTUlOX0RZTkFNSUNfUkFOR0UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHZhcmlhdGlvbiB3aXRoaW4gdGhlIGJsb2NrIGlzIGxvdywgYXNzdW1lIHRoaXMgaXMgYSBibG9jayB3aXRoIG9ubHkgbGlnaHQgb3Igb25seVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZGFyayBwaXhlbHMuIEluIHRoYXQgY2FzZSB3ZSBkbyBub3Qgd2FudCB0byB1c2UgdGhlIGF2ZXJhZ2UsIGFzIGl0IHdvdWxkIGRpdmlkZSB0aGlzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBsb3cgY29udHJhc3QgYXJlYSBpbnRvIGJsYWNrIGFuZCB3aGl0ZSBwaXhlbHMsIGVzc2VudGlhbGx5IGNyZWF0aW5nIGRhdGEgb3V0IG9mIG5vaXNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBkZWZhdWx0IGFzc3VtcHRpb24gaXMgdGhhdCB0aGUgYmxvY2sgaXMgbGlnaHQvYmFja2dyb3VuZC4gU2luY2Ugbm8gZXN0aW1hdGUgZm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgbGV2ZWwgb2YgZGFyayBwaXhlbHMgZXhpc3RzIGxvY2FsbHksIHVzZSBoYWxmIHRoZSBtaW4gZm9yIHRoZSBibG9jay5cbiAgICAgICAgICAgICAgICAgICAgICAgIGF2ZXJhZ2UgPSBtaW4gLyAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHkgPiAwICYmIHggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ29ycmVjdCB0aGUgXCJ3aGl0ZSBiYWNrZ3JvdW5kXCIgYXNzdW1wdGlvbiBmb3IgYmxvY2tzIHRoYXQgaGF2ZSBuZWlnaGJvcnMgYnkgY29tcGFyaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHBpeGVscyBpbiB0aGlzIGJsb2NrIHRvIHRoZSBwcmV2aW91c2x5IGNhbGN1bGF0ZWQgYmxhY2sgcG9pbnRzLiBUaGlzIGlzIGJhc2VkIG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGZhY3QgdGhhdCBkYXJrIGJhcmNvZGUgc3ltYm9sb2d5IGlzIGFsd2F5cyBzdXJyb3VuZGVkIGJ5IHNvbWUgYW1vdW50IG9mIGxpZ2h0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYmFja2dyb3VuZCBmb3Igd2hpY2ggcmVhc29uYWJsZSBibGFjayBwb2ludCBlc3RpbWF0ZXMgd2VyZSBtYWRlLiBUaGUgYnAgZXN0aW1hdGVkIGF0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGJvdW5kYXJpZXMgaXMgdXNlZCBmb3IgdGhlIGludGVyaW9yLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSAobWluIDwgYnApIGlzIGFyYml0cmFyeSBidXQgd29ya3MgYmV0dGVyIHRoYW4gb3RoZXIgaGV1cmlzdGljcyB0aGF0IHdlcmUgdHJpZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXZlcmFnZU5laWdoYm9yQmxhY2tQb2ludCA9IChibGFja1BvaW50c1t5IC0gMV1beF0gKyAoMiAqIGJsYWNrUG9pbnRzW3ldW3ggLSAxXSkgKyBibGFja1BvaW50c1t5IC0gMV1beCAtIDFdKSAvIDQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1pbiA8IGF2ZXJhZ2VOZWlnaGJvckJsYWNrUG9pbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXZlcmFnZSA9IGF2ZXJhZ2VOZWlnaGJvckJsYWNrUG9pbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJsYWNrUG9pbnRzW3ldW3hdID0gYXZlcmFnZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYmxhY2tQb2ludHM7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gVGhpcyBjbGFzcyB1c2VzIDV4NSBibG9ja3MgdG8gY29tcHV0ZSBsb2NhbCBsdW1pbmFuY2UsIHdoZXJlIGVhY2ggYmxvY2sgaXMgOHg4IHBpeGVscy5cbiAgICAvLyBTbyB0aGlzIGlzIHRoZSBzbWFsbGVzdCBkaW1lbnNpb24gaW4gZWFjaCBheGlzIHdlIGNhbiBhY2NlcHQuXG4gICAgSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkVfUE9XRVIgPSAzO1xuICAgIEh5YnJpZEJpbmFyaXplci5CTE9DS19TSVpFID0gMSA8PCBIeWJyaWRCaW5hcml6ZXIuQkxPQ0tfU0laRV9QT1dFUjsgLy8gLi4uMDEwMC4uLjAwXG4gICAgSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkVfTUFTSyA9IEh5YnJpZEJpbmFyaXplci5CTE9DS19TSVpFIC0gMTsgLy8gLi4uMDAxMS4uLjExXG4gICAgSHlicmlkQmluYXJpemVyLk1JTklNVU1fRElNRU5TSU9OID0gSHlicmlkQmluYXJpemVyLkJMT0NLX1NJWkUgKiA1O1xuICAgIEh5YnJpZEJpbmFyaXplci5NSU5fRFlOQU1JQ19SQU5HRSA9IDI0O1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwOSBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKm5hbWVzcGFjZSBjb20uZ29vZ2xlLnp4aW5nIHsqL1xuICAgIC8qKlxuICAgICAqIFRoZSBwdXJwb3NlIG9mIHRoaXMgY2xhc3MgaGllcmFyY2h5IGlzIHRvIGFic3RyYWN0IGRpZmZlcmVudCBiaXRtYXAgaW1wbGVtZW50YXRpb25zIGFjcm9zc1xuICAgICAqIHBsYXRmb3JtcyBpbnRvIGEgc3RhbmRhcmQgaW50ZXJmYWNlIGZvciByZXF1ZXN0aW5nIGdyZXlzY2FsZSBsdW1pbmFuY2UgdmFsdWVzLiBUaGUgaW50ZXJmYWNlXG4gICAgICogb25seSBwcm92aWRlcyBpbW11dGFibGUgbWV0aG9kczsgdGhlcmVmb3JlIGNyb3AgYW5kIHJvdGF0aW9uIGNyZWF0ZSBjb3BpZXMuIFRoaXMgaXMgdG8gZW5zdXJlXG4gICAgICogdGhhdCBvbmUgUmVhZGVyIGRvZXMgbm90IG1vZGlmeSB0aGUgb3JpZ2luYWwgbHVtaW5hbmNlIHNvdXJjZSBhbmQgbGVhdmUgaXQgaW4gYW4gdW5rbm93biBzdGF0ZVxuICAgICAqIGZvciBvdGhlciBSZWFkZXJzIGluIHRoZSBjaGFpbi5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pXG4gICAgICovXG4gICAgY2xhc3MgTHVtaW5hbmNlU291cmNlIHtcbiAgICAgICAgY29uc3RydWN0b3Iod2lkdGggLyppbnQqLywgaGVpZ2h0IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHRoaXMud2lkdGggPSB3aWR0aDtcbiAgICAgICAgICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIFRoZSB3aWR0aCBvZiB0aGUgYml0bWFwLlxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0V2lkdGgoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aWR0aDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBUaGUgaGVpZ2h0IG9mIHRoZSBiaXRtYXAuXG4gICAgICAgICAqL1xuICAgICAgICBnZXRIZWlnaHQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5oZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGlzIHN1YmNsYXNzIHN1cHBvcnRzIGNyb3BwaW5nLlxuICAgICAgICAgKi9cbiAgICAgICAgaXNDcm9wU3VwcG9ydGVkKCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXR1cm5zIGEgbmV3IG9iamVjdCB3aXRoIGNyb3BwZWQgaW1hZ2UgZGF0YS4gSW1wbGVtZW50YXRpb25zIG1heSBrZWVwIGEgcmVmZXJlbmNlIHRvIHRoZVxuICAgICAgICAgKiBvcmlnaW5hbCBkYXRhIHJhdGhlciB0aGFuIGEgY29weS4gT25seSBjYWxsYWJsZSBpZiBpc0Nyb3BTdXBwb3J0ZWQoKSBpcyB0cnVlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gbGVmdCBUaGUgbGVmdCBjb29yZGluYXRlLCB3aGljaCBtdXN0IGJlIGluIFswLGdldFdpZHRoKCkpXG4gICAgICAgICAqIEBwYXJhbSB0b3AgVGhlIHRvcCBjb29yZGluYXRlLCB3aGljaCBtdXN0IGJlIGluIFswLGdldEhlaWdodCgpKVxuICAgICAgICAgKiBAcGFyYW0gd2lkdGggVGhlIHdpZHRoIG9mIHRoZSByZWN0YW5nbGUgdG8gY3JvcC5cbiAgICAgICAgICogQHBhcmFtIGhlaWdodCBUaGUgaGVpZ2h0IG9mIHRoZSByZWN0YW5nbGUgdG8gY3JvcC5cbiAgICAgICAgICogQHJldHVybiBBIGNyb3BwZWQgdmVyc2lvbiBvZiB0aGlzIG9iamVjdC5cbiAgICAgICAgICovXG4gICAgICAgIGNyb3AobGVmdCAvKmludCovLCB0b3AgLyppbnQqLywgd2lkdGggLyppbnQqLywgaGVpZ2h0IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZE9wZXJhdGlvbkV4Y2VwdGlvbignVGhpcyBsdW1pbmFuY2Ugc291cmNlIGRvZXMgbm90IHN1cHBvcnQgY3JvcHBpbmcuJyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gV2hldGhlciB0aGlzIHN1YmNsYXNzIHN1cHBvcnRzIGNvdW50ZXItY2xvY2t3aXNlIHJvdGF0aW9uLlxuICAgICAgICAgKi9cbiAgICAgICAgaXNSb3RhdGVTdXBwb3J0ZWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldHVybnMgYSBuZXcgb2JqZWN0IHdpdGggcm90YXRlZCBpbWFnZSBkYXRhIGJ5IDkwIGRlZ3JlZXMgY291bnRlcmNsb2Nrd2lzZS5cbiAgICAgICAgICogT25seSBjYWxsYWJsZSBpZiB7QGxpbmsgI2lzUm90YXRlU3VwcG9ydGVkKCl9IGlzIHRydWUuXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gQSByb3RhdGVkIHZlcnNpb24gb2YgdGhpcyBvYmplY3QuXG4gICAgICAgICAqL1xuICAgICAgICByb3RhdGVDb3VudGVyQ2xvY2t3aXNlKCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkT3BlcmF0aW9uRXhjZXB0aW9uKCdUaGlzIGx1bWluYW5jZSBzb3VyY2UgZG9lcyBub3Qgc3VwcG9ydCByb3RhdGlvbiBieSA5MCBkZWdyZWVzLicpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXR1cm5zIGEgbmV3IG9iamVjdCB3aXRoIHJvdGF0ZWQgaW1hZ2UgZGF0YSBieSA0NSBkZWdyZWVzIGNvdW50ZXJjbG9ja3dpc2UuXG4gICAgICAgICAqIE9ubHkgY2FsbGFibGUgaWYge0BsaW5rICNpc1JvdGF0ZVN1cHBvcnRlZCgpfSBpcyB0cnVlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIEEgcm90YXRlZCB2ZXJzaW9uIG9mIHRoaXMgb2JqZWN0LlxuICAgICAgICAgKi9cbiAgICAgICAgcm90YXRlQ291bnRlckNsb2Nrd2lzZTQ1KCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkT3BlcmF0aW9uRXhjZXB0aW9uKCdUaGlzIGx1bWluYW5jZSBzb3VyY2UgZG9lcyBub3Qgc3VwcG9ydCByb3RhdGlvbiBieSA0NSBkZWdyZWVzLicpO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICBjb25zdCByb3cgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkodGhpcy53aWR0aCk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gbmV3IFN0cmluZ0J1aWxkZXIoKTtcbiAgICAgICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgdGhpcy5oZWlnaHQ7IHkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZVJvdyA9IHRoaXMuZ2V0Um93KHksIHJvdyk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCB0aGlzLndpZHRoOyB4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbHVtaW5hbmNlID0gc291cmNlUm93W3hdICYgMHhGRjtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGM7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsdW1pbmFuY2UgPCAweDQwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjID0gJyMnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGx1bWluYW5jZSA8IDB4ODApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGMgPSAnKyc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobHVtaW5hbmNlIDwgMHhDMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYyA9ICcuJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGMgPSAnICc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChjKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnXFxuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0LnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA5IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qbmFtZXNwYWNlIGNvbS5nb29nbGUuenhpbmcgeyovXG4gICAgLyoqXG4gICAgICogQSB3cmFwcGVyIGltcGxlbWVudGF0aW9uIG9mIHtAbGluayBMdW1pbmFuY2VTb3VyY2V9IHdoaWNoIGludmVydHMgdGhlIGx1bWluYW5jZXMgaXQgcmV0dXJucyAtLSBibGFjayBiZWNvbWVzXG4gICAgICogd2hpdGUgYW5kIHZpY2UgdmVyc2EsIGFuZCBlYWNoIHZhbHVlIGJlY29tZXMgKDI1NS12YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIEludmVydGVkTHVtaW5hbmNlU291cmNlIGV4dGVuZHMgTHVtaW5hbmNlU291cmNlIHtcbiAgICAgICAgY29uc3RydWN0b3IoZGVsZWdhdGUpIHtcbiAgICAgICAgICAgIHN1cGVyKGRlbGVnYXRlLmdldFdpZHRoKCksIGRlbGVnYXRlLmdldEhlaWdodCgpKTtcbiAgICAgICAgICAgIHRoaXMuZGVsZWdhdGUgPSBkZWxlZ2F0ZTtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGdldFJvdyh5IC8qaW50Ki8sIHJvdykge1xuICAgICAgICAgICAgY29uc3Qgc291cmNlUm93ID0gdGhpcy5kZWxlZ2F0ZS5nZXRSb3coeSwgcm93KTtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB3aWR0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgc291cmNlUm93W2ldID0gLyooYnl0ZSkqLyAoMjU1IC0gKHNvdXJjZVJvd1tpXSAmIDB4RkYpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzb3VyY2VSb3c7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBnZXRNYXRyaXgoKSB7XG4gICAgICAgICAgICBjb25zdCBtYXRyaXggPSB0aGlzLmRlbGVnYXRlLmdldE1hdHJpeCgpO1xuICAgICAgICAgICAgY29uc3QgbGVuZ3RoID0gdGhpcy5nZXRXaWR0aCgpICogdGhpcy5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IGludmVydGVkTWF0cml4ID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KGxlbmd0aCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaW52ZXJ0ZWRNYXRyaXhbaV0gPSAvKihieXRlKSovICgyNTUgLSAobWF0cml4W2ldICYgMHhGRikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGludmVydGVkTWF0cml4O1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgaXNDcm9wU3VwcG9ydGVkKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVsZWdhdGUuaXNDcm9wU3VwcG9ydGVkKCk7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBjcm9wKGxlZnQgLyppbnQqLywgdG9wIC8qaW50Ki8sIHdpZHRoIC8qaW50Ki8sIGhlaWdodCAvKmludCovKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEludmVydGVkTHVtaW5hbmNlU291cmNlKHRoaXMuZGVsZWdhdGUuY3JvcChsZWZ0LCB0b3AsIHdpZHRoLCBoZWlnaHQpKTtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGlzUm90YXRlU3VwcG9ydGVkKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVsZWdhdGUuaXNSb3RhdGVTdXBwb3J0ZWQoKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBvcmlnaW5hbCBkZWxlZ2F0ZSB7QGxpbmsgTHVtaW5hbmNlU291cmNlfSBzaW5jZSBpbnZlcnQgdW5kb2VzIGl0c2VsZlxuICAgICAgICAgKi9cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBpbnZlcnQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWxlZ2F0ZTtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIHJvdGF0ZUNvdW50ZXJDbG9ja3dpc2UoKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEludmVydGVkTHVtaW5hbmNlU291cmNlKHRoaXMuZGVsZWdhdGUucm90YXRlQ291bnRlckNsb2Nrd2lzZSgpKTtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIHJvdGF0ZUNvdW50ZXJDbG9ja3dpc2U0NSgpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgSW52ZXJ0ZWRMdW1pbmFuY2VTb3VyY2UodGhpcy5kZWxlZ2F0ZS5yb3RhdGVDb3VudGVyQ2xvY2t3aXNlNDUoKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAZGVwcmVjYXRlZCBNb3ZpbmcgdG8gQHp4aW5nL2Jyb3dzZXJcbiAgICAgKi9cbiAgICBjbGFzcyBIVE1MQ2FudmFzRWxlbWVudEx1bWluYW5jZVNvdXJjZSBleHRlbmRzIEx1bWluYW5jZVNvdXJjZSB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGNhbnZhcykge1xuICAgICAgICAgICAgc3VwZXIoY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzID0gY2FudmFzO1xuICAgICAgICAgICAgdGhpcy50ZW1wQ2FudmFzRWxlbWVudCA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmJ1ZmZlciA9IEhUTUxDYW52YXNFbGVtZW50THVtaW5hbmNlU291cmNlLm1ha2VCdWZmZXJGcm9tQ2FudmFzSW1hZ2VEYXRhKGNhbnZhcyk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIG1ha2VCdWZmZXJGcm9tQ2FudmFzSW1hZ2VEYXRhKGNhbnZhcykge1xuICAgICAgICAgICAgY29uc3QgaW1hZ2VEYXRhID0gY2FudmFzLmdldENvbnRleHQoJzJkJykuZ2V0SW1hZ2VEYXRhKDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG4gICAgICAgICAgICByZXR1cm4gSFRNTENhbnZhc0VsZW1lbnRMdW1pbmFuY2VTb3VyY2UudG9HcmF5c2NhbGVCdWZmZXIoaW1hZ2VEYXRhLmRhdGEsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHRvR3JheXNjYWxlQnVmZmVyKGltYWdlQnVmZmVyLCB3aWR0aCwgaGVpZ2h0KSB7XG4gICAgICAgICAgICBjb25zdCBncmF5c2NhbGVCdWZmZXIgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkod2lkdGggKiBoZWlnaHQpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGogPSAwLCBsZW5ndGggPSBpbWFnZUJ1ZmZlci5sZW5ndGg7IGkgPCBsZW5ndGg7IGkgKz0gNCwgaisrKSB7XG4gICAgICAgICAgICAgICAgbGV0IGdyYXk7XG4gICAgICAgICAgICAgICAgY29uc3QgYWxwaGEgPSBpbWFnZUJ1ZmZlcltpICsgM107XG4gICAgICAgICAgICAgICAgLy8gVGhlIGNvbG9yIG9mIGZ1bGx5LXRyYW5zcGFyZW50IHBpeGVscyBpcyBpcnJlbGV2YW50LiBUaGV5IGFyZSBvZnRlbiwgdGVjaG5pY2FsbHksIGZ1bGx5LXRyYW5zcGFyZW50XG4gICAgICAgICAgICAgICAgLy8gYmxhY2sgKDAgYWxwaGEsIGFuZCB0aGVuIDAgUkdCKS4gVGhleSBhcmUgb2Z0ZW4gdXNlZCwgb2YgY291cnNlIGFzIHRoZSBcIndoaXRlXCIgYXJlYSBpbiBhXG4gICAgICAgICAgICAgICAgLy8gYmFyY29kZSBpbWFnZS4gRm9yY2UgYW55IHN1Y2ggcGl4ZWwgdG8gYmUgd2hpdGU6XG4gICAgICAgICAgICAgICAgaWYgKGFscGhhID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGdyYXkgPSAweEZGO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGl4ZWxSID0gaW1hZ2VCdWZmZXJbaV07XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBpeGVsRyA9IGltYWdlQnVmZmVyW2kgKyAxXTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGl4ZWxCID0gaW1hZ2VCdWZmZXJbaSArIDJdO1xuICAgICAgICAgICAgICAgICAgICAvLyAuMjk5UiArIDAuNTg3RyArIDAuMTE0QiAoWVVWL1lJUSBmb3IgUEFMIGFuZCBOVFNDKSxcbiAgICAgICAgICAgICAgICAgICAgLy8gKDMwNipSKSA+PiAxMCBpcyBhcHByb3hpbWF0ZWx5IGVxdWFsIHRvIFIqMC4yOTksIGFuZCBzbyBvbi5cbiAgICAgICAgICAgICAgICAgICAgLy8gMHgyMDAgPj4gMTAgaXMgMC41LCBpdCBpbXBsZW1lbnRzIHJvdW5kaW5nLlxuICAgICAgICAgICAgICAgICAgICBncmF5ID0gKDMwNiAqIHBpeGVsUiArXG4gICAgICAgICAgICAgICAgICAgICAgICA2MDEgKiBwaXhlbEcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgMTE3ICogcGl4ZWxCICtcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4MjAwKSA+PiAxMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZ3JheXNjYWxlQnVmZmVyW2pdID0gZ3JheTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBncmF5c2NhbGVCdWZmZXI7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Um93KHkgLyppbnQqLywgcm93KSB7XG4gICAgICAgICAgICBpZiAoeSA8IDAgfHwgeSA+PSB0aGlzLmdldEhlaWdodCgpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignUmVxdWVzdGVkIHJvdyBpcyBvdXRzaWRlIHRoZSBpbWFnZTogJyArIHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSB0aGlzLmdldFdpZHRoKCk7XG4gICAgICAgICAgICBjb25zdCBzdGFydCA9IHkgKiB3aWR0aDtcbiAgICAgICAgICAgIGlmIChyb3cgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByb3cgPSB0aGlzLmJ1ZmZlci5zbGljZShzdGFydCwgc3RhcnQgKyB3aWR0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAocm93Lmxlbmd0aCA8IHdpZHRoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJvdyA9IG5ldyBVaW50OENsYW1wZWRBcnJheSh3aWR0aCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIFRoZSB1bmRlcmx5aW5nIHJhc3RlciBvZiBpbWFnZSBjb25zaXN0cyBvZiBieXRlcyB3aXRoIHRoZSBsdW1pbmFuY2UgdmFsdWVzXG4gICAgICAgICAgICAgICAgLy8gVE9ETzogY2FuIGF2b2lkIHNldC9zbGljZT9cbiAgICAgICAgICAgICAgICByb3cuc2V0KHRoaXMuYnVmZmVyLnNsaWNlKHN0YXJ0LCBzdGFydCArIHdpZHRoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcm93O1xuICAgICAgICB9XG4gICAgICAgIGdldE1hdHJpeCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJ1ZmZlcjtcbiAgICAgICAgfVxuICAgICAgICBpc0Nyb3BTdXBwb3J0ZWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBjcm9wKGxlZnQgLyppbnQqLywgdG9wIC8qaW50Ki8sIHdpZHRoIC8qaW50Ki8sIGhlaWdodCAvKmludCovKSB7XG4gICAgICAgICAgICBzdXBlci5jcm9wKGxlZnQsIHRvcCwgd2lkdGgsIGhlaWdodCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogVGhpcyBpcyBhbHdheXMgdHJ1ZSwgc2luY2UgdGhlIGltYWdlIGlzIGEgZ3JheS1zY2FsZSBpbWFnZS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiB0cnVlXG4gICAgICAgICAqL1xuICAgICAgICBpc1JvdGF0ZVN1cHBvcnRlZCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJvdGF0ZUNvdW50ZXJDbG9ja3dpc2UoKSB7XG4gICAgICAgICAgICB0aGlzLnJvdGF0ZSgtOTApO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgcm90YXRlQ291bnRlckNsb2Nrd2lzZTQ1KCkge1xuICAgICAgICAgICAgdGhpcy5yb3RhdGUoLTQ1KTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGdldFRlbXBDYW52YXNFbGVtZW50KCkge1xuICAgICAgICAgICAgaWYgKG51bGwgPT09IHRoaXMudGVtcENhbnZhc0VsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0ZW1wQ2FudmFzRWxlbWVudCA9IHRoaXMuY2FudmFzLm93bmVyRG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgICAgICAgICAgICAgdGVtcENhbnZhc0VsZW1lbnQud2lkdGggPSB0aGlzLmNhbnZhcy53aWR0aDtcbiAgICAgICAgICAgICAgICB0ZW1wQ2FudmFzRWxlbWVudC5oZWlnaHQgPSB0aGlzLmNhbnZhcy5oZWlnaHQ7XG4gICAgICAgICAgICAgICAgdGhpcy50ZW1wQ2FudmFzRWxlbWVudCA9IHRlbXBDYW52YXNFbGVtZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMudGVtcENhbnZhc0VsZW1lbnQ7XG4gICAgICAgIH1cbiAgICAgICAgcm90YXRlKGFuZ2xlKSB7XG4gICAgICAgICAgICBjb25zdCB0ZW1wQ2FudmFzRWxlbWVudCA9IHRoaXMuZ2V0VGVtcENhbnZhc0VsZW1lbnQoKTtcbiAgICAgICAgICAgIGNvbnN0IHRlbXBDb250ZXh0ID0gdGVtcENhbnZhc0VsZW1lbnQuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgICAgIGNvbnN0IGFuZ2xlUmFkaWFucyA9IGFuZ2xlICogSFRNTENhbnZhc0VsZW1lbnRMdW1pbmFuY2VTb3VyY2UuREVHUkVFX1RPX1JBRElBTlM7XG4gICAgICAgICAgICAvLyBDYWxjdWxhdGUgYW5kIHNldCBuZXcgZGltZW5zaW9ucyBmb3IgdGVtcCBjYW52YXNcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy5jYW52YXMud2lkdGg7XG4gICAgICAgICAgICBjb25zdCBoZWlnaHQgPSB0aGlzLmNhbnZhcy5oZWlnaHQ7XG4gICAgICAgICAgICBjb25zdCBuZXdXaWR0aCA9IE1hdGguY2VpbChNYXRoLmFicyhNYXRoLmNvcyhhbmdsZVJhZGlhbnMpKSAqIHdpZHRoICsgTWF0aC5hYnMoTWF0aC5zaW4oYW5nbGVSYWRpYW5zKSkgKiBoZWlnaHQpO1xuICAgICAgICAgICAgY29uc3QgbmV3SGVpZ2h0ID0gTWF0aC5jZWlsKE1hdGguYWJzKE1hdGguc2luKGFuZ2xlUmFkaWFucykpICogd2lkdGggKyBNYXRoLmFicyhNYXRoLmNvcyhhbmdsZVJhZGlhbnMpKSAqIGhlaWdodCk7XG4gICAgICAgICAgICB0ZW1wQ2FudmFzRWxlbWVudC53aWR0aCA9IG5ld1dpZHRoO1xuICAgICAgICAgICAgdGVtcENhbnZhc0VsZW1lbnQuaGVpZ2h0ID0gbmV3SGVpZ2h0O1xuICAgICAgICAgICAgLy8gRHJhdyBhdCBjZW50ZXIgb2YgdGVtcCBjYW52YXMgdG8gcHJldmVudCBjbGlwcGluZyBvZiBpbWFnZSBkYXRhXG4gICAgICAgICAgICB0ZW1wQ29udGV4dC50cmFuc2xhdGUobmV3V2lkdGggLyAyLCBuZXdIZWlnaHQgLyAyKTtcbiAgICAgICAgICAgIHRlbXBDb250ZXh0LnJvdGF0ZShhbmdsZVJhZGlhbnMpO1xuICAgICAgICAgICAgdGVtcENvbnRleHQuZHJhd0ltYWdlKHRoaXMuY2FudmFzLCB3aWR0aCAvIC0yLCBoZWlnaHQgLyAtMik7XG4gICAgICAgICAgICB0aGlzLmJ1ZmZlciA9IEhUTUxDYW52YXNFbGVtZW50THVtaW5hbmNlU291cmNlLm1ha2VCdWZmZXJGcm9tQ2FudmFzSW1hZ2VEYXRhKHRlbXBDYW52YXNFbGVtZW50KTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGludmVydCgpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgSW52ZXJ0ZWRMdW1pbmFuY2VTb3VyY2UodGhpcyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgSFRNTENhbnZhc0VsZW1lbnRMdW1pbmFuY2VTb3VyY2UuREVHUkVFX1RPX1JBRElBTlMgPSBNYXRoLlBJIC8gMTgwO1xuXG4gICAgLyoqXG4gICAgICogQGRlcHJlY2F0ZWQgTW92aW5nIHRvIEB6eGluZy9icm93c2VyXG4gICAgICpcbiAgICAgKiBWaWRlbyBpbnB1dCBkZXZpY2UgbWV0YWRhdGEgY29udGFpbmluZyB0aGUgaWQgYW5kIGxhYmVsIG9mIHRoZSBkZXZpY2UgaWYgYXZhaWxhYmxlLlxuICAgICAqL1xuICAgIGNsYXNzIFZpZGVvSW5wdXREZXZpY2Uge1xuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBWaWRlb0lucHV0RGV2aWNlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gZGV2aWNlSWQgdGhlIHZpZGVvIGlucHV0IGRldmljZSBpZFxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGFiZWwgdGhlIGxhYmVsIG9mIHRoZSBkZXZpY2UgaWYgYXZhaWxhYmxlXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3RvcihkZXZpY2VJZCwgbGFiZWwsIGdyb3VwSWQpIHtcbiAgICAgICAgICAgIHRoaXMuZGV2aWNlSWQgPSBkZXZpY2VJZDtcbiAgICAgICAgICAgIHRoaXMubGFiZWwgPSBsYWJlbDtcbiAgICAgICAgICAgIC8qKiBAaW5oZXJpdGRvYyAqL1xuICAgICAgICAgICAgdGhpcy5raW5kID0gJ3ZpZGVvaW5wdXQnO1xuICAgICAgICAgICAgdGhpcy5ncm91cElkID0gZ3JvdXBJZCB8fCB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqIEBpbmhlcml0ZG9jICovXG4gICAgICAgIHRvSlNPTigpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAga2luZDogdGhpcy5raW5kLFxuICAgICAgICAgICAgICAgIGdyb3VwSWQ6IHRoaXMuZ3JvdXBJZCxcbiAgICAgICAgICAgICAgICBkZXZpY2VJZDogdGhpcy5kZXZpY2VJZCxcbiAgICAgICAgICAgICAgICBsYWJlbDogdGhpcy5sYWJlbCxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgX19hd2FpdGVyID0gKChnbG9iYWxUaGlzIHx8IGdsb2JhbCB8fCBzZWxmIHx8IHdpbmRvdyB8fCB1bmRlZmluZWQpICYmIChnbG9iYWxUaGlzIHx8IGdsb2JhbCB8fCBzZWxmIHx8IHdpbmRvdyB8fCB1bmRlZmluZWQpLl9fYXdhaXRlcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xuICAgICAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH1cbiAgICAgICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XG4gICAgICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgLyoqXG4gICAgICogQGRlcHJlY2F0ZWQgTW92aW5nIHRvIEB6eGluZy9icm93c2VyXG4gICAgICpcbiAgICAgKiBCYXNlIGNsYXNzIGZvciBicm93c2VyIGNvZGUgcmVhZGVyLlxuICAgICAqL1xuICAgIGNsYXNzIEJyb3dzZXJDb2RlUmVhZGVyIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgQnJvd3NlckNvZGVSZWFkZXIuXG4gICAgICAgICAqIEBwYXJhbSB7UmVhZGVyfSByZWFkZXIgVGhlIHJlYWRlciBpbnN0YW5jZSB0byBkZWNvZGUgdGhlIGJhcmNvZGVcbiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IFt0aW1lQmV0d2VlblNjYW5zTWlsbGlzPTUwMF0gdGhlIHRpbWUgZGVsYXkgYmV0d2VlbiBzdWJzZXF1ZW50IHN1Y2Nlc3NmdWwgZGVjb2RlIHRyaWVzXG4gICAgICAgICAqXG4gICAgICAgICAqIEBtZW1iZXJPZiBCcm93c2VyQ29kZVJlYWRlclxuICAgICAgICAgKi9cbiAgICAgICAgY29uc3RydWN0b3IocmVhZGVyLCB0aW1lQmV0d2VlblNjYW5zTWlsbGlzID0gNTAwLCBfaGludHMpIHtcbiAgICAgICAgICAgIHRoaXMucmVhZGVyID0gcmVhZGVyO1xuICAgICAgICAgICAgdGhpcy50aW1lQmV0d2VlblNjYW5zTWlsbGlzID0gdGltZUJldHdlZW5TY2Fuc01pbGxpcztcbiAgICAgICAgICAgIHRoaXMuX2hpbnRzID0gX2hpbnRzO1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBUaGlzIHdpbGwgYnJlYWsgdGhlIGxvb3AuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHRoaXMuX3N0b3BDb250aW51b3VzRGVjb2RlID0gZmFsc2U7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFRoaXMgd2lsbCBicmVhayB0aGUgbG9vcC5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgdGhpcy5fc3RvcEFzeW5jRGVjb2RlID0gZmFsc2U7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIERlbGF5IHRpbWUgYmV0d2VlbiBkZWNvZGUgYXR0ZW1wdHMgbWFkZSBieSB0aGUgc2Nhbm5lci5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgdGhpcy5fdGltZUJldHdlZW5EZWNvZGluZ0F0dGVtcHRzID0gMDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogSWYgbmF2aWdhdG9yIGlzIHByZXNlbnQuXG4gICAgICAgICAqL1xuICAgICAgICBnZXQgaGFzTmF2aWdhdG9yKCkge1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBuYXZpZ2F0b3IgIT09ICd1bmRlZmluZWQnO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJZiBtZWRpYURldmljZXMgdW5kZXIgbmF2aWdhdG9yIGlzIHN1cHBvcnRlZC5cbiAgICAgICAgICovXG4gICAgICAgIGdldCBpc01lZGlhRGV2aWNlc1N1cG9ydGVkKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaGFzTmF2aWdhdG9yICYmICEhbmF2aWdhdG9yLm1lZGlhRGV2aWNlcztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogSWYgZW51bWVyYXRlRGV2aWNlcyB1bmRlciBuYXZpZ2F0b3IgaXMgc3VwcG9ydGVkLlxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0IGNhbkVudW1lcmF0ZURldmljZXMoKSB7XG4gICAgICAgICAgICByZXR1cm4gISEodGhpcy5pc01lZGlhRGV2aWNlc1N1cG9ydGVkICYmIG5hdmlnYXRvci5tZWRpYURldmljZXMuZW51bWVyYXRlRGV2aWNlcyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqIFRpbWUgYmV0d2VlbiB0d28gZGVjb2RpbmcgdHJpZXMgaW4gbWlsbGkgc2Vjb25kcy4gKi9cbiAgICAgICAgZ2V0IHRpbWVCZXR3ZWVuRGVjb2RpbmdBdHRlbXB0cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl90aW1lQmV0d2VlbkRlY29kaW5nQXR0ZW1wdHM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENoYW5nZSB0aGUgdGltZSBzcGFuIHRoZSBkZWNvZGVyIHdhaXRzIGJldHdlZW4gdHdvIGRlY29kaW5nIHRyaWVzLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gbWlsbGlzIFRpbWUgYmV0d2VlbiB0d28gZGVjb2RpbmcgdHJpZXMgaW4gbWlsbGkgc2Vjb25kcy5cbiAgICAgICAgICovXG4gICAgICAgIHNldCB0aW1lQmV0d2VlbkRlY29kaW5nQXR0ZW1wdHMobWlsbGlzKSB7XG4gICAgICAgICAgICB0aGlzLl90aW1lQmV0d2VlbkRlY29kaW5nQXR0ZW1wdHMgPSBtaWxsaXMgPCAwID8gMCA6IG1pbGxpcztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogU2V0cyB0aGUgaGludHMuXG4gICAgICAgICAqL1xuICAgICAgICBzZXQgaGludHMoaGludHMpIHtcbiAgICAgICAgICAgIHRoaXMuX2hpbnRzID0gaGludHMgfHwgbnVsbDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogU2V0cyB0aGUgaGludHMuXG4gICAgICAgICAqL1xuICAgICAgICBnZXQgaGludHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5faGludHM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIExpc3RzIGFsbCB0aGUgYXZhaWxhYmxlIHZpZGVvIGlucHV0IGRldmljZXMuXG4gICAgICAgICAqL1xuICAgICAgICBsaXN0VmlkZW9JbnB1dERldmljZXMoKSB7XG4gICAgICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5oYXNOYXZpZ2F0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXCd0IGVudW1lcmF0ZSBkZXZpY2VzLCBuYXZpZ2F0b3IgaXMgbm90IHByZXNlbnQuJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5jYW5FbnVtZXJhdGVEZXZpY2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuXFwndCBlbnVtZXJhdGUgZGV2aWNlcywgbWV0aG9kIG5vdCBzdXBwb3J0ZWQuJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGRldmljZXMgPSB5aWVsZCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmVudW1lcmF0ZURldmljZXMoKTtcbiAgICAgICAgICAgICAgICBjb25zdCB2aWRlb0RldmljZXMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGRldmljZSBvZiBkZXZpY2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGtpbmQgPSBkZXZpY2Uua2luZCA9PT0gJ3ZpZGVvJyA/ICd2aWRlb2lucHV0JyA6IGRldmljZS5raW5kO1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2luZCAhPT0gJ3ZpZGVvaW5wdXQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb25zdCBkZXZpY2VJZCA9IGRldmljZS5kZXZpY2VJZCB8fCBkZXZpY2UuaWQ7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxhYmVsID0gZGV2aWNlLmxhYmVsIHx8IGBWaWRlbyBkZXZpY2UgJHt2aWRlb0RldmljZXMubGVuZ3RoICsgMX1gO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBncm91cElkID0gZGV2aWNlLmdyb3VwSWQ7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHZpZGVvRGV2aWNlID0geyBkZXZpY2VJZCwgbGFiZWwsIGtpbmQsIGdyb3VwSWQgfTtcbiAgICAgICAgICAgICAgICAgICAgdmlkZW9EZXZpY2VzLnB1c2godmlkZW9EZXZpY2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdmlkZW9EZXZpY2VzO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE9idGFpbiB0aGUgbGlzdCBvZiBhdmFpbGFibGUgZGV2aWNlcyB3aXRoIHR5cGUgJ3ZpZGVvaW5wdXQnLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxWaWRlb0lucHV0RGV2aWNlW10+fSBhbiBhcnJheSBvZiBhdmFpbGFibGUgdmlkZW8gaW5wdXQgZGV2aWNlc1xuICAgICAgICAgKlxuICAgICAgICAgKiBAbWVtYmVyT2YgQnJvd3NlckNvZGVSZWFkZXJcbiAgICAgICAgICpcbiAgICAgICAgICogQGRlcHJlY2F0ZWQgVXNlIGBsaXN0VmlkZW9JbnB1dERldmljZXNgIGluc3RlYWQuXG4gICAgICAgICAqL1xuICAgICAgICBnZXRWaWRlb0lucHV0RGV2aWNlcygpIHtcbiAgICAgICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGV2aWNlcyA9IHlpZWxkIHRoaXMubGlzdFZpZGVvSW5wdXREZXZpY2VzKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRldmljZXMubWFwKGQgPT4gbmV3IFZpZGVvSW5wdXREZXZpY2UoZC5kZXZpY2VJZCwgZC5sYWJlbCkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIExldCdzIHlvdSBmaW5kIGEgZGV2aWNlIHVzaW5nIGl0J3MgSWQuXG4gICAgICAgICAqL1xuICAgICAgICBmaW5kRGV2aWNlQnlJZChkZXZpY2VJZCkge1xuICAgICAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkZXZpY2VzID0geWllbGQgdGhpcy5saXN0VmlkZW9JbnB1dERldmljZXMoKTtcbiAgICAgICAgICAgICAgICBpZiAoIWRldmljZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBkZXZpY2VzLmZpbmQoeCA9PiB4LmRldmljZUlkID09PSBkZXZpY2VJZCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyB0aGUgYmFyY29kZSBmcm9tIHRoZSBkZXZpY2Ugc3BlY2lmaWVkIGJ5IGRldmljZUlkIHdoaWxlIHNob3dpbmcgdGhlIHZpZGVvIGluIHRoZSBzcGVjaWZpZWQgdmlkZW8gZWxlbWVudC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGRldmljZUlkIHRoZSBpZCBvZiBvbmUgb2YgdGhlIGRldmljZXMgb2J0YWluZWQgYWZ0ZXIgY2FsbGluZyBnZXRWaWRlb0lucHV0RGV2aWNlcy4gQ2FuIGJlIHVuZGVmaW5lZCwgaW4gdGhpcyBjYXNlIGl0IHdpbGwgZGVjb2RlIGZyb20gb25lIG9mIHRoZSBhdmFpbGFibGUgZGV2aWNlcywgcHJlZmZlcmluZyB0aGUgbWFpbiBjYW1lcmEgKGVudmlyb25tZW50IGZhY2luZykgaWYgYXZhaWxhYmxlLlxuICAgICAgICAgKiBAcGFyYW0gdmlkZW8gdGhlIHZpZGVvIGVsZW1lbnQgaW4gcGFnZSB3aGVyZSB0byBzaG93IHRoZSB2aWRlbyB3aGlsZSBkZWNvZGluZy4gQ2FuIGJlIGVpdGhlciBhbiBlbGVtZW50IGlkIG9yIGRpcmVjdGx5IGFuIEhUTUxWaWRlb0VsZW1lbnQuIENhbiBiZSB1bmRlZmluZWQsIGluIHdoaWNoIGNhc2Ugbm8gdmlkZW8gd2lsbCBiZSBzaG93bi5cbiAgICAgICAgICogQHJldHVybnMgVGhlIGRlY29kaW5nIHJlc3VsdC5cbiAgICAgICAgICpcbiAgICAgICAgICogQG1lbWJlck9mIEJyb3dzZXJDb2RlUmVhZGVyXG4gICAgICAgICAqXG4gICAgICAgICAqIEBkZXByZWNhdGVkIFVzZSBgZGVjb2RlT25jZUZyb21WaWRlb0RldmljZWAgaW5zdGVhZC5cbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZUZyb21JbnB1dFZpZGVvRGV2aWNlKGRldmljZUlkLCB2aWRlb1NvdXJjZSkge1xuICAgICAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geWllbGQgdGhpcy5kZWNvZGVPbmNlRnJvbVZpZGVvRGV2aWNlKGRldmljZUlkLCB2aWRlb1NvdXJjZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogSW4gb25lIGF0dGVtcHQsIHRyaWVzIHRvIGRlY29kZSB0aGUgYmFyY29kZSBmcm9tIHRoZSBkZXZpY2Ugc3BlY2lmaWVkIGJ5IGRldmljZUlkIHdoaWxlIHNob3dpbmcgdGhlIHZpZGVvIGluIHRoZSBzcGVjaWZpZWQgdmlkZW8gZWxlbWVudC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGRldmljZUlkIHRoZSBpZCBvZiBvbmUgb2YgdGhlIGRldmljZXMgb2J0YWluZWQgYWZ0ZXIgY2FsbGluZyBnZXRWaWRlb0lucHV0RGV2aWNlcy4gQ2FuIGJlIHVuZGVmaW5lZCwgaW4gdGhpcyBjYXNlIGl0IHdpbGwgZGVjb2RlIGZyb20gb25lIG9mIHRoZSBhdmFpbGFibGUgZGV2aWNlcywgcHJlZmZlcmluZyB0aGUgbWFpbiBjYW1lcmEgKGVudmlyb25tZW50IGZhY2luZykgaWYgYXZhaWxhYmxlLlxuICAgICAgICAgKiBAcGFyYW0gdmlkZW8gdGhlIHZpZGVvIGVsZW1lbnQgaW4gcGFnZSB3aGVyZSB0byBzaG93IHRoZSB2aWRlbyB3aGlsZSBkZWNvZGluZy4gQ2FuIGJlIGVpdGhlciBhbiBlbGVtZW50IGlkIG9yIGRpcmVjdGx5IGFuIEhUTUxWaWRlb0VsZW1lbnQuIENhbiBiZSB1bmRlZmluZWQsIGluIHdoaWNoIGNhc2Ugbm8gdmlkZW8gd2lsbCBiZSBzaG93bi5cbiAgICAgICAgICogQHJldHVybnMgVGhlIGRlY29kaW5nIHJlc3VsdC5cbiAgICAgICAgICpcbiAgICAgICAgICogQG1lbWJlck9mIEJyb3dzZXJDb2RlUmVhZGVyXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGVPbmNlRnJvbVZpZGVvRGV2aWNlKGRldmljZUlkLCB2aWRlb1NvdXJjZSkge1xuICAgICAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgICAgICAgICAgICAgbGV0IHZpZGVvQ29uc3RyYWludHM7XG4gICAgICAgICAgICAgICAgaWYgKCFkZXZpY2VJZCkge1xuICAgICAgICAgICAgICAgICAgICB2aWRlb0NvbnN0cmFpbnRzID0geyBmYWNpbmdNb2RlOiAnZW52aXJvbm1lbnQnIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2aWRlb0NvbnN0cmFpbnRzID0geyBkZXZpY2VJZDogeyBleGFjdDogZGV2aWNlSWQgfSB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBjb25zdHJhaW50cyA9IHsgdmlkZW86IHZpZGVvQ29uc3RyYWludHMgfTtcbiAgICAgICAgICAgICAgICByZXR1cm4geWllbGQgdGhpcy5kZWNvZGVPbmNlRnJvbUNvbnN0cmFpbnRzKGNvbnN0cmFpbnRzLCB2aWRlb1NvdXJjZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogSW4gb25lIGF0dGVtcHQsIHRyaWVzIHRvIGRlY29kZSB0aGUgYmFyY29kZSBmcm9tIGEgc3RyZWFtIG9idGFpbmVkIGZyb20gdGhlIGdpdmVuIGNvbnN0cmFpbnRzIHdoaWxlIHNob3dpbmcgdGhlIHZpZGVvIGluIHRoZSBzcGVjaWZpZWQgdmlkZW8gZWxlbWVudC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGNvbnN0cmFpbnRzIHRoZSBtZWRpYSBzdHJlYW0gY29uc3RyYWludHMgdG8gZ2V0IHMgdmFsaWQgbWVkaWEgc3RyZWFtIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAqIEBwYXJhbSB2aWRlbyB0aGUgdmlkZW8gZWxlbWVudCBpbiBwYWdlIHdoZXJlIHRvIHNob3cgdGhlIHZpZGVvIHdoaWxlIGRlY29kaW5nLiBDYW4gYmUgZWl0aGVyIGFuIGVsZW1lbnQgaWQgb3IgZGlyZWN0bHkgYW4gSFRNTFZpZGVvRWxlbWVudC4gQ2FuIGJlIHVuZGVmaW5lZCwgaW4gd2hpY2ggY2FzZSBubyB2aWRlbyB3aWxsIGJlIHNob3duLlxuICAgICAgICAgKiBAcmV0dXJucyBUaGUgZGVjb2RpbmcgcmVzdWx0LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAbWVtYmVyT2YgQnJvd3NlckNvZGVSZWFkZXJcbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZU9uY2VGcm9tQ29uc3RyYWludHMoY29uc3RyYWludHMsIHZpZGVvU291cmNlKSB7XG4gICAgICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IHlpZWxkIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgICAgICByZXR1cm4geWllbGQgdGhpcy5kZWNvZGVPbmNlRnJvbVN0cmVhbShzdHJlYW0sIHZpZGVvU291cmNlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJbiBvbmUgYXR0ZW1wdCwgdHJpZXMgdG8gZGVjb2RlIHRoZSBiYXJjb2RlIGZyb20gYSBzdHJlYW0gb2J0YWluZWQgZnJvbSB0aGUgZ2l2ZW4gY29uc3RyYWludHMgd2hpbGUgc2hvd2luZyB0aGUgdmlkZW8gaW4gdGhlIHNwZWNpZmllZCB2aWRlbyBlbGVtZW50LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0ge01lZGlhU3RyZWFtfSBbY29uc3RyYWludHNdIHRoZSBtZWRpYSBzdHJlYW0gY29uc3RyYWludHMgdG8gZ2V0IHMgdmFsaWQgbWVkaWEgc3RyZWFtIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfEhUTUxWaWRlb0VsZW1lbnR9IFt2aWRlb10gdGhlIHZpZGVvIGVsZW1lbnQgaW4gcGFnZSB3aGVyZSB0byBzaG93IHRoZSB2aWRlbyB3aGlsZSBkZWNvZGluZy4gQ2FuIGJlIGVpdGhlciBhbiBlbGVtZW50IGlkIG9yIGRpcmVjdGx5IGFuIEhUTUxWaWRlb0VsZW1lbnQuIENhbiBiZSB1bmRlZmluZWQsIGluIHdoaWNoIGNhc2Ugbm8gdmlkZW8gd2lsbCBiZSBzaG93bi5cbiAgICAgICAgICogQHJldHVybnMge1Byb21pc2U8UmVzdWx0Pn0gVGhlIGRlY29kaW5nIHJlc3VsdC5cbiAgICAgICAgICpcbiAgICAgICAgICogQG1lbWJlck9mIEJyb3dzZXJDb2RlUmVhZGVyXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGVPbmNlRnJvbVN0cmVhbShzdHJlYW0sIHZpZGVvU291cmNlKSB7XG4gICAgICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgICAgICAgICBjb25zdCB2aWRlbyA9IHlpZWxkIHRoaXMuYXR0YWNoU3RyZWFtVG9WaWRlbyhzdHJlYW0sIHZpZGVvU291cmNlKTtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSB5aWVsZCB0aGlzLmRlY29kZU9uY2UodmlkZW8pO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ29udGludW91c2x5IGRlY29kZXMgdGhlIGJhcmNvZGUgZnJvbSB0aGUgZGV2aWNlIHNwZWNpZmllZCBieSBkZXZpY2Ugd2hpbGUgc2hvd2luZyB0aGUgdmlkZW8gaW4gdGhlIHNwZWNpZmllZCB2aWRlbyBlbGVtZW50LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ3xudWxsfSBbZGV2aWNlSWRdIHRoZSBpZCBvZiBvbmUgb2YgdGhlIGRldmljZXMgb2J0YWluZWQgYWZ0ZXIgY2FsbGluZyBnZXRWaWRlb0lucHV0RGV2aWNlcy4gQ2FuIGJlIHVuZGVmaW5lZCwgaW4gdGhpcyBjYXNlIGl0IHdpbGwgZGVjb2RlIGZyb20gb25lIG9mIHRoZSBhdmFpbGFibGUgZGV2aWNlcywgcHJlZmZlcmluZyB0aGUgbWFpbiBjYW1lcmEgKGVudmlyb25tZW50IGZhY2luZykgaWYgYXZhaWxhYmxlLlxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ3xIVE1MVmlkZW9FbGVtZW50fG51bGx9IFt2aWRlb10gdGhlIHZpZGVvIGVsZW1lbnQgaW4gcGFnZSB3aGVyZSB0byBzaG93IHRoZSB2aWRlbyB3aGlsZSBkZWNvZGluZy4gQ2FuIGJlIGVpdGhlciBhbiBlbGVtZW50IGlkIG9yIGRpcmVjdGx5IGFuIEhUTUxWaWRlb0VsZW1lbnQuIENhbiBiZSB1bmRlZmluZWQsIGluIHdoaWNoIGNhc2Ugbm8gdmlkZW8gd2lsbCBiZSBzaG93bi5cbiAgICAgICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAgICAgICAqXG4gICAgICAgICAqIEBtZW1iZXJPZiBCcm93c2VyQ29kZVJlYWRlclxuICAgICAgICAgKlxuICAgICAgICAgKiBAZGVwcmVjYXRlZCBVc2UgYGRlY29kZUZyb21WaWRlb0RldmljZWAgaW5zdGVhZC5cbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZUZyb21JbnB1dFZpZGVvRGV2aWNlQ29udGludW91c2x5KGRldmljZUlkLCB2aWRlb1NvdXJjZSwgY2FsbGJhY2tGbikge1xuICAgICAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geWllbGQgdGhpcy5kZWNvZGVGcm9tVmlkZW9EZXZpY2UoZGV2aWNlSWQsIHZpZGVvU291cmNlLCBjYWxsYmFja0ZuKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb250aW51b3VzbHkgdHJpZXMgdG8gZGVjb2RlIHRoZSBiYXJjb2RlIGZyb20gdGhlIGRldmljZSBzcGVjaWZpZWQgYnkgZGV2aWNlIHdoaWxlIHNob3dpbmcgdGhlIHZpZGVvIGluIHRoZSBzcGVjaWZpZWQgdmlkZW8gZWxlbWVudC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd8bnVsbH0gW2RldmljZUlkXSB0aGUgaWQgb2Ygb25lIG9mIHRoZSBkZXZpY2VzIG9idGFpbmVkIGFmdGVyIGNhbGxpbmcgZ2V0VmlkZW9JbnB1dERldmljZXMuIENhbiBiZSB1bmRlZmluZWQsIGluIHRoaXMgY2FzZSBpdCB3aWxsIGRlY29kZSBmcm9tIG9uZSBvZiB0aGUgYXZhaWxhYmxlIGRldmljZXMsIHByZWZmZXJpbmcgdGhlIG1haW4gY2FtZXJhIChlbnZpcm9ubWVudCBmYWNpbmcpIGlmIGF2YWlsYWJsZS5cbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd8SFRNTFZpZGVvRWxlbWVudHxudWxsfSBbdmlkZW9dIHRoZSB2aWRlbyBlbGVtZW50IGluIHBhZ2Ugd2hlcmUgdG8gc2hvdyB0aGUgdmlkZW8gd2hpbGUgZGVjb2RpbmcuIENhbiBiZSBlaXRoZXIgYW4gZWxlbWVudCBpZCBvciBkaXJlY3RseSBhbiBIVE1MVmlkZW9FbGVtZW50LiBDYW4gYmUgdW5kZWZpbmVkLCBpbiB3aGljaCBjYXNlIG5vIHZpZGVvIHdpbGwgYmUgc2hvd24uXG4gICAgICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgICAgICAgKlxuICAgICAgICAgKiBAbWVtYmVyT2YgQnJvd3NlckNvZGVSZWFkZXJcbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZUZyb21WaWRlb0RldmljZShkZXZpY2VJZCwgdmlkZW9Tb3VyY2UsIGNhbGxiYWNrRm4pIHtcbiAgICAgICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgICAgICAgICAgbGV0IHZpZGVvQ29uc3RyYWludHM7XG4gICAgICAgICAgICAgICAgaWYgKCFkZXZpY2VJZCkge1xuICAgICAgICAgICAgICAgICAgICB2aWRlb0NvbnN0cmFpbnRzID0geyBmYWNpbmdNb2RlOiAnZW52aXJvbm1lbnQnIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2aWRlb0NvbnN0cmFpbnRzID0geyBkZXZpY2VJZDogeyBleGFjdDogZGV2aWNlSWQgfSB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBjb25zdHJhaW50cyA9IHsgdmlkZW86IHZpZGVvQ29uc3RyYWludHMgfTtcbiAgICAgICAgICAgICAgICByZXR1cm4geWllbGQgdGhpcy5kZWNvZGVGcm9tQ29uc3RyYWludHMoY29uc3RyYWludHMsIHZpZGVvU291cmNlLCBjYWxsYmFja0ZuKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb250aW51b3VzbHkgdHJpZXMgdG8gZGVjb2RlIHRoZSBiYXJjb2RlIGZyb20gYSBzdHJlYW0gb2J0YWluZWQgZnJvbSB0aGUgZ2l2ZW4gY29uc3RyYWludHMgd2hpbGUgc2hvd2luZyB0aGUgdmlkZW8gaW4gdGhlIHNwZWNpZmllZCB2aWRlbyBlbGVtZW50LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0ge01lZGlhU3RyZWFtfSBbY29uc3RyYWludHNdIHRoZSBtZWRpYSBzdHJlYW0gY29uc3RyYWludHMgdG8gZ2V0IHMgdmFsaWQgbWVkaWEgc3RyZWFtIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfEhUTUxWaWRlb0VsZW1lbnR9IFt2aWRlb10gdGhlIHZpZGVvIGVsZW1lbnQgaW4gcGFnZSB3aGVyZSB0byBzaG93IHRoZSB2aWRlbyB3aGlsZSBkZWNvZGluZy4gQ2FuIGJlIGVpdGhlciBhbiBlbGVtZW50IGlkIG9yIGRpcmVjdGx5IGFuIEhUTUxWaWRlb0VsZW1lbnQuIENhbiBiZSB1bmRlZmluZWQsIGluIHdoaWNoIGNhc2Ugbm8gdmlkZW8gd2lsbCBiZSBzaG93bi5cbiAgICAgICAgICogQHJldHVybnMge1Byb21pc2U8UmVzdWx0Pn0gVGhlIGRlY29kaW5nIHJlc3VsdC5cbiAgICAgICAgICpcbiAgICAgICAgICogQG1lbWJlck9mIEJyb3dzZXJDb2RlUmVhZGVyXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGVGcm9tQ29uc3RyYWludHMoY29uc3RyYWludHMsIHZpZGVvU291cmNlLCBjYWxsYmFja0ZuKSB7XG4gICAgICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IHlpZWxkIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgICAgICByZXR1cm4geWllbGQgdGhpcy5kZWNvZGVGcm9tU3RyZWFtKHN0cmVhbSwgdmlkZW9Tb3VyY2UsIGNhbGxiYWNrRm4pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEluIG9uZSBhdHRlbXB0LCB0cmllcyB0byBkZWNvZGUgdGhlIGJhcmNvZGUgZnJvbSBhIHN0cmVhbSBvYnRhaW5lZCBmcm9tIHRoZSBnaXZlbiBjb25zdHJhaW50cyB3aGlsZSBzaG93aW5nIHRoZSB2aWRlbyBpbiB0aGUgc3BlY2lmaWVkIHZpZGVvIGVsZW1lbnQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB7TWVkaWFTdHJlYW19IFtjb25zdHJhaW50c10gdGhlIG1lZGlhIHN0cmVhbSBjb25zdHJhaW50cyB0byBnZXQgcyB2YWxpZCBtZWRpYSBzdHJlYW0gdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd8SFRNTFZpZGVvRWxlbWVudH0gW3ZpZGVvXSB0aGUgdmlkZW8gZWxlbWVudCBpbiBwYWdlIHdoZXJlIHRvIHNob3cgdGhlIHZpZGVvIHdoaWxlIGRlY29kaW5nLiBDYW4gYmUgZWl0aGVyIGFuIGVsZW1lbnQgaWQgb3IgZGlyZWN0bHkgYW4gSFRNTFZpZGVvRWxlbWVudC4gQ2FuIGJlIHVuZGVmaW5lZCwgaW4gd2hpY2ggY2FzZSBubyB2aWRlbyB3aWxsIGJlIHNob3duLlxuICAgICAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZXN1bHQ+fSBUaGUgZGVjb2RpbmcgcmVzdWx0LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAbWVtYmVyT2YgQnJvd3NlckNvZGVSZWFkZXJcbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZUZyb21TdHJlYW0oc3RyZWFtLCB2aWRlb1NvdXJjZSwgY2FsbGJhY2tGbikge1xuICAgICAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgICAgICAgICAgICAgY29uc3QgdmlkZW8gPSB5aWVsZCB0aGlzLmF0dGFjaFN0cmVhbVRvVmlkZW8oc3RyZWFtLCB2aWRlb1NvdXJjZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHlpZWxkIHRoaXMuZGVjb2RlQ29udGludW91c2x5KHZpZGVvLCBjYWxsYmFja0ZuKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBCcmVha3MgdGhlIGRlY29kaW5nIGxvb3AuXG4gICAgICAgICAqL1xuICAgICAgICBzdG9wQXN5bmNEZWNvZGUoKSB7XG4gICAgICAgICAgICB0aGlzLl9zdG9wQXN5bmNEZWNvZGUgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBCcmVha3MgdGhlIGRlY29kaW5nIGxvb3AuXG4gICAgICAgICAqL1xuICAgICAgICBzdG9wQ29udGludW91c0RlY29kZSgpIHtcbiAgICAgICAgICAgIHRoaXMuX3N0b3BDb250aW51b3VzRGVjb2RlID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogU2V0cyB0aGUgbmV3IHN0cmVhbSBhbmQgcmVxdWVzdCBhIG5ldyBkZWNvZGluZy13aXRoLWRlbGF5LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gc3RyZWFtIFRoZSBzdHJlYW0gdG8gYmUgc2hvd24gaW4gdGhlIHZpZGVvIGVsZW1lbnQuXG4gICAgICAgICAqIEBwYXJhbSBkZWNvZGVGbiBBIGNhbGxiYWNrIGZvciB0aGUgZGVjb2RlIG1ldGhvZC5cbiAgICAgICAgICovXG4gICAgICAgIGF0dGFjaFN0cmVhbVRvVmlkZW8oc3RyZWFtLCB2aWRlb1NvdXJjZSkge1xuICAgICAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB2aWRlb0VsZW1lbnQgPSB0aGlzLnByZXBhcmVWaWRlb0VsZW1lbnQodmlkZW9Tb3VyY2UpO1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkVmlkZW9Tb3VyY2UodmlkZW9FbGVtZW50LCBzdHJlYW0pO1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9FbGVtZW50ID0gdmlkZW9FbGVtZW50O1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICAgICAgICAgIHlpZWxkIHRoaXMucGxheVZpZGVvT25Mb2FkQXN5bmModmlkZW9FbGVtZW50KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdmlkZW9FbGVtZW50O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB2aWRlb0VsZW1lbnRcbiAgICAgICAgICovXG4gICAgICAgIHBsYXlWaWRlb09uTG9hZEFzeW5jKHZpZGVvRWxlbWVudCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHRoaXMucGxheVZpZGVvT25Mb2FkKHZpZGVvRWxlbWVudCwgKCkgPT4gcmVzb2x2ZSgpKSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEJpbmRzIGxpc3RlbmVycyBhbmQgY2FsbGJhY2tzIHRvIHRoZSB2aWRlb0VsZW1lbnQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBlbGVtZW50XG4gICAgICAgICAqIEBwYXJhbSBjYWxsYmFja0ZuXG4gICAgICAgICAqL1xuICAgICAgICBwbGF5VmlkZW9PbkxvYWQoZWxlbWVudCwgY2FsbGJhY2tGbikge1xuICAgICAgICAgICAgdGhpcy52aWRlb0VuZGVkTGlzdGVuZXIgPSAoKSA9PiB0aGlzLnN0b3BTdHJlYW1zKCk7XG4gICAgICAgICAgICB0aGlzLnZpZGVvQ2FuUGxheUxpc3RlbmVyID0gKCkgPT4gdGhpcy50cnlQbGF5VmlkZW8oZWxlbWVudCk7XG4gICAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2VuZGVkJywgdGhpcy52aWRlb0VuZGVkTGlzdGVuZXIpO1xuICAgICAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdjYW5wbGF5JywgdGhpcy52aWRlb0NhblBsYXlMaXN0ZW5lcik7XG4gICAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3BsYXlpbmcnLCBjYWxsYmFja0ZuKTtcbiAgICAgICAgICAgIC8vIGlmIGNhbnBsYXkgd2FzIGFscmVhZHkgZmlyZWQsIHdlIHdvbid0IGtub3cgd2hlbiB0byBwbGF5LCBzbyBqdXN0IGdpdmUgaXQgYSB0cnlcbiAgICAgICAgICAgIHRoaXMudHJ5UGxheVZpZGVvKGVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDaGVja3MgaWYgdGhlIGdpdmVuIHZpZGVvIGVsZW1lbnQgaXMgY3VycmVudGx5IHBsYXlpbmcuXG4gICAgICAgICAqL1xuICAgICAgICBpc1ZpZGVvUGxheWluZyh2aWRlbykge1xuICAgICAgICAgICAgcmV0dXJuIHZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJiAhdmlkZW8ucGF1c2VkICYmICF2aWRlby5lbmRlZCAmJiB2aWRlby5yZWFkeVN0YXRlID4gMjtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogSnVzdCB0cmllcyB0byBwbGF5IHRoZSB2aWRlbyBhbmQgbG9ncyBhbnkgZXJyb3JzLlxuICAgICAgICAgKiBUaGUgcGxheSBjYWxsIGlzIG9ubHkgbWFkZSBpcyB0aGUgdmlkZW8gaXMgbm90IGFscmVhZHkgcGxheWluZy5cbiAgICAgICAgICovXG4gICAgICAgIHRyeVBsYXlWaWRlbyh2aWRlb0VsZW1lbnQpIHtcbiAgICAgICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNWaWRlb1BsYXlpbmcodmlkZW9FbGVtZW50KSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1RyeWluZyB0byBwbGF5IHZpZGVvIHRoYXQgaXMgYWxyZWFkeSBwbGF5aW5nLicpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHlpZWxkIHZpZGVvRWxlbWVudC5wbGF5KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChfYSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0l0IHdhcyBub3QgcG9zc2libGUgdG8gcGxheSB0aGUgdmlkZW8uJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNlYXJjaGVzIGFuZCB2YWxpZGF0ZXMgYSBtZWRpYSBlbGVtZW50LlxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0TWVkaWFFbGVtZW50KG1lZGlhRWxlbWVudElkLCB0eXBlKSB7XG4gICAgICAgICAgICBjb25zdCBtZWRpYUVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChtZWRpYUVsZW1lbnRJZCk7XG4gICAgICAgICAgICBpZiAoIW1lZGlhRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBBcmd1bWVudEV4Y2VwdGlvbihgZWxlbWVudCB3aXRoIGlkICcke21lZGlhRWxlbWVudElkfScgbm90IGZvdW5kYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVkaWFFbGVtZW50Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgIT09IHR5cGUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBBcmd1bWVudEV4Y2VwdGlvbihgZWxlbWVudCB3aXRoIGlkICcke21lZGlhRWxlbWVudElkfScgbXVzdCBiZSBhbiAke3R5cGV9IGVsZW1lbnRgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtZWRpYUVsZW1lbnQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgdGhlIGJhcmNvZGUgZnJvbSBhbiBpbWFnZS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHsoc3RyaW5nfEhUTUxJbWFnZUVsZW1lbnQpfSBbc291cmNlXSBUaGUgaW1hZ2UgZWxlbWVudCB0aGF0IGNhbiBiZSBlaXRoZXIgYW4gZWxlbWVudCBpZCBvciB0aGUgZWxlbWVudCBpdHNlbGYuIENhbiBiZSB1bmRlZmluZWQgaW4gd2hpY2ggY2FzZSB0aGUgZGVjb2Rpbmcgd2lsbCBiZSBkb25lIGZyb20gdGhlIGltYWdlVXJsIHBhcmFtZXRlci5cbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IFt1cmxdXG4gICAgICAgICAqIEByZXR1cm5zIHtQcm9taXNlPFJlc3VsdD59IFRoZSBkZWNvZGluZyByZXN1bHQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBtZW1iZXJPZiBCcm93c2VyQ29kZVJlYWRlclxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlRnJvbUltYWdlKHNvdXJjZSwgdXJsKSB7XG4gICAgICAgICAgICBpZiAoIXNvdXJjZSAmJiAhdXJsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEFyZ3VtZW50RXhjZXB0aW9uKCdlaXRoZXIgaW1hZ2VFbGVtZW50IHdpdGggYSBzcmMgc2V0IG9yIGFuIHVybCBtdXN0IGJlIHByb3ZpZGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodXJsICYmICFzb3VyY2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGVGcm9tSW1hZ2VVcmwodXJsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZUZyb21JbWFnZUVsZW1lbnQoc291cmNlKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyB0aGUgYmFyY29kZSBmcm9tIGEgdmlkZW8uXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB7KHN0cmluZ3xIVE1MSW1hZ2VFbGVtZW50KX0gW3NvdXJjZV0gVGhlIGltYWdlIGVsZW1lbnQgdGhhdCBjYW4gYmUgZWl0aGVyIGFuIGVsZW1lbnQgaWQgb3IgdGhlIGVsZW1lbnQgaXRzZWxmLiBDYW4gYmUgdW5kZWZpbmVkIGluIHdoaWNoIGNhc2UgdGhlIGRlY29kaW5nIHdpbGwgYmUgZG9uZSBmcm9tIHRoZSBpbWFnZVVybCBwYXJhbWV0ZXIuXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbdXJsXVxuICAgICAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZXN1bHQ+fSBUaGUgZGVjb2RpbmcgcmVzdWx0LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAbWVtYmVyT2YgQnJvd3NlckNvZGVSZWFkZXJcbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZUZyb21WaWRlbyhzb3VyY2UsIHVybCkge1xuICAgICAgICAgICAgaWYgKCFzb3VyY2UgJiYgIXVybCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBBcmd1bWVudEV4Y2VwdGlvbignRWl0aGVyIGFuIGVsZW1lbnQgd2l0aCBhIHNyYyBzZXQgb3IgYW4gVVJMIG11c3QgYmUgcHJvdmlkZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh1cmwgJiYgIXNvdXJjZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZUZyb21WaWRlb1VybCh1cmwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlRnJvbVZpZGVvRWxlbWVudChzb3VyY2UpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIGNvbnRpbnVvdXNseSB0aGUgYmFyY29kZSBmcm9tIGEgdmlkZW8uXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB7KHN0cmluZ3xIVE1MSW1hZ2VFbGVtZW50KX0gW3NvdXJjZV0gVGhlIGltYWdlIGVsZW1lbnQgdGhhdCBjYW4gYmUgZWl0aGVyIGFuIGVsZW1lbnQgaWQgb3IgdGhlIGVsZW1lbnQgaXRzZWxmLiBDYW4gYmUgdW5kZWZpbmVkIGluIHdoaWNoIGNhc2UgdGhlIGRlY29kaW5nIHdpbGwgYmUgZG9uZSBmcm9tIHRoZSBpbWFnZVVybCBwYXJhbWV0ZXIuXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbdXJsXVxuICAgICAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZXN1bHQ+fSBUaGUgZGVjb2RpbmcgcmVzdWx0LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAbWVtYmVyT2YgQnJvd3NlckNvZGVSZWFkZXJcbiAgICAgICAgICpcbiAgICAgICAgICogQGV4cGVyaW1lbnRhbFxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlRnJvbVZpZGVvQ29udGludW91c2x5KHNvdXJjZSwgdXJsLCBjYWxsYmFja0ZuKSB7XG4gICAgICAgICAgICBpZiAodW5kZWZpbmVkID09PSBzb3VyY2UgJiYgdW5kZWZpbmVkID09PSB1cmwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQXJndW1lbnRFeGNlcHRpb24oJ0VpdGhlciBhbiBlbGVtZW50IHdpdGggYSBzcmMgc2V0IG9yIGFuIFVSTCBtdXN0IGJlIHByb3ZpZGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodXJsICYmICFzb3VyY2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGVGcm9tVmlkZW9VcmxDb250aW51b3VzbHkodXJsLCBjYWxsYmFja0ZuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZUZyb21WaWRlb0VsZW1lbnRDb250aW51b3VzbHkoc291cmNlLCBjYWxsYmFja0ZuKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBzb21ldGhpbmcgZnJvbSBhbiBpbWFnZSBIVE1MIGVsZW1lbnQuXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGVGcm9tSW1hZ2VFbGVtZW50KHNvdXJjZSkge1xuICAgICAgICAgICAgaWYgKCFzb3VyY2UpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQXJndW1lbnRFeGNlcHRpb24oJ0FuIGltYWdlIGVsZW1lbnQgbXVzdCBiZSBwcm92aWRlZC4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLnByZXBhcmVJbWFnZUVsZW1lbnQoc291cmNlKTtcbiAgICAgICAgICAgIHRoaXMuaW1hZ2VFbGVtZW50ID0gZWxlbWVudDtcbiAgICAgICAgICAgIGxldCB0YXNrO1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNJbWFnZUxvYWRlZChlbGVtZW50KSkge1xuICAgICAgICAgICAgICAgIHRhc2sgPSB0aGlzLmRlY29kZU9uY2UoZWxlbWVudCwgZmFsc2UsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGFzayA9IHRoaXMuX2RlY29kZU9uTG9hZEltYWdlKGVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRhc2s7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgc29tZXRoaW5nIGZyb20gYW4gaW1hZ2UgSFRNTCBlbGVtZW50LlxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlRnJvbVZpZGVvRWxlbWVudChzb3VyY2UpIHtcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLl9kZWNvZGVGcm9tVmlkZW9FbGVtZW50U2V0dXAoc291cmNlKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9kZWNvZGVPbkxvYWRWaWRlbyhlbGVtZW50KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBzb21ldGhpbmcgZnJvbSBhbiBpbWFnZSBIVE1MIGVsZW1lbnQuXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGVGcm9tVmlkZW9FbGVtZW50Q29udGludW91c2x5KHNvdXJjZSwgY2FsbGJhY2tGbikge1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuX2RlY29kZUZyb21WaWRlb0VsZW1lbnRTZXR1cChzb3VyY2UpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2RlY29kZU9uTG9hZFZpZGVvQ29udGludW91c2x5KGVsZW1lbnQsIGNhbGxiYWNrRm4pO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZXRzIHVwIHRoZSB2aWRlbyBzb3VyY2Ugc28gaXQgY2FuIGJlIGRlY29kZWQgd2hlbiBsb2FkZWQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBzb3VyY2UgVGhlIHZpZGVvIHNvdXJjZSBlbGVtZW50LlxuICAgICAgICAgKi9cbiAgICAgICAgX2RlY29kZUZyb21WaWRlb0VsZW1lbnRTZXR1cChzb3VyY2UpIHtcbiAgICAgICAgICAgIGlmICghc291cmNlKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEFyZ3VtZW50RXhjZXB0aW9uKCdBIHZpZGVvIGVsZW1lbnQgbXVzdCBiZSBwcm92aWRlZC4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLnByZXBhcmVWaWRlb0VsZW1lbnQoc291cmNlKTtcbiAgICAgICAgICAgIC8vIGRlZmluZXMgdGhlIHZpZGVvIGVsZW1lbnQgYmVmb3JlIHN0YXJ0cyBkZWNvZGluZ1xuICAgICAgICAgICAgdGhpcy52aWRlb0VsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgICAgICAgcmV0dXJuIGVsZW1lbnQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYW4gaW1hZ2UgZnJvbSBhIFVSTC5cbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZUZyb21JbWFnZVVybCh1cmwpIHtcbiAgICAgICAgICAgIGlmICghdXJsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEFyZ3VtZW50RXhjZXB0aW9uKCdBbiBVUkwgbXVzdCBiZSBwcm92aWRlZC4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLnByZXBhcmVJbWFnZUVsZW1lbnQoKTtcbiAgICAgICAgICAgIHRoaXMuaW1hZ2VFbGVtZW50ID0gZWxlbWVudDtcbiAgICAgICAgICAgIGNvbnN0IGRlY29kZVRhc2sgPSB0aGlzLl9kZWNvZGVPbkxvYWRJbWFnZShlbGVtZW50KTtcbiAgICAgICAgICAgIGVsZW1lbnQuc3JjID0gdXJsO1xuICAgICAgICAgICAgcmV0dXJuIGRlY29kZVRhc2s7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYW4gaW1hZ2UgZnJvbSBhIFVSTC5cbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZUZyb21WaWRlb1VybCh1cmwpIHtcbiAgICAgICAgICAgIGlmICghdXJsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEFyZ3VtZW50RXhjZXB0aW9uKCdBbiBVUkwgbXVzdCBiZSBwcm92aWRlZC4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgICAgIC8vIGNyZWF0ZXMgYSBuZXcgZWxlbWVudFxuICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMucHJlcGFyZVZpZGVvRWxlbWVudCgpO1xuICAgICAgICAgICAgY29uc3QgZGVjb2RlVGFzayA9IHRoaXMuZGVjb2RlRnJvbVZpZGVvRWxlbWVudChlbGVtZW50KTtcbiAgICAgICAgICAgIGVsZW1lbnQuc3JjID0gdXJsO1xuICAgICAgICAgICAgcmV0dXJuIGRlY29kZVRhc2s7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYW4gaW1hZ2UgZnJvbSBhIFVSTC5cbiAgICAgICAgICpcbiAgICAgICAgICogQGV4cGVyaW1lbnRhbFxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlRnJvbVZpZGVvVXJsQ29udGludW91c2x5KHVybCwgY2FsbGJhY2tGbikge1xuICAgICAgICAgICAgaWYgKCF1cmwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQXJndW1lbnRFeGNlcHRpb24oJ0FuIFVSTCBtdXN0IGJlIHByb3ZpZGVkLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yZXNldCgpO1xuICAgICAgICAgICAgLy8gY3JlYXRlcyBhIG5ldyBlbGVtZW50XG4gICAgICAgICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5wcmVwYXJlVmlkZW9FbGVtZW50KCk7XG4gICAgICAgICAgICBjb25zdCBkZWNvZGVUYXNrID0gdGhpcy5kZWNvZGVGcm9tVmlkZW9FbGVtZW50Q29udGludW91c2x5KGVsZW1lbnQsIGNhbGxiYWNrRm4pO1xuICAgICAgICAgICAgZWxlbWVudC5zcmMgPSB1cmw7XG4gICAgICAgICAgICByZXR1cm4gZGVjb2RlVGFzaztcbiAgICAgICAgfVxuICAgICAgICBfZGVjb2RlT25Mb2FkSW1hZ2UoZWxlbWVudCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmltYWdlTG9hZGVkTGlzdGVuZXIgPSAoKSA9PiB0aGlzLmRlY29kZU9uY2UoZWxlbWVudCwgZmFsc2UsIHRydWUpLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCB0aGlzLmltYWdlTG9hZGVkTGlzdGVuZXIpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgX2RlY29kZU9uTG9hZFZpZGVvKHZpZGVvRWxlbWVudCkge1xuICAgICAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgICAgICAgICAgICAvLyBwbGF5cyB0aGUgdmlkZW9cbiAgICAgICAgICAgICAgICB5aWVsZCB0aGlzLnBsYXlWaWRlb09uTG9hZEFzeW5jKHZpZGVvRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgLy8gc3RhcnRzIGRlY29kaW5nIGFmdGVyIHBsYXllZCB0aGUgdmlkZW9cbiAgICAgICAgICAgICAgICByZXR1cm4geWllbGQgdGhpcy5kZWNvZGVPbmNlKHZpZGVvRWxlbWVudCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBfZGVjb2RlT25Mb2FkVmlkZW9Db250aW51b3VzbHkodmlkZW9FbGVtZW50LCBjYWxsYmFja0ZuKSB7XG4gICAgICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgICAgICAgICAgIC8vIHBsYXlzIHRoZSB2aWRlb1xuICAgICAgICAgICAgICAgIHlpZWxkIHRoaXMucGxheVZpZGVvT25Mb2FkQXN5bmModmlkZW9FbGVtZW50KTtcbiAgICAgICAgICAgICAgICAvLyBzdGFydHMgZGVjb2RpbmcgYWZ0ZXIgcGxheWVkIHRoZSB2aWRlb1xuICAgICAgICAgICAgICAgIHRoaXMuZGVjb2RlQ29udGludW91c2x5KHZpZGVvRWxlbWVudCwgY2FsbGJhY2tGbik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpc0ltYWdlTG9hZGVkKGltZykge1xuICAgICAgICAgICAgLy8gRHVyaW5nIHRoZSBvbmxvYWQgZXZlbnQsIElFIGNvcnJlY3RseSBpZGVudGlmaWVzIGFueSBpbWFnZXMgdGhhdFxuICAgICAgICAgICAgLy8gd2VyZW7igJl0IGRvd25sb2FkZWQgYXMgbm90IGNvbXBsZXRlLiBPdGhlcnMgc2hvdWxkIHRvby4gR2Vja28tYmFzZWRcbiAgICAgICAgICAgIC8vIGJyb3dzZXJzIGFjdCBsaWtlIE5TNCBpbiB0aGF0IHRoZXkgcmVwb3J0IHRoaXMgaW5jb3JyZWN0bHkuXG4gICAgICAgICAgICBpZiAoIWltZy5jb21wbGV0ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEhvd2V2ZXIsIHRoZXkgZG8gaGF2ZSB0d28gdmVyeSB1c2VmdWwgcHJvcGVydGllczogbmF0dXJhbFdpZHRoIGFuZFxuICAgICAgICAgICAgLy8gbmF0dXJhbEhlaWdodC4gVGhlc2UgZ2l2ZSB0aGUgdHJ1ZSBzaXplIG9mIHRoZSBpbWFnZS4gSWYgaXQgZmFpbGVkXG4gICAgICAgICAgICAvLyB0byBsb2FkLCBlaXRoZXIgb2YgdGhlc2Ugc2hvdWxkIGJlIHplcm8uXG4gICAgICAgICAgICBpZiAoaW1nLm5hdHVyYWxXaWR0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE5vIG90aGVyIHdheSBvZiBjaGVja2luZzogYXNzdW1lIGl04oCZcyBvay5cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHByZXBhcmVJbWFnZUVsZW1lbnQoaW1hZ2VTb3VyY2UpIHtcbiAgICAgICAgICAgIGxldCBpbWFnZUVsZW1lbnQ7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGltYWdlU291cmNlID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGltYWdlRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xuICAgICAgICAgICAgICAgIGltYWdlRWxlbWVudC53aWR0aCA9IDIwMDtcbiAgICAgICAgICAgICAgICBpbWFnZUVsZW1lbnQuaGVpZ2h0ID0gMjAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBpbWFnZVNvdXJjZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBpbWFnZUVsZW1lbnQgPSB0aGlzLmdldE1lZGlhRWxlbWVudChpbWFnZVNvdXJjZSwgJ2ltZycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGltYWdlU291cmNlIGluc3RhbmNlb2YgSFRNTEltYWdlRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIGltYWdlRWxlbWVudCA9IGltYWdlU291cmNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGltYWdlRWxlbWVudDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogU2V0cyBhIEhUTUxWaWRlb0VsZW1lbnQgZm9yIHNjYW5uaW5nIG9yIGNyZWF0ZXMgYSBuZXcgb25lLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gdmlkZW9Tb3VyY2UgVGhlIEhUTUxWaWRlb0VsZW1lbnQgdG8gYmUgc2V0LlxuICAgICAgICAgKi9cbiAgICAgICAgcHJlcGFyZVZpZGVvRWxlbWVudCh2aWRlb1NvdXJjZSkge1xuICAgICAgICAgICAgbGV0IHZpZGVvRWxlbWVudDtcbiAgICAgICAgICAgIGlmICghdmlkZW9Tb3VyY2UgJiYgdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIHZpZGVvRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgICAgICAgICAgdmlkZW9FbGVtZW50LndpZHRoID0gMjAwO1xuICAgICAgICAgICAgICAgIHZpZGVvRWxlbWVudC5oZWlnaHQgPSAyMDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIHZpZGVvU291cmNlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHZpZGVvRWxlbWVudCA9IHRoaXMuZ2V0TWVkaWFFbGVtZW50KHZpZGVvU291cmNlLCAndmlkZW8nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh2aWRlb1NvdXJjZSBpbnN0YW5jZW9mIEhUTUxWaWRlb0VsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB2aWRlb0VsZW1lbnQgPSB2aWRlb1NvdXJjZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE5lZWRlZCBmb3IgaU9TIDExXG4gICAgICAgICAgICB2aWRlb0VsZW1lbnQuc2V0QXR0cmlidXRlKCdhdXRvcGxheScsICd0cnVlJyk7XG4gICAgICAgICAgICB2aWRlb0VsZW1lbnQuc2V0QXR0cmlidXRlKCdtdXRlZCcsICd0cnVlJyk7XG4gICAgICAgICAgICB2aWRlb0VsZW1lbnQuc2V0QXR0cmlidXRlKCdwbGF5c2lubGluZScsICd0cnVlJyk7XG4gICAgICAgICAgICByZXR1cm4gdmlkZW9FbGVtZW50O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUcmllcyB0byBkZWNvZGUgZnJvbSB0aGUgdmlkZW8gaW5wdXQgdW50aWwgaXQgZmluZHMgc29tZSB2YWx1ZS5cbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZU9uY2UoZWxlbWVudCwgcmV0cnlJZk5vdEZvdW5kID0gdHJ1ZSwgcmV0cnlJZkNoZWNrc3VtT3JGb3JtYXRFcnJvciA9IHRydWUpIHtcbiAgICAgICAgICAgIHRoaXMuX3N0b3BBc3luY0RlY29kZSA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3QgbG9vcCA9IChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fc3RvcEFzeW5jRGVjb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgTm90Rm91bmRFeGNlcHRpb24oJ1ZpZGVvIHN0cmVhbSBoYXMgZW5kZWQgYmVmb3JlIGFueSBjb2RlIGNvdWxkIGJlIGRldGVjdGVkLicpKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc3RvcEFzeW5jRGVjb2RlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuZGVjb2RlKGVsZW1lbnQpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGlmTm90Rm91bmQgPSByZXRyeUlmTm90Rm91bmQgJiYgZSBpbnN0YW5jZW9mIE5vdEZvdW5kRXhjZXB0aW9uO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBpc0NoZWNrc3VtT3JGb3JtYXRFcnJvciA9IGUgaW5zdGFuY2VvZiBDaGVja3N1bUV4Y2VwdGlvbiB8fCBlIGluc3RhbmNlb2YgRm9ybWF0RXhjZXB0aW9uO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBpZkNoZWNrc3VtT3JGb3JtYXQgPSBpc0NoZWNrc3VtT3JGb3JtYXRFcnJvciAmJiByZXRyeUlmQ2hlY2tzdW1PckZvcm1hdEVycm9yO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaWZOb3RGb3VuZCB8fCBpZkNoZWNrc3VtT3JGb3JtYXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRyeWluZyBhZ2FpblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQobG9vcCwgdGhpcy5fdGltZUJldHdlZW5EZWNvZGluZ0F0dGVtcHRzLCByZXNvbHZlLCByZWplY3QpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IGxvb3AocmVzb2x2ZSwgcmVqZWN0KSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnRpbnVvdXNseSBkZWNvZGVzIGZyb20gdmlkZW8gaW5wdXQuXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGVDb250aW51b3VzbHkoZWxlbWVudCwgY2FsbGJhY2tGbikge1xuICAgICAgICAgICAgdGhpcy5fc3RvcENvbnRpbnVvdXNEZWNvZGUgPSBmYWxzZTtcbiAgICAgICAgICAgIGNvbnN0IGxvb3AgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX3N0b3BDb250aW51b3VzRGVjb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3N0b3BDb250aW51b3VzRGVjb2RlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuZGVjb2RlKGVsZW1lbnQpO1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFja0ZuKHJlc3VsdCwgbnVsbCk7XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQobG9vcCwgdGhpcy50aW1lQmV0d2VlblNjYW5zTWlsbGlzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2tGbihudWxsLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaXNDaGVja3N1bU9yRm9ybWF0RXJyb3IgPSBlIGluc3RhbmNlb2YgQ2hlY2tzdW1FeGNlcHRpb24gfHwgZSBpbnN0YW5jZW9mIEZvcm1hdEV4Y2VwdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaXNOb3RGb3VuZCA9IGUgaW5zdGFuY2VvZiBOb3RGb3VuZEV4Y2VwdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzQ2hlY2tzdW1PckZvcm1hdEVycm9yIHx8IGlzTm90Rm91bmQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRyeWluZyBhZ2FpblxuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChsb29wLCB0aGlzLl90aW1lQmV0d2VlbkRlY29kaW5nQXR0ZW1wdHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGxvb3AoKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogR2V0cyB0aGUgQmluYXJ5Qml0bWFwIGZvciB5YSEgKGFuZCBkZWNvZGVzIGl0KVxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlKGVsZW1lbnQpIHtcbiAgICAgICAgICAgIC8vIGdldCBiaW5hcnkgYml0bWFwIGZvciBkZWNvZGUgZnVuY3Rpb25cbiAgICAgICAgICAgIGNvbnN0IGJpbmFyeUJpdG1hcCA9IHRoaXMuY3JlYXRlQmluYXJ5Qml0bWFwKGVsZW1lbnQpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlQml0bWFwKGJpbmFyeUJpdG1hcCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldHVybnMgdHJ1ZSBpZiBtZWRpYSBlbGVtZW50IGlzIGluZGVlZCBhIHtAbGluayBIdG1sVmlkZW9FbGVtZW50fS5cbiAgICAgICAgICovXG4gICAgICAgIF9pc0hUTUxWaWRlb0VsZW1lbnQobWVkaWFFbGVtZW50KSB7XG4gICAgICAgICAgICBjb25zdCBwb3RlbnRpYWxWaWRlbyA9IG1lZGlhRWxlbWVudDtcbiAgICAgICAgICAgIHJldHVybiBwb3RlbnRpYWxWaWRlby52aWRlb1dpZHRoICE9PSAwO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBPdmVyd3JpdGluZyB0aGlzIGFsbG93cyB5b3UgdG8gbWFuaXB1bGF0ZSB0aGUgbmV4dCBmcmFtZSBpbiBhbnl3YXlcbiAgICAgICAgICogeW91IHdhbnQgYmVmb3JlIGRlY29kZS5cbiAgICAgICAgICovXG4gICAgICAgIGRyYXdGcmFtZU9uQ2FudmFzKFxuICAgICAgICAgICAgc3JjRWxlbWVudCwgZGltZW5zaW9ucywgY2FudmFzRWxlbWVudENvbnRleHQpIHtcbiAgICAgICAgICAgIGlmICghZGltZW5zaW9ucykge1xuICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHN4OiAwLFxuICAgICAgICAgICAgICAgICAgICBzeTogMCxcbiAgICAgICAgICAgICAgICAgICAgc1dpZHRoOiBzcmNFbGVtZW50LnZpZGVvV2lkdGgsXG4gICAgICAgICAgICAgICAgICAgIHNIZWlnaHQ6IHNyY0VsZW1lbnQudmlkZW9IZWlnaHQsXG4gICAgICAgICAgICAgICAgICAgIGR4OiAwLFxuICAgICAgICAgICAgICAgICAgICBkeTogMCxcbiAgICAgICAgICAgICAgICAgICAgZFdpZHRoOiBzcmNFbGVtZW50LnZpZGVvV2lkdGgsXG4gICAgICAgICAgICAgICAgICAgIGRIZWlnaHQ6IHNyY0VsZW1lbnQudmlkZW9IZWlnaHR9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFjYW52YXNFbGVtZW50Q29udGV4dCkge1xuICAgICAgICAgICAgICAgIGNhbnZhc0VsZW1lbnRDb250ZXh0ID0gdGhpcy5jYXB0dXJlQ2FudmFzQ29udGV4dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbnZhc0VsZW1lbnRDb250ZXh0LmRyYXdJbWFnZShcbiAgICAgICAgICAgICAgICBzcmNFbGVtZW50LFxuICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMuc3gsXG4gICAgICAgICAgICAgICAgZGltZW5zaW9ucy5zeSxcbiAgICAgICAgICAgICAgICBkaW1lbnNpb25zLnNXaWR0aCxcbiAgICAgICAgICAgICAgICBkaW1lbnNpb25zLnNIZWlnaHQsXG4gICAgICAgICAgICAgICAgZGltZW5zaW9ucy5keCxcbiAgICAgICAgICAgICAgICBkaW1lbnNpb25zLmR5LFxuICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMuZFdpZHRoLFxuICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMuZEhlaWdodCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE92ZXdyaXRpbmcgdGhpcyBhbGxvd3MgeW91IHRvIG1hbmlwdWxhdGUgdGhlIHNuYXBzaG90IGltYWdlIGluIGFueXdheVxuICAgICAgICAgKiAgeW91IHdhbnQgYmVmb3JlIGRlY29kZS5cbiAgICAgICAgICovXG4gICAgICAgIGRyYXdJbWFnZU9uQ2FudmFzKFxuICAgICAgICAgICAgc3JjRWxlbWVudCxcbiAgICAgICAgICAgIGRpbWVuc2lvbnMsXG4gICAgICAgICAgICBjYW52YXNFbGVtZW50Q29udGV4dCA9IHRoaXMuY2FwdHVyZUNhbnZhc0NvbnRleHQpIHtcbiAgICAgICAgICAgIGlmICghZGltZW5zaW9ucykge1xuICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHN4OiAwLFxuICAgICAgICAgICAgICAgICAgICBzeTogMCxcbiAgICAgICAgICAgICAgICAgICAgc1dpZHRoOiBzcmNFbGVtZW50Lm5hdHVyYWxXaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgc0hlaWdodDogc3JjRWxlbWVudC5uYXR1cmFsSGVpZ2h0LFxuICAgICAgICAgICAgICAgICAgICBkeDogMCxcbiAgICAgICAgICAgICAgICAgICAgZHk6IDAsXG4gICAgICAgICAgICAgICAgICAgIGRXaWR0aDogc3JjRWxlbWVudC5uYXR1cmFsV2lkdGgsXG4gICAgICAgICAgICAgICAgICAgIGRIZWlnaHQ6IHNyY0VsZW1lbnQubmF0dXJhbEhlaWdodFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWNhbnZhc0VsZW1lbnRDb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgY2FudmFzRWxlbWVudENvbnRleHQgPSB0aGlzLmNhcHR1cmVDYW52YXNDb250ZXh0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FudmFzRWxlbWVudENvbnRleHQuZHJhd0ltYWdlKFxuICAgICAgICAgICAgICAgIHNyY0VsZW1lbnQsXG4gICAgICAgICAgICAgICAgZGltZW5zaW9ucy5zeCxcbiAgICAgICAgICAgICAgICBkaW1lbnNpb25zLnN5LFxuICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMuc1dpZHRoLFxuICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMuc0hlaWdodCxcbiAgICAgICAgICAgICAgICBkaW1lbnNpb25zLmR4LFxuICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMuZHksXG4gICAgICAgICAgICAgICAgZGltZW5zaW9ucy5kV2lkdGgsXG4gICAgICAgICAgICAgICAgZGltZW5zaW9ucy5kSGVpZ2h0KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIGJpbmFyeUJpdG1hcCBiYXNlZCBpbiBzb21lIGltYWdlIHNvdXJjZS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIG1lZGlhRWxlbWVudCBIVE1MIGVsZW1lbnQgY29udGFpbmluZyBkcmF3YWJsZSBpbWFnZSBzb3VyY2UuXG4gICAgICAgICAqL1xuICAgICAgICBjcmVhdGVCaW5hcnlCaXRtYXAobWVkaWFFbGVtZW50KSB7XG4gICAgICAgICAgICBjb25zdCBjdHggPSB0aGlzLmdldENhcHR1cmVDYW52YXNDb250ZXh0KG1lZGlhRWxlbWVudCk7XG4gICAgICAgICAgICBpZiAodGhpcy5faXNIVE1MVmlkZW9FbGVtZW50KG1lZGlhRWxlbWVudCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRyYXdGcmFtZU9uQ2FudmFzKG1lZGlhRWxlbWVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuZHJhd0ltYWdlT25DYW52YXMobWVkaWFFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGNhbnZhcyA9IHRoaXMuZ2V0Q2FwdHVyZUNhbnZhcyhtZWRpYUVsZW1lbnQpO1xuICAgICAgICAgICAgY29uc3QgbHVtaW5hbmNlU291cmNlID0gbmV3IEhUTUxDYW52YXNFbGVtZW50THVtaW5hbmNlU291cmNlKGNhbnZhcyk7XG4gICAgICAgICAgICBjb25zdCBoeWJyaWRCaW5hcml6ZXIgPSBuZXcgSHlicmlkQmluYXJpemVyKGx1bWluYW5jZVNvdXJjZSk7XG5cbiAgICAgICAgICAgIHJldHVybiBuZXcgQmluYXJ5Qml0bWFwKGh5YnJpZEJpbmFyaXplcik7XG4gICAgICAgIH1cblxuICAgICAgICBnZXRDYXB0dXJlQ2FudmFzQ29udGV4dChtZWRpYUVsZW1lbnQpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5jYXB0dXJlQ2FudmFzQ29udGV4dCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGVsZW0gPSB0aGlzLmdldENhcHR1cmVDYW52YXMobWVkaWFFbGVtZW50KTtcbiAgICAgICAgICAgICAgICBjb25zdCBjdHggPSBlbGVtLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgICAgICAgICAgdGhpcy5jYXB0dXJlQ2FudmFzQ29udGV4dCA9IGN0eDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNhcHR1cmVDYW52YXNDb250ZXh0O1xuICAgICAgICB9XG4gICAgICAgIGdldENhcHR1cmVDYW52YXMobWVkaWFFbGVtZW50KSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY2FwdHVyZUNhbnZhcykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGVsZW0gPSB0aGlzLmNyZWF0ZUNhcHR1cmVDYW52YXMobWVkaWFFbGVtZW50KTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhcHR1cmVDYW52YXMgPSBlbGVtO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2FwdHVyZUNhbnZhcztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ2FsbCB0aGUgZW5jYXBzdWxhdGVkIHJlYWRlcnMgZGVjb2RlXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGVCaXRtYXAoYmluYXJ5Qml0bWFwKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZWFkZXIuZGVjb2RlKGJpbmFyeUJpdG1hcCwgdGhpcy5faGludHMpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiDwn5aMIFByZXBhcmVzIHRoZSBjYW52YXMgZm9yIGNhcHR1cmUgYW5kIHNjYW4gZnJhbWVzLlxuICAgICAgICAgKi9cbiAgICAgICAgY3JlYXRlQ2FwdHVyZUNhbnZhcyhtZWRpYUVsZW1lbnQpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZGVzdHJveUNhcHR1cmVDYW52YXMoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGNhbnZhc0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgICAgIGxldCB3aWR0aDtcbiAgICAgICAgICAgIGxldCBoZWlnaHQ7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1lZGlhRWxlbWVudCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICBpZiAobWVkaWFFbGVtZW50IGluc3RhbmNlb2YgSFRNTFZpZGVvRWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICB3aWR0aCA9IG1lZGlhRWxlbWVudC52aWRlb1dpZHRoO1xuICAgICAgICAgICAgICAgICAgICBoZWlnaHQgPSBtZWRpYUVsZW1lbnQudmlkZW9IZWlnaHQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKG1lZGlhRWxlbWVudCBpbnN0YW5jZW9mIEhUTUxJbWFnZUVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgd2lkdGggPSBtZWRpYUVsZW1lbnQubmF0dXJhbFdpZHRoIHx8IG1lZGlhRWxlbWVudC53aWR0aDtcbiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0ID0gbWVkaWFFbGVtZW50Lm5hdHVyYWxIZWlnaHQgfHwgbWVkaWFFbGVtZW50LmhlaWdodDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYW52YXNFbGVtZW50LnN0eWxlLndpZHRoID0gd2lkdGggKyAncHgnO1xuICAgICAgICAgICAgY2FudmFzRWxlbWVudC5zdHlsZS5oZWlnaHQgPSBoZWlnaHQgKyAncHgnO1xuICAgICAgICAgICAgY2FudmFzRWxlbWVudC53aWR0aCA9IHdpZHRoO1xuICAgICAgICAgICAgY2FudmFzRWxlbWVudC5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgICAgICByZXR1cm4gY2FudmFzRWxlbWVudDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogU3RvcHMgdGhlIGNvbnRpbnVvdXMgc2NhbiBhbmQgY2xlYW5zIHRoZSBzdHJlYW0uXG4gICAgICAgICAqL1xuICAgICAgICBzdG9wU3RyZWFtcygpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCh0ID0+IHQuc3RvcCgpKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9zdG9wQXN5bmNEZWNvZGUgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdG9wQXN5bmNEZWNvZGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9zdG9wQ29udGludW91c0RlY29kZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0b3BDb250aW51b3VzRGVjb2RlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJlc2V0cyB0aGUgY29kZSByZWFkZXIgdG8gdGhlIGluaXRpYWwgc3RhdGUuIENhbmNlbHMgYW55IG9uZ29pbmcgYmFyY29kZSBzY2FubmluZyBmcm9tIHZpZGVvIG9yIGNhbWVyYS5cbiAgICAgICAgICpcbiAgICAgICAgICogQG1lbWJlck9mIEJyb3dzZXJDb2RlUmVhZGVyXG4gICAgICAgICAqL1xuICAgICAgICByZXNldCgpIHtcbiAgICAgICAgICAgIC8vIHN0b3BzIHRoZSBjYW1lcmEsIHByZXZpZXcgYW5kIHNjYW4g8J+UtFxuICAgICAgICAgICAgdGhpcy5zdG9wU3RyZWFtcygpO1xuICAgICAgICAgICAgLy8gY2xlYW4gYW5kIGZvcmdldCBhYm91dCBIVE1MIGVsZW1lbnRzXG4gICAgICAgICAgICB0aGlzLl9kZXN0cm95VmlkZW9FbGVtZW50KCk7XG4gICAgICAgICAgICB0aGlzLl9kZXN0cm95SW1hZ2VFbGVtZW50KCk7XG4gICAgICAgICAgICB0aGlzLl9kZXN0cm95Q2FwdHVyZUNhbnZhcygpO1xuICAgICAgICB9XG4gICAgICAgIF9kZXN0cm95VmlkZW9FbGVtZW50KCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnZpZGVvRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGZpcnN0IGdpdmVzIGZyZWVkb24gdG8gdGhlIGVsZW1lbnQg8J+VilxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLnZpZGVvRW5kZWRMaXN0ZW5lciAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdlbmRlZCcsIHRoaXMudmlkZW9FbmRlZExpc3RlbmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy52aWRlb1BsYXlpbmdFdmVudExpc3RlbmVyICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9FbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3BsYXlpbmcnLCB0aGlzLnZpZGVvUGxheWluZ0V2ZW50TGlzdGVuZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLnZpZGVvQ2FuUGxheUxpc3RlbmVyICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9FbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2xvYWRlZG1ldGFkYXRhJywgdGhpcy52aWRlb0NhblBsYXlMaXN0ZW5lcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyB0aGVuIGZvcmdldHMgYWJvdXQgdGhhdCBlbGVtZW50IPCfmKJcbiAgICAgICAgICAgIHRoaXMuY2xlYW5WaWRlb1NvdXJjZSh0aGlzLnZpZGVvRWxlbWVudCk7XG4gICAgICAgICAgICB0aGlzLnZpZGVvRWxlbWVudCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBfZGVzdHJveUltYWdlRWxlbWVudCgpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5pbWFnZUVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBmaXJzdCBnaXZlcyBmcmVlZG9uIHRvIHRoZSBlbGVtZW50IPCflYpcbiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgIT09IHRoaXMuaW1hZ2VMb2FkZWRMaXN0ZW5lcikge1xuICAgICAgICAgICAgICAgIHRoaXMuaW1hZ2VFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2xvYWQnLCB0aGlzLmltYWdlTG9hZGVkTGlzdGVuZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gdGhlbiBmb3JnZXQgYWJvdXQgdGhhdCBlbGVtZW50IPCfmKJcbiAgICAgICAgICAgIHRoaXMuaW1hZ2VFbGVtZW50LnNyYyA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRoaXMuaW1hZ2VFbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgnc3JjJyk7XG4gICAgICAgICAgICB0aGlzLmltYWdlRWxlbWVudCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ2xlYW5zIGNhbnZhcyByZWZlcmVuY2VzIPCfloxcbiAgICAgICAgICovXG4gICAgICAgIF9kZXN0cm95Q2FwdHVyZUNhbnZhcygpIHtcbiAgICAgICAgICAgIC8vIHRoZW4gZm9yZ2V0IGFib3V0IHRoYXQgZWxlbWVudCDwn5iiXG4gICAgICAgICAgICB0aGlzLmNhcHR1cmVDYW52YXNDb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgdGhpcy5jYXB0dXJlQ2FudmFzID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWZpbmVzIHdoYXQgdGhlIHZpZGVvRWxlbWVudCBzcmMgd2lsbCBiZS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHZpZGVvRWxlbWVudFxuICAgICAgICAgKiBAcGFyYW0gc3RyZWFtXG4gICAgICAgICAqL1xuICAgICAgICBhZGRWaWRlb1NvdXJjZSh2aWRlb0VsZW1lbnQsIHN0cmVhbSkge1xuICAgICAgICAgICAgLy8gT2xkZXIgYnJvd3NlcnMgbWF5IG5vdCBoYXZlIGBzcmNPYmplY3RgXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIC8vIEBub3RlIFRocm93cyBFeGNlcHRpb24gaWYgaW50ZXJydXB0ZWQgYnkgYSBuZXcgbG9hZGVkIHJlcXVlc3RcbiAgICAgICAgICAgICAgICB2aWRlb0VsZW1lbnQuc3JjT2JqZWN0ID0gc3RyZWFtO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIC8vIEBub3RlIEF2b2lkIHVzaW5nIHRoaXMgaW4gbmV3IGJyb3dzZXJzLCBhcyBpdCBpcyBnb2luZyBhd2F5LlxuICAgICAgICAgICAgICAgIHZpZGVvRWxlbWVudC5zcmMgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKHN0cmVhbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFVuYmluZHMgYSBIVE1MIHZpZGVvIHNyYyBwcm9wZXJ0eS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHZpZGVvRWxlbWVudFxuICAgICAgICAgKi9cbiAgICAgICAgY2xlYW5WaWRlb1NvdXJjZSh2aWRlb0VsZW1lbnQpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmlkZW9FbGVtZW50LnNyY09iamVjdCA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgdmlkZW9FbGVtZW50LnNyYyA9ICcnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy52aWRlb0VsZW1lbnQucmVtb3ZlQXR0cmlidXRlKCdzcmMnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogPHA+RW5jYXBzdWxhdGVzIHRoZSByZXN1bHQgb2YgZGVjb2RpbmcgYSBiYXJjb2RlIHdpdGhpbiBhbiBpbWFnZS48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIFJlc3VsdCB7XG4gICAgICAgIC8vIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIHRleHQ6IHN0cmluZyxcbiAgICAgICAgLy8gICAgICAgICAgICAgICBVaW50OEFycmF5IHJhd0J5dGVzLFxuICAgICAgICAvLyAgICAgICAgICAgICAgIFJlc3VsdFBvY29uc3QgcmVzdWx0UG9pbnRzOiBJbnQzMkFycmF5LFxuICAgICAgICAvLyAgICAgICAgICAgICAgIEJhcmNvZGVGb3JtYXQgZm9ybWF0KSB7XG4gICAgICAgIC8vICAgdGhpcyh0ZXh0LCByYXdCeXRlcywgcmVzdWx0UG9pbnRzLCBmb3JtYXQsIFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpKVxuICAgICAgICAvLyB9XG4gICAgICAgIC8vIHB1YmxpYyBjb25zdHJ1Y3Rvcih0ZXh0OiBzdHJpbmcsXG4gICAgICAgIC8vICAgICAgICAgICAgICAgVWludDhBcnJheSByYXdCeXRlcyxcbiAgICAgICAgLy8gICAgICAgICAgICAgICBSZXN1bHRQb2NvbnN0IHJlc3VsdFBvaW50czogSW50MzJBcnJheSxcbiAgICAgICAgLy8gICAgICAgICAgICAgICBCYXJjb2RlRm9ybWF0IGZvcm1hdCxcbiAgICAgICAgLy8gICAgICAgICAgICAgICBsb25nIHRpbWVzdGFtcCkge1xuICAgICAgICAvLyAgIHRoaXModGV4dCwgcmF3Qnl0ZXMsIHJhd0J5dGVzID09IG51bGwgPyAwIDogOCAqIHJhd0J5dGVzLmxlbmd0aCxcbiAgICAgICAgLy8gICAgICAgIHJlc3VsdFBvaW50cywgZm9ybWF0LCB0aW1lc3RhbXApXG4gICAgICAgIC8vIH1cbiAgICAgICAgY29uc3RydWN0b3IodGV4dCwgcmF3Qnl0ZXMsIG51bUJpdHMgPSByYXdCeXRlcyA9PSBudWxsID8gMCA6IDggKiByYXdCeXRlcy5sZW5ndGgsIHJlc3VsdFBvaW50cywgZm9ybWF0LCB0aW1lc3RhbXAgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKSkge1xuICAgICAgICAgICAgdGhpcy50ZXh0ID0gdGV4dDtcbiAgICAgICAgICAgIHRoaXMucmF3Qnl0ZXMgPSByYXdCeXRlcztcbiAgICAgICAgICAgIHRoaXMubnVtQml0cyA9IG51bUJpdHM7XG4gICAgICAgICAgICB0aGlzLnJlc3VsdFBvaW50cyA9IHJlc3VsdFBvaW50cztcbiAgICAgICAgICAgIHRoaXMuZm9ybWF0ID0gZm9ybWF0O1xuICAgICAgICAgICAgdGhpcy50aW1lc3RhbXAgPSB0aW1lc3RhbXA7XG4gICAgICAgICAgICB0aGlzLnRleHQgPSB0ZXh0O1xuICAgICAgICAgICAgdGhpcy5yYXdCeXRlcyA9IHJhd0J5dGVzO1xuICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCA9PT0gbnVtQml0cyB8fCBudWxsID09PSBudW1CaXRzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5udW1CaXRzID0gKHJhd0J5dGVzID09PSBudWxsIHx8IHJhd0J5dGVzID09PSB1bmRlZmluZWQpID8gMCA6IDggKiByYXdCeXRlcy5sZW5ndGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm51bUJpdHMgPSBudW1CaXRzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yZXN1bHRQb2ludHMgPSByZXN1bHRQb2ludHM7XG4gICAgICAgICAgICB0aGlzLmZvcm1hdCA9IGZvcm1hdDtcbiAgICAgICAgICAgIHRoaXMucmVzdWx0TWV0YWRhdGEgPSBudWxsO1xuICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCA9PT0gdGltZXN0YW1wIHx8IG51bGwgPT09IHRpbWVzdGFtcCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGltZXN0YW1wID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRpbWVzdGFtcCA9IHRpbWVzdGFtcDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiByYXcgdGV4dCBlbmNvZGVkIGJ5IHRoZSBiYXJjb2RlXG4gICAgICAgICAqL1xuICAgICAgICBnZXRUZXh0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudGV4dDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiByYXcgYnl0ZXMgZW5jb2RlZCBieSB0aGUgYmFyY29kZSwgaWYgYXBwbGljYWJsZSwgb3RoZXJ3aXNlIHtAY29kZSBudWxsfVxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0UmF3Qnl0ZXMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yYXdCeXRlcztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBob3cgbWFueSBiaXRzIG9mIHtAbGluayAjZ2V0UmF3Qnl0ZXMoKX0gYXJlIHZhbGlkOyB0eXBpY2FsbHkgOCB0aW1lcyBpdHMgbGVuZ3RoXG4gICAgICAgICAqIEBzaW5jZSAzLjMuMFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0TnVtQml0cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm51bUJpdHM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gcG9pbnRzIHJlbGF0ZWQgdG8gdGhlIGJhcmNvZGUgaW4gdGhlIGltYWdlLiBUaGVzZSBhcmUgdHlwaWNhbGx5IHBvaW50c1xuICAgICAgICAgKiAgICAgICAgIGlkZW50aWZ5aW5nIGZpbmRlciBwYXR0ZXJucyBvciB0aGUgY29ybmVycyBvZiB0aGUgYmFyY29kZS4gVGhlIGV4YWN0IG1lYW5pbmcgaXNcbiAgICAgICAgICogICAgICAgICBzcGVjaWZpYyB0byB0aGUgdHlwZSBvZiBiYXJjb2RlIHRoYXQgd2FzIGRlY29kZWQuXG4gICAgICAgICAqL1xuICAgICAgICBnZXRSZXN1bHRQb2ludHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZXN1bHRQb2ludHM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4ge0BsaW5rIEJhcmNvZGVGb3JtYXR9IHJlcHJlc2VudGluZyB0aGUgZm9ybWF0IG9mIHRoZSBiYXJjb2RlIHRoYXQgd2FzIGRlY29kZWRcbiAgICAgICAgICovXG4gICAgICAgIGdldEJhcmNvZGVGb3JtYXQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5mb3JtYXQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4ge0BsaW5rIE1hcH0gbWFwcGluZyB7QGxpbmsgUmVzdWx0TWV0YWRhdGFUeXBlfSBrZXlzIHRvIHZhbHVlcy4gTWF5IGJlXG4gICAgICAgICAqICAge0Bjb2RlIG51bGx9LiBUaGlzIGNvbnRhaW5zIG9wdGlvbmFsIG1ldGFkYXRhIGFib3V0IHdoYXQgd2FzIGRldGVjdGVkIGFib3V0IHRoZSBiYXJjb2RlLFxuICAgICAgICAgKiAgIGxpa2Ugb3JpZW50YXRpb24uXG4gICAgICAgICAqL1xuICAgICAgICBnZXRSZXN1bHRNZXRhZGF0YSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlc3VsdE1ldGFkYXRhO1xuICAgICAgICB9XG4gICAgICAgIHB1dE1ldGFkYXRhKHR5cGUsIHZhbHVlKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5yZXN1bHRNZXRhZGF0YSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzdWx0TWV0YWRhdGEgPSBuZXcgTWFwKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnJlc3VsdE1ldGFkYXRhLnNldCh0eXBlLCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcHV0QWxsTWV0YWRhdGEobWV0YWRhdGEpIHtcbiAgICAgICAgICAgIGlmIChtZXRhZGF0YSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlc3VsdE1ldGFkYXRhID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVzdWx0TWV0YWRhdGEgPSBtZXRhZGF0YTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVzdWx0TWV0YWRhdGEgPSBuZXcgTWFwKG1ldGFkYXRhKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYWRkUmVzdWx0UG9pbnRzKG5ld1BvaW50cykge1xuICAgICAgICAgICAgY29uc3Qgb2xkUG9pbnRzID0gdGhpcy5yZXN1bHRQb2ludHM7XG4gICAgICAgICAgICBpZiAob2xkUG9pbnRzID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXN1bHRQb2ludHMgPSBuZXdQb2ludHM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChuZXdQb2ludHMgIT09IG51bGwgJiYgbmV3UG9pbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBhbGxQb2ludHMgPSBuZXcgQXJyYXkob2xkUG9pbnRzLmxlbmd0aCArIG5ld1BvaW50cy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkob2xkUG9pbnRzLCAwLCBhbGxQb2ludHMsIDAsIG9sZFBvaW50cy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkobmV3UG9pbnRzLCAwLCBhbGxQb2ludHMsIG9sZFBvaW50cy5sZW5ndGgsIG5ld1BvaW50cy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVzdWx0UG9pbnRzID0gYWxsUG9pbnRzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGdldFRpbWVzdGFtcCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRpbWVzdGFtcDtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudGV4dDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogRGlyZWN0IHBvcnQgdG8gVHlwZVNjcmlwdCBvZiBaWGluZyBieSBBZHJpYW4gVG/ImWPEg1xuICAgICAqL1xuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDkgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLypuYW1lc3BhY2UgY29tLmdvb2dsZS56eGluZyB7Ki9cbiAgICAvKipcbiAgICAgKiBFbnVtZXJhdGVzIGJhcmNvZGUgZm9ybWF0cyBrbm93biB0byB0aGlzIHBhY2thZ2UuIFBsZWFzZSBrZWVwIGFscGhhYmV0aXplZC5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgdmFyIEJhcmNvZGVGb3JtYXQ7XG4gICAgKGZ1bmN0aW9uIChCYXJjb2RlRm9ybWF0KSB7XG4gICAgICAgIC8qKiBBenRlYyAyRCBiYXJjb2RlIGZvcm1hdC4gKi9cbiAgICAgICAgQmFyY29kZUZvcm1hdFtCYXJjb2RlRm9ybWF0W1wiQVpURUNcIl0gPSAwXSA9IFwiQVpURUNcIjtcbiAgICAgICAgLyoqIENPREFCQVIgMUQgZm9ybWF0LiAqL1xuICAgICAgICBCYXJjb2RlRm9ybWF0W0JhcmNvZGVGb3JtYXRbXCJDT0RBQkFSXCJdID0gMV0gPSBcIkNPREFCQVJcIjtcbiAgICAgICAgLyoqIENvZGUgMzkgMUQgZm9ybWF0LiAqL1xuICAgICAgICBCYXJjb2RlRm9ybWF0W0JhcmNvZGVGb3JtYXRbXCJDT0RFXzM5XCJdID0gMl0gPSBcIkNPREVfMzlcIjtcbiAgICAgICAgLyoqIENvZGUgOTMgMUQgZm9ybWF0LiAqL1xuICAgICAgICBCYXJjb2RlRm9ybWF0W0JhcmNvZGVGb3JtYXRbXCJDT0RFXzkzXCJdID0gM10gPSBcIkNPREVfOTNcIjtcbiAgICAgICAgLyoqIENvZGUgMTI4IDFEIGZvcm1hdC4gKi9cbiAgICAgICAgQmFyY29kZUZvcm1hdFtCYXJjb2RlRm9ybWF0W1wiQ09ERV8xMjhcIl0gPSA0XSA9IFwiQ09ERV8xMjhcIjtcbiAgICAgICAgLyoqIERhdGEgTWF0cml4IDJEIGJhcmNvZGUgZm9ybWF0LiAqL1xuICAgICAgICBCYXJjb2RlRm9ybWF0W0JhcmNvZGVGb3JtYXRbXCJEQVRBX01BVFJJWFwiXSA9IDVdID0gXCJEQVRBX01BVFJJWFwiO1xuICAgICAgICAvKiogRUFOLTggMUQgZm9ybWF0LiAqL1xuICAgICAgICBCYXJjb2RlRm9ybWF0W0JhcmNvZGVGb3JtYXRbXCJFQU5fOFwiXSA9IDZdID0gXCJFQU5fOFwiO1xuICAgICAgICAvKiogRUFOLTEzIDFEIGZvcm1hdC4gKi9cbiAgICAgICAgQmFyY29kZUZvcm1hdFtCYXJjb2RlRm9ybWF0W1wiRUFOXzEzXCJdID0gN10gPSBcIkVBTl8xM1wiO1xuICAgICAgICAvKiogSVRGIChJbnRlcmxlYXZlZCBUd28gb2YgRml2ZSkgMUQgZm9ybWF0LiAqL1xuICAgICAgICBCYXJjb2RlRm9ybWF0W0JhcmNvZGVGb3JtYXRbXCJJVEZcIl0gPSA4XSA9IFwiSVRGXCI7XG4gICAgICAgIC8qKiBNYXhpQ29kZSAyRCBiYXJjb2RlIGZvcm1hdC4gKi9cbiAgICAgICAgQmFyY29kZUZvcm1hdFtCYXJjb2RlRm9ybWF0W1wiTUFYSUNPREVcIl0gPSA5XSA9IFwiTUFYSUNPREVcIjtcbiAgICAgICAgLyoqIFBERjQxNyBmb3JtYXQuICovXG4gICAgICAgIEJhcmNvZGVGb3JtYXRbQmFyY29kZUZvcm1hdFtcIlBERl80MTdcIl0gPSAxMF0gPSBcIlBERl80MTdcIjtcbiAgICAgICAgLyoqIFFSIENvZGUgMkQgYmFyY29kZSBmb3JtYXQuICovXG4gICAgICAgIEJhcmNvZGVGb3JtYXRbQmFyY29kZUZvcm1hdFtcIlFSX0NPREVcIl0gPSAxMV0gPSBcIlFSX0NPREVcIjtcbiAgICAgICAgLyoqIFJTUyAxNCAqL1xuICAgICAgICBCYXJjb2RlRm9ybWF0W0JhcmNvZGVGb3JtYXRbXCJSU1NfMTRcIl0gPSAxMl0gPSBcIlJTU18xNFwiO1xuICAgICAgICAvKiogUlNTIEVYUEFOREVEICovXG4gICAgICAgIEJhcmNvZGVGb3JtYXRbQmFyY29kZUZvcm1hdFtcIlJTU19FWFBBTkRFRFwiXSA9IDEzXSA9IFwiUlNTX0VYUEFOREVEXCI7XG4gICAgICAgIC8qKiBVUEMtQSAxRCBmb3JtYXQuICovXG4gICAgICAgIEJhcmNvZGVGb3JtYXRbQmFyY29kZUZvcm1hdFtcIlVQQ19BXCJdID0gMTRdID0gXCJVUENfQVwiO1xuICAgICAgICAvKiogVVBDLUUgMUQgZm9ybWF0LiAqL1xuICAgICAgICBCYXJjb2RlRm9ybWF0W0JhcmNvZGVGb3JtYXRbXCJVUENfRVwiXSA9IDE1XSA9IFwiVVBDX0VcIjtcbiAgICAgICAgLyoqIFVQQy9FQU4gZXh0ZW5zaW9uIGZvcm1hdC4gTm90IGEgc3RhbmQtYWxvbmUgZm9ybWF0LiAqL1xuICAgICAgICBCYXJjb2RlRm9ybWF0W0JhcmNvZGVGb3JtYXRbXCJVUENfRUFOX0VYVEVOU0lPTlwiXSA9IDE2XSA9IFwiVVBDX0VBTl9FWFRFTlNJT05cIjtcbiAgICB9KShCYXJjb2RlRm9ybWF0IHx8IChCYXJjb2RlRm9ybWF0ID0ge30pKTtcbiAgICB2YXIgQmFyY29kZUZvcm1hdCQxID0gQmFyY29kZUZvcm1hdDtcblxuICAgIC8qbmFtZXNwYWNlIGNvbS5nb29nbGUuenhpbmcgeyovXG4gICAgLyoqXG4gICAgICogUmVwcmVzZW50cyBzb21lIHR5cGUgb2YgbWV0YWRhdGEgYWJvdXQgdGhlIHJlc3VsdCBvZiB0aGUgZGVjb2RpbmcgdGhhdCB0aGUgZGVjb2RlclxuICAgICAqIHdpc2hlcyB0byBjb21tdW5pY2F0ZSBiYWNrIHRvIHRoZSBjYWxsZXIuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIHZhciBSZXN1bHRNZXRhZGF0YVR5cGU7XG4gICAgKGZ1bmN0aW9uIChSZXN1bHRNZXRhZGF0YVR5cGUpIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFVuc3BlY2lmaWVkLCBhcHBsaWNhdGlvbi1zcGVjaWZpYyBtZXRhZGF0YS4gTWFwcyB0byBhbiB1bnNwZWNpZmllZCB7QGxpbmsgT2JqZWN0fS5cbiAgICAgICAgICovXG4gICAgICAgIFJlc3VsdE1ldGFkYXRhVHlwZVtSZXN1bHRNZXRhZGF0YVR5cGVbXCJPVEhFUlwiXSA9IDBdID0gXCJPVEhFUlwiO1xuICAgICAgICAvKipcbiAgICAgICAgICogRGVub3RlcyB0aGUgbGlrZWx5IGFwcHJveGltYXRlIG9yaWVudGF0aW9uIG9mIHRoZSBiYXJjb2RlIGluIHRoZSBpbWFnZS4gVGhpcyB2YWx1ZVxuICAgICAgICAgKiBpcyBnaXZlbiBhcyBkZWdyZWVzIHJvdGF0ZWQgY2xvY2t3aXNlIGZyb20gdGhlIG5vcm1hbCwgdXByaWdodCBvcmllbnRhdGlvbi5cbiAgICAgICAgICogRm9yIGV4YW1wbGUgYSAxRCBiYXJjb2RlIHdoaWNoIHdhcyBmb3VuZCBieSByZWFkaW5nIHRvcC10by1ib3R0b20gd291bGQgYmVcbiAgICAgICAgICogc2FpZCB0byBoYXZlIG9yaWVudGF0aW9uIFwiOTBcIi4gVGhpcyBrZXkgbWFwcyB0byBhbiB7QGxpbmsgSW50ZWdlcn0gd2hvc2VcbiAgICAgICAgICogdmFsdWUgaXMgaW4gdGhlIHJhbmdlIFswLDM2MCkuXG4gICAgICAgICAqL1xuICAgICAgICBSZXN1bHRNZXRhZGF0YVR5cGVbUmVzdWx0TWV0YWRhdGFUeXBlW1wiT1JJRU5UQVRJT05cIl0gPSAxXSA9IFwiT1JJRU5UQVRJT05cIjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPjJEIGJhcmNvZGUgZm9ybWF0cyB0eXBpY2FsbHkgZW5jb2RlIHRleHQsIGJ1dCBhbGxvdyBmb3IgYSBzb3J0IG9mICdieXRlIG1vZGUnXG4gICAgICAgICAqIHdoaWNoIGlzIHNvbWV0aW1lcyB1c2VkIHRvIGVuY29kZSBiaW5hcnkgZGF0YS4gV2hpbGUge0BsaW5rIFJlc3VsdH0gbWFrZXMgYXZhaWxhYmxlXG4gICAgICAgICAqIHRoZSBjb21wbGV0ZSByYXcgYnl0ZXMgaW4gdGhlIGJhcmNvZGUgZm9yIHRoZXNlIGZvcm1hdHMsIGl0IGRvZXMgbm90IG9mZmVyIHRoZSBieXRlc1xuICAgICAgICAgKiBmcm9tIHRoZSBieXRlIHNlZ21lbnRzIGFsb25lLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogPHA+VGhpcyBtYXBzIHRvIGEge0BsaW5rIGphdmEudXRpbC5MaXN0fSBvZiBieXRlIGFycmF5cyBjb3JyZXNwb25kaW5nIHRvIHRoZVxuICAgICAgICAgKiByYXcgYnl0ZXMgaW4gdGhlIGJ5dGUgc2VnbWVudHMgaW4gdGhlIGJhcmNvZGUsIGluIG9yZGVyLjwvcD5cbiAgICAgICAgICovXG4gICAgICAgIFJlc3VsdE1ldGFkYXRhVHlwZVtSZXN1bHRNZXRhZGF0YVR5cGVbXCJCWVRFX1NFR01FTlRTXCJdID0gMl0gPSBcIkJZVEVfU0VHTUVOVFNcIjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVycm9yIGNvcnJlY3Rpb24gbGV2ZWwgdXNlZCwgaWYgYXBwbGljYWJsZS4gVGhlIHZhbHVlIHR5cGUgZGVwZW5kcyBvbiB0aGVcbiAgICAgICAgICogZm9ybWF0LCBidXQgaXMgdHlwaWNhbGx5IGEgU3RyaW5nLlxuICAgICAgICAgKi9cbiAgICAgICAgUmVzdWx0TWV0YWRhdGFUeXBlW1Jlc3VsdE1ldGFkYXRhVHlwZVtcIkVSUk9SX0NPUlJFQ1RJT05fTEVWRUxcIl0gPSAzXSA9IFwiRVJST1JfQ09SUkVDVElPTl9MRVZFTFwiO1xuICAgICAgICAvKipcbiAgICAgICAgICogRm9yIHNvbWUgcGVyaW9kaWNhbHMsIGluZGljYXRlcyB0aGUgaXNzdWUgbnVtYmVyIGFzIGFuIHtAbGluayBJbnRlZ2VyfS5cbiAgICAgICAgICovXG4gICAgICAgIFJlc3VsdE1ldGFkYXRhVHlwZVtSZXN1bHRNZXRhZGF0YVR5cGVbXCJJU1NVRV9OVU1CRVJcIl0gPSA0XSA9IFwiSVNTVUVfTlVNQkVSXCI7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBGb3Igc29tZSBwcm9kdWN0cywgaW5kaWNhdGVzIHRoZSBzdWdnZXN0ZWQgcmV0YWlsIHByaWNlIGluIHRoZSBiYXJjb2RlIGFzIGFcbiAgICAgICAgICogZm9ybWF0dGVkIHtAbGluayBTdHJpbmd9LlxuICAgICAgICAgKi9cbiAgICAgICAgUmVzdWx0TWV0YWRhdGFUeXBlW1Jlc3VsdE1ldGFkYXRhVHlwZVtcIlNVR0dFU1RFRF9QUklDRVwiXSA9IDVdID0gXCJTVUdHRVNURURfUFJJQ0VcIjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEZvciBzb21lIHByb2R1Y3RzLCB0aGUgcG9zc2libGUgY291bnRyeSBvZiBtYW51ZmFjdHVyZSBhcyBhIHtAbGluayBTdHJpbmd9IGRlbm90aW5nIHRoZVxuICAgICAgICAgKiBJU08gY291bnRyeSBjb2RlLiBTb21lIG1hcCB0byBtdWx0aXBsZSBwb3NzaWJsZSBjb3VudHJpZXMsIGxpa2UgXCJVUy9DQVwiLlxuICAgICAgICAgKi9cbiAgICAgICAgUmVzdWx0TWV0YWRhdGFUeXBlW1Jlc3VsdE1ldGFkYXRhVHlwZVtcIlBPU1NJQkxFX0NPVU5UUllcIl0gPSA2XSA9IFwiUE9TU0lCTEVfQ09VTlRSWVwiO1xuICAgICAgICAvKipcbiAgICAgICAgICogRm9yIHNvbWUgcHJvZHVjdHMsIHRoZSBleHRlbnNpb24gdGV4dFxuICAgICAgICAgKi9cbiAgICAgICAgUmVzdWx0TWV0YWRhdGFUeXBlW1Jlc3VsdE1ldGFkYXRhVHlwZVtcIlVQQ19FQU5fRVhURU5TSU9OXCJdID0gN10gPSBcIlVQQ19FQU5fRVhURU5TSU9OXCI7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQREY0MTctc3BlY2lmaWMgbWV0YWRhdGFcbiAgICAgICAgICovXG4gICAgICAgIFJlc3VsdE1ldGFkYXRhVHlwZVtSZXN1bHRNZXRhZGF0YVR5cGVbXCJQREY0MTdfRVhUUkFfTUVUQURBVEFcIl0gPSA4XSA9IFwiUERGNDE3X0VYVFJBX01FVEFEQVRBXCI7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJZiB0aGUgY29kZSBmb3JtYXQgc3VwcG9ydHMgc3RydWN0dXJlZCBhcHBlbmQgYW5kIHRoZSBjdXJyZW50IHNjYW5uZWQgY29kZSBpcyBwYXJ0IG9mIG9uZSB0aGVuIHRoZVxuICAgICAgICAgKiBzZXF1ZW5jZSBudW1iZXIgaXMgZ2l2ZW4gd2l0aCBpdC5cbiAgICAgICAgICovXG4gICAgICAgIFJlc3VsdE1ldGFkYXRhVHlwZVtSZXN1bHRNZXRhZGF0YVR5cGVbXCJTVFJVQ1RVUkVEX0FQUEVORF9TRVFVRU5DRVwiXSA9IDldID0gXCJTVFJVQ1RVUkVEX0FQUEVORF9TRVFVRU5DRVwiO1xuICAgICAgICAvKipcbiAgICAgICAgICogSWYgdGhlIGNvZGUgZm9ybWF0IHN1cHBvcnRzIHN0cnVjdHVyZWQgYXBwZW5kIGFuZCB0aGUgY3VycmVudCBzY2FubmVkIGNvZGUgaXMgcGFydCBvZiBvbmUgdGhlbiB0aGVcbiAgICAgICAgICogcGFyaXR5IGlzIGdpdmVuIHdpdGggaXQuXG4gICAgICAgICAqL1xuICAgICAgICBSZXN1bHRNZXRhZGF0YVR5cGVbUmVzdWx0TWV0YWRhdGFUeXBlW1wiU1RSVUNUVVJFRF9BUFBFTkRfUEFSSVRZXCJdID0gMTBdID0gXCJTVFJVQ1RVUkVEX0FQUEVORF9QQVJJVFlcIjtcbiAgICB9KShSZXN1bHRNZXRhZGF0YVR5cGUgfHwgKFJlc3VsdE1ldGFkYXRhVHlwZSA9IHt9KSk7XG4gICAgdmFyIFJlc3VsdE1ldGFkYXRhVHlwZSQxID0gUmVzdWx0TWV0YWRhdGFUeXBlO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKm5hbWVzcGFjZSBjb20uZ29vZ2xlLnp4aW5nLmNvbW1vbiB7Ki9cbiAgICAvKmltcG9ydCBqYXZhLnV0aWwuTGlzdDsqL1xuICAgIC8qKlxuICAgICAqIDxwPkVuY2Fwc3VsYXRlcyB0aGUgcmVzdWx0IG9mIGRlY29kaW5nIGEgbWF0cml4IG9mIGJpdHMuIFRoaXMgdHlwaWNhbGx5XG4gICAgICogYXBwbGllcyB0byAyRCBiYXJjb2RlIGZvcm1hdHMuIEZvciBub3cgaXQgY29udGFpbnMgdGhlIHJhdyBieXRlcyBvYnRhaW5lZCxcbiAgICAgKiBhcyB3ZWxsIGFzIGEgU3RyaW5nIGludGVycHJldGF0aW9uIG9mIHRob3NlIGJ5dGVzLCBpZiBhcHBsaWNhYmxlLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgRGVjb2RlclJlc3VsdCB7XG4gICAgICAgIC8vIHB1YmxpYyBjb25zdHJ1Y3RvcihyYXdCeXRlczogVWludDhBcnJheSxcbiAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgdGV4dDogc3RyaW5nLFxuICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgICBMaXN0PFVpbnQ4QXJyYXk+IGJ5dGVTZWdtZW50cyxcbiAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgU3RyaW5nIGVjTGV2ZWwpIHtcbiAgICAgICAgLy8gICB0aGlzKHJhd0J5dGVzLCB0ZXh0LCBieXRlU2VnbWVudHMsIGVjTGV2ZWwsIC0xLCAtMSlcbiAgICAgICAgLy8gfVxuICAgICAgICBjb25zdHJ1Y3RvcihyYXdCeXRlcywgdGV4dCwgYnl0ZVNlZ21lbnRzLCBlY0xldmVsLCBzdHJ1Y3R1cmVkQXBwZW5kU2VxdWVuY2VOdW1iZXIgPSAtMSwgc3RydWN0dXJlZEFwcGVuZFBhcml0eSA9IC0xKSB7XG4gICAgICAgICAgICB0aGlzLnJhd0J5dGVzID0gcmF3Qnl0ZXM7XG4gICAgICAgICAgICB0aGlzLnRleHQgPSB0ZXh0O1xuICAgICAgICAgICAgdGhpcy5ieXRlU2VnbWVudHMgPSBieXRlU2VnbWVudHM7XG4gICAgICAgICAgICB0aGlzLmVjTGV2ZWwgPSBlY0xldmVsO1xuICAgICAgICAgICAgdGhpcy5zdHJ1Y3R1cmVkQXBwZW5kU2VxdWVuY2VOdW1iZXIgPSBzdHJ1Y3R1cmVkQXBwZW5kU2VxdWVuY2VOdW1iZXI7XG4gICAgICAgICAgICB0aGlzLnN0cnVjdHVyZWRBcHBlbmRQYXJpdHkgPSBzdHJ1Y3R1cmVkQXBwZW5kUGFyaXR5O1xuICAgICAgICAgICAgdGhpcy5udW1CaXRzID0gKHJhd0J5dGVzID09PSB1bmRlZmluZWQgfHwgcmF3Qnl0ZXMgPT09IG51bGwpID8gMCA6IDggKiByYXdCeXRlcy5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gcmF3IGJ5dGVzIHJlcHJlc2VudGluZyB0aGUgcmVzdWx0LCBvciB7QGNvZGUgbnVsbH0gaWYgbm90IGFwcGxpY2FibGVcbiAgICAgICAgICovXG4gICAgICAgIGdldFJhd0J5dGVzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucmF3Qnl0ZXM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gaG93IG1hbnkgYml0cyBvZiB7QGxpbmsgI2dldFJhd0J5dGVzKCl9IGFyZSB2YWxpZDsgdHlwaWNhbGx5IDggdGltZXMgaXRzIGxlbmd0aFxuICAgICAgICAgKiBAc2luY2UgMy4zLjBcbiAgICAgICAgICovXG4gICAgICAgIGdldE51bUJpdHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5udW1CaXRzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gbnVtQml0cyBvdmVycmlkZXMgdGhlIG51bWJlciBvZiBiaXRzIHRoYXQgYXJlIHZhbGlkIGluIHtAbGluayAjZ2V0UmF3Qnl0ZXMoKX1cbiAgICAgICAgICogQHNpbmNlIDMuMy4wXG4gICAgICAgICAqL1xuICAgICAgICBzZXROdW1CaXRzKG51bUJpdHMgLyppbnQqLykge1xuICAgICAgICAgICAgdGhpcy5udW1CaXRzID0gbnVtQml0cztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB0ZXh0IHJlcHJlc2VudGF0aW9uIG9mIHRoZSByZXN1bHRcbiAgICAgICAgICovXG4gICAgICAgIGdldFRleHQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50ZXh0O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIGxpc3Qgb2YgYnl0ZSBzZWdtZW50cyBpbiB0aGUgcmVzdWx0LCBvciB7QGNvZGUgbnVsbH0gaWYgbm90IGFwcGxpY2FibGVcbiAgICAgICAgICovXG4gICAgICAgIGdldEJ5dGVTZWdtZW50cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJ5dGVTZWdtZW50cztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBuYW1lIG9mIGVycm9yIGNvcnJlY3Rpb24gbGV2ZWwgdXNlZCwgb3Ige0Bjb2RlIG51bGx9IGlmIG5vdCBhcHBsaWNhYmxlXG4gICAgICAgICAqL1xuICAgICAgICBnZXRFQ0xldmVsKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWNMZXZlbDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBudW1iZXIgb2YgZXJyb3JzIGNvcnJlY3RlZCwgb3Ige0Bjb2RlIG51bGx9IGlmIG5vdCBhcHBsaWNhYmxlXG4gICAgICAgICAqL1xuICAgICAgICBnZXRFcnJvcnNDb3JyZWN0ZWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lcnJvcnNDb3JyZWN0ZWQ7XG4gICAgICAgIH1cbiAgICAgICAgc2V0RXJyb3JzQ29ycmVjdGVkKGVycm9yc0NvcnJlY3RlZCAvKkludGVnZXIqLykge1xuICAgICAgICAgICAgdGhpcy5lcnJvcnNDb3JyZWN0ZWQgPSBlcnJvcnNDb3JyZWN0ZWQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gbnVtYmVyIG9mIGVyYXN1cmVzIGNvcnJlY3RlZCwgb3Ige0Bjb2RlIG51bGx9IGlmIG5vdCBhcHBsaWNhYmxlXG4gICAgICAgICAqL1xuICAgICAgICBnZXRFcmFzdXJlcygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVyYXN1cmVzO1xuICAgICAgICB9XG4gICAgICAgIHNldEVyYXN1cmVzKGVyYXN1cmVzIC8qSW50ZWdlciovKSB7XG4gICAgICAgICAgICB0aGlzLmVyYXN1cmVzID0gZXJhc3VyZXM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gYXJiaXRyYXJ5IGFkZGl0aW9uYWwgbWV0YWRhdGFcbiAgICAgICAgICovXG4gICAgICAgIGdldE90aGVyKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMub3RoZXI7XG4gICAgICAgIH1cbiAgICAgICAgc2V0T3RoZXIob3RoZXIpIHtcbiAgICAgICAgICAgIHRoaXMub3RoZXIgPSBvdGhlcjtcbiAgICAgICAgfVxuICAgICAgICBoYXNTdHJ1Y3R1cmVkQXBwZW5kKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RydWN0dXJlZEFwcGVuZFBhcml0eSA+PSAwICYmIHRoaXMuc3RydWN0dXJlZEFwcGVuZFNlcXVlbmNlTnVtYmVyID49IDA7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0U3RydWN0dXJlZEFwcGVuZFBhcml0eSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0cnVjdHVyZWRBcHBlbmRQYXJpdHk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0U3RydWN0dXJlZEFwcGVuZFNlcXVlbmNlTnVtYmVyKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RydWN0dXJlZEFwcGVuZFNlcXVlbmNlTnVtYmVyO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiA8cD5UaGlzIGNsYXNzIGNvbnRhaW5zIHV0aWxpdHkgbWV0aG9kcyBmb3IgcGVyZm9ybWluZyBtYXRoZW1hdGljYWwgb3BlcmF0aW9ucyBvdmVyXG4gICAgICogdGhlIEdhbG9pcyBGaWVsZHMuIE9wZXJhdGlvbnMgdXNlIGEgZ2l2ZW4gcHJpbWl0aXZlIHBvbHlub21pYWwgaW4gY2FsY3VsYXRpb25zLjwvcD5cbiAgICAgKlxuICAgICAqIDxwPlRocm91Z2hvdXQgdGhpcyBwYWNrYWdlLCBlbGVtZW50cyBvZiB0aGUgR0YgYXJlIHJlcHJlc2VudGVkIGFzIGFuIHtAY29kZSBpbnR9XG4gICAgICogZm9yIGNvbnZlbmllbmNlIGFuZCBzcGVlZCAoYnV0IGF0IHRoZSBjb3N0IG9mIG1lbW9yeSkuXG4gICAgICogPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKiBAYXV0aG9yIERhdmlkIE9saXZpZXJcbiAgICAgKi9cbiAgICBjbGFzcyBBYnN0cmFjdEdlbmVyaWNHRiB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIDIgdG8gdGhlIHBvd2VyIG9mIGEgaW4gR0Yoc2l6ZSlcbiAgICAgICAgICovXG4gICAgICAgIGV4cChhKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5leHBUYWJsZVthXTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBiYXNlIDIgbG9nIG9mIGEgaW4gR0Yoc2l6ZSlcbiAgICAgICAgICovXG4gICAgICAgIGxvZyhhIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGlmIChhID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubG9nVGFibGVbYV07XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEltcGxlbWVudHMgYm90aCBhZGRpdGlvbiBhbmQgc3VidHJhY3Rpb24gLS0gdGhleSBhcmUgdGhlIHNhbWUgaW4gR0Yoc2l6ZSkuXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gc3VtL2RpZmZlcmVuY2Ugb2YgYSBhbmQgYlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGFkZE9yU3VidHJhY3QoYSAvKmludCovLCBiIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHJldHVybiBhIF4gYjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogPHA+UmVwcmVzZW50cyBhIHBvbHlub21pYWwgd2hvc2UgY29lZmZpY2llbnRzIGFyZSBlbGVtZW50cyBvZiBhIEdGLlxuICAgICAqIEluc3RhbmNlcyBvZiB0aGlzIGNsYXNzIGFyZSBpbW11dGFibGUuPC9wPlxuICAgICAqXG4gICAgICogPHA+TXVjaCBjcmVkaXQgaXMgZHVlIHRvIFdpbGxpYW0gUnVja2xpZGdlIHNpbmNlIHBvcnRpb25zIG9mIHRoaXMgY29kZSBhcmUgYW4gaW5kaXJlY3RcbiAgICAgKiBwb3J0IG9mIGhpcyBDKysgUmVlZC1Tb2xvbW9uIGltcGxlbWVudGF0aW9uLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgR2VuZXJpY0dGUG9seSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gZmllbGQgdGhlIHtAbGluayBHZW5lcmljR0Z9IGluc3RhbmNlIHJlcHJlc2VudGluZyB0aGUgZmllbGQgdG8gdXNlXG4gICAgICAgICAqIHRvIHBlcmZvcm0gY29tcHV0YXRpb25zXG4gICAgICAgICAqIEBwYXJhbSBjb2VmZmljaWVudHMgY29lZmZpY2llbnRzIGFzIGludHMgcmVwcmVzZW50aW5nIGVsZW1lbnRzIG9mIEdGKHNpemUpLCBhcnJhbmdlZFxuICAgICAgICAgKiBmcm9tIG1vc3Qgc2lnbmlmaWNhbnQgKGhpZ2hlc3QtcG93ZXIgdGVybSkgY29lZmZpY2llbnQgdG8gbGVhc3Qgc2lnbmlmaWNhbnRcbiAgICAgICAgICogQHRocm93cyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24gaWYgYXJndW1lbnQgaXMgbnVsbCBvciBlbXB0eSxcbiAgICAgICAgICogb3IgaWYgbGVhZGluZyBjb2VmZmljaWVudCBpcyAwIGFuZCB0aGlzIGlzIG5vdCBhXG4gICAgICAgICAqIGNvbnN0YW50IHBvbHlub21pYWwgKHRoYXQgaXMsIGl0IGlzIG5vdCB0aGUgbW9ub21pYWwgXCIwXCIpXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3RvcihmaWVsZCwgY29lZmZpY2llbnRzKSB7XG4gICAgICAgICAgICBpZiAoY29lZmZpY2llbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZmllbGQgPSBmaWVsZDtcbiAgICAgICAgICAgIGNvbnN0IGNvZWZmaWNpZW50c0xlbmd0aCA9IGNvZWZmaWNpZW50cy5sZW5ndGg7XG4gICAgICAgICAgICBpZiAoY29lZmZpY2llbnRzTGVuZ3RoID4gMSAmJiBjb2VmZmljaWVudHNbMF0gPT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyBMZWFkaW5nIHRlcm0gbXVzdCBiZSBub24temVybyBmb3IgYW55dGhpbmcgZXhjZXB0IHRoZSBjb25zdGFudCBwb2x5bm9taWFsIFwiMFwiXG4gICAgICAgICAgICAgICAgbGV0IGZpcnN0Tm9uWmVybyA9IDE7XG4gICAgICAgICAgICAgICAgd2hpbGUgKGZpcnN0Tm9uWmVybyA8IGNvZWZmaWNpZW50c0xlbmd0aCAmJiBjb2VmZmljaWVudHNbZmlyc3ROb25aZXJvXSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBmaXJzdE5vblplcm8rKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGZpcnN0Tm9uWmVybyA9PT0gY29lZmZpY2llbnRzTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29lZmZpY2llbnRzID0gSW50MzJBcnJheS5mcm9tKFswXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvZWZmaWNpZW50cyA9IG5ldyBJbnQzMkFycmF5KGNvZWZmaWNpZW50c0xlbmd0aCAtIGZpcnN0Tm9uWmVybyk7XG4gICAgICAgICAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkoY29lZmZpY2llbnRzLCBmaXJzdE5vblplcm8sIHRoaXMuY29lZmZpY2llbnRzLCAwLCB0aGlzLmNvZWZmaWNpZW50cy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuY29lZmZpY2llbnRzID0gY29lZmZpY2llbnRzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGdldENvZWZmaWNpZW50cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvZWZmaWNpZW50cztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBkZWdyZWUgb2YgdGhpcyBwb2x5bm9taWFsXG4gICAgICAgICAqL1xuICAgICAgICBnZXREZWdyZWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2VmZmljaWVudHMubGVuZ3RoIC0gMTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB0cnVlIGlmZiB0aGlzIHBvbHlub21pYWwgaXMgdGhlIG1vbm9taWFsIFwiMFwiXG4gICAgICAgICAqL1xuICAgICAgICBpc1plcm8oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2VmZmljaWVudHNbMF0gPT09IDA7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gY29lZmZpY2llbnQgb2YgeF5kZWdyZWUgdGVybSBpbiB0aGlzIHBvbHlub21pYWxcbiAgICAgICAgICovXG4gICAgICAgIGdldENvZWZmaWNpZW50KGRlZ3JlZSAvKmludCovKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2VmZmljaWVudHNbdGhpcy5jb2VmZmljaWVudHMubGVuZ3RoIC0gMSAtIGRlZ3JlZV07XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gZXZhbHVhdGlvbiBvZiB0aGlzIHBvbHlub21pYWwgYXQgYSBnaXZlbiBwb2ludFxuICAgICAgICAgKi9cbiAgICAgICAgZXZhbHVhdGVBdChhIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGlmIChhID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gSnVzdCByZXR1cm4gdGhlIHheMCBjb2VmZmljaWVudFxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldENvZWZmaWNpZW50KDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgY29lZmZpY2llbnRzID0gdGhpcy5jb2VmZmljaWVudHM7XG4gICAgICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICAgICAgaWYgKGEgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAvLyBKdXN0IHRoZSBzdW0gb2YgdGhlIGNvZWZmaWNpZW50c1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IDA7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGxlbmd0aCA9IGNvZWZmaWNpZW50cy5sZW5ndGg7IGkgIT09IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvZWZmaWNpZW50ID0gY29lZmZpY2llbnRzW2ldO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBBYnN0cmFjdEdlbmVyaWNHRi5hZGRPclN1YnRyYWN0KHJlc3VsdCwgY29lZmZpY2llbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzdWx0ID0gY29lZmZpY2llbnRzWzBdO1xuICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IGNvZWZmaWNpZW50cy5sZW5ndGg7XG4gICAgICAgICAgICBjb25zdCBmaWVsZCA9IHRoaXMuZmllbGQ7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHNpemU7IGkrKykge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IEFic3RyYWN0R2VuZXJpY0dGLmFkZE9yU3VidHJhY3QoZmllbGQubXVsdGlwbHkoYSwgcmVzdWx0KSwgY29lZmZpY2llbnRzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgYWRkT3JTdWJ0cmFjdChvdGhlcikge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmZpZWxkLmVxdWFscyhvdGhlci5maWVsZCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdHZW5lcmljR0ZQb2x5cyBkbyBub3QgaGF2ZSBzYW1lIEdlbmVyaWNHRiBmaWVsZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaXNaZXJvKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gb3RoZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob3RoZXIuaXNaZXJvKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBzbWFsbGVyQ29lZmZpY2llbnRzID0gdGhpcy5jb2VmZmljaWVudHM7XG4gICAgICAgICAgICBsZXQgbGFyZ2VyQ29lZmZpY2llbnRzID0gb3RoZXIuY29lZmZpY2llbnRzO1xuICAgICAgICAgICAgaWYgKHNtYWxsZXJDb2VmZmljaWVudHMubGVuZ3RoID4gbGFyZ2VyQ29lZmZpY2llbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHRlbXAgPSBzbWFsbGVyQ29lZmZpY2llbnRzO1xuICAgICAgICAgICAgICAgIHNtYWxsZXJDb2VmZmljaWVudHMgPSBsYXJnZXJDb2VmZmljaWVudHM7XG4gICAgICAgICAgICAgICAgbGFyZ2VyQ29lZmZpY2llbnRzID0gdGVtcDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBzdW1EaWZmID0gbmV3IEludDMyQXJyYXkobGFyZ2VyQ29lZmZpY2llbnRzLmxlbmd0aCk7XG4gICAgICAgICAgICBjb25zdCBsZW5ndGhEaWZmID0gbGFyZ2VyQ29lZmZpY2llbnRzLmxlbmd0aCAtIHNtYWxsZXJDb2VmZmljaWVudHMubGVuZ3RoO1xuICAgICAgICAgICAgLy8gQ29weSBoaWdoLW9yZGVyIHRlcm1zIG9ubHkgZm91bmQgaW4gaGlnaGVyLWRlZ3JlZSBwb2x5bm9taWFsJ3MgY29lZmZpY2llbnRzXG4gICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KGxhcmdlckNvZWZmaWNpZW50cywgMCwgc3VtRGlmZiwgMCwgbGVuZ3RoRGlmZik7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gbGVuZ3RoRGlmZjsgaSA8IGxhcmdlckNvZWZmaWNpZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHN1bURpZmZbaV0gPSBBYnN0cmFjdEdlbmVyaWNHRi5hZGRPclN1YnRyYWN0KHNtYWxsZXJDb2VmZmljaWVudHNbaSAtIGxlbmd0aERpZmZdLCBsYXJnZXJDb2VmZmljaWVudHNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBHZW5lcmljR0ZQb2x5KHRoaXMuZmllbGQsIHN1bURpZmYpO1xuICAgICAgICB9XG4gICAgICAgIG11bHRpcGx5KG90aGVyKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZmllbGQuZXF1YWxzKG90aGVyLmZpZWxkKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ0dlbmVyaWNHRlBvbHlzIGRvIG5vdCBoYXZlIHNhbWUgR2VuZXJpY0dGIGZpZWxkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5pc1plcm8oKSB8fCBvdGhlci5pc1plcm8oKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmZpZWxkLmdldFplcm8oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGFDb2VmZmljaWVudHMgPSB0aGlzLmNvZWZmaWNpZW50cztcbiAgICAgICAgICAgIGNvbnN0IGFMZW5ndGggPSBhQ29lZmZpY2llbnRzLmxlbmd0aDtcbiAgICAgICAgICAgIGNvbnN0IGJDb2VmZmljaWVudHMgPSBvdGhlci5jb2VmZmljaWVudHM7XG4gICAgICAgICAgICBjb25zdCBiTGVuZ3RoID0gYkNvZWZmaWNpZW50cy5sZW5ndGg7XG4gICAgICAgICAgICBjb25zdCBwcm9kdWN0ID0gbmV3IEludDMyQXJyYXkoYUxlbmd0aCArIGJMZW5ndGggLSAxKTtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gdGhpcy5maWVsZDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYUxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYUNvZWZmID0gYUNvZWZmaWNpZW50c1tpXTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGJMZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBwcm9kdWN0W2kgKyBqXSA9IEFic3RyYWN0R2VuZXJpY0dGLmFkZE9yU3VidHJhY3QocHJvZHVjdFtpICsgal0sIGZpZWxkLm11bHRpcGx5KGFDb2VmZiwgYkNvZWZmaWNpZW50c1tqXSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgR2VuZXJpY0dGUG9seShmaWVsZCwgcHJvZHVjdCk7XG4gICAgICAgIH1cbiAgICAgICAgbXVsdGlwbHlTY2FsYXIoc2NhbGFyIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGlmIChzY2FsYXIgPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5maWVsZC5nZXRaZXJvKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2NhbGFyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBzaXplID0gdGhpcy5jb2VmZmljaWVudHMubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpZWxkO1xuICAgICAgICAgICAgY29uc3QgcHJvZHVjdCA9IG5ldyBJbnQzMkFycmF5KHNpemUpO1xuICAgICAgICAgICAgY29uc3QgY29lZmZpY2llbnRzID0gdGhpcy5jb2VmZmljaWVudHM7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykge1xuICAgICAgICAgICAgICAgIHByb2R1Y3RbaV0gPSBmaWVsZC5tdWx0aXBseShjb2VmZmljaWVudHNbaV0sIHNjYWxhcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IEdlbmVyaWNHRlBvbHkoZmllbGQsIHByb2R1Y3QpO1xuICAgICAgICB9XG4gICAgICAgIG11bHRpcGx5QnlNb25vbWlhbChkZWdyZWUgLyppbnQqLywgY29lZmZpY2llbnQgLyppbnQqLykge1xuICAgICAgICAgICAgaWYgKGRlZ3JlZSA8IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29lZmZpY2llbnQgPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5maWVsZC5nZXRaZXJvKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBjb2VmZmljaWVudHMgPSB0aGlzLmNvZWZmaWNpZW50cztcbiAgICAgICAgICAgIGNvbnN0IHNpemUgPSBjb2VmZmljaWVudHMubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3QgcHJvZHVjdCA9IG5ldyBJbnQzMkFycmF5KHNpemUgKyBkZWdyZWUpO1xuICAgICAgICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpZWxkO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgICAgICAgICAgICBwcm9kdWN0W2ldID0gZmllbGQubXVsdGlwbHkoY29lZmZpY2llbnRzW2ldLCBjb2VmZmljaWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IEdlbmVyaWNHRlBvbHkoZmllbGQsIHByb2R1Y3QpO1xuICAgICAgICB9XG4gICAgICAgIGRpdmlkZShvdGhlcikge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmZpZWxkLmVxdWFscyhvdGhlci5maWVsZCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdHZW5lcmljR0ZQb2x5cyBkbyBub3QgaGF2ZSBzYW1lIEdlbmVyaWNHRiBmaWVsZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG90aGVyLmlzWmVybygpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignRGl2aWRlIGJ5IDAnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gdGhpcy5maWVsZDtcbiAgICAgICAgICAgIGxldCBxdW90aWVudCA9IGZpZWxkLmdldFplcm8oKTtcbiAgICAgICAgICAgIGxldCByZW1haW5kZXIgPSB0aGlzO1xuICAgICAgICAgICAgY29uc3QgZGVub21pbmF0b3JMZWFkaW5nVGVybSA9IG90aGVyLmdldENvZWZmaWNpZW50KG90aGVyLmdldERlZ3JlZSgpKTtcbiAgICAgICAgICAgIGNvbnN0IGludmVyc2VEZW5vbWluYXRvckxlYWRpbmdUZXJtID0gZmllbGQuaW52ZXJzZShkZW5vbWluYXRvckxlYWRpbmdUZXJtKTtcbiAgICAgICAgICAgIHdoaWxlIChyZW1haW5kZXIuZ2V0RGVncmVlKCkgPj0gb3RoZXIuZ2V0RGVncmVlKCkgJiYgIXJlbWFpbmRlci5pc1plcm8oKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRlZ3JlZURpZmZlcmVuY2UgPSByZW1haW5kZXIuZ2V0RGVncmVlKCkgLSBvdGhlci5nZXREZWdyZWUoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBzY2FsZSA9IGZpZWxkLm11bHRpcGx5KHJlbWFpbmRlci5nZXRDb2VmZmljaWVudChyZW1haW5kZXIuZ2V0RGVncmVlKCkpLCBpbnZlcnNlRGVub21pbmF0b3JMZWFkaW5nVGVybSk7XG4gICAgICAgICAgICAgICAgY29uc3QgdGVybSA9IG90aGVyLm11bHRpcGx5QnlNb25vbWlhbChkZWdyZWVEaWZmZXJlbmNlLCBzY2FsZSk7XG4gICAgICAgICAgICAgICAgY29uc3QgaXRlcmF0aW9uUXVvdGllbnQgPSBmaWVsZC5idWlsZE1vbm9taWFsKGRlZ3JlZURpZmZlcmVuY2UsIHNjYWxlKTtcbiAgICAgICAgICAgICAgICBxdW90aWVudCA9IHF1b3RpZW50LmFkZE9yU3VidHJhY3QoaXRlcmF0aW9uUXVvdGllbnQpO1xuICAgICAgICAgICAgICAgIHJlbWFpbmRlciA9IHJlbWFpbmRlci5hZGRPclN1YnRyYWN0KHRlcm0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIFtxdW90aWVudCwgcmVtYWluZGVyXTtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9ICcnO1xuICAgICAgICAgICAgZm9yIChsZXQgZGVncmVlID0gdGhpcy5nZXREZWdyZWUoKTsgZGVncmVlID49IDA7IGRlZ3JlZS0tKSB7XG4gICAgICAgICAgICAgICAgbGV0IGNvZWZmaWNpZW50ID0gdGhpcy5nZXRDb2VmZmljaWVudChkZWdyZWUpO1xuICAgICAgICAgICAgICAgIGlmIChjb2VmZmljaWVudCAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29lZmZpY2llbnQgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJyAtICc7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb2VmZmljaWVudCA9IC1jb2VmZmljaWVudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnICsgJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZGVncmVlID09PSAwIHx8IGNvZWZmaWNpZW50ICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhbHBoYVBvd2VyID0gdGhpcy5maWVsZC5sb2coY29lZmZpY2llbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFscGhhUG93ZXIgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJzEnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoYWxwaGFQb3dlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnYSc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ2FeJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gYWxwaGFQb3dlcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZGVncmVlICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGVncmVlID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICd4JztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAneF4nO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSBkZWdyZWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3VzdG9tIEVycm9yIGNsYXNzIG9mIHR5cGUgRXhjZXB0aW9uLlxuICAgICAqL1xuICAgIGNsYXNzIEFyaXRobWV0aWNFeGNlcHRpb24gZXh0ZW5kcyBFeGNlcHRpb24ge1xuICAgIH1cbiAgICBBcml0aG1ldGljRXhjZXB0aW9uLmtpbmQgPSAnQXJpdGhtZXRpY0V4Y2VwdGlvbic7XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIDxwPlRoaXMgY2xhc3MgY29udGFpbnMgdXRpbGl0eSBtZXRob2RzIGZvciBwZXJmb3JtaW5nIG1hdGhlbWF0aWNhbCBvcGVyYXRpb25zIG92ZXJcbiAgICAgKiB0aGUgR2Fsb2lzIEZpZWxkcy4gT3BlcmF0aW9ucyB1c2UgYSBnaXZlbiBwcmltaXRpdmUgcG9seW5vbWlhbCBpbiBjYWxjdWxhdGlvbnMuPC9wPlxuICAgICAqXG4gICAgICogPHA+VGhyb3VnaG91dCB0aGlzIHBhY2thZ2UsIGVsZW1lbnRzIG9mIHRoZSBHRiBhcmUgcmVwcmVzZW50ZWQgYXMgYW4ge0Bjb2RlIGludH1cbiAgICAgKiBmb3IgY29udmVuaWVuY2UgYW5kIHNwZWVkIChidXQgYXQgdGhlIGNvc3Qgb2YgbWVtb3J5KS5cbiAgICAgKiA8L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqIEBhdXRob3IgRGF2aWQgT2xpdmllclxuICAgICAqL1xuICAgIGNsYXNzIEdlbmVyaWNHRiBleHRlbmRzIEFic3RyYWN0R2VuZXJpY0dGIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZSBhIHJlcHJlc2VudGF0aW9uIG9mIEdGKHNpemUpIHVzaW5nIHRoZSBnaXZlbiBwcmltaXRpdmUgcG9seW5vbWlhbC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHByaW1pdGl2ZSBpcnJlZHVjaWJsZSBwb2x5bm9taWFsIHdob3NlIGNvZWZmaWNpZW50cyBhcmUgcmVwcmVzZW50ZWQgYnlcbiAgICAgICAgICogIHRoZSBiaXRzIG9mIGFuIGludCwgd2hlcmUgdGhlIGxlYXN0LXNpZ25pZmljYW50IGJpdCByZXByZXNlbnRzIHRoZSBjb25zdGFudFxuICAgICAgICAgKiAgY29lZmZpY2llbnRcbiAgICAgICAgICogQHBhcmFtIHNpemUgdGhlIHNpemUgb2YgdGhlIGZpZWxkXG4gICAgICAgICAqIEBwYXJhbSBiIHRoZSBmYWN0b3IgYiBpbiB0aGUgZ2VuZXJhdG9yIHBvbHlub21pYWwgY2FuIGJlIDAtIG9yIDEtYmFzZWRcbiAgICAgICAgICogIChnKHgpID0gKHgrYV5iKSh4K2FeKGIrMSkpLi4uKHgrYV4oYisydC0xKSkpLlxuICAgICAgICAgKiAgSW4gbW9zdCBjYXNlcyBpdCBzaG91bGQgYmUgMSwgYnV0IGZvciBRUiBjb2RlIGl0IGlzIDAuXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3RvcihwcmltaXRpdmUgLyppbnQqLywgc2l6ZSAvKmludCovLCBnZW5lcmF0b3JCYXNlIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHN1cGVyKCk7XG4gICAgICAgICAgICB0aGlzLnByaW1pdGl2ZSA9IHByaW1pdGl2ZTtcbiAgICAgICAgICAgIHRoaXMuc2l6ZSA9IHNpemU7XG4gICAgICAgICAgICB0aGlzLmdlbmVyYXRvckJhc2UgPSBnZW5lcmF0b3JCYXNlO1xuICAgICAgICAgICAgY29uc3QgZXhwVGFibGUgPSBuZXcgSW50MzJBcnJheShzaXplKTtcbiAgICAgICAgICAgIGxldCB4ID0gMTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgZXhwVGFibGVbaV0gPSB4O1xuICAgICAgICAgICAgICAgIHggKj0gMjsgLy8gd2UncmUgYXNzdW1pbmcgdGhlIGdlbmVyYXRvciBhbHBoYSBpcyAyXG4gICAgICAgICAgICAgICAgaWYgKHggPj0gc2l6ZSkge1xuICAgICAgICAgICAgICAgICAgICB4IF49IHByaW1pdGl2ZTtcbiAgICAgICAgICAgICAgICAgICAgeCAmPSBzaXplIC0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmV4cFRhYmxlID0gZXhwVGFibGU7XG4gICAgICAgICAgICBjb25zdCBsb2dUYWJsZSA9IG5ldyBJbnQzMkFycmF5KHNpemUpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplIC0gMTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbG9nVGFibGVbZXhwVGFibGVbaV1dID0gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMubG9nVGFibGUgPSBsb2dUYWJsZTtcbiAgICAgICAgICAgIC8vIGxvZ1RhYmxlWzBdID09IDAgYnV0IHRoaXMgc2hvdWxkIG5ldmVyIGJlIHVzZWRcbiAgICAgICAgICAgIHRoaXMuemVybyA9IG5ldyBHZW5lcmljR0ZQb2x5KHRoaXMsIEludDMyQXJyYXkuZnJvbShbMF0pKTtcbiAgICAgICAgICAgIHRoaXMub25lID0gbmV3IEdlbmVyaWNHRlBvbHkodGhpcywgSW50MzJBcnJheS5mcm9tKFsxXSkpO1xuICAgICAgICB9XG4gICAgICAgIGdldFplcm8oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy56ZXJvO1xuICAgICAgICB9XG4gICAgICAgIGdldE9uZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm9uZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB0aGUgbW9ub21pYWwgcmVwcmVzZW50aW5nIGNvZWZmaWNpZW50ICogeF5kZWdyZWVcbiAgICAgICAgICovXG4gICAgICAgIGJ1aWxkTW9ub21pYWwoZGVncmVlIC8qaW50Ki8sIGNvZWZmaWNpZW50IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGlmIChkZWdyZWUgPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvZWZmaWNpZW50ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuemVybztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGNvZWZmaWNpZW50cyA9IG5ldyBJbnQzMkFycmF5KGRlZ3JlZSArIDEpO1xuICAgICAgICAgICAgY29lZmZpY2llbnRzWzBdID0gY29lZmZpY2llbnQ7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEdlbmVyaWNHRlBvbHkodGhpcywgY29lZmZpY2llbnRzKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBtdWx0aXBsaWNhdGl2ZSBpbnZlcnNlIG9mIGFcbiAgICAgICAgICovXG4gICAgICAgIGludmVyc2UoYSAvKmludCovKSB7XG4gICAgICAgICAgICBpZiAoYSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBBcml0aG1ldGljRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5leHBUYWJsZVt0aGlzLnNpemUgLSB0aGlzLmxvZ1RhYmxlW2FdIC0gMV07XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gcHJvZHVjdCBvZiBhIGFuZCBiIGluIEdGKHNpemUpXG4gICAgICAgICAqL1xuICAgICAgICBtdWx0aXBseShhIC8qaW50Ki8sIGIgLyppbnQqLykge1xuICAgICAgICAgICAgaWYgKGEgPT09IDAgfHwgYiA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXhwVGFibGVbKHRoaXMubG9nVGFibGVbYV0gKyB0aGlzLmxvZ1RhYmxlW2JdKSAlICh0aGlzLnNpemUgLSAxKV07XG4gICAgICAgIH1cbiAgICAgICAgZ2V0U2l6ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNpemU7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0R2VuZXJhdG9yQmFzZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdlbmVyYXRvckJhc2U7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICB0b1N0cmluZygpIHtcbiAgICAgICAgICAgIHJldHVybiAoJ0dGKDB4JyArIEludGVnZXIudG9IZXhTdHJpbmcodGhpcy5wcmltaXRpdmUpICsgJywnICsgdGhpcy5zaXplICsgJyknKTtcbiAgICAgICAgfVxuICAgICAgICBlcXVhbHMobykge1xuICAgICAgICAgICAgcmV0dXJuIG8gPT09IHRoaXM7XG4gICAgICAgIH1cbiAgICB9XG4gICAgR2VuZXJpY0dGLkFaVEVDX0RBVEFfMTIgPSBuZXcgR2VuZXJpY0dGKDB4MTA2OSwgNDA5NiwgMSk7IC8vIHheMTIgKyB4XjYgKyB4XjUgKyB4XjMgKyAxXG4gICAgR2VuZXJpY0dGLkFaVEVDX0RBVEFfMTAgPSBuZXcgR2VuZXJpY0dGKDB4NDA5LCAxMDI0LCAxKTsgLy8geF4xMCArIHheMyArIDFcbiAgICBHZW5lcmljR0YuQVpURUNfREFUQV82ID0gbmV3IEdlbmVyaWNHRigweDQzLCA2NCwgMSk7IC8vIHheNiArIHggKyAxXG4gICAgR2VuZXJpY0dGLkFaVEVDX1BBUkFNID0gbmV3IEdlbmVyaWNHRigweDEzLCAxNiwgMSk7IC8vIHheNCArIHggKyAxXG4gICAgR2VuZXJpY0dGLlFSX0NPREVfRklFTERfMjU2ID0gbmV3IEdlbmVyaWNHRigweDAxMWQsIDI1NiwgMCk7IC8vIHheOCArIHheNCArIHheMyArIHheMiArIDFcbiAgICBHZW5lcmljR0YuREFUQV9NQVRSSVhfRklFTERfMjU2ID0gbmV3IEdlbmVyaWNHRigweDAxMmQsIDI1NiwgMSk7IC8vIHheOCArIHheNSArIHheMyArIHheMiArIDFcbiAgICBHZW5lcmljR0YuQVpURUNfREFUQV84ID0gR2VuZXJpY0dGLkRBVEFfTUFUUklYX0ZJRUxEXzI1NjtcbiAgICBHZW5lcmljR0YuTUFYSUNPREVfRklFTERfNjQgPSBHZW5lcmljR0YuQVpURUNfREFUQV82O1xuXG4gICAgLyoqXG4gICAgICogQ3VzdG9tIEVycm9yIGNsYXNzIG9mIHR5cGUgRXhjZXB0aW9uLlxuICAgICAqL1xuICAgIGNsYXNzIFJlZWRTb2xvbW9uRXhjZXB0aW9uIGV4dGVuZHMgRXhjZXB0aW9uIHtcbiAgICB9XG4gICAgUmVlZFNvbG9tb25FeGNlcHRpb24ua2luZCA9ICdSZWVkU29sb21vbkV4Y2VwdGlvbic7XG5cbiAgICAvKipcbiAgICAgKiBDdXN0b20gRXJyb3IgY2xhc3Mgb2YgdHlwZSBFeGNlcHRpb24uXG4gICAgICovXG4gICAgY2xhc3MgSWxsZWdhbFN0YXRlRXhjZXB0aW9uIGV4dGVuZHMgRXhjZXB0aW9uIHtcbiAgICB9XG4gICAgSWxsZWdhbFN0YXRlRXhjZXB0aW9uLmtpbmQgPSAnSWxsZWdhbFN0YXRlRXhjZXB0aW9uJztcblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogPHA+SW1wbGVtZW50cyBSZWVkLVNvbG9tb24gZGVjb2RpbmcsIGFzIHRoZSBuYW1lIGltcGxpZXMuPC9wPlxuICAgICAqXG4gICAgICogPHA+VGhlIGFsZ29yaXRobSB3aWxsIG5vdCBiZSBleHBsYWluZWQgaGVyZSwgYnV0IHRoZSBmb2xsb3dpbmcgcmVmZXJlbmNlcyB3ZXJlIGhlbHBmdWxcbiAgICAgKiBpbiBjcmVhdGluZyB0aGlzIGltcGxlbWVudGF0aW9uOjwvcD5cbiAgICAgKlxuICAgICAqIDx1bD5cbiAgICAgKiA8bGk+QnJ1Y2UgTWFnZ3MuXG4gICAgICogPGEgaHJlZj1cImh0dHA6Ly93d3cuY3MuY211LmVkdS9hZnMvY3MuY211LmVkdS9wcm9qZWN0L3BzY2ljby1ndXliL3JlYWx3b3JsZC93d3cvcnNfZGVjb2RlLnBzXCI+XG4gICAgICogXCJEZWNvZGluZyBSZWVkLVNvbG9tb24gQ29kZXNcIjwvYT4gKHNlZSBkaXNjdXNzaW9uIG9mIEZvcm5leSdzIEZvcm11bGEpPC9saT5cbiAgICAgKiA8bGk+Si5JLiBIYWxsLiA8YSBocmVmPVwid3d3Lm10aC5tc3UuZWR1L35qaGFsbC9jbGFzc2VzL2NvZGVub3Rlcy9HUlMucGRmXCI+XG4gICAgICogXCJDaGFwdGVyIDUuIEdlbmVyYWxpemVkIFJlZWQtU29sb21vbiBDb2Rlc1wiPC9hPlxuICAgICAqIChzZWUgZGlzY3Vzc2lvbiBvZiBFdWNsaWRlYW4gYWxnb3JpdGhtKTwvbGk+XG4gICAgICogPC91bD5cbiAgICAgKlxuICAgICAqIDxwPk11Y2ggY3JlZGl0IGlzIGR1ZSB0byBXaWxsaWFtIFJ1Y2tsaWRnZSBzaW5jZSBwb3J0aW9ucyBvZiB0aGlzIGNvZGUgYXJlIGFuIGluZGlyZWN0XG4gICAgICogcG9ydCBvZiBoaXMgQysrIFJlZWQtU29sb21vbiBpbXBsZW1lbnRhdGlvbi48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqIEBhdXRob3IgV2lsbGlhbSBSdWNrbGlkZ2VcbiAgICAgKiBAYXV0aG9yIHNhbmZvcmRzcXVpcmVzXG4gICAgICovXG4gICAgY2xhc3MgUmVlZFNvbG9tb25EZWNvZGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IoZmllbGQpIHtcbiAgICAgICAgICAgIHRoaXMuZmllbGQgPSBmaWVsZDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+RGVjb2RlcyBnaXZlbiBzZXQgb2YgcmVjZWl2ZWQgY29kZXdvcmRzLCB3aGljaCBpbmNsdWRlIGJvdGggZGF0YSBhbmQgZXJyb3ItY29ycmVjdGlvblxuICAgICAgICAgKiBjb2Rld29yZHMuIFJlYWxseSwgdGhpcyBtZWFucyBpdCB1c2VzIFJlZWQtU29sb21vbiB0byBkZXRlY3QgYW5kIGNvcnJlY3QgZXJyb3JzLCBpbi1wbGFjZSxcbiAgICAgICAgICogaW4gdGhlIGlucHV0LjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHJlY2VpdmVkIGRhdGEgYW5kIGVycm9yLWNvcnJlY3Rpb24gY29kZXdvcmRzXG4gICAgICAgICAqIEBwYXJhbSB0d29TIG51bWJlciBvZiBlcnJvci1jb3JyZWN0aW9uIGNvZGV3b3JkcyBhdmFpbGFibGVcbiAgICAgICAgICogQHRocm93cyBSZWVkU29sb21vbkV4Y2VwdGlvbiBpZiBkZWNvZGluZyBmYWlscyBmb3IgYW55IHJlYXNvblxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlKHJlY2VpdmVkLCB0d29TIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gdGhpcy5maWVsZDtcbiAgICAgICAgICAgIGNvbnN0IHBvbHkgPSBuZXcgR2VuZXJpY0dGUG9seShmaWVsZCwgcmVjZWl2ZWQpO1xuICAgICAgICAgICAgY29uc3Qgc3luZHJvbWVDb2VmZmljaWVudHMgPSBuZXcgSW50MzJBcnJheSh0d29TKTtcbiAgICAgICAgICAgIGxldCBub0Vycm9yID0gdHJ1ZTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdHdvUzsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXZhbFJlc3VsdCA9IHBvbHkuZXZhbHVhdGVBdChmaWVsZC5leHAoaSArIGZpZWxkLmdldEdlbmVyYXRvckJhc2UoKSkpO1xuICAgICAgICAgICAgICAgIHN5bmRyb21lQ29lZmZpY2llbnRzW3N5bmRyb21lQ29lZmZpY2llbnRzLmxlbmd0aCAtIDEgLSBpXSA9IGV2YWxSZXN1bHQ7XG4gICAgICAgICAgICAgICAgaWYgKGV2YWxSZXN1bHQgIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgbm9FcnJvciA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChub0Vycm9yKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgc3luZHJvbWUgPSBuZXcgR2VuZXJpY0dGUG9seShmaWVsZCwgc3luZHJvbWVDb2VmZmljaWVudHMpO1xuICAgICAgICAgICAgY29uc3Qgc2lnbWFPbWVnYSA9IHRoaXMucnVuRXVjbGlkZWFuQWxnb3JpdGhtKGZpZWxkLmJ1aWxkTW9ub21pYWwodHdvUywgMSksIHN5bmRyb21lLCB0d29TKTtcbiAgICAgICAgICAgIGNvbnN0IHNpZ21hID0gc2lnbWFPbWVnYVswXTtcbiAgICAgICAgICAgIGNvbnN0IG9tZWdhID0gc2lnbWFPbWVnYVsxXTtcbiAgICAgICAgICAgIGNvbnN0IGVycm9yTG9jYXRpb25zID0gdGhpcy5maW5kRXJyb3JMb2NhdGlvbnMoc2lnbWEpO1xuICAgICAgICAgICAgY29uc3QgZXJyb3JNYWduaXR1ZGVzID0gdGhpcy5maW5kRXJyb3JNYWduaXR1ZGVzKG9tZWdhLCBlcnJvckxvY2F0aW9ucyk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVycm9yTG9jYXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcG9zaXRpb24gPSByZWNlaXZlZC5sZW5ndGggLSAxIC0gZmllbGQubG9nKGVycm9yTG9jYXRpb25zW2ldKTtcbiAgICAgICAgICAgICAgICBpZiAocG9zaXRpb24gPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBSZWVkU29sb21vbkV4Y2VwdGlvbignQmFkIGVycm9yIGxvY2F0aW9uJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlY2VpdmVkW3Bvc2l0aW9uXSA9IEdlbmVyaWNHRi5hZGRPclN1YnRyYWN0KHJlY2VpdmVkW3Bvc2l0aW9uXSwgZXJyb3JNYWduaXR1ZGVzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBydW5FdWNsaWRlYW5BbGdvcml0aG0oYSwgYiwgUiAvKmludCovKSB7XG4gICAgICAgICAgICAvLyBBc3N1bWUgYSdzIGRlZ3JlZSBpcyA+PSBiJ3NcbiAgICAgICAgICAgIGlmIChhLmdldERlZ3JlZSgpIDwgYi5nZXREZWdyZWUoKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHRlbXAgPSBhO1xuICAgICAgICAgICAgICAgIGEgPSBiO1xuICAgICAgICAgICAgICAgIGIgPSB0ZW1wO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpZWxkO1xuICAgICAgICAgICAgbGV0IHJMYXN0ID0gYTtcbiAgICAgICAgICAgIGxldCByID0gYjtcbiAgICAgICAgICAgIGxldCB0TGFzdCA9IGZpZWxkLmdldFplcm8oKTtcbiAgICAgICAgICAgIGxldCB0ID0gZmllbGQuZ2V0T25lKCk7XG4gICAgICAgICAgICAvLyBSdW4gRXVjbGlkZWFuIGFsZ29yaXRobSB1bnRpbCByJ3MgZGVncmVlIGlzIGxlc3MgdGhhbiBSLzJcbiAgICAgICAgICAgIHdoaWxlIChyLmdldERlZ3JlZSgpID49IChSIC8gMiB8IDApKSB7XG4gICAgICAgICAgICAgICAgbGV0IHJMYXN0TGFzdCA9IHJMYXN0O1xuICAgICAgICAgICAgICAgIGxldCB0TGFzdExhc3QgPSB0TGFzdDtcbiAgICAgICAgICAgICAgICByTGFzdCA9IHI7XG4gICAgICAgICAgICAgICAgdExhc3QgPSB0O1xuICAgICAgICAgICAgICAgIC8vIERpdmlkZSByTGFzdExhc3QgYnkgckxhc3QsIHdpdGggcXVvdGllbnQgaW4gcSBhbmQgcmVtYWluZGVyIGluIHJcbiAgICAgICAgICAgICAgICBpZiAockxhc3QuaXNaZXJvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gT29wcywgRXVjbGlkZWFuIGFsZ29yaXRobSBhbHJlYWR5IHRlcm1pbmF0ZWQ/XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBSZWVkU29sb21vbkV4Y2VwdGlvbigncl97aS0xfSB3YXMgemVybycpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByID0gckxhc3RMYXN0O1xuICAgICAgICAgICAgICAgIGxldCBxID0gZmllbGQuZ2V0WmVybygpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGRlbm9taW5hdG9yTGVhZGluZ1Rlcm0gPSByTGFzdC5nZXRDb2VmZmljaWVudChyTGFzdC5nZXREZWdyZWUoKSk7XG4gICAgICAgICAgICAgICAgY29uc3QgZGx0SW52ZXJzZSA9IGZpZWxkLmludmVyc2UoZGVub21pbmF0b3JMZWFkaW5nVGVybSk7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHIuZ2V0RGVncmVlKCkgPj0gckxhc3QuZ2V0RGVncmVlKCkgJiYgIXIuaXNaZXJvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGVncmVlRGlmZiA9IHIuZ2V0RGVncmVlKCkgLSByTGFzdC5nZXREZWdyZWUoKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2NhbGUgPSBmaWVsZC5tdWx0aXBseShyLmdldENvZWZmaWNpZW50KHIuZ2V0RGVncmVlKCkpLCBkbHRJbnZlcnNlKTtcbiAgICAgICAgICAgICAgICAgICAgcSA9IHEuYWRkT3JTdWJ0cmFjdChmaWVsZC5idWlsZE1vbm9taWFsKGRlZ3JlZURpZmYsIHNjYWxlKSk7XG4gICAgICAgICAgICAgICAgICAgIHIgPSByLmFkZE9yU3VidHJhY3Qockxhc3QubXVsdGlwbHlCeU1vbm9taWFsKGRlZ3JlZURpZmYsIHNjYWxlKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHQgPSBxLm11bHRpcGx5KHRMYXN0KS5hZGRPclN1YnRyYWN0KHRMYXN0TGFzdCk7XG4gICAgICAgICAgICAgICAgaWYgKHIuZ2V0RGVncmVlKCkgPj0gckxhc3QuZ2V0RGVncmVlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbignRGl2aXNpb24gYWxnb3JpdGhtIGZhaWxlZCB0byByZWR1Y2UgcG9seW5vbWlhbD8nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBzaWdtYVRpbGRlQXRaZXJvID0gdC5nZXRDb2VmZmljaWVudCgwKTtcbiAgICAgICAgICAgIGlmIChzaWdtYVRpbGRlQXRaZXJvID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFJlZWRTb2xvbW9uRXhjZXB0aW9uKCdzaWdtYVRpbGRlKDApIHdhcyB6ZXJvJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBpbnZlcnNlID0gZmllbGQuaW52ZXJzZShzaWdtYVRpbGRlQXRaZXJvKTtcbiAgICAgICAgICAgIGNvbnN0IHNpZ21hID0gdC5tdWx0aXBseVNjYWxhcihpbnZlcnNlKTtcbiAgICAgICAgICAgIGNvbnN0IG9tZWdhID0gci5tdWx0aXBseVNjYWxhcihpbnZlcnNlKTtcbiAgICAgICAgICAgIHJldHVybiBbc2lnbWEsIG9tZWdhXTtcbiAgICAgICAgfVxuICAgICAgICBmaW5kRXJyb3JMb2NhdGlvbnMoZXJyb3JMb2NhdG9yKSB7XG4gICAgICAgICAgICAvLyBUaGlzIGlzIGEgZGlyZWN0IGFwcGxpY2F0aW9uIG9mIENoaWVuJ3Mgc2VhcmNoXG4gICAgICAgICAgICBjb25zdCBudW1FcnJvcnMgPSBlcnJvckxvY2F0b3IuZ2V0RGVncmVlKCk7XG4gICAgICAgICAgICBpZiAobnVtRXJyb3JzID09PSAxKSB7IC8vIHNob3J0Y3V0XG4gICAgICAgICAgICAgICAgcmV0dXJuIEludDMyQXJyYXkuZnJvbShbZXJyb3JMb2NhdG9yLmdldENvZWZmaWNpZW50KDEpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgSW50MzJBcnJheShudW1FcnJvcnMpO1xuICAgICAgICAgICAgbGV0IGUgPSAwO1xuICAgICAgICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpZWxkO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBmaWVsZC5nZXRTaXplKCkgJiYgZSA8IG51bUVycm9yczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yTG9jYXRvci5ldmFsdWF0ZUF0KGkpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtlXSA9IGZpZWxkLmludmVyc2UoaSk7XG4gICAgICAgICAgICAgICAgICAgIGUrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZSAhPT0gbnVtRXJyb3JzKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFJlZWRTb2xvbW9uRXhjZXB0aW9uKCdFcnJvciBsb2NhdG9yIGRlZ3JlZSBkb2VzIG5vdCBtYXRjaCBudW1iZXIgb2Ygcm9vdHMnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgZmluZEVycm9yTWFnbml0dWRlcyhlcnJvckV2YWx1YXRvciwgZXJyb3JMb2NhdGlvbnMpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgZGlyZWN0bHkgYXBwbHlpbmcgRm9ybmV5J3MgRm9ybXVsYVxuICAgICAgICAgICAgY29uc3QgcyA9IGVycm9yTG9jYXRpb25zLmxlbmd0aDtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBJbnQzMkFycmF5KHMpO1xuICAgICAgICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpZWxkO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCB4aUludmVyc2UgPSBmaWVsZC5pbnZlcnNlKGVycm9yTG9jYXRpb25zW2ldKTtcbiAgICAgICAgICAgICAgICBsZXQgZGVub21pbmF0b3IgPSAxO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgczsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpICE9PSBqKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBkZW5vbWluYXRvciA9IGZpZWxkLm11bHRpcGx5KGRlbm9taW5hdG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgR2VuZXJpY0dGLmFkZE9yU3VidHJhY3QoMSwgZmllbGQubXVsdGlwbHkoZXJyb3JMb2NhdGlvbnNbal0sIHhpSW52ZXJzZSkpKVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWJvdmUgc2hvdWxkIHdvcmsgYnV0IGZhaWxzIG9uIHNvbWUgQXBwbGUgYW5kIExpbnV4IEpES3MgZHVlIHRvIGEgSG90c3BvdCBidWcuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBCZWxvdyBpcyBhIGZ1bm55LWxvb2tpbmcgd29ya2Fyb3VuZCBmcm9tIFN0ZXZlbiBQYXJrZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRlcm0gPSBmaWVsZC5tdWx0aXBseShlcnJvckxvY2F0aW9uc1tqXSwgeGlJbnZlcnNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRlcm1QbHVzMSA9ICh0ZXJtICYgMHgxKSA9PT0gMCA/IHRlcm0gfCAxIDogdGVybSAmIH4xO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVub21pbmF0b3IgPSBmaWVsZC5tdWx0aXBseShkZW5vbWluYXRvciwgdGVybVBsdXMxKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXN1bHRbaV0gPSBmaWVsZC5tdWx0aXBseShlcnJvckV2YWx1YXRvci5ldmFsdWF0ZUF0KHhpSW52ZXJzZSksIGZpZWxkLmludmVyc2UoZGVub21pbmF0b3IpKTtcbiAgICAgICAgICAgICAgICBpZiAoZmllbGQuZ2V0R2VuZXJhdG9yQmFzZSgpICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtpXSA9IGZpZWxkLm11bHRpcGx5KHJlc3VsdFtpXSwgeGlJbnZlcnNlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAxMCBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLkFycmF5cztcbiAgICB2YXIgVGFibGU7XG4gICAgKGZ1bmN0aW9uIChUYWJsZSkge1xuICAgICAgICBUYWJsZVtUYWJsZVtcIlVQUEVSXCJdID0gMF0gPSBcIlVQUEVSXCI7XG4gICAgICAgIFRhYmxlW1RhYmxlW1wiTE9XRVJcIl0gPSAxXSA9IFwiTE9XRVJcIjtcbiAgICAgICAgVGFibGVbVGFibGVbXCJNSVhFRFwiXSA9IDJdID0gXCJNSVhFRFwiO1xuICAgICAgICBUYWJsZVtUYWJsZVtcIkRJR0lUXCJdID0gM10gPSBcIkRJR0lUXCI7XG4gICAgICAgIFRhYmxlW1RhYmxlW1wiUFVOQ1RcIl0gPSA0XSA9IFwiUFVOQ1RcIjtcbiAgICAgICAgVGFibGVbVGFibGVbXCJCSU5BUllcIl0gPSA1XSA9IFwiQklOQVJZXCI7XG4gICAgfSkoVGFibGUgfHwgKFRhYmxlID0ge30pKTtcbiAgICAvKipcbiAgICAgKiA8cD5UaGUgbWFpbiBjbGFzcyB3aGljaCBpbXBsZW1lbnRzIEF6dGVjIENvZGUgZGVjb2RpbmcgLS0gYXMgb3Bwb3NlZCB0byBsb2NhdGluZyBhbmQgZXh0cmFjdGluZ1xuICAgICAqIHRoZSBBenRlYyBDb2RlIGZyb20gYW4gaW1hZ2UuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBEYXZpZCBPbGl2aWVyXG4gICAgICovXG4gICAgY2xhc3MgRGVjb2RlciB7XG4gICAgICAgIGRlY29kZShkZXRlY3RvclJlc3VsdCkge1xuICAgICAgICAgICAgdGhpcy5kZGF0YSA9IGRldGVjdG9yUmVzdWx0O1xuICAgICAgICAgICAgbGV0IG1hdHJpeCA9IGRldGVjdG9yUmVzdWx0LmdldEJpdHMoKTtcbiAgICAgICAgICAgIGxldCByYXdiaXRzID0gdGhpcy5leHRyYWN0Qml0cyhtYXRyaXgpO1xuICAgICAgICAgICAgbGV0IGNvcnJlY3RlZEJpdHMgPSB0aGlzLmNvcnJlY3RCaXRzKHJhd2JpdHMpO1xuICAgICAgICAgICAgbGV0IHJhd0J5dGVzID0gRGVjb2Rlci5jb252ZXJ0Qm9vbEFycmF5VG9CeXRlQXJyYXkoY29ycmVjdGVkQml0cyk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gRGVjb2Rlci5nZXRFbmNvZGVkRGF0YShjb3JyZWN0ZWRCaXRzKTtcbiAgICAgICAgICAgIGxldCBkZWNvZGVyUmVzdWx0ID0gbmV3IERlY29kZXJSZXN1bHQocmF3Qnl0ZXMsIHJlc3VsdCwgbnVsbCwgbnVsbCk7XG4gICAgICAgICAgICBkZWNvZGVyUmVzdWx0LnNldE51bUJpdHMoY29ycmVjdGVkQml0cy5sZW5ndGgpO1xuICAgICAgICAgICAgcmV0dXJuIGRlY29kZXJSZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVGhpcyBtZXRob2QgaXMgdXNlZCBmb3IgdGVzdGluZyB0aGUgaGlnaC1sZXZlbCBlbmNvZGVyXG4gICAgICAgIHN0YXRpYyBoaWdoTGV2ZWxEZWNvZGUoY29ycmVjdGVkQml0cykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RW5jb2RlZERhdGEoY29ycmVjdGVkQml0cyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdldHMgdGhlIHN0cmluZyBlbmNvZGVkIGluIHRoZSBhenRlYyBjb2RlIGJpdHNcbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiB0aGUgZGVjb2RlZCBzdHJpbmdcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBnZXRFbmNvZGVkRGF0YShjb3JyZWN0ZWRCaXRzKSB7XG4gICAgICAgICAgICBsZXQgZW5kSW5kZXggPSBjb3JyZWN0ZWRCaXRzLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBsYXRjaFRhYmxlID0gVGFibGUuVVBQRVI7IC8vIHRhYmxlIG1vc3QgcmVjZW50bHkgbGF0Y2hlZCB0b1xuICAgICAgICAgICAgbGV0IHNoaWZ0VGFibGUgPSBUYWJsZS5VUFBFUjsgLy8gdGFibGUgdG8gdXNlIGZvciB0aGUgbmV4dCByZWFkXG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gJyc7XG4gICAgICAgICAgICBsZXQgaW5kZXggPSAwO1xuICAgICAgICAgICAgd2hpbGUgKGluZGV4IDwgZW5kSW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2hpZnRUYWJsZSA9PT0gVGFibGUuQklOQVJZKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlbmRJbmRleCAtIGluZGV4IDwgNSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbGV0IGxlbmd0aCA9IERlY29kZXIucmVhZENvZGUoY29ycmVjdGVkQml0cywgaW5kZXgsIDUpO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSA1O1xuICAgICAgICAgICAgICAgICAgICBpZiAobGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZW5kSW5kZXggLSBpbmRleCA8IDExKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGggPSBEZWNvZGVyLnJlYWRDb2RlKGNvcnJlY3RlZEJpdHMsIGluZGV4LCAxMSkgKyAzMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDExO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGNoYXJDb3VudCA9IDA7IGNoYXJDb3VudCA8IGxlbmd0aDsgY2hhckNvdW50KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbmRJbmRleCAtIGluZGV4IDwgOCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ID0gZW5kSW5kZXg7IC8vIEZvcmNlIG91dGVyIGxvb3AgdG8gZXhpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29kZSA9IERlY29kZXIucmVhZENvZGUoY29ycmVjdGVkQml0cywgaW5kZXgsIDgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IC8qKGNoYXIpKi8gU3RyaW5nVXRpbHMuY2FzdEFzTm9uVXRmOENoYXIoY29kZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSA4O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIEdvIGJhY2sgdG8gd2hhdGV2ZXIgbW9kZSB3ZSBoYWQgYmVlbiBpblxuICAgICAgICAgICAgICAgICAgICBzaGlmdFRhYmxlID0gbGF0Y2hUYWJsZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBzaXplID0gc2hpZnRUYWJsZSA9PT0gVGFibGUuRElHSVQgPyA0IDogNTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVuZEluZGV4IC0gaW5kZXggPCBzaXplKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBsZXQgY29kZSA9IERlY29kZXIucmVhZENvZGUoY29ycmVjdGVkQml0cywgaW5kZXgsIHNpemUpO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBzaXplO1xuICAgICAgICAgICAgICAgICAgICBsZXQgc3RyID0gRGVjb2Rlci5nZXRDaGFyYWN0ZXIoc2hpZnRUYWJsZSwgY29kZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHIuc3RhcnRzV2l0aCgnQ1RSTF8nKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGFibGUgY2hhbmdlc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSVNPL0lFQyAyNDc3ODoyMDA4IHByZXNjcmliZXMgZW5kaW5nIGEgc2hpZnQgc2VxdWVuY2UgaW4gdGhlIG1vZGUgZnJvbSB3aGljaCBpdCB3YXMgaW52b2tlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoYXQncyBpbmNsdWRpbmcgd2hlbiB0aGF0IG1vZGUgaXMgYSBzaGlmdC5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE91ciB0ZXN0IGNhc2UgZGx1c2JzLnBuZyBmb3IgaXNzdWUgIzY0MiBleGVyY2lzZXMgdGhhdC5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxhdGNoVGFibGUgPSBzaGlmdFRhYmxlOyAvLyBMYXRjaCB0aGUgY3VycmVudCBtb2RlLCBzbyBhcyB0byByZXR1cm4gdG8gVXBwZXIgYWZ0ZXIgVS9TIEIvU1xuICAgICAgICAgICAgICAgICAgICAgICAgc2hpZnRUYWJsZSA9IERlY29kZXIuZ2V0VGFibGUoc3RyLmNoYXJBdCg1KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RyLmNoYXJBdCg2KSA9PT0gJ0wnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0Y2hUYWJsZSA9IHNoaWZ0VGFibGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gc3RyO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gR28gYmFjayB0byB3aGF0ZXZlciBtb2RlIHdlIGhhZCBiZWVuIGluXG4gICAgICAgICAgICAgICAgICAgICAgICBzaGlmdFRhYmxlID0gbGF0Y2hUYWJsZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIGdldHMgdGhlIHRhYmxlIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGNoYXIgcGFzc2VkXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZ2V0VGFibGUodCkge1xuICAgICAgICAgICAgc3dpdGNoICh0KSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnTCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBUYWJsZS5MT1dFUjtcbiAgICAgICAgICAgICAgICBjYXNlICdQJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFRhYmxlLlBVTkNUO1xuICAgICAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gVGFibGUuTUlYRUQ7XG4gICAgICAgICAgICAgICAgY2FzZSAnRCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBUYWJsZS5ESUdJVDtcbiAgICAgICAgICAgICAgICBjYXNlICdCJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFRhYmxlLkJJTkFSWTtcbiAgICAgICAgICAgICAgICBjYXNlICdVJzpcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gVGFibGUuVVBQRVI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdldHMgdGhlIGNoYXJhY3RlciAob3Igc3RyaW5nKSBjb3JyZXNwb25kaW5nIHRvIHRoZSBwYXNzZWQgY29kZSBpbiB0aGUgZ2l2ZW4gdGFibGVcbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHRhYmxlIHRoZSB0YWJsZSB1c2VkXG4gICAgICAgICAqIEBwYXJhbSBjb2RlIHRoZSBjb2RlIG9mIHRoZSBjaGFyYWN0ZXJcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBnZXRDaGFyYWN0ZXIodGFibGUsIGNvZGUpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodGFibGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIFRhYmxlLlVQUEVSOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gRGVjb2Rlci5VUFBFUl9UQUJMRVtjb2RlXTtcbiAgICAgICAgICAgICAgICBjYXNlIFRhYmxlLkxPV0VSOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gRGVjb2Rlci5MT1dFUl9UQUJMRVtjb2RlXTtcbiAgICAgICAgICAgICAgICBjYXNlIFRhYmxlLk1JWEVEOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gRGVjb2Rlci5NSVhFRF9UQUJMRVtjb2RlXTtcbiAgICAgICAgICAgICAgICBjYXNlIFRhYmxlLlBVTkNUOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gRGVjb2Rlci5QVU5DVF9UQUJMRVtjb2RlXTtcbiAgICAgICAgICAgICAgICBjYXNlIFRhYmxlLkRJR0lUOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gRGVjb2Rlci5ESUdJVF9UQUJMRVtjb2RlXTtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAvLyBTaG91bGQgbm90IHJlYWNoIGhlcmUuXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oJ0JhZCB0YWJsZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5QZXJmb3JtcyBSUyBlcnJvciBjb3JyZWN0aW9uIG9uIGFuIGFycmF5IG9mIGJpdHMuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIHRoZSBjb3JyZWN0ZWQgYXJyYXlcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb24gaWYgdGhlIGlucHV0IGNvbnRhaW5zIHRvbyBtYW55IGVycm9yc1xuICAgICAgICAgKi9cbiAgICAgICAgY29ycmVjdEJpdHMocmF3Yml0cykge1xuICAgICAgICAgICAgbGV0IGdmO1xuICAgICAgICAgICAgbGV0IGNvZGV3b3JkU2l6ZTtcbiAgICAgICAgICAgIGlmICh0aGlzLmRkYXRhLmdldE5iTGF5ZXJzKCkgPD0gMikge1xuICAgICAgICAgICAgICAgIGNvZGV3b3JkU2l6ZSA9IDY7XG4gICAgICAgICAgICAgICAgZ2YgPSBHZW5lcmljR0YuQVpURUNfREFUQV82O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5kZGF0YS5nZXROYkxheWVycygpIDw9IDgpIHtcbiAgICAgICAgICAgICAgICBjb2Rld29yZFNpemUgPSA4O1xuICAgICAgICAgICAgICAgIGdmID0gR2VuZXJpY0dGLkFaVEVDX0RBVEFfODtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuZGRhdGEuZ2V0TmJMYXllcnMoKSA8PSAyMikge1xuICAgICAgICAgICAgICAgIGNvZGV3b3JkU2l6ZSA9IDEwO1xuICAgICAgICAgICAgICAgIGdmID0gR2VuZXJpY0dGLkFaVEVDX0RBVEFfMTA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb2Rld29yZFNpemUgPSAxMjtcbiAgICAgICAgICAgICAgICBnZiA9IEdlbmVyaWNHRi5BWlRFQ19EQVRBXzEyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IG51bURhdGFDb2Rld29yZHMgPSB0aGlzLmRkYXRhLmdldE5iRGF0YWJsb2NrcygpO1xuICAgICAgICAgICAgbGV0IG51bUNvZGV3b3JkcyA9IHJhd2JpdHMubGVuZ3RoIC8gY29kZXdvcmRTaXplO1xuICAgICAgICAgICAgaWYgKG51bUNvZGV3b3JkcyA8IG51bURhdGFDb2Rld29yZHMpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgb2Zmc2V0ID0gcmF3Yml0cy5sZW5ndGggJSBjb2Rld29yZFNpemU7XG4gICAgICAgICAgICBsZXQgZGF0YVdvcmRzID0gbmV3IEludDMyQXJyYXkobnVtQ29kZXdvcmRzKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtQ29kZXdvcmRzOyBpKyssIG9mZnNldCArPSBjb2Rld29yZFNpemUpIHtcbiAgICAgICAgICAgICAgICBkYXRhV29yZHNbaV0gPSBEZWNvZGVyLnJlYWRDb2RlKHJhd2JpdHMsIG9mZnNldCwgY29kZXdvcmRTaXplKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbGV0IHJzRGVjb2RlciA9IG5ldyBSZWVkU29sb21vbkRlY29kZXIoZ2YpO1xuICAgICAgICAgICAgICAgIHJzRGVjb2Rlci5kZWNvZGUoZGF0YVdvcmRzLCBudW1Db2Rld29yZHMgLSBudW1EYXRhQ29kZXdvcmRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChleCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gTm93IHBlcmZvcm0gdGhlIHVuc3R1ZmZpbmcgb3BlcmF0aW9uLlxuICAgICAgICAgICAgLy8gRmlyc3QsIGNvdW50IGhvdyBtYW55IGJpdHMgYXJlIGdvaW5nIHRvIGJlIHRocm93biBvdXQgYXMgc3R1ZmZpbmdcbiAgICAgICAgICAgIGxldCBtYXNrID0gKDEgPDwgY29kZXdvcmRTaXplKSAtIDE7XG4gICAgICAgICAgICBsZXQgc3R1ZmZlZEJpdHMgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1EYXRhQ29kZXdvcmRzOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgZGF0YVdvcmQgPSBkYXRhV29yZHNbaV07XG4gICAgICAgICAgICAgICAgaWYgKGRhdGFXb3JkID09PSAwIHx8IGRhdGFXb3JkID09PSBtYXNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZGF0YVdvcmQgPT09IDEgfHwgZGF0YVdvcmQgPT09IG1hc2sgLSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0dWZmZWRCaXRzKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gTm93LCBhY3R1YWxseSB1bnBhY2sgdGhlIGJpdHMgYW5kIHJlbW92ZSB0aGUgc3R1ZmZpbmdcbiAgICAgICAgICAgIGxldCBjb3JyZWN0ZWRCaXRzID0gbmV3IEFycmF5KG51bURhdGFDb2Rld29yZHMgKiBjb2Rld29yZFNpemUgLSBzdHVmZmVkQml0cyk7XG4gICAgICAgICAgICBsZXQgaW5kZXggPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1EYXRhQ29kZXdvcmRzOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgZGF0YVdvcmQgPSBkYXRhV29yZHNbaV07XG4gICAgICAgICAgICAgICAgaWYgKGRhdGFXb3JkID09PSAxIHx8IGRhdGFXb3JkID09PSBtYXNrIC0gMSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBuZXh0IGNvZGV3b3JkU2l6ZS0xIGJpdHMgYXJlIGFsbCB6ZXJvcyBvciBhbGwgb25lc1xuICAgICAgICAgICAgICAgICAgICBjb3JyZWN0ZWRCaXRzLmZpbGwoZGF0YVdvcmQgPiAxLCBpbmRleCwgaW5kZXggKyBjb2Rld29yZFNpemUgLSAxKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gQXJyYXlzLmZpbGwoY29ycmVjdGVkQml0cywgaW5kZXgsIGluZGV4ICsgY29kZXdvcmRTaXplIC0gMSwgZGF0YVdvcmQgPiAxKTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY29kZXdvcmRTaXplIC0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGJpdCA9IGNvZGV3b3JkU2l6ZSAtIDE7IGJpdCA+PSAwOyAtLWJpdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVjdGVkQml0c1tpbmRleCsrXSA9IChkYXRhV29yZCAmICgxIDw8IGJpdCkpICE9PSAwO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGNvcnJlY3RlZEJpdHM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdldHMgdGhlIGFycmF5IG9mIGJpdHMgZnJvbSBhbiBBenRlYyBDb2RlIG1hdHJpeFxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIHRoZSBhcnJheSBvZiBiaXRzXG4gICAgICAgICAqL1xuICAgICAgICBleHRyYWN0Qml0cyhtYXRyaXgpIHtcbiAgICAgICAgICAgIGxldCBjb21wYWN0ID0gdGhpcy5kZGF0YS5pc0NvbXBhY3QoKTtcbiAgICAgICAgICAgIGxldCBsYXllcnMgPSB0aGlzLmRkYXRhLmdldE5iTGF5ZXJzKCk7XG4gICAgICAgICAgICBsZXQgYmFzZU1hdHJpeFNpemUgPSAoY29tcGFjdCA/IDExIDogMTQpICsgbGF5ZXJzICogNDsgLy8gbm90IGluY2x1ZGluZyBhbGlnbm1lbnQgbGluZXNcbiAgICAgICAgICAgIGxldCBhbGlnbm1lbnRNYXAgPSBuZXcgSW50MzJBcnJheShiYXNlTWF0cml4U2l6ZSk7XG4gICAgICAgICAgICBsZXQgcmF3Yml0cyA9IG5ldyBBcnJheSh0aGlzLnRvdGFsQml0c0luTGF5ZXIobGF5ZXJzLCBjb21wYWN0KSk7XG4gICAgICAgICAgICBpZiAoY29tcGFjdCkge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYWxpZ25tZW50TWFwLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGFsaWdubWVudE1hcFtpXSA9IGk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbGV0IG1hdHJpeFNpemUgPSBiYXNlTWF0cml4U2l6ZSArIDEgKyAyICogSW50ZWdlci50cnVuY0RpdmlzaW9uKChJbnRlZ2VyLnRydW5jRGl2aXNpb24oYmFzZU1hdHJpeFNpemUsIDIpIC0gMSksIDE1KTtcbiAgICAgICAgICAgICAgICBsZXQgb3JpZ0NlbnRlciA9IGJhc2VNYXRyaXhTaXplIC8gMjtcbiAgICAgICAgICAgICAgICBsZXQgY2VudGVyID0gSW50ZWdlci50cnVuY0RpdmlzaW9uKG1hdHJpeFNpemUsIDIpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3JpZ0NlbnRlcjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBuZXdPZmZzZXQgPSBpICsgSW50ZWdlci50cnVuY0RpdmlzaW9uKGksIDE1KTtcbiAgICAgICAgICAgICAgICAgICAgYWxpZ25tZW50TWFwW29yaWdDZW50ZXIgLSBpIC0gMV0gPSBjZW50ZXIgLSBuZXdPZmZzZXQgLSAxO1xuICAgICAgICAgICAgICAgICAgICBhbGlnbm1lbnRNYXBbb3JpZ0NlbnRlciArIGldID0gY2VudGVyICsgbmV3T2Zmc2V0ICsgMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgcm93T2Zmc2V0ID0gMDsgaSA8IGxheWVyczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IHJvd1NpemUgPSAobGF5ZXJzIC0gaSkgKiA0ICsgKGNvbXBhY3QgPyA5IDogMTIpO1xuICAgICAgICAgICAgICAgIC8vIFRoZSB0b3AtbGVmdCBtb3N0IHBvaW50IG9mIHRoaXMgbGF5ZXIgaXMgPGxvdywgbG93PiAobm90IGluY2x1ZGluZyBhbGlnbm1lbnQgbGluZXMpXG4gICAgICAgICAgICAgICAgbGV0IGxvdyA9IGkgKiAyO1xuICAgICAgICAgICAgICAgIC8vIFRoZSBib3R0b20tcmlnaHQgbW9zdCBwb2ludCBvZiB0aGlzIGxheWVyIGlzIDxoaWdoLCBoaWdoPiAobm90IGluY2x1ZGluZyBhbGlnbm1lbnQgbGluZXMpXG4gICAgICAgICAgICAgICAgbGV0IGhpZ2ggPSBiYXNlTWF0cml4U2l6ZSAtIDEgLSBsb3c7XG4gICAgICAgICAgICAgICAgLy8gV2UgcHVsbCBiaXRzIGZyb20gdGhlIHR3byAyIHggcm93U2l6ZSBjb2x1bW5zIGFuZCB0d28gcm93U2l6ZSB4IDIgcm93c1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgcm93U2l6ZTsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBjb2x1bW5PZmZzZXQgPSBqICogMjtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCAyOyBrKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxlZnQgY29sdW1uXG4gICAgICAgICAgICAgICAgICAgICAgICByYXdiaXRzW3Jvd09mZnNldCArIGNvbHVtbk9mZnNldCArIGtdID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXguZ2V0KGFsaWdubWVudE1hcFtsb3cgKyBrXSwgYWxpZ25tZW50TWFwW2xvdyArIGpdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJvdHRvbSByb3dcbiAgICAgICAgICAgICAgICAgICAgICAgIHJhd2JpdHNbcm93T2Zmc2V0ICsgMiAqIHJvd1NpemUgKyBjb2x1bW5PZmZzZXQgKyBrXSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LmdldChhbGlnbm1lbnRNYXBbbG93ICsgal0sIGFsaWdubWVudE1hcFtoaWdoIC0ga10pO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmlnaHQgY29sdW1uXG4gICAgICAgICAgICAgICAgICAgICAgICByYXdiaXRzW3Jvd09mZnNldCArIDQgKiByb3dTaXplICsgY29sdW1uT2Zmc2V0ICsga10gPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdHJpeC5nZXQoYWxpZ25tZW50TWFwW2hpZ2ggLSBrXSwgYWxpZ25tZW50TWFwW2hpZ2ggLSBqXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0b3Agcm93XG4gICAgICAgICAgICAgICAgICAgICAgICByYXdiaXRzW3Jvd09mZnNldCArIDYgKiByb3dTaXplICsgY29sdW1uT2Zmc2V0ICsga10gPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdHJpeC5nZXQoYWxpZ25tZW50TWFwW2hpZ2ggLSBqXSwgYWxpZ25tZW50TWFwW2xvdyArIGtdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByb3dPZmZzZXQgKz0gcm93U2l6ZSAqIDg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmF3Yml0cztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogUmVhZHMgYSBjb2RlIG9mIGdpdmVuIGxlbmd0aCBhbmQgYXQgZ2l2ZW4gaW5kZXggaW4gYW4gYXJyYXkgb2YgYml0c1xuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIHJlYWRDb2RlKHJhd2JpdHMsIHN0YXJ0SW5kZXgsIGxlbmd0aCkge1xuICAgICAgICAgICAgbGV0IHJlcyA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gc3RhcnRJbmRleDsgaSA8IHN0YXJ0SW5kZXggKyBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHJlcyA8PD0gMTtcbiAgICAgICAgICAgICAgICBpZiAocmF3Yml0c1tpXSkge1xuICAgICAgICAgICAgICAgICAgICByZXMgfD0gMHgwMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZWFkcyBhIGNvZGUgb2YgbGVuZ3RoIDggaW4gYW4gYXJyYXkgb2YgYml0cywgcGFkZGluZyB3aXRoIHplcm9zXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgcmVhZEJ5dGUocmF3Yml0cywgc3RhcnRJbmRleCkge1xuICAgICAgICAgICAgbGV0IG4gPSByYXdiaXRzLmxlbmd0aCAtIHN0YXJ0SW5kZXg7XG4gICAgICAgICAgICBpZiAobiA+PSA4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIERlY29kZXIucmVhZENvZGUocmF3Yml0cywgc3RhcnRJbmRleCwgOCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gRGVjb2Rlci5yZWFkQ29kZShyYXdiaXRzLCBzdGFydEluZGV4LCBuKSA8PCAoOCAtIG4pO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQYWNrcyBhIGJpdCBhcnJheSBpbnRvIGJ5dGVzLCBtb3N0IHNpZ25pZmljYW50IGJpdCBmaXJzdFxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGNvbnZlcnRCb29sQXJyYXlUb0J5dGVBcnJheShib29sQXJyKSB7XG4gICAgICAgICAgICBsZXQgYnl0ZUFyciA9IG5ldyBVaW50OEFycmF5KChib29sQXJyLmxlbmd0aCArIDcpIC8gOCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJ5dGVBcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBieXRlQXJyW2ldID0gRGVjb2Rlci5yZWFkQnl0ZShib29sQXJyLCA4ICogaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYnl0ZUFycjtcbiAgICAgICAgfVxuICAgICAgICB0b3RhbEJpdHNJbkxheWVyKGxheWVycywgY29tcGFjdCkge1xuICAgICAgICAgICAgcmV0dXJuICgoY29tcGFjdCA/IDg4IDogMTEyKSArIDE2ICogbGF5ZXJzKSAqIGxheWVycztcbiAgICAgICAgfVxuICAgIH1cbiAgICBEZWNvZGVyLlVQUEVSX1RBQkxFID0gW1xuICAgICAgICAnQ1RSTF9QUycsICcgJywgJ0EnLCAnQicsICdDJywgJ0QnLCAnRScsICdGJywgJ0cnLCAnSCcsICdJJywgJ0onLCAnSycsICdMJywgJ00nLCAnTicsICdPJywgJ1AnLFxuICAgICAgICAnUScsICdSJywgJ1MnLCAnVCcsICdVJywgJ1YnLCAnVycsICdYJywgJ1knLCAnWicsICdDVFJMX0xMJywgJ0NUUkxfTUwnLCAnQ1RSTF9ETCcsICdDVFJMX0JTJ1xuICAgIF07XG4gICAgRGVjb2Rlci5MT1dFUl9UQUJMRSA9IFtcbiAgICAgICAgJ0NUUkxfUFMnLCAnICcsICdhJywgJ2InLCAnYycsICdkJywgJ2UnLCAnZicsICdnJywgJ2gnLCAnaScsICdqJywgJ2snLCAnbCcsICdtJywgJ24nLCAnbycsICdwJyxcbiAgICAgICAgJ3EnLCAncicsICdzJywgJ3QnLCAndScsICd2JywgJ3cnLCAneCcsICd5JywgJ3onLCAnQ1RSTF9VUycsICdDVFJMX01MJywgJ0NUUkxfREwnLCAnQ1RSTF9CUydcbiAgICBdO1xuICAgIERlY29kZXIuTUlYRURfVEFCTEUgPSBbXG4gICAgICAgIC8vIE1vZHVsZSBwYXJzZSBmYWlsZWQ6IE9jdGFsIGxpdGVyYWwgaW4gc3RyaWN0IG1vZGUgKDUwOjI5KVxuICAgICAgICAvLyBzbyBudW1iZXIgc3RyaW5nIHdlcmUgc2NhcGVkXG4gICAgICAgICdDVFJMX1BTJywgJyAnLCAnXFxcXDEnLCAnXFxcXDInLCAnXFxcXDMnLCAnXFxcXDQnLCAnXFxcXDUnLCAnXFxcXDYnLCAnXFxcXDcnLCAnXFxiJywgJ1xcdCcsICdcXG4nLFxuICAgICAgICAnXFxcXDEzJywgJ1xcZicsICdcXHInLCAnXFxcXDMzJywgJ1xcXFwzNCcsICdcXFxcMzUnLCAnXFxcXDM2JywgJ1xcXFwzNycsICdAJywgJ1xcXFwnLCAnXicsICdfJyxcbiAgICAgICAgJ2AnLCAnfCcsICd+JywgJ1xcXFwxNzcnLCAnQ1RSTF9MTCcsICdDVFJMX1VMJywgJ0NUUkxfUEwnLCAnQ1RSTF9CUydcbiAgICBdO1xuICAgIERlY29kZXIuUFVOQ1RfVEFCTEUgPSBbXG4gICAgICAgICcnLCAnXFxyJywgJ1xcclxcbicsICcuICcsICcsICcsICc6ICcsICchJywgJ1wiJywgJyMnLCAnJCcsICclJywgJyYnLCAnXFwnJywgJygnLCAnKScsXG4gICAgICAgICcqJywgJysnLCAnLCcsICctJywgJy4nLCAnLycsICc6JywgJzsnLCAnPCcsICc9JywgJz4nLCAnPycsICdbJywgJ10nLCAneycsICd9JywgJ0NUUkxfVUwnXG4gICAgXTtcbiAgICBEZWNvZGVyLkRJR0lUX1RBQkxFID0gW1xuICAgICAgICAnQ1RSTF9QUycsICcgJywgJzAnLCAnMScsICcyJywgJzMnLCAnNCcsICc1JywgJzYnLCAnNycsICc4JywgJzknLCAnLCcsICcuJywgJ0NUUkxfVUwnLCAnQ1RSTF9VUydcbiAgICBdO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAxMiBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKm5hbWVzcGFjZSBjb20uZ29vZ2xlLnp4aW5nLmNvbW1vbi5kZXRlY3RvciB7Ki9cbiAgICAvKipcbiAgICAgKiBHZW5lcmFsIG1hdGgtcmVsYXRlZCBhbmQgbnVtZXJpYyB1dGlsaXR5IGZ1bmN0aW9ucy5cbiAgICAgKi9cbiAgICBjbGFzcyBNYXRoVXRpbHMge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHsgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRW5kcyB1cCBiZWluZyBhIGJpdCBmYXN0ZXIgdGhhbiB7QGxpbmsgTWF0aCNyb3VuZChmbG9hdCl9LiBUaGlzIG1lcmVseSByb3VuZHMgaXRzXG4gICAgICAgICAqIGFyZ3VtZW50IHRvIHRoZSBuZWFyZXN0IGludCwgd2hlcmUgeC41IHJvdW5kcyB1cCB0byB4KzEuIFNlbWFudGljcyBvZiB0aGlzIHNob3J0Y3V0XG4gICAgICAgICAqIGRpZmZlciBzbGlnaHRseSBmcm9tIHtAbGluayBNYXRoI3JvdW5kKGZsb2F0KX0gaW4gdGhhdCBoYWxmIHJvdW5kcyBkb3duIGZvciBuZWdhdGl2ZVxuICAgICAgICAgKiB2YWx1ZXMuIC0yLjUgcm91bmRzIHRvIC0zLCBub3QgLTIuIEZvciBwdXJwb3NlcyBoZXJlIGl0IG1ha2VzIG5vIGRpZmZlcmVuY2UuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBkIHJlYWwgdmFsdWUgdG8gcm91bmRcbiAgICAgICAgICogQHJldHVybiBuZWFyZXN0IHtAY29kZSBpbnR9XG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgcm91bmQoZCAvKmZsb2F0Ki8pIHtcbiAgICAgICAgICAgIGlmIChOYU4gPT09IGQpXG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICBpZiAoZCA8PSBOdW1iZXIuTUlOX1NBRkVfSU5URUdFUilcbiAgICAgICAgICAgICAgICByZXR1cm4gTnVtYmVyLk1JTl9TQUZFX0lOVEVHRVI7XG4gICAgICAgICAgICBpZiAoZCA+PSBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUilcbiAgICAgICAgICAgICAgICByZXR1cm4gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVI7XG4gICAgICAgICAgICByZXR1cm4gLyooaW50KSAqLyAoZCArIChkIDwgMC4wID8gLTAuNSA6IDAuNSkpIHwgMDtcbiAgICAgICAgfVxuICAgICAgICAvLyBUWVBFU0NSSVBUUE9SVDogbWF5YmUgcmVtb3ZlIHJvdW5kIG1ldGhvZCBhbmQgY2FsbCBkaXJlY3RseSBNYXRoLnJvdW5kLCBpdCBsb29rcyBsaWtlIGl0IGRvZXNuJ3QgbWFrZSBzZW5zZSBmb3IganNcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBhWCBwb2ludCBBIHggY29vcmRpbmF0ZVxuICAgICAgICAgKiBAcGFyYW0gYVkgcG9pbnQgQSB5IGNvb3JkaW5hdGVcbiAgICAgICAgICogQHBhcmFtIGJYIHBvaW50IEIgeCBjb29yZGluYXRlXG4gICAgICAgICAqIEBwYXJhbSBiWSBwb2ludCBCIHkgY29vcmRpbmF0ZVxuICAgICAgICAgKiBAcmV0dXJuIEV1Y2xpZGVhbiBkaXN0YW5jZSBiZXR3ZWVuIHBvaW50cyBBIGFuZCBCXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGlzdGFuY2UoYVggLypmbG9hdHxpbnQqLywgYVkgLypmbG9hdHxpbnQqLywgYlggLypmbG9hdHxpbnQqLywgYlkgLypmbG9hdHxpbnQqLykge1xuICAgICAgICAgICAgY29uc3QgeERpZmYgPSBhWCAtIGJYO1xuICAgICAgICAgICAgY29uc3QgeURpZmYgPSBhWSAtIGJZO1xuICAgICAgICAgICAgcmV0dXJuIC8qKGZsb2F0KSAqLyBNYXRoLnNxcnQoeERpZmYgKiB4RGlmZiArIHlEaWZmICogeURpZmYpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gYVggcG9pbnQgQSB4IGNvb3JkaW5hdGVcbiAgICAgICAgICogQHBhcmFtIGFZIHBvaW50IEEgeSBjb29yZGluYXRlXG4gICAgICAgICAqIEBwYXJhbSBiWCBwb2ludCBCIHggY29vcmRpbmF0ZVxuICAgICAgICAgKiBAcGFyYW0gYlkgcG9pbnQgQiB5IGNvb3JkaW5hdGVcbiAgICAgICAgICogQHJldHVybiBFdWNsaWRlYW4gZGlzdGFuY2UgYmV0d2VlbiBwb2ludHMgQSBhbmQgQlxuICAgICAgICAgKi9cbiAgICAgICAgLy8gcHVibGljIHN0YXRpYyBkaXN0YW5jZShhWDogbnVtYmVyIC8qaW50Ki8sIGFZOiBudW1iZXIgLyppbnQqLywgYlg6IG51bWJlciAvKmludCovLCBiWTogbnVtYmVyIC8qaW50Ki8pOiBmbG9hdCB7XG4gICAgICAgIC8vICAgY29uc3QgeERpZmYgPSBhWCAtIGJYXG4gICAgICAgIC8vICAgY29uc3QgeURpZmYgPSBhWSAtIGJZXG4gICAgICAgIC8vICAgcmV0dXJuIChmbG9hdCkgTWF0aC5zcXJ0KHhEaWZmICogeERpZmYgKyB5RGlmZiAqIHlEaWZmKTtcbiAgICAgICAgLy8gfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIGFycmF5IHZhbHVlcyB0byBzdW1cbiAgICAgICAgICogQHJldHVybiBzdW0gb2YgdmFsdWVzIGluIGFycmF5XG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgc3VtKGFycmF5KSB7XG4gICAgICAgICAgICBsZXQgY291bnQgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDsgaSAhPT0gbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBhID0gYXJyYXlbaV07XG4gICAgICAgICAgICAgICAgY291bnQgKz0gYTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBjb3VudDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBvbnlmaWxsIGZvciBKYXZhJ3MgRmxvYXQgY2xhc3MuXG4gICAgICovXG4gICAgY2xhc3MgRmxvYXQge1xuICAgICAgICAvKipcbiAgICAgICAgICogU2luY1RTIGhhcyBubyBkaWZmZXJlbmNlIGJldHdlZW4gaW50IGFuZCBmbG9hdCwgdGhlcmUncyBhbGwgbnVtYmVycyxcbiAgICAgICAgICogdGhpcyBpcyB1c2VkIG9ubHkgdG8gcG9seWZpbGwgSmF2YSBjb2RlLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGZsb2F0VG9JbnRCaXRzKGYpIHtcbiAgICAgICAgICAgIHJldHVybiBmO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoZSBmbG9hdCBtYXggdmFsdWUgaW4gSlMgaXMgdGhlIG51bWJlciBtYXggdmFsdWUuXG4gICAgICovXG4gICAgRmxvYXQuTUFYX1ZBTFVFID0gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVI7XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIDxwPkVuY2Fwc3VsYXRlcyBhIHBvaW50IG9mIGludGVyZXN0IGluIGFuIGltYWdlIGNvbnRhaW5pbmcgYSBiYXJjb2RlLiBUeXBpY2FsbHksIHRoaXNcbiAgICAgKiB3b3VsZCBiZSB0aGUgbG9jYXRpb24gb2YgYSBmaW5kZXIgcGF0dGVybiBvciB0aGUgY29ybmVyIG9mIHRoZSBiYXJjb2RlLCBmb3IgZXhhbXBsZS48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIFJlc3VsdFBvaW50IHtcbiAgICAgICAgY29uc3RydWN0b3IoeCwgeSkge1xuICAgICAgICAgICAgdGhpcy54ID0geDtcbiAgICAgICAgICAgIHRoaXMueSA9IHk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0WCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLng7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0WSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnk7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBlcXVhbHMob3RoZXIpIHtcbiAgICAgICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIFJlc3VsdFBvaW50KSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgb3RoZXJQb2ludCA9IG90aGVyO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnggPT09IG90aGVyUG9pbnQueCAmJiB0aGlzLnkgPT09IG90aGVyUG9pbnQueTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGhhc2hDb2RlKCkge1xuICAgICAgICAgICAgcmV0dXJuIDMxICogRmxvYXQuZmxvYXRUb0ludEJpdHModGhpcy54KSArIEZsb2F0LmZsb2F0VG9JbnRCaXRzKHRoaXMueSk7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICB0b1N0cmluZygpIHtcbiAgICAgICAgICAgIHJldHVybiAnKCcgKyB0aGlzLnggKyAnLCcgKyB0aGlzLnkgKyAnKSc7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE9yZGVycyBhbiBhcnJheSBvZiB0aHJlZSBSZXN1bHRQb2ludHMgaW4gYW4gb3JkZXIgW0EsQixDXSBzdWNoIHRoYXQgQUIgaXMgbGVzcyB0aGFuIEFDXG4gICAgICAgICAqIGFuZCBCQyBpcyBsZXNzIHRoYW4gQUMsIGFuZCB0aGUgYW5nbGUgYmV0d2VlbiBCQyBhbmQgQkEgaXMgbGVzcyB0aGFuIDE4MCBkZWdyZWVzLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gcGF0dGVybnMgYXJyYXkgb2YgdGhyZWUge0Bjb2RlIFJlc3VsdFBvaW50fSB0byBvcmRlclxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIG9yZGVyQmVzdFBhdHRlcm5zKHBhdHRlcm5zKSB7XG4gICAgICAgICAgICAvLyBGaW5kIGRpc3RhbmNlcyBiZXR3ZWVuIHBhdHRlcm4gY2VudGVyc1xuICAgICAgICAgICAgY29uc3QgemVyb09uZURpc3RhbmNlID0gdGhpcy5kaXN0YW5jZShwYXR0ZXJuc1swXSwgcGF0dGVybnNbMV0pO1xuICAgICAgICAgICAgY29uc3Qgb25lVHdvRGlzdGFuY2UgPSB0aGlzLmRpc3RhbmNlKHBhdHRlcm5zWzFdLCBwYXR0ZXJuc1syXSk7XG4gICAgICAgICAgICBjb25zdCB6ZXJvVHdvRGlzdGFuY2UgPSB0aGlzLmRpc3RhbmNlKHBhdHRlcm5zWzBdLCBwYXR0ZXJuc1syXSk7XG4gICAgICAgICAgICBsZXQgcG9pbnRBO1xuICAgICAgICAgICAgbGV0IHBvaW50QjtcbiAgICAgICAgICAgIGxldCBwb2ludEM7XG4gICAgICAgICAgICAvLyBBc3N1bWUgb25lIGNsb3Nlc3QgdG8gb3RoZXIgdHdvIGlzIEI7IEEgYW5kIEMgd2lsbCBqdXN0IGJlIGd1ZXNzZXMgYXQgZmlyc3RcbiAgICAgICAgICAgIGlmIChvbmVUd29EaXN0YW5jZSA+PSB6ZXJvT25lRGlzdGFuY2UgJiYgb25lVHdvRGlzdGFuY2UgPj0gemVyb1R3b0Rpc3RhbmNlKSB7XG4gICAgICAgICAgICAgICAgcG9pbnRCID0gcGF0dGVybnNbMF07XG4gICAgICAgICAgICAgICAgcG9pbnRBID0gcGF0dGVybnNbMV07XG4gICAgICAgICAgICAgICAgcG9pbnRDID0gcGF0dGVybnNbMl07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh6ZXJvVHdvRGlzdGFuY2UgPj0gb25lVHdvRGlzdGFuY2UgJiYgemVyb1R3b0Rpc3RhbmNlID49IHplcm9PbmVEaXN0YW5jZSkge1xuICAgICAgICAgICAgICAgIHBvaW50QiA9IHBhdHRlcm5zWzFdO1xuICAgICAgICAgICAgICAgIHBvaW50QSA9IHBhdHRlcm5zWzBdO1xuICAgICAgICAgICAgICAgIHBvaW50QyA9IHBhdHRlcm5zWzJdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcG9pbnRCID0gcGF0dGVybnNbMl07XG4gICAgICAgICAgICAgICAgcG9pbnRBID0gcGF0dGVybnNbMF07XG4gICAgICAgICAgICAgICAgcG9pbnRDID0gcGF0dGVybnNbMV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBVc2UgY3Jvc3MgcHJvZHVjdCB0byBmaWd1cmUgb3V0IHdoZXRoZXIgQSBhbmQgQyBhcmUgY29ycmVjdCBvciBmbGlwcGVkLlxuICAgICAgICAgICAgLy8gVGhpcyBhc2tzIHdoZXRoZXIgQkMgeCBCQSBoYXMgYSBwb3NpdGl2ZSB6IGNvbXBvbmVudCwgd2hpY2ggaXMgdGhlIGFycmFuZ2VtZW50XG4gICAgICAgICAgICAvLyB3ZSB3YW50IGZvciBBLCBCLCBDLiBJZiBpdCdzIG5lZ2F0aXZlLCB0aGVuIHdlJ3ZlIGdvdCBpdCBmbGlwcGVkIGFyb3VuZCBhbmRcbiAgICAgICAgICAgIC8vIHNob3VsZCBzd2FwIEEgYW5kIEMuXG4gICAgICAgICAgICBpZiAodGhpcy5jcm9zc1Byb2R1Y3RaKHBvaW50QSwgcG9pbnRCLCBwb2ludEMpIDwgMC4wKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdGVtcCA9IHBvaW50QTtcbiAgICAgICAgICAgICAgICBwb2ludEEgPSBwb2ludEM7XG4gICAgICAgICAgICAgICAgcG9pbnRDID0gdGVtcDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBhdHRlcm5zWzBdID0gcG9pbnRBO1xuICAgICAgICAgICAgcGF0dGVybnNbMV0gPSBwb2ludEI7XG4gICAgICAgICAgICBwYXR0ZXJuc1syXSA9IHBvaW50QztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHBhdHRlcm4xIGZpcnN0IHBhdHRlcm5cbiAgICAgICAgICogQHBhcmFtIHBhdHRlcm4yIHNlY29uZCBwYXR0ZXJuXG4gICAgICAgICAqIEByZXR1cm4gZGlzdGFuY2UgYmV0d2VlbiB0d28gcG9pbnRzXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGlzdGFuY2UocGF0dGVybjEsIHBhdHRlcm4yKSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aFV0aWxzLmRpc3RhbmNlKHBhdHRlcm4xLngsIHBhdHRlcm4xLnksIHBhdHRlcm4yLngsIHBhdHRlcm4yLnkpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXR1cm5zIHRoZSB6IGNvbXBvbmVudCBvZiB0aGUgY3Jvc3MgcHJvZHVjdCBiZXR3ZWVuIHZlY3RvcnMgQkMgYW5kIEJBLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGNyb3NzUHJvZHVjdFoocG9pbnRBLCBwb2ludEIsIHBvaW50Qykge1xuICAgICAgICAgICAgY29uc3QgYlggPSBwb2ludEIueDtcbiAgICAgICAgICAgIGNvbnN0IGJZID0gcG9pbnRCLnk7XG4gICAgICAgICAgICByZXR1cm4gKChwb2ludEMueCAtIGJYKSAqIChwb2ludEEueSAtIGJZKSkgLSAoKHBvaW50Qy55IC0gYlkpICogKHBvaW50QS54IC0gYlgpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogPHA+RW5jYXBzdWxhdGVzIHRoZSByZXN1bHQgb2YgZGV0ZWN0aW5nIGEgYmFyY29kZSBpbiBhbiBpbWFnZS4gVGhpcyBpbmNsdWRlcyB0aGUgcmF3XG4gICAgICogbWF0cml4IG9mIGJsYWNrL3doaXRlIHBpeGVscyBjb3JyZXNwb25kaW5nIHRvIHRoZSBiYXJjb2RlLCBhbmQgcG9zc2libHkgcG9pbnRzIG9mIGludGVyZXN0XG4gICAgICogaW4gdGhlIGltYWdlLCBsaWtlIHRoZSBsb2NhdGlvbiBvZiBmaW5kZXIgcGF0dGVybnMgb3IgY29ybmVycyBvZiB0aGUgYmFyY29kZSBpbiB0aGUgaW1hZ2UuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBEZXRlY3RvclJlc3VsdCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGJpdHMsIHBvaW50cykge1xuICAgICAgICAgICAgdGhpcy5iaXRzID0gYml0cztcbiAgICAgICAgICAgIHRoaXMucG9pbnRzID0gcG9pbnRzO1xuICAgICAgICB9XG4gICAgICAgIGdldEJpdHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5iaXRzO1xuICAgICAgICB9XG4gICAgICAgIGdldFBvaW50cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBvaW50cztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMTAgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogPHA+RXh0ZW5kcyB7QGxpbmsgRGV0ZWN0b3JSZXN1bHR9IHdpdGggbW9yZSBpbmZvcm1hdGlvbiBzcGVjaWZpYyB0byB0aGUgQXp0ZWMgZm9ybWF0LFxuICAgICAqIGxpa2UgdGhlIG51bWJlciBvZiBsYXllcnMgYW5kIHdoZXRoZXIgaXQncyBjb21wYWN0LjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgQXp0ZWNEZXRlY3RvclJlc3VsdCBleHRlbmRzIERldGVjdG9yUmVzdWx0IHtcbiAgICAgICAgY29uc3RydWN0b3IoYml0cywgcG9pbnRzLCBjb21wYWN0LCBuYkRhdGFibG9ja3MsIG5iTGF5ZXJzKSB7XG4gICAgICAgICAgICBzdXBlcihiaXRzLCBwb2ludHMpO1xuICAgICAgICAgICAgdGhpcy5jb21wYWN0ID0gY29tcGFjdDtcbiAgICAgICAgICAgIHRoaXMubmJEYXRhYmxvY2tzID0gbmJEYXRhYmxvY2tzO1xuICAgICAgICAgICAgdGhpcy5uYkxheWVycyA9IG5iTGF5ZXJzO1xuICAgICAgICB9XG4gICAgICAgIGdldE5iTGF5ZXJzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubmJMYXllcnM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0TmJEYXRhYmxvY2tzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubmJEYXRhYmxvY2tzO1xuICAgICAgICB9XG4gICAgICAgIGlzQ29tcGFjdCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbXBhY3Q7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDEwIFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIDxwPlxuICAgICAqIERldGVjdHMgYSBjYW5kaWRhdGUgYmFyY29kZS1saWtlIHJlY3Rhbmd1bGFyIHJlZ2lvbiB3aXRoaW4gYW4gaW1hZ2UuIEl0XG4gICAgICogc3RhcnRzIGFyb3VuZCB0aGUgY2VudGVyIG9mIHRoZSBpbWFnZSwgaW5jcmVhc2VzIHRoZSBzaXplIG9mIHRoZSBjYW5kaWRhdGVcbiAgICAgKiByZWdpb24gdW50aWwgaXQgZmluZHMgYSB3aGl0ZSByZWN0YW5ndWxhciByZWdpb24uIEJ5IGtlZXBpbmcgdHJhY2sgb2YgdGhlXG4gICAgICogbGFzdCBibGFjayBwb2ludHMgaXQgZW5jb3VudGVyZWQsIGl0IGRldGVybWluZXMgdGhlIGNvcm5lcnMgb2YgdGhlIGJhcmNvZGUuXG4gICAgICogPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBEYXZpZCBPbGl2aWVyXG4gICAgICovXG4gICAgY2xhc3MgV2hpdGVSZWN0YW5nbGVEZXRlY3RvciB7XG4gICAgICAgIC8vIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIGltYWdlOiBCaXRNYXRyaXgpIC8qdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uKi8ge1xuICAgICAgICAvLyAgIHRoaXMoaW1hZ2UsIElOSVRfU0laRSwgaW1hZ2UuZ2V0V2lkdGgoKSAvIDIsIGltYWdlLmdldEhlaWdodCgpIC8gMilcbiAgICAgICAgLy8gfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIGltYWdlIGJhcmNvZGUgaW1hZ2UgdG8gZmluZCBhIHJlY3RhbmdsZSBpblxuICAgICAgICAgKiBAcGFyYW0gaW5pdFNpemUgaW5pdGlhbCBzaXplIG9mIHNlYXJjaCBhcmVhIGFyb3VuZCBjZW50ZXJcbiAgICAgICAgICogQHBhcmFtIHggeCBwb3NpdGlvbiBvZiBzZWFyY2ggY2VudGVyXG4gICAgICAgICAqIEBwYXJhbSB5IHkgcG9zaXRpb24gb2Ygc2VhcmNoIGNlbnRlclxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIGltYWdlIGlzIHRvbyBzbWFsbCB0byBhY2NvbW1vZGF0ZSB7QGNvZGUgaW5pdFNpemV9XG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3RvcihpbWFnZSwgaW5pdFNpemUgLyppbnQqLywgeCAvKmludCovLCB5IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHRoaXMuaW1hZ2UgPSBpbWFnZTtcbiAgICAgICAgICAgIHRoaXMuaGVpZ2h0ID0gaW1hZ2UuZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICB0aGlzLndpZHRoID0gaW1hZ2UuZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IGluaXRTaXplIHx8IG51bGwgPT09IGluaXRTaXplKSB7XG4gICAgICAgICAgICAgICAgaW5pdFNpemUgPSBXaGl0ZVJlY3RhbmdsZURldGVjdG9yLklOSVRfU0laRTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IHggfHwgbnVsbCA9PT0geCkge1xuICAgICAgICAgICAgICAgIHggPSBpbWFnZS5nZXRXaWR0aCgpIC8gMiB8IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodW5kZWZpbmVkID09PSB5IHx8IG51bGwgPT09IHkpIHtcbiAgICAgICAgICAgICAgICB5ID0gaW1hZ2UuZ2V0SGVpZ2h0KCkgLyAyIHwgMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGhhbGZzaXplID0gaW5pdFNpemUgLyAyIHwgMDtcbiAgICAgICAgICAgIHRoaXMubGVmdEluaXQgPSB4IC0gaGFsZnNpemU7XG4gICAgICAgICAgICB0aGlzLnJpZ2h0SW5pdCA9IHggKyBoYWxmc2l6ZTtcbiAgICAgICAgICAgIHRoaXMudXBJbml0ID0geSAtIGhhbGZzaXplO1xuICAgICAgICAgICAgdGhpcy5kb3duSW5pdCA9IHkgKyBoYWxmc2l6ZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnVwSW5pdCA8IDAgfHwgdGhpcy5sZWZ0SW5pdCA8IDAgfHwgdGhpcy5kb3duSW5pdCA+PSB0aGlzLmhlaWdodCB8fCB0aGlzLnJpZ2h0SW5pdCA+PSB0aGlzLndpZHRoKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPlxuICAgICAgICAgKiBEZXRlY3RzIGEgY2FuZGlkYXRlIGJhcmNvZGUtbGlrZSByZWN0YW5ndWxhciByZWdpb24gd2l0aGluIGFuIGltYWdlLiBJdFxuICAgICAgICAgKiBzdGFydHMgYXJvdW5kIHRoZSBjZW50ZXIgb2YgdGhlIGltYWdlLCBpbmNyZWFzZXMgdGhlIHNpemUgb2YgdGhlIGNhbmRpZGF0ZVxuICAgICAgICAgKiByZWdpb24gdW50aWwgaXQgZmluZHMgYSB3aGl0ZSByZWN0YW5ndWxhciByZWdpb24uXG4gICAgICAgICAqIDwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiB7QGxpbmsgUmVzdWx0UG9pbnR9W10gZGVzY3JpYmluZyB0aGUgY29ybmVycyBvZiB0aGUgcmVjdGFuZ3VsYXJcbiAgICAgICAgICogICAgICAgICByZWdpb24uIFRoZSBmaXJzdCBhbmQgbGFzdCBwb2ludHMgYXJlIG9wcG9zZWQgb24gdGhlIGRpYWdvbmFsLCBhc1xuICAgICAgICAgKiAgICAgICAgIGFyZSB0aGUgc2Vjb25kIGFuZCB0aGlyZC4gVGhlIGZpcnN0IHBvaW50IHdpbGwgYmUgdGhlIHRvcG1vc3RcbiAgICAgICAgICogICAgICAgICBwb2ludCBhbmQgdGhlIGxhc3QsIHRoZSBib3R0b21tb3N0LiBUaGUgc2Vjb25kIHBvaW50IHdpbGwgYmVcbiAgICAgICAgICogICAgICAgICBsZWZ0bW9zdCBhbmQgdGhlIHRoaXJkLCB0aGUgcmlnaHRtb3N0XG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gaWYgbm8gRGF0YSBNYXRyaXggQ29kZSBjYW4gYmUgZm91bmRcbiAgICAgICAgICovXG4gICAgICAgIGRldGVjdCgpIHtcbiAgICAgICAgICAgIGxldCBsZWZ0ID0gdGhpcy5sZWZ0SW5pdDtcbiAgICAgICAgICAgIGxldCByaWdodCA9IHRoaXMucmlnaHRJbml0O1xuICAgICAgICAgICAgbGV0IHVwID0gdGhpcy51cEluaXQ7XG4gICAgICAgICAgICBsZXQgZG93biA9IHRoaXMuZG93bkluaXQ7XG4gICAgICAgICAgICBsZXQgc2l6ZUV4Y2VlZGVkID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgYUJsYWNrUG9pbnRGb3VuZE9uQm9yZGVyID0gdHJ1ZTtcbiAgICAgICAgICAgIGxldCBhdExlYXN0T25lQmxhY2tQb2ludEZvdW5kT25Cb3JkZXIgPSBmYWxzZTtcbiAgICAgICAgICAgIGxldCBhdExlYXN0T25lQmxhY2tQb2ludEZvdW5kT25SaWdodCA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPbkJvdHRvbSA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPbkxlZnQgPSBmYWxzZTtcbiAgICAgICAgICAgIGxldCBhdExlYXN0T25lQmxhY2tQb2ludEZvdW5kT25Ub3AgPSBmYWxzZTtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy53aWR0aDtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuaGVpZ2h0O1xuICAgICAgICAgICAgd2hpbGUgKGFCbGFja1BvaW50Rm91bmRPbkJvcmRlcikge1xuICAgICAgICAgICAgICAgIGFCbGFja1BvaW50Rm91bmRPbkJvcmRlciA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIC8vIC4uLi4uXG4gICAgICAgICAgICAgICAgLy8gLiAgIHxcbiAgICAgICAgICAgICAgICAvLyAuLi4uLlxuICAgICAgICAgICAgICAgIGxldCByaWdodEJvcmRlck5vdFdoaXRlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB3aGlsZSAoKHJpZ2h0Qm9yZGVyTm90V2hpdGUgfHwgIWF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPblJpZ2h0KSAmJiByaWdodCA8IHdpZHRoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0Qm9yZGVyTm90V2hpdGUgPSB0aGlzLmNvbnRhaW5zQmxhY2tQb2ludCh1cCwgZG93biwgcmlnaHQsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Qm9yZGVyTm90V2hpdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBhQmxhY2tQb2ludEZvdW5kT25Cb3JkZXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXRMZWFzdE9uZUJsYWNrUG9pbnRGb3VuZE9uUmlnaHQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFhdExlYXN0T25lQmxhY2tQb2ludEZvdW5kT25SaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocmlnaHQgPj0gd2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2l6ZUV4Y2VlZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIC4uLi4uXG4gICAgICAgICAgICAgICAgLy8gLiAgIC5cbiAgICAgICAgICAgICAgICAvLyAuX19fLlxuICAgICAgICAgICAgICAgIGxldCBib3R0b21Cb3JkZXJOb3RXaGl0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgd2hpbGUgKChib3R0b21Cb3JkZXJOb3RXaGl0ZSB8fCAhYXRMZWFzdE9uZUJsYWNrUG9pbnRGb3VuZE9uQm90dG9tKSAmJiBkb3duIDwgaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIGJvdHRvbUJvcmRlck5vdFdoaXRlID0gdGhpcy5jb250YWluc0JsYWNrUG9pbnQobGVmdCwgcmlnaHQsIGRvd24sIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoYm90dG9tQm9yZGVyTm90V2hpdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvd24rKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGFCbGFja1BvaW50Rm91bmRPbkJvcmRlciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBhdExlYXN0T25lQmxhY2tQb2ludEZvdW5kT25Cb3R0b20gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFhdExlYXN0T25lQmxhY2tQb2ludEZvdW5kT25Cb3R0b20pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvd24rKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZG93biA+PSBoZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgc2l6ZUV4Y2VlZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIC4uLi4uXG4gICAgICAgICAgICAgICAgLy8gfCAgIC5cbiAgICAgICAgICAgICAgICAvLyAuLi4uLlxuICAgICAgICAgICAgICAgIGxldCBsZWZ0Qm9yZGVyTm90V2hpdGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHdoaWxlICgobGVmdEJvcmRlck5vdFdoaXRlIHx8ICFhdExlYXN0T25lQmxhY2tQb2ludEZvdW5kT25MZWZ0KSAmJiBsZWZ0ID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgbGVmdEJvcmRlck5vdFdoaXRlID0gdGhpcy5jb250YWluc0JsYWNrUG9pbnQodXAsIGRvd24sIGxlZnQsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxlZnRCb3JkZXJOb3RXaGl0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdC0tO1xuICAgICAgICAgICAgICAgICAgICAgICAgYUJsYWNrUG9pbnRGb3VuZE9uQm9yZGVyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPbkxlZnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFhdExlYXN0T25lQmxhY2tQb2ludEZvdW5kT25MZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0LS07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGxlZnQgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpemVFeGNlZWRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyAuX19fLlxuICAgICAgICAgICAgICAgIC8vIC4gICAuXG4gICAgICAgICAgICAgICAgLy8gLi4uLi5cbiAgICAgICAgICAgICAgICBsZXQgdG9wQm9yZGVyTm90V2hpdGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHdoaWxlICgodG9wQm9yZGVyTm90V2hpdGUgfHwgIWF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPblRvcCkgJiYgdXAgPj0gMCkge1xuICAgICAgICAgICAgICAgICAgICB0b3BCb3JkZXJOb3RXaGl0ZSA9IHRoaXMuY29udGFpbnNCbGFja1BvaW50KGxlZnQsIHJpZ2h0LCB1cCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0b3BCb3JkZXJOb3RXaGl0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdXAtLTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFCbGFja1BvaW50Rm91bmRPbkJvcmRlciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBhdExlYXN0T25lQmxhY2tQb2ludEZvdW5kT25Ub3AgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFhdExlYXN0T25lQmxhY2tQb2ludEZvdW5kT25Ub3ApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHVwLS07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHVwIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICBzaXplRXhjZWVkZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGFCbGFja1BvaW50Rm91bmRPbkJvcmRlcikge1xuICAgICAgICAgICAgICAgICAgICBhdExlYXN0T25lQmxhY2tQb2ludEZvdW5kT25Cb3JkZXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghc2l6ZUV4Y2VlZGVkICYmIGF0TGVhc3RPbmVCbGFja1BvaW50Rm91bmRPbkJvcmRlcikge1xuICAgICAgICAgICAgICAgIGNvbnN0IG1heFNpemUgPSByaWdodCAtIGxlZnQ7XG4gICAgICAgICAgICAgICAgbGV0IHogPSBudWxsO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAxOyB6ID09PSBudWxsICYmIGkgPCBtYXhTaXplOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgeiA9IHRoaXMuZ2V0QmxhY2tQb2ludE9uU2VnbWVudChsZWZ0LCBkb3duIC0gaSwgbGVmdCArIGksIGRvd24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoeiA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgdCA9IG51bGw7XG4gICAgICAgICAgICAgICAgLy8gZ28gZG93biByaWdodFxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAxOyB0ID09PSBudWxsICYmIGkgPCBtYXhTaXplOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdCA9IHRoaXMuZ2V0QmxhY2tQb2ludE9uU2VnbWVudChsZWZ0LCB1cCArIGksIGxlZnQgKyBpLCB1cCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCB4ID0gbnVsbDtcbiAgICAgICAgICAgICAgICAvLyBnbyBkb3duIGxlZnRcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMTsgeCA9PT0gbnVsbCAmJiBpIDwgbWF4U2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHggPSB0aGlzLmdldEJsYWNrUG9pbnRPblNlZ21lbnQocmlnaHQsIHVwICsgaSwgcmlnaHQgLSBpLCB1cCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh4ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCB5ID0gbnVsbDtcbiAgICAgICAgICAgICAgICAvLyBnbyB1cCBsZWZ0XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDE7IHkgPT09IG51bGwgJiYgaSA8IG1heFNpemU7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB5ID0gdGhpcy5nZXRCbGFja1BvaW50T25TZWdtZW50KHJpZ2h0LCBkb3duIC0gaSwgcmlnaHQgLSBpLCBkb3duKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2VudGVyRWRnZXMoeSwgeiwgeCwgdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBnZXRCbGFja1BvaW50T25TZWdtZW50KGFYIC8qZmxvYXQqLywgYVkgLypmbG9hdCovLCBiWCAvKmZsb2F0Ki8sIGJZIC8qZmxvYXQqLykge1xuICAgICAgICAgICAgY29uc3QgZGlzdCA9IE1hdGhVdGlscy5yb3VuZChNYXRoVXRpbHMuZGlzdGFuY2UoYVgsIGFZLCBiWCwgYlkpKTtcbiAgICAgICAgICAgIGNvbnN0IHhTdGVwID0gKGJYIC0gYVgpIC8gZGlzdDtcbiAgICAgICAgICAgIGNvbnN0IHlTdGVwID0gKGJZIC0gYVkpIC8gZGlzdDtcbiAgICAgICAgICAgIGNvbnN0IGltYWdlID0gdGhpcy5pbWFnZTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGlzdDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgeCA9IE1hdGhVdGlscy5yb3VuZChhWCArIGkgKiB4U3RlcCk7XG4gICAgICAgICAgICAgICAgY29uc3QgeSA9IE1hdGhVdGlscy5yb3VuZChhWSArIGkgKiB5U3RlcCk7XG4gICAgICAgICAgICAgICAgaWYgKGltYWdlLmdldCh4LCB5KSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFJlc3VsdFBvaW50KHgsIHkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiByZWNlbnRlcnMgdGhlIHBvaW50cyBvZiBhIGNvbnN0YW50IGRpc3RhbmNlIHRvd2FyZHMgdGhlIGNlbnRlclxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0geSBib3R0b20gbW9zdCBwb2ludFxuICAgICAgICAgKiBAcGFyYW0geiBsZWZ0IG1vc3QgcG9pbnRcbiAgICAgICAgICogQHBhcmFtIHggcmlnaHQgbW9zdCBwb2ludFxuICAgICAgICAgKiBAcGFyYW0gdCB0b3AgbW9zdCBwb2ludFxuICAgICAgICAgKiBAcmV0dXJuIHtAbGluayBSZXN1bHRQb2ludH1bXSBkZXNjcmliaW5nIHRoZSBjb3JuZXJzIG9mIHRoZSByZWN0YW5ndWxhclxuICAgICAgICAgKiAgICAgICAgIHJlZ2lvbi4gVGhlIGZpcnN0IGFuZCBsYXN0IHBvaW50cyBhcmUgb3Bwb3NlZCBvbiB0aGUgZGlhZ29uYWwsIGFzXG4gICAgICAgICAqICAgICAgICAgYXJlIHRoZSBzZWNvbmQgYW5kIHRoaXJkLiBUaGUgZmlyc3QgcG9pbnQgd2lsbCBiZSB0aGUgdG9wbW9zdFxuICAgICAgICAgKiAgICAgICAgIHBvaW50IGFuZCB0aGUgbGFzdCwgdGhlIGJvdHRvbW1vc3QuIFRoZSBzZWNvbmQgcG9pbnQgd2lsbCBiZVxuICAgICAgICAgKiAgICAgICAgIGxlZnRtb3N0IGFuZCB0aGUgdGhpcmQsIHRoZSByaWdodG1vc3RcbiAgICAgICAgICovXG4gICAgICAgIGNlbnRlckVkZ2VzKHksIHosIHgsIHQpIHtcbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyAgICAgICB0ICAgICAgICAgICAgdFxuICAgICAgICAgICAgLy8gIHogICAgICAgICAgICAgICAgICAgICAgeFxuICAgICAgICAgICAgLy8gICAgICAgIHggICAgT1IgICAgelxuICAgICAgICAgICAgLy8gICB5ICAgICAgICAgICAgICAgICAgICB5XG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgY29uc3QgeWkgPSB5LmdldFgoKTtcbiAgICAgICAgICAgIGNvbnN0IHlqID0geS5nZXRZKCk7XG4gICAgICAgICAgICBjb25zdCB6aSA9IHouZ2V0WCgpO1xuICAgICAgICAgICAgY29uc3QgemogPSB6LmdldFkoKTtcbiAgICAgICAgICAgIGNvbnN0IHhpID0geC5nZXRYKCk7XG4gICAgICAgICAgICBjb25zdCB4aiA9IHguZ2V0WSgpO1xuICAgICAgICAgICAgY29uc3QgdGkgPSB0LmdldFgoKTtcbiAgICAgICAgICAgIGNvbnN0IHRqID0gdC5nZXRZKCk7XG4gICAgICAgICAgICBjb25zdCBDT1JSID0gV2hpdGVSZWN0YW5nbGVEZXRlY3Rvci5DT1JSO1xuICAgICAgICAgICAgaWYgKHlpIDwgdGhpcy53aWR0aCAvIDIuMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAgICAgIG5ldyBSZXN1bHRQb2ludCh0aSAtIENPUlIsIHRqICsgQ09SUiksXG4gICAgICAgICAgICAgICAgICAgIG5ldyBSZXN1bHRQb2ludCh6aSArIENPUlIsIHpqICsgQ09SUiksXG4gICAgICAgICAgICAgICAgICAgIG5ldyBSZXN1bHRQb2ludCh4aSAtIENPUlIsIHhqIC0gQ09SUiksXG4gICAgICAgICAgICAgICAgICAgIG5ldyBSZXN1bHRQb2ludCh5aSArIENPUlIsIHlqIC0gQ09SUilcbiAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICAgICAgbmV3IFJlc3VsdFBvaW50KHRpICsgQ09SUiwgdGogKyBDT1JSKSxcbiAgICAgICAgICAgICAgICAgICAgbmV3IFJlc3VsdFBvaW50KHppICsgQ09SUiwgemogLSBDT1JSKSxcbiAgICAgICAgICAgICAgICAgICAgbmV3IFJlc3VsdFBvaW50KHhpIC0gQ09SUiwgeGogKyBDT1JSKSxcbiAgICAgICAgICAgICAgICAgICAgbmV3IFJlc3VsdFBvaW50KHlpIC0gQ09SUiwgeWogLSBDT1JSKVxuICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERldGVybWluZXMgd2hldGhlciBhIHNlZ21lbnQgY29udGFpbnMgYSBibGFjayBwb2ludFxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gYSAgICAgICAgICBtaW4gdmFsdWUgb2YgdGhlIHNjYW5uZWQgY29vcmRpbmF0ZVxuICAgICAgICAgKiBAcGFyYW0gYiAgICAgICAgICBtYXggdmFsdWUgb2YgdGhlIHNjYW5uZWQgY29vcmRpbmF0ZVxuICAgICAgICAgKiBAcGFyYW0gZml4ZWQgICAgICB2YWx1ZSBvZiBmaXhlZCBjb29yZGluYXRlXG4gICAgICAgICAqIEBwYXJhbSBob3Jpem9udGFsIHNldCB0byB0cnVlIGlmIHNjYW4gbXVzdCBiZSBob3Jpem9udGFsLCBmYWxzZSBpZiB2ZXJ0aWNhbFxuICAgICAgICAgKiBAcmV0dXJuIHRydWUgaWYgYSBibGFjayBwb2ludCBoYXMgYmVlbiBmb3VuZCwgZWxzZSBmYWxzZS5cbiAgICAgICAgICovXG4gICAgICAgIGNvbnRhaW5zQmxhY2tQb2ludChhIC8qaW50Ki8sIGIgLyppbnQqLywgZml4ZWQgLyppbnQqLywgaG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgY29uc3QgaW1hZ2UgPSB0aGlzLmltYWdlO1xuICAgICAgICAgICAgaWYgKGhvcml6b250YWwpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB4ID0gYTsgeCA8PSBiOyB4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGltYWdlLmdldCh4LCBmaXhlZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeSA9IGE7IHkgPD0gYjsgeSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbWFnZS5nZXQoZml4ZWQsIHkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBXaGl0ZVJlY3RhbmdsZURldGVjdG9yLklOSVRfU0laRSA9IDEwO1xuICAgIFdoaXRlUmVjdGFuZ2xlRGV0ZWN0b3IuQ09SUiA9IDE7XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIEltcGxlbWVudGF0aW9ucyBvZiB0aGlzIGNsYXNzIGNhbiwgZ2l2ZW4gbG9jYXRpb25zIG9mIGZpbmRlciBwYXR0ZXJucyBmb3IgYSBRUiBjb2RlIGluIGFuXG4gICAgICogaW1hZ2UsIHNhbXBsZSB0aGUgcmlnaHQgcG9pbnRzIGluIHRoZSBpbWFnZSB0byByZWNvbnN0cnVjdCB0aGUgUVIgY29kZSwgYWNjb3VudGluZyBmb3JcbiAgICAgKiBwZXJzcGVjdGl2ZSBkaXN0b3J0aW9uLiBJdCBpcyBhYnN0cmFjdGVkIHNpbmNlIGl0IGlzIHJlbGF0aXZlbHkgZXhwZW5zaXZlIGFuZCBzaG91bGQgYmUgYWxsb3dlZFxuICAgICAqIHRvIHRha2UgYWR2YW50YWdlIG9mIHBsYXRmb3JtLXNwZWNpZmljIG9wdGltaXplZCBpbXBsZW1lbnRhdGlvbnMsIGxpa2UgU3VuJ3MgSmF2YSBBZHZhbmNlZFxuICAgICAqIEltYWdpbmcgbGlicmFyeSwgYnV0IHdoaWNoIG1heSBub3QgYmUgYXZhaWxhYmxlIGluIG90aGVyIGVudmlyb25tZW50cyBzdWNoIGFzIEoyTUUsIGFuZCB2aWNlXG4gICAgICogdmVyc2EuXG4gICAgICpcbiAgICAgKiBUaGUgaW1wbGVtZW50YXRpb24gdXNlZCBjYW4gYmUgY29udHJvbGxlZCBieSBjYWxsaW5nIHtAbGluayAjc2V0R3JpZFNhbXBsZXIoR3JpZFNhbXBsZXIpfVxuICAgICAqIHdpdGggYW4gaW5zdGFuY2Ugb2YgYSBjbGFzcyB3aGljaCBpbXBsZW1lbnRzIHRoaXMgaW50ZXJmYWNlLlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBHcmlkU2FtcGxlciB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5DaGVja3MgYSBzZXQgb2YgcG9pbnRzIHRoYXQgaGF2ZSBiZWVuIHRyYW5zZm9ybWVkIHRvIHNhbXBsZSBwb2ludHMgb24gYW4gaW1hZ2UgYWdhaW5zdFxuICAgICAgICAgKiB0aGUgaW1hZ2UncyBkaW1lbnNpb25zIHRvIHNlZSBpZiB0aGUgcG9pbnQgYXJlIGV2ZW4gd2l0aGluIHRoZSBpbWFnZS48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIDxwPlRoaXMgbWV0aG9kIHdpbGwgYWN0dWFsbHkgXCJudWRnZVwiIHRoZSBlbmRwb2ludHMgYmFjayBvbnRvIHRoZSBpbWFnZSBpZiB0aGV5IGFyZSBmb3VuZCB0byBiZVxuICAgICAgICAgKiBiYXJlbHkgKGxlc3MgdGhhbiAxIHBpeGVsKSBvZmYgdGhlIGltYWdlLiBUaGlzIGFjY291bnRzIGZvciBpbXBlcmZlY3QgZGV0ZWN0aW9uIG9mIGZpbmRlclxuICAgICAgICAgKiBwYXR0ZXJucyBpbiBhbiBpbWFnZSB3aGVyZSB0aGUgUVIgQ29kZSBydW5zIGFsbCB0aGUgd2F5IHRvIHRoZSBpbWFnZSBib3JkZXIuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiA8cD5Gb3IgZWZmaWNpZW5jeSwgdGhlIG1ldGhvZCB3aWxsIGNoZWNrIHBvaW50cyBmcm9tIGVpdGhlciBlbmQgb2YgdGhlIGxpbmUgdW50aWwgb25lIGlzIGZvdW5kXG4gICAgICAgICAqIHRvIGJlIHdpdGhpbiB0aGUgaW1hZ2UuIEJlY2F1c2UgdGhlIHNldCBvZiBwb2ludHMgYXJlIGFzc3VtZWQgdG8gYmUgbGluZWFyLCB0aGlzIGlzIHZhbGlkLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGltYWdlIGltYWdlIGludG8gd2hpY2ggdGhlIHBvaW50cyBzaG91bGQgbWFwXG4gICAgICAgICAqIEBwYXJhbSBwb2ludHMgYWN0dWFsIHBvaW50cyBpbiB4MSx5MSwuLi4seG4seW4gZm9ybVxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIGFuIGVuZHBvaW50IGlzIGxpZXMgb3V0c2lkZSB0aGUgaW1hZ2UgYm91bmRhcmllc1xuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGNoZWNrQW5kTnVkZ2VQb2ludHMoaW1hZ2UsIHBvaW50cykge1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBpbWFnZS5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gaW1hZ2UuZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICAvLyBDaGVjayBhbmQgbnVkZ2UgcG9pbnRzIGZyb20gc3RhcnQgdW50aWwgd2Ugc2VlIHNvbWUgdGhhdCBhcmUgT0s6XG4gICAgICAgICAgICBsZXQgbnVkZ2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIGZvciAobGV0IG9mZnNldCA9IDA7IG9mZnNldCA8IHBvaW50cy5sZW5ndGggJiYgbnVkZ2VkOyBvZmZzZXQgKz0gMikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHggPSBNYXRoLmZsb29yKHBvaW50c1tvZmZzZXRdKTtcbiAgICAgICAgICAgICAgICBjb25zdCB5ID0gTWF0aC5mbG9vcihwb2ludHNbb2Zmc2V0ICsgMV0pO1xuICAgICAgICAgICAgICAgIGlmICh4IDwgLTEgfHwgeCA+IHdpZHRoIHx8IHkgPCAtMSB8fCB5ID4gaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBudWRnZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBpZiAoeCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcG9pbnRzW29mZnNldF0gPSAwLjA7XG4gICAgICAgICAgICAgICAgICAgIG51ZGdlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHggPT09IHdpZHRoKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvaW50c1tvZmZzZXRdID0gd2lkdGggLSAxO1xuICAgICAgICAgICAgICAgICAgICBudWRnZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoeSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcG9pbnRzW29mZnNldCArIDFdID0gMC4wO1xuICAgICAgICAgICAgICAgICAgICBudWRnZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh5ID09PSBoZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgcG9pbnRzW29mZnNldCArIDFdID0gaGVpZ2h0IC0gMTtcbiAgICAgICAgICAgICAgICAgICAgbnVkZ2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBDaGVjayBhbmQgbnVkZ2UgcG9pbnRzIGZyb20gZW5kOlxuICAgICAgICAgICAgbnVkZ2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIGZvciAobGV0IG9mZnNldCA9IHBvaW50cy5sZW5ndGggLSAyOyBvZmZzZXQgPj0gMCAmJiBudWRnZWQ7IG9mZnNldCAtPSAyKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgeCA9IE1hdGguZmxvb3IocG9pbnRzW29mZnNldF0pO1xuICAgICAgICAgICAgICAgIGNvbnN0IHkgPSBNYXRoLmZsb29yKHBvaW50c1tvZmZzZXQgKyAxXSk7XG4gICAgICAgICAgICAgICAgaWYgKHggPCAtMSB8fCB4ID4gd2lkdGggfHwgeSA8IC0xIHx8IHkgPiBoZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG51ZGdlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGlmICh4ID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBwb2ludHNbb2Zmc2V0XSA9IDAuMDtcbiAgICAgICAgICAgICAgICAgICAgbnVkZ2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoeCA9PT0gd2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcG9pbnRzW29mZnNldF0gPSB3aWR0aCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIG51ZGdlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh5ID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBwb2ludHNbb2Zmc2V0ICsgMV0gPSAwLjA7XG4gICAgICAgICAgICAgICAgICAgIG51ZGdlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHkgPT09IGhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICBwb2ludHNbb2Zmc2V0ICsgMV0gPSBoZWlnaHQgLSAxO1xuICAgICAgICAgICAgICAgICAgICBudWRnZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLypuYW1lc3BhY2UgY29tLmdvb2dsZS56eGluZy5jb21tb24geyovXG4gICAgLyoqXG4gICAgICogPHA+VGhpcyBjbGFzcyBpbXBsZW1lbnRzIGEgcGVyc3BlY3RpdmUgdHJhbnNmb3JtIGluIHR3byBkaW1lbnNpb25zLiBHaXZlbiBmb3VyIHNvdXJjZSBhbmQgZm91clxuICAgICAqIGRlc3RpbmF0aW9uIHBvaW50cywgaXQgd2lsbCBjb21wdXRlIHRoZSB0cmFuc2Zvcm1hdGlvbiBpbXBsaWVkIGJldHdlZW4gdGhlbS4gVGhlIGNvZGUgaXMgYmFzZWRcbiAgICAgKiBkaXJlY3RseSB1cG9uIHNlY3Rpb24gMy40LjIgb2YgR2VvcmdlIFdvbGJlcmcncyBcIkRpZ2l0YWwgSW1hZ2UgV2FycGluZ1wiOyBzZWUgcGFnZXMgNTQtNTYuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBQZXJzcGVjdGl2ZVRyYW5zZm9ybSB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGExMSAvKmZsb2F0Ki8sIGEyMSAvKmZsb2F0Ki8sIGEzMSAvKmZsb2F0Ki8sIGExMiAvKmZsb2F0Ki8sIGEyMiAvKmZsb2F0Ki8sIGEzMiAvKmZsb2F0Ki8sIGExMyAvKmZsb2F0Ki8sIGEyMyAvKmZsb2F0Ki8sIGEzMyAvKmZsb2F0Ki8pIHtcbiAgICAgICAgICAgIHRoaXMuYTExID0gYTExO1xuICAgICAgICAgICAgdGhpcy5hMjEgPSBhMjE7XG4gICAgICAgICAgICB0aGlzLmEzMSA9IGEzMTtcbiAgICAgICAgICAgIHRoaXMuYTEyID0gYTEyO1xuICAgICAgICAgICAgdGhpcy5hMjIgPSBhMjI7XG4gICAgICAgICAgICB0aGlzLmEzMiA9IGEzMjtcbiAgICAgICAgICAgIHRoaXMuYTEzID0gYTEzO1xuICAgICAgICAgICAgdGhpcy5hMjMgPSBhMjM7XG4gICAgICAgICAgICB0aGlzLmEzMyA9IGEzMztcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgcXVhZHJpbGF0ZXJhbFRvUXVhZHJpbGF0ZXJhbCh4MCAvKmZsb2F0Ki8sIHkwIC8qZmxvYXQqLywgeDEgLypmbG9hdCovLCB5MSAvKmZsb2F0Ki8sIHgyIC8qZmxvYXQqLywgeTIgLypmbG9hdCovLCB4MyAvKmZsb2F0Ki8sIHkzIC8qZmxvYXQqLywgeDBwIC8qZmxvYXQqLywgeTBwIC8qZmxvYXQqLywgeDFwIC8qZmxvYXQqLywgeTFwIC8qZmxvYXQqLywgeDJwIC8qZmxvYXQqLywgeTJwIC8qZmxvYXQqLywgeDNwIC8qZmxvYXQqLywgeTNwIC8qZmxvYXQqLykge1xuICAgICAgICAgICAgY29uc3QgcVRvUyA9IFBlcnNwZWN0aXZlVHJhbnNmb3JtLnF1YWRyaWxhdGVyYWxUb1NxdWFyZSh4MCwgeTAsIHgxLCB5MSwgeDIsIHkyLCB4MywgeTMpO1xuICAgICAgICAgICAgY29uc3Qgc1RvUSA9IFBlcnNwZWN0aXZlVHJhbnNmb3JtLnNxdWFyZVRvUXVhZHJpbGF0ZXJhbCh4MHAsIHkwcCwgeDFwLCB5MXAsIHgycCwgeTJwLCB4M3AsIHkzcCk7XG4gICAgICAgICAgICByZXR1cm4gc1RvUS50aW1lcyhxVG9TKTtcbiAgICAgICAgfVxuICAgICAgICB0cmFuc2Zvcm1Qb2ludHMocG9pbnRzKSB7XG4gICAgICAgICAgICBjb25zdCBtYXggPSBwb2ludHMubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3QgYTExID0gdGhpcy5hMTE7XG4gICAgICAgICAgICBjb25zdCBhMTIgPSB0aGlzLmExMjtcbiAgICAgICAgICAgIGNvbnN0IGExMyA9IHRoaXMuYTEzO1xuICAgICAgICAgICAgY29uc3QgYTIxID0gdGhpcy5hMjE7XG4gICAgICAgICAgICBjb25zdCBhMjIgPSB0aGlzLmEyMjtcbiAgICAgICAgICAgIGNvbnN0IGEyMyA9IHRoaXMuYTIzO1xuICAgICAgICAgICAgY29uc3QgYTMxID0gdGhpcy5hMzE7XG4gICAgICAgICAgICBjb25zdCBhMzIgPSB0aGlzLmEzMjtcbiAgICAgICAgICAgIGNvbnN0IGEzMyA9IHRoaXMuYTMzO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXg7IGkgKz0gMikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHggPSBwb2ludHNbaV07XG4gICAgICAgICAgICAgICAgY29uc3QgeSA9IHBvaW50c1tpICsgMV07XG4gICAgICAgICAgICAgICAgY29uc3QgZGVub21pbmF0b3IgPSBhMTMgKiB4ICsgYTIzICogeSArIGEzMztcbiAgICAgICAgICAgICAgICBwb2ludHNbaV0gPSAoYTExICogeCArIGEyMSAqIHkgKyBhMzEpIC8gZGVub21pbmF0b3I7XG4gICAgICAgICAgICAgICAgcG9pbnRzW2kgKyAxXSA9IChhMTIgKiB4ICsgYTIyICogeSArIGEzMikgLyBkZW5vbWluYXRvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0cmFuc2Zvcm1Qb2ludHNXaXRoVmFsdWVzKHhWYWx1ZXMsIHlWYWx1ZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IGExMSA9IHRoaXMuYTExO1xuICAgICAgICAgICAgY29uc3QgYTEyID0gdGhpcy5hMTI7XG4gICAgICAgICAgICBjb25zdCBhMTMgPSB0aGlzLmExMztcbiAgICAgICAgICAgIGNvbnN0IGEyMSA9IHRoaXMuYTIxO1xuICAgICAgICAgICAgY29uc3QgYTIyID0gdGhpcy5hMjI7XG4gICAgICAgICAgICBjb25zdCBhMjMgPSB0aGlzLmEyMztcbiAgICAgICAgICAgIGNvbnN0IGEzMSA9IHRoaXMuYTMxO1xuICAgICAgICAgICAgY29uc3QgYTMyID0gdGhpcy5hMzI7XG4gICAgICAgICAgICBjb25zdCBhMzMgPSB0aGlzLmEzMztcbiAgICAgICAgICAgIGNvbnN0IG4gPSB4VmFsdWVzLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgeCA9IHhWYWx1ZXNbaV07XG4gICAgICAgICAgICAgICAgY29uc3QgeSA9IHlWYWx1ZXNbaV07XG4gICAgICAgICAgICAgICAgY29uc3QgZGVub21pbmF0b3IgPSBhMTMgKiB4ICsgYTIzICogeSArIGEzMztcbiAgICAgICAgICAgICAgICB4VmFsdWVzW2ldID0gKGExMSAqIHggKyBhMjEgKiB5ICsgYTMxKSAvIGRlbm9taW5hdG9yO1xuICAgICAgICAgICAgICAgIHlWYWx1ZXNbaV0gPSAoYTEyICogeCArIGEyMiAqIHkgKyBhMzIpIC8gZGVub21pbmF0b3I7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHNxdWFyZVRvUXVhZHJpbGF0ZXJhbCh4MCAvKmZsb2F0Ki8sIHkwIC8qZmxvYXQqLywgeDEgLypmbG9hdCovLCB5MSAvKmZsb2F0Ki8sIHgyIC8qZmxvYXQqLywgeTIgLypmbG9hdCovLCB4MyAvKmZsb2F0Ki8sIHkzIC8qZmxvYXQqLykge1xuICAgICAgICAgICAgY29uc3QgZHgzID0geDAgLSB4MSArIHgyIC0geDM7XG4gICAgICAgICAgICBjb25zdCBkeTMgPSB5MCAtIHkxICsgeTIgLSB5MztcbiAgICAgICAgICAgIGlmIChkeDMgPT09IDAuMCAmJiBkeTMgPT09IDAuMCkge1xuICAgICAgICAgICAgICAgIC8vIEFmZmluZVxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUGVyc3BlY3RpdmVUcmFuc2Zvcm0oeDEgLSB4MCwgeDIgLSB4MSwgeDAsIHkxIC0geTAsIHkyIC0geTEsIHkwLCAwLjAsIDAuMCwgMS4wKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGR4MSA9IHgxIC0geDI7XG4gICAgICAgICAgICAgICAgY29uc3QgZHgyID0geDMgLSB4MjtcbiAgICAgICAgICAgICAgICBjb25zdCBkeTEgPSB5MSAtIHkyO1xuICAgICAgICAgICAgICAgIGNvbnN0IGR5MiA9IHkzIC0geTI7XG4gICAgICAgICAgICAgICAgY29uc3QgZGVub21pbmF0b3IgPSBkeDEgKiBkeTIgLSBkeDIgKiBkeTE7XG4gICAgICAgICAgICAgICAgY29uc3QgYTEzID0gKGR4MyAqIGR5MiAtIGR4MiAqIGR5MykgLyBkZW5vbWluYXRvcjtcbiAgICAgICAgICAgICAgICBjb25zdCBhMjMgPSAoZHgxICogZHkzIC0gZHgzICogZHkxKSAvIGRlbm9taW5hdG9yO1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUGVyc3BlY3RpdmVUcmFuc2Zvcm0oeDEgLSB4MCArIGExMyAqIHgxLCB4MyAtIHgwICsgYTIzICogeDMsIHgwLCB5MSAtIHkwICsgYTEzICogeTEsIHkzIC0geTAgKyBhMjMgKiB5MywgeTAsIGExMywgYTIzLCAxLjApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBxdWFkcmlsYXRlcmFsVG9TcXVhcmUoeDAgLypmbG9hdCovLCB5MCAvKmZsb2F0Ki8sIHgxIC8qZmxvYXQqLywgeTEgLypmbG9hdCovLCB4MiAvKmZsb2F0Ki8sIHkyIC8qZmxvYXQqLywgeDMgLypmbG9hdCovLCB5MyAvKmZsb2F0Ki8pIHtcbiAgICAgICAgICAgIC8vIEhlcmUsIHRoZSBhZGpvaW50IHNlcnZlcyBhcyB0aGUgaW52ZXJzZTpcbiAgICAgICAgICAgIHJldHVybiBQZXJzcGVjdGl2ZVRyYW5zZm9ybS5zcXVhcmVUb1F1YWRyaWxhdGVyYWwoeDAsIHkwLCB4MSwgeTEsIHgyLCB5MiwgeDMsIHkzKS5idWlsZEFkam9pbnQoKTtcbiAgICAgICAgfVxuICAgICAgICBidWlsZEFkam9pbnQoKSB7XG4gICAgICAgICAgICAvLyBBZGpvaW50IGlzIHRoZSB0cmFuc3Bvc2Ugb2YgdGhlIGNvZmFjdG9yIG1hdHJpeDpcbiAgICAgICAgICAgIHJldHVybiBuZXcgUGVyc3BlY3RpdmVUcmFuc2Zvcm0odGhpcy5hMjIgKiB0aGlzLmEzMyAtIHRoaXMuYTIzICogdGhpcy5hMzIsIHRoaXMuYTIzICogdGhpcy5hMzEgLSB0aGlzLmEyMSAqIHRoaXMuYTMzLCB0aGlzLmEyMSAqIHRoaXMuYTMyIC0gdGhpcy5hMjIgKiB0aGlzLmEzMSwgdGhpcy5hMTMgKiB0aGlzLmEzMiAtIHRoaXMuYTEyICogdGhpcy5hMzMsIHRoaXMuYTExICogdGhpcy5hMzMgLSB0aGlzLmExMyAqIHRoaXMuYTMxLCB0aGlzLmExMiAqIHRoaXMuYTMxIC0gdGhpcy5hMTEgKiB0aGlzLmEzMiwgdGhpcy5hMTIgKiB0aGlzLmEyMyAtIHRoaXMuYTEzICogdGhpcy5hMjIsIHRoaXMuYTEzICogdGhpcy5hMjEgLSB0aGlzLmExMSAqIHRoaXMuYTIzLCB0aGlzLmExMSAqIHRoaXMuYTIyIC0gdGhpcy5hMTIgKiB0aGlzLmEyMSk7XG4gICAgICAgIH1cbiAgICAgICAgdGltZXMob3RoZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUGVyc3BlY3RpdmVUcmFuc2Zvcm0odGhpcy5hMTEgKiBvdGhlci5hMTEgKyB0aGlzLmEyMSAqIG90aGVyLmExMiArIHRoaXMuYTMxICogb3RoZXIuYTEzLCB0aGlzLmExMSAqIG90aGVyLmEyMSArIHRoaXMuYTIxICogb3RoZXIuYTIyICsgdGhpcy5hMzEgKiBvdGhlci5hMjMsIHRoaXMuYTExICogb3RoZXIuYTMxICsgdGhpcy5hMjEgKiBvdGhlci5hMzIgKyB0aGlzLmEzMSAqIG90aGVyLmEzMywgdGhpcy5hMTIgKiBvdGhlci5hMTEgKyB0aGlzLmEyMiAqIG90aGVyLmExMiArIHRoaXMuYTMyICogb3RoZXIuYTEzLCB0aGlzLmExMiAqIG90aGVyLmEyMSArIHRoaXMuYTIyICogb3RoZXIuYTIyICsgdGhpcy5hMzIgKiBvdGhlci5hMjMsIHRoaXMuYTEyICogb3RoZXIuYTMxICsgdGhpcy5hMjIgKiBvdGhlci5hMzIgKyB0aGlzLmEzMiAqIG90aGVyLmEzMywgdGhpcy5hMTMgKiBvdGhlci5hMTEgKyB0aGlzLmEyMyAqIG90aGVyLmExMiArIHRoaXMuYTMzICogb3RoZXIuYTEzLCB0aGlzLmExMyAqIG90aGVyLmEyMSArIHRoaXMuYTIzICogb3RoZXIuYTIyICsgdGhpcy5hMzMgKiBvdGhlci5hMjMsIHRoaXMuYTEzICogb3RoZXIuYTMxICsgdGhpcy5hMjMgKiBvdGhlci5hMzIgKyB0aGlzLmEzMyAqIG90aGVyLmEzMyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgRGVmYXVsdEdyaWRTYW1wbGVyIGV4dGVuZHMgR3JpZFNhbXBsZXIge1xuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIHNhbXBsZUdyaWQoaW1hZ2UsIGRpbWVuc2lvblggLyppbnQqLywgZGltZW5zaW9uWSAvKmludCovLCBwMVRvWCAvKmZsb2F0Ki8sIHAxVG9ZIC8qZmxvYXQqLywgcDJUb1ggLypmbG9hdCovLCBwMlRvWSAvKmZsb2F0Ki8sIHAzVG9YIC8qZmxvYXQqLywgcDNUb1kgLypmbG9hdCovLCBwNFRvWCAvKmZsb2F0Ki8sIHA0VG9ZIC8qZmxvYXQqLywgcDFGcm9tWCAvKmZsb2F0Ki8sIHAxRnJvbVkgLypmbG9hdCovLCBwMkZyb21YIC8qZmxvYXQqLywgcDJGcm9tWSAvKmZsb2F0Ki8sIHAzRnJvbVggLypmbG9hdCovLCBwM0Zyb21ZIC8qZmxvYXQqLywgcDRGcm9tWCAvKmZsb2F0Ki8sIHA0RnJvbVkgLypmbG9hdCovKSB7XG4gICAgICAgICAgICBjb25zdCB0cmFuc2Zvcm0gPSBQZXJzcGVjdGl2ZVRyYW5zZm9ybS5xdWFkcmlsYXRlcmFsVG9RdWFkcmlsYXRlcmFsKHAxVG9YLCBwMVRvWSwgcDJUb1gsIHAyVG9ZLCBwM1RvWCwgcDNUb1ksIHA0VG9YLCBwNFRvWSwgcDFGcm9tWCwgcDFGcm9tWSwgcDJGcm9tWCwgcDJGcm9tWSwgcDNGcm9tWCwgcDNGcm9tWSwgcDRGcm9tWCwgcDRGcm9tWSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zYW1wbGVHcmlkV2l0aFRyYW5zZm9ybShpbWFnZSwgZGltZW5zaW9uWCwgZGltZW5zaW9uWSwgdHJhbnNmb3JtKTtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIHNhbXBsZUdyaWRXaXRoVHJhbnNmb3JtKGltYWdlLCBkaW1lbnNpb25YIC8qaW50Ki8sIGRpbWVuc2lvblkgLyppbnQqLywgdHJhbnNmb3JtKSB7XG4gICAgICAgICAgICBpZiAoZGltZW5zaW9uWCA8PSAwIHx8IGRpbWVuc2lvblkgPD0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYml0cyA9IG5ldyBCaXRNYXRyaXgoZGltZW5zaW9uWCwgZGltZW5zaW9uWSk7XG4gICAgICAgICAgICBjb25zdCBwb2ludHMgPSBuZXcgRmxvYXQzMkFycmF5KDIgKiBkaW1lbnNpb25YKTtcbiAgICAgICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgZGltZW5zaW9uWTsgeSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbWF4ID0gcG9pbnRzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBjb25zdCBpVmFsdWUgPSB5ICsgMC41O1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgbWF4OyB4ICs9IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgcG9pbnRzW3hdID0gKHggLyAyKSArIDAuNTtcbiAgICAgICAgICAgICAgICAgICAgcG9pbnRzW3ggKyAxXSA9IGlWYWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtLnRyYW5zZm9ybVBvaW50cyhwb2ludHMpO1xuICAgICAgICAgICAgICAgIC8vIFF1aWNrIGNoZWNrIHRvIHNlZSBpZiBwb2ludHMgdHJhbnNmb3JtZWQgdG8gc29tZXRoaW5nIGluc2lkZSB0aGUgaW1hZ2VcbiAgICAgICAgICAgICAgICAvLyBzdWZmaWNpZW50IHRvIGNoZWNrIHRoZSBlbmRwb2ludHNcbiAgICAgICAgICAgICAgICBHcmlkU2FtcGxlci5jaGVja0FuZE51ZGdlUG9pbnRzKGltYWdlLCBwb2ludHMpO1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgbWF4OyB4ICs9IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbWFnZS5nZXQoTWF0aC5mbG9vcihwb2ludHNbeF0pLCBNYXRoLmZsb29yKHBvaW50c1t4ICsgMV0pKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrKC1pc2gpIHBpeGVsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYml0cy5zZXQoeCAvIDIsIHkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChhaW9vYmUgLyo6IEFycmF5SW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbiovKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgZmVlbHMgd3JvbmcsIGJ1dCwgc29tZXRpbWVzIGlmIHRoZSBmaW5kZXIgcGF0dGVybnMgYXJlIG1pc2lkZW50aWZpZWQsIHRoZSByZXN1bHRpbmdcbiAgICAgICAgICAgICAgICAgICAgLy8gdHJhbnNmb3JtIGdldHMgXCJ0d2lzdGVkXCIgc3VjaCB0aGF0IGl0IG1hcHMgYSBzdHJhaWdodCBsaW5lIG9mIHBvaW50cyB0byBhIHNldCBvZiBwb2ludHNcbiAgICAgICAgICAgICAgICAgICAgLy8gd2hvc2UgZW5kcG9pbnRzIGFyZSBpbiBib3VuZHMsIGJ1dCBvdGhlcnMgYXJlIG5vdC4gVGhlcmUgaXMgcHJvYmFibHkgc29tZSBtYXRoZW1hdGljYWxcbiAgICAgICAgICAgICAgICAgICAgLy8gd2F5IHRvIGRldGVjdCB0aGlzIGFib3V0IHRoZSB0cmFuc2Zvcm1hdGlvbiB0aGF0IEkgZG9uJ3Qga25vdyB5ZXQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcmVzdWx0cyBpbiBhbiB1Z2x5IHJ1bnRpbWUgZXhjZXB0aW9uIGRlc3BpdGUgb3VyIGNsZXZlciBjaGVja3MgYWJvdmUgLS0gY2FuJ3QgaGF2ZVxuICAgICAgICAgICAgICAgICAgICAvLyB0aGF0LiBXZSBjb3VsZCBjaGVjayBlYWNoIHBvaW50J3MgY29vcmRpbmF0ZXMgYnV0IHRoYXQgZmVlbHMgZHVwbGljYXRpdmUuIFdlIHNldHRsZSBmb3JcbiAgICAgICAgICAgICAgICAgICAgLy8gY2F0Y2hpbmcgYW5kIHdyYXBwaW5nIEFycmF5SW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbi5cbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGJpdHM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjbGFzcyBHcmlkU2FtcGxlckluc3RhbmNlIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNldHMgdGhlIGltcGxlbWVudGF0aW9uIG9mIEdyaWRTYW1wbGVyIHVzZWQgYnkgdGhlIGxpYnJhcnkuIE9uZSBnbG9iYWxcbiAgICAgICAgICogaW5zdGFuY2UgaXMgc3RvcmVkLCB3aGljaCBtYXkgc291bmQgcHJvYmxlbWF0aWMuIEJ1dCwgdGhlIGltcGxlbWVudGF0aW9uIHByb3ZpZGVkXG4gICAgICAgICAqIG91Z2h0IHRvIGJlIGFwcHJvcHJpYXRlIGZvciB0aGUgZW50aXJlIHBsYXRmb3JtLCBhbmQgYWxsIHVzZXMgb2YgdGhpcyBsaWJyYXJ5XG4gICAgICAgICAqIGluIHRoZSB3aG9sZSBsaWZldGltZSBvZiB0aGUgSlZNLiBGb3IgaW5zdGFuY2UsIGFuIEFuZHJvaWQgYWN0aXZpdHkgY2FuIHN3YXAgaW5cbiAgICAgICAgICogYW4gaW1wbGVtZW50YXRpb24gdGhhdCB0YWtlcyBhZHZhbnRhZ2Ugb2YgbmF0aXZlIHBsYXRmb3JtIGxpYnJhcmllcy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIG5ld0dyaWRTYW1wbGVyIFRoZSBwbGF0Zm9ybS1zcGVjaWZpYyBvYmplY3QgdG8gaW5zdGFsbC5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBzZXRHcmlkU2FtcGxlcihuZXdHcmlkU2FtcGxlcikge1xuICAgICAgICAgICAgR3JpZFNhbXBsZXJJbnN0YW5jZS5ncmlkU2FtcGxlciA9IG5ld0dyaWRTYW1wbGVyO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHRoZSBjdXJyZW50IGltcGxlbWVudGF0aW9uIG9mIEdyaWRTYW1wbGVyXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZ2V0SW5zdGFuY2UoKSB7XG4gICAgICAgICAgICByZXR1cm4gR3JpZFNhbXBsZXJJbnN0YW5jZS5ncmlkU2FtcGxlcjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBHcmlkU2FtcGxlckluc3RhbmNlLmdyaWRTYW1wbGVyID0gbmV3IERlZmF1bHRHcmlkU2FtcGxlcigpO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAxMCBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICBjbGFzcyBQb2ludCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHgsIHkpIHtcbiAgICAgICAgICAgIHRoaXMueCA9IHg7XG4gICAgICAgICAgICB0aGlzLnkgPSB5O1xuICAgICAgICB9XG4gICAgICAgIHRvUmVzdWx0UG9pbnQoKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFJlc3VsdFBvaW50KHRoaXMuZ2V0WCgpLCB0aGlzLmdldFkoKSk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0WCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLng7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0WSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogRW5jYXBzdWxhdGVzIGxvZ2ljIHRoYXQgY2FuIGRldGVjdCBhbiBBenRlYyBDb2RlIGluIGFuIGltYWdlLCBldmVuIGlmIHRoZSBBenRlYyBDb2RlXG4gICAgICogaXMgcm90YXRlZCBvciBza2V3ZWQsIG9yIHBhcnRpYWxseSBvYnNjdXJlZC5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgRGF2aWQgT2xpdmllclxuICAgICAqIEBhdXRob3IgRnJhbmsgWWVsbGluXG4gICAgICovXG4gICAgY2xhc3MgRGV0ZWN0b3Ige1xuICAgICAgICBjb25zdHJ1Y3RvcihpbWFnZSkge1xuICAgICAgICAgICAgdGhpcy5FWFBFQ1RFRF9DT1JORVJfQklUUyA9IG5ldyBJbnQzMkFycmF5KFtcbiAgICAgICAgICAgICAgICAweGVlMCxcbiAgICAgICAgICAgICAgICAweDFkYyxcbiAgICAgICAgICAgICAgICAweDgzYixcbiAgICAgICAgICAgICAgICAweDcwNyxcbiAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgdGhpcy5pbWFnZSA9IGltYWdlO1xuICAgICAgICB9XG4gICAgICAgIGRldGVjdCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRldGVjdE1pcnJvcihmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERldGVjdHMgYW4gQXp0ZWMgQ29kZSBpbiBhbiBpbWFnZS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGlzTWlycm9yIGlmIHRydWUsIGltYWdlIGlzIGEgbWlycm9yLWltYWdlIG9mIG9yaWdpbmFsXG4gICAgICAgICAqIEByZXR1cm4ge0BsaW5rIEF6dGVjRGV0ZWN0b3JSZXN1bHR9IGVuY2Fwc3VsYXRpbmcgcmVzdWx0cyBvZiBkZXRlY3RpbmcgYW4gQXp0ZWMgQ29kZVxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIG5vIEF6dGVjIENvZGUgY2FuIGJlIGZvdW5kXG4gICAgICAgICAqL1xuICAgICAgICBkZXRlY3RNaXJyb3IoaXNNaXJyb3IpIHtcbiAgICAgICAgICAgIC8vIDEuIEdldCB0aGUgY2VudGVyIG9mIHRoZSBhenRlYyBtYXRyaXhcbiAgICAgICAgICAgIGxldCBwQ2VudGVyID0gdGhpcy5nZXRNYXRyaXhDZW50ZXIoKTtcbiAgICAgICAgICAgIC8vIDIuIEdldCB0aGUgY2VudGVyIHBvaW50cyBvZiB0aGUgZm91ciBkaWFnb25hbCBwb2ludHMganVzdCBvdXRzaWRlIHRoZSBidWxsJ3MgZXllXG4gICAgICAgICAgICAvLyAgW3RvcFJpZ2h0LCBib3R0b21SaWdodCwgYm90dG9tTGVmdCwgdG9wTGVmdF1cbiAgICAgICAgICAgIGxldCBidWxsc0V5ZUNvcm5lcnMgPSB0aGlzLmdldEJ1bGxzRXllQ29ybmVycyhwQ2VudGVyKTtcbiAgICAgICAgICAgIGlmIChpc01pcnJvcikge1xuICAgICAgICAgICAgICAgIGxldCB0ZW1wID0gYnVsbHNFeWVDb3JuZXJzWzBdO1xuICAgICAgICAgICAgICAgIGJ1bGxzRXllQ29ybmVyc1swXSA9IGJ1bGxzRXllQ29ybmVyc1syXTtcbiAgICAgICAgICAgICAgICBidWxsc0V5ZUNvcm5lcnNbMl0gPSB0ZW1wO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gMy4gR2V0IHRoZSBzaXplIG9mIHRoZSBtYXRyaXggYW5kIG90aGVyIHBhcmFtZXRlcnMgZnJvbSB0aGUgYnVsbCdzIGV5ZVxuICAgICAgICAgICAgdGhpcy5leHRyYWN0UGFyYW1ldGVycyhidWxsc0V5ZUNvcm5lcnMpO1xuICAgICAgICAgICAgLy8gNC4gU2FtcGxlIHRoZSBncmlkXG4gICAgICAgICAgICBsZXQgYml0cyA9IHRoaXMuc2FtcGxlR3JpZCh0aGlzLmltYWdlLCBidWxsc0V5ZUNvcm5lcnNbdGhpcy5zaGlmdCAlIDRdLCBidWxsc0V5ZUNvcm5lcnNbKHRoaXMuc2hpZnQgKyAxKSAlIDRdLCBidWxsc0V5ZUNvcm5lcnNbKHRoaXMuc2hpZnQgKyAyKSAlIDRdLCBidWxsc0V5ZUNvcm5lcnNbKHRoaXMuc2hpZnQgKyAzKSAlIDRdKTtcbiAgICAgICAgICAgIC8vIDUuIEdldCB0aGUgY29ybmVycyBvZiB0aGUgbWF0cml4LlxuICAgICAgICAgICAgbGV0IGNvcm5lcnMgPSB0aGlzLmdldE1hdHJpeENvcm5lclBvaW50cyhidWxsc0V5ZUNvcm5lcnMpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBBenRlY0RldGVjdG9yUmVzdWx0KGJpdHMsIGNvcm5lcnMsIHRoaXMuY29tcGFjdCwgdGhpcy5uYkRhdGFCbG9ja3MsIHRoaXMubmJMYXllcnMpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFeHRyYWN0cyB0aGUgbnVtYmVyIG9mIGRhdGEgbGF5ZXJzIGFuZCBkYXRhIGJsb2NrcyBmcm9tIHRoZSBsYXllciBhcm91bmQgdGhlIGJ1bGwncyBleWUuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBidWxsc0V5ZUNvcm5lcnMgdGhlIGFycmF5IG9mIGJ1bGwncyBleWUgY29ybmVyc1xuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGluIGNhc2Ugb2YgdG9vIG1hbnkgZXJyb3JzIG9yIGludmFsaWQgcGFyYW1ldGVyc1xuICAgICAgICAgKi9cbiAgICAgICAgZXh0cmFjdFBhcmFtZXRlcnMoYnVsbHNFeWVDb3JuZXJzKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNWYWxpZFBvaW50KGJ1bGxzRXllQ29ybmVyc1swXSkgfHwgIXRoaXMuaXNWYWxpZFBvaW50KGJ1bGxzRXllQ29ybmVyc1sxXSkgfHxcbiAgICAgICAgICAgICAgICAhdGhpcy5pc1ZhbGlkUG9pbnQoYnVsbHNFeWVDb3JuZXJzWzJdKSB8fCAhdGhpcy5pc1ZhbGlkUG9pbnQoYnVsbHNFeWVDb3JuZXJzWzNdKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGxlbmd0aCA9IDIgKiB0aGlzLm5iQ2VudGVyTGF5ZXJzO1xuICAgICAgICAgICAgLy8gR2V0IHRoZSBiaXRzIGFyb3VuZCB0aGUgYnVsbCdzIGV5ZVxuICAgICAgICAgICAgbGV0IHNpZGVzID0gbmV3IEludDMyQXJyYXkoW1xuICAgICAgICAgICAgICAgIHRoaXMuc2FtcGxlTGluZShidWxsc0V5ZUNvcm5lcnNbMF0sIGJ1bGxzRXllQ29ybmVyc1sxXSwgbGVuZ3RoKSxcbiAgICAgICAgICAgICAgICB0aGlzLnNhbXBsZUxpbmUoYnVsbHNFeWVDb3JuZXJzWzFdLCBidWxsc0V5ZUNvcm5lcnNbMl0sIGxlbmd0aCksXG4gICAgICAgICAgICAgICAgdGhpcy5zYW1wbGVMaW5lKGJ1bGxzRXllQ29ybmVyc1syXSwgYnVsbHNFeWVDb3JuZXJzWzNdLCBsZW5ndGgpLFxuICAgICAgICAgICAgICAgIHRoaXMuc2FtcGxlTGluZShidWxsc0V5ZUNvcm5lcnNbM10sIGJ1bGxzRXllQ29ybmVyc1swXSwgbGVuZ3RoKSAvLyBUb3BcbiAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgLy8gYnVsbHNFeWVDb3JuZXJzW3NoaWZ0XSBpcyB0aGUgY29ybmVyIG9mIHRoZSBidWxscydleWUgdGhhdCBoYXMgdGhyZWVcbiAgICAgICAgICAgIC8vIG9yaWVudGF0aW9uIG1hcmtzLlxuICAgICAgICAgICAgLy8gc2lkZXNbc2hpZnRdIGlzIHRoZSByb3cvY29sdW1uIHRoYXQgZ29lcyBmcm9tIHRoZSBjb3JuZXIgd2l0aCB0aHJlZVxuICAgICAgICAgICAgLy8gb3JpZW50YXRpb24gbWFya3MgdG8gdGhlIGNvcm5lciB3aXRoIHR3by5cbiAgICAgICAgICAgIHRoaXMuc2hpZnQgPSB0aGlzLmdldFJvdGF0aW9uKHNpZGVzLCBsZW5ndGgpO1xuICAgICAgICAgICAgLy8gRmxhdHRlbiB0aGUgcGFyYW1ldGVyIGJpdHMgaW50byBhIHNpbmdsZSAyOC0gb3IgNDAtYml0IGxvbmdcbiAgICAgICAgICAgIGxldCBwYXJhbWV0ZXJEYXRhID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IHNpZGUgPSBzaWRlc1sodGhpcy5zaGlmdCArIGkpICUgNF07XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29tcGFjdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBFYWNoIHNpZGUgb2YgdGhlIGZvcm0gLi5YWFhYWFhYLiB3aGVyZSBYcyBhcmUgcGFyYW1ldGVyIGRhdGFcbiAgICAgICAgICAgICAgICAgICAgcGFyYW1ldGVyRGF0YSA8PD0gNztcbiAgICAgICAgICAgICAgICAgICAgcGFyYW1ldGVyRGF0YSArPSAoc2lkZSA+PiAxKSAmIDB4N0Y7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBFYWNoIHNpZGUgb2YgdGhlIGZvcm0gLi5YWFhYWC5YWFhYWC4gd2hlcmUgWHMgYXJlIHBhcmFtZXRlciBkYXRhXG4gICAgICAgICAgICAgICAgICAgIHBhcmFtZXRlckRhdGEgPDw9IDEwO1xuICAgICAgICAgICAgICAgICAgICBwYXJhbWV0ZXJEYXRhICs9ICgoc2lkZSA+PiAyKSAmICgweDFmIDw8IDUpKSArICgoc2lkZSA+PiAxKSAmIDB4MUYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIENvcnJlY3RzIHBhcmFtZXRlciBkYXRhIHVzaW5nIFJTLiAgUmV0dXJucyBqdXN0IHRoZSBkYXRhIHBvcnRpb25cbiAgICAgICAgICAgIC8vIHdpdGhvdXQgdGhlIGVycm9yIGNvcnJlY3Rpb24uXG4gICAgICAgICAgICBsZXQgY29ycmVjdGVkRGF0YSA9IHRoaXMuZ2V0Q29ycmVjdGVkUGFyYW1ldGVyRGF0YShwYXJhbWV0ZXJEYXRhLCB0aGlzLmNvbXBhY3QpO1xuICAgICAgICAgICAgaWYgKHRoaXMuY29tcGFjdCkge1xuICAgICAgICAgICAgICAgIC8vIDggYml0czogIDIgYml0cyBsYXllcnMgYW5kIDYgYml0cyBkYXRhIGJsb2Nrc1xuICAgICAgICAgICAgICAgIHRoaXMubmJMYXllcnMgPSAoY29ycmVjdGVkRGF0YSA+PiA2KSArIDE7XG4gICAgICAgICAgICAgICAgdGhpcy5uYkRhdGFCbG9ja3MgPSAoY29ycmVjdGVkRGF0YSAmIDB4M0YpICsgMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIDE2IGJpdHM6ICA1IGJpdHMgbGF5ZXJzIGFuZCAxMSBiaXRzIGRhdGEgYmxvY2tzXG4gICAgICAgICAgICAgICAgdGhpcy5uYkxheWVycyA9IChjb3JyZWN0ZWREYXRhID4+IDExKSArIDE7XG4gICAgICAgICAgICAgICAgdGhpcy5uYkRhdGFCbG9ja3MgPSAoY29ycmVjdGVkRGF0YSAmIDB4N0ZGKSArIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Um90YXRpb24oc2lkZXMsIGxlbmd0aCkge1xuICAgICAgICAgICAgLy8gSW4gYSBub3JtYWwgcGF0dGVybiwgd2UgZXhwZWN0IHRvIFNlZVxuICAgICAgICAgICAgLy8gICAqKiAgICAuKiAgICAgICAgICAgICBEICAgICAgIEFcbiAgICAgICAgICAgIC8vICAgKiAgICAgICpcbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyAgIC4gICAgICAqXG4gICAgICAgICAgICAvLyAgIC4uICAgIC4uICAgICAgICAgICAgIEMgICAgICAgQlxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIEdyYWIgdGhlIDMgYml0cyBmcm9tIGVhY2ggb2YgdGhlIHNpZGVzIHRoZSBmb3JtIHRoZSBsb2NhdG9yIHBhdHRlcm4gYW5kIGNvbmNhdGVuYXRlXG4gICAgICAgICAgICAvLyBpbnRvIGEgMTItYml0IGludGVnZXIuICBTdGFydCB3aXRoIHRoZSBiaXQgYXQgQVxuICAgICAgICAgICAgbGV0IGNvcm5lckJpdHMgPSAwO1xuICAgICAgICAgICAgc2lkZXMuZm9yRWFjaCgoc2lkZSwgaWR4LCBhcnIpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBYWC4uLi4uLlggd2hlcmUgWCdzIGFyZSBvcmllbnRhdGlvbiBtYXJrc1xuICAgICAgICAgICAgICAgIGxldCB0ID0gKChzaWRlID4+IChsZW5ndGggLSAyKSkgPDwgMSkgKyAoc2lkZSAmIDEpO1xuICAgICAgICAgICAgICAgIGNvcm5lckJpdHMgPSAoY29ybmVyQml0cyA8PCAzKSArIHQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vIGZvciAodmFyIHNpZGUgaW4gc2lkZXMpIHtcbiAgICAgICAgICAgIC8vICAgICAvLyBYWC4uLi4uLlggd2hlcmUgWCdzIGFyZSBvcmllbnRhdGlvbiBtYXJrc1xuICAgICAgICAgICAgLy8gICAgIHZhciB0ID0gKChzaWRlID4+IChsZW5ndGggLSAyKSkgPDwgMSkgKyAoc2lkZSAmIDEpO1xuICAgICAgICAgICAgLy8gICAgIGNvcm5lckJpdHMgPSAoY29ybmVyQml0cyA8PCAzKSArIHQ7XG4gICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICAvLyBNb3YgdGhlIGJvdHRvbSBiaXQgdG8gdGhlIHRvcCwgc28gdGhhdCB0aGUgdGhyZWUgYml0cyBvZiB0aGUgbG9jYXRvciBwYXR0ZXJuIGF0IEEgYXJlXG4gICAgICAgICAgICAvLyB0b2dldGhlci4gIGNvcm5lckJpdHMgaXMgbm93OlxuICAgICAgICAgICAgLy8gIDMgb3JpZW50YXRpb24gYml0cyBhdCBBIHx8IDMgb3JpZW50YXRpb24gYml0cyBhdCBCIHx8IC4uLiB8fCAzIG9yaWVudGF0aW9uIGJpdHMgYXQgRFxuICAgICAgICAgICAgY29ybmVyQml0cyA9ICgoY29ybmVyQml0cyAmIDEpIDw8IDExKSArIChjb3JuZXJCaXRzID4+IDEpO1xuICAgICAgICAgICAgLy8gVGhlIHJlc3VsdCBzaGlmdCBpbmRpY2F0ZXMgd2hpY2ggZWxlbWVudCBvZiBCdWxsc0V5ZUNvcm5lcnNbXSBnb2VzIGludG8gdGhlIHRvcC1sZWZ0XG4gICAgICAgICAgICAvLyBjb3JuZXIuIFNpbmNlIHRoZSBmb3VyIHJvdGF0aW9uIHZhbHVlcyBoYXZlIGEgSGFtbWluZyBkaXN0YW5jZSBvZiA4LCB3ZVxuICAgICAgICAgICAgLy8gY2FuIGVhc2lseSB0b2xlcmF0ZSB0d28gZXJyb3JzLlxuICAgICAgICAgICAgZm9yIChsZXQgc2hpZnQgPSAwOyBzaGlmdCA8IDQ7IHNoaWZ0KyspIHtcbiAgICAgICAgICAgICAgICBpZiAoSW50ZWdlci5iaXRDb3VudChjb3JuZXJCaXRzIF4gdGhpcy5FWFBFQ1RFRF9DT1JORVJfQklUU1tzaGlmdF0pIDw9IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNoaWZ0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb3JyZWN0cyB0aGUgcGFyYW1ldGVyIGJpdHMgdXNpbmcgUmVlZC1Tb2xvbW9uIGFsZ29yaXRobS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHBhcmFtZXRlckRhdGEgcGFyYW1ldGVyIGJpdHNcbiAgICAgICAgICogQHBhcmFtIGNvbXBhY3QgdHJ1ZSBpZiB0aGlzIGlzIGEgY29tcGFjdCBBenRlYyBjb2RlXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gaWYgdGhlIGFycmF5IGNvbnRhaW5zIHRvbyBtYW55IGVycm9yc1xuICAgICAgICAgKi9cbiAgICAgICAgZ2V0Q29ycmVjdGVkUGFyYW1ldGVyRGF0YShwYXJhbWV0ZXJEYXRhLCBjb21wYWN0KSB7XG4gICAgICAgICAgICBsZXQgbnVtQ29kZXdvcmRzO1xuICAgICAgICAgICAgbGV0IG51bURhdGFDb2Rld29yZHM7XG4gICAgICAgICAgICBpZiAoY29tcGFjdCkge1xuICAgICAgICAgICAgICAgIG51bUNvZGV3b3JkcyA9IDc7XG4gICAgICAgICAgICAgICAgbnVtRGF0YUNvZGV3b3JkcyA9IDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBudW1Db2Rld29yZHMgPSAxMDtcbiAgICAgICAgICAgICAgICBudW1EYXRhQ29kZXdvcmRzID0gNDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBudW1FQ0NvZGV3b3JkcyA9IG51bUNvZGV3b3JkcyAtIG51bURhdGFDb2Rld29yZHM7XG4gICAgICAgICAgICBsZXQgcGFyYW1ldGVyV29yZHMgPSBuZXcgSW50MzJBcnJheShudW1Db2Rld29yZHMpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IG51bUNvZGV3b3JkcyAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1ldGVyV29yZHNbaV0gPSBwYXJhbWV0ZXJEYXRhICYgMHhGO1xuICAgICAgICAgICAgICAgIHBhcmFtZXRlckRhdGEgPj49IDQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGxldCByc0RlY29kZXIgPSBuZXcgUmVlZFNvbG9tb25EZWNvZGVyKEdlbmVyaWNHRi5BWlRFQ19QQVJBTSk7XG4gICAgICAgICAgICAgICAgcnNEZWNvZGVyLmRlY29kZShwYXJhbWV0ZXJXb3JkcywgbnVtRUNDb2Rld29yZHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGlnbm9yZWQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFRvc3MgdGhlIGVycm9yIGNvcnJlY3Rpb24uICBKdXN0IHJldHVybiB0aGUgZGF0YSBhcyBhbiBpbnRlZ2VyXG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtRGF0YUNvZGV3b3JkczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gKHJlc3VsdCA8PCA0KSArIHBhcmFtZXRlcldvcmRzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRmluZHMgdGhlIGNvcm5lcnMgb2YgYSBidWxsLWV5ZSBjZW50ZXJlZCBvbiB0aGUgcGFzc2VkIHBvaW50LlxuICAgICAgICAgKiBUaGlzIHJldHVybnMgdGhlIGNlbnRlcnMgb2YgdGhlIGRpYWdvbmFsIHBvaW50cyBqdXN0IG91dHNpZGUgdGhlIGJ1bGwncyBleWVcbiAgICAgICAgICogUmV0dXJucyBbdG9wUmlnaHQsIGJvdHRvbVJpZ2h0LCBib3R0b21MZWZ0LCB0b3BMZWZ0XVxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gcENlbnRlciBDZW50ZXIgcG9pbnRcbiAgICAgICAgICogQHJldHVybiBUaGUgY29ybmVycyBvZiB0aGUgYnVsbC1leWVcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBJZiBubyB2YWxpZCBidWxsLWV5ZSBjYW4gYmUgZm91bmRcbiAgICAgICAgICovXG4gICAgICAgIGdldEJ1bGxzRXllQ29ybmVycyhwQ2VudGVyKSB7XG4gICAgICAgICAgICBsZXQgcGluYSA9IHBDZW50ZXI7XG4gICAgICAgICAgICBsZXQgcGluYiA9IHBDZW50ZXI7XG4gICAgICAgICAgICBsZXQgcGluYyA9IHBDZW50ZXI7XG4gICAgICAgICAgICBsZXQgcGluZCA9IHBDZW50ZXI7XG4gICAgICAgICAgICBsZXQgY29sb3IgPSB0cnVlO1xuICAgICAgICAgICAgZm9yICh0aGlzLm5iQ2VudGVyTGF5ZXJzID0gMTsgdGhpcy5uYkNlbnRlckxheWVycyA8IDk7IHRoaXMubmJDZW50ZXJMYXllcnMrKykge1xuICAgICAgICAgICAgICAgIGxldCBwb3V0YSA9IHRoaXMuZ2V0Rmlyc3REaWZmZXJlbnQocGluYSwgY29sb3IsIDEsIC0xKTtcbiAgICAgICAgICAgICAgICBsZXQgcG91dGIgPSB0aGlzLmdldEZpcnN0RGlmZmVyZW50KHBpbmIsIGNvbG9yLCAxLCAxKTtcbiAgICAgICAgICAgICAgICBsZXQgcG91dGMgPSB0aGlzLmdldEZpcnN0RGlmZmVyZW50KHBpbmMsIGNvbG9yLCAtMSwgMSk7XG4gICAgICAgICAgICAgICAgbGV0IHBvdXRkID0gdGhpcy5nZXRGaXJzdERpZmZlcmVudChwaW5kLCBjb2xvciwgLTEsIC0xKTtcbiAgICAgICAgICAgICAgICAvLyBkICAgICAgYVxuICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgLy8gYyAgICAgIGJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5uYkNlbnRlckxheWVycyA+IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHEgPSAodGhpcy5kaXN0YW5jZVBvaW50KHBvdXRkLCBwb3V0YSkgKiB0aGlzLm5iQ2VudGVyTGF5ZXJzKSAvICh0aGlzLmRpc3RhbmNlUG9pbnQocGluZCwgcGluYSkgKiAodGhpcy5uYkNlbnRlckxheWVycyArIDIpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHEgPCAwLjc1IHx8IHEgPiAxLjI1IHx8ICF0aGlzLmlzV2hpdGVPckJsYWNrUmVjdGFuZ2xlKHBvdXRhLCBwb3V0YiwgcG91dGMsIHBvdXRkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcGluYSA9IHBvdXRhO1xuICAgICAgICAgICAgICAgIHBpbmIgPSBwb3V0YjtcbiAgICAgICAgICAgICAgICBwaW5jID0gcG91dGM7XG4gICAgICAgICAgICAgICAgcGluZCA9IHBvdXRkO1xuICAgICAgICAgICAgICAgIGNvbG9yID0gIWNvbG9yO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMubmJDZW50ZXJMYXllcnMgIT09IDUgJiYgdGhpcy5uYkNlbnRlckxheWVycyAhPT0gNykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jb21wYWN0ID0gdGhpcy5uYkNlbnRlckxheWVycyA9PT0gNTtcbiAgICAgICAgICAgIC8vIEV4cGFuZCB0aGUgc3F1YXJlIGJ5IC41IHBpeGVsIGluIGVhY2ggZGlyZWN0aW9uIHNvIHRoYXQgd2UncmUgb24gdGhlIGJvcmRlclxuICAgICAgICAgICAgLy8gYmV0d2VlbiB0aGUgd2hpdGUgc3F1YXJlIGFuZCB0aGUgYmxhY2sgc3F1YXJlXG4gICAgICAgICAgICBsZXQgcGluYXggPSBuZXcgUmVzdWx0UG9pbnQocGluYS5nZXRYKCkgKyAwLjUsIHBpbmEuZ2V0WSgpIC0gMC41KTtcbiAgICAgICAgICAgIGxldCBwaW5ieCA9IG5ldyBSZXN1bHRQb2ludChwaW5iLmdldFgoKSArIDAuNSwgcGluYi5nZXRZKCkgKyAwLjUpO1xuICAgICAgICAgICAgbGV0IHBpbmN4ID0gbmV3IFJlc3VsdFBvaW50KHBpbmMuZ2V0WCgpIC0gMC41LCBwaW5jLmdldFkoKSArIDAuNSk7XG4gICAgICAgICAgICBsZXQgcGluZHggPSBuZXcgUmVzdWx0UG9pbnQocGluZC5nZXRYKCkgLSAwLjUsIHBpbmQuZ2V0WSgpIC0gMC41KTtcbiAgICAgICAgICAgIC8vIEV4cGFuZCB0aGUgc3F1YXJlIHNvIHRoYXQgaXRzIGNvcm5lcnMgYXJlIHRoZSBjZW50ZXJzIG9mIHRoZSBwb2ludHNcbiAgICAgICAgICAgIC8vIGp1c3Qgb3V0c2lkZSB0aGUgYnVsbCdzIGV5ZS5cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmV4cGFuZFNxdWFyZShbcGluYXgsIHBpbmJ4LCBwaW5jeCwgcGluZHhdLCAyICogdGhpcy5uYkNlbnRlckxheWVycyAtIDMsIDIgKiB0aGlzLm5iQ2VudGVyTGF5ZXJzKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRmluZHMgYSBjYW5kaWRhdGUgY2VudGVyIHBvaW50IG9mIGFuIEF6dGVjIGNvZGUgZnJvbSBhbiBpbWFnZVxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIHRoZSBjZW50ZXIgcG9pbnRcbiAgICAgICAgICovXG4gICAgICAgIGdldE1hdHJpeENlbnRlcigpIHtcbiAgICAgICAgICAgIGxldCBwb2ludEE7XG4gICAgICAgICAgICBsZXQgcG9pbnRCO1xuICAgICAgICAgICAgbGV0IHBvaW50QztcbiAgICAgICAgICAgIGxldCBwb2ludEQ7XG4gICAgICAgICAgICAvLyBHZXQgYSB3aGl0ZSByZWN0YW5nbGUgdGhhdCBjYW4gYmUgdGhlIGJvcmRlciBvZiB0aGUgbWF0cml4IGluIGNlbnRlciBidWxsJ3MgZXllIG9yXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGxldCBjb3JuZXJQb2ludHMgPSBuZXcgV2hpdGVSZWN0YW5nbGVEZXRlY3Rvcih0aGlzLmltYWdlKS5kZXRlY3QoKTtcbiAgICAgICAgICAgICAgICBwb2ludEEgPSBjb3JuZXJQb2ludHNbMF07XG4gICAgICAgICAgICAgICAgcG9pbnRCID0gY29ybmVyUG9pbnRzWzFdO1xuICAgICAgICAgICAgICAgIHBvaW50QyA9IGNvcm5lclBvaW50c1syXTtcbiAgICAgICAgICAgICAgICBwb2ludEQgPSBjb3JuZXJQb2ludHNbM107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgZXhjZXB0aW9uIGNhbiBiZSBpbiBjYXNlIHRoZSBpbml0aWFsIHJlY3RhbmdsZSBpcyB3aGl0ZVxuICAgICAgICAgICAgICAgIC8vIEluIHRoYXQgY2FzZSwgc3VyZWx5IGluIHRoZSBidWxsJ3MgZXllLCB3ZSB0cnkgdG8gZXhwYW5kIHRoZSByZWN0YW5nbGUuXG4gICAgICAgICAgICAgICAgbGV0IGN4ID0gdGhpcy5pbWFnZS5nZXRXaWR0aCgpIC8gMjtcbiAgICAgICAgICAgICAgICBsZXQgY3kgPSB0aGlzLmltYWdlLmdldEhlaWdodCgpIC8gMjtcbiAgICAgICAgICAgICAgICBwb2ludEEgPSB0aGlzLmdldEZpcnN0RGlmZmVyZW50KG5ldyBQb2ludChjeCArIDcsIGN5IC0gNyksIGZhbHNlLCAxLCAtMSkudG9SZXN1bHRQb2ludCgpO1xuICAgICAgICAgICAgICAgIHBvaW50QiA9IHRoaXMuZ2V0Rmlyc3REaWZmZXJlbnQobmV3IFBvaW50KGN4ICsgNywgY3kgKyA3KSwgZmFsc2UsIDEsIDEpLnRvUmVzdWx0UG9pbnQoKTtcbiAgICAgICAgICAgICAgICBwb2ludEMgPSB0aGlzLmdldEZpcnN0RGlmZmVyZW50KG5ldyBQb2ludChjeCAtIDcsIGN5ICsgNyksIGZhbHNlLCAtMSwgMSkudG9SZXN1bHRQb2ludCgpO1xuICAgICAgICAgICAgICAgIHBvaW50RCA9IHRoaXMuZ2V0Rmlyc3REaWZmZXJlbnQobmV3IFBvaW50KGN4IC0gNywgY3kgLSA3KSwgZmFsc2UsIC0xLCAtMSkudG9SZXN1bHRQb2ludCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQ29tcHV0ZSB0aGUgY2VudGVyIG9mIHRoZSByZWN0YW5nbGVcbiAgICAgICAgICAgIGxldCBjeCA9IE1hdGhVdGlscy5yb3VuZCgocG9pbnRBLmdldFgoKSArIHBvaW50RC5nZXRYKCkgKyBwb2ludEIuZ2V0WCgpICsgcG9pbnRDLmdldFgoKSkgLyA0LjApO1xuICAgICAgICAgICAgbGV0IGN5ID0gTWF0aFV0aWxzLnJvdW5kKChwb2ludEEuZ2V0WSgpICsgcG9pbnRELmdldFkoKSArIHBvaW50Qi5nZXRZKCkgKyBwb2ludEMuZ2V0WSgpKSAvIDQuMCk7XG4gICAgICAgICAgICAvLyBSZWRldGVybWluZSB0aGUgd2hpdGUgcmVjdGFuZ2xlIHN0YXJ0aW5nIGZyb20gcHJldmlvdXNseSBjb21wdXRlZCBjZW50ZXIuXG4gICAgICAgICAgICAvLyBUaGlzIHdpbGwgZW5zdXJlIHRoYXQgd2UgZW5kIHVwIHdpdGggYSB3aGl0ZSByZWN0YW5nbGUgaW4gY2VudGVyIGJ1bGwncyBleWVcbiAgICAgICAgICAgIC8vIGluIG9yZGVyIHRvIGNvbXB1dGUgYSBtb3JlIGFjY3VyYXRlIGNlbnRlci5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbGV0IGNvcm5lclBvaW50cyA9IG5ldyBXaGl0ZVJlY3RhbmdsZURldGVjdG9yKHRoaXMuaW1hZ2UsIDE1LCBjeCwgY3kpLmRldGVjdCgpO1xuICAgICAgICAgICAgICAgIHBvaW50QSA9IGNvcm5lclBvaW50c1swXTtcbiAgICAgICAgICAgICAgICBwb2ludEIgPSBjb3JuZXJQb2ludHNbMV07XG4gICAgICAgICAgICAgICAgcG9pbnRDID0gY29ybmVyUG9pbnRzWzJdO1xuICAgICAgICAgICAgICAgIHBvaW50RCA9IGNvcm5lclBvaW50c1szXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBleGNlcHRpb24gY2FuIGJlIGluIGNhc2UgdGhlIGluaXRpYWwgcmVjdGFuZ2xlIGlzIHdoaXRlXG4gICAgICAgICAgICAgICAgLy8gSW4gdGhhdCBjYXNlIHdlIHRyeSB0byBleHBhbmQgdGhlIHJlY3RhbmdsZS5cbiAgICAgICAgICAgICAgICBwb2ludEEgPSB0aGlzLmdldEZpcnN0RGlmZmVyZW50KG5ldyBQb2ludChjeCArIDcsIGN5IC0gNyksIGZhbHNlLCAxLCAtMSkudG9SZXN1bHRQb2ludCgpO1xuICAgICAgICAgICAgICAgIHBvaW50QiA9IHRoaXMuZ2V0Rmlyc3REaWZmZXJlbnQobmV3IFBvaW50KGN4ICsgNywgY3kgKyA3KSwgZmFsc2UsIDEsIDEpLnRvUmVzdWx0UG9pbnQoKTtcbiAgICAgICAgICAgICAgICBwb2ludEMgPSB0aGlzLmdldEZpcnN0RGlmZmVyZW50KG5ldyBQb2ludChjeCAtIDcsIGN5ICsgNyksIGZhbHNlLCAtMSwgMSkudG9SZXN1bHRQb2ludCgpO1xuICAgICAgICAgICAgICAgIHBvaW50RCA9IHRoaXMuZ2V0Rmlyc3REaWZmZXJlbnQobmV3IFBvaW50KGN4IC0gNywgY3kgLSA3KSwgZmFsc2UsIC0xLCAtMSkudG9SZXN1bHRQb2ludCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gUmVjb21wdXRlIHRoZSBjZW50ZXIgb2YgdGhlIHJlY3RhbmdsZVxuICAgICAgICAgICAgY3ggPSBNYXRoVXRpbHMucm91bmQoKHBvaW50QS5nZXRYKCkgKyBwb2ludEQuZ2V0WCgpICsgcG9pbnRCLmdldFgoKSArIHBvaW50Qy5nZXRYKCkpIC8gNC4wKTtcbiAgICAgICAgICAgIGN5ID0gTWF0aFV0aWxzLnJvdW5kKChwb2ludEEuZ2V0WSgpICsgcG9pbnRELmdldFkoKSArIHBvaW50Qi5nZXRZKCkgKyBwb2ludEMuZ2V0WSgpKSAvIDQuMCk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFBvaW50KGN4LCBjeSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdldHMgdGhlIEF6dGVjIGNvZGUgY29ybmVycyBmcm9tIHRoZSBidWxsJ3MgZXllIGNvcm5lcnMgYW5kIHRoZSBwYXJhbWV0ZXJzLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gYnVsbHNFeWVDb3JuZXJzIHRoZSBhcnJheSBvZiBidWxsJ3MgZXllIGNvcm5lcnNcbiAgICAgICAgICogQHJldHVybiB0aGUgYXJyYXkgb2YgYXp0ZWMgY29kZSBjb3JuZXJzXG4gICAgICAgICAqL1xuICAgICAgICBnZXRNYXRyaXhDb3JuZXJQb2ludHMoYnVsbHNFeWVDb3JuZXJzKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5leHBhbmRTcXVhcmUoYnVsbHNFeWVDb3JuZXJzLCAyICogdGhpcy5uYkNlbnRlckxheWVycywgdGhpcy5nZXREaW1lbnNpb24oKSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBCaXRNYXRyaXggYnkgc2FtcGxpbmcgdGhlIHByb3ZpZGVkIGltYWdlLlxuICAgICAgICAgKiB0b3BMZWZ0LCB0b3BSaWdodCwgYm90dG9tUmlnaHQsIGFuZCBib3R0b21MZWZ0IGFyZSB0aGUgY2VudGVycyBvZiB0aGUgc3F1YXJlcyBvbiB0aGVcbiAgICAgICAgICogZGlhZ29uYWwganVzdCBvdXRzaWRlIHRoZSBidWxsJ3MgZXllLlxuICAgICAgICAgKi9cbiAgICAgICAgc2FtcGxlR3JpZChpbWFnZSwgdG9wTGVmdCwgdG9wUmlnaHQsIGJvdHRvbVJpZ2h0LCBib3R0b21MZWZ0KSB7XG4gICAgICAgICAgICBsZXQgc2FtcGxlciA9IEdyaWRTYW1wbGVySW5zdGFuY2UuZ2V0SW5zdGFuY2UoKTtcbiAgICAgICAgICAgIGxldCBkaW1lbnNpb24gPSB0aGlzLmdldERpbWVuc2lvbigpO1xuICAgICAgICAgICAgbGV0IGxvdyA9IGRpbWVuc2lvbiAvIDIgLSB0aGlzLm5iQ2VudGVyTGF5ZXJzO1xuICAgICAgICAgICAgbGV0IGhpZ2ggPSBkaW1lbnNpb24gLyAyICsgdGhpcy5uYkNlbnRlckxheWVycztcbiAgICAgICAgICAgIHJldHVybiBzYW1wbGVyLnNhbXBsZUdyaWQoaW1hZ2UsIGRpbWVuc2lvbiwgZGltZW5zaW9uLCBsb3csIGxvdywgLy8gdG9wbGVmdFxuICAgICAgICAgICAgaGlnaCwgbG93LCAvLyB0b3ByaWdodFxuICAgICAgICAgICAgaGlnaCwgaGlnaCwgLy8gYm90dG9tcmlnaHRcbiAgICAgICAgICAgIGxvdywgaGlnaCwgLy8gYm90dG9tbGVmdFxuICAgICAgICAgICAgdG9wTGVmdC5nZXRYKCksIHRvcExlZnQuZ2V0WSgpLCB0b3BSaWdodC5nZXRYKCksIHRvcFJpZ2h0LmdldFkoKSwgYm90dG9tUmlnaHQuZ2V0WCgpLCBib3R0b21SaWdodC5nZXRZKCksIGJvdHRvbUxlZnQuZ2V0WCgpLCBib3R0b21MZWZ0LmdldFkoKSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNhbXBsZXMgYSBsaW5lLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gcDEgICBzdGFydCBwb2ludCAoaW5jbHVzaXZlKVxuICAgICAgICAgKiBAcGFyYW0gcDIgICBlbmQgcG9pbnQgKGV4Y2x1c2l2ZSlcbiAgICAgICAgICogQHBhcmFtIHNpemUgbnVtYmVyIG9mIGJpdHNcbiAgICAgICAgICogQHJldHVybiB0aGUgYXJyYXkgb2YgYml0cyBhcyBhbiBpbnQgKGZpcnN0IGJpdCBpcyBoaWdoLW9yZGVyIGJpdCBvZiByZXN1bHQpXG4gICAgICAgICAqL1xuICAgICAgICBzYW1wbGVMaW5lKHAxLCBwMiwgc2l6ZSkge1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IDA7XG4gICAgICAgICAgICBsZXQgZCA9IHRoaXMuZGlzdGFuY2VSZXN1bHRQb2ludChwMSwgcDIpO1xuICAgICAgICAgICAgbGV0IG1vZHVsZVNpemUgPSBkIC8gc2l6ZTtcbiAgICAgICAgICAgIGxldCBweCA9IHAxLmdldFgoKTtcbiAgICAgICAgICAgIGxldCBweSA9IHAxLmdldFkoKTtcbiAgICAgICAgICAgIGxldCBkeCA9IG1vZHVsZVNpemUgKiAocDIuZ2V0WCgpIC0gcDEuZ2V0WCgpKSAvIGQ7XG4gICAgICAgICAgICBsZXQgZHkgPSBtb2R1bGVTaXplICogKHAyLmdldFkoKSAtIHAxLmdldFkoKSkgLyBkO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pbWFnZS5nZXQoTWF0aFV0aWxzLnJvdW5kKHB4ICsgaSAqIGR4KSwgTWF0aFV0aWxzLnJvdW5kKHB5ICsgaSAqIGR5KSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0IHw9IDEgPDwgKHNpemUgLSBpIC0gMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB0cnVlIGlmIHRoZSBib3JkZXIgb2YgdGhlIHJlY3RhbmdsZSBwYXNzZWQgaW4gcGFyYW1ldGVyIGlzIGNvbXBvdW5kIG9mIHdoaXRlIHBvaW50cyBvbmx5XG4gICAgICAgICAqICAgICAgICAgb3IgYmxhY2sgcG9pbnRzIG9ubHlcbiAgICAgICAgICovXG4gICAgICAgIGlzV2hpdGVPckJsYWNrUmVjdGFuZ2xlKHAxLCBwMiwgcDMsIHA0KSB7XG4gICAgICAgICAgICBsZXQgY29yciA9IDM7XG4gICAgICAgICAgICBwMSA9IG5ldyBQb2ludChwMS5nZXRYKCkgLSBjb3JyLCBwMS5nZXRZKCkgKyBjb3JyKTtcbiAgICAgICAgICAgIHAyID0gbmV3IFBvaW50KHAyLmdldFgoKSAtIGNvcnIsIHAyLmdldFkoKSAtIGNvcnIpO1xuICAgICAgICAgICAgcDMgPSBuZXcgUG9pbnQocDMuZ2V0WCgpICsgY29yciwgcDMuZ2V0WSgpIC0gY29ycik7XG4gICAgICAgICAgICBwNCA9IG5ldyBQb2ludChwNC5nZXRYKCkgKyBjb3JyLCBwNC5nZXRZKCkgKyBjb3JyKTtcbiAgICAgICAgICAgIGxldCBjSW5pdCA9IHRoaXMuZ2V0Q29sb3IocDQsIHAxKTtcbiAgICAgICAgICAgIGlmIChjSW5pdCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBjID0gdGhpcy5nZXRDb2xvcihwMSwgcDIpO1xuICAgICAgICAgICAgaWYgKGMgIT09IGNJbml0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYyA9IHRoaXMuZ2V0Q29sb3IocDIsIHAzKTtcbiAgICAgICAgICAgIGlmIChjICE9PSBjSW5pdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGMgPSB0aGlzLmdldENvbG9yKHAzLCBwNCk7XG4gICAgICAgICAgICByZXR1cm4gYyA9PT0gY0luaXQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdldHMgdGhlIGNvbG9yIG9mIGEgc2VnbWVudFxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIDEgaWYgc2VnbWVudCBtb3JlIHRoYW4gOTAlIGJsYWNrLCAtMSBpZiBzZWdtZW50IGlzIG1vcmUgdGhhbiA5MCUgd2hpdGUsIDAgZWxzZVxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0Q29sb3IocDEsIHAyKSB7XG4gICAgICAgICAgICBsZXQgZCA9IHRoaXMuZGlzdGFuY2VQb2ludChwMSwgcDIpO1xuICAgICAgICAgICAgbGV0IGR4ID0gKHAyLmdldFgoKSAtIHAxLmdldFgoKSkgLyBkO1xuICAgICAgICAgICAgbGV0IGR5ID0gKHAyLmdldFkoKSAtIHAxLmdldFkoKSkgLyBkO1xuICAgICAgICAgICAgbGV0IGVycm9yID0gMDtcbiAgICAgICAgICAgIGxldCBweCA9IHAxLmdldFgoKTtcbiAgICAgICAgICAgIGxldCBweSA9IHAxLmdldFkoKTtcbiAgICAgICAgICAgIGxldCBjb2xvck1vZGVsID0gdGhpcy5pbWFnZS5nZXQocDEuZ2V0WCgpLCBwMS5nZXRZKCkpO1xuICAgICAgICAgICAgbGV0IGlNYXggPSBNYXRoLmNlaWwoZCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlNYXg7IGkrKykge1xuICAgICAgICAgICAgICAgIHB4ICs9IGR4O1xuICAgICAgICAgICAgICAgIHB5ICs9IGR5O1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmltYWdlLmdldChNYXRoVXRpbHMucm91bmQocHgpLCBNYXRoVXRpbHMucm91bmQocHkpKSAhPT0gY29sb3JNb2RlbCkge1xuICAgICAgICAgICAgICAgICAgICBlcnJvcisrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBlcnJSYXRpbyA9IGVycm9yIC8gZDtcbiAgICAgICAgICAgIGlmIChlcnJSYXRpbyA+IDAuMSAmJiBlcnJSYXRpbyA8IDAuOSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIChlcnJSYXRpbyA8PSAwLjEpID09PSBjb2xvck1vZGVsID8gMSA6IC0xO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHZXRzIHRoZSBjb29yZGluYXRlIG9mIHRoZSBmaXJzdCBwb2ludCB3aXRoIGEgZGlmZmVyZW50IGNvbG9yIGluIHRoZSBnaXZlbiBkaXJlY3Rpb25cbiAgICAgICAgICovXG4gICAgICAgIGdldEZpcnN0RGlmZmVyZW50KGluaXQsIGNvbG9yLCBkeCwgZHkpIHtcbiAgICAgICAgICAgIGxldCB4ID0gaW5pdC5nZXRYKCkgKyBkeDtcbiAgICAgICAgICAgIGxldCB5ID0gaW5pdC5nZXRZKCkgKyBkeTtcbiAgICAgICAgICAgIHdoaWxlICh0aGlzLmlzVmFsaWQoeCwgeSkgJiYgdGhpcy5pbWFnZS5nZXQoeCwgeSkgPT09IGNvbG9yKSB7XG4gICAgICAgICAgICAgICAgeCArPSBkeDtcbiAgICAgICAgICAgICAgICB5ICs9IGR5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgeCAtPSBkeDtcbiAgICAgICAgICAgIHkgLT0gZHk7XG4gICAgICAgICAgICB3aGlsZSAodGhpcy5pc1ZhbGlkKHgsIHkpICYmIHRoaXMuaW1hZ2UuZ2V0KHgsIHkpID09PSBjb2xvcikge1xuICAgICAgICAgICAgICAgIHggKz0gZHg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB4IC09IGR4O1xuICAgICAgICAgICAgd2hpbGUgKHRoaXMuaXNWYWxpZCh4LCB5KSAmJiB0aGlzLmltYWdlLmdldCh4LCB5KSA9PT0gY29sb3IpIHtcbiAgICAgICAgICAgICAgICB5ICs9IGR5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgeSAtPSBkeTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUG9pbnQoeCwgeSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEV4cGFuZCB0aGUgc3F1YXJlIHJlcHJlc2VudGVkIGJ5IHRoZSBjb3JuZXIgcG9pbnRzIGJ5IHB1c2hpbmcgb3V0IGVxdWFsbHkgaW4gYWxsIGRpcmVjdGlvbnNcbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGNvcm5lclBvaW50cyB0aGUgY29ybmVycyBvZiB0aGUgc3F1YXJlLCB3aGljaCBoYXMgdGhlIGJ1bGwncyBleWUgYXQgaXRzIGNlbnRlclxuICAgICAgICAgKiBAcGFyYW0gb2xkU2lkZSB0aGUgb3JpZ2luYWwgbGVuZ3RoIG9mIHRoZSBzaWRlIG9mIHRoZSBzcXVhcmUgaW4gdGhlIHRhcmdldCBiaXQgbWF0cml4XG4gICAgICAgICAqIEBwYXJhbSBuZXdTaWRlIHRoZSBuZXcgbGVuZ3RoIG9mIHRoZSBzaXplIG9mIHRoZSBzcXVhcmUgaW4gdGhlIHRhcmdldCBiaXQgbWF0cml4XG4gICAgICAgICAqIEByZXR1cm4gdGhlIGNvcm5lcnMgb2YgdGhlIGV4cGFuZGVkIHNxdWFyZVxuICAgICAgICAgKi9cbiAgICAgICAgZXhwYW5kU3F1YXJlKGNvcm5lclBvaW50cywgb2xkU2lkZSwgbmV3U2lkZSkge1xuICAgICAgICAgICAgbGV0IHJhdGlvID0gbmV3U2lkZSAvICgyLjAgKiBvbGRTaWRlKTtcbiAgICAgICAgICAgIGxldCBkeCA9IGNvcm5lclBvaW50c1swXS5nZXRYKCkgLSBjb3JuZXJQb2ludHNbMl0uZ2V0WCgpO1xuICAgICAgICAgICAgbGV0IGR5ID0gY29ybmVyUG9pbnRzWzBdLmdldFkoKSAtIGNvcm5lclBvaW50c1syXS5nZXRZKCk7XG4gICAgICAgICAgICBsZXQgY2VudGVyeCA9IChjb3JuZXJQb2ludHNbMF0uZ2V0WCgpICsgY29ybmVyUG9pbnRzWzJdLmdldFgoKSkgLyAyLjA7XG4gICAgICAgICAgICBsZXQgY2VudGVyeSA9IChjb3JuZXJQb2ludHNbMF0uZ2V0WSgpICsgY29ybmVyUG9pbnRzWzJdLmdldFkoKSkgLyAyLjA7XG4gICAgICAgICAgICBsZXQgcmVzdWx0MCA9IG5ldyBSZXN1bHRQb2ludChjZW50ZXJ4ICsgcmF0aW8gKiBkeCwgY2VudGVyeSArIHJhdGlvICogZHkpO1xuICAgICAgICAgICAgbGV0IHJlc3VsdDIgPSBuZXcgUmVzdWx0UG9pbnQoY2VudGVyeCAtIHJhdGlvICogZHgsIGNlbnRlcnkgLSByYXRpbyAqIGR5KTtcbiAgICAgICAgICAgIGR4ID0gY29ybmVyUG9pbnRzWzFdLmdldFgoKSAtIGNvcm5lclBvaW50c1szXS5nZXRYKCk7XG4gICAgICAgICAgICBkeSA9IGNvcm5lclBvaW50c1sxXS5nZXRZKCkgLSBjb3JuZXJQb2ludHNbM10uZ2V0WSgpO1xuICAgICAgICAgICAgY2VudGVyeCA9IChjb3JuZXJQb2ludHNbMV0uZ2V0WCgpICsgY29ybmVyUG9pbnRzWzNdLmdldFgoKSkgLyAyLjA7XG4gICAgICAgICAgICBjZW50ZXJ5ID0gKGNvcm5lclBvaW50c1sxXS5nZXRZKCkgKyBjb3JuZXJQb2ludHNbM10uZ2V0WSgpKSAvIDIuMDtcbiAgICAgICAgICAgIGxldCByZXN1bHQxID0gbmV3IFJlc3VsdFBvaW50KGNlbnRlcnggKyByYXRpbyAqIGR4LCBjZW50ZXJ5ICsgcmF0aW8gKiBkeSk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0MyA9IG5ldyBSZXN1bHRQb2ludChjZW50ZXJ4IC0gcmF0aW8gKiBkeCwgY2VudGVyeSAtIHJhdGlvICogZHkpO1xuICAgICAgICAgICAgbGV0IHJlc3VsdHMgPSBbcmVzdWx0MCwgcmVzdWx0MSwgcmVzdWx0MiwgcmVzdWx0M107XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICAgICAgfVxuICAgICAgICBpc1ZhbGlkKHgsIHkpIHtcbiAgICAgICAgICAgIHJldHVybiB4ID49IDAgJiYgeCA8IHRoaXMuaW1hZ2UuZ2V0V2lkdGgoKSAmJiB5ID4gMCAmJiB5IDwgdGhpcy5pbWFnZS5nZXRIZWlnaHQoKTtcbiAgICAgICAgfVxuICAgICAgICBpc1ZhbGlkUG9pbnQocG9pbnQpIHtcbiAgICAgICAgICAgIGxldCB4ID0gTWF0aFV0aWxzLnJvdW5kKHBvaW50LmdldFgoKSk7XG4gICAgICAgICAgICBsZXQgeSA9IE1hdGhVdGlscy5yb3VuZChwb2ludC5nZXRZKCkpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaXNWYWxpZCh4LCB5KTtcbiAgICAgICAgfVxuICAgICAgICBkaXN0YW5jZVBvaW50KGEsIGIpIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoVXRpbHMuZGlzdGFuY2UoYS5nZXRYKCksIGEuZ2V0WSgpLCBiLmdldFgoKSwgYi5nZXRZKCkpO1xuICAgICAgICB9XG4gICAgICAgIGRpc3RhbmNlUmVzdWx0UG9pbnQoYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGhVdGlscy5kaXN0YW5jZShhLmdldFgoKSwgYS5nZXRZKCksIGIuZ2V0WCgpLCBiLmdldFkoKSk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RGltZW5zaW9uKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuY29tcGFjdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiA0ICogdGhpcy5uYkxheWVycyArIDExO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMubmJMYXllcnMgPD0gNCkge1xuICAgICAgICAgICAgICAgIHJldHVybiA0ICogdGhpcy5uYkxheWVycyArIDE1O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIDQgKiB0aGlzLm5iTGF5ZXJzICsgMiAqIChJbnRlZ2VyLnRydW5jRGl2aXNpb24oKHRoaXMubmJMYXllcnMgLSA0KSwgOCkgKyAxKSArIDE1O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAxMCBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLkxpc3Q7XG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5NYXA7XG4gICAgLyoqXG4gICAgICogVGhpcyBpbXBsZW1lbnRhdGlvbiBjYW4gZGV0ZWN0IGFuZCBkZWNvZGUgQXp0ZWMgY29kZXMgaW4gYW4gaW1hZ2UuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIERhdmlkIE9saXZpZXJcbiAgICAgKi9cbiAgICBjbGFzcyBBenRlY1JlYWRlciB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBMb2NhdGVzIGFuZCBkZWNvZGVzIGEgRGF0YSBNYXRyaXggY29kZSBpbiBhbiBpbWFnZS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiBhIFN0cmluZyByZXByZXNlbnRpbmcgdGhlIGNvbnRlbnQgZW5jb2RlZCBieSB0aGUgRGF0YSBNYXRyaXggY29kZVxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIGEgRGF0YSBNYXRyaXggY29kZSBjYW5ub3QgYmUgZm91bmRcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb24gaWYgYSBEYXRhIE1hdHJpeCBjb2RlIGNhbm5vdCBiZSBkZWNvZGVkXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGUoaW1hZ2UsIGhpbnRzID0gbnVsbCkge1xuICAgICAgICAgICAgbGV0IGV4Y2VwdGlvbiA9IG51bGw7XG4gICAgICAgICAgICBsZXQgZGV0ZWN0b3IgPSBuZXcgRGV0ZWN0b3IoaW1hZ2UuZ2V0QmxhY2tNYXRyaXgoKSk7XG4gICAgICAgICAgICBsZXQgcG9pbnRzID0gbnVsbDtcbiAgICAgICAgICAgIGxldCBkZWNvZGVyUmVzdWx0ID0gbnVsbDtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbGV0IGRldGVjdG9yUmVzdWx0ID0gZGV0ZWN0b3IuZGV0ZWN0TWlycm9yKGZhbHNlKTtcbiAgICAgICAgICAgICAgICBwb2ludHMgPSBkZXRlY3RvclJlc3VsdC5nZXRQb2ludHMoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlcG9ydEZvdW5kUmVzdWx0UG9pbnRzKGhpbnRzLCBwb2ludHMpO1xuICAgICAgICAgICAgICAgIGRlY29kZXJSZXN1bHQgPSBuZXcgRGVjb2RlcigpLmRlY29kZShkZXRlY3RvclJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGV4Y2VwdGlvbiA9IGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZGVjb2RlclJlc3VsdCA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGRldGVjdG9yUmVzdWx0ID0gZGV0ZWN0b3IuZGV0ZWN0TWlycm9yKHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBwb2ludHMgPSBkZXRlY3RvclJlc3VsdC5nZXRQb2ludHMoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXBvcnRGb3VuZFJlc3VsdFBvaW50cyhoaW50cywgcG9pbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgZGVjb2RlclJlc3VsdCA9IG5ldyBEZWNvZGVyKCkuZGVjb2RlKGRldGVjdG9yUmVzdWx0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGV4Y2VwdGlvbiAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBleGNlcHRpb247XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gbmV3IFJlc3VsdChkZWNvZGVyUmVzdWx0LmdldFRleHQoKSwgZGVjb2RlclJlc3VsdC5nZXRSYXdCeXRlcygpLCBkZWNvZGVyUmVzdWx0LmdldE51bUJpdHMoKSwgcG9pbnRzLCBCYXJjb2RlRm9ybWF0JDEuQVpURUMsIFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpKTtcbiAgICAgICAgICAgIGxldCBieXRlU2VnbWVudHMgPSBkZWNvZGVyUmVzdWx0LmdldEJ5dGVTZWdtZW50cygpO1xuICAgICAgICAgICAgaWYgKGJ5dGVTZWdtZW50cyAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1dE1ldGFkYXRhKFJlc3VsdE1ldGFkYXRhVHlwZSQxLkJZVEVfU0VHTUVOVFMsIGJ5dGVTZWdtZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZWNMZXZlbCA9IGRlY29kZXJSZXN1bHQuZ2V0RUNMZXZlbCgpO1xuICAgICAgICAgICAgaWYgKGVjTGV2ZWwgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXRNZXRhZGF0YShSZXN1bHRNZXRhZGF0YVR5cGUkMS5FUlJPUl9DT1JSRUNUSU9OX0xFVkVMLCBlY0xldmVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmVwb3J0Rm91bmRSZXN1bHRQb2ludHMoaGludHMsIHBvaW50cykge1xuICAgICAgICAgICAgaWYgKGhpbnRzICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBsZXQgcnBjYiA9IGhpbnRzLmdldChEZWNvZGVIaW50VHlwZSQxLk5FRURfUkVTVUxUX1BPSU5UX0NBTExCQUNLKTtcbiAgICAgICAgICAgICAgICBpZiAocnBjYiAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvaW50cy5mb3JFYWNoKChwb2ludCwgaWR4LCBhcnIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJwY2IuZm91bmRQb3NzaWJsZVJlc3VsdFBvaW50KHBvaW50KTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIEBPdmVycmlkZVxuICAgICAgICByZXNldCgpIHtcbiAgICAgICAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEF6dGVjIENvZGUgcmVhZGVyIHRvIHVzZSBmcm9tIGJyb3dzZXIuXG4gICAgICpcbiAgICAgKiBAY2xhc3MgQnJvd3NlckF6dGVjQ29kZVJlYWRlclxuICAgICAqIEBleHRlbmRzIHtCcm93c2VyQ29kZVJlYWRlcn1cbiAgICAgKi9cbiAgICBjbGFzcyBCcm93c2VyQXp0ZWNDb2RlUmVhZGVyIGV4dGVuZHMgQnJvd3NlckNvZGVSZWFkZXIge1xuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBCcm93c2VyQXp0ZWNDb2RlUmVhZGVyLlxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gW3RpbWVCZXR3ZWVuU2NhbnNNaWxsaXM9NTAwXSB0aGUgdGltZSBkZWxheSBiZXR3ZWVuIHN1YnNlcXVlbnQgZGVjb2RlIHRyaWVzXG4gICAgICAgICAqXG4gICAgICAgICAqIEBtZW1iZXJPZiBCcm93c2VyQXp0ZWNDb2RlUmVhZGVyXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3Rvcih0aW1lQmV0d2VlblNjYW5zTWlsbGlzID0gNTAwKSB7XG4gICAgICAgICAgICBzdXBlcihuZXcgQXp0ZWNSZWFkZXIoKSwgdGltZUJldHdlZW5TY2Fuc01pbGxpcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFbmNhcHN1bGF0ZXMgZnVuY3Rpb25hbGl0eSBhbmQgaW1wbGVtZW50YXRpb24gdGhhdCBpcyBjb21tb24gdG8gYWxsIGZhbWlsaWVzXG4gICAgICogb2Ygb25lLWRpbWVuc2lvbmFsIGJhcmNvZGVzLlxuICAgICAqXG4gICAgICogQGF1dGhvciBkc3dpdGtpbkBnb29nbGUuY29tIChEYW5pZWwgU3dpdGtpbilcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIE9uZURSZWFkZXIge1xuICAgICAgICAvKlxuICAgICAgICBAT3ZlcnJpZGVcbiAgICAgICAgcHVibGljIFJlc3VsdCBkZWNvZGUoQmluYXJ5Qml0bWFwIGltYWdlKSB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24sIEZvcm1hdEV4Y2VwdGlvbiB7XG4gICAgICAgICAgcmV0dXJuIGRlY29kZShpbWFnZSwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgICAgKi9cbiAgICAgICAgLy8gTm90ZSB0aGF0IHdlIGRvbid0IHRyeSByb3RhdGlvbiB3aXRob3V0IHRoZSB0cnkgaGFyZGVyIGZsYWcsIGV2ZW4gaWYgcm90YXRpb24gd2FzIHN1cHBvcnRlZC5cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIGRlY29kZShpbWFnZSwgaGludHMpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZG9EZWNvZGUoaW1hZ2UsIGhpbnRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChuZmUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0cnlIYXJkZXIgPSBoaW50cyAmJiAoaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuVFJZX0hBUkRFUikgPT09IHRydWUpO1xuICAgICAgICAgICAgICAgIGlmICh0cnlIYXJkZXIgJiYgaW1hZ2UuaXNSb3RhdGVTdXBwb3J0ZWQoKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByb3RhdGVkSW1hZ2UgPSBpbWFnZS5yb3RhdGVDb3VudGVyQ2xvY2t3aXNlKCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuZG9EZWNvZGUocm90YXRlZEltYWdlLCBoaW50cyk7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlY29yZCB0aGF0IHdlIGZvdW5kIGl0IHJvdGF0ZWQgOTAgZGVncmVlcyBDQ1cgLyAyNzAgZGVncmVlcyBDV1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRhZGF0YSA9IHJlc3VsdC5nZXRSZXN1bHRNZXRhZGF0YSgpO1xuICAgICAgICAgICAgICAgICAgICBsZXQgb3JpZW50YXRpb24gPSAyNzA7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtZXRhZGF0YSAhPT0gbnVsbCAmJiAobWV0YWRhdGEuZ2V0KFJlc3VsdE1ldGFkYXRhVHlwZSQxLk9SSUVOVEFUSU9OKSA9PT0gdHJ1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJ1dCBpZiB3ZSBmb3VuZCBpdCByZXZlcnNlZCBpbiBkb0RlY29kZSgpLCBhZGQgaW4gdGhhdCByZXN1bHQgaGVyZTpcbiAgICAgICAgICAgICAgICAgICAgICAgIG9yaWVudGF0aW9uID0gKG9yaWVudGF0aW9uICsgbWV0YWRhdGEuZ2V0KFJlc3VsdE1ldGFkYXRhVHlwZSQxLk9SSUVOVEFUSU9OKSAlIDM2MCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1dE1ldGFkYXRhKFJlc3VsdE1ldGFkYXRhVHlwZSQxLk9SSUVOVEFUSU9OLCBvcmllbnRhdGlvbik7XG4gICAgICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSByZXN1bHQgcG9pbnRzXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvaW50cyA9IHJlc3VsdC5nZXRSZXN1bHRQb2ludHMoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBvaW50cyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gcm90YXRlZEltYWdlLmdldEhlaWdodCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwb2ludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludHNbaV0gPSBuZXcgUmVzdWx0UG9pbnQoaGVpZ2h0IC0gcG9pbnRzW2ldLmdldFkoKSAtIDEsIHBvaW50c1tpXS5nZXRYKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIHJlc2V0KCkge1xuICAgICAgICAgICAgLy8gZG8gbm90aGluZ1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXZSdyZSBnb2luZyB0byBleGFtaW5lIHJvd3MgZnJvbSB0aGUgbWlkZGxlIG91dHdhcmQsIHNlYXJjaGluZyBhbHRlcm5hdGVseSBhYm92ZSBhbmQgYmVsb3cgdGhlXG4gICAgICAgICAqIG1pZGRsZSwgYW5kIGZhcnRoZXIgb3V0IGVhY2ggdGltZS4gcm93U3RlcCBpcyB0aGUgbnVtYmVyIG9mIHJvd3MgYmV0d2VlbiBlYWNoIHN1Y2Nlc3NpdmVcbiAgICAgICAgICogYXR0ZW1wdCBhYm92ZSBhbmQgYmVsb3cgdGhlIG1pZGRsZS4gU28gd2UnZCBzY2FuIHJvdyBtaWRkbGUsIHRoZW4gbWlkZGxlIC0gcm93U3RlcCwgdGhlblxuICAgICAgICAgKiBtaWRkbGUgKyByb3dTdGVwLCB0aGVuIG1pZGRsZSAtICgyICogcm93U3RlcCksIGV0Yy5cbiAgICAgICAgICogcm93U3RlcCBpcyBiaWdnZXIgYXMgdGhlIGltYWdlIGlzIHRhbGxlciwgYnV0IGlzIGFsd2F5cyBhdCBsZWFzdCAxLiBXZSd2ZSBzb21ld2hhdCBhcmJpdHJhcmlseVxuICAgICAgICAgKiBkZWNpZGVkIHRoYXQgbW92aW5nIHVwIGFuZCBkb3duIGJ5IGFib3V0IDEvMTYgb2YgdGhlIGltYWdlIGlzIHByZXR0eSBnb29kOyB3ZSB0cnkgbW9yZSBvZiB0aGVcbiAgICAgICAgICogaW1hZ2UgaWYgXCJ0cnlpbmcgaGFyZGVyXCIuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBpbWFnZSBUaGUgaW1hZ2UgdG8gZGVjb2RlXG4gICAgICAgICAqIEBwYXJhbSBoaW50cyBBbnkgaGludHMgdGhhdCB3ZXJlIHJlcXVlc3RlZFxuICAgICAgICAgKiBAcmV0dXJuIFRoZSBjb250ZW50cyBvZiB0aGUgZGVjb2RlZCBiYXJjb2RlXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gQW55IHNwb250YW5lb3VzIGVycm9ycyB3aGljaCBvY2N1clxuICAgICAgICAgKi9cbiAgICAgICAgZG9EZWNvZGUoaW1hZ2UsIGhpbnRzKSB7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IGltYWdlLmdldFdpZHRoKCk7XG4gICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBpbWFnZS5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGxldCByb3cgPSBuZXcgQml0QXJyYXkod2lkdGgpO1xuICAgICAgICAgICAgY29uc3QgdHJ5SGFyZGVyID0gaGludHMgJiYgKGhpbnRzLmdldChEZWNvZGVIaW50VHlwZSQxLlRSWV9IQVJERVIpID09PSB0cnVlKTtcbiAgICAgICAgICAgIGNvbnN0IHJvd1N0ZXAgPSBNYXRoLm1heCgxLCBoZWlnaHQgPj4gKHRyeUhhcmRlciA/IDggOiA1KSk7XG4gICAgICAgICAgICBsZXQgbWF4TGluZXM7XG4gICAgICAgICAgICBpZiAodHJ5SGFyZGVyKSB7XG4gICAgICAgICAgICAgICAgbWF4TGluZXMgPSBoZWlnaHQ7IC8vIExvb2sgYXQgdGhlIHdob2xlIGltYWdlLCBub3QganVzdCB0aGUgY2VudGVyXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBtYXhMaW5lcyA9IDE1OyAvLyAxNSByb3dzIHNwYWNlZCAxLzMyIGFwYXJ0IGlzIHJvdWdobHkgdGhlIG1pZGRsZSBoYWxmIG9mIHRoZSBpbWFnZVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbWlkZGxlID0gTWF0aC50cnVuYyhoZWlnaHQgLyAyKTtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgbWF4TGluZXM7IHgrKykge1xuICAgICAgICAgICAgICAgIC8vIFNjYW5uaW5nIGZyb20gdGhlIG1pZGRsZSBvdXQuIERldGVybWluZSB3aGljaCByb3cgd2UncmUgbG9va2luZyBhdCBuZXh0OlxuICAgICAgICAgICAgICAgIGNvbnN0IHJvd1N0ZXBzQWJvdmVPckJlbG93ID0gTWF0aC50cnVuYygoeCArIDEpIC8gMik7XG4gICAgICAgICAgICAgICAgY29uc3QgaXNBYm92ZSA9ICh4ICYgMHgwMSkgPT09IDA7IC8vIGkuZS4gaXMgeCBldmVuP1xuICAgICAgICAgICAgICAgIGNvbnN0IHJvd051bWJlciA9IG1pZGRsZSArIHJvd1N0ZXAgKiAoaXNBYm92ZSA/IHJvd1N0ZXBzQWJvdmVPckJlbG93IDogLXJvd1N0ZXBzQWJvdmVPckJlbG93KTtcbiAgICAgICAgICAgICAgICBpZiAocm93TnVtYmVyIDwgMCB8fCByb3dOdW1iZXIgPj0gaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE9vcHMsIGlmIHdlIHJ1biBvZmYgdGhlIHRvcCBvciBib3R0b20sIHN0b3BcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIEVzdGltYXRlIGJsYWNrIHBvaW50IGZvciB0aGlzIHJvdyBhbmQgbG9hZCBpdDpcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByb3cgPSBpbWFnZS5nZXRCbGFja1Jvdyhyb3dOdW1iZXIsIHJvdyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChpZ25vcmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBXaGlsZSB3ZSBoYXZlIHRoZSBpbWFnZSBkYXRhIGluIGEgQml0QXJyYXksIGl0J3MgZmFpcmx5IGNoZWFwIHRvIHJldmVyc2UgaXQgaW4gcGxhY2UgdG9cbiAgICAgICAgICAgICAgICAvLyBoYW5kbGUgZGVjb2RpbmcgdXBzaWRlIGRvd24gYmFyY29kZXMuXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgYXR0ZW1wdCA9IDA7IGF0dGVtcHQgPCAyOyBhdHRlbXB0KyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGF0dGVtcHQgPT09IDEpIHsgLy8gdHJ5aW5nIGFnYWluP1xuICAgICAgICAgICAgICAgICAgICAgICAgcm93LnJldmVyc2UoKTsgLy8gcmV2ZXJzZSB0aGUgcm93IGFuZCBjb250aW51ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBtZWFucyB3ZSB3aWxsIG9ubHkgZXZlciBkcmF3IHJlc3VsdCBwb2ludHMgKm9uY2UqIGluIHRoZSBsaWZlIG9mIHRoaXMgbWV0aG9kXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzaW5jZSB3ZSB3YW50IHRvIGF2b2lkIGRyYXdpbmcgdGhlIHdyb25nIHBvaW50cyBhZnRlciBmbGlwcGluZyB0aGUgcm93LCBhbmQsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBkb24ndCB3YW50IHRvIGNsdXR0ZXIgd2l0aCBub2lzZSBmcm9tIGV2ZXJ5IHNpbmdsZSByb3cgc2NhbiAtLSBqdXN0IHRoZSBzY2Fuc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhhdCBzdGFydCBvbiB0aGUgY2VudGVyIGxpbmUuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaGludHMgJiYgKGhpbnRzLmdldChEZWNvZGVIaW50VHlwZSQxLk5FRURfUkVTVUxUX1BPSU5UX0NBTExCQUNLKSA9PT0gdHJ1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdIaW50cyA9IG5ldyBNYXAoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaW50cy5mb3JFYWNoKChoaW50LCBrZXkpID0+IG5ld0hpbnRzLnNldChrZXksIGhpbnQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdIaW50cy5kZWxldGUoRGVjb2RlSGludFR5cGUkMS5ORUVEX1JFU1VMVF9QT0lOVF9DQUxMQkFDSyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGludHMgPSBuZXdIaW50cztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTG9vayBmb3IgYSBiYXJjb2RlXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLmRlY29kZVJvdyhyb3dOdW1iZXIsIHJvdywgaGludHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgZm91bmQgb3VyIGJhcmNvZGVcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRlbXB0ID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQnV0IGl0IHdhcyB1cHNpZGUgZG93biwgc28gbm90ZSB0aGF0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1dE1ldGFkYXRhKFJlc3VsdE1ldGFkYXRhVHlwZSQxLk9SSUVOVEFUSU9OLCAxODApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFuZCByZW1lbWJlciB0byBmbGlwIHRoZSByZXN1bHQgcG9pbnRzIGhvcml6b250YWxseS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwb2ludHMgPSByZXN1bHQuZ2V0UmVzdWx0UG9pbnRzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBvaW50cyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludHNbMF0gPSBuZXcgUmVzdWx0UG9pbnQod2lkdGggLSBwb2ludHNbMF0uZ2V0WCgpIC0gMSwgcG9pbnRzWzBdLmdldFkoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50c1sxXSA9IG5ldyBSZXN1bHRQb2ludCh3aWR0aCAtIHBvaW50c1sxXS5nZXRYKCkgLSAxLCBwb2ludHNbMV0uZ2V0WSgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNhdGNoIChyZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29udGludWUgLS0ganVzdCBjb3VsZG4ndCBkZWNvZGUgdGhpcyByb3dcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZWNvcmRzIHRoZSBzaXplIG9mIHN1Y2Nlc3NpdmUgcnVucyBvZiB3aGl0ZSBhbmQgYmxhY2sgcGl4ZWxzIGluIGEgcm93LCBzdGFydGluZyBhdCBhIGdpdmVuIHBvaW50LlxuICAgICAgICAgKiBUaGUgdmFsdWVzIGFyZSByZWNvcmRlZCBpbiB0aGUgZ2l2ZW4gYXJyYXksIGFuZCB0aGUgbnVtYmVyIG9mIHJ1bnMgcmVjb3JkZWQgaXMgZXF1YWwgdG8gdGhlIHNpemVcbiAgICAgICAgICogb2YgdGhlIGFycmF5LiBJZiB0aGUgcm93IHN0YXJ0cyBvbiBhIHdoaXRlIHBpeGVsIGF0IHRoZSBnaXZlbiBzdGFydCBwb2ludCwgdGhlbiB0aGUgZmlyc3QgY291bnRcbiAgICAgICAgICogcmVjb3JkZWQgaXMgdGhlIHJ1biBvZiB3aGl0ZSBwaXhlbHMgc3RhcnRpbmcgZnJvbSB0aGF0IHBvaW50OyBsaWtld2lzZSBpdCBpcyB0aGUgY291bnQgb2YgYSBydW5cbiAgICAgICAgICogb2YgYmxhY2sgcGl4ZWxzIGlmIHRoZSByb3cgYmVnaW4gb24gYSBibGFjayBwaXhlbHMgYXQgdGhhdCBwb2ludC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHJvdyByb3cgdG8gY291bnQgZnJvbVxuICAgICAgICAgKiBAcGFyYW0gc3RhcnQgb2Zmc2V0IGludG8gcm93IHRvIHN0YXJ0IGF0XG4gICAgICAgICAqIEBwYXJhbSBjb3VudGVycyBhcnJheSBpbnRvIHdoaWNoIHRvIHJlY29yZCBjb3VudHNcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBpZiBjb3VudGVycyBjYW5ub3QgYmUgZmlsbGVkIGVudGlyZWx5IGZyb20gcm93IGJlZm9yZSBydW5uaW5nIG91dFxuICAgICAgICAgKiAgb2YgcGl4ZWxzXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgcmVjb3JkUGF0dGVybihyb3csIHN0YXJ0LCBjb3VudGVycykge1xuICAgICAgICAgICAgY29uc3QgbnVtQ291bnRlcnMgPSBjb3VudGVycy5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgbnVtQ291bnRlcnM7IGluZGV4KyspXG4gICAgICAgICAgICAgICAgY291bnRlcnNbaW5kZXhdID0gMDtcbiAgICAgICAgICAgIGNvbnN0IGVuZCA9IHJvdy5nZXRTaXplKCk7XG4gICAgICAgICAgICBpZiAoc3RhcnQgPj0gZW5kKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgaXNXaGl0ZSA9ICFyb3cuZ2V0KHN0YXJ0KTtcbiAgICAgICAgICAgIGxldCBjb3VudGVyUG9zaXRpb24gPSAwO1xuICAgICAgICAgICAgbGV0IGkgPSBzdGFydDtcbiAgICAgICAgICAgIHdoaWxlIChpIDwgZW5kKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJvdy5nZXQoaSkgIT09IGlzV2hpdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbY291bnRlclBvc2l0aW9uXSsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCsrY291bnRlclBvc2l0aW9uID09PSBudW1Db3VudGVycykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb25dID0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzV2hpdGUgPSAhaXNXaGl0ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBJZiB3ZSByZWFkIGZ1bGx5IHRoZSBsYXN0IHNlY3Rpb24gb2YgcGl4ZWxzIGFuZCBmaWxsZWQgdXAgb3VyIGNvdW50ZXJzIC0tIG9yIGZpbGxlZFxuICAgICAgICAgICAgLy8gdGhlIGxhc3QgY291bnRlciBidXQgcmFuIG9mZiB0aGUgc2lkZSBvZiB0aGUgaW1hZ2UsIE9LLiBPdGhlcndpc2UsIGEgcHJvYmxlbS5cbiAgICAgICAgICAgIGlmICghKGNvdW50ZXJQb3NpdGlvbiA9PT0gbnVtQ291bnRlcnMgfHwgKGNvdW50ZXJQb3NpdGlvbiA9PT0gbnVtQ291bnRlcnMgLSAxICYmIGkgPT09IGVuZCkpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHJlY29yZFBhdHRlcm5JblJldmVyc2Uocm93LCBzdGFydCwgY291bnRlcnMpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgY291bGQgYmUgbW9yZSBlZmZpY2llbnQgSSBndWVzc1xuICAgICAgICAgICAgbGV0IG51bVRyYW5zaXRpb25zTGVmdCA9IGNvdW50ZXJzLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBsYXN0ID0gcm93LmdldChzdGFydCk7XG4gICAgICAgICAgICB3aGlsZSAoc3RhcnQgPiAwICYmIG51bVRyYW5zaXRpb25zTGVmdCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJvdy5nZXQoLS1zdGFydCkgIT09IGxhc3QpIHtcbiAgICAgICAgICAgICAgICAgICAgbnVtVHJhbnNpdGlvbnNMZWZ0LS07XG4gICAgICAgICAgICAgICAgICAgIGxhc3QgPSAhbGFzdDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobnVtVHJhbnNpdGlvbnNMZWZ0ID49IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIE9uZURSZWFkZXIucmVjb3JkUGF0dGVybihyb3csIHN0YXJ0ICsgMSwgY291bnRlcnMpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZXRlcm1pbmVzIGhvdyBjbG9zZWx5IGEgc2V0IG9mIG9ic2VydmVkIGNvdW50cyBvZiBydW5zIG9mIGJsYWNrL3doaXRlIHZhbHVlcyBtYXRjaGVzIGEgZ2l2ZW5cbiAgICAgICAgICogdGFyZ2V0IHBhdHRlcm4uIFRoaXMgaXMgcmVwb3J0ZWQgYXMgdGhlIHJhdGlvIG9mIHRoZSB0b3RhbCB2YXJpYW5jZSBmcm9tIHRoZSBleHBlY3RlZCBwYXR0ZXJuXG4gICAgICAgICAqIHByb3BvcnRpb25zIGFjcm9zcyBhbGwgcGF0dGVybiBlbGVtZW50cywgdG8gdGhlIGxlbmd0aCBvZiB0aGUgcGF0dGVybi5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGNvdW50ZXJzIG9ic2VydmVkIGNvdW50ZXJzXG4gICAgICAgICAqIEBwYXJhbSBwYXR0ZXJuIGV4cGVjdGVkIHBhdHRlcm5cbiAgICAgICAgICogQHBhcmFtIG1heEluZGl2aWR1YWxWYXJpYW5jZSBUaGUgbW9zdCBhbnkgY291bnRlciBjYW4gZGlmZmVyIGJlZm9yZSB3ZSBnaXZlIHVwXG4gICAgICAgICAqIEByZXR1cm4gcmF0aW8gb2YgdG90YWwgdmFyaWFuY2UgYmV0d2VlbiBjb3VudGVycyBhbmQgcGF0dGVybiBjb21wYXJlZCB0byB0b3RhbCBwYXR0ZXJuIHNpemVcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBwYXR0ZXJuTWF0Y2hWYXJpYW5jZShjb3VudGVycywgcGF0dGVybiwgbWF4SW5kaXZpZHVhbFZhcmlhbmNlKSB7XG4gICAgICAgICAgICBjb25zdCBudW1Db3VudGVycyA9IGNvdW50ZXJzLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCB0b3RhbCA9IDA7XG4gICAgICAgICAgICBsZXQgcGF0dGVybkxlbmd0aCA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUNvdW50ZXJzOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0b3RhbCArPSBjb3VudGVyc1tpXTtcbiAgICAgICAgICAgICAgICBwYXR0ZXJuTGVuZ3RoICs9IHBhdHRlcm5baV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodG90YWwgPCBwYXR0ZXJuTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgd2UgZG9uJ3QgZXZlbiBoYXZlIG9uZSBwaXhlbCBwZXIgdW5pdCBvZiBiYXIgd2lkdGgsIGFzc3VtZSB0aGlzIGlzIHRvbyBzbWFsbFxuICAgICAgICAgICAgICAgIC8vIHRvIHJlbGlhYmx5IG1hdGNoLCBzbyBmYWlsOlxuICAgICAgICAgICAgICAgIHJldHVybiBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCB1bml0QmFyV2lkdGggPSB0b3RhbCAvIHBhdHRlcm5MZW5ndGg7XG4gICAgICAgICAgICBtYXhJbmRpdmlkdWFsVmFyaWFuY2UgKj0gdW5pdEJhcldpZHRoO1xuICAgICAgICAgICAgbGV0IHRvdGFsVmFyaWFuY2UgPSAwLjA7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IG51bUNvdW50ZXJzOyB4KyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb3VudGVyID0gY291bnRlcnNbeF07XG4gICAgICAgICAgICAgICAgY29uc3Qgc2NhbGVkUGF0dGVybiA9IHBhdHRlcm5beF0gKiB1bml0QmFyV2lkdGg7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFyaWFuY2UgPSBjb3VudGVyID4gc2NhbGVkUGF0dGVybiA/IGNvdW50ZXIgLSBzY2FsZWRQYXR0ZXJuIDogc2NhbGVkUGF0dGVybiAtIGNvdW50ZXI7XG4gICAgICAgICAgICAgICAgaWYgKHZhcmlhbmNlID4gbWF4SW5kaXZpZHVhbFZhcmlhbmNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRvdGFsVmFyaWFuY2UgKz0gdmFyaWFuY2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdG90YWxWYXJpYW5jZSAvIHRvdGFsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogPHA+RGVjb2RlcyBDb2RlIDEyOCBiYXJjb2Rlcy48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIENvZGUxMjhSZWFkZXIgZXh0ZW5kcyBPbmVEUmVhZGVyIHtcbiAgICAgICAgc3RhdGljIGZpbmRTdGFydFBhdHRlcm4ocm93KSB7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IHJvdy5nZXRTaXplKCk7XG4gICAgICAgICAgICBjb25zdCByb3dPZmZzZXQgPSByb3cuZ2V0TmV4dFNldCgwKTtcbiAgICAgICAgICAgIGxldCBjb3VudGVyUG9zaXRpb24gPSAwO1xuICAgICAgICAgICAgbGV0IGNvdW50ZXJzID0gSW50MzJBcnJheS5mcm9tKFswLCAwLCAwLCAwLCAwLCAwXSk7XG4gICAgICAgICAgICBsZXQgcGF0dGVyblN0YXJ0ID0gcm93T2Zmc2V0O1xuICAgICAgICAgICAgbGV0IGlzV2hpdGUgPSBmYWxzZTtcbiAgICAgICAgICAgIGNvbnN0IHBhdHRlcm5MZW5ndGggPSA2O1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IHJvd09mZnNldDsgaSA8IHdpZHRoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAocm93LmdldChpKSAhPT0gaXNXaGl0ZSkge1xuICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb25dKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY291bnRlclBvc2l0aW9uID09PSAocGF0dGVybkxlbmd0aCAtIDEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgYmVzdFZhcmlhbmNlID0gQ29kZTEyOFJlYWRlci5NQVhfQVZHX1ZBUklBTkNFO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGJlc3RNYXRjaCA9IC0xO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgc3RhcnRDb2RlID0gQ29kZTEyOFJlYWRlci5DT0RFX1NUQVJUX0E7IHN0YXJ0Q29kZSA8PSBDb2RlMTI4UmVhZGVyLkNPREVfU1RBUlRfQzsgc3RhcnRDb2RlKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB2YXJpYW5jZSA9IE9uZURSZWFkZXIucGF0dGVybk1hdGNoVmFyaWFuY2UoY291bnRlcnMsIENvZGUxMjhSZWFkZXIuQ09ERV9QQVRURVJOU1tzdGFydENvZGVdLCBDb2RlMTI4UmVhZGVyLk1BWF9JTkRJVklEVUFMX1ZBUklBTkNFKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFyaWFuY2UgPCBiZXN0VmFyaWFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVzdFZhcmlhbmNlID0gdmFyaWFuY2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlc3RNYXRjaCA9IHN0YXJ0Q29kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBMb29rIGZvciB3aGl0ZXNwYWNlIGJlZm9yZSBzdGFydCBwYXR0ZXJuLCA+PSA1MCUgb2Ygd2lkdGggb2Ygc3RhcnQgcGF0dGVyblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJlc3RNYXRjaCA+PSAwICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93LmlzUmFuZ2UoTWF0aC5tYXgoMCwgcGF0dGVyblN0YXJ0IC0gKGkgLSBwYXR0ZXJuU3RhcnQpIC8gMiksIHBhdHRlcm5TdGFydCwgZmFsc2UpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEludDMyQXJyYXkuZnJvbShbcGF0dGVyblN0YXJ0LCBpLCBiZXN0TWF0Y2hdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm5TdGFydCArPSBjb3VudGVyc1swXSArIGNvdW50ZXJzWzFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlcnMgPSBjb3VudGVycy5zbGljZSgyLCBjb3VudGVycy5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbiAtIDFdID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbl0gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlclBvc2l0aW9uLS07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyUG9zaXRpb24rKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb25dID0gMTtcbiAgICAgICAgICAgICAgICAgICAgaXNXaGl0ZSA9ICFpc1doaXRlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBkZWNvZGVDb2RlKHJvdywgY291bnRlcnMsIHJvd09mZnNldCkge1xuICAgICAgICAgICAgT25lRFJlYWRlci5yZWNvcmRQYXR0ZXJuKHJvdywgcm93T2Zmc2V0LCBjb3VudGVycyk7XG4gICAgICAgICAgICBsZXQgYmVzdFZhcmlhbmNlID0gQ29kZTEyOFJlYWRlci5NQVhfQVZHX1ZBUklBTkNFOyAvLyB3b3JzdCB2YXJpYW5jZSB3ZSdsbCBhY2NlcHRcbiAgICAgICAgICAgIGxldCBiZXN0TWF0Y2ggPSAtMTtcbiAgICAgICAgICAgIGZvciAobGV0IGQgPSAwOyBkIDwgQ29kZTEyOFJlYWRlci5DT0RFX1BBVFRFUk5TLmxlbmd0aDsgZCsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGF0dGVybiA9IENvZGUxMjhSZWFkZXIuQ09ERV9QQVRURVJOU1tkXTtcbiAgICAgICAgICAgICAgICBjb25zdCB2YXJpYW5jZSA9IHRoaXMucGF0dGVybk1hdGNoVmFyaWFuY2UoY291bnRlcnMsIHBhdHRlcm4sIENvZGUxMjhSZWFkZXIuTUFYX0lORElWSURVQUxfVkFSSUFOQ0UpO1xuICAgICAgICAgICAgICAgIGlmICh2YXJpYW5jZSA8IGJlc3RWYXJpYW5jZSkge1xuICAgICAgICAgICAgICAgICAgICBiZXN0VmFyaWFuY2UgPSB2YXJpYW5jZTtcbiAgICAgICAgICAgICAgICAgICAgYmVzdE1hdGNoID0gZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBUT0RPIFdlJ3JlIG92ZXJsb29raW5nIHRoZSBmYWN0IHRoYXQgdGhlIFNUT1AgcGF0dGVybiBoYXMgNyB2YWx1ZXMsIG5vdCA2LlxuICAgICAgICAgICAgaWYgKGJlc3RNYXRjaCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGJlc3RNYXRjaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGRlY29kZVJvdyhyb3dOdW1iZXIsIHJvdywgaGludHMpIHtcbiAgICAgICAgICAgIGNvbnN0IGNvbnZlcnRGTkMxID0gaGludHMgJiYgKGhpbnRzLmdldChEZWNvZGVIaW50VHlwZSQxLkFTU1VNRV9HUzEpID09PSB0cnVlKTtcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0UGF0dGVybkluZm8gPSBDb2RlMTI4UmVhZGVyLmZpbmRTdGFydFBhdHRlcm4ocm93KTtcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0Q29kZSA9IHN0YXJ0UGF0dGVybkluZm9bMl07XG4gICAgICAgICAgICBsZXQgY3VycmVudFJhd0NvZGVzSW5kZXggPSAwO1xuICAgICAgICAgICAgY29uc3QgcmF3Q29kZXMgPSBuZXcgVWludDhBcnJheSgyMCk7XG4gICAgICAgICAgICByYXdDb2Rlc1tjdXJyZW50UmF3Q29kZXNJbmRleCsrXSA9IHN0YXJ0Q29kZTtcbiAgICAgICAgICAgIGxldCBjb2RlU2V0O1xuICAgICAgICAgICAgc3dpdGNoIChzdGFydENvZGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9TVEFSVF9BOlxuICAgICAgICAgICAgICAgICAgICBjb2RlU2V0ID0gQ29kZTEyOFJlYWRlci5DT0RFX0NPREVfQTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfU1RBUlRfQjpcbiAgICAgICAgICAgICAgICAgICAgY29kZVNldCA9IENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0I7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX1NUQVJUX0M6XG4gICAgICAgICAgICAgICAgICAgIGNvZGVTZXQgPSBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9DO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZG9uZSA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGlzTmV4dFNoaWZ0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSAnJztcbiAgICAgICAgICAgIGxldCBsYXN0U3RhcnQgPSBzdGFydFBhdHRlcm5JbmZvWzBdO1xuICAgICAgICAgICAgbGV0IG5leHRTdGFydCA9IHN0YXJ0UGF0dGVybkluZm9bMV07XG4gICAgICAgICAgICBjb25zdCBjb3VudGVycyA9IEludDMyQXJyYXkuZnJvbShbMCwgMCwgMCwgMCwgMCwgMF0pO1xuICAgICAgICAgICAgbGV0IGxhc3RDb2RlID0gMDtcbiAgICAgICAgICAgIGxldCBjb2RlID0gMDtcbiAgICAgICAgICAgIGxldCBjaGVja3N1bVRvdGFsID0gc3RhcnRDb2RlO1xuICAgICAgICAgICAgbGV0IG11bHRpcGxpZXIgPSAwO1xuICAgICAgICAgICAgbGV0IGxhc3RDaGFyYWN0ZXJXYXNQcmludGFibGUgPSB0cnVlO1xuICAgICAgICAgICAgbGV0IHVwcGVyTW9kZSA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IHNoaWZ0VXBwZXJNb2RlID0gZmFsc2U7XG4gICAgICAgICAgICB3aGlsZSAoIWRvbmUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB1bnNoaWZ0ID0gaXNOZXh0U2hpZnRlZDtcbiAgICAgICAgICAgICAgICBpc05leHRTaGlmdGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgLy8gU2F2ZSBvZmYgbGFzdCBjb2RlXG4gICAgICAgICAgICAgICAgbGFzdENvZGUgPSBjb2RlO1xuICAgICAgICAgICAgICAgIC8vIERlY29kZSBhbm90aGVyIGNvZGUgZnJvbSBpbWFnZVxuICAgICAgICAgICAgICAgIGNvZGUgPSBDb2RlMTI4UmVhZGVyLmRlY29kZUNvZGUocm93LCBjb3VudGVycywgbmV4dFN0YXJ0KTtcbiAgICAgICAgICAgICAgICByYXdDb2Rlc1tjdXJyZW50UmF3Q29kZXNJbmRleCsrXSA9IGNvZGU7XG4gICAgICAgICAgICAgICAgLy8gUmVtZW1iZXIgd2hldGhlciB0aGUgbGFzdCBjb2RlIHdhcyBwcmludGFibGUgb3Igbm90IChleGNsdWRpbmcgQ09ERV9TVE9QKVxuICAgICAgICAgICAgICAgIGlmIChjb2RlICE9PSBDb2RlMTI4UmVhZGVyLkNPREVfU1RPUCkge1xuICAgICAgICAgICAgICAgICAgICBsYXN0Q2hhcmFjdGVyV2FzUHJpbnRhYmxlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gQWRkIHRvIGNoZWNrc3VtIGNvbXB1dGF0aW9uIChpZiBub3QgQ09ERV9TVE9QIG9mIGNvdXJzZSlcbiAgICAgICAgICAgICAgICBpZiAoY29kZSAhPT0gQ29kZTEyOFJlYWRlci5DT0RFX1NUT1ApIHtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlwbGllcisrO1xuICAgICAgICAgICAgICAgICAgICBjaGVja3N1bVRvdGFsICs9IG11bHRpcGxpZXIgKiBjb2RlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBBZHZhbmNlIHRvIHdoZXJlIHRoZSBuZXh0IGNvZGUgd2lsbCB0byBzdGFydFxuICAgICAgICAgICAgICAgIGxhc3RTdGFydCA9IG5leHRTdGFydDtcbiAgICAgICAgICAgICAgICBuZXh0U3RhcnQgKz0gY291bnRlcnMucmVkdWNlKChwcmV2aW91cywgY3VycmVudCkgPT4gcHJldmlvdXMgKyBjdXJyZW50LCAwKTtcbiAgICAgICAgICAgICAgICAvLyBUYWtlIGNhcmUgb2YgaWxsZWdhbCBzdGFydCBjb2Rlc1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoY29kZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9TVEFSVF9BOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9TVEFSVF9COlxuICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9TVEFSVF9DOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGNvZGVTZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9BOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvZGUgPCA2NCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaGlmdFVwcGVyTW9kZSA9PT0gdXBwZXJNb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKCgnICcuY2hhckNvZGVBdCgwKSArIGNvZGUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKCgnICcuY2hhckNvZGVBdCgwKSArIGNvZGUgKyAxMjgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hpZnRVcHBlck1vZGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGNvZGUgPCA5Nikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaGlmdFVwcGVyTW9kZSA9PT0gdXBwZXJNb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKChjb2RlIC0gNjQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKChjb2RlICsgNjQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hpZnRVcHBlck1vZGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvbid0IGxldCBDT0RFX1NUT1AsIHdoaWNoIGFsd2F5cyBhcHBlYXJzLCBhZmZlY3Qgd2hldGhlciB3aGV0aGVyIHdlIHRoaW5rIHRoZSBsYXN0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29kZSB3YXMgcHJpbnRhYmxlIG9yIG5vdC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29kZSAhPT0gQ29kZTEyOFJlYWRlci5DT0RFX1NUT1ApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdENoYXJhY3Rlcldhc1ByaW50YWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGNvZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfRk5DXzE6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29udmVydEZOQzEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHUzEgc3BlY2lmaWNhdGlvbiA1LjQuMy43LiBhbmQgNS40LjYuNC4gSWYgdGhlIGZpcnN0IGNoYXIgYWZ0ZXIgdGhlIHN0YXJ0IGNvZGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXMgRk5DMSB0aGVuIHRoaXMgaXMgR1MxLTEyOC4gV2UgYWRkIHRoZSBzeW1ib2xvZ3kgaWRlbnRpZmllci5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICddQzEnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR1MxIHNwZWNpZmljYXRpb24gNS40LjcuNS4gRXZlcnkgc3Vic2VxdWVudCBGTkMxIGlzIHJldHVybmVkIGFzIEFTQ0lJIDI5IChHUylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMjkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9GTkNfMjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfRk5DXzM6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBkbyBub3RoaW5nP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX0ZOQ180X0E6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXVwcGVyTW9kZSAmJiBzaGlmdFVwcGVyTW9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwcGVyTW9kZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hpZnRVcHBlck1vZGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHVwcGVyTW9kZSAmJiBzaGlmdFVwcGVyTW9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwcGVyTW9kZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoaWZ0VXBwZXJNb2RlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaGlmdFVwcGVyTW9kZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfU0hJRlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc05leHRTaGlmdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVTZXQgPSBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9CO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX0NPREVfQjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVTZXQgPSBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9CO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX0NPREVfQzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVTZXQgPSBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9DO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX1NUT1A6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0I6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29kZSA8IDk2KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNoaWZ0VXBwZXJNb2RlID09PSB1cHBlck1vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKCcgJy5jaGFyQ29kZUF0KDApICsgY29kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKCcgJy5jaGFyQ29kZUF0KDApICsgY29kZSArIDEyOCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaGlmdFVwcGVyTW9kZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvZGUgIT09IENvZGUxMjhSZWFkZXIuQ09ERV9TVE9QKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RDaGFyYWN0ZXJXYXNQcmludGFibGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChjb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX0ZOQ18xOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbnZlcnRGTkMxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR1MxIHNwZWNpZmljYXRpb24gNS40LjMuNy4gYW5kIDUuNC42LjQuIElmIHRoZSBmaXJzdCBjaGFyIGFmdGVyIHRoZSBzdGFydCBjb2RlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlzIEZOQzEgdGhlbiB0aGlzIGlzIEdTMS0xMjguIFdlIGFkZCB0aGUgc3ltYm9sb2d5IGlkZW50aWZpZXIuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnXUMxJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdTMSBzcGVjaWZpY2F0aW9uIDUuNC43LjUuIEV2ZXJ5IHN1YnNlcXVlbnQgRk5DMSBpcyByZXR1cm5lZCBhcyBBU0NJSSAyOSAoR1MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDI5KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfRk5DXzI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX0ZOQ18zOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZG8gbm90aGluZz9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9GTkNfNF9COlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF1cHBlck1vZGUgJiYgc2hpZnRVcHBlck1vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cHBlck1vZGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoaWZ0VXBwZXJNb2RlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh1cHBlck1vZGUgJiYgc2hpZnRVcHBlck1vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cHBlck1vZGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaGlmdFVwcGVyTW9kZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hpZnRVcHBlck1vZGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX1NISUZUOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNOZXh0U2hpZnRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2RlU2V0ID0gQ29kZTEyOFJlYWRlci5DT0RFX0NPREVfQTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0E6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2RlU2V0ID0gQ29kZTEyOFJlYWRlci5DT0RFX0NPREVfQTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0M6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2RlU2V0ID0gQ29kZTEyOFJlYWRlci5DT0RFX0NPREVfQztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIENvZGUxMjhSZWFkZXIuQ09ERV9TVE9QOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9DOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvZGUgPCAxMDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29kZSA8IDEwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnMCc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSBjb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvZGUgIT09IENvZGUxMjhSZWFkZXIuQ09ERV9TVE9QKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RDaGFyYWN0ZXJXYXNQcmludGFibGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChjb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQ29kZTEyOFJlYWRlci5DT0RFX0ZOQ18xOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbnZlcnRGTkMxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR1MxIHNwZWNpZmljYXRpb24gNS40LjMuNy4gYW5kIDUuNC42LjQuIElmIHRoZSBmaXJzdCBjaGFyIGFmdGVyIHRoZSBzdGFydCBjb2RlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlzIEZOQzEgdGhlbiB0aGlzIGlzIEdTMS0xMjguIFdlIGFkZCB0aGUgc3ltYm9sb2d5IGlkZW50aWZpZXIuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnXUMxJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdTMSBzcGVjaWZpY2F0aW9uIDUuNC43LjUuIEV2ZXJ5IHN1YnNlcXVlbnQgRk5DMSBpcyByZXR1cm5lZCBhcyBBU0NJSSAyOSAoR1MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDI5KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9BOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZVNldCA9IENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0E7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9COlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZVNldCA9IENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2RlMTI4UmVhZGVyLkNPREVfU1RPUDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIFVuc2hpZnQgYmFjayB0byBhbm90aGVyIGNvZGUgc2V0IGlmIHdlIHdlcmUgc2hpZnRlZFxuICAgICAgICAgICAgICAgIGlmICh1bnNoaWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvZGVTZXQgPSBjb2RlU2V0ID09PSBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9BID8gQ29kZTEyOFJlYWRlci5DT0RFX0NPREVfQiA6IENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0E7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbGFzdFBhdHRlcm5TaXplID0gbmV4dFN0YXJ0IC0gbGFzdFN0YXJ0O1xuICAgICAgICAgICAgLy8gQ2hlY2sgZm9yIGFtcGxlIHdoaXRlc3BhY2UgZm9sbG93aW5nIHBhdHRlcm4sIGJ1dCwgdG8gZG8gdGhpcyB3ZSBmaXJzdCBuZWVkIHRvIHJlbWVtYmVyIHRoYXRcbiAgICAgICAgICAgIC8vIHdlIGZ1ZGdlZCBkZWNvZGluZyBDT0RFX1NUT1Agc2luY2UgaXQgYWN0dWFsbHkgaGFzIDcgYmFycywgbm90IDYuIFRoZXJlIGlzIGEgYmxhY2sgYmFyIGxlZnRcbiAgICAgICAgICAgIC8vIHRvIHJlYWQgb2ZmLiBXb3VsZCBiZSBzbGlnaHRseSBiZXR0ZXIgdG8gcHJvcGVybHkgcmVhZC4gSGVyZSB3ZSBqdXN0IHNraXAgaXQ6XG4gICAgICAgICAgICBuZXh0U3RhcnQgPSByb3cuZ2V0TmV4dFVuc2V0KG5leHRTdGFydCk7XG4gICAgICAgICAgICBpZiAoIXJvdy5pc1JhbmdlKG5leHRTdGFydCwgTWF0aC5taW4ocm93LmdldFNpemUoKSwgbmV4dFN0YXJ0ICsgKG5leHRTdGFydCAtIGxhc3RTdGFydCkgLyAyKSwgZmFsc2UpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBQdWxsIG91dCBmcm9tIHN1bSB0aGUgdmFsdWUgb2YgdGhlIHBlbnVsdGltYXRlIGNoZWNrIGNvZGVcbiAgICAgICAgICAgIGNoZWNrc3VtVG90YWwgLT0gbXVsdGlwbGllciAqIGxhc3RDb2RlO1xuICAgICAgICAgICAgLy8gbGFzdENvZGUgaXMgdGhlIGNoZWNrc3VtIHRoZW46XG4gICAgICAgICAgICBpZiAoY2hlY2tzdW1Ub3RhbCAlIDEwMyAhPT0gbGFzdENvZGUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQ2hlY2tzdW1FeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE5lZWQgdG8gcHVsbCBvdXQgdGhlIGNoZWNrIGRpZ2l0cyBmcm9tIHN0cmluZ1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0TGVuZ3RoID0gcmVzdWx0Lmxlbmd0aDtcbiAgICAgICAgICAgIGlmIChyZXN1bHRMZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyBmYWxzZSBwb3NpdGl2ZVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gT25seSBib3RoZXIgaWYgdGhlIHJlc3VsdCBoYWQgYXQgbGVhc3Qgb25lIGNoYXJhY3RlciwgYW5kIGlmIHRoZSBjaGVja3N1bSBkaWdpdCBoYXBwZW5lZCB0b1xuICAgICAgICAgICAgLy8gYmUgYSBwcmludGFibGUgY2hhcmFjdGVyLiBJZiBpdCB3YXMganVzdCBpbnRlcnByZXRlZCBhcyBhIGNvbnRyb2wgY29kZSwgbm90aGluZyB0byByZW1vdmUuXG4gICAgICAgICAgICBpZiAocmVzdWx0TGVuZ3RoID4gMCAmJiBsYXN0Q2hhcmFjdGVyV2FzUHJpbnRhYmxlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvZGVTZXQgPT09IENvZGUxMjhSZWFkZXIuQ09ERV9DT0RFX0MpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LnN1YnN0cmluZygwLCByZXN1bHRMZW5ndGggLSAyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5zdWJzdHJpbmcoMCwgcmVzdWx0TGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbGVmdCA9IChzdGFydFBhdHRlcm5JbmZvWzFdICsgc3RhcnRQYXR0ZXJuSW5mb1swXSkgLyAyLjA7XG4gICAgICAgICAgICBjb25zdCByaWdodCA9IGxhc3RTdGFydCArIGxhc3RQYXR0ZXJuU2l6ZSAvIDIuMDtcbiAgICAgICAgICAgIGNvbnN0IHJhd0NvZGVzU2l6ZSA9IHJhd0NvZGVzLmxlbmd0aDtcbiAgICAgICAgICAgIGNvbnN0IHJhd0J5dGVzID0gbmV3IFVpbnQ4QXJyYXkocmF3Q29kZXNTaXplKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmF3Q29kZXNTaXplOyBpKyspIHtcbiAgICAgICAgICAgICAgICByYXdCeXRlc1tpXSA9IHJhd0NvZGVzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcG9pbnRzID0gW25ldyBSZXN1bHRQb2ludChsZWZ0LCByb3dOdW1iZXIpLCBuZXcgUmVzdWx0UG9pbnQocmlnaHQsIHJvd051bWJlcildO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBSZXN1bHQocmVzdWx0LCByYXdCeXRlcywgMCwgcG9pbnRzLCBCYXJjb2RlRm9ybWF0JDEuQ09ERV8xMjgsIG5ldyBEYXRlKCkuZ2V0VGltZSgpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBDb2RlMTI4UmVhZGVyLkNPREVfUEFUVEVSTlMgPSBbXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMSwgMiwgMiwgMiwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDIsIDIsIDEsIDIsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAyLCAyLCAyLCAyLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMiwgMSwgMiwgMiwgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDIsIDEsIDMsIDIsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAzLCAxLCAyLCAyLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMiwgMiwgMiwgMSwgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDIsIDIsIDMsIDEsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAzLCAyLCAyLCAxLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMiwgMSwgMiwgMSwgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDIsIDEsIDMsIDEsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAzLCAxLCAyLCAxLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMiwgMiwgMywgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDIsIDIsIDEsIDMsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAyLCAyLCAyLCAzLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMywgMiwgMiwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDIsIDMsIDEsIDIsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAyLCAzLCAyLCAyLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMiwgMywgMiwgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDIsIDEsIDEsIDMsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAyLCAxLCAyLCAzLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMSwgMywgMiwgMSwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDIsIDMsIDEsIDEsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAxLCAyLCAxLCAzLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgMSwgMSwgMiwgMiwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDIsIDEsIDEsIDIsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAyLCAxLCAyLCAyLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgMSwgMiwgMiwgMSwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDIsIDIsIDEsIDEsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAyLCAyLCAyLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMSwgMiwgMSwgMiwgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDEsIDIsIDMsIDIsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAzLCAyLCAxLCAyLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMSwgMywgMiwgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDMsIDEsIDEsIDIsIDNdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAzLCAxLCAzLCAyLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMiwgMywgMSwgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDMsIDIsIDEsIDEsIDNdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAzLCAyLCAzLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMSwgMSwgMywgMSwgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDMsIDEsIDEsIDEsIDNdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAzLCAxLCAzLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMiwgMSwgMywgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDIsIDMsIDMsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAzLCAyLCAxLCAzLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMywgMSwgMiwgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDMsIDMsIDIsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAzLCAzLCAxLCAyLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgMSwgMywgMSwgMiwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDEsIDEsIDMsIDMsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAzLCAxLCAxLCAzLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMSwgMywgMSwgMSwgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDEsIDMsIDMsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAxLCAzLCAxLCAzLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgMSwgMSwgMSwgMiwgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDEsIDEsIDMsIDIsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAzLCAxLCAxLCAyLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgMSwgMiwgMSwgMSwgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDEsIDIsIDMsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAzLCAyLCAxLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgMSwgNCwgMSwgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDIsIDEsIDQsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs0LCAzLCAxLCAxLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMSwgMiwgMiwgNF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDEsIDQsIDIsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAyLCAxLCAxLCAyLCA0XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMiwgMSwgNCwgMiwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDQsIDEsIDEsIDIsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCA0LCAxLCAyLCAyLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMiwgMiwgMSwgNF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDIsIDQsIDEsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAyLCAyLCAxLCAxLCA0XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMiwgMiwgNCwgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDQsIDIsIDEsIDEsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCA0LCAyLCAyLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgNCwgMSwgMiwgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDIsIDEsIDEsIDEsIDRdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs0LCAxLCAzLCAxLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgNCwgMSwgMSwgMSwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDMsIDQsIDEsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAxLCAyLCA0LCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMiwgMSwgMSwgNCwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDIsIDEsIDIsIDQsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCA0LCAyLCAxLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMiwgNCwgMSwgMSwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDIsIDQsIDIsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs0LCAxLCAxLCAyLCAxLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNCwgMiwgMSwgMSwgMSwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzQsIDIsIDEsIDIsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAxLCAyLCAxLCA0LCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMSwgNCwgMSwgMiwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzQsIDEsIDIsIDEsIDIsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAxLCAxLCA0LCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMSwgMywgNCwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDMsIDEsIDEsIDQsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCA0LCAxLCAxLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgNCwgMywgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzQsIDEsIDEsIDEsIDEsIDNdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs0LCAxLCAxLCAzLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMywgMSwgNCwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDQsIDEsIDMsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAxLCAxLCAxLCA0LCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNCwgMSwgMSwgMSwgMywgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDEsIDEsIDQsIDEsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAxLCAxLCAyLCAxLCA0XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMSwgMSwgMiwgMywgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDMsIDMsIDEsIDEsIDEsIDJdKSxcbiAgICBdO1xuICAgIENvZGUxMjhSZWFkZXIuTUFYX0FWR19WQVJJQU5DRSA9IDAuMjU7XG4gICAgQ29kZTEyOFJlYWRlci5NQVhfSU5ESVZJRFVBTF9WQVJJQU5DRSA9IDAuNztcbiAgICBDb2RlMTI4UmVhZGVyLkNPREVfU0hJRlQgPSA5ODtcbiAgICBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9DID0gOTk7XG4gICAgQ29kZTEyOFJlYWRlci5DT0RFX0NPREVfQiA9IDEwMDtcbiAgICBDb2RlMTI4UmVhZGVyLkNPREVfQ09ERV9BID0gMTAxO1xuICAgIENvZGUxMjhSZWFkZXIuQ09ERV9GTkNfMSA9IDEwMjtcbiAgICBDb2RlMTI4UmVhZGVyLkNPREVfRk5DXzIgPSA5NztcbiAgICBDb2RlMTI4UmVhZGVyLkNPREVfRk5DXzMgPSA5NjtcbiAgICBDb2RlMTI4UmVhZGVyLkNPREVfRk5DXzRfQSA9IDEwMTtcbiAgICBDb2RlMTI4UmVhZGVyLkNPREVfRk5DXzRfQiA9IDEwMDtcbiAgICBDb2RlMTI4UmVhZGVyLkNPREVfU1RBUlRfQSA9IDEwMztcbiAgICBDb2RlMTI4UmVhZGVyLkNPREVfU1RBUlRfQiA9IDEwNDtcbiAgICBDb2RlMTI4UmVhZGVyLkNPREVfU1RBUlRfQyA9IDEwNTtcbiAgICBDb2RlMTI4UmVhZGVyLkNPREVfU1RPUCA9IDEwNjtcblxuICAgIC8qKlxuICAgICAqIDxwPkRlY29kZXMgQ29kZSAzOSBiYXJjb2Rlcy4gU3VwcG9ydHMgXCJGdWxsIEFTQ0lJIENvZGUgMzlcIiBpZiBVU0VfQ09ERV8zOV9FWFRFTkRFRF9NT0RFIGlzIHNldC48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqIEBzZWUgQ29kZTkzUmVhZGVyXG4gICAgICovXG4gICAgY2xhc3MgQ29kZTM5UmVhZGVyIGV4dGVuZHMgT25lRFJlYWRlciB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgcmVhZGVyIHRoYXQgYXNzdW1lcyBhbGwgZW5jb2RlZCBkYXRhIGlzIGRhdGEsIGFuZCBkb2VzIG5vdCB0cmVhdCB0aGUgZmluYWxcbiAgICAgICAgICogY2hhcmFjdGVyIGFzIGEgY2hlY2sgZGlnaXQuIEl0IHdpbGwgbm90IGRlY29kZWQgXCJleHRlbmRlZCBDb2RlIDM5XCIgc2VxdWVuY2VzLlxuICAgICAgICAgKi9cbiAgICAgICAgLy8gcHVibGljIENvZGUzOVJlYWRlcigpIHtcbiAgICAgICAgLy8gICB0aGlzKGZhbHNlKTtcbiAgICAgICAgLy8gfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIHJlYWRlciB0aGF0IGNhbiBiZSBjb25maWd1cmVkIHRvIGNoZWNrIHRoZSBsYXN0IGNoYXJhY3RlciBhcyBhIGNoZWNrIGRpZ2l0LlxuICAgICAgICAgKiBJdCB3aWxsIG5vdCBkZWNvZGVkIFwiZXh0ZW5kZWQgQ29kZSAzOVwiIHNlcXVlbmNlcy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHVzaW5nQ2hlY2tEaWdpdCBpZiB0cnVlLCB0cmVhdCB0aGUgbGFzdCBkYXRhIGNoYXJhY3RlciBhcyBhIGNoZWNrIGRpZ2l0LCBub3RcbiAgICAgICAgICogZGF0YSwgYW5kIHZlcmlmeSB0aGF0IHRoZSBjaGVja3N1bSBwYXNzZXMuXG4gICAgICAgICAqL1xuICAgICAgICAvLyBwdWJsaWMgQ29kZTM5UmVhZGVyKGJvb2xlYW4gdXNpbmdDaGVja0RpZ2l0KSB7XG4gICAgICAgIC8vICAgdGhpcyh1c2luZ0NoZWNrRGlnaXQsIGZhbHNlKTtcbiAgICAgICAgLy8gfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIHJlYWRlciB0aGF0IGNhbiBiZSBjb25maWd1cmVkIHRvIGNoZWNrIHRoZSBsYXN0IGNoYXJhY3RlciBhcyBhIGNoZWNrIGRpZ2l0LFxuICAgICAgICAgKiBvciBvcHRpb25hbGx5IGF0dGVtcHQgdG8gZGVjb2RlIFwiZXh0ZW5kZWQgQ29kZSAzOVwiIHNlcXVlbmNlcyB0aGF0IGFyZSB1c2VkIHRvIGVuY29kZVxuICAgICAgICAgKiB0aGUgZnVsbCBBU0NJSSBjaGFyYWN0ZXIgc2V0LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gdXNpbmdDaGVja0RpZ2l0IGlmIHRydWUsIHRyZWF0IHRoZSBsYXN0IGRhdGEgY2hhcmFjdGVyIGFzIGEgY2hlY2sgZGlnaXQsIG5vdFxuICAgICAgICAgKiBkYXRhLCBhbmQgdmVyaWZ5IHRoYXQgdGhlIGNoZWNrc3VtIHBhc3Nlcy5cbiAgICAgICAgICogQHBhcmFtIGV4dGVuZGVkTW9kZSBpZiB0cnVlLCB3aWxsIGF0dGVtcHQgdG8gZGVjb2RlIGV4dGVuZGVkIENvZGUgMzkgc2VxdWVuY2VzIGluIHRoZVxuICAgICAgICAgKiB0ZXh0LlxuICAgICAgICAgKi9cbiAgICAgICAgY29uc3RydWN0b3IodXNpbmdDaGVja0RpZ2l0ID0gZmFsc2UsIGV4dGVuZGVkTW9kZSA9IGZhbHNlKSB7XG4gICAgICAgICAgICBzdXBlcigpO1xuICAgICAgICAgICAgdGhpcy51c2luZ0NoZWNrRGlnaXQgPSB1c2luZ0NoZWNrRGlnaXQ7XG4gICAgICAgICAgICB0aGlzLmV4dGVuZGVkTW9kZSA9IGV4dGVuZGVkTW9kZTtcbiAgICAgICAgICAgIHRoaXMuZGVjb2RlUm93UmVzdWx0ID0gJyc7XG4gICAgICAgICAgICB0aGlzLmNvdW50ZXJzID0gbmV3IEludDMyQXJyYXkoOSk7XG4gICAgICAgIH1cbiAgICAgICAgZGVjb2RlUm93KHJvd051bWJlciwgcm93LCBoaW50cykge1xuICAgICAgICAgICAgbGV0IHRoZUNvdW50ZXJzID0gdGhpcy5jb3VudGVycztcbiAgICAgICAgICAgIHRoZUNvdW50ZXJzLmZpbGwoMCk7XG4gICAgICAgICAgICB0aGlzLmRlY29kZVJvd1Jlc3VsdCA9ICcnO1xuICAgICAgICAgICAgbGV0IHN0YXJ0ID0gQ29kZTM5UmVhZGVyLmZpbmRBc3Rlcmlza1BhdHRlcm4ocm93LCB0aGVDb3VudGVycyk7XG4gICAgICAgICAgICAvLyBSZWFkIG9mZiB3aGl0ZSBzcGFjZVxuICAgICAgICAgICAgbGV0IG5leHRTdGFydCA9IHJvdy5nZXROZXh0U2V0KHN0YXJ0WzFdKTtcbiAgICAgICAgICAgIGxldCBlbmQgPSByb3cuZ2V0U2l6ZSgpO1xuICAgICAgICAgICAgbGV0IGRlY29kZWRDaGFyO1xuICAgICAgICAgICAgbGV0IGxhc3RTdGFydDtcbiAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICBDb2RlMzlSZWFkZXIucmVjb3JkUGF0dGVybihyb3csIG5leHRTdGFydCwgdGhlQ291bnRlcnMpO1xuICAgICAgICAgICAgICAgIGxldCBwYXR0ZXJuID0gQ29kZTM5UmVhZGVyLnRvTmFycm93V2lkZVBhdHRlcm4odGhlQ291bnRlcnMpO1xuICAgICAgICAgICAgICAgIGlmIChwYXR0ZXJuIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVjb2RlZENoYXIgPSBDb2RlMzlSZWFkZXIucGF0dGVyblRvQ2hhcihwYXR0ZXJuKTtcbiAgICAgICAgICAgICAgICB0aGlzLmRlY29kZVJvd1Jlc3VsdCArPSBkZWNvZGVkQ2hhcjtcbiAgICAgICAgICAgICAgICBsYXN0U3RhcnQgPSBuZXh0U3RhcnQ7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgY291bnRlciBvZiB0aGVDb3VudGVycykge1xuICAgICAgICAgICAgICAgICAgICBuZXh0U3RhcnQgKz0gY291bnRlcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gUmVhZCBvZmYgd2hpdGUgc3BhY2VcbiAgICAgICAgICAgICAgICBuZXh0U3RhcnQgPSByb3cuZ2V0TmV4dFNldChuZXh0U3RhcnQpO1xuICAgICAgICAgICAgfSB3aGlsZSAoZGVjb2RlZENoYXIgIT09ICcqJyk7XG4gICAgICAgICAgICB0aGlzLmRlY29kZVJvd1Jlc3VsdCA9IHRoaXMuZGVjb2RlUm93UmVzdWx0LnN1YnN0cmluZygwLCB0aGlzLmRlY29kZVJvd1Jlc3VsdC5sZW5ndGggLSAxKTsgLy8gcmVtb3ZlIGFzdGVyaXNrXG4gICAgICAgICAgICAvLyBMb29rIGZvciB3aGl0ZXNwYWNlIGFmdGVyIHBhdHRlcm46XG4gICAgICAgICAgICBsZXQgbGFzdFBhdHRlcm5TaXplID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGNvdW50ZXIgb2YgdGhlQ291bnRlcnMpIHtcbiAgICAgICAgICAgICAgICBsYXN0UGF0dGVyblNpemUgKz0gY291bnRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCB3aGl0ZVNwYWNlQWZ0ZXJFbmQgPSBuZXh0U3RhcnQgLSBsYXN0U3RhcnQgLSBsYXN0UGF0dGVyblNpemU7XG4gICAgICAgICAgICAvLyBJZiA1MCUgb2YgbGFzdCBwYXR0ZXJuIHNpemUsIGZvbGxvd2luZyBsYXN0IHBhdHRlcm4sIGlzIG5vdCB3aGl0ZXNwYWNlLCBmYWlsXG4gICAgICAgICAgICAvLyAoYnV0IGlmIGl0J3Mgd2hpdGVzcGFjZSB0byB0aGUgdmVyeSBlbmQgb2YgdGhlIGltYWdlLCB0aGF0J3MgT0spXG4gICAgICAgICAgICBpZiAobmV4dFN0YXJ0ICE9PSBlbmQgJiYgKHdoaXRlU3BhY2VBZnRlckVuZCAqIDIpIDwgbGFzdFBhdHRlcm5TaXplKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy51c2luZ0NoZWNrRGlnaXQpIHtcbiAgICAgICAgICAgICAgICBsZXQgbWF4ID0gdGhpcy5kZWNvZGVSb3dSZXN1bHQubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICBsZXQgdG90YWwgPSAwO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbWF4OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdG90YWwgKz0gQ29kZTM5UmVhZGVyLkFMUEhBQkVUX1NUUklORy5pbmRleE9mKHRoaXMuZGVjb2RlUm93UmVzdWx0LmNoYXJBdChpKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmRlY29kZVJvd1Jlc3VsdC5jaGFyQXQobWF4KSAhPT0gQ29kZTM5UmVhZGVyLkFMUEhBQkVUX1NUUklORy5jaGFyQXQodG90YWwgJSA0MykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IENoZWNrc3VtRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZGVjb2RlUm93UmVzdWx0ID0gdGhpcy5kZWNvZGVSb3dSZXN1bHQuc3Vic3RyaW5nKDAsIG1heCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5kZWNvZGVSb3dSZXN1bHQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gZmFsc2UgcG9zaXRpdmVcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCByZXN1bHRTdHJpbmc7XG4gICAgICAgICAgICBpZiAodGhpcy5leHRlbmRlZE1vZGUpIHtcbiAgICAgICAgICAgICAgICByZXN1bHRTdHJpbmcgPSBDb2RlMzlSZWFkZXIuZGVjb2RlRXh0ZW5kZWQodGhpcy5kZWNvZGVSb3dSZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0U3RyaW5nID0gdGhpcy5kZWNvZGVSb3dSZXN1bHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgbGVmdCA9IChzdGFydFsxXSArIHN0YXJ0WzBdKSAvIDIuMDtcbiAgICAgICAgICAgIGxldCByaWdodCA9IGxhc3RTdGFydCArIGxhc3RQYXR0ZXJuU2l6ZSAvIDIuMDtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUmVzdWx0KHJlc3VsdFN0cmluZywgbnVsbCwgMCwgW25ldyBSZXN1bHRQb2ludChsZWZ0LCByb3dOdW1iZXIpLCBuZXcgUmVzdWx0UG9pbnQocmlnaHQsIHJvd051bWJlcildLCBCYXJjb2RlRm9ybWF0JDEuQ09ERV8zOSwgbmV3IERhdGUoKS5nZXRUaW1lKCkpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBmaW5kQXN0ZXJpc2tQYXR0ZXJuKHJvdywgY291bnRlcnMpIHtcbiAgICAgICAgICAgIGxldCB3aWR0aCA9IHJvdy5nZXRTaXplKCk7XG4gICAgICAgICAgICBsZXQgcm93T2Zmc2V0ID0gcm93LmdldE5leHRTZXQoMCk7XG4gICAgICAgICAgICBsZXQgY291bnRlclBvc2l0aW9uID0gMDtcbiAgICAgICAgICAgIGxldCBwYXR0ZXJuU3RhcnQgPSByb3dPZmZzZXQ7XG4gICAgICAgICAgICBsZXQgaXNXaGl0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IHBhdHRlcm5MZW5ndGggPSBjb3VudGVycy5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gcm93T2Zmc2V0OyBpIDwgd2lkdGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChyb3cuZ2V0KGkpICE9PSBpc1doaXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbl0rKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb3VudGVyUG9zaXRpb24gPT09IHBhdHRlcm5MZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBMb29rIGZvciB3aGl0ZXNwYWNlIGJlZm9yZSBzdGFydCBwYXR0ZXJuLCA+PSA1MCUgb2Ygd2lkdGggb2Ygc3RhcnQgcGF0dGVyblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMudG9OYXJyb3dXaWRlUGF0dGVybihjb3VudGVycykgPT09IENvZGUzOVJlYWRlci5BU1RFUklTS19FTkNPRElORyAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdy5pc1JhbmdlKE1hdGgubWF4KDAsIHBhdHRlcm5TdGFydCAtIE1hdGguZmxvb3IoKGkgLSBwYXR0ZXJuU3RhcnQpIC8gMikpLCBwYXR0ZXJuU3RhcnQsIGZhbHNlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbcGF0dGVyblN0YXJ0LCBpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm5TdGFydCArPSBjb3VudGVyc1swXSArIGNvdW50ZXJzWzFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlcnMuY29weVdpdGhpbigwLCAyLCAyICsgY291bnRlclBvc2l0aW9uIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb24gLSAxXSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb25dID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJQb3NpdGlvbi0tO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlclBvc2l0aW9uKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbY291bnRlclBvc2l0aW9uXSA9IDE7XG4gICAgICAgICAgICAgICAgICAgIGlzV2hpdGUgPSAhaXNXaGl0ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBGb3IgZWZmaWNpZW5jeSwgcmV0dXJucyAtMSBvbiBmYWlsdXJlLiBOb3QgdGhyb3dpbmcgaGVyZSBzYXZlZCBhcyBtYW55IGFzIDcwMCBleGNlcHRpb25zXG4gICAgICAgIC8vIHBlciBpbWFnZSB3aGVuIHVzaW5nIHNvbWUgb2Ygb3VyIGJsYWNrYm94IGltYWdlcy5cbiAgICAgICAgc3RhdGljIHRvTmFycm93V2lkZVBhdHRlcm4oY291bnRlcnMpIHtcbiAgICAgICAgICAgIGxldCBudW1Db3VudGVycyA9IGNvdW50ZXJzLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBtYXhOYXJyb3dDb3VudGVyID0gMDtcbiAgICAgICAgICAgIGxldCB3aWRlQ291bnRlcnM7XG4gICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgbGV0IG1pbkNvdW50ZXIgPSAweDdmZmZmZmZmO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGNvdW50ZXIgb2YgY291bnRlcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvdW50ZXIgPCBtaW5Db3VudGVyICYmIGNvdW50ZXIgPiBtYXhOYXJyb3dDb3VudGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5Db3VudGVyID0gY291bnRlcjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBtYXhOYXJyb3dDb3VudGVyID0gbWluQ291bnRlcjtcbiAgICAgICAgICAgICAgICB3aWRlQ291bnRlcnMgPSAwO1xuICAgICAgICAgICAgICAgIGxldCB0b3RhbFdpZGVDb3VudGVyc1dpZHRoID0gMDtcbiAgICAgICAgICAgICAgICBsZXQgcGF0dGVybiA9IDA7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1Db3VudGVyczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBjb3VudGVyID0gY291bnRlcnNbaV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb3VudGVyID4gbWF4TmFycm93Q291bnRlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiB8PSAxIDw8IChudW1Db3VudGVycyAtIDEgLSBpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpZGVDb3VudGVycysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxXaWRlQ291bnRlcnNXaWR0aCArPSBjb3VudGVyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh3aWRlQ291bnRlcnMgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRm91bmQgMyB3aWRlIGNvdW50ZXJzLCBidXQgYXJlIHRoZXkgY2xvc2UgZW5vdWdoIGluIHdpZHRoP1xuICAgICAgICAgICAgICAgICAgICAvLyBXZSBjYW4gcGVyZm9ybSBhIGNoZWFwLCBjb25zZXJ2YXRpdmUgY2hlY2sgdG8gc2VlIGlmIGFueSBpbmRpdmlkdWFsXG4gICAgICAgICAgICAgICAgICAgIC8vIGNvdW50ZXIgaXMgbW9yZSB0aGFuIDEuNSB0aW1lcyB0aGUgYXZlcmFnZTpcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1Db3VudGVycyAmJiB3aWRlQ291bnRlcnMgPiAwOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjb3VudGVyID0gY291bnRlcnNbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY291bnRlciA+IG1heE5hcnJvd0NvdW50ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWRlQ291bnRlcnMtLTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0b3RhbFdpZGVDb3VudGVyc1dpZHRoID0gMyAqIGF2ZXJhZ2UsIHNvIHRoaXMgY2hlY2tzIGlmIGNvdW50ZXIgPj0gMy8yICogYXZlcmFnZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoY291bnRlciAqIDIpID49IHRvdGFsV2lkZUNvdW50ZXJzV2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0dGVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IHdoaWxlICh3aWRlQ291bnRlcnMgPiAzKTtcbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgcGF0dGVyblRvQ2hhcihwYXR0ZXJuKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IENvZGUzOVJlYWRlci5DSEFSQUNURVJfRU5DT0RJTkdTLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKENvZGUzOVJlYWRlci5DSEFSQUNURVJfRU5DT0RJTkdTW2ldID09PSBwYXR0ZXJuKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBDb2RlMzlSZWFkZXIuQUxQSEFCRVRfU1RSSU5HLmNoYXJBdChpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocGF0dGVybiA9PT0gQ29kZTM5UmVhZGVyLkFTVEVSSVNLX0VOQ09ESU5HKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICcqJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBkZWNvZGVFeHRlbmRlZChlbmNvZGVkKSB7XG4gICAgICAgICAgICBsZXQgbGVuZ3RoID0gZW5jb2RlZC5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgZGVjb2RlZCA9ICcnO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCBjID0gZW5jb2RlZC5jaGFyQXQoaSk7XG4gICAgICAgICAgICAgICAgaWYgKGMgPT09ICcrJyB8fCBjID09PSAnJCcgfHwgYyA9PT0gJyUnIHx8IGMgPT09ICcvJykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgbmV4dCA9IGVuY29kZWQuY2hhckF0KGkgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGRlY29kZWRDaGFyID0gJ1xcMCc7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoYykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnKyc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gK0EgdG8gK1ogbWFwIHRvIGEgdG8gelxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuZXh0ID49ICdBJyAmJiBuZXh0IDw9ICdaJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNvZGVkQ2hhciA9IFN0cmluZy5mcm9tQ2hhckNvZGUobmV4dC5jaGFyQ29kZUF0KDApICsgMzIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJyQnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vICRBIHRvICRaIG1hcCB0byBjb250cm9sIGNvZGVzIFNIIHRvIFNCXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5leHQgPj0gJ0EnICYmIG5leHQgPD0gJ1onKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY29kZWRDaGFyID0gU3RyaW5nLmZyb21DaGFyQ29kZShuZXh0LmNoYXJDb2RlQXQoMCkgLSA2NCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnJSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gJUEgdG8gJUUgbWFwIHRvIGNvbnRyb2wgY29kZXMgRVNDIHRvIFVTXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5leHQgPj0gJ0EnICYmIG5leHQgPD0gJ0UnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY29kZWRDaGFyID0gU3RyaW5nLmZyb21DaGFyQ29kZShuZXh0LmNoYXJDb2RlQXQoMCkgLSAzOCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKG5leHQgPj0gJ0YnICYmIG5leHQgPD0gJ0onKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY29kZWRDaGFyID0gU3RyaW5nLmZyb21DaGFyQ29kZShuZXh0LmNoYXJDb2RlQXQoMCkgLSAxMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKG5leHQgPj0gJ0snICYmIG5leHQgPD0gJ08nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY29kZWRDaGFyID0gU3RyaW5nLmZyb21DaGFyQ29kZShuZXh0LmNoYXJDb2RlQXQoMCkgKyAxNik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKG5leHQgPj0gJ1AnICYmIG5leHQgPD0gJ1QnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY29kZWRDaGFyID0gU3RyaW5nLmZyb21DaGFyQ29kZShuZXh0LmNoYXJDb2RlQXQoMCkgKyA0Myk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKG5leHQgPT09ICdVJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNvZGVkQ2hhciA9ICdcXDAnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChuZXh0ID09PSAnVicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjb2RlZENoYXIgPSAnQCc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKG5leHQgPT09ICdXJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNvZGVkQ2hhciA9ICdgJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobmV4dCA9PT0gJ1gnIHx8IG5leHQgPT09ICdZJyB8fCBuZXh0ID09PSAnWicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjb2RlZENoYXIgPSAnXFx4N2YnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJy8nOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC9BIHRvIC9PIG1hcCB0byAhIHRvICwgYW5kIC9aIG1hcHMgdG8gOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuZXh0ID49ICdBJyAmJiBuZXh0IDw9ICdPJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNvZGVkQ2hhciA9IFN0cmluZy5mcm9tQ2hhckNvZGUobmV4dC5jaGFyQ29kZUF0KDApIC0gMzIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChuZXh0ID09PSAnWicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjb2RlZENoYXIgPSAnOic7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRlY29kZWQgKz0gZGVjb2RlZENoYXI7XG4gICAgICAgICAgICAgICAgICAgIC8vIGJ1bXAgdXAgaSBhZ2FpbiBzaW5jZSB3ZSByZWFkIHR3byBjaGFyYWN0ZXJzXG4gICAgICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRlY29kZWQgKz0gYztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZGVjb2RlZDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBDb2RlMzlSZWFkZXIuQUxQSEFCRVRfU1RSSU5HID0gJzAxMjM0NTY3ODlBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWi0uICQvKyUnO1xuICAgIC8qKlxuICAgICAqIFRoZXNlIHJlcHJlc2VudCB0aGUgZW5jb2RpbmdzIG9mIGNoYXJhY3RlcnMsIGFzIHBhdHRlcm5zIG9mIHdpZGUgYW5kIG5hcnJvdyBiYXJzLlxuICAgICAqIFRoZSA5IGxlYXN0LXNpZ25pZmljYW50IGJpdHMgb2YgZWFjaCBpbnQgY29ycmVzcG9uZCB0byB0aGUgcGF0dGVybiBvZiB3aWRlIGFuZCBuYXJyb3csXG4gICAgICogd2l0aCAxcyByZXByZXNlbnRpbmcgXCJ3aWRlXCIgYW5kIDBzIHJlcHJlc2VudGluZyBuYXJyb3cuXG4gICAgICovXG4gICAgQ29kZTM5UmVhZGVyLkNIQVJBQ1RFUl9FTkNPRElOR1MgPSBbXG4gICAgICAgIDB4MDM0LCAweDEyMSwgMHgwNjEsIDB4MTYwLCAweDAzMSwgMHgxMzAsIDB4MDcwLCAweDAyNSwgMHgxMjQsIDB4MDY0LFxuICAgICAgICAweDEwOSwgMHgwNDksIDB4MTQ4LCAweDAxOSwgMHgxMTgsIDB4MDU4LCAweDAwRCwgMHgxMEMsIDB4MDRDLCAweDAxQyxcbiAgICAgICAgMHgxMDMsIDB4MDQzLCAweDE0MiwgMHgwMTMsIDB4MTEyLCAweDA1MiwgMHgwMDcsIDB4MTA2LCAweDA0NiwgMHgwMTYsXG4gICAgICAgIDB4MTgxLCAweDBDMSwgMHgxQzAsIDB4MDkxLCAweDE5MCwgMHgwRDAsIDB4MDg1LCAweDE4NCwgMHgwQzQsIDB4MEE4LFxuICAgICAgICAweDBBMiwgMHgwOEEsIDB4MDJBIC8vIC8tJVxuICAgIF07XG4gICAgQ29kZTM5UmVhZGVyLkFTVEVSSVNLX0VOQ09ESU5HID0gMHgwOTQ7XG5cbiAgICAvKipcbiAgICAgKiA8cD5EZWNvZGVzIElURiBiYXJjb2Rlcy48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFRqaWVjb1xuICAgICAqL1xuICAgIGNsYXNzIElURlJlYWRlciBleHRlbmRzIE9uZURSZWFkZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICAgIC8vIHByaXZhdGUgc3RhdGljIFcgPSAzOyAvLyBQaXhlbCB3aWR0aCBvZiBhIDN4IHdpZGUgbGluZVxuICAgICAgICAgICAgLy8gcHJpdmF0ZSBzdGF0aWMgdyA9IDI7IC8vIFBpeGVsIHdpZHRoIG9mIGEgMnggd2lkZSBsaW5lXG4gICAgICAgICAgICAvLyBwcml2YXRlIHN0YXRpYyBOID0gMTsgLy8gUGl4ZWQgd2lkdGggb2YgYSBuYXJyb3cgbGluZVxuICAgICAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgICAgIC8vIFN0b3JlcyB0aGUgYWN0dWFsIG5hcnJvdyBsaW5lIHdpZHRoIG9mIHRoZSBpbWFnZSBiZWluZyBkZWNvZGVkLlxuICAgICAgICAgICAgdGhpcy5uYXJyb3dMaW5lV2lkdGggPSAtMTtcbiAgICAgICAgfVxuICAgICAgICAvLyBTZWUgSVRGV3JpdGVyLlBBVFRFUk5TXG4gICAgICAgIC8qXG4gICAgICBcbiAgICAgICAgLyEqKlxuICAgICAgICAgKiBQYXR0ZXJucyBvZiBXaWRlIC8gTmFycm93IGxpbmVzIHRvIGluZGljYXRlIGVhY2ggZGlnaXRcbiAgICAgICAgICohL1xuICAgICAgICAqL1xuICAgICAgICBkZWNvZGVSb3cocm93TnVtYmVyLCByb3csIGhpbnRzKSB7XG4gICAgICAgICAgICAvLyBGaW5kIG91dCB3aGVyZSB0aGUgTWlkZGxlIHNlY3Rpb24gKHBheWxvYWQpIHN0YXJ0cyAmIGVuZHNcbiAgICAgICAgICAgIGxldCBzdGFydFJhbmdlID0gdGhpcy5kZWNvZGVTdGFydChyb3cpO1xuICAgICAgICAgICAgbGV0IGVuZFJhbmdlID0gdGhpcy5kZWNvZGVFbmQocm93KTtcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSBuZXcgU3RyaW5nQnVpbGRlcigpO1xuICAgICAgICAgICAgSVRGUmVhZGVyLmRlY29kZU1pZGRsZShyb3csIHN0YXJ0UmFuZ2VbMV0sIGVuZFJhbmdlWzBdLCByZXN1bHQpO1xuICAgICAgICAgICAgbGV0IHJlc3VsdFN0cmluZyA9IHJlc3VsdC50b1N0cmluZygpO1xuICAgICAgICAgICAgbGV0IGFsbG93ZWRMZW5ndGhzID0gbnVsbDtcbiAgICAgICAgICAgIGlmIChoaW50cyAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgYWxsb3dlZExlbmd0aHMgPSBoaW50cy5nZXQoRGVjb2RlSGludFR5cGUkMS5BTExPV0VEX0xFTkdUSFMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGFsbG93ZWRMZW5ndGhzID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBhbGxvd2VkTGVuZ3RocyA9IElURlJlYWRlci5ERUZBVUxUX0FMTE9XRURfTEVOR1RIUztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFRvIGF2b2lkIGZhbHNlIHBvc2l0aXZlcyB3aXRoIDJEIGJhcmNvZGVzIChhbmQgb3RoZXIgcGF0dGVybnMpLCBtYWtlXG4gICAgICAgICAgICAvLyBhbiBhc3N1bXB0aW9uIHRoYXQgdGhlIGRlY29kZWQgc3RyaW5nIG11c3QgYmUgYSAnc3RhbmRhcmQnIGxlbmd0aCBpZiBpdCdzIHNob3J0XG4gICAgICAgICAgICBsZXQgbGVuZ3RoID0gcmVzdWx0U3RyaW5nLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBsZW5ndGhPSyA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IG1heEFsbG93ZWRMZW5ndGggPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgdmFsdWUgb2YgYWxsb3dlZExlbmd0aHMpIHtcbiAgICAgICAgICAgICAgICBpZiAobGVuZ3RoID09PSB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBsZW5ndGhPSyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodmFsdWUgPiBtYXhBbGxvd2VkTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIG1heEFsbG93ZWRMZW5ndGggPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWxlbmd0aE9LICYmIGxlbmd0aCA+IG1heEFsbG93ZWRMZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBsZW5ndGhPSyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWxlbmd0aE9LKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcG9pbnRzID0gW25ldyBSZXN1bHRQb2ludChzdGFydFJhbmdlWzFdLCByb3dOdW1iZXIpLCBuZXcgUmVzdWx0UG9pbnQoZW5kUmFuZ2VbMF0sIHJvd051bWJlcildO1xuICAgICAgICAgICAgbGV0IHJlc3VsdFJldHVybiA9IG5ldyBSZXN1bHQocmVzdWx0U3RyaW5nLCBudWxsLCAvLyBubyBuYXR1cmFsIGJ5dGUgcmVwcmVzZW50YXRpb24gZm9yIHRoZXNlIGJhcmNvZGVzXG4gICAgICAgICAgICAwLCBwb2ludHMsIEJhcmNvZGVGb3JtYXQkMS5JVEYsIG5ldyBEYXRlKCkuZ2V0VGltZSgpKTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHRSZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLypcbiAgICAgICAgLyEqKlxuICAgICAgICAgKiBAcGFyYW0gcm93ICAgICAgICAgIHJvdyBvZiBibGFjay93aGl0ZSB2YWx1ZXMgdG8gc2VhcmNoXG4gICAgICAgICAqIEBwYXJhbSBwYXlsb2FkU3RhcnQgb2Zmc2V0IG9mIHN0YXJ0IHBhdHRlcm5cbiAgICAgICAgICogQHBhcmFtIHJlc3VsdFN0cmluZyB7QGxpbmsgU3RyaW5nQnVpbGRlcn0gdG8gYXBwZW5kIGRlY29kZWQgY2hhcnMgdG9cbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBpZiBkZWNvZGluZyBjb3VsZCBub3QgY29tcGxldGUgc3VjY2Vzc2Z1bGx5XG4gICAgICAgICAqIS8qL1xuICAgICAgICBzdGF0aWMgZGVjb2RlTWlkZGxlKHJvdywgcGF5bG9hZFN0YXJ0LCBwYXlsb2FkRW5kLCByZXN1bHRTdHJpbmcpIHtcbiAgICAgICAgICAgIC8vIERpZ2l0cyBhcmUgaW50ZXJsZWF2ZWQgaW4gcGFpcnMgLSA1IGJsYWNrIGxpbmVzIGZvciBvbmUgZGlnaXQsIGFuZCB0aGVcbiAgICAgICAgICAgIC8vIDVcbiAgICAgICAgICAgIC8vIGludGVybGVhdmVkIHdoaXRlIGxpbmVzIGZvciB0aGUgc2Vjb25kIGRpZ2l0LlxuICAgICAgICAgICAgLy8gVGhlcmVmb3JlLCBuZWVkIHRvIHNjYW4gMTAgbGluZXMgYW5kIHRoZW5cbiAgICAgICAgICAgIC8vIHNwbGl0IHRoZXNlIGludG8gdHdvIGFycmF5c1xuICAgICAgICAgICAgbGV0IGNvdW50ZXJEaWdpdFBhaXIgPSBuZXcgSW50MzJBcnJheSgxMCk7IC8vIDEwXG4gICAgICAgICAgICBsZXQgY291bnRlckJsYWNrID0gbmV3IEludDMyQXJyYXkoNSk7IC8vIDVcbiAgICAgICAgICAgIGxldCBjb3VudGVyV2hpdGUgPSBuZXcgSW50MzJBcnJheSg1KTsgLy8gNVxuICAgICAgICAgICAgY291bnRlckRpZ2l0UGFpci5maWxsKDApO1xuICAgICAgICAgICAgY291bnRlckJsYWNrLmZpbGwoMCk7XG4gICAgICAgICAgICBjb3VudGVyV2hpdGUuZmlsbCgwKTtcbiAgICAgICAgICAgIHdoaWxlIChwYXlsb2FkU3RhcnQgPCBwYXlsb2FkRW5kKSB7XG4gICAgICAgICAgICAgICAgLy8gR2V0IDEwIHJ1bnMgb2YgYmxhY2svd2hpdGUuXG4gICAgICAgICAgICAgICAgT25lRFJlYWRlci5yZWNvcmRQYXR0ZXJuKHJvdywgcGF5bG9hZFN0YXJ0LCBjb3VudGVyRGlnaXRQYWlyKTtcbiAgICAgICAgICAgICAgICAvLyBTcGxpdCB0aGVtIGludG8gZWFjaCBhcnJheVxuICAgICAgICAgICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgNTsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCB0d29LID0gMiAqIGs7XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ZXJCbGFja1trXSA9IGNvdW50ZXJEaWdpdFBhaXJbdHdvS107XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ZXJXaGl0ZVtrXSA9IGNvdW50ZXJEaWdpdFBhaXJbdHdvSyArIDFdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgYmVzdE1hdGNoID0gSVRGUmVhZGVyLmRlY29kZURpZ2l0KGNvdW50ZXJCbGFjayk7XG4gICAgICAgICAgICAgICAgcmVzdWx0U3RyaW5nLmFwcGVuZChiZXN0TWF0Y2gudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgYmVzdE1hdGNoID0gdGhpcy5kZWNvZGVEaWdpdChjb3VudGVyV2hpdGUpO1xuICAgICAgICAgICAgICAgIHJlc3VsdFN0cmluZy5hcHBlbmQoYmVzdE1hdGNoLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgIGNvdW50ZXJEaWdpdFBhaXIuZm9yRWFjaChmdW5jdGlvbiAoY291bnRlckRpZ2l0KSB7XG4gICAgICAgICAgICAgICAgICAgIHBheWxvYWRTdGFydCArPSBjb3VudGVyRGlnaXQ7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyovISoqXG4gICAgICAgICAqIElkZW50aWZ5IHdoZXJlIHRoZSBzdGFydCBvZiB0aGUgbWlkZGxlIC8gcGF5bG9hZCBzZWN0aW9uIHN0YXJ0cy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHJvdyByb3cgb2YgYmxhY2svd2hpdGUgdmFsdWVzIHRvIHNlYXJjaFxuICAgICAgICAgKiBAcmV0dXJuIEFycmF5LCBjb250YWluaW5nIGluZGV4IG9mIHN0YXJ0IG9mICdzdGFydCBibG9jaycgYW5kIGVuZCBvZlxuICAgICAgICAgKiAgICAgICAgICdzdGFydCBibG9jaydcbiAgICAgICAgICohLyovXG4gICAgICAgIGRlY29kZVN0YXJ0KHJvdykge1xuICAgICAgICAgICAgbGV0IGVuZFN0YXJ0ID0gSVRGUmVhZGVyLnNraXBXaGl0ZVNwYWNlKHJvdyk7XG4gICAgICAgICAgICBsZXQgc3RhcnRQYXR0ZXJuID0gSVRGUmVhZGVyLmZpbmRHdWFyZFBhdHRlcm4ocm93LCBlbmRTdGFydCwgSVRGUmVhZGVyLlNUQVJUX1BBVFRFUk4pO1xuICAgICAgICAgICAgLy8gRGV0ZXJtaW5lIHRoZSB3aWR0aCBvZiBhIG5hcnJvdyBsaW5lIGluIHBpeGVscy4gV2UgY2FuIGRvIHRoaXMgYnlcbiAgICAgICAgICAgIC8vIGdldHRpbmcgdGhlIHdpZHRoIG9mIHRoZSBzdGFydCBwYXR0ZXJuIGFuZCBkaXZpZGluZyBieSA0IGJlY2F1c2UgaXRzXG4gICAgICAgICAgICAvLyBtYWRlIHVwIG9mIDQgbmFycm93IGxpbmVzLlxuICAgICAgICAgICAgdGhpcy5uYXJyb3dMaW5lV2lkdGggPSAoc3RhcnRQYXR0ZXJuWzFdIC0gc3RhcnRQYXR0ZXJuWzBdKSAvIDQ7XG4gICAgICAgICAgICB0aGlzLnZhbGlkYXRlUXVpZXRab25lKHJvdywgc3RhcnRQYXR0ZXJuWzBdKTtcbiAgICAgICAgICAgIHJldHVybiBzdGFydFBhdHRlcm47XG4gICAgICAgIH1cbiAgICAgICAgLyovISoqXG4gICAgICAgICAqIFRoZSBzdGFydCAmIGVuZCBwYXR0ZXJucyBtdXN0IGJlIHByZS9wb3N0IGZpeGVkIGJ5IGEgcXVpZXQgem9uZS4gVGhpc1xuICAgICAgICAgKiB6b25lIG11c3QgYmUgYXQgbGVhc3QgMTAgdGltZXMgdGhlIHdpZHRoIG9mIGEgbmFycm93IGxpbmUuICBTY2FuIGJhY2sgdW50aWxcbiAgICAgICAgICogd2UgZWl0aGVyIGdldCB0byB0aGUgc3RhcnQgb2YgdGhlIGJhcmNvZGUgb3IgbWF0Y2ggdGhlIG5lY2Vzc2FyeSBudW1iZXIgb2ZcbiAgICAgICAgICogcXVpZXQgem9uZSBwaXhlbHMuXG4gICAgICAgICAqXG4gICAgICAgICAqIE5vdGU6IEl0cyBhc3N1bWVkIHRoZSByb3cgaXMgcmV2ZXJzZWQgd2hlbiB1c2luZyB0aGlzIG1ldGhvZCB0byBmaW5kXG4gICAgICAgICAqIHF1aWV0IHpvbmUgYWZ0ZXIgdGhlIGVuZCBwYXR0ZXJuLlxuICAgICAgICAgKlxuICAgICAgICAgKiByZWY6IGh0dHA6Ly93d3cuYmFyY29kZS0xLm5ldC9pMjVjb2RlLmh0bWxcbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHJvdyBiaXQgYXJyYXkgcmVwcmVzZW50aW5nIHRoZSBzY2FubmVkIGJhcmNvZGUuXG4gICAgICAgICAqIEBwYXJhbSBzdGFydFBhdHRlcm4gaW5kZXggaW50byByb3cgb2YgdGhlIHN0YXJ0IG9yIGVuZCBwYXR0ZXJuLlxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIHRoZSBxdWlldCB6b25lIGNhbm5vdCBiZSBmb3VuZFxuICAgICAgICAgKiEvKi9cbiAgICAgICAgdmFsaWRhdGVRdWlldFpvbmUocm93LCBzdGFydFBhdHRlcm4pIHtcbiAgICAgICAgICAgIGxldCBxdWlldENvdW50ID0gdGhpcy5uYXJyb3dMaW5lV2lkdGggKiAxMDsgLy8gZXhwZWN0IHRvIGZpbmQgdGhpcyBtYW55IHBpeGVscyBvZiBxdWlldCB6b25lXG4gICAgICAgICAgICAvLyBpZiB0aGVyZSBhcmUgbm90IHNvIG1hbnkgcGl4ZWwgYXQgYWxsIGxldCdzIHRyeSBhcyBtYW55IGFzIHBvc3NpYmxlXG4gICAgICAgICAgICBxdWlldENvdW50ID0gcXVpZXRDb3VudCA8IHN0YXJ0UGF0dGVybiA/IHF1aWV0Q291bnQgOiBzdGFydFBhdHRlcm47XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gc3RhcnRQYXR0ZXJuIC0gMTsgcXVpZXRDb3VudCA+IDAgJiYgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgICAgICBpZiAocm93LmdldChpKSkge1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcXVpZXRDb3VudC0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHF1aWV0Q291bnQgIT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyBVbmFibGUgdG8gZmluZCB0aGUgbmVjZXNzYXJ5IG51bWJlciBvZiBxdWlldCB6b25lIHBpeGVscy5cbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKlxuICAgICAgICAvISoqXG4gICAgICAgICAqIFNraXAgYWxsIHdoaXRlc3BhY2UgdW50aWwgd2UgZ2V0IHRvIHRoZSBmaXJzdCBibGFjayBsaW5lLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gcm93IHJvdyBvZiBibGFjay93aGl0ZSB2YWx1ZXMgdG8gc2VhcmNoXG4gICAgICAgICAqIEByZXR1cm4gaW5kZXggb2YgdGhlIGZpcnN0IGJsYWNrIGxpbmUuXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gVGhyb3dzIGV4Y2VwdGlvbiBpZiBubyBibGFjayBsaW5lcyBhcmUgZm91bmQgaW4gdGhlIHJvd1xuICAgICAgICAgKiEvKi9cbiAgICAgICAgc3RhdGljIHNraXBXaGl0ZVNwYWNlKHJvdykge1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSByb3cuZ2V0U2l6ZSgpO1xuICAgICAgICAgICAgY29uc3QgZW5kU3RhcnQgPSByb3cuZ2V0TmV4dFNldCgwKTtcbiAgICAgICAgICAgIGlmIChlbmRTdGFydCA9PT0gd2lkdGgpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBlbmRTdGFydDtcbiAgICAgICAgfVxuICAgICAgICAvKi8hKipcbiAgICAgICAgICogSWRlbnRpZnkgd2hlcmUgdGhlIGVuZCBvZiB0aGUgbWlkZGxlIC8gcGF5bG9hZCBzZWN0aW9uIGVuZHMuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSByb3cgcm93IG9mIGJsYWNrL3doaXRlIHZhbHVlcyB0byBzZWFyY2hcbiAgICAgICAgICogQHJldHVybiBBcnJheSwgY29udGFpbmluZyBpbmRleCBvZiBzdGFydCBvZiAnZW5kIGJsb2NrJyBhbmQgZW5kIG9mICdlbmRcbiAgICAgICAgICogICAgICAgICBibG9jaydcbiAgICAgICAgICohLyovXG4gICAgICAgIGRlY29kZUVuZChyb3cpIHtcbiAgICAgICAgICAgIC8vIEZvciBjb252ZW5pZW5jZSwgcmV2ZXJzZSB0aGUgcm93IGFuZCB0aGVuXG4gICAgICAgICAgICAvLyBzZWFyY2ggZnJvbSAndGhlIHN0YXJ0JyBmb3IgdGhlIGVuZCBibG9ja1xuICAgICAgICAgICAgcm93LnJldmVyc2UoKTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbGV0IGVuZFN0YXJ0ID0gSVRGUmVhZGVyLnNraXBXaGl0ZVNwYWNlKHJvdyk7XG4gICAgICAgICAgICAgICAgbGV0IGVuZFBhdHRlcm47XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgZW5kUGF0dGVybiA9IElURlJlYWRlci5maW5kR3VhcmRQYXR0ZXJuKHJvdywgZW5kU3RhcnQsIElURlJlYWRlci5FTkRfUEFUVEVSTl9SRVZFUlNFRFswXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBOb3RGb3VuZEV4Y2VwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZW5kUGF0dGVybiA9IElURlJlYWRlci5maW5kR3VhcmRQYXR0ZXJuKHJvdywgZW5kU3RhcnQsIElURlJlYWRlci5FTkRfUEFUVEVSTl9SRVZFUlNFRFsxXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gVGhlIHN0YXJ0ICYgZW5kIHBhdHRlcm5zIG11c3QgYmUgcHJlL3Bvc3QgZml4ZWQgYnkgYSBxdWlldCB6b25lLiBUaGlzXG4gICAgICAgICAgICAgICAgLy8gem9uZSBtdXN0IGJlIGF0IGxlYXN0IDEwIHRpbWVzIHRoZSB3aWR0aCBvZiBhIG5hcnJvdyBsaW5lLlxuICAgICAgICAgICAgICAgIC8vIHJlZjogaHR0cDovL3d3dy5iYXJjb2RlLTEubmV0L2kyNWNvZGUuaHRtbFxuICAgICAgICAgICAgICAgIHRoaXMudmFsaWRhdGVRdWlldFpvbmUocm93LCBlbmRQYXR0ZXJuWzBdKTtcbiAgICAgICAgICAgICAgICAvLyBOb3cgcmVjYWxjdWxhdGUgdGhlIGluZGljZXMgb2Ygd2hlcmUgdGhlICdlbmRibG9jaycgc3RhcnRzICYgc3RvcHMgdG9cbiAgICAgICAgICAgICAgICAvLyBhY2NvbW1vZGF0ZVxuICAgICAgICAgICAgICAgIC8vIHRoZSByZXZlcnNlZCBuYXR1cmUgb2YgdGhlIHNlYXJjaFxuICAgICAgICAgICAgICAgIGxldCB0ZW1wID0gZW5kUGF0dGVyblswXTtcbiAgICAgICAgICAgICAgICBlbmRQYXR0ZXJuWzBdID0gcm93LmdldFNpemUoKSAtIGVuZFBhdHRlcm5bMV07XG4gICAgICAgICAgICAgICAgZW5kUGF0dGVyblsxXSA9IHJvdy5nZXRTaXplKCkgLSB0ZW1wO1xuICAgICAgICAgICAgICAgIHJldHVybiBlbmRQYXR0ZXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZmluYWxseSB7XG4gICAgICAgICAgICAgICAgLy8gUHV0IHRoZSByb3cgYmFjayB0aGUgcmlnaHQgd2F5LlxuICAgICAgICAgICAgICAgIHJvdy5yZXZlcnNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLypcbiAgICAgICAgLyEqKlxuICAgICAgICAgKiBAcGFyYW0gcm93ICAgICAgIHJvdyBvZiBibGFjay93aGl0ZSB2YWx1ZXMgdG8gc2VhcmNoXG4gICAgICAgICAqIEBwYXJhbSByb3dPZmZzZXQgcG9zaXRpb24gdG8gc3RhcnQgc2VhcmNoXG4gICAgICAgICAqIEBwYXJhbSBwYXR0ZXJuICAgcGF0dGVybiBvZiBjb3VudHMgb2YgbnVtYmVyIG9mIGJsYWNrIGFuZCB3aGl0ZSBwaXhlbHMgdGhhdCBhcmVcbiAgICAgICAgICogICAgICAgICAgICAgICAgICBiZWluZyBzZWFyY2hlZCBmb3IgYXMgYSBwYXR0ZXJuXG4gICAgICAgICAqIEByZXR1cm4gc3RhcnQvZW5kIGhvcml6b250YWwgb2Zmc2V0IG9mIGd1YXJkIHBhdHRlcm4sIGFzIGFuIGFycmF5IG9mIHR3b1xuICAgICAgICAgKiAgICAgICAgIGludHNcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBpZiBwYXR0ZXJuIGlzIG5vdCBmb3VuZFxuICAgICAgICAgKiEvKi9cbiAgICAgICAgc3RhdGljIGZpbmRHdWFyZFBhdHRlcm4ocm93LCByb3dPZmZzZXQsIHBhdHRlcm4pIHtcbiAgICAgICAgICAgIGxldCBwYXR0ZXJuTGVuZ3RoID0gcGF0dGVybi5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgY291bnRlcnMgPSBuZXcgSW50MzJBcnJheShwYXR0ZXJuTGVuZ3RoKTtcbiAgICAgICAgICAgIGxldCB3aWR0aCA9IHJvdy5nZXRTaXplKCk7XG4gICAgICAgICAgICBsZXQgaXNXaGl0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGNvdW50ZXJQb3NpdGlvbiA9IDA7XG4gICAgICAgICAgICBsZXQgcGF0dGVyblN0YXJ0ID0gcm93T2Zmc2V0O1xuICAgICAgICAgICAgY291bnRlcnMuZmlsbCgwKTtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSByb3dPZmZzZXQ7IHggPCB3aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJvdy5nZXQoeCkgIT09IGlzV2hpdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbY291bnRlclBvc2l0aW9uXSsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvdW50ZXJQb3NpdGlvbiA9PT0gcGF0dGVybkxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChPbmVEUmVhZGVyLnBhdHRlcm5NYXRjaFZhcmlhbmNlKGNvdW50ZXJzLCBwYXR0ZXJuLCBJVEZSZWFkZXIuTUFYX0lORElWSURVQUxfVkFSSUFOQ0UpIDwgSVRGUmVhZGVyLk1BWF9BVkdfVkFSSUFOQ0UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gW3BhdHRlcm5TdGFydCwgeF07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuU3RhcnQgKz0gY291bnRlcnNbMF0gKyBjb3VudGVyc1sxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkoY291bnRlcnMsIDIsIGNvdW50ZXJzLCAwLCBjb3VudGVyUG9zaXRpb24gLSAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbiAtIDFdID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbl0gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlclBvc2l0aW9uLS07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyUG9zaXRpb24rKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb25dID0gMTtcbiAgICAgICAgICAgICAgICAgICAgaXNXaGl0ZSA9ICFpc1doaXRlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIC8qLyEqKlxuICAgICAgICAgKiBBdHRlbXB0cyB0byBkZWNvZGUgYSBzZXF1ZW5jZSBvZiBJVEYgYmxhY2svd2hpdGUgbGluZXMgaW50byBzaW5nbGVcbiAgICAgICAgICogZGlnaXQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBjb3VudGVycyB0aGUgY291bnRzIG9mIHJ1bnMgb2Ygb2JzZXJ2ZWQgYmxhY2svd2hpdGUvYmxhY2svLi4uIHZhbHVlc1xuICAgICAgICAgKiBAcmV0dXJuIFRoZSBkZWNvZGVkIGRpZ2l0XG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gaWYgZGlnaXQgY2Fubm90IGJlIGRlY29kZWRcbiAgICAgICAgICohLyovXG4gICAgICAgIHN0YXRpYyBkZWNvZGVEaWdpdChjb3VudGVycykge1xuICAgICAgICAgICAgbGV0IGJlc3RWYXJpYW5jZSA9IElURlJlYWRlci5NQVhfQVZHX1ZBUklBTkNFOyAvLyB3b3JzdCB2YXJpYW5jZSB3ZSdsbCBhY2NlcHRcbiAgICAgICAgICAgIGxldCBiZXN0TWF0Y2ggPSAtMTtcbiAgICAgICAgICAgIGxldCBtYXggPSBJVEZSZWFkZXIuUEFUVEVSTlMubGVuZ3RoO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXg7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCBwYXR0ZXJuID0gSVRGUmVhZGVyLlBBVFRFUk5TW2ldO1xuICAgICAgICAgICAgICAgIGxldCB2YXJpYW5jZSA9IE9uZURSZWFkZXIucGF0dGVybk1hdGNoVmFyaWFuY2UoY291bnRlcnMsIHBhdHRlcm4sIElURlJlYWRlci5NQVhfSU5ESVZJRFVBTF9WQVJJQU5DRSk7XG4gICAgICAgICAgICAgICAgaWYgKHZhcmlhbmNlIDwgYmVzdFZhcmlhbmNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RWYXJpYW5jZSA9IHZhcmlhbmNlO1xuICAgICAgICAgICAgICAgICAgICBiZXN0TWF0Y2ggPSBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh2YXJpYW5jZSA9PT0gYmVzdFZhcmlhbmNlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIHdlIGZpbmQgYSBzZWNvbmQgJ2Jlc3QgbWF0Y2gnIHdpdGggdGhlIHNhbWUgdmFyaWFuY2UsIHdlIGNhbiBub3QgcmVsaWFibHkgcmVwb3J0IHRvIGhhdmUgYSBzdWl0YWJsZSBtYXRjaFxuICAgICAgICAgICAgICAgICAgICBiZXN0TWF0Y2ggPSAtMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYmVzdE1hdGNoID49IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYmVzdE1hdGNoICUgMTA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBJVEZSZWFkZXIuUEFUVEVSTlMgPSBbXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMiwgMiwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDEsIDEsIDEsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAyLCAxLCAxLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgMiwgMSwgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDIsIDEsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAxLCAyLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMiwgMiwgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDEsIDIsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAxLCAxLCAyLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMiwgMSwgMiwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDMsIDMsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAxLCAxLCAxLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMywgMSwgMSwgM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDMsIDEsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAzLCAxLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgMSwgMywgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDMsIDMsIDEsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAxLCAzLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgMSwgMSwgMywgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDMsIDEsIDMsIDFdKSAvLyA5XG4gICAgXTtcbiAgICBJVEZSZWFkZXIuTUFYX0FWR19WQVJJQU5DRSA9IDAuMzg7XG4gICAgSVRGUmVhZGVyLk1BWF9JTkRJVklEVUFMX1ZBUklBTkNFID0gMC41O1xuICAgIC8qIC8hKiogVmFsaWQgSVRGIGxlbmd0aHMuIEFueXRoaW5nIGxvbmdlciB0aGFuIHRoZSBsYXJnZXN0IHZhbHVlIGlzIGFsc28gYWxsb3dlZC4gKiEvKi9cbiAgICBJVEZSZWFkZXIuREVGQVVMVF9BTExPV0VEX0xFTkdUSFMgPSBbNiwgOCwgMTAsIDEyLCAxNF07XG4gICAgLyovISoqXG4gICAgICogU3RhcnQvZW5kIGd1YXJkIHBhdHRlcm4uXG4gICAgICpcbiAgICAgKiBOb3RlOiBUaGUgZW5kIHBhdHRlcm4gaXMgcmV2ZXJzZWQgYmVjYXVzZSB0aGUgcm93IGlzIHJldmVyc2VkIGJlZm9yZVxuICAgICAqIHNlYXJjaGluZyBmb3IgdGhlIEVORF9QQVRURVJOXG4gICAgICohLyovXG4gICAgSVRGUmVhZGVyLlNUQVJUX1BBVFRFUk4gPSBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDEsIDFdKTtcbiAgICBJVEZSZWFkZXIuRU5EX1BBVFRFUk5fUkVWRVJTRUQgPSBbXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDNdKSAvLyAzeFxuICAgIF07XG5cbiAgICAvKipcbiAgICAgKiA8cD5FbmNhcHN1bGF0ZXMgZnVuY3Rpb25hbGl0eSBhbmQgaW1wbGVtZW50YXRpb24gdGhhdCBpcyBjb21tb24gdG8gVVBDIGFuZCBFQU4gZmFtaWxpZXNcbiAgICAgKiBvZiBvbmUtZGltZW5zaW9uYWwgYmFyY29kZXMuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBkc3dpdGtpbkBnb29nbGUuY29tIChEYW5pZWwgU3dpdGtpbilcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqIEBhdXRob3IgYWxhc2RhaXJAZ29vZ2xlLmNvbSAoQWxhc2RhaXIgTWFja2ludG9zaClcbiAgICAgKi9cbiAgICBjbGFzcyBBYnN0cmFjdFVQQ0VBTlJlYWRlciBleHRlbmRzIE9uZURSZWFkZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgICAgICB0aGlzLmRlY29kZVJvd1N0cmluZ0J1ZmZlciA9ICcnO1xuICAgICAgICB9XG5cbiAgICAgICAgc3RhdGljIGZpbmRTdGFydEd1YXJkUGF0dGVybihyb3cpIHtcbiAgICAgICAgICAgIGxldCBmb3VuZFN0YXJ0ID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgc3RhcnRSYW5nZTtcbiAgICAgICAgICAgIGxldCBuZXh0U3RhcnQgPSAwO1xuICAgICAgICAgICAgbGV0IGNvdW50ZXJzID0gSW50MzJBcnJheS5mcm9tKFswLCAwLCAwXSk7XG4gICAgICAgICAgICB3aGlsZSAoIWZvdW5kU3RhcnQpIHtcbiAgICAgICAgICAgICAgICBjb3VudGVycyA9IEludDMyQXJyYXkuZnJvbShbMCwgMCwgMF0pO1xuICAgICAgICAgICAgICAgIHN0YXJ0UmFuZ2UgPSBBYnN0cmFjdFVQQ0VBTlJlYWRlci5maW5kR3VhcmRQYXR0ZXJuKHJvdywgbmV4dFN0YXJ0LCBmYWxzZSwgdGhpcy5TVEFSVF9FTkRfUEFUVEVSTiwgY291bnRlcnMpO1xuICAgICAgICAgICAgICAgIGxldCBzdGFydCA9IHN0YXJ0UmFuZ2VbMF07XG4gICAgICAgICAgICAgICAgbmV4dFN0YXJ0ID0gc3RhcnRSYW5nZVsxXTtcbiAgICAgICAgICAgICAgICBsZXQgcXVpZXRTdGFydCA9IHN0YXJ0IC0gKG5leHRTdGFydCAtIHN0YXJ0KTtcbiAgICAgICAgICAgICAgICBpZiAocXVpZXRTdGFydCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvdW5kU3RhcnQgPSByb3cuaXNSYW5nZShxdWlldFN0YXJ0LCBzdGFydCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzdGFydFJhbmdlO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBjaGVja0NoZWNrc3VtKHMpIHtcbiAgICAgICAgICAgIHJldHVybiBBYnN0cmFjdFVQQ0VBTlJlYWRlci5jaGVja1N0YW5kYXJkVVBDRUFOQ2hlY2tzdW0ocyk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGNoZWNrU3RhbmRhcmRVUENFQU5DaGVja3N1bShzKSB7XG4gICAgICAgICAgICBsZXQgbGVuZ3RoID0gcy5sZW5ndGg7XG4gICAgICAgICAgICBpZiAobGVuZ3RoID09PSAwKVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIGxldCBjaGVjayA9IHBhcnNlSW50KHMuY2hhckF0KGxlbmd0aCAtIDEpLCAxMCk7XG4gICAgICAgICAgICByZXR1cm4gQWJzdHJhY3RVUENFQU5SZWFkZXIuZ2V0U3RhbmRhcmRVUENFQU5DaGVja3N1bShzLnN1YnN0cmluZygwLCBsZW5ndGggLSAxKSkgPT09IGNoZWNrO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXRTdGFuZGFyZFVQQ0VBTkNoZWNrc3VtKHMpIHtcbiAgICAgICAgICAgIGxldCBsZW5ndGggPSBzLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBzdW0gPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGxlbmd0aCAtIDE7IGkgPj0gMDsgaSAtPSAyKSB7XG4gICAgICAgICAgICAgICAgbGV0IGRpZ2l0ID0gcy5jaGFyQXQoaSkuY2hhckNvZGVBdCgwKSAtICcwJy5jaGFyQ29kZUF0KDApO1xuICAgICAgICAgICAgICAgIGlmIChkaWdpdCA8IDAgfHwgZGlnaXQgPiA5KSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3VtICs9IGRpZ2l0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3VtICo9IDM7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gbGVuZ3RoIC0gMjsgaSA+PSAwOyBpIC09IDIpIHtcbiAgICAgICAgICAgICAgICBsZXQgZGlnaXQgPSBzLmNoYXJBdChpKS5jaGFyQ29kZUF0KDApIC0gJzAnLmNoYXJDb2RlQXQoMCk7XG4gICAgICAgICAgICAgICAgaWYgKGRpZ2l0IDwgMCB8fCBkaWdpdCA+IDkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzdW0gKz0gZGlnaXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gKDEwMDAgLSBzdW0pICUgMTA7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGRlY29kZUVuZChyb3csIGVuZFN0YXJ0KSB7XG4gICAgICAgICAgICByZXR1cm4gQWJzdHJhY3RVUENFQU5SZWFkZXIuZmluZEd1YXJkUGF0dGVybihyb3csIGVuZFN0YXJ0LCBmYWxzZSwgQWJzdHJhY3RVUENFQU5SZWFkZXIuU1RBUlRfRU5EX1BBVFRFUk4sIG5ldyBJbnQzMkFycmF5KEFic3RyYWN0VVBDRUFOUmVhZGVyLlNUQVJUX0VORF9QQVRURVJOLmxlbmd0aCkuZmlsbCgwKSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBmaW5kR3VhcmRQYXR0ZXJuV2l0aG91dENvdW50ZXJzKHJvdywgcm93T2Zmc2V0LCB3aGl0ZUZpcnN0LCBwYXR0ZXJuKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5maW5kR3VhcmRQYXR0ZXJuKHJvdywgcm93T2Zmc2V0LCB3aGl0ZUZpcnN0LCBwYXR0ZXJuLCBuZXcgSW50MzJBcnJheShwYXR0ZXJuLmxlbmd0aCkpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gcm93IHJvdyBvZiBibGFjay93aGl0ZSB2YWx1ZXMgdG8gc2VhcmNoXG4gICAgICAgICAqIEBwYXJhbSByb3dPZmZzZXQgcG9zaXRpb24gdG8gc3RhcnQgc2VhcmNoXG4gICAgICAgICAqIEBwYXJhbSB3aGl0ZUZpcnN0IGlmIHRydWUsIGluZGljYXRlcyB0aGF0IHRoZSBwYXR0ZXJuIHNwZWNpZmllcyB3aGl0ZS9ibGFjay93aGl0ZS8uLi5cbiAgICAgICAgICogcGl4ZWwgY291bnRzLCBvdGhlcndpc2UsIGl0IGlzIGludGVycHJldGVkIGFzIGJsYWNrL3doaXRlL2JsYWNrLy4uLlxuICAgICAgICAgKiBAcGFyYW0gcGF0dGVybiBwYXR0ZXJuIG9mIGNvdW50cyBvZiBudW1iZXIgb2YgYmxhY2sgYW5kIHdoaXRlIHBpeGVscyB0aGF0IGFyZSBiZWluZ1xuICAgICAgICAgKiBzZWFyY2hlZCBmb3IgYXMgYSBwYXR0ZXJuXG4gICAgICAgICAqIEBwYXJhbSBjb3VudGVycyBhcnJheSBvZiBjb3VudGVycywgYXMgbG9uZyBhcyBwYXR0ZXJuLCB0byByZS11c2VcbiAgICAgICAgICogQHJldHVybiBzdGFydC9lbmQgaG9yaXpvbnRhbCBvZmZzZXQgb2YgZ3VhcmQgcGF0dGVybiwgYXMgYW4gYXJyYXkgb2YgdHdvIGludHNcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBpZiBwYXR0ZXJuIGlzIG5vdCBmb3VuZFxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGZpbmRHdWFyZFBhdHRlcm4ocm93LCByb3dPZmZzZXQsIHdoaXRlRmlyc3QsIHBhdHRlcm4sIGNvdW50ZXJzKSB7XG4gICAgICAgICAgICBsZXQgd2lkdGggPSByb3cuZ2V0U2l6ZSgpO1xuICAgICAgICAgICAgcm93T2Zmc2V0ID0gd2hpdGVGaXJzdCA/IHJvdy5nZXROZXh0VW5zZXQocm93T2Zmc2V0KSA6IHJvdy5nZXROZXh0U2V0KHJvd09mZnNldCk7XG4gICAgICAgICAgICBsZXQgY291bnRlclBvc2l0aW9uID0gMDtcbiAgICAgICAgICAgIGxldCBwYXR0ZXJuU3RhcnQgPSByb3dPZmZzZXQ7XG4gICAgICAgICAgICBsZXQgcGF0dGVybkxlbmd0aCA9IHBhdHRlcm4ubGVuZ3RoO1xuICAgICAgICAgICAgbGV0IGlzV2hpdGUgPSB3aGl0ZUZpcnN0O1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IHJvd09mZnNldDsgeCA8IHdpZHRoOyB4KyspIHtcbiAgICAgICAgICAgICAgICBpZiAocm93LmdldCh4KSAhPT0gaXNXaGl0ZSkge1xuICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb25dKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY291bnRlclBvc2l0aW9uID09PSBwYXR0ZXJuTGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKE9uZURSZWFkZXIucGF0dGVybk1hdGNoVmFyaWFuY2UoY291bnRlcnMsIHBhdHRlcm4sIEFic3RyYWN0VVBDRUFOUmVhZGVyLk1BWF9JTkRJVklEVUFMX1ZBUklBTkNFKSA8IEFic3RyYWN0VVBDRUFOUmVhZGVyLk1BWF9BVkdfVkFSSUFOQ0UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gSW50MzJBcnJheS5mcm9tKFtwYXR0ZXJuU3RhcnQsIHhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm5TdGFydCArPSBjb3VudGVyc1swXSArIGNvdW50ZXJzWzFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNsaWNlID0gY291bnRlcnMuc2xpY2UoMiwgY291bnRlcnMubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50ZXJQb3NpdGlvbiAtIDE7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2ldID0gc2xpY2VbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb24gLSAxXSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb25dID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJQb3NpdGlvbi0tO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlclBvc2l0aW9uKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbY291bnRlclBvc2l0aW9uXSA9IDE7XG4gICAgICAgICAgICAgICAgICAgIGlzV2hpdGUgPSAhaXNXaGl0ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZGVjb2RlRGlnaXQocm93LCBjb3VudGVycywgcm93T2Zmc2V0LCBwYXR0ZXJucykge1xuICAgICAgICAgICAgdGhpcy5yZWNvcmRQYXR0ZXJuKHJvdywgcm93T2Zmc2V0LCBjb3VudGVycyk7XG4gICAgICAgICAgICBsZXQgYmVzdFZhcmlhbmNlID0gdGhpcy5NQVhfQVZHX1ZBUklBTkNFO1xuICAgICAgICAgICAgbGV0IGJlc3RNYXRjaCA9IC0xO1xuICAgICAgICAgICAgbGV0IG1heCA9IHBhdHRlcm5zLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbWF4OyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgcGF0dGVybiA9IHBhdHRlcm5zW2ldO1xuICAgICAgICAgICAgICAgIGxldCB2YXJpYW5jZSA9IE9uZURSZWFkZXIucGF0dGVybk1hdGNoVmFyaWFuY2UoY291bnRlcnMsIHBhdHRlcm4sIEFic3RyYWN0VVBDRUFOUmVhZGVyLk1BWF9JTkRJVklEVUFMX1ZBUklBTkNFKTtcbiAgICAgICAgICAgICAgICBpZiAodmFyaWFuY2UgPCBiZXN0VmFyaWFuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgYmVzdFZhcmlhbmNlID0gdmFyaWFuY2U7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RNYXRjaCA9IGk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGJlc3RNYXRjaCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGJlc3RNYXRjaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIC8vIFRoZXNlIHR3byB2YWx1ZXMgYXJlIGNyaXRpY2FsIGZvciBkZXRlcm1pbmluZyBob3cgcGVybWlzc2l2ZSB0aGUgZGVjb2Rpbmcgd2lsbCBiZS5cbiAgICAvLyBXZSd2ZSBhcnJpdmVkIGF0IHRoZXNlIHZhbHVlcyB0aHJvdWdoIGEgbG90IG9mIHRyaWFsIGFuZCBlcnJvci4gU2V0dGluZyB0aGVtIGFueSBoaWdoZXJcbiAgICAvLyBsZXRzIGZhbHNlIHBvc2l0aXZlcyBjcmVlcCBpbiBxdWlja2x5LlxuICAgIEFic3RyYWN0VVBDRUFOUmVhZGVyLk1BWF9BVkdfVkFSSUFOQ0UgPSAwLjQ4O1xuICAgIEFic3RyYWN0VVBDRUFOUmVhZGVyLk1BWF9JTkRJVklEVUFMX1ZBUklBTkNFID0gMC43O1xuICAgIC8qKlxuICAgICAqIFN0YXJ0L2VuZCBndWFyZCBwYXR0ZXJuLlxuICAgICAqL1xuICAgIEFic3RyYWN0VVBDRUFOUmVhZGVyLlNUQVJUX0VORF9QQVRURVJOID0gSW50MzJBcnJheS5mcm9tKFsxLCAxLCAxXSk7XG4gICAgLyoqXG4gICAgICogUGF0dGVybiBtYXJraW5nIHRoZSBtaWRkbGUgb2YgYSBVUEMvRUFOIHBhdHRlcm4sIHNlcGFyYXRpbmcgdGhlIHR3byBoYWx2ZXMuXG4gICAgICovXG4gICAgQWJzdHJhY3RVUENFQU5SZWFkZXIuTUlERExFX1BBVFRFUk4gPSBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDEsIDEsIDFdKTtcbiAgICAvKipcbiAgICAgKiBlbmQgZ3VhcmQgcGF0dGVybi5cbiAgICAgKi9cbiAgICBBYnN0cmFjdFVQQ0VBTlJlYWRlci5FTkRfUEFUVEVSTiA9IEludDMyQXJyYXkuZnJvbShbMSwgMSwgMSwgMSwgMSwgMV0pO1xuICAgIC8qKlxuICAgICAqIFwiT2RkXCIsIG9yIFwiTFwiIHBhdHRlcm5zIHVzZWQgdG8gZW5jb2RlIFVQQy9FQU4gZGlnaXRzLlxuICAgICAqL1xuICAgIEFic3RyYWN0VVBDRUFOUmVhZGVyLkxfUEFUVEVSTlMgPSBbXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgMiwgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDIsIDIsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAxLCAyLCAyXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgNCwgMSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDEsIDMsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAyLCAzLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMSwgNF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDMsIDEsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAyLCAxLCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgMSwgMSwgMl0pLFxuICAgIF07XG5cbiAgICAvKipcbiAgICAgKiBAc2VlIFVQQ0VBTkV4dGVuc2lvbjJTdXBwb3J0XG4gICAgICovXG4gICAgY2xhc3MgVVBDRUFORXh0ZW5zaW9uNVN1cHBvcnQge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICAgIHRoaXMuQ0hFQ0tfRElHSVRfRU5DT0RJTkdTID0gWzB4MTgsIDB4MTQsIDB4MTIsIDB4MTEsIDB4MEMsIDB4MDYsIDB4MDMsIDB4MEEsIDB4MDksIDB4MDVdO1xuICAgICAgICAgICAgdGhpcy5kZWNvZGVNaWRkbGVDb3VudGVycyA9IEludDMyQXJyYXkuZnJvbShbMCwgMCwgMCwgMF0pO1xuICAgICAgICAgICAgdGhpcy5kZWNvZGVSb3dTdHJpbmdCdWZmZXIgPSAnJztcbiAgICAgICAgfVxuICAgICAgICBkZWNvZGVSb3cocm93TnVtYmVyLCByb3csIGV4dGVuc2lvblN0YXJ0UmFuZ2UpIHtcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSB0aGlzLmRlY29kZVJvd1N0cmluZ0J1ZmZlcjtcbiAgICAgICAgICAgIGxldCBlbmQgPSB0aGlzLmRlY29kZU1pZGRsZShyb3csIGV4dGVuc2lvblN0YXJ0UmFuZ2UsIHJlc3VsdCk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0U3RyaW5nID0gcmVzdWx0LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICBsZXQgZXh0ZW5zaW9uRGF0YSA9IFVQQ0VBTkV4dGVuc2lvbjVTdXBwb3J0LnBhcnNlRXh0ZW5zaW9uU3RyaW5nKHJlc3VsdFN0cmluZyk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0UG9pbnRzID0gW1xuICAgICAgICAgICAgICAgIG5ldyBSZXN1bHRQb2ludCgoZXh0ZW5zaW9uU3RhcnRSYW5nZVswXSArIGV4dGVuc2lvblN0YXJ0UmFuZ2VbMV0pIC8gMi4wLCByb3dOdW1iZXIpLFxuICAgICAgICAgICAgICAgIG5ldyBSZXN1bHRQb2ludChlbmQsIHJvd051bWJlcilcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBsZXQgZXh0ZW5zaW9uUmVzdWx0ID0gbmV3IFJlc3VsdChyZXN1bHRTdHJpbmcsIG51bGwsIDAsIHJlc3VsdFBvaW50cywgQmFyY29kZUZvcm1hdCQxLlVQQ19FQU5fRVhURU5TSU9OLCBuZXcgRGF0ZSgpLmdldFRpbWUoKSk7XG4gICAgICAgICAgICBpZiAoZXh0ZW5zaW9uRGF0YSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgZXh0ZW5zaW9uUmVzdWx0LnB1dEFsbE1ldGFkYXRhKGV4dGVuc2lvbkRhdGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGV4dGVuc2lvblJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBkZWNvZGVNaWRkbGUocm93LCBzdGFydFJhbmdlLCByZXN1bHRTdHJpbmcpIHtcbiAgICAgICAgICAgIGxldCBjb3VudGVycyA9IHRoaXMuZGVjb2RlTWlkZGxlQ291bnRlcnM7XG4gICAgICAgICAgICBjb3VudGVyc1swXSA9IDA7XG4gICAgICAgICAgICBjb3VudGVyc1sxXSA9IDA7XG4gICAgICAgICAgICBjb3VudGVyc1syXSA9IDA7XG4gICAgICAgICAgICBjb3VudGVyc1szXSA9IDA7XG4gICAgICAgICAgICBsZXQgZW5kID0gcm93LmdldFNpemUoKTtcbiAgICAgICAgICAgIGxldCByb3dPZmZzZXQgPSBzdGFydFJhbmdlWzFdO1xuICAgICAgICAgICAgbGV0IGxnUGF0dGVybkZvdW5kID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgNSAmJiByb3dPZmZzZXQgPCBlbmQ7IHgrKykge1xuICAgICAgICAgICAgICAgIGxldCBiZXN0TWF0Y2ggPSBBYnN0cmFjdFVQQ0VBTlJlYWRlci5kZWNvZGVEaWdpdChcbiAgICAgICAgICAgICAgICAgICAgcm93LFxuICAgICAgICAgICAgICAgICAgICBjb3VudGVycyxcbiAgICAgICAgICAgICAgICAgICAgcm93T2Zmc2V0LFxuICAgICAgICAgICAgICAgICAgICBBYnN0cmFjdFVQQ0VBTlJlYWRlci5MX0FORF9HX1BBVFRFUk5TKTtcbiAgICAgICAgICAgICAgICByZXN1bHRTdHJpbmcgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgoJzAnLmNoYXJDb2RlQXQoMCkgKyBiZXN0TWF0Y2ggJSAxMCkpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGNvdW50ZXIgb2YgY291bnRlcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgcm93T2Zmc2V0ICs9IGNvdW50ZXI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChiZXN0TWF0Y2ggPj0gMTApIHtcbiAgICAgICAgICAgICAgICAgICAgbGdQYXR0ZXJuRm91bmQgfD0gMSA8PCAoNCAtIHgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoeCAhPT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZWFkIG9mZiBzZXBhcmF0b3IgaWYgbm90IGxhc3RcbiAgICAgICAgICAgICAgICAgICAgcm93T2Zmc2V0ID0gcm93LmdldE5leHRTZXQocm93T2Zmc2V0KTtcbiAgICAgICAgICAgICAgICAgICAgcm93T2Zmc2V0ID0gcm93LmdldE5leHRVbnNldChyb3dPZmZzZXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyZXN1bHRTdHJpbmcubGVuZ3RoICE9PSA1KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgY2hlY2tEaWdpdCA9IHRoaXMuZGV0ZXJtaW5lQ2hlY2tEaWdpdChsZ1BhdHRlcm5Gb3VuZCk7XG4gICAgICAgICAgICBpZiAoVVBDRUFORXh0ZW5zaW9uNVN1cHBvcnQuZXh0ZW5zaW9uQ2hlY2tzdW0ocmVzdWx0U3RyaW5nLnRvU3RyaW5nKCkpICE9PSBjaGVja0RpZ2l0KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcm93T2Zmc2V0O1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBleHRlbnNpb25DaGVja3N1bShzKSB7XG4gICAgICAgICAgICBsZXQgbGVuZ3RoID0gcy5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgc3VtID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBsZW5ndGggLSAyOyBpID49IDA7IGkgLT0gMikge1xuICAgICAgICAgICAgICAgIHN1bSArPSBzLmNoYXJBdChpKS5jaGFyQ29kZUF0KDApIC0gJzAnLmNoYXJDb2RlQXQoMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdW0gKj0gMztcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBsZW5ndGggLSAxOyBpID49IDA7IGkgLT0gMikge1xuICAgICAgICAgICAgICAgIHN1bSArPSBzLmNoYXJBdChpKS5jaGFyQ29kZUF0KDApIC0gJzAnLmNoYXJDb2RlQXQoMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdW0gKj0gMztcbiAgICAgICAgICAgIHJldHVybiBzdW0gJSAxMDtcbiAgICAgICAgfVxuICAgICAgICBkZXRlcm1pbmVDaGVja0RpZ2l0KGxnUGF0dGVybkZvdW5kKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBkID0gMDsgZCA8IDEwOyBkKyspIHtcbiAgICAgICAgICAgICAgICBpZiAobGdQYXR0ZXJuRm91bmQgPT09IHRoaXMuQ0hFQ0tfRElHSVRfRU5DT0RJTkdTW2RdKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBwYXJzZUV4dGVuc2lvblN0cmluZyhyYXcpIHtcbiAgICAgICAgICAgIGlmIChyYXcubGVuZ3RoICE9PSA1KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSBVUENFQU5FeHRlbnNpb241U3VwcG9ydC5wYXJzZUV4dGVuc2lvbjVTdHJpbmcocmF3KTtcbiAgICAgICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IE1hcChbW1Jlc3VsdE1ldGFkYXRhVHlwZSQxLlNVR0dFU1RFRF9QUklDRSwgdmFsdWVdXSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHBhcnNlRXh0ZW5zaW9uNVN0cmluZyhyYXcpIHtcbiAgICAgICAgICAgIGxldCBjdXJyZW5jeTtcbiAgICAgICAgICAgIHN3aXRjaCAocmF3LmNoYXJBdCgwKSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJzAnOlxuICAgICAgICAgICAgICAgICAgICBjdXJyZW5jeSA9ICfCoyc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJzUnOlxuICAgICAgICAgICAgICAgICAgICBjdXJyZW5jeSA9ICckJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnOSc6XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlZmVyZW5jZTogaHR0cDovL3d3dy5qb2xseXRlY2guY29tXG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAocmF3KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICc5MDAwMCc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm8gc3VnZ2VzdGVkIHJldGFpbCBwcmljZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnOTk5OTEnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENvbXBsZW1lbnRhcnlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJzAuMDAnO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnOTk5OTAnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnVXNlZCc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlLi4uIHVua25vd24gY3VycmVuY3k/XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gJyc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gJyc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHJhd0Ftb3VudCA9IHBhcnNlSW50KHJhdy5zdWJzdHJpbmcoMSkpO1xuICAgICAgICAgICAgbGV0IHVuaXRzU3RyaW5nID0gKHJhd0Ftb3VudCAvIDEwMCkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGxldCBodW5kcmVkdGhzID0gcmF3QW1vdW50ICUgMTAwO1xuICAgICAgICAgICAgbGV0IGh1bmRyZWR0aHNTdHJpbmcgPSBodW5kcmVkdGhzIDwgMTAgPyAnMCcgKyBodW5kcmVkdGhzIDogaHVuZHJlZHRocy50b1N0cmluZygpOyAvLyBmaXhtZVxuICAgICAgICAgICAgcmV0dXJuIGN1cnJlbmN5ICsgdW5pdHNTdHJpbmcgKyAnLicgKyBodW5kcmVkdGhzU3RyaW5nO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHNlZSBVUENFQU5FeHRlbnNpb241U3VwcG9ydFxuICAgICAqL1xuICAgIGNsYXNzIFVQQ0VBTkV4dGVuc2lvbjJTdXBwb3J0IHtcbiAgICAgICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgICAgICB0aGlzLmRlY29kZU1pZGRsZUNvdW50ZXJzID0gSW50MzJBcnJheS5mcm9tKFswLCAwLCAwLCAwXSk7XG4gICAgICAgICAgICB0aGlzLmRlY29kZVJvd1N0cmluZ0J1ZmZlciA9ICcnO1xuICAgICAgICB9XG4gICAgICAgIGRlY29kZVJvdyhyb3dOdW1iZXIsIHJvdywgZXh0ZW5zaW9uU3RhcnRSYW5nZSkge1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IHRoaXMuZGVjb2RlUm93U3RyaW5nQnVmZmVyO1xuICAgICAgICAgICAgbGV0IGVuZCA9IHRoaXMuZGVjb2RlTWlkZGxlKHJvdywgZXh0ZW5zaW9uU3RhcnRSYW5nZSwgcmVzdWx0KTtcbiAgICAgICAgICAgIGxldCByZXN1bHRTdHJpbmcgPSByZXN1bHQudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGxldCBleHRlbnNpb25EYXRhID0gVVBDRUFORXh0ZW5zaW9uMlN1cHBvcnQucGFyc2VFeHRlbnNpb25TdHJpbmcocmVzdWx0U3RyaW5nKTtcbiAgICAgICAgICAgIGxldCByZXN1bHRQb2ludHMgPSBbXG4gICAgICAgICAgICAgICAgbmV3IFJlc3VsdFBvaW50KChleHRlbnNpb25TdGFydFJhbmdlWzBdICsgZXh0ZW5zaW9uU3RhcnRSYW5nZVsxXSkgLyAyLjAsIHJvd051bWJlciksXG4gICAgICAgICAgICAgICAgbmV3IFJlc3VsdFBvaW50KGVuZCwgcm93TnVtYmVyKVxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIGxldCBleHRlbnNpb25SZXN1bHQgPSBuZXcgUmVzdWx0KHJlc3VsdFN0cmluZywgbnVsbCwgMCwgcmVzdWx0UG9pbnRzLCBCYXJjb2RlRm9ybWF0JDEuVVBDX0VBTl9FWFRFTlNJT04sIG5ldyBEYXRlKCkuZ2V0VGltZSgpKTtcbiAgICAgICAgICAgIGlmIChleHRlbnNpb25EYXRhICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBleHRlbnNpb25SZXN1bHQucHV0QWxsTWV0YWRhdGEoZXh0ZW5zaW9uRGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZXh0ZW5zaW9uUmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIGRlY29kZU1pZGRsZShyb3csIHN0YXJ0UmFuZ2UsIHJlc3VsdFN0cmluZykge1xuICAgICAgICAgICAgbGV0IGNvdW50ZXJzID0gdGhpcy5kZWNvZGVNaWRkbGVDb3VudGVycztcbiAgICAgICAgICAgIGNvdW50ZXJzWzBdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzFdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzJdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzNdID0gMDtcbiAgICAgICAgICAgIGxldCBlbmQgPSByb3cuZ2V0U2l6ZSgpO1xuICAgICAgICAgICAgbGV0IHJvd09mZnNldCA9IHN0YXJ0UmFuZ2VbMV07XG4gICAgICAgICAgICBsZXQgY2hlY2tQYXJpdHkgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCAyICYmIHJvd09mZnNldCA8IGVuZDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IGJlc3RNYXRjaCA9IEFic3RyYWN0VVBDRUFOUmVhZGVyLmRlY29kZURpZ2l0KHJvdywgY291bnRlcnMsIHJvd09mZnNldCwgQWJzdHJhY3RVUENFQU5SZWFkZXIuTF9BTkRfR19QQVRURVJOUyk7XG4gICAgICAgICAgICAgICAgcmVzdWx0U3RyaW5nICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKCcwJy5jaGFyQ29kZUF0KDApICsgYmVzdE1hdGNoICUgMTApKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBjb3VudGVyIG9mIGNvdW50ZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJvd09mZnNldCArPSBjb3VudGVyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYmVzdE1hdGNoID49IDEwKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrUGFyaXR5IHw9IDEgPDwgKDEgLSB4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHggIT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVhZCBvZmYgc2VwYXJhdG9yIGlmIG5vdCBsYXN0XG4gICAgICAgICAgICAgICAgICAgIHJvd09mZnNldCA9IHJvdy5nZXROZXh0U2V0KHJvd09mZnNldCk7XG4gICAgICAgICAgICAgICAgICAgIHJvd09mZnNldCA9IHJvdy5nZXROZXh0VW5zZXQocm93T2Zmc2V0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmVzdWx0U3RyaW5nLmxlbmd0aCAhPT0gMikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBhcnNlSW50KHJlc3VsdFN0cmluZy50b1N0cmluZygpKSAlIDQgIT09IGNoZWNrUGFyaXR5KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcm93T2Zmc2V0O1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBwYXJzZUV4dGVuc2lvblN0cmluZyhyYXcpIHtcbiAgICAgICAgICAgIGlmIChyYXcubGVuZ3RoICE9PSAyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IE1hcChbW1Jlc3VsdE1ldGFkYXRhVHlwZSQxLklTU1VFX05VTUJFUiwgcGFyc2VJbnQocmF3KV1dKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNsYXNzIFVQQ0VBTkV4dGVuc2lvblN1cHBvcnQge1xuICAgICAgICBzdGF0aWMgZGVjb2RlUm93KHJvd051bWJlciwgcm93LCByb3dPZmZzZXQpIHtcbiAgICAgICAgICAgIGxldCBleHRlbnNpb25TdGFydFJhbmdlID0gQWJzdHJhY3RVUENFQU5SZWFkZXIuZmluZEd1YXJkUGF0dGVybihcbiAgICAgICAgICAgICAgICByb3csXG4gICAgICAgICAgICAgICAgcm93T2Zmc2V0LFxuICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICAgIHRoaXMuRVhURU5TSU9OX1NUQVJUX1BBVFRFUk4sXG4gICAgICAgICAgICAgICAgbmV3IEludDMyQXJyYXkodGhpcy5FWFRFTlNJT05fU1RBUlRfUEFUVEVSTi5sZW5ndGgpLmZpbGwoMCkpO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAvLyByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICBsZXQgZml2ZVN1cHBvcnQgPSBuZXcgVVBDRUFORXh0ZW5zaW9uNVN1cHBvcnQoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZml2ZVN1cHBvcnQuZGVjb2RlUm93KHJvd051bWJlciwgcm93LCBleHRlbnNpb25TdGFydFJhbmdlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAvLyByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICBsZXQgdHdvU3VwcG9ydCA9IG5ldyBVUENFQU5FeHRlbnNpb24yU3VwcG9ydCgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0d29TdXBwb3J0LmRlY29kZVJvdyhyb3dOdW1iZXIsIHJvdywgZXh0ZW5zaW9uU3RhcnRSYW5nZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgVVBDRUFORXh0ZW5zaW9uU3VwcG9ydC5FWFRFTlNJT05fU1RBUlRfUEFUVEVSTiA9IEludDMyQXJyYXkuZnJvbShbMSwgMSwgMl0pO1xuXG4gICAgLyoqXG4gICAgICogPHA+RW5jYXBzdWxhdGVzIGZ1bmN0aW9uYWxpdHkgYW5kIGltcGxlbWVudGF0aW9uIHRoYXQgaXMgY29tbW9uIHRvIFVQQyBhbmQgRUFOIGZhbWlsaWVzXG4gICAgICogb2Ygb25lLWRpbWVuc2lvbmFsIGJhcmNvZGVzLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKiBAYXV0aG9yIGFsYXNkYWlyQGdvb2dsZS5jb20gKEFsYXNkYWlyIE1hY2tpbnRvc2gpXG4gICAgICovXG4gICAgY2xhc3MgVVBDRUFOUmVhZGVyIGV4dGVuZHMgQWJzdHJhY3RVUENFQU5SZWFkZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICAgIHN1cGVyKCk7XG4gICAgICAgICAgICB0aGlzLmRlY29kZVJvd1N0cmluZ0J1ZmZlciA9ICcnO1xuICAgICAgICAgICAgVVBDRUFOUmVhZGVyLkxfQU5EX0dfUEFUVEVSTlMgPSBVUENFQU5SZWFkZXIuTF9QQVRURVJOUy5tYXAoYXJyID0+IEludDMyQXJyYXkuZnJvbShhcnIpKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAxMDsgaSA8IDIwOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgd2lkdGhzID0gVVBDRUFOUmVhZGVyLkxfUEFUVEVSTlNbaSAtIDEwXTtcbiAgICAgICAgICAgICAgICBsZXQgcmV2ZXJzZWRXaWR0aHMgPSBuZXcgSW50MzJBcnJheSh3aWR0aHMubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHdpZHRocy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICByZXZlcnNlZFdpZHRoc1tqXSA9IHdpZHRoc1t3aWR0aHMubGVuZ3RoIC0gaiAtIDFdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBVUENFQU5SZWFkZXIuTF9BTkRfR19QQVRURVJOU1tpXSA9IHJldmVyc2VkV2lkdGhzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGRlY29kZVJvdyhyb3dOdW1iZXIsIHJvdywgaGludHMpIHtcbiAgICAgICAgICAgIGxldCBzdGFydEd1YXJkUmFuZ2UgPSBVUENFQU5SZWFkZXIuZmluZFN0YXJ0R3VhcmRQYXR0ZXJuKHJvdyk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0UG9pbnRDYWxsYmFjayA9IGhpbnRzID09IG51bGwgPyBudWxsIDogaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuTkVFRF9SRVNVTFRfUE9JTlRfQ0FMTEJBQ0spO1xuICAgICAgICAgICAgaWYgKHJlc3VsdFBvaW50Q2FsbGJhY2sgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdFBvaW50ID0gbmV3IFJlc3VsdFBvaW50KChzdGFydEd1YXJkUmFuZ2VbMF0gKyBzdGFydEd1YXJkUmFuZ2VbMV0pIC8gMi4wLCByb3dOdW1iZXIpO1xuICAgICAgICAgICAgICAgIHJlc3VsdFBvaW50Q2FsbGJhY2suZm91bmRQb3NzaWJsZVJlc3VsdFBvaW50KHJlc3VsdFBvaW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBidWRlbGxvID0gdGhpcy5kZWNvZGVNaWRkbGUocm93LCBzdGFydEd1YXJkUmFuZ2UsIHRoaXMuZGVjb2RlUm93U3RyaW5nQnVmZmVyKTtcbiAgICAgICAgICAgIGxldCBlbmRTdGFydCA9IGJ1ZGVsbG8ucm93T2Zmc2V0O1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IGJ1ZGVsbG8ucmVzdWx0U3RyaW5nO1xuICAgICAgICAgICAgaWYgKHJlc3VsdFBvaW50Q2FsbGJhY2sgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdFBvaW50ID0gbmV3IFJlc3VsdFBvaW50KGVuZFN0YXJ0LCByb3dOdW1iZXIpO1xuICAgICAgICAgICAgICAgIHJlc3VsdFBvaW50Q2FsbGJhY2suZm91bmRQb3NzaWJsZVJlc3VsdFBvaW50KHJlc3VsdFBvaW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBlbmRSYW5nZSA9IHRoaXMuZGVjb2RlRW5kKHJvdywgZW5kU3RhcnQpO1xuICAgICAgICAgICAgaWYgKHJlc3VsdFBvaW50Q2FsbGJhY2sgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdFBvaW50ID0gbmV3IFJlc3VsdFBvaW50KChlbmRSYW5nZVswXSArIGVuZFJhbmdlWzFdKSAvIDIuMCwgcm93TnVtYmVyKTtcbiAgICAgICAgICAgICAgICByZXN1bHRQb2ludENhbGxiYWNrLmZvdW5kUG9zc2libGVSZXN1bHRQb2ludChyZXN1bHRQb2ludCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgdGhlcmUgaXMgYSBxdWlldCB6b25lIGF0IGxlYXN0IGFzIGJpZyBhcyB0aGUgZW5kIHBhdHRlcm4gYWZ0ZXIgdGhlIGJhcmNvZGUuIFRoZVxuICAgICAgICAgICAgLy8gc3BlYyBtaWdodCB3YW50IG1vcmUgd2hpdGVzcGFjZSwgYnV0IGluIHByYWN0aWNlIHRoaXMgaXMgdGhlIG1heGltdW0gd2UgY2FuIGNvdW50IG9uLlxuICAgICAgICAgICAgbGV0IGVuZCA9IGVuZFJhbmdlWzFdO1xuICAgICAgICAgICAgbGV0IHF1aWV0RW5kID0gZW5kICsgKGVuZCAtIGVuZFJhbmdlWzBdKTtcbiAgICAgICAgICAgIGlmIChxdWlldEVuZCA+PSByb3cuZ2V0U2l6ZSgpIHx8ICFyb3cuaXNSYW5nZShlbmQsIHF1aWV0RW5kLCBmYWxzZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCByZXN1bHRTdHJpbmcgPSByZXN1bHQudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIC8vIFVQQy9FQU4gc2hvdWxkIG5ldmVyIGJlIGxlc3MgdGhhbiA4IGNoYXJzIGFueXdheVxuICAgICAgICAgICAgaWYgKHJlc3VsdFN0cmluZy5sZW5ndGggPCA4KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFVUENFQU5SZWFkZXIuY2hlY2tDaGVja3N1bShyZXN1bHRTdHJpbmcpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IENoZWNrc3VtRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgbGVmdCA9IChzdGFydEd1YXJkUmFuZ2VbMV0gKyBzdGFydEd1YXJkUmFuZ2VbMF0pIC8gMi4wO1xuICAgICAgICAgICAgbGV0IHJpZ2h0ID0gKGVuZFJhbmdlWzFdICsgZW5kUmFuZ2VbMF0pIC8gMi4wO1xuICAgICAgICAgICAgbGV0IGZvcm1hdCA9IHRoaXMuZ2V0QmFyY29kZUZvcm1hdCgpO1xuICAgICAgICAgICAgbGV0IHJlc3VsdFBvaW50ID0gW25ldyBSZXN1bHRQb2ludChsZWZ0LCByb3dOdW1iZXIpLCBuZXcgUmVzdWx0UG9pbnQocmlnaHQsIHJvd051bWJlcildO1xuICAgICAgICAgICAgbGV0IGRlY29kZVJlc3VsdCA9IG5ldyBSZXN1bHQocmVzdWx0U3RyaW5nLCBudWxsLCAwLCByZXN1bHRQb2ludCwgZm9ybWF0LCBuZXcgRGF0ZSgpLmdldFRpbWUoKSk7XG4gICAgICAgICAgICBsZXQgZXh0ZW5zaW9uTGVuZ3RoID0gMDtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbGV0IGV4dGVuc2lvblJlc3VsdCA9IFVQQ0VBTkV4dGVuc2lvblN1cHBvcnQuZGVjb2RlUm93KHJvd051bWJlciwgcm93LCBlbmRSYW5nZVsxXSk7XG4gICAgICAgICAgICAgICAgZGVjb2RlUmVzdWx0LnB1dE1ldGFkYXRhKFJlc3VsdE1ldGFkYXRhVHlwZSQxLlVQQ19FQU5fRVhURU5TSU9OLCBleHRlbnNpb25SZXN1bHQuZ2V0VGV4dCgpKTtcbiAgICAgICAgICAgICAgICBkZWNvZGVSZXN1bHQucHV0QWxsTWV0YWRhdGEoZXh0ZW5zaW9uUmVzdWx0LmdldFJlc3VsdE1ldGFkYXRhKCkpO1xuICAgICAgICAgICAgICAgIGRlY29kZVJlc3VsdC5hZGRSZXN1bHRQb2ludHMoZXh0ZW5zaW9uUmVzdWx0LmdldFJlc3VsdFBvaW50cygpKTtcbiAgICAgICAgICAgICAgICBleHRlbnNpb25MZW5ndGggPSBleHRlbnNpb25SZXN1bHQuZ2V0VGV4dCgpLmxlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChpZ25vcmVFcnJvcikge31cbiAgICAgICAgICAgIGxldCBhbGxvd2VkRXh0ZW5zaW9ucyA9IGhpbnRzID09IG51bGwgPyBudWxsIDogaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuQUxMT1dFRF9FQU5fRVhURU5TSU9OUyk7XG4gICAgICAgICAgICBpZiAoYWxsb3dlZEV4dGVuc2lvbnMgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGxldCB2YWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGxlbmd0aCBpbiBhbGxvd2VkRXh0ZW5zaW9ucykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXh0ZW5zaW9uTGVuZ3RoLnRvU3RyaW5nKCkgPT09IGxlbmd0aCkgeyAvLyBjaGVjayBtZVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCF2YWxpZCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZGVjb2RlUmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIGRlY29kZUVuZChyb3csIGVuZFN0YXJ0KSB7XG4gICAgICAgICAgICByZXR1cm4gVVBDRUFOUmVhZGVyLmZpbmRHdWFyZFBhdHRlcm4oXG4gICAgICAgICAgICAgICAgcm93LCBlbmRTdGFydCwgZmFsc2UsIFVQQ0VBTlJlYWRlci5TVEFSVF9FTkRfUEFUVEVSTixcbiAgICAgICAgICAgICAgICBuZXcgSW50MzJBcnJheShVUENFQU5SZWFkZXIuU1RBUlRfRU5EX1BBVFRFUk4ubGVuZ3RoKS5maWxsKDApKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgY2hlY2tDaGVja3N1bShzKSB7XG4gICAgICAgICAgICByZXR1cm4gVVBDRUFOUmVhZGVyLmNoZWNrU3RhbmRhcmRVUENFQU5DaGVja3N1bShzKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgY2hlY2tTdGFuZGFyZFVQQ0VBTkNoZWNrc3VtKHMpIHtcbiAgICAgICAgICAgIGxldCBsZW5ndGggPSBzLmxlbmd0aDtcbiAgICAgICAgICAgIGlmIChsZW5ndGggPT09IDApXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgbGV0IGNoZWNrID0gcGFyc2VJbnQocy5jaGFyQXQobGVuZ3RoIC0gMSksIDEwKTtcbiAgICAgICAgICAgIHJldHVybiBVUENFQU5SZWFkZXIuZ2V0U3RhbmRhcmRVUENFQU5DaGVja3N1bShzLnN1YnN0cmluZygwLCBsZW5ndGggLSAxKSkgPT09IGNoZWNrO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXRTdGFuZGFyZFVQQ0VBTkNoZWNrc3VtKHMpIHtcbiAgICAgICAgICAgIGxldCBsZW5ndGggPSBzLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBzdW0gPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGxlbmd0aCAtIDE7IGkgPj0gMDsgaSAtPSAyKSB7XG4gICAgICAgICAgICAgICAgbGV0IGRpZ2l0ID0gcy5jaGFyQXQoaSkuY2hhckNvZGVBdCgwKSAtICcwJy5jaGFyQ29kZUF0KDApO1xuICAgICAgICAgICAgICAgIGlmIChkaWdpdCA8IDAgfHwgZGlnaXQgPiA5KSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3VtICs9IGRpZ2l0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3VtICo9IDM7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gbGVuZ3RoIC0gMjsgaSA+PSAwOyBpIC09IDIpIHtcbiAgICAgICAgICAgICAgICBsZXQgZGlnaXQgPSBzLmNoYXJBdChpKS5jaGFyQ29kZUF0KDApIC0gJzAnLmNoYXJDb2RlQXQoMCk7XG4gICAgICAgICAgICAgICAgaWYgKGRpZ2l0IDwgMCB8fCBkaWdpdCA+IDkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzdW0gKz0gZGlnaXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gKDEwMDAgLSBzdW0pICUgMTA7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiA8cD5JbXBsZW1lbnRzIGRlY29kaW5nIG9mIHRoZSBFQU4tMTMgZm9ybWF0LjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKiBAYXV0aG9yIGFsYXNkYWlyQGdvb2dsZS5jb20gKEFsYXNkYWlyIE1hY2tpbnRvc2gpXG4gICAgICovXG4gICAgY2xhc3MgRUFOMTNSZWFkZXIgZXh0ZW5kcyBVUENFQU5SZWFkZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICAgIHN1cGVyKCk7XG4gICAgICAgICAgICB0aGlzLmRlY29kZU1pZGRsZUNvdW50ZXJzID0gSW50MzJBcnJheS5mcm9tKFswLCAwLCAwLCAwXSk7XG4gICAgICAgIH1cbiAgICAgICAgZGVjb2RlTWlkZGxlKHJvdywgc3RhcnRSYW5nZSwgcmVzdWx0U3RyaW5nKSB7XG4gICAgICAgICAgICBsZXQgY291bnRlcnMgPSB0aGlzLmRlY29kZU1pZGRsZUNvdW50ZXJzO1xuICAgICAgICAgICAgY291bnRlcnNbMF0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbMV0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbMl0gPSAwO1xuICAgICAgICAgICAgY291bnRlcnNbM10gPSAwO1xuICAgICAgICAgICAgbGV0IGVuZCA9IHJvdy5nZXRTaXplKCk7XG4gICAgICAgICAgICBsZXQgcm93T2Zmc2V0ID0gc3RhcnRSYW5nZVsxXTtcbiAgICAgICAgICAgIGxldCBsZ1BhdHRlcm5Gb3VuZCA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IDYgJiYgcm93T2Zmc2V0IDwgZW5kOyB4KyspIHtcbiAgICAgICAgICAgICAgICBsZXQgYmVzdE1hdGNoID0gVVBDRUFOUmVhZGVyLmRlY29kZURpZ2l0KHJvdywgY291bnRlcnMsIHJvd09mZnNldCwgVVBDRUFOUmVhZGVyLkxfQU5EX0dfUEFUVEVSTlMpO1xuICAgICAgICAgICAgICAgIHJlc3VsdFN0cmluZyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKCgnMCcuY2hhckNvZGVBdCgwKSArIGJlc3RNYXRjaCAlIDEwKSk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgY291bnRlciBvZiBjb3VudGVycykge1xuICAgICAgICAgICAgICAgICAgICByb3dPZmZzZXQgKz0gY291bnRlcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGJlc3RNYXRjaCA+PSAxMCkge1xuICAgICAgICAgICAgICAgICAgICBsZ1BhdHRlcm5Gb3VuZCB8PSAxIDw8ICg1IC0geCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzdWx0U3RyaW5nID0gRUFOMTNSZWFkZXIuZGV0ZXJtaW5lRmlyc3REaWdpdChyZXN1bHRTdHJpbmcsIGxnUGF0dGVybkZvdW5kKTtcbiAgICAgICAgICAgIGxldCBtaWRkbGVSYW5nZSA9IFVQQ0VBTlJlYWRlci5maW5kR3VhcmRQYXR0ZXJuKFxuICAgICAgICAgICAgICAgIHJvdyxcbiAgICAgICAgICAgICAgICByb3dPZmZzZXQsXG4gICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICAgICAgICBVUENFQU5SZWFkZXIuTUlERExFX1BBVFRFUk4sXG4gICAgICAgICAgICAgICAgbmV3IEludDMyQXJyYXkoVVBDRUFOUmVhZGVyLk1JRERMRV9QQVRURVJOLmxlbmd0aCkuZmlsbCgwKSk7XG4gICAgICAgICAgICByb3dPZmZzZXQgPSBtaWRkbGVSYW5nZVsxXTtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgNiAmJiByb3dPZmZzZXQgPCBlbmQ7IHgrKykge1xuICAgICAgICAgICAgICAgIGxldCBiZXN0TWF0Y2ggPSBVUENFQU5SZWFkZXIuZGVjb2RlRGlnaXQocm93LCBjb3VudGVycywgcm93T2Zmc2V0LCBVUENFQU5SZWFkZXIuTF9QQVRURVJOUyk7XG4gICAgICAgICAgICAgICAgcmVzdWx0U3RyaW5nICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKCcwJy5jaGFyQ29kZUF0KDApICsgYmVzdE1hdGNoKSk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgY291bnRlciBvZiBjb3VudGVycykge1xuICAgICAgICAgICAgICAgICAgICByb3dPZmZzZXQgKz0gY291bnRlcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4geyByb3dPZmZzZXQsIHJlc3VsdFN0cmluZyB9O1xuICAgICAgICB9XG4gICAgICAgIGdldEJhcmNvZGVGb3JtYXQoKSB7XG4gICAgICAgICAgICByZXR1cm4gQmFyY29kZUZvcm1hdCQxLkVBTl8xMztcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZGV0ZXJtaW5lRmlyc3REaWdpdChyZXN1bHRTdHJpbmcsIGxnUGF0dGVybkZvdW5kKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBkID0gMDsgZCA8IDEwOyBkKyspIHtcbiAgICAgICAgICAgICAgICBpZiAobGdQYXR0ZXJuRm91bmQgPT09IHRoaXMuRklSU1RfRElHSVRfRU5DT0RJTkdTW2RdKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFN0cmluZyA9IFN0cmluZy5mcm9tQ2hhckNvZGUoKCcwJy5jaGFyQ29kZUF0KDApICsgZCkpICsgcmVzdWx0U3RyaW5nO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0U3RyaW5nO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgfVxuICAgIEVBTjEzUmVhZGVyLkZJUlNUX0RJR0lUX0VOQ09ESU5HUyA9IFsweDAwLCAweDBCLCAweDBELCAweEUsIDB4MTMsIDB4MTksIDB4MUMsIDB4MTUsIDB4MTYsIDB4MUFdO1xuXG4gICAgLyoqXG4gICAgICogPHA+SW1wbGVtZW50cyBkZWNvZGluZyBvZiB0aGUgRUFOLTggZm9ybWF0LjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgRUFOOFJlYWRlciBleHRlbmRzIFVQQ0VBTlJlYWRlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgICAgIHRoaXMuZGVjb2RlTWlkZGxlQ291bnRlcnMgPSBJbnQzMkFycmF5LmZyb20oWzAsIDAsIDAsIDBdKTtcbiAgICAgICAgfVxuICAgICAgICBkZWNvZGVNaWRkbGUocm93LCBzdGFydFJhbmdlLCByZXN1bHRTdHJpbmcpIHtcbiAgICAgICAgICAgIGNvbnN0IGNvdW50ZXJzID0gdGhpcy5kZWNvZGVNaWRkbGVDb3VudGVycztcbiAgICAgICAgICAgIGNvdW50ZXJzWzBdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzFdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzJdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzNdID0gMDtcbiAgICAgICAgICAgIGxldCBlbmQgPSByb3cuZ2V0U2l6ZSgpO1xuICAgICAgICAgICAgbGV0IHJvd09mZnNldCA9IHN0YXJ0UmFuZ2VbMV07XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IDQgJiYgcm93T2Zmc2V0IDwgZW5kOyB4KyspIHtcbiAgICAgICAgICAgICAgICBsZXQgYmVzdE1hdGNoID0gVVBDRUFOUmVhZGVyLmRlY29kZURpZ2l0KHJvdywgY291bnRlcnMsIHJvd09mZnNldCwgVVBDRUFOUmVhZGVyLkxfUEFUVEVSTlMpO1xuICAgICAgICAgICAgICAgIHJlc3VsdFN0cmluZyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKCgnMCcuY2hhckNvZGVBdCgwKSArIGJlc3RNYXRjaCkpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGNvdW50ZXIgb2YgY291bnRlcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgcm93T2Zmc2V0ICs9IGNvdW50ZXI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IG1pZGRsZVJhbmdlID0gVVBDRUFOUmVhZGVyLmZpbmRHdWFyZFBhdHRlcm4ocm93LCByb3dPZmZzZXQsIHRydWUsIFVQQ0VBTlJlYWRlci5NSURETEVfUEFUVEVSTiwgbmV3IEludDMyQXJyYXkoVVBDRUFOUmVhZGVyLk1JRERMRV9QQVRURVJOLmxlbmd0aCkuZmlsbCgwKSk7XG4gICAgICAgICAgICByb3dPZmZzZXQgPSBtaWRkbGVSYW5nZVsxXTtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgNCAmJiByb3dPZmZzZXQgPCBlbmQ7IHgrKykge1xuICAgICAgICAgICAgICAgIGxldCBiZXN0TWF0Y2ggPSBVUENFQU5SZWFkZXIuZGVjb2RlRGlnaXQocm93LCBjb3VudGVycywgcm93T2Zmc2V0LCBVUENFQU5SZWFkZXIuTF9QQVRURVJOUyk7XG4gICAgICAgICAgICAgICAgcmVzdWx0U3RyaW5nICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKCcwJy5jaGFyQ29kZUF0KDApICsgYmVzdE1hdGNoKSk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgY291bnRlciBvZiBjb3VudGVycykge1xuICAgICAgICAgICAgICAgICAgICByb3dPZmZzZXQgKz0gY291bnRlcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4geyByb3dPZmZzZXQsIHJlc3VsdFN0cmluZyB9O1xuICAgICAgICB9XG4gICAgICAgIGdldEJhcmNvZGVGb3JtYXQoKSB7XG4gICAgICAgICAgICByZXR1cm4gQmFyY29kZUZvcm1hdCQxLkVBTl84O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW5jYXBzdWxhdGVzIGZ1bmN0aW9uYWxpdHkgYW5kIGltcGxlbWVudGF0aW9uIHRoYXQgaXMgY29tbW9uIHRvIGFsbCBmYW1pbGllc1xuICAgICAqIG9mIG9uZS1kaW1lbnNpb25hbCBiYXJjb2Rlcy5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKiBAYXV0aG9yIHNhbTIzMzIgKFNhbSBSdWRsb2ZmKVxuICAgICAqXG4gICAgICogQHNvdXJjZSBodHRwczovL2dpdGh1Yi5jb20venhpbmcvenhpbmcvYmxvYi8zYzk2OTIzMjc2ZGQ1Nzg1ZDU4ZWI5NzBiNmJhM2Y4MGQzNmE5NTA1L2NvcmUvc3JjL21haW4vamF2YS9jb20vZ29vZ2xlL3p4aW5nL29uZWQvVVBDQVJlYWRlci5qYXZhXG4gICAgICpcbiAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICovXG4gICAgY2xhc3MgVVBDQVJlYWRlciBleHRlbmRzIFVQQ0VBTlJlYWRlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgICAgIHRoaXMuZWFuMTNSZWFkZXIgPSBuZXcgRUFOMTNSZWFkZXIoKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBAT3ZlcnJpZGVcbiAgICAgICAgZ2V0QmFyY29kZUZvcm1hdCgpIHtcbiAgICAgICAgICAgIHJldHVybiBCYXJjb2RlRm9ybWF0JDEuVVBDX0E7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTm90ZSB0aGF0IHdlIGRvbid0IHRyeSByb3RhdGlvbiB3aXRob3V0IHRoZSB0cnkgaGFyZGVyIGZsYWcsIGV2ZW4gaWYgcm90YXRpb24gd2FzIHN1cHBvcnRlZC5cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIGRlY29kZShpbWFnZSwgaGludHMpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1heWJlUmV0dXJuUmVzdWx0KHRoaXMuZWFuMTNSZWFkZXIuZGVjb2RlKGltYWdlKSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIGRlY29kZVJvdyhyb3dOdW1iZXIsIHJvdywgaGludHMpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1heWJlUmV0dXJuUmVzdWx0KHRoaXMuZWFuMTNSZWFkZXIuZGVjb2RlUm93KHJvd051bWJlciwgcm93LCBoaW50cykpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEBPdmVycmlkZVxuICAgICAgICBkZWNvZGVNaWRkbGUocm93LCBzdGFydFJhbmdlLCByZXN1bHRTdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVhbjEzUmVhZGVyLmRlY29kZU1pZGRsZShyb3csIHN0YXJ0UmFuZ2UsIHJlc3VsdFN0cmluZyk7XG4gICAgICAgIH1cbiAgICAgICAgbWF5YmVSZXR1cm5SZXN1bHQocmVzdWx0KSB7XG4gICAgICAgICAgICBsZXQgdGV4dCA9IHJlc3VsdC5nZXRUZXh0KCk7XG4gICAgICAgICAgICBpZiAodGV4dC5jaGFyQXQoMCkgPT09ICcwJykge1xuICAgICAgICAgICAgICAgIGxldCB1cGNhUmVzdWx0ID0gbmV3IFJlc3VsdCh0ZXh0LnN1YnN0cmluZygxKSwgbnVsbCwgbnVsbCwgcmVzdWx0LmdldFJlc3VsdFBvaW50cygpLCBCYXJjb2RlRm9ybWF0JDEuVVBDX0EpO1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQuZ2V0UmVzdWx0TWV0YWRhdGEoKSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHVwY2FSZXN1bHQucHV0QWxsTWV0YWRhdGEocmVzdWx0LmdldFJlc3VsdE1ldGFkYXRhKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdXBjYVJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJlc2V0KCkge1xuICAgICAgICAgICAgdGhpcy5lYW4xM1JlYWRlci5yZXNldCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogPHA+SW1wbGVtZW50cyBkZWNvZGluZyBvZiB0aGUgVVBDLUUgZm9ybWF0LjwvcD5cbiAgICAgKiA8cD48YSBocmVmPVwiaHR0cDovL3d3dy5iYXJjb2RlaXNsYW5kLmNvbS91cGNlLnBodG1sXCI+VGhpczwvYT4gaXMgYSBncmVhdCByZWZlcmVuY2UgZm9yXG4gICAgICogVVBDLUUgaW5mb3JtYXRpb24uPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKlxuICAgICAqIEBzb3VyY2UgaHR0cHM6Ly9naXRodWIuY29tL3p4aW5nL3p4aW5nL2Jsb2IvM2M5NjkyMzI3NmRkNTc4NWQ1OGViOTcwYjZiYTNmODBkMzZhOTUwNS9jb3JlL3NyYy9tYWluL2phdmEvY29tL2dvb2dsZS96eGluZy9vbmVkL1VQQ0VSZWFkZXIuamF2YVxuICAgICAqXG4gICAgICogQGV4cGVyaW1lbnRhbFxuICAgICAqL1xuICAgIC8qIGZpbmFsICovIGNsYXNzIFVQQ0VSZWFkZXIgZXh0ZW5kcyBVUENFQU5SZWFkZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICAgIHN1cGVyKCk7XG4gICAgICAgICAgICB0aGlzLmRlY29kZU1pZGRsZUNvdW50ZXJzID0gbmV3IEludDMyQXJyYXkoNCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIC8vIEBPdmVycmlkZVxuICAgICAgICBkZWNvZGVNaWRkbGUocm93LCBzdGFydFJhbmdlLCByZXN1bHQpIHtcbiAgICAgICAgICAgIGNvbnN0IGNvdW50ZXJzID0gdGhpcy5kZWNvZGVNaWRkbGVDb3VudGVycy5tYXAoeCA9PiB4KTtcbiAgICAgICAgICAgIGNvdW50ZXJzWzBdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzFdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzJdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzNdID0gMDtcbiAgICAgICAgICAgIGNvbnN0IGVuZCA9IHJvdy5nZXRTaXplKCk7XG4gICAgICAgICAgICBsZXQgcm93T2Zmc2V0ID0gc3RhcnRSYW5nZVsxXTtcbiAgICAgICAgICAgIGxldCBsZ1BhdHRlcm5Gb3VuZCA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IDYgJiYgcm93T2Zmc2V0IDwgZW5kOyB4KyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBiZXN0TWF0Y2ggPSBVUENFUmVhZGVyLmRlY29kZURpZ2l0KFxuICAgICAgICAgICAgICAgICAgICByb3csIGNvdW50ZXJzLCByb3dPZmZzZXQsIFVQQ0VSZWFkZXIuTF9BTkRfR19QQVRURVJOUyk7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKCcwJy5jaGFyQ29kZUF0KDApICsgKGJlc3RNYXRjaCAlIDEwKSkpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGNvdW50ZXIgb2YgY291bnRlcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgcm93T2Zmc2V0ICs9IGNvdW50ZXI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChiZXN0TWF0Y2ggPj0gMTApIHtcbiAgICAgICAgICAgICAgICAgICAgbGdQYXR0ZXJuRm91bmQgfD0gKDEgPDwgKDUgLSB4KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHJlc3VsdFN0cmluZyA9IFVQQ0VSZWFkZXIuZGV0ZXJtaW5lTnVtU3lzQW5kQ2hlY2tEaWdpdChcbiAgICAgICAgICAgICAgICByZXN1bHQsIGxnUGF0dGVybkZvdW5kKTtcbiAgICAgICAgICAgIHJldHVybiB7cm93T2Zmc2V0LCByZXN1bHRTdHJpbmd9O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uXG4gICAgICAgICAqL1xuICAgICAgICAvLyBAT3ZlcnJpZGVcbiAgICAgICAgZGVjb2RlRW5kKHJvdywgZW5kU3RhcnQpIHtcbiAgICAgICAgICAgIHJldHVybiBVUENFUmVhZGVyLmZpbmRHdWFyZFBhdHRlcm5XaXRob3V0Q291bnRlcnMoXG4gICAgICAgICAgICAgICAgcm93LCBlbmRTdGFydCwgdHJ1ZSwgVVBDRVJlYWRlci5NSURETEVfRU5EX1BBVFRFUk4pO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIGNoZWNrQ2hlY2tzdW0ocykge1xuICAgICAgICAgICAgcmV0dXJuIFVQQ0VBTlJlYWRlci5jaGVja0NoZWNrc3VtKFVQQ0VSZWFkZXIuY29udmVydFVQQ0V0b1VQQ0EocykpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGV0ZXJtaW5lTnVtU3lzQW5kQ2hlY2tEaWdpdChyZXN1bHRTdHJpbmcsIGxnUGF0dGVybkZvdW5kKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBudW1TeXMgPSAwOyBudW1TeXMgPD0gMTsgbnVtU3lzKyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBkID0gMDsgZCA8IDEwOyBkKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxnUGF0dGVybkZvdW5kID09PSB0aGlzLk5VTVNZU19BTkRfQ0hFQ0tfRElHSVRfUEFUVEVSTlNbbnVtU3lzXVtkXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHByZWZpeCA9IFN0cmluZy5mcm9tQ2hhckNvZGUoJzAnLmNoYXJDb2RlQXQoMCkgKyBudW1TeXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN1ZmZpeCA9IFN0cmluZy5mcm9tQ2hhckNvZGUoJzAnLmNoYXJDb2RlQXQoMCkgKyBkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwcmVmaXggKyByZXN1bHRTdHJpbmcgKyBzdWZmaXg7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBOb3RGb3VuZEV4Y2VwdGlvbi5nZXROb3RGb3VuZEluc3RhbmNlKCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIGdldEJhcmNvZGVGb3JtYXQoKSB7XG4gICAgICAgICAgICByZXR1cm4gQmFyY29kZUZvcm1hdCQxLlVQQ19FO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFeHBhbmRzIGEgVVBDLUUgdmFsdWUgYmFjayBpbnRvIGl0cyBmdWxsLCBlcXVpdmFsZW50IFVQQy1BIGNvZGUgdmFsdWUuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB1cGNlIFVQQy1FIGNvZGUgYXMgc3RyaW5nIG9mIGRpZ2l0c1xuICAgICAgICAgKiBAcmV0dXJuIGVxdWl2YWxlbnQgVVBDLUEgY29kZSBhcyBzdHJpbmcgb2YgZGlnaXRzXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgY29udmVydFVQQ0V0b1VQQ0EodXBjZSkge1xuICAgICAgICAgICAgLy8gdGhlIGZvbGxvd2luZyBsaW5lIGlzIGVxdWl2YWxlbnQgdG8gdXBjZS5nZXRDaGFycygxLCA3LCB1cGNlQ2hhcnMsIDApO1xuICAgICAgICAgICAgY29uc3QgdXBjZUNoYXJzID0gdXBjZS5zbGljZSgxLCA3KS5zcGxpdCgnJykubWFwKHggPT4geC5jaGFyQ29kZUF0KDApKTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBTdHJpbmdCdWlsZGVyKCAvKjEyKi8pO1xuICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCh1cGNlLmNoYXJBdCgwKSk7XG4gICAgICAgICAgICBsZXQgbGFzdENoYXIgPSB1cGNlQ2hhcnNbNV07XG4gICAgICAgICAgICBzd2l0Y2ggKGxhc3RDaGFyKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmRDaGFycyh1cGNlQ2hhcnMsIDAsIDIpO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKGxhc3RDaGFyKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnMDAwMCcpO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kQ2hhcnModXBjZUNoYXJzLCAyLCAzKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kQ2hhcnModXBjZUNoYXJzLCAwLCAzKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnMDAwMDAnKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZENoYXJzKHVwY2VDaGFycywgMywgMik7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZENoYXJzKHVwY2VDaGFycywgMCwgNCk7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoJzAwMDAwJyk7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQodXBjZUNoYXJzWzRdKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZENoYXJzKHVwY2VDaGFycywgMCwgNSk7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoJzAwMDAnKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChsYXN0Q2hhcik7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gT25seSBhcHBlbmQgY2hlY2sgZGlnaXQgaW4gY29udmVyc2lvbiBpZiBzdXBwbGllZFxuICAgICAgICAgICAgaWYgKHVwY2UubGVuZ3RoID49IDgpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKHVwY2UuY2hhckF0KDcpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBUaGUgcGF0dGVybiB0aGF0IG1hcmtzIHRoZSBtaWRkbGUsIGFuZCBlbmQsIG9mIGEgVVBDLUUgcGF0dGVybi5cbiAgICAgKiBUaGVyZSBpcyBubyBcInNlY29uZCBoYWxmXCIgdG8gYSBVUEMtRSBiYXJjb2RlLlxuICAgICAqL1xuICAgIFVQQ0VSZWFkZXIuTUlERExFX0VORF9QQVRURVJOID0gSW50MzJBcnJheS5mcm9tKFsxLCAxLCAxLCAxLCAxLCAxXSk7XG4gICAgLy8gRm9yIGFuIFVQQy1FIGJhcmNvZGUsIHRoZSBmaW5hbCBkaWdpdCBpcyByZXByZXNlbnRlZCBieSB0aGUgcGFyaXRpZXMgdXNlZFxuICAgIC8vIHRvIGVuY29kZSB0aGUgbWlkZGxlIHNpeCBkaWdpdHMsIGFjY29yZGluZyB0byB0aGUgdGFibGUgYmVsb3cuXG4gICAgLy9cbiAgICAvLyAgICAgICAgICAgICAgICBQYXJpdHkgb2YgbmV4dCA2IGRpZ2l0c1xuICAgIC8vICAgIERpZ2l0ICAgMCAgICAgMSAgICAgMiAgICAgMyAgICAgNCAgICAgNVxuICAgIC8vICAgICAgIDAgICAgRXZlbiAgIEV2ZW4gIEV2ZW4gT2RkICBPZGQgICBPZGRcbiAgICAvLyAgICAgICAxICAgIEV2ZW4gICBFdmVuICBPZGQgIEV2ZW4gT2RkICAgT2RkXG4gICAgLy8gICAgICAgMiAgICBFdmVuICAgRXZlbiAgT2RkICBPZGQgIEV2ZW4gIE9kZFxuICAgIC8vICAgICAgIDMgICAgRXZlbiAgIEV2ZW4gIE9kZCAgT2RkICBPZGQgICBFdmVuXG4gICAgLy8gICAgICAgNCAgICBFdmVuICAgT2RkICAgRXZlbiBFdmVuIE9kZCAgIE9kZFxuICAgIC8vICAgICAgIDUgICAgRXZlbiAgIE9kZCAgIE9kZCAgRXZlbiBFdmVuICBPZGRcbiAgICAvLyAgICAgICA2ICAgIEV2ZW4gICBPZGQgICBPZGQgIE9kZCAgRXZlbiAgRXZlblxuICAgIC8vICAgICAgIDcgICAgRXZlbiAgIE9kZCAgIEV2ZW4gT2RkICBFdmVuICBPZGRcbiAgICAvLyAgICAgICA4ICAgIEV2ZW4gICBPZGQgICBFdmVuIE9kZCAgT2RkICAgRXZlblxuICAgIC8vICAgICAgIDkgICAgRXZlbiAgIE9kZCAgIE9kZCAgRXZlbiBPZGQgICBFdmVuXG4gICAgLy9cbiAgICAvLyBUaGUgZW5jb2RpbmcgaXMgcmVwcmVzZW50ZWQgYnkgdGhlIGZvbGxvd2luZyBhcnJheSwgd2hpY2ggaXMgYSBiaXQgcGF0dGVyblxuICAgIC8vIHVzaW5nIE9kZCA9IDAgYW5kIEV2ZW4gPSAxLiBGb3IgZXhhbXBsZSwgNSBpcyByZXByZXNlbnRlZCBieTpcbiAgICAvL1xuICAgIC8vICAgICAgICAgICAgICBPZGQgRXZlbiBFdmVuIE9kZCBPZGQgRXZlblxuICAgIC8vIGluIGJpbmFyeTpcbiAgICAvLyAgICAgICAgICAgICAgICAwICAgIDEgICAgMSAgIDAgICAwICAgIDEgICA9PSAweDE5XG4gICAgLy9cbiAgICAvKipcbiAgICAgKiBTZWUge0BsaW5rICNMX0FORF9HX1BBVFRFUk5TfTsgdGhlc2UgdmFsdWVzIHNpbWlsYXJseSByZXByZXNlbnQgcGF0dGVybnMgb2ZcbiAgICAgKiBldmVuLW9kZCBwYXJpdHkgZW5jb2RpbmdzIG9mIGRpZ2l0cyB0aGF0IGltcGx5IGJvdGggdGhlIG51bWJlciBzeXN0ZW0gKDAgb3IgMSlcbiAgICAgKiB1c2VkLCBhbmQgdGhlIGNoZWNrIGRpZ2l0LlxuICAgICAqL1xuICAgIFVQQ0VSZWFkZXIuTlVNU1lTX0FORF9DSEVDS19ESUdJVF9QQVRURVJOUyA9IFtcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsweDM4LCAweDM0LCAweDMyLCAweDMxLCAweDJDLCAweDI2LCAweDIzLCAweDJBLCAweDI5LCAweDI1XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMHgwNywgMHgwQiwgMHgwRCwgMHgwRSwgMHgxMywgMHgxOSwgMHgxQywgMHgxNSwgMHgxNiwgMHgxQV0pLFxuICAgIF07XG5cbiAgICAvKipcbiAgICAgKiA8cD5BIHJlYWRlciB0aGF0IGNhbiByZWFkIGFsbCBhdmFpbGFibGUgVVBDL0VBTiBmb3JtYXRzLiBJZiBhIGNhbGxlciB3YW50cyB0byB0cnkgdG9cbiAgICAgKiByZWFkIGFsbCBzdWNoIGZvcm1hdHMsIGl0IGlzIG1vc3QgZWZmaWNpZW50IHRvIHVzZSB0aGlzIGltcGxlbWVudGF0aW9uIHJhdGhlciB0aGFuIGludm9rZVxuICAgICAqIGluZGl2aWR1YWwgcmVhZGVycy48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIE11bHRpRm9ybWF0VVBDRUFOUmVhZGVyIGV4dGVuZHMgT25lRFJlYWRlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGhpbnRzKSB7XG4gICAgICAgICAgICBzdXBlcigpO1xuICAgICAgICAgICAgbGV0IHBvc3NpYmxlRm9ybWF0cyA9IGhpbnRzID09IG51bGwgPyBudWxsIDogaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuUE9TU0lCTEVfRk9STUFUUyk7XG4gICAgICAgICAgICBsZXQgcmVhZGVycyA9IFtdO1xuICAgICAgICAgICAgaWYgKCFpc051bGxPclVuZGVmaW5lZChwb3NzaWJsZUZvcm1hdHMpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHBvc3NpYmxlRm9ybWF0cy5pbmRleE9mKEJhcmNvZGVGb3JtYXQkMS5FQU5fMTMpID4gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVycy5wdXNoKG5ldyBFQU4xM1JlYWRlcigpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHBvc3NpYmxlRm9ybWF0cy5pbmRleE9mKEJhcmNvZGVGb3JtYXQkMS5VUENfQSkgPiAtMSkge1xuICAgICAgICAgICAgICAgICAgICByZWFkZXJzLnB1c2gobmV3IFVQQ0FSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChwb3NzaWJsZUZvcm1hdHMuaW5kZXhPZihCYXJjb2RlRm9ybWF0JDEuRUFOXzgpID4gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVycy5wdXNoKG5ldyBFQU44UmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocG9zc2libGVGb3JtYXRzLmluZGV4T2YoQmFyY29kZUZvcm1hdCQxLlVQQ19FKSA+IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlcnMucHVzaChuZXcgVVBDRVJlYWRlcigpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIE5vIGhpbnRzIHByb3ZpZGVkLlxuICAgICAgICAgICAgICAgIHJlYWRlcnMucHVzaChuZXcgRUFOMTNSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgcmVhZGVycy5wdXNoKG5ldyBVUENBUmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIHJlYWRlcnMucHVzaChuZXcgRUFOOFJlYWRlcigpKTtcbiAgICAgICAgICAgICAgICByZWFkZXJzLnB1c2gobmV3IFVQQ0VSZWFkZXIoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnJlYWRlcnMgPSByZWFkZXJzO1xuICAgICAgICB9XG4gICAgICAgIGRlY29kZVJvdyhyb3dOdW1iZXIsIHJvdywgaGludHMpIHtcbiAgICAgICAgICAgIGZvciAobGV0IHJlYWRlciBvZiB0aGlzLnJlYWRlcnMpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAvLyBjb25zdCByZXN1bHQ6IFJlc3VsdCA9IHJlYWRlci5kZWNvZGVSb3cocm93TnVtYmVyLCByb3csIHN0YXJ0R3VhcmRQYXR0ZXJuLCBoaW50cyk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHJlYWRlci5kZWNvZGVSb3cocm93TnVtYmVyLCByb3csIGhpbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gU3BlY2lhbCBjYXNlOiBhIDEyLWRpZ2l0IGNvZGUgZW5jb2RlZCBpbiBVUEMtQSBpcyBpZGVudGljYWwgdG8gYSBcIjBcIlxuICAgICAgICAgICAgICAgICAgICAvLyBmb2xsb3dlZCBieSB0aG9zZSAxMiBkaWdpdHMgZW5jb2RlZCBhcyBFQU4tMTMuIEVhY2ggd2lsbCByZWNvZ25pemUgc3VjaCBhIGNvZGUsXG4gICAgICAgICAgICAgICAgICAgIC8vIFVQQy1BIGFzIGEgMTItZGlnaXQgc3RyaW5nIGFuZCBFQU4tMTMgYXMgYSAxMy1kaWdpdCBzdHJpbmcgc3RhcnRpbmcgd2l0aCBcIjBcIi5cbiAgICAgICAgICAgICAgICAgICAgLy8gSW5kaXZpZHVhbGx5IHRoZXNlIGFyZSBjb3JyZWN0IGFuZCB0aGVpciByZWFkZXJzIHdpbGwgYm90aCByZWFkIHN1Y2ggYSBjb2RlXG4gICAgICAgICAgICAgICAgICAgIC8vIGFuZCBjb3JyZWN0bHkgY2FsbCBpdCBFQU4tMTMsIG9yIFVQQy1BLCByZXNwZWN0aXZlbHkuXG4gICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgIC8vIEluIHRoaXMgY2FzZSwgaWYgd2UndmUgYmVlbiBsb29raW5nIGZvciBib3RoIHR5cGVzLCB3ZSdkIGxpa2UgdG8gY2FsbCBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBhIFVQQy1BIGNvZGUuIEJ1dCBmb3IgZWZmaWNpZW5jeSB3ZSBvbmx5IHJ1biB0aGUgRUFOLTEzIGRlY29kZXIgdG8gYWxzbyByZWFkXG4gICAgICAgICAgICAgICAgICAgIC8vIFVQQy1BLiBTbyB3ZSBzcGVjaWFsIGNhc2UgaXQgaGVyZSwgYW5kIGNvbnZlcnQgYW4gRUFOLTEzIHJlc3VsdCB0byBhIFVQQy1BXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlc3VsdCBpZiBhcHByb3ByaWF0ZS5cbiAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgLy8gQnV0LCBkb24ndCByZXR1cm4gVVBDLUEgaWYgVVBDLUEgd2FzIG5vdCBhIHJlcXVlc3RlZCBmb3JtYXQhXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVhbjEzTWF5QmVVUENBID0gcmVzdWx0LmdldEJhcmNvZGVGb3JtYXQoKSA9PT0gQmFyY29kZUZvcm1hdCQxLkVBTl8xMyAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmdldFRleHQoKS5jaGFyQXQoMCkgPT09ICcwJztcbiAgICAgICAgICAgICAgICAgICAgLy8gQFN1cHByZXNzV2FybmluZ3MoXCJ1bmNoZWNrZWRcIilcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9zc2libGVGb3JtYXRzID0gaGludHMgPT0gbnVsbCA/IG51bGwgOiBoaW50cy5nZXQoRGVjb2RlSGludFR5cGUkMS5QT1NTSUJMRV9GT1JNQVRTKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuUmV0dXJuVVBDQSA9IHBvc3NpYmxlRm9ybWF0cyA9PSBudWxsIHx8IHBvc3NpYmxlRm9ybWF0cy5pbmNsdWRlcyhCYXJjb2RlRm9ybWF0JDEuVVBDX0EpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZWFuMTNNYXlCZVVQQ0EgJiYgY2FuUmV0dXJuVVBDQSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmF3Qnl0ZXMgPSByZXN1bHQuZ2V0UmF3Qnl0ZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRyYW5zZmVyIHRoZSBtZXRhZGF0YSBhY3Jvc3NcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdFVQQ0EgPSBuZXcgUmVzdWx0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5nZXRUZXh0KCkuc3Vic3RyaW5nKDEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd0J5dGVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChyYXdCeXRlcyA/IHJhd0J5dGVzLmxlbmd0aCA6IG51bGwpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5nZXRSZXN1bHRQb2ludHMoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCYXJjb2RlRm9ybWF0JDEuVVBDX0EpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0VVBDQS5wdXRBbGxNZXRhZGF0YShyZXN1bHQuZ2V0UmVzdWx0TWV0YWRhdGEoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0VVBDQTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIHJlc2V0KCkge1xuICAgICAgICAgICAgZm9yIChsZXQgcmVhZGVyIG9mIHRoaXMucmVhZGVycykge1xuICAgICAgICAgICAgICAgIHJlYWRlci5yZXNldCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gaW1wb3J0IEludGVnZXIgZnJvbSAnLi4vLi4vdXRpbC9JbnRlZ2VyJztcbiAgICAvLyBpbXBvcnQgRmxvYXQgZnJvbSAnLi4vLi4vdXRpbC9GbG9hdCc7XG4gICAgY2xhc3MgQWJzdHJhY3RSU1NSZWFkZXIgZXh0ZW5kcyBPbmVEUmVhZGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgICAgICBzdXBlcigpO1xuICAgICAgICAgICAgdGhpcy5kZWNvZGVGaW5kZXJDb3VudGVycyA9IG5ldyBJbnQzMkFycmF5KDQpO1xuICAgICAgICAgICAgdGhpcy5kYXRhQ2hhcmFjdGVyQ291bnRlcnMgPSBuZXcgSW50MzJBcnJheSg4KTtcbiAgICAgICAgICAgIHRoaXMub2RkUm91bmRpbmdFcnJvcnMgPSBuZXcgQXJyYXkoNCk7XG4gICAgICAgICAgICB0aGlzLmV2ZW5Sb3VuZGluZ0Vycm9ycyA9IG5ldyBBcnJheSg0KTtcbiAgICAgICAgICAgIHRoaXMub2RkQ291bnRzID0gbmV3IEFycmF5KHRoaXMuZGF0YUNoYXJhY3RlckNvdW50ZXJzLmxlbmd0aCAvIDIpO1xuICAgICAgICAgICAgdGhpcy5ldmVuQ291bnRzID0gbmV3IEFycmF5KHRoaXMuZGF0YUNoYXJhY3RlckNvdW50ZXJzLmxlbmd0aCAvIDIpO1xuICAgICAgICB9XG4gICAgICAgIGdldERlY29kZUZpbmRlckNvdW50ZXJzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlRmluZGVyQ291bnRlcnM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RGF0YUNoYXJhY3RlckNvdW50ZXJzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0YUNoYXJhY3RlckNvdW50ZXJzO1xuICAgICAgICB9XG4gICAgICAgIGdldE9kZFJvdW5kaW5nRXJyb3JzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMub2RkUm91bmRpbmdFcnJvcnM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RXZlblJvdW5kaW5nRXJyb3JzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXZlblJvdW5kaW5nRXJyb3JzO1xuICAgICAgICB9XG4gICAgICAgIGdldE9kZENvdW50cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm9kZENvdW50cztcbiAgICAgICAgfVxuICAgICAgICBnZXRFdmVuQ291bnRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXZlbkNvdW50cztcbiAgICAgICAgfVxuICAgICAgICBwYXJzZUZpbmRlclZhbHVlKGNvdW50ZXJzLCBmaW5kZXJQYXR0ZXJucykge1xuICAgICAgICAgICAgZm9yIChsZXQgdmFsdWUgPSAwOyB2YWx1ZSA8IGZpbmRlclBhdHRlcm5zLmxlbmd0aDsgdmFsdWUrKykge1xuICAgICAgICAgICAgICAgIGlmIChPbmVEUmVhZGVyLnBhdHRlcm5NYXRjaFZhcmlhbmNlKGNvdW50ZXJzLCBmaW5kZXJQYXR0ZXJuc1t2YWx1ZV0sIEFic3RyYWN0UlNTUmVhZGVyLk1BWF9JTkRJVklEVUFMX1ZBUklBTkNFKSA8IEFic3RyYWN0UlNTUmVhZGVyLk1BWF9BVkdfVkFSSUFOQ0UpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gYXJyYXkgdmFsdWVzIHRvIHN1bVxuICAgICAgICAgKiBAcmV0dXJuIHN1bSBvZiB2YWx1ZXNcbiAgICAgICAgICogQGRlcHJlY2F0ZWQgY2FsbCB7QGxpbmsgTWF0aFV0aWxzI3N1bShpbnRbXSl9XG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgY291bnQoYXJyYXkpIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoVXRpbHMuc3VtKG5ldyBJbnQzMkFycmF5KGFycmF5KSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGluY3JlbWVudChhcnJheSwgZXJyb3JzKSB7XG4gICAgICAgICAgICBsZXQgaW5kZXggPSAwO1xuICAgICAgICAgICAgbGV0IGJpZ2dlc3RFcnJvciA9IGVycm9yc1swXTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3JzW2ldID4gYmlnZ2VzdEVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGJpZ2dlc3RFcnJvciA9IGVycm9yc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggPSBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFycmF5W2luZGV4XSsrO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBkZWNyZW1lbnQoYXJyYXksIGVycm9ycykge1xuICAgICAgICAgICAgbGV0IGluZGV4ID0gMDtcbiAgICAgICAgICAgIGxldCBiaWdnZXN0RXJyb3IgPSBlcnJvcnNbMF07XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yc1tpXSA8IGJpZ2dlc3RFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBiaWdnZXN0RXJyb3IgPSBlcnJvcnNbaV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhcnJheVtpbmRleF0tLTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgaXNGaW5kZXJQYXR0ZXJuKGNvdW50ZXJzKSB7XG4gICAgICAgICAgICBsZXQgZmlyc3RUd29TdW0gPSBjb3VudGVyc1swXSArIGNvdW50ZXJzWzFdO1xuICAgICAgICAgICAgbGV0IHN1bSA9IGZpcnN0VHdvU3VtICsgY291bnRlcnNbMl0gKyBjb3VudGVyc1szXTtcbiAgICAgICAgICAgIGxldCByYXRpbyA9IGZpcnN0VHdvU3VtIC8gc3VtO1xuICAgICAgICAgICAgaWYgKHJhdGlvID49IEFic3RyYWN0UlNTUmVhZGVyLk1JTl9GSU5ERVJfUEFUVEVSTl9SQVRJTyAmJiByYXRpbyA8PSBBYnN0cmFjdFJTU1JlYWRlci5NQVhfRklOREVSX1BBVFRFUk5fUkFUSU8pIHtcbiAgICAgICAgICAgICAgICAvLyBwYXNzZXMgcmF0aW8gdGVzdCBpbiBzcGVjLCBidXQgc2VlIGlmIHRoZSBjb3VudHMgYXJlIHVucmVhc29uYWJsZVxuICAgICAgICAgICAgICAgIGxldCBtaW5Db3VudGVyID0gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVI7XG4gICAgICAgICAgICAgICAgbGV0IG1heENvdW50ZXIgPSBOdW1iZXIuTUlOX1NBRkVfSU5URUdFUjtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBjb3VudGVyIG9mIGNvdW50ZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb3VudGVyID4gbWF4Q291bnRlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4Q291bnRlciA9IGNvdW50ZXI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvdW50ZXIgPCBtaW5Db3VudGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5Db3VudGVyID0gY291bnRlcjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gbWF4Q291bnRlciA8IDEwICogbWluQ291bnRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBBYnN0cmFjdFJTU1JlYWRlci5NQVhfQVZHX1ZBUklBTkNFID0gMC4yO1xuICAgIEFic3RyYWN0UlNTUmVhZGVyLk1BWF9JTkRJVklEVUFMX1ZBUklBTkNFID0gMC40NTtcbiAgICBBYnN0cmFjdFJTU1JlYWRlci5NSU5fRklOREVSX1BBVFRFUk5fUkFUSU8gPSA5LjUgLyAxMi4wO1xuICAgIEFic3RyYWN0UlNTUmVhZGVyLk1BWF9GSU5ERVJfUEFUVEVSTl9SQVRJTyA9IDEyLjUgLyAxNC4wO1xuXG4gICAgY2xhc3MgRGF0YUNoYXJhY3RlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHZhbHVlLCBjaGVja3N1bVBvcnRpb24pIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIHRoaXMuY2hlY2tzdW1Qb3J0aW9uID0gY2hlY2tzdW1Qb3J0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGdldFZhbHVlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Q2hlY2tzdW1Qb3J0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2hlY2tzdW1Qb3J0aW9uO1xuICAgICAgICB9XG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWUgKyAnKCcgKyB0aGlzLmNoZWNrc3VtUG9ydGlvbiArICcpJztcbiAgICAgICAgfVxuICAgICAgICBlcXVhbHMobykge1xuICAgICAgICAgICAgaWYgKCEobyBpbnN0YW5jZW9mIERhdGFDaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgdGhhdCA9IG87XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZSA9PT0gdGhhdC52YWx1ZSAmJiB0aGlzLmNoZWNrc3VtUG9ydGlvbiA9PT0gdGhhdC5jaGVja3N1bVBvcnRpb247XG4gICAgICAgIH1cbiAgICAgICAgaGFzaENvZGUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZSBeIHRoaXMuY2hlY2tzdW1Qb3J0aW9uO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xhc3MgRmluZGVyUGF0dGVybiB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHZhbHVlLCBzdGFydEVuZCwgc3RhcnQsIGVuZCwgcm93TnVtYmVyKSB7XG4gICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB0aGlzLnN0YXJ0RW5kID0gc3RhcnRFbmQ7XG4gICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB0aGlzLnN0YXJ0RW5kID0gc3RhcnRFbmQ7XG4gICAgICAgICAgICB0aGlzLnJlc3VsdFBvaW50cyA9IG5ldyBBcnJheSgpO1xuICAgICAgICAgICAgdGhpcy5yZXN1bHRQb2ludHMucHVzaChuZXcgUmVzdWx0UG9pbnQoc3RhcnQsIHJvd051bWJlcikpO1xuICAgICAgICAgICAgdGhpcy5yZXN1bHRQb2ludHMucHVzaChuZXcgUmVzdWx0UG9pbnQoZW5kLCByb3dOdW1iZXIpKTtcbiAgICAgICAgfVxuICAgICAgICBnZXRWYWx1ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGdldFN0YXJ0RW5kKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RhcnRFbmQ7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0UmVzdWx0UG9pbnRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVzdWx0UG9pbnRzO1xuICAgICAgICB9XG4gICAgICAgIGVxdWFscyhvKSB7XG4gICAgICAgICAgICBpZiAoIShvIGluc3RhbmNlb2YgRmluZGVyUGF0dGVybikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCB0aGF0ID0gbztcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlID09PSB0aGF0LnZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGhhc2hDb2RlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSU1MgdXRpbCBmdW5jdGlvbnMuXG4gICAgICovXG4gICAgY2xhc3MgUlNTVXRpbHMge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHsgfVxuICAgICAgICBzdGF0aWMgZ2V0UlNTdmFsdWUod2lkdGhzLCBtYXhXaWR0aCwgbm9OYXJyb3cpIHtcbiAgICAgICAgICAgIGxldCBuID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IHdpZHRoIG9mIHdpZHRocykge1xuICAgICAgICAgICAgICAgIG4gKz0gd2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgdmFsID0gMDtcbiAgICAgICAgICAgIGxldCBuYXJyb3dNYXNrID0gMDtcbiAgICAgICAgICAgIGxldCBlbGVtZW50cyA9IHdpZHRocy5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGxldCBiYXIgPSAwOyBiYXIgPCBlbGVtZW50cyAtIDE7IGJhcisrKSB7XG4gICAgICAgICAgICAgICAgbGV0IGVsbVdpZHRoO1xuICAgICAgICAgICAgICAgIGZvciAoZWxtV2lkdGggPSAxLCBuYXJyb3dNYXNrIHw9IDEgPDwgYmFyOyBlbG1XaWR0aCA8IHdpZHRoc1tiYXJdOyBlbG1XaWR0aCsrLCBuYXJyb3dNYXNrICY9IH4oMSA8PCBiYXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBzdWJWYWwgPSBSU1NVdGlscy5jb21iaW5zKG4gLSBlbG1XaWR0aCAtIDEsIGVsZW1lbnRzIC0gYmFyIC0gMik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChub05hcnJvdyAmJiAobmFycm93TWFzayA9PT0gMCkgJiYgKG4gLSBlbG1XaWR0aCAtIChlbGVtZW50cyAtIGJhciAtIDEpID49IGVsZW1lbnRzIC0gYmFyIC0gMSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1YlZhbCAtPSBSU1NVdGlscy5jb21iaW5zKG4gLSBlbG1XaWR0aCAtIChlbGVtZW50cyAtIGJhciksIGVsZW1lbnRzIC0gYmFyIC0gMik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnRzIC0gYmFyIC0gMSA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBsZXNzVmFsID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IG14d0VsZW1lbnQgPSBuIC0gZWxtV2lkdGggLSAoZWxlbWVudHMgLSBiYXIgLSAyKTsgbXh3RWxlbWVudCA+IG1heFdpZHRoOyBteHdFbGVtZW50LS0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXNzVmFsICs9IFJTU1V0aWxzLmNvbWJpbnMobiAtIGVsbVdpZHRoIC0gbXh3RWxlbWVudCAtIDEsIGVsZW1lbnRzIC0gYmFyIC0gMyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJWYWwgLT0gbGVzc1ZhbCAqIChlbGVtZW50cyAtIDEgLSBiYXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKG4gLSBlbG1XaWR0aCA+IG1heFdpZHRoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJWYWwtLTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YWwgKz0gc3ViVmFsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBuIC09IGVsbVdpZHRoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHZhbDtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgY29tYmlucyhuLCByKSB7XG4gICAgICAgICAgICBsZXQgbWF4RGVub207XG4gICAgICAgICAgICBsZXQgbWluRGVub207XG4gICAgICAgICAgICBpZiAobiAtIHIgPiByKSB7XG4gICAgICAgICAgICAgICAgbWluRGVub20gPSByO1xuICAgICAgICAgICAgICAgIG1heERlbm9tID0gbiAtIHI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBtaW5EZW5vbSA9IG4gLSByO1xuICAgICAgICAgICAgICAgIG1heERlbm9tID0gcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCB2YWwgPSAxO1xuICAgICAgICAgICAgbGV0IGogPSAxO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IG47IGkgPiBtYXhEZW5vbTsgaS0tKSB7XG4gICAgICAgICAgICAgICAgdmFsICo9IGk7XG4gICAgICAgICAgICAgICAgaWYgKGogPD0gbWluRGVub20pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsIC89IGo7XG4gICAgICAgICAgICAgICAgICAgIGorKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aGlsZSAoKGogPD0gbWluRGVub20pKSB7XG4gICAgICAgICAgICAgICAgdmFsIC89IGo7XG4gICAgICAgICAgICAgICAgaisrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHZhbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNsYXNzIEJpdEFycmF5QnVpbGRlciB7XG4gICAgICAgIHN0YXRpYyBidWlsZEJpdEFycmF5KHBhaXJzKSB7XG4gICAgICAgICAgICBsZXQgY2hhck51bWJlciA9IChwYWlycy5sZW5ndGggKiAyKSAtIDE7XG4gICAgICAgICAgICBpZiAocGFpcnNbcGFpcnMubGVuZ3RoIC0gMV0uZ2V0UmlnaHRDaGFyKCkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNoYXJOdW1iZXIgLT0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBzaXplID0gMTIgKiBjaGFyTnVtYmVyO1xuICAgICAgICAgICAgbGV0IGJpbmFyeSA9IG5ldyBCaXRBcnJheShzaXplKTtcbiAgICAgICAgICAgIGxldCBhY2NQb3MgPSAwO1xuICAgICAgICAgICAgbGV0IGZpcnN0UGFpciA9IHBhaXJzWzBdO1xuICAgICAgICAgICAgbGV0IGZpcnN0VmFsdWUgPSBmaXJzdFBhaXIuZ2V0UmlnaHRDaGFyKCkuZ2V0VmFsdWUoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAxMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgICAgICAgICBpZiAoKGZpcnN0VmFsdWUgJiAoMSA8PCBpKSkgIT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBiaW5hcnkuc2V0KGFjY1Bvcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGFjY1BvcysrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBwYWlycy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgIGxldCBjdXJyZW50UGFpciA9IHBhaXJzW2ldO1xuICAgICAgICAgICAgICAgIGxldCBsZWZ0VmFsdWUgPSBjdXJyZW50UGFpci5nZXRMZWZ0Q2hhcigpLmdldFZhbHVlKCk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDExOyBqID49IDA7IC0taikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoKGxlZnRWYWx1ZSAmICgxIDw8IGopKSAhPSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBiaW5hcnkuc2V0KGFjY1Bvcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYWNjUG9zKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50UGFpci5nZXRSaWdodENoYXIoKSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCByaWdodFZhbHVlID0gY3VycmVudFBhaXIuZ2V0UmlnaHRDaGFyKCkuZ2V0VmFsdWUoKTtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDExOyBqID49IDA7IC0taikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChyaWdodFZhbHVlICYgKDEgPDwgaikpICE9IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaW5hcnkuc2V0KGFjY1Bvcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBhY2NQb3MrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBiaW5hcnk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjbGFzcyBCbG9ja1BhcnNlZFJlc3VsdCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGZpbmlzaGVkLCBkZWNvZGVkSW5mb3JtYXRpb24pIHtcbiAgICAgICAgICAgIGlmIChkZWNvZGVkSW5mb3JtYXRpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRlY29kZWRJbmZvcm1hdGlvbiA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpbmlzaGVkID0gZmluaXNoZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5kZWNvZGVkSW5mb3JtYXRpb24gPSBkZWNvZGVkSW5mb3JtYXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RGVjb2RlZEluZm9ybWF0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlZEluZm9ybWF0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGlzRmluaXNoZWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5maW5pc2hlZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNsYXNzIERlY29kZWRPYmplY3Qge1xuICAgICAgICBjb25zdHJ1Y3RvcihuZXdQb3NpdGlvbikge1xuICAgICAgICAgICAgdGhpcy5uZXdQb3NpdGlvbiA9IG5ld1Bvc2l0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGdldE5ld1Bvc2l0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubmV3UG9zaXRpb247XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjbGFzcyBEZWNvZGVkQ2hhciBleHRlbmRzIERlY29kZWRPYmplY3Qge1xuICAgICAgICBjb25zdHJ1Y3RvcihuZXdQb3NpdGlvbiwgdmFsdWUpIHtcbiAgICAgICAgICAgIHN1cGVyKG5ld1Bvc2l0aW9uKTtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRWYWx1ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGlzRk5DMSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlID09PSBEZWNvZGVkQ2hhci5GTkMxO1xuICAgICAgICB9XG4gICAgfVxuICAgIERlY29kZWRDaGFyLkZOQzEgPSAnJCc7XG5cbiAgICBjbGFzcyBEZWNvZGVkSW5mb3JtYXRpb24gZXh0ZW5kcyBEZWNvZGVkT2JqZWN0IHtcbiAgICAgICAgY29uc3RydWN0b3IobmV3UG9zaXRpb24sIG5ld1N0cmluZywgcmVtYWluaW5nVmFsdWUpIHtcbiAgICAgICAgICAgIHN1cGVyKG5ld1Bvc2l0aW9uKTtcbiAgICAgICAgICAgIGlmIChyZW1haW5pbmdWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVtYWluaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbWFpbmluZ1ZhbHVlID0gdGhpcy5yZW1haW5pbmdWYWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMucmVtYWluaW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1haW5pbmdWYWx1ZSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLm5ld1N0cmluZyA9IG5ld1N0cmluZztcbiAgICAgICAgfVxuICAgICAgICBnZXROZXdTdHJpbmcoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5uZXdTdHJpbmc7XG4gICAgICAgIH1cbiAgICAgICAgaXNSZW1haW5pbmcoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZW1haW5pbmc7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0UmVtYWluaW5nVmFsdWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZW1haW5pbmdWYWx1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNsYXNzIERlY29kZWROdW1lcmljIGV4dGVuZHMgRGVjb2RlZE9iamVjdCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKG5ld1Bvc2l0aW9uLCBmaXJzdERpZ2l0LCBzZWNvbmREaWdpdCkge1xuICAgICAgICAgICAgc3VwZXIobmV3UG9zaXRpb24pO1xuICAgICAgICAgICAgaWYgKGZpcnN0RGlnaXQgPCAwIHx8IGZpcnN0RGlnaXQgPiAxMCB8fCBzZWNvbmREaWdpdCA8IDAgfHwgc2Vjb25kRGlnaXQgPiAxMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZmlyc3REaWdpdCA9IGZpcnN0RGlnaXQ7XG4gICAgICAgICAgICB0aGlzLnNlY29uZERpZ2l0ID0gc2Vjb25kRGlnaXQ7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Rmlyc3REaWdpdCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZpcnN0RGlnaXQ7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0U2Vjb25kRGlnaXQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zZWNvbmREaWdpdDtcbiAgICAgICAgfVxuICAgICAgICBnZXRWYWx1ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZpcnN0RGlnaXQgKiAxMCArIHRoaXMuc2Vjb25kRGlnaXQ7XG4gICAgICAgIH1cbiAgICAgICAgaXNGaXJzdERpZ2l0Rk5DMSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZpcnN0RGlnaXQgPT09IERlY29kZWROdW1lcmljLkZOQzE7XG4gICAgICAgIH1cbiAgICAgICAgaXNTZWNvbmREaWdpdEZOQzEoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zZWNvbmREaWdpdCA9PT0gRGVjb2RlZE51bWVyaWMuRk5DMTtcbiAgICAgICAgfVxuICAgICAgICBpc0FueUZOQzEoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5maXJzdERpZ2l0ID09PSBEZWNvZGVkTnVtZXJpYy5GTkMxIHx8IHRoaXMuc2Vjb25kRGlnaXQgPT09IERlY29kZWROdW1lcmljLkZOQzE7XG4gICAgICAgIH1cbiAgICB9XG4gICAgRGVjb2RlZE51bWVyaWMuRk5DMSA9IDEwO1xuXG4gICAgY2xhc3MgRmllbGRQYXJzZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgcGFyc2VGaWVsZHNJbkdlbmVyYWxQdXJwb3NlKHJhd0luZm9ybWF0aW9uKSB7XG4gICAgICAgICAgICBpZiAoIXJhd0luZm9ybWF0aW9uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBQcm9jZXNzaW5nIDItZGlnaXQgQUlzXG4gICAgICAgICAgICBpZiAocmF3SW5mb3JtYXRpb24ubGVuZ3RoIDwgMikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGZpcnN0VHdvRGlnaXRzID0gcmF3SW5mb3JtYXRpb24uc3Vic3RyaW5nKDAsIDIpO1xuICAgICAgICAgICAgZm9yIChsZXQgZGF0YUxlbmd0aCBvZiBGaWVsZFBhcnNlci5UV09fRElHSVRfREFUQV9MRU5HVEgpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YUxlbmd0aFswXSA9PT0gZmlyc3RUd29EaWdpdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFMZW5ndGhbMV0gPT09IEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEZpZWxkUGFyc2VyLnByb2Nlc3NWYXJpYWJsZUFJKDIsIGRhdGFMZW5ndGhbMl0sIHJhd0luZm9ybWF0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gRmllbGRQYXJzZXIucHJvY2Vzc0ZpeGVkQUkoMiwgZGF0YUxlbmd0aFsxXSwgcmF3SW5mb3JtYXRpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyYXdJbmZvcm1hdGlvbi5sZW5ndGggPCAzKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZmlyc3RUaHJlZURpZ2l0cyA9IHJhd0luZm9ybWF0aW9uLnN1YnN0cmluZygwLCAzKTtcbiAgICAgICAgICAgIGZvciAobGV0IGRhdGFMZW5ndGggb2YgRmllbGRQYXJzZXIuVEhSRUVfRElHSVRfREFUQV9MRU5HVEgpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YUxlbmd0aFswXSA9PT0gZmlyc3RUaHJlZURpZ2l0cykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YUxlbmd0aFsxXSA9PT0gRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RIKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gRmllbGRQYXJzZXIucHJvY2Vzc1ZhcmlhYmxlQUkoMywgZGF0YUxlbmd0aFsyXSwgcmF3SW5mb3JtYXRpb24pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBGaWVsZFBhcnNlci5wcm9jZXNzRml4ZWRBSSgzLCBkYXRhTGVuZ3RoWzFdLCByYXdJbmZvcm1hdGlvbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgZGF0YUxlbmd0aCBvZiBGaWVsZFBhcnNlci5USFJFRV9ESUdJVF9QTFVTX0RJR0lUX0RBVEFfTEVOR1RIKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGFMZW5ndGhbMF0gPT09IGZpcnN0VGhyZWVEaWdpdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFMZW5ndGhbMV0gPT09IEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEZpZWxkUGFyc2VyLnByb2Nlc3NWYXJpYWJsZUFJKDQsIGRhdGFMZW5ndGhbMl0sIHJhd0luZm9ybWF0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gRmllbGRQYXJzZXIucHJvY2Vzc0ZpeGVkQUkoNCwgZGF0YUxlbmd0aFsxXSwgcmF3SW5mb3JtYXRpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyYXdJbmZvcm1hdGlvbi5sZW5ndGggPCA0KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZmlyc3RGb3VyRGlnaXRzID0gcmF3SW5mb3JtYXRpb24uc3Vic3RyaW5nKDAsIDQpO1xuICAgICAgICAgICAgZm9yIChsZXQgZGF0YUxlbmd0aCBvZiBGaWVsZFBhcnNlci5GT1VSX0RJR0lUX0RBVEFfTEVOR1RIKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGFMZW5ndGhbMF0gPT09IGZpcnN0Rm91ckRpZ2l0cykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YUxlbmd0aFsxXSA9PT0gRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RIKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gRmllbGRQYXJzZXIucHJvY2Vzc1ZhcmlhYmxlQUkoNCwgZGF0YUxlbmd0aFsyXSwgcmF3SW5mb3JtYXRpb24pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBGaWVsZFBhcnNlci5wcm9jZXNzRml4ZWRBSSg0LCBkYXRhTGVuZ3RoWzFdLCByYXdJbmZvcm1hdGlvbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHByb2Nlc3NGaXhlZEFJKGFpU2l6ZSwgZmllbGRTaXplLCByYXdJbmZvcm1hdGlvbikge1xuICAgICAgICAgICAgaWYgKHJhd0luZm9ybWF0aW9uLmxlbmd0aCA8IGFpU2l6ZSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGFpID0gcmF3SW5mb3JtYXRpb24uc3Vic3RyaW5nKDAsIGFpU2l6ZSk7XG4gICAgICAgICAgICBpZiAocmF3SW5mb3JtYXRpb24ubGVuZ3RoIDwgYWlTaXplICsgZmllbGRTaXplKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZmllbGQgPSByYXdJbmZvcm1hdGlvbi5zdWJzdHJpbmcoYWlTaXplLCBhaVNpemUgKyBmaWVsZFNpemUpO1xuICAgICAgICAgICAgbGV0IHJlbWFpbmluZyA9IHJhd0luZm9ybWF0aW9uLnN1YnN0cmluZyhhaVNpemUgKyBmaWVsZFNpemUpO1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9ICcoJyArIGFpICsgJyknICsgZmllbGQ7XG4gICAgICAgICAgICBsZXQgcGFyc2VkQUkgPSBGaWVsZFBhcnNlci5wYXJzZUZpZWxkc0luR2VuZXJhbFB1cnBvc2UocmVtYWluaW5nKTtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZWRBSSA9PSBudWxsID8gcmVzdWx0IDogcmVzdWx0ICsgcGFyc2VkQUk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHByb2Nlc3NWYXJpYWJsZUFJKGFpU2l6ZSwgdmFyaWFibGVGaWVsZFNpemUsIHJhd0luZm9ybWF0aW9uKSB7XG4gICAgICAgICAgICBsZXQgYWkgPSByYXdJbmZvcm1hdGlvbi5zdWJzdHJpbmcoMCwgYWlTaXplKTtcbiAgICAgICAgICAgIGxldCBtYXhTaXplO1xuICAgICAgICAgICAgaWYgKHJhd0luZm9ybWF0aW9uLmxlbmd0aCA8IGFpU2l6ZSArIHZhcmlhYmxlRmllbGRTaXplKSB7XG4gICAgICAgICAgICAgICAgbWF4U2l6ZSA9IHJhd0luZm9ybWF0aW9uLmxlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG1heFNpemUgPSBhaVNpemUgKyB2YXJpYWJsZUZpZWxkU2l6ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBmaWVsZCA9IHJhd0luZm9ybWF0aW9uLnN1YnN0cmluZyhhaVNpemUsIG1heFNpemUpO1xuICAgICAgICAgICAgbGV0IHJlbWFpbmluZyA9IHJhd0luZm9ybWF0aW9uLnN1YnN0cmluZyhtYXhTaXplKTtcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSAnKCcgKyBhaSArICcpJyArIGZpZWxkO1xuICAgICAgICAgICAgbGV0IHBhcnNlZEFJID0gRmllbGRQYXJzZXIucGFyc2VGaWVsZHNJbkdlbmVyYWxQdXJwb3NlKHJlbWFpbmluZyk7XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VkQUkgPT0gbnVsbCA/IHJlc3VsdCA6IHJlc3VsdCArIHBhcnNlZEFJO1xuICAgICAgICB9XG4gICAgfVxuICAgIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCA9IFtdO1xuICAgIEZpZWxkUGFyc2VyLlRXT19ESUdJVF9EQVRBX0xFTkdUSCA9IFtcbiAgICAgICAgWycwMCcsIDE4XSxcbiAgICAgICAgWycwMScsIDE0XSxcbiAgICAgICAgWycwMicsIDE0XSxcbiAgICAgICAgWycxMCcsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMjBdLFxuICAgICAgICBbJzExJywgNl0sXG4gICAgICAgIFsnMTInLCA2XSxcbiAgICAgICAgWycxMycsIDZdLFxuICAgICAgICBbJzE1JywgNl0sXG4gICAgICAgIFsnMTcnLCA2XSxcbiAgICAgICAgWycyMCcsIDJdLFxuICAgICAgICBbJzIxJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAyMF0sXG4gICAgICAgIFsnMjInLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDI5XSxcbiAgICAgICAgWyczMCcsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgOF0sXG4gICAgICAgIFsnMzcnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDhdLFxuICAgICAgICAvLyBpbnRlcm5hbCBjb21wYW55IGNvZGVzXG4gICAgICAgIFsnOTAnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDMwXSxcbiAgICAgICAgWyc5MScsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMzBdLFxuICAgICAgICBbJzkyJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAzMF0sXG4gICAgICAgIFsnOTMnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDMwXSxcbiAgICAgICAgWyc5NCcsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMzBdLFxuICAgICAgICBbJzk1JywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAzMF0sXG4gICAgICAgIFsnOTYnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDMwXSxcbiAgICAgICAgWyc5NycsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgM10sXG4gICAgICAgIFsnOTgnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDMwXSxcbiAgICAgICAgWyc5OScsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMzBdLFxuICAgIF07XG4gICAgRmllbGRQYXJzZXIuVEhSRUVfRElHSVRfREFUQV9MRU5HVEggPSBbXG4gICAgICAgIC8vIFNhbWUgZm9ybWF0IGFzIGFib3ZlXG4gICAgICAgIFsnMjQwJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAzMF0sXG4gICAgICAgIFsnMjQxJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAzMF0sXG4gICAgICAgIFsnMjQyJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCA2XSxcbiAgICAgICAgWycyNTAnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDMwXSxcbiAgICAgICAgWycyNTEnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDMwXSxcbiAgICAgICAgWycyNTMnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDE3XSxcbiAgICAgICAgWycyNTQnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDIwXSxcbiAgICAgICAgWyc0MDAnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDMwXSxcbiAgICAgICAgWyc0MDEnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDMwXSxcbiAgICAgICAgWyc0MDInLCAxN10sXG4gICAgICAgIFsnNDAzJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAzMF0sXG4gICAgICAgIFsnNDEwJywgMTNdLFxuICAgICAgICBbJzQxMScsIDEzXSxcbiAgICAgICAgWyc0MTInLCAxM10sXG4gICAgICAgIFsnNDEzJywgMTNdLFxuICAgICAgICBbJzQxNCcsIDEzXSxcbiAgICAgICAgWyc0MjAnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDIwXSxcbiAgICAgICAgWyc0MjEnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDE1XSxcbiAgICAgICAgWyc0MjInLCAzXSxcbiAgICAgICAgWyc0MjMnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDE1XSxcbiAgICAgICAgWyc0MjQnLCAzXSxcbiAgICAgICAgWyc0MjUnLCAzXSxcbiAgICAgICAgWyc0MjYnLCAzXSxcbiAgICBdO1xuICAgIEZpZWxkUGFyc2VyLlRIUkVFX0RJR0lUX1BMVVNfRElHSVRfREFUQV9MRU5HVEggPSBbXG4gICAgICAgIC8vIFNhbWUgZm9ybWF0IGFzIGFib3ZlXG4gICAgICAgIFsnMzEwJywgNl0sXG4gICAgICAgIFsnMzExJywgNl0sXG4gICAgICAgIFsnMzEyJywgNl0sXG4gICAgICAgIFsnMzEzJywgNl0sXG4gICAgICAgIFsnMzE0JywgNl0sXG4gICAgICAgIFsnMzE1JywgNl0sXG4gICAgICAgIFsnMzE2JywgNl0sXG4gICAgICAgIFsnMzIwJywgNl0sXG4gICAgICAgIFsnMzIxJywgNl0sXG4gICAgICAgIFsnMzIyJywgNl0sXG4gICAgICAgIFsnMzIzJywgNl0sXG4gICAgICAgIFsnMzI0JywgNl0sXG4gICAgICAgIFsnMzI1JywgNl0sXG4gICAgICAgIFsnMzI2JywgNl0sXG4gICAgICAgIFsnMzI3JywgNl0sXG4gICAgICAgIFsnMzI4JywgNl0sXG4gICAgICAgIFsnMzI5JywgNl0sXG4gICAgICAgIFsnMzMwJywgNl0sXG4gICAgICAgIFsnMzMxJywgNl0sXG4gICAgICAgIFsnMzMyJywgNl0sXG4gICAgICAgIFsnMzMzJywgNl0sXG4gICAgICAgIFsnMzM0JywgNl0sXG4gICAgICAgIFsnMzM1JywgNl0sXG4gICAgICAgIFsnMzM2JywgNl0sXG4gICAgICAgIFsnMzQwJywgNl0sXG4gICAgICAgIFsnMzQxJywgNl0sXG4gICAgICAgIFsnMzQyJywgNl0sXG4gICAgICAgIFsnMzQzJywgNl0sXG4gICAgICAgIFsnMzQ0JywgNl0sXG4gICAgICAgIFsnMzQ1JywgNl0sXG4gICAgICAgIFsnMzQ2JywgNl0sXG4gICAgICAgIFsnMzQ3JywgNl0sXG4gICAgICAgIFsnMzQ4JywgNl0sXG4gICAgICAgIFsnMzQ5JywgNl0sXG4gICAgICAgIFsnMzUwJywgNl0sXG4gICAgICAgIFsnMzUxJywgNl0sXG4gICAgICAgIFsnMzUyJywgNl0sXG4gICAgICAgIFsnMzUzJywgNl0sXG4gICAgICAgIFsnMzU0JywgNl0sXG4gICAgICAgIFsnMzU1JywgNl0sXG4gICAgICAgIFsnMzU2JywgNl0sXG4gICAgICAgIFsnMzU3JywgNl0sXG4gICAgICAgIFsnMzYwJywgNl0sXG4gICAgICAgIFsnMzYxJywgNl0sXG4gICAgICAgIFsnMzYyJywgNl0sXG4gICAgICAgIFsnMzYzJywgNl0sXG4gICAgICAgIFsnMzY0JywgNl0sXG4gICAgICAgIFsnMzY1JywgNl0sXG4gICAgICAgIFsnMzY2JywgNl0sXG4gICAgICAgIFsnMzY3JywgNl0sXG4gICAgICAgIFsnMzY4JywgNl0sXG4gICAgICAgIFsnMzY5JywgNl0sXG4gICAgICAgIFsnMzkwJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAxNV0sXG4gICAgICAgIFsnMzkxJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAxOF0sXG4gICAgICAgIFsnMzkyJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAxNV0sXG4gICAgICAgIFsnMzkzJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAxOF0sXG4gICAgICAgIFsnNzAzJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAzMF0sXG4gICAgXTtcbiAgICBGaWVsZFBhcnNlci5GT1VSX0RJR0lUX0RBVEFfTEVOR1RIID0gW1xuICAgICAgICAvLyBTYW1lIGZvcm1hdCBhcyBhYm92ZVxuICAgICAgICBbJzcwMDEnLCAxM10sXG4gICAgICAgIFsnNzAwMicsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMzBdLFxuICAgICAgICBbJzcwMDMnLCAxMF0sXG4gICAgICAgIFsnODAwMScsIDE0XSxcbiAgICAgICAgWyc4MDAyJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAyMF0sXG4gICAgICAgIFsnODAwMycsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMzBdLFxuICAgICAgICBbJzgwMDQnLCBGaWVsZFBhcnNlci5WQVJJQUJMRV9MRU5HVEgsIDMwXSxcbiAgICAgICAgWyc4MDA1JywgNl0sXG4gICAgICAgIFsnODAwNicsIDE4XSxcbiAgICAgICAgWyc4MDA3JywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCAzMF0sXG4gICAgICAgIFsnODAwOCcsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMTJdLFxuICAgICAgICBbJzgwMTgnLCAxOF0sXG4gICAgICAgIFsnODAyMCcsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgMjVdLFxuICAgICAgICBbJzgxMDAnLCA2XSxcbiAgICAgICAgWyc4MTAxJywgMTBdLFxuICAgICAgICBbJzgxMDInLCAyXSxcbiAgICAgICAgWyc4MTEwJywgRmllbGRQYXJzZXIuVkFSSUFCTEVfTEVOR1RILCA3MF0sXG4gICAgICAgIFsnODIwMCcsIEZpZWxkUGFyc2VyLlZBUklBQkxFX0xFTkdUSCwgNzBdLFxuICAgIF07XG5cbiAgICBjbGFzcyBHZW5lcmFsQXBwSWREZWNvZGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IoaW5mb3JtYXRpb24pIHtcbiAgICAgICAgICAgIHRoaXMuYnVmZmVyID0gbmV3IFN0cmluZ0J1aWxkZXIoKTtcbiAgICAgICAgICAgIHRoaXMuaW5mb3JtYXRpb24gPSBpbmZvcm1hdGlvbjtcbiAgICAgICAgfVxuICAgICAgICBkZWNvZGVBbGxDb2RlcyhidWZmLCBpbml0aWFsUG9zaXRpb24pIHtcbiAgICAgICAgICAgIGxldCBjdXJyZW50UG9zaXRpb24gPSBpbml0aWFsUG9zaXRpb247XG4gICAgICAgICAgICBsZXQgcmVtYWluaW5nID0gbnVsbDtcbiAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICBsZXQgaW5mbyA9IHRoaXMuZGVjb2RlR2VuZXJhbFB1cnBvc2VGaWVsZChjdXJyZW50UG9zaXRpb24sIHJlbWFpbmluZyk7XG4gICAgICAgICAgICAgICAgbGV0IHBhcnNlZEZpZWxkcyA9IEZpZWxkUGFyc2VyLnBhcnNlRmllbGRzSW5HZW5lcmFsUHVycG9zZShpbmZvLmdldE5ld1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICBpZiAocGFyc2VkRmllbGRzICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYnVmZi5hcHBlbmQocGFyc2VkRmllbGRzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGluZm8uaXNSZW1haW5pbmcoKSkge1xuICAgICAgICAgICAgICAgICAgICByZW1haW5pbmcgPSAnJyArIGluZm8uZ2V0UmVtYWluaW5nVmFsdWUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbWFpbmluZyA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50UG9zaXRpb24gPT09IGluZm8uZ2V0TmV3UG9zaXRpb24oKSkgeyAvLyBObyBzdGVwIGZvcndhcmQhXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjdXJyZW50UG9zaXRpb24gPSBpbmZvLmdldE5ld1Bvc2l0aW9uKCk7XG4gICAgICAgICAgICB9IHdoaWxlICh0cnVlKTtcbiAgICAgICAgICAgIHJldHVybiBidWZmLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICAgICAgaXNTdGlsbE51bWVyaWMocG9zKSB7XG4gICAgICAgICAgICAvLyBJdCdzIG51bWVyaWMgaWYgaXQgc3RpbGwgaGFzIDcgcG9zaXRpb25zXG4gICAgICAgICAgICAvLyBhbmQgb25lIG9mIHRoZSBmaXJzdCA0IGJpdHMgaXMgXCIxXCIuXG4gICAgICAgICAgICBpZiAocG9zICsgNyA+IHRoaXMuaW5mb3JtYXRpb24uZ2V0U2l6ZSgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBvcyArIDQgPD0gdGhpcy5pbmZvcm1hdGlvbi5nZXRTaXplKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gcG9zOyBpIDwgcG9zICsgMzsgKytpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5mb3JtYXRpb24uZ2V0KGkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmluZm9ybWF0aW9uLmdldChwb3MgKyAzKTtcbiAgICAgICAgfVxuICAgICAgICBkZWNvZGVOdW1lcmljKHBvcykge1xuICAgICAgICAgICAgaWYgKHBvcyArIDcgPiB0aGlzLmluZm9ybWF0aW9uLmdldFNpemUoKSkge1xuICAgICAgICAgICAgICAgIGxldCBudW1lcmljID0gdGhpcy5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KHBvcywgNCk7XG4gICAgICAgICAgICAgICAgaWYgKG51bWVyaWMgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBEZWNvZGVkTnVtZXJpYyh0aGlzLmluZm9ybWF0aW9uLmdldFNpemUoKSwgRGVjb2RlZE51bWVyaWMuRk5DMSwgRGVjb2RlZE51bWVyaWMuRk5DMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRGVjb2RlZE51bWVyaWModGhpcy5pbmZvcm1hdGlvbi5nZXRTaXplKCksIG51bWVyaWMgLSAxLCBEZWNvZGVkTnVtZXJpYy5GTkMxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBudW1lcmljID0gdGhpcy5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KHBvcywgNyk7XG4gICAgICAgICAgICBsZXQgZGlnaXQxID0gKG51bWVyaWMgLSA4KSAvIDExO1xuICAgICAgICAgICAgbGV0IGRpZ2l0MiA9IChudW1lcmljIC0gOCkgJSAxMTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRGVjb2RlZE51bWVyaWMocG9zICsgNywgZGlnaXQxLCBkaWdpdDIpO1xuICAgICAgICB9XG4gICAgICAgIGV4dHJhY3ROdW1lcmljVmFsdWVGcm9tQml0QXJyYXkocG9zLCBiaXRzKSB7XG4gICAgICAgICAgICByZXR1cm4gR2VuZXJhbEFwcElkRGVjb2Rlci5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KHRoaXMuaW5mb3JtYXRpb24sIHBvcywgYml0cyk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGV4dHJhY3ROdW1lcmljVmFsdWVGcm9tQml0QXJyYXkoaW5mb3JtYXRpb24sIHBvcywgYml0cykge1xuICAgICAgICAgICAgbGV0IHZhbHVlID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYml0czsgKytpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGluZm9ybWF0aW9uLmdldChwb3MgKyBpKSkge1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSB8PSAxIDw8IChiaXRzIC0gaSAtIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBkZWNvZGVHZW5lcmFsUHVycG9zZUZpZWxkKHBvcywgcmVtYWluaW5nKSB7XG4gICAgICAgICAgICAvLyB0aGlzLmJ1ZmZlci5zZXRMZW5ndGgoMCk7XG4gICAgICAgICAgICB0aGlzLmJ1ZmZlci5zZXRMZW5ndGhUb1plcm8oKTtcbiAgICAgICAgICAgIGlmIChyZW1haW5pbmcgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuYnVmZmVyLmFwcGVuZChyZW1haW5pbmcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jdXJyZW50LnNldFBvc2l0aW9uKHBvcyk7XG4gICAgICAgICAgICBsZXQgbGFzdERlY29kZWQgPSB0aGlzLnBhcnNlQmxvY2tzKCk7XG4gICAgICAgICAgICBpZiAobGFzdERlY29kZWQgIT0gbnVsbCAmJiBsYXN0RGVjb2RlZC5pc1JlbWFpbmluZygpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBEZWNvZGVkSW5mb3JtYXRpb24odGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCksIHRoaXMuYnVmZmVyLnRvU3RyaW5nKCksIGxhc3REZWNvZGVkLmdldFJlbWFpbmluZ1ZhbHVlKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBEZWNvZGVkSW5mb3JtYXRpb24odGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCksIHRoaXMuYnVmZmVyLnRvU3RyaW5nKCkpO1xuICAgICAgICB9XG4gICAgICAgIHBhcnNlQmxvY2tzKCkge1xuICAgICAgICAgICAgbGV0IGlzRmluaXNoZWQ7XG4gICAgICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgIGxldCBpbml0aWFsUG9zaXRpb24gPSB0aGlzLmN1cnJlbnQuZ2V0UG9zaXRpb24oKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jdXJyZW50LmlzQWxwaGEoKSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLnBhcnNlQWxwaGFCbG9jaygpO1xuICAgICAgICAgICAgICAgICAgICBpc0ZpbmlzaGVkID0gcmVzdWx0LmlzRmluaXNoZWQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5jdXJyZW50LmlzSXNvSWVjNjQ2KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy5wYXJzZUlzb0llYzY0NkJsb2NrKCk7XG4gICAgICAgICAgICAgICAgICAgIGlzRmluaXNoZWQgPSByZXN1bHQuaXNGaW5pc2hlZCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHsgLy8gaXQgbXVzdCBiZSBudW1lcmljXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMucGFyc2VOdW1lcmljQmxvY2soKTtcbiAgICAgICAgICAgICAgICAgICAgaXNGaW5pc2hlZCA9IHJlc3VsdC5pc0ZpbmlzaGVkKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCBwb3NpdGlvbkNoYW5nZWQgPSBpbml0aWFsUG9zaXRpb24gIT09IHRoaXMuY3VycmVudC5nZXRQb3NpdGlvbigpO1xuICAgICAgICAgICAgICAgIGlmICghcG9zaXRpb25DaGFuZ2VkICYmICFpc0ZpbmlzaGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gd2hpbGUgKCFpc0ZpbmlzaGVkKTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQuZ2V0RGVjb2RlZEluZm9ybWF0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgcGFyc2VOdW1lcmljQmxvY2soKSB7XG4gICAgICAgICAgICB3aGlsZSAodGhpcy5pc1N0aWxsTnVtZXJpYyh0aGlzLmN1cnJlbnQuZ2V0UG9zaXRpb24oKSkpIHtcbiAgICAgICAgICAgICAgICBsZXQgbnVtZXJpYyA9IHRoaXMuZGVjb2RlTnVtZXJpYyh0aGlzLmN1cnJlbnQuZ2V0UG9zaXRpb24oKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnNldFBvc2l0aW9uKG51bWVyaWMuZ2V0TmV3UG9zaXRpb24oKSk7XG4gICAgICAgICAgICAgICAgaWYgKG51bWVyaWMuaXNGaXJzdERpZ2l0Rk5DMSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBpbmZvcm1hdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG51bWVyaWMuaXNTZWNvbmREaWdpdEZOQzEoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5mb3JtYXRpb24gPSBuZXcgRGVjb2RlZEluZm9ybWF0aW9uKHRoaXMuY3VycmVudC5nZXRQb3NpdGlvbigpLCB0aGlzLmJ1ZmZlci50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZm9ybWF0aW9uID0gbmV3IERlY29kZWRJbmZvcm1hdGlvbih0aGlzLmN1cnJlbnQuZ2V0UG9zaXRpb24oKSwgdGhpcy5idWZmZXIudG9TdHJpbmcoKSwgbnVtZXJpYy5nZXRTZWNvbmREaWdpdCgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEJsb2NrUGFyc2VkUmVzdWx0KHRydWUsIGluZm9ybWF0aW9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5idWZmZXIuYXBwZW5kKG51bWVyaWMuZ2V0Rmlyc3REaWdpdCgpKTtcbiAgICAgICAgICAgICAgICBpZiAobnVtZXJpYy5pc1NlY29uZERpZ2l0Rk5DMSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBpbmZvcm1hdGlvbiA9IG5ldyBEZWNvZGVkSW5mb3JtYXRpb24odGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCksIHRoaXMuYnVmZmVyLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEJsb2NrUGFyc2VkUmVzdWx0KHRydWUsIGluZm9ybWF0aW9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5idWZmZXIuYXBwZW5kKG51bWVyaWMuZ2V0U2Vjb25kRGlnaXQoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5pc051bWVyaWNUb0FscGhhTnVtZXJpY0xhdGNoKHRoaXMuY3VycmVudC5nZXRQb3NpdGlvbigpKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5zZXRBbHBoYSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5pbmNyZW1lbnRQb3NpdGlvbig0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgQmxvY2tQYXJzZWRSZXN1bHQoZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIHBhcnNlSXNvSWVjNjQ2QmxvY2soKSB7XG4gICAgICAgICAgICB3aGlsZSAodGhpcy5pc1N0aWxsSXNvSWVjNjQ2KHRoaXMuY3VycmVudC5nZXRQb3NpdGlvbigpKSkge1xuICAgICAgICAgICAgICAgIGxldCBpc28gPSB0aGlzLmRlY29kZUlzb0llYzY0Nih0aGlzLmN1cnJlbnQuZ2V0UG9zaXRpb24oKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnNldFBvc2l0aW9uKGlzby5nZXROZXdQb3NpdGlvbigpKTtcbiAgICAgICAgICAgICAgICBpZiAoaXNvLmlzRk5DMSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBpbmZvcm1hdGlvbiA9IG5ldyBEZWNvZGVkSW5mb3JtYXRpb24odGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCksIHRoaXMuYnVmZmVyLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEJsb2NrUGFyc2VkUmVzdWx0KHRydWUsIGluZm9ybWF0aW9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5idWZmZXIuYXBwZW5kKGlzby5nZXRWYWx1ZSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmlzQWxwaGFPcjY0NlRvTnVtZXJpY0xhdGNoKHRoaXMuY3VycmVudC5nZXRQb3NpdGlvbigpKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5pbmNyZW1lbnRQb3NpdGlvbigzKTtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQuc2V0TnVtZXJpYygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5pc0FscGhhVG82NDZUb0FscGhhTGF0Y2godGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCkpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY3VycmVudC5nZXRQb3NpdGlvbigpICsgNSA8IHRoaXMuaW5mb3JtYXRpb24uZ2V0U2l6ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5pbmNyZW1lbnRQb3NpdGlvbig1KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5zZXRQb3NpdGlvbih0aGlzLmluZm9ybWF0aW9uLmdldFNpemUoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5zZXRBbHBoYSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBCbG9ja1BhcnNlZFJlc3VsdChmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgcGFyc2VBbHBoYUJsb2NrKCkge1xuICAgICAgICAgICAgd2hpbGUgKHRoaXMuaXNTdGlsbEFscGhhKHRoaXMuY3VycmVudC5nZXRQb3NpdGlvbigpKSkge1xuICAgICAgICAgICAgICAgIGxldCBhbHBoYSA9IHRoaXMuZGVjb2RlQWxwaGFudW1lcmljKHRoaXMuY3VycmVudC5nZXRQb3NpdGlvbigpKTtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQuc2V0UG9zaXRpb24oYWxwaGEuZ2V0TmV3UG9zaXRpb24oKSk7XG4gICAgICAgICAgICAgICAgaWYgKGFscGhhLmlzRk5DMSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBpbmZvcm1hdGlvbiA9IG5ldyBEZWNvZGVkSW5mb3JtYXRpb24odGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCksIHRoaXMuYnVmZmVyLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEJsb2NrUGFyc2VkUmVzdWx0KHRydWUsIGluZm9ybWF0aW9uKTsgLy8gZW5kIG9mIHRoZSBjaGFyIGJsb2NrXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuYnVmZmVyLmFwcGVuZChhbHBoYS5nZXRWYWx1ZSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmlzQWxwaGFPcjY0NlRvTnVtZXJpY0xhdGNoKHRoaXMuY3VycmVudC5nZXRQb3NpdGlvbigpKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5pbmNyZW1lbnRQb3NpdGlvbigzKTtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQuc2V0TnVtZXJpYygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5pc0FscGhhVG82NDZUb0FscGhhTGF0Y2godGhpcy5jdXJyZW50LmdldFBvc2l0aW9uKCkpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY3VycmVudC5nZXRQb3NpdGlvbigpICsgNSA8IHRoaXMuaW5mb3JtYXRpb24uZ2V0U2l6ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5pbmNyZW1lbnRQb3NpdGlvbig1KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5zZXRQb3NpdGlvbih0aGlzLmluZm9ybWF0aW9uLmdldFNpemUoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5zZXRJc29JZWM2NDYoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgQmxvY2tQYXJzZWRSZXN1bHQoZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIGlzU3RpbGxJc29JZWM2NDYocG9zKSB7XG4gICAgICAgICAgICBpZiAocG9zICsgNSA+IHRoaXMuaW5mb3JtYXRpb24uZ2V0U2l6ZSgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGZpdmVCaXRWYWx1ZSA9IHRoaXMuZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShwb3MsIDUpO1xuICAgICAgICAgICAgaWYgKGZpdmVCaXRWYWx1ZSA+PSA1ICYmIGZpdmVCaXRWYWx1ZSA8IDE2KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocG9zICsgNyA+IHRoaXMuaW5mb3JtYXRpb24uZ2V0U2l6ZSgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHNldmVuQml0VmFsdWUgPSB0aGlzLmV4dHJhY3ROdW1lcmljVmFsdWVGcm9tQml0QXJyYXkocG9zLCA3KTtcbiAgICAgICAgICAgIGlmIChzZXZlbkJpdFZhbHVlID49IDY0ICYmIHNldmVuQml0VmFsdWUgPCAxMTYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChwb3MgKyA4ID4gdGhpcy5pbmZvcm1hdGlvbi5nZXRTaXplKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZWlnaHRCaXRWYWx1ZSA9IHRoaXMuZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShwb3MsIDgpO1xuICAgICAgICAgICAgcmV0dXJuIGVpZ2h0Qml0VmFsdWUgPj0gMjMyICYmIGVpZ2h0Qml0VmFsdWUgPCAyNTM7XG4gICAgICAgIH1cbiAgICAgICAgZGVjb2RlSXNvSWVjNjQ2KHBvcykge1xuICAgICAgICAgICAgbGV0IGZpdmVCaXRWYWx1ZSA9IHRoaXMuZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShwb3MsIDUpO1xuICAgICAgICAgICAgaWYgKGZpdmVCaXRWYWx1ZSA9PT0gMTUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERlY29kZWRDaGFyKHBvcyArIDUsIERlY29kZWRDaGFyLkZOQzEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZpdmVCaXRWYWx1ZSA+PSA1ICYmIGZpdmVCaXRWYWx1ZSA8IDE1KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBEZWNvZGVkQ2hhcihwb3MgKyA1LCAoJzAnICsgKGZpdmVCaXRWYWx1ZSAtIDUpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc2V2ZW5CaXRWYWx1ZSA9IHRoaXMuZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShwb3MsIDcpO1xuICAgICAgICAgICAgaWYgKHNldmVuQml0VmFsdWUgPj0gNjQgJiYgc2V2ZW5CaXRWYWx1ZSA8IDkwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBEZWNvZGVkQ2hhcihwb3MgKyA3LCAoJycgKyAoc2V2ZW5CaXRWYWx1ZSArIDEpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2V2ZW5CaXRWYWx1ZSA+PSA5MCAmJiBzZXZlbkJpdFZhbHVlIDwgMTE2KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBEZWNvZGVkQ2hhcihwb3MgKyA3LCAoJycgKyAoc2V2ZW5CaXRWYWx1ZSArIDcpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZWlnaHRCaXRWYWx1ZSA9IHRoaXMuZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShwb3MsIDgpO1xuICAgICAgICAgICAgbGV0IGM7XG4gICAgICAgICAgICBzd2l0Y2ggKGVpZ2h0Qml0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDIzMjpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICchJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyMzM6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnXCInO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDIzNDpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICclJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyMzU6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnJic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjM2OlxuICAgICAgICAgICAgICAgICAgICBjID0gJ1xcJyc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjM3OlxuICAgICAgICAgICAgICAgICAgICBjID0gJygnO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDIzODpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICcpJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyMzk6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnKic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjQwOlxuICAgICAgICAgICAgICAgICAgICBjID0gJysnO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDI0MTpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICcsJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyNDI6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnLSc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjQzOlxuICAgICAgICAgICAgICAgICAgICBjID0gJy4nO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDI0NDpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICcvJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyNDU6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnOic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjQ2OlxuICAgICAgICAgICAgICAgICAgICBjID0gJzsnO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDI0NzpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICc8JztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyNDg6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnPSc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjQ5OlxuICAgICAgICAgICAgICAgICAgICBjID0gJz4nO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDI1MDpcbiAgICAgICAgICAgICAgICAgICAgYyA9ICc/JztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyNTE6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnXyc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjUyOlxuICAgICAgICAgICAgICAgICAgICBjID0gJyAnO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IERlY29kZWRDaGFyKHBvcyArIDgsIGMpO1xuICAgICAgICB9XG4gICAgICAgIGlzU3RpbGxBbHBoYShwb3MpIHtcbiAgICAgICAgICAgIGlmIChwb3MgKyA1ID4gdGhpcy5pbmZvcm1hdGlvbi5nZXRTaXplKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBXZSBub3cgY2hlY2sgaWYgaXQncyBhIHZhbGlkIDUtYml0IHZhbHVlICgwLi45IGFuZCBGTkMxKVxuICAgICAgICAgICAgbGV0IGZpdmVCaXRWYWx1ZSA9IHRoaXMuZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShwb3MsIDUpO1xuICAgICAgICAgICAgaWYgKGZpdmVCaXRWYWx1ZSA+PSA1ICYmIGZpdmVCaXRWYWx1ZSA8IDE2KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocG9zICsgNiA+IHRoaXMuaW5mb3JtYXRpb24uZ2V0U2l6ZSgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHNpeEJpdFZhbHVlID0gdGhpcy5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KHBvcywgNik7XG4gICAgICAgICAgICByZXR1cm4gc2l4Qml0VmFsdWUgPj0gMTYgJiYgc2l4Qml0VmFsdWUgPCA2MzsgLy8gNjMgbm90IGluY2x1ZGVkXG4gICAgICAgIH1cbiAgICAgICAgZGVjb2RlQWxwaGFudW1lcmljKHBvcykge1xuICAgICAgICAgICAgbGV0IGZpdmVCaXRWYWx1ZSA9IHRoaXMuZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShwb3MsIDUpO1xuICAgICAgICAgICAgaWYgKGZpdmVCaXRWYWx1ZSA9PT0gMTUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERlY29kZWRDaGFyKHBvcyArIDUsIERlY29kZWRDaGFyLkZOQzEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZpdmVCaXRWYWx1ZSA+PSA1ICYmIGZpdmVCaXRWYWx1ZSA8IDE1KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBEZWNvZGVkQ2hhcihwb3MgKyA1LCAoJzAnICsgKGZpdmVCaXRWYWx1ZSAtIDUpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc2l4Qml0VmFsdWUgPSB0aGlzLmV4dHJhY3ROdW1lcmljVmFsdWVGcm9tQml0QXJyYXkocG9zLCA2KTtcbiAgICAgICAgICAgIGlmIChzaXhCaXRWYWx1ZSA+PSAzMiAmJiBzaXhCaXRWYWx1ZSA8IDU4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBEZWNvZGVkQ2hhcihwb3MgKyA2LCAoJycgKyAoc2l4Qml0VmFsdWUgKyAzMykpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBjO1xuICAgICAgICAgICAgc3dpdGNoIChzaXhCaXRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgNTg6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnKic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNTk6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnLCc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNjA6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnLSc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNjE6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnLic7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNjI6XG4gICAgICAgICAgICAgICAgICAgIGMgPSAnLyc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oJ0RlY29kaW5nIGludmFsaWQgYWxwaGFudW1lcmljIHZhbHVlOiAnICsgc2l4Qml0VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBEZWNvZGVkQ2hhcihwb3MgKyA2LCBjKTtcbiAgICAgICAgfVxuICAgICAgICBpc0FscGhhVG82NDZUb0FscGhhTGF0Y2gocG9zKSB7XG4gICAgICAgICAgICBpZiAocG9zICsgMSA+IHRoaXMuaW5mb3JtYXRpb24uZ2V0U2l6ZSgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCA1ICYmIGkgKyBwb3MgPCB0aGlzLmluZm9ybWF0aW9uLmdldFNpemUoKTsgKytpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmluZm9ybWF0aW9uLmdldChwb3MgKyAyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuaW5mb3JtYXRpb24uZ2V0KHBvcyArIGkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpc0FscGhhT3I2NDZUb051bWVyaWNMYXRjaChwb3MpIHtcbiAgICAgICAgICAgIC8vIE5leHQgaXMgYWxwaGFudW1lcmljIGlmIHRoZXJlIGFyZSAzIHBvc2l0aW9ucyBhbmQgdGhleSBhcmUgYWxsIHplcm9zXG4gICAgICAgICAgICBpZiAocG9zICsgMyA+IHRoaXMuaW5mb3JtYXRpb24uZ2V0U2l6ZSgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IHBvczsgaSA8IHBvcyArIDM7ICsraSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmluZm9ybWF0aW9uLmdldChpKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaXNOdW1lcmljVG9BbHBoYU51bWVyaWNMYXRjaChwb3MpIHtcbiAgICAgICAgICAgIC8vIE5leHQgaXMgYWxwaGFudW1lcmljIGlmIHRoZXJlIGFyZSA0IHBvc2l0aW9ucyBhbmQgdGhleSBhcmUgYWxsIHplcm9zLCBvclxuICAgICAgICAgICAgLy8gaWYgdGhlcmUgaXMgYSBzdWJzZXQgb2YgdGhpcyBqdXN0IGJlZm9yZSB0aGUgZW5kIG9mIHRoZSBzeW1ib2xcbiAgICAgICAgICAgIGlmIChwb3MgKyAxID4gdGhpcy5pbmZvcm1hdGlvbi5nZXRTaXplKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDQgJiYgaSArIHBvcyA8IHRoaXMuaW5mb3JtYXRpb24uZ2V0U2l6ZSgpOyArK2kpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pbmZvcm1hdGlvbi5nZXQocG9zICsgaSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xhc3MgQWJzdHJhY3RFeHBhbmRlZERlY29kZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcihpbmZvcm1hdGlvbikge1xuICAgICAgICAgICAgdGhpcy5pbmZvcm1hdGlvbiA9IGluZm9ybWF0aW9uO1xuICAgICAgICAgICAgdGhpcy5nZW5lcmFsRGVjb2RlciA9IG5ldyBHZW5lcmFsQXBwSWREZWNvZGVyKGluZm9ybWF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBnZXRJbmZvcm1hdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmluZm9ybWF0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGdldEdlbmVyYWxEZWNvZGVyKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2VuZXJhbERlY29kZXI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjbGFzcyBBSTAxZGVjb2RlciBleHRlbmRzIEFic3RyYWN0RXhwYW5kZWREZWNvZGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IoaW5mb3JtYXRpb24pIHtcbiAgICAgICAgICAgIHN1cGVyKGluZm9ybWF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBlbmNvZGVDb21wcmVzc2VkR3RpbihidWYsIGN1cnJlbnRQb3MpIHtcbiAgICAgICAgICAgIGJ1Zi5hcHBlbmQoJygwMSknKTtcbiAgICAgICAgICAgIGxldCBpbml0aWFsUG9zaXRpb24gPSBidWYubGVuZ3RoKCk7XG4gICAgICAgICAgICBidWYuYXBwZW5kKCc5Jyk7XG4gICAgICAgICAgICB0aGlzLmVuY29kZUNvbXByZXNzZWRHdGluV2l0aG91dEFJKGJ1ZiwgY3VycmVudFBvcywgaW5pdGlhbFBvc2l0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBlbmNvZGVDb21wcmVzc2VkR3RpbldpdGhvdXRBSShidWYsIGN1cnJlbnRQb3MsIGluaXRpYWxCdWZmZXJQb3NpdGlvbikge1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCA0OyArK2kpIHtcbiAgICAgICAgICAgICAgICBsZXQgY3VycmVudEJsb2NrID0gdGhpcy5nZXRHZW5lcmFsRGVjb2RlcigpLmV4dHJhY3ROdW1lcmljVmFsdWVGcm9tQml0QXJyYXkoY3VycmVudFBvcyArIDEwICogaSwgMTApO1xuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50QmxvY2sgLyAxMDAgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgYnVmLmFwcGVuZCgnMCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudEJsb2NrIC8gMTAgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgYnVmLmFwcGVuZCgnMCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBidWYuYXBwZW5kKGN1cnJlbnRCbG9jayk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBBSTAxZGVjb2Rlci5hcHBlbmRDaGVja0RpZ2l0KGJ1ZiwgaW5pdGlhbEJ1ZmZlclBvc2l0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgYXBwZW5kQ2hlY2tEaWdpdChidWYsIGN1cnJlbnRQb3MpIHtcbiAgICAgICAgICAgIGxldCBjaGVja0RpZ2l0ID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMTM7IGkrKykge1xuICAgICAgICAgICAgICAgIC8vIGxldCBkaWdpdCA9IGJ1Zi5jaGFyQXQoaSArIGN1cnJlbnRQb3MpIC0gJzAnO1xuICAgICAgICAgICAgICAgIC8vIFRvIGJlIGNoZWNrZWRcbiAgICAgICAgICAgICAgICBsZXQgZGlnaXQgPSBidWYuY2hhckF0KGkgKyBjdXJyZW50UG9zKS5jaGFyQ29kZUF0KDApIC0gJzAnLmNoYXJDb2RlQXQoMCk7XG4gICAgICAgICAgICAgICAgY2hlY2tEaWdpdCArPSAoaSAmIDB4MDEpID09PSAwID8gMyAqIGRpZ2l0IDogZGlnaXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjaGVja0RpZ2l0ID0gMTAgLSAoY2hlY2tEaWdpdCAlIDEwKTtcbiAgICAgICAgICAgIGlmIChjaGVja0RpZ2l0ID09PSAxMCkge1xuICAgICAgICAgICAgICAgIGNoZWNrRGlnaXQgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnVmLmFwcGVuZChjaGVja0RpZ2l0KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBBSTAxZGVjb2Rlci5HVElOX1NJWkUgPSA0MDtcblxuICAgIGNsYXNzIEFJMDFBbmRPdGhlckFJcyBleHRlbmRzIEFJMDFkZWNvZGVyIHtcbiAgICAgICAgLy8gdGhlIHNlY29uZCBvbmUgaXMgdGhlIGVuY29kYXRpb24gbWV0aG9kLCBhbmQgdGhlIG90aGVyIHR3byBhcmUgZm9yIHRoZSB2YXJpYWJsZSBsZW5ndGhcbiAgICAgICAgY29uc3RydWN0b3IoaW5mb3JtYXRpb24pIHtcbiAgICAgICAgICAgIHN1cGVyKGluZm9ybWF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBwYXJzZUluZm9ybWF0aW9uKCkge1xuICAgICAgICAgICAgbGV0IGJ1ZmYgPSBuZXcgU3RyaW5nQnVpbGRlcigpO1xuICAgICAgICAgICAgYnVmZi5hcHBlbmQoJygwMSknKTtcbiAgICAgICAgICAgIGxldCBpbml0aWFsR3RpblBvc2l0aW9uID0gYnVmZi5sZW5ndGgoKTtcbiAgICAgICAgICAgIGxldCBmaXJzdEd0aW5EaWdpdCA9IHRoaXMuZ2V0R2VuZXJhbERlY29kZXIoKS5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KEFJMDFBbmRPdGhlckFJcy5IRUFERVJfU0laRSwgNCk7XG4gICAgICAgICAgICBidWZmLmFwcGVuZChmaXJzdEd0aW5EaWdpdCk7XG4gICAgICAgICAgICB0aGlzLmVuY29kZUNvbXByZXNzZWRHdGluV2l0aG91dEFJKGJ1ZmYsIEFJMDFBbmRPdGhlckFJcy5IRUFERVJfU0laRSArIDQsIGluaXRpYWxHdGluUG9zaXRpb24pO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0R2VuZXJhbERlY29kZXIoKS5kZWNvZGVBbGxDb2RlcyhidWZmLCBBSTAxQW5kT3RoZXJBSXMuSEVBREVSX1NJWkUgKyA0NCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgQUkwMUFuZE90aGVyQUlzLkhFQURFUl9TSVpFID0gMSArIDEgKyAyOyAvLyBmaXJzdCBiaXQgZW5jb2RlcyB0aGUgbGlua2FnZSBmbGFnLFxuXG4gICAgY2xhc3MgQW55QUlEZWNvZGVyIGV4dGVuZHMgQWJzdHJhY3RFeHBhbmRlZERlY29kZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcihpbmZvcm1hdGlvbikge1xuICAgICAgICAgICAgc3VwZXIoaW5mb3JtYXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIHBhcnNlSW5mb3JtYXRpb24oKSB7XG4gICAgICAgICAgICBsZXQgYnVmID0gbmV3IFN0cmluZ0J1aWxkZXIoKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldEdlbmVyYWxEZWNvZGVyKCkuZGVjb2RlQWxsQ29kZXMoYnVmLCBBbnlBSURlY29kZXIuSEVBREVSX1NJWkUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIEFueUFJRGVjb2Rlci5IRUFERVJfU0laRSA9IDIgKyAxICsgMjtcblxuICAgIGNsYXNzIEFJMDF3ZWlnaHREZWNvZGVyIGV4dGVuZHMgQUkwMWRlY29kZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcihpbmZvcm1hdGlvbikge1xuICAgICAgICAgICAgc3VwZXIoaW5mb3JtYXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIGVuY29kZUNvbXByZXNzZWRXZWlnaHQoYnVmLCBjdXJyZW50UG9zLCB3ZWlnaHRTaXplKSB7XG4gICAgICAgICAgICBsZXQgb3JpZ2luYWxXZWlnaHROdW1lcmljID0gdGhpcy5nZXRHZW5lcmFsRGVjb2RlcigpLmV4dHJhY3ROdW1lcmljVmFsdWVGcm9tQml0QXJyYXkoY3VycmVudFBvcywgd2VpZ2h0U2l6ZSk7XG4gICAgICAgICAgICB0aGlzLmFkZFdlaWdodENvZGUoYnVmLCBvcmlnaW5hbFdlaWdodE51bWVyaWMpO1xuICAgICAgICAgICAgbGV0IHdlaWdodE51bWVyaWMgPSB0aGlzLmNoZWNrV2VpZ2h0KG9yaWdpbmFsV2VpZ2h0TnVtZXJpYyk7XG4gICAgICAgICAgICBsZXQgY3VycmVudERpdmlzb3IgPSAxMDAwMDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDU7ICsraSkge1xuICAgICAgICAgICAgICAgIGlmICh3ZWlnaHROdW1lcmljIC8gY3VycmVudERpdmlzb3IgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgYnVmLmFwcGVuZCgnMCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjdXJyZW50RGl2aXNvciAvPSAxMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJ1Zi5hcHBlbmQod2VpZ2h0TnVtZXJpYyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjbGFzcyBBSTAxM3gweERlY29kZXIgZXh0ZW5kcyBBSTAxd2VpZ2h0RGVjb2RlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGluZm9ybWF0aW9uKSB7XG4gICAgICAgICAgICBzdXBlcihpbmZvcm1hdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgcGFyc2VJbmZvcm1hdGlvbigpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmdldEluZm9ybWF0aW9uKCkuZ2V0U2l6ZSgpICE9IEFJMDEzeDB4RGVjb2Rlci5IRUFERVJfU0laRSArIEFJMDF3ZWlnaHREZWNvZGVyLkdUSU5fU0laRSArIEFJMDEzeDB4RGVjb2Rlci5XRUlHSFRfU0laRSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGJ1ZiA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICB0aGlzLmVuY29kZUNvbXByZXNzZWRHdGluKGJ1ZiwgQUkwMTN4MHhEZWNvZGVyLkhFQURFUl9TSVpFKTtcbiAgICAgICAgICAgIHRoaXMuZW5jb2RlQ29tcHJlc3NlZFdlaWdodChidWYsIEFJMDEzeDB4RGVjb2Rlci5IRUFERVJfU0laRSArIEFJMDF3ZWlnaHREZWNvZGVyLkdUSU5fU0laRSwgQUkwMTN4MHhEZWNvZGVyLldFSUdIVF9TSVpFKTtcbiAgICAgICAgICAgIHJldHVybiBidWYudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBBSTAxM3gweERlY29kZXIuSEVBREVSX1NJWkUgPSA0ICsgMTtcbiAgICBBSTAxM3gweERlY29kZXIuV0VJR0hUX1NJWkUgPSAxNTtcblxuICAgIGNsYXNzIEFJMDEzMTAzZGVjb2RlciBleHRlbmRzIEFJMDEzeDB4RGVjb2RlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGluZm9ybWF0aW9uKSB7XG4gICAgICAgICAgICBzdXBlcihpbmZvcm1hdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgYWRkV2VpZ2h0Q29kZShidWYsIHdlaWdodCkge1xuICAgICAgICAgICAgYnVmLmFwcGVuZCgnKDMxMDMpJyk7XG4gICAgICAgIH1cbiAgICAgICAgY2hlY2tXZWlnaHQod2VpZ2h0KSB7XG4gICAgICAgICAgICByZXR1cm4gd2VpZ2h0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xhc3MgQUkwMTMyMHhEZWNvZGVyIGV4dGVuZHMgQUkwMTN4MHhEZWNvZGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IoaW5mb3JtYXRpb24pIHtcbiAgICAgICAgICAgIHN1cGVyKGluZm9ybWF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBhZGRXZWlnaHRDb2RlKGJ1Ziwgd2VpZ2h0KSB7XG4gICAgICAgICAgICBpZiAod2VpZ2h0IDwgMTAwMDApIHtcbiAgICAgICAgICAgICAgICBidWYuYXBwZW5kKCcoMzIwMiknKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGJ1Zi5hcHBlbmQoJygzMjAzKScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNoZWNrV2VpZ2h0KHdlaWdodCkge1xuICAgICAgICAgICAgaWYgKHdlaWdodCA8IDEwMDAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdlaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB3ZWlnaHQgLSAxMDAwMDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNsYXNzIEFJMDEzOTJ4RGVjb2RlciBleHRlbmRzIEFJMDFkZWNvZGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IoaW5mb3JtYXRpb24pIHtcbiAgICAgICAgICAgIHN1cGVyKGluZm9ybWF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBwYXJzZUluZm9ybWF0aW9uKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZ2V0SW5mb3JtYXRpb24oKS5nZXRTaXplKCkgPCBBSTAxMzkyeERlY29kZXIuSEVBREVSX1NJWkUgKyBBSTAxZGVjb2Rlci5HVElOX1NJWkUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBidWYgPSBuZXcgU3RyaW5nQnVpbGRlcigpO1xuICAgICAgICAgICAgdGhpcy5lbmNvZGVDb21wcmVzc2VkR3RpbihidWYsIEFJMDEzOTJ4RGVjb2Rlci5IRUFERVJfU0laRSk7XG4gICAgICAgICAgICBsZXQgbGFzdEFJZGlnaXQgPSB0aGlzLmdldEdlbmVyYWxEZWNvZGVyKCkuZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShBSTAxMzkyeERlY29kZXIuSEVBREVSX1NJWkUgKyBBSTAxZGVjb2Rlci5HVElOX1NJWkUsIEFJMDEzOTJ4RGVjb2Rlci5MQVNUX0RJR0lUX1NJWkUpO1xuICAgICAgICAgICAgYnVmLmFwcGVuZCgnKDM5MicpO1xuICAgICAgICAgICAgYnVmLmFwcGVuZChsYXN0QUlkaWdpdCk7XG4gICAgICAgICAgICBidWYuYXBwZW5kKCcpJyk7XG4gICAgICAgICAgICBsZXQgZGVjb2RlZEluZm9ybWF0aW9uID0gdGhpcy5nZXRHZW5lcmFsRGVjb2RlcigpLmRlY29kZUdlbmVyYWxQdXJwb3NlRmllbGQoQUkwMTM5MnhEZWNvZGVyLkhFQURFUl9TSVpFICsgQUkwMWRlY29kZXIuR1RJTl9TSVpFICsgQUkwMTM5MnhEZWNvZGVyLkxBU1RfRElHSVRfU0laRSwgbnVsbCk7XG4gICAgICAgICAgICBidWYuYXBwZW5kKGRlY29kZWRJbmZvcm1hdGlvbi5nZXROZXdTdHJpbmcoKSk7XG4gICAgICAgICAgICByZXR1cm4gYnVmLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgQUkwMTM5MnhEZWNvZGVyLkhFQURFUl9TSVpFID0gNSArIDEgKyAyO1xuICAgIEFJMDEzOTJ4RGVjb2Rlci5MQVNUX0RJR0lUX1NJWkUgPSAyO1xuXG4gICAgY2xhc3MgQUkwMTM5M3hEZWNvZGVyIGV4dGVuZHMgQUkwMWRlY29kZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcihpbmZvcm1hdGlvbikge1xuICAgICAgICAgICAgc3VwZXIoaW5mb3JtYXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIHBhcnNlSW5mb3JtYXRpb24oKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5nZXRJbmZvcm1hdGlvbigpLmdldFNpemUoKSA8IEFJMDEzOTN4RGVjb2Rlci5IRUFERVJfU0laRSArIEFJMDFkZWNvZGVyLkdUSU5fU0laRSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGJ1ZiA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICB0aGlzLmVuY29kZUNvbXByZXNzZWRHdGluKGJ1ZiwgQUkwMTM5M3hEZWNvZGVyLkhFQURFUl9TSVpFKTtcbiAgICAgICAgICAgIGxldCBsYXN0QUlkaWdpdCA9IHRoaXMuZ2V0R2VuZXJhbERlY29kZXIoKS5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KEFJMDEzOTN4RGVjb2Rlci5IRUFERVJfU0laRSArIEFJMDFkZWNvZGVyLkdUSU5fU0laRSwgQUkwMTM5M3hEZWNvZGVyLkxBU1RfRElHSVRfU0laRSk7XG4gICAgICAgICAgICBidWYuYXBwZW5kKCcoMzkzJyk7XG4gICAgICAgICAgICBidWYuYXBwZW5kKGxhc3RBSWRpZ2l0KTtcbiAgICAgICAgICAgIGJ1Zi5hcHBlbmQoJyknKTtcbiAgICAgICAgICAgIGxldCBmaXJzdFRocmVlRGlnaXRzID0gdGhpcy5nZXRHZW5lcmFsRGVjb2RlcigpLmV4dHJhY3ROdW1lcmljVmFsdWVGcm9tQml0QXJyYXkoQUkwMTM5M3hEZWNvZGVyLkhFQURFUl9TSVpFICsgQUkwMWRlY29kZXIuR1RJTl9TSVpFICsgQUkwMTM5M3hEZWNvZGVyLkxBU1RfRElHSVRfU0laRSwgQUkwMTM5M3hEZWNvZGVyLkZJUlNUX1RIUkVFX0RJR0lUU19TSVpFKTtcbiAgICAgICAgICAgIGlmIChmaXJzdFRocmVlRGlnaXRzIC8gMTAwID09IDApIHtcbiAgICAgICAgICAgICAgICBidWYuYXBwZW5kKCcwJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZmlyc3RUaHJlZURpZ2l0cyAvIDEwID09IDApIHtcbiAgICAgICAgICAgICAgICBidWYuYXBwZW5kKCcwJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBidWYuYXBwZW5kKGZpcnN0VGhyZWVEaWdpdHMpO1xuICAgICAgICAgICAgbGV0IGdlbmVyYWxJbmZvcm1hdGlvbiA9IHRoaXMuZ2V0R2VuZXJhbERlY29kZXIoKS5kZWNvZGVHZW5lcmFsUHVycG9zZUZpZWxkKEFJMDEzOTN4RGVjb2Rlci5IRUFERVJfU0laRSArIEFJMDFkZWNvZGVyLkdUSU5fU0laRSArIEFJMDEzOTN4RGVjb2Rlci5MQVNUX0RJR0lUX1NJWkUgKyBBSTAxMzkzeERlY29kZXIuRklSU1RfVEhSRUVfRElHSVRTX1NJWkUsIG51bGwpO1xuICAgICAgICAgICAgYnVmLmFwcGVuZChnZW5lcmFsSW5mb3JtYXRpb24uZ2V0TmV3U3RyaW5nKCkpO1xuICAgICAgICAgICAgcmV0dXJuIGJ1Zi50b1N0cmluZygpO1xuICAgICAgICB9XG4gICAgfVxuICAgIEFJMDEzOTN4RGVjb2Rlci5IRUFERVJfU0laRSA9IDUgKyAxICsgMjtcbiAgICBBSTAxMzkzeERlY29kZXIuTEFTVF9ESUdJVF9TSVpFID0gMjtcbiAgICBBSTAxMzkzeERlY29kZXIuRklSU1RfVEhSRUVfRElHSVRTX1NJWkUgPSAxMDtcblxuICAgIGNsYXNzIEFJMDEzeDB4MXhEZWNvZGVyIGV4dGVuZHMgQUkwMXdlaWdodERlY29kZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcihpbmZvcm1hdGlvbiwgZmlyc3RBSWRpZ2l0cywgZGF0ZUNvZGUpIHtcbiAgICAgICAgICAgIHN1cGVyKGluZm9ybWF0aW9uKTtcbiAgICAgICAgICAgIHRoaXMuZGF0ZUNvZGUgPSBkYXRlQ29kZTtcbiAgICAgICAgICAgIHRoaXMuZmlyc3RBSWRpZ2l0cyA9IGZpcnN0QUlkaWdpdHM7XG4gICAgICAgIH1cbiAgICAgICAgcGFyc2VJbmZvcm1hdGlvbigpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmdldEluZm9ybWF0aW9uKCkuZ2V0U2l6ZSgpICE9IEFJMDEzeDB4MXhEZWNvZGVyLkhFQURFUl9TSVpFICsgQUkwMTN4MHgxeERlY29kZXIuR1RJTl9TSVpFICsgQUkwMTN4MHgxeERlY29kZXIuV0VJR0hUX1NJWkUgKyBBSTAxM3gweDF4RGVjb2Rlci5EQVRFX1NJWkUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBidWYgPSBuZXcgU3RyaW5nQnVpbGRlcigpO1xuICAgICAgICAgICAgdGhpcy5lbmNvZGVDb21wcmVzc2VkR3RpbihidWYsIEFJMDEzeDB4MXhEZWNvZGVyLkhFQURFUl9TSVpFKTtcbiAgICAgICAgICAgIHRoaXMuZW5jb2RlQ29tcHJlc3NlZFdlaWdodChidWYsIEFJMDEzeDB4MXhEZWNvZGVyLkhFQURFUl9TSVpFICsgQUkwMTN4MHgxeERlY29kZXIuR1RJTl9TSVpFLCBBSTAxM3gweDF4RGVjb2Rlci5XRUlHSFRfU0laRSk7XG4gICAgICAgICAgICB0aGlzLmVuY29kZUNvbXByZXNzZWREYXRlKGJ1ZiwgQUkwMTN4MHgxeERlY29kZXIuSEVBREVSX1NJWkUgKyBBSTAxM3gweDF4RGVjb2Rlci5HVElOX1NJWkUgKyBBSTAxM3gweDF4RGVjb2Rlci5XRUlHSFRfU0laRSk7XG4gICAgICAgICAgICByZXR1cm4gYnVmLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICAgICAgZW5jb2RlQ29tcHJlc3NlZERhdGUoYnVmLCBjdXJyZW50UG9zKSB7XG4gICAgICAgICAgICBsZXQgbnVtZXJpY0RhdGUgPSB0aGlzLmdldEdlbmVyYWxEZWNvZGVyKCkuZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShjdXJyZW50UG9zLCBBSTAxM3gweDF4RGVjb2Rlci5EQVRFX1NJWkUpO1xuICAgICAgICAgICAgaWYgKG51bWVyaWNEYXRlID09IDM4NDAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnVmLmFwcGVuZCgnKCcpO1xuICAgICAgICAgICAgYnVmLmFwcGVuZCh0aGlzLmRhdGVDb2RlKTtcbiAgICAgICAgICAgIGJ1Zi5hcHBlbmQoJyknKTtcbiAgICAgICAgICAgIGxldCBkYXkgPSBudW1lcmljRGF0ZSAlIDMyO1xuICAgICAgICAgICAgbnVtZXJpY0RhdGUgLz0gMzI7XG4gICAgICAgICAgICBsZXQgbW9udGggPSBudW1lcmljRGF0ZSAlIDEyICsgMTtcbiAgICAgICAgICAgIG51bWVyaWNEYXRlIC89IDEyO1xuICAgICAgICAgICAgbGV0IHllYXIgPSBudW1lcmljRGF0ZTtcbiAgICAgICAgICAgIGlmICh5ZWFyIC8gMTAgPT0gMCkge1xuICAgICAgICAgICAgICAgIGJ1Zi5hcHBlbmQoJzAnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJ1Zi5hcHBlbmQoeWVhcik7XG4gICAgICAgICAgICBpZiAobW9udGggLyAxMCA9PSAwKSB7XG4gICAgICAgICAgICAgICAgYnVmLmFwcGVuZCgnMCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnVmLmFwcGVuZChtb250aCk7XG4gICAgICAgICAgICBpZiAoZGF5IC8gMTAgPT0gMCkge1xuICAgICAgICAgICAgICAgIGJ1Zi5hcHBlbmQoJzAnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJ1Zi5hcHBlbmQoZGF5KTtcbiAgICAgICAgfVxuICAgICAgICBhZGRXZWlnaHRDb2RlKGJ1Ziwgd2VpZ2h0KSB7XG4gICAgICAgICAgICBidWYuYXBwZW5kKCcoJyk7XG4gICAgICAgICAgICBidWYuYXBwZW5kKHRoaXMuZmlyc3RBSWRpZ2l0cyk7XG4gICAgICAgICAgICBidWYuYXBwZW5kKHdlaWdodCAvIDEwMDAwMCk7XG4gICAgICAgICAgICBidWYuYXBwZW5kKCcpJyk7XG4gICAgICAgIH1cbiAgICAgICAgY2hlY2tXZWlnaHQod2VpZ2h0KSB7XG4gICAgICAgICAgICByZXR1cm4gd2VpZ2h0ICUgMTAwMDAwO1xuICAgICAgICB9XG4gICAgfVxuICAgIEFJMDEzeDB4MXhEZWNvZGVyLkhFQURFUl9TSVpFID0gNyArIDE7XG4gICAgQUkwMTN4MHgxeERlY29kZXIuV0VJR0hUX1NJWkUgPSAyMDtcbiAgICBBSTAxM3gweDF4RGVjb2Rlci5EQVRFX1NJWkUgPSAxNjtcblxuICAgIGZ1bmN0aW9uIGNyZWF0ZURlY29kZXIoaW5mb3JtYXRpb24pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChpbmZvcm1hdGlvbi5nZXQoMSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEFJMDFBbmRPdGhlckFJcyhpbmZvcm1hdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWluZm9ybWF0aW9uLmdldCgyKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQW55QUlEZWNvZGVyKGluZm9ybWF0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBmb3VyQml0RW5jb2RhdGlvbk1ldGhvZCA9IEdlbmVyYWxBcHBJZERlY29kZXIuZXh0cmFjdE51bWVyaWNWYWx1ZUZyb21CaXRBcnJheShpbmZvcm1hdGlvbiwgMSwgNCk7XG4gICAgICAgICAgICBzd2l0Y2ggKGZvdXJCaXRFbmNvZGF0aW9uTWV0aG9kKSB7XG4gICAgICAgICAgICAgICAgY2FzZSA0OiByZXR1cm4gbmV3IEFJMDEzMTAzZGVjb2RlcihpbmZvcm1hdGlvbik7XG4gICAgICAgICAgICAgICAgY2FzZSA1OiByZXR1cm4gbmV3IEFJMDEzMjB4RGVjb2RlcihpbmZvcm1hdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZml2ZUJpdEVuY29kYXRpb25NZXRob2QgPSBHZW5lcmFsQXBwSWREZWNvZGVyLmV4dHJhY3ROdW1lcmljVmFsdWVGcm9tQml0QXJyYXkoaW5mb3JtYXRpb24sIDEsIDUpO1xuICAgICAgICAgICAgc3dpdGNoIChmaXZlQml0RW5jb2RhdGlvbk1ldGhvZCkge1xuICAgICAgICAgICAgICAgIGNhc2UgMTI6IHJldHVybiBuZXcgQUkwMTM5MnhEZWNvZGVyKGluZm9ybWF0aW9uKTtcbiAgICAgICAgICAgICAgICBjYXNlIDEzOiByZXR1cm4gbmV3IEFJMDEzOTN4RGVjb2RlcihpbmZvcm1hdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc2V2ZW5CaXRFbmNvZGF0aW9uTWV0aG9kID0gR2VuZXJhbEFwcElkRGVjb2Rlci5leHRyYWN0TnVtZXJpY1ZhbHVlRnJvbUJpdEFycmF5KGluZm9ybWF0aW9uLCAxLCA3KTtcbiAgICAgICAgICAgIHN3aXRjaCAoc2V2ZW5CaXRFbmNvZGF0aW9uTWV0aG9kKSB7XG4gICAgICAgICAgICAgICAgY2FzZSA1NjogcmV0dXJuIG5ldyBBSTAxM3gweDF4RGVjb2RlcihpbmZvcm1hdGlvbiwgJzMxMCcsICcxMScpO1xuICAgICAgICAgICAgICAgIGNhc2UgNTc6IHJldHVybiBuZXcgQUkwMTN4MHgxeERlY29kZXIoaW5mb3JtYXRpb24sICczMjAnLCAnMTEnKTtcbiAgICAgICAgICAgICAgICBjYXNlIDU4OiByZXR1cm4gbmV3IEFJMDEzeDB4MXhEZWNvZGVyKGluZm9ybWF0aW9uLCAnMzEwJywgJzEzJyk7XG4gICAgICAgICAgICAgICAgY2FzZSA1OTogcmV0dXJuIG5ldyBBSTAxM3gweDF4RGVjb2RlcihpbmZvcm1hdGlvbiwgJzMyMCcsICcxMycpO1xuICAgICAgICAgICAgICAgIGNhc2UgNjA6IHJldHVybiBuZXcgQUkwMTN4MHgxeERlY29kZXIoaW5mb3JtYXRpb24sICczMTAnLCAnMTUnKTtcbiAgICAgICAgICAgICAgICBjYXNlIDYxOiByZXR1cm4gbmV3IEFJMDEzeDB4MXhEZWNvZGVyKGluZm9ybWF0aW9uLCAnMzIwJywgJzE1Jyk7XG4gICAgICAgICAgICAgICAgY2FzZSA2MjogcmV0dXJuIG5ldyBBSTAxM3gweDF4RGVjb2RlcihpbmZvcm1hdGlvbiwgJzMxMCcsICcxNycpO1xuICAgICAgICAgICAgICAgIGNhc2UgNjM6IHJldHVybiBuZXcgQUkwMTN4MHgxeERlY29kZXIoaW5mb3JtYXRpb24sICczMjAnLCAnMTcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc29sZS5sb2coZSk7XG4gICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCd1bmtub3duIGRlY29kZXI6ICcgKyBpbmZvcm1hdGlvbik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjbGFzcyBFeHBhbmRlZFBhaXIge1xuICAgICAgICBjb25zdHJ1Y3RvcihsZWZ0Q2hhciwgcmlnaHRDaGFyLCBmaW5kZXJQYXR0ZXIsIG1heUJlTGFzdCkge1xuICAgICAgICAgICAgdGhpcy5sZWZ0Y2hhciA9IGxlZnRDaGFyO1xuICAgICAgICAgICAgdGhpcy5yaWdodGNoYXIgPSByaWdodENoYXI7XG4gICAgICAgICAgICB0aGlzLmZpbmRlcnBhdHRlcm4gPSBmaW5kZXJQYXR0ZXI7XG4gICAgICAgICAgICB0aGlzLm1heWJlTGFzdCA9IG1heUJlTGFzdDtcbiAgICAgICAgfVxuICAgICAgICBtYXlCZUxhc3QoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXliZUxhc3Q7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0TGVmdENoYXIoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sZWZ0Y2hhcjtcbiAgICAgICAgfVxuICAgICAgICBnZXRSaWdodENoYXIoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yaWdodGNoYXI7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RmluZGVyUGF0dGVybigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbmRlcnBhdHRlcm47XG4gICAgICAgIH1cbiAgICAgICAgbXVzdEJlTGFzdCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJpZ2h0Y2hhciA9PSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgcmV0dXJuICdbICcgKyB0aGlzLmxlZnRjaGFyICsgJywgJyArIHRoaXMucmlnaHRjaGFyICsgJyA6ICcgKyAodGhpcy5maW5kZXJwYXR0ZXJuID09IG51bGwgPyAnbnVsbCcgOiB0aGlzLmZpbmRlcnBhdHRlcm4uZ2V0VmFsdWUoKSkgKyAnIF0nO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBlcXVhbHMobzEsIG8yKSB7XG4gICAgICAgICAgICBpZiAoIShvMSBpbnN0YW5jZW9mIEV4cGFuZGVkUGFpcikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gRXhwYW5kZWRQYWlyLmVxdWFsc09yTnVsbChvMS5sZWZ0Y2hhciwgbzIubGVmdGNoYXIpICYmXG4gICAgICAgICAgICAgICAgRXhwYW5kZWRQYWlyLmVxdWFsc09yTnVsbChvMS5yaWdodGNoYXIsIG8yLnJpZ2h0Y2hhcikgJiZcbiAgICAgICAgICAgICAgICBFeHBhbmRlZFBhaXIuZXF1YWxzT3JOdWxsKG8xLmZpbmRlcnBhdHRlcm4sIG8yLmZpbmRlcnBhdHRlcm4pO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBlcXVhbHNPck51bGwobzEsIG8yKSB7XG4gICAgICAgICAgICByZXR1cm4gbzEgPT09IG51bGwgPyBvMiA9PT0gbnVsbCA6IEV4cGFuZGVkUGFpci5lcXVhbHMobzEsIG8yKTtcbiAgICAgICAgfVxuICAgICAgICBoYXNoQ29kZSgpIHtcbiAgICAgICAgICAgIC8vIHJldHVybiBFeHBhbmRlZFBhaXIuaGFzaE5vdE51bGwobGVmdENoYXIpIF4gaGFzaE5vdE51bGwocmlnaHRDaGFyKSBeIGhhc2hOb3ROdWxsKGZpbmRlclBhdHRlcm4pO1xuICAgICAgICAgICAgbGV0IHZhbHVlID0gdGhpcy5sZWZ0Y2hhci5nZXRWYWx1ZSgpIF4gdGhpcy5yaWdodGNoYXIuZ2V0VmFsdWUoKSBeIHRoaXMuZmluZGVycGF0dGVybi5nZXRWYWx1ZSgpO1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xhc3MgRXhwYW5kZWRSb3cge1xuICAgICAgICBjb25zdHJ1Y3RvcihwYWlycywgcm93TnVtYmVyLCB3YXNSZXZlcnNlZCkge1xuICAgICAgICAgICAgdGhpcy5wYWlycyA9IHBhaXJzO1xuICAgICAgICAgICAgdGhpcy5yb3dOdW1iZXIgPSByb3dOdW1iZXI7XG4gICAgICAgICAgICB0aGlzLndhc1JldmVyc2VkID0gd2FzUmV2ZXJzZWQ7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0UGFpcnMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wYWlycztcbiAgICAgICAgfVxuICAgICAgICBnZXRSb3dOdW1iZXIoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yb3dOdW1iZXI7XG4gICAgICAgIH1cbiAgICAgICAgaXNSZXZlcnNlZCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndhc1JldmVyc2VkO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNoZWNrIGltcGxlbWVudGF0aW9uXG4gICAgICAgIGlzRXF1aXZhbGVudChvdGhlclBhaXJzKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jaGVja0VxdWFsaXRpdHkodGhpcywgb3RoZXJQYWlycyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgcmV0dXJuICd7ICcgKyB0aGlzLnBhaXJzICsgJyB9JztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogVHdvIHJvd3MgYXJlIGVxdWFsIGlmIHRoZXkgY29udGFpbiB0aGUgc2FtZSBwYWlycyBpbiB0aGUgc2FtZSBvcmRlci5cbiAgICAgICAgICovXG4gICAgICAgIC8vIEBPdmVycmlkZVxuICAgICAgICAvLyBjaGVjayBpbXBsZW1lbnRhdGlvblxuICAgICAgICBlcXVhbHMobzEsIG8yKSB7XG4gICAgICAgICAgICBpZiAoIShvMSBpbnN0YW5jZW9mIEV4cGFuZGVkUm93KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNoZWNrRXF1YWxpdGl0eShvMSwgbzIpICYmIG8xLndhc1JldmVyc2VkID09PSBvMi53YXNSZXZlcnNlZDtcbiAgICAgICAgfVxuICAgICAgICBjaGVja0VxdWFsaXRpdHkocGFpcjEsIHBhaXIyKSB7XG4gICAgICAgICAgICBpZiAoIXBhaXIxIHx8ICFwYWlyMilcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICAgICAgcGFpcjEuZm9yRWFjaCgoZTEsIGkpID0+IHtcbiAgICAgICAgICAgICAgICBwYWlyMi5mb3JFYWNoKGUyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGUxLmdldExlZnRDaGFyKCkuZ2V0VmFsdWUoKSA9PT0gZTIuZ2V0TGVmdENoYXIoKS5nZXRWYWx1ZSgpICYmIGUxLmdldFJpZ2h0Q2hhcigpLmdldFZhbHVlKCkgPT09IGUyLmdldFJpZ2h0Q2hhcigpLmdldFZhbHVlKCkgJiYgZTEuZ2V0RmluZGVyUGF0dGVyKCkuZ2V0VmFsdWUoKSA9PT0gZTIuZ2V0RmluZGVyUGF0dGVyKCkuZ2V0VmFsdWUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7XG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5JdGVyYXRvcjtcbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLkxpc3Q7XG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5NYXA7XG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5Db2xsZWN0aW9ucztcbiAgICBjbGFzcyBSU1NFeHBhbmRlZFJlYWRlciBleHRlbmRzIEFic3RyYWN0UlNTUmVhZGVyIHtcbiAgICAgICAgY29uc3RydWN0b3IodmVyYm9zZSkge1xuICAgICAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgICAgIHRoaXMucGFpcnMgPSBuZXcgQXJyYXkoUlNTRXhwYW5kZWRSZWFkZXIuTUFYX1BBSVJTKTtcbiAgICAgICAgICAgIHRoaXMucm93cyA9IG5ldyBBcnJheSgpO1xuICAgICAgICAgICAgdGhpcy5zdGFydEVuZCA9IFsyXTtcbiAgICAgICAgICAgIHRoaXMudmVyYm9zZSA9ICh2ZXJib3NlID09PSB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICBkZWNvZGVSb3cocm93TnVtYmVyLCByb3csIGhpbnRzKSB7XG4gICAgICAgICAgICAvLyBSb3dzIGNhbiBzdGFydCB3aXRoIGV2ZW4gcGF0dGVybiBpbiBjYXNlIGluIHByZXYgcm93cyB0aGVyZSB3aGVyZSBvZGQgbnVtYmVyIG9mIHBhdHRlcnMuXG4gICAgICAgICAgICAvLyBTbyBsZXRzIHRyeSB0d2ljZVxuICAgICAgICAgICAgLy8gdGhpcy5wYWlycy5jbGVhcigpO1xuICAgICAgICAgICAgdGhpcy5wYWlycy5sZW5ndGggPSAwO1xuICAgICAgICAgICAgdGhpcy5zdGFydEZyb21FdmVuID0gZmFsc2U7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJldHVybiBSU1NFeHBhbmRlZFJlYWRlci5jb25zdHJ1Y3RSZXN1bHQodGhpcy5kZWNvZGVSb3cycGFpcnMocm93TnVtYmVyLCByb3cpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgLy8gT0tcbiAgICAgICAgICAgICAgICBpZiAodGhpcy52ZXJib3NlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucGFpcnMubGVuZ3RoID0gMDtcbiAgICAgICAgICAgIHRoaXMuc3RhcnRGcm9tRXZlbiA9IHRydWU7XG4gICAgICAgICAgICByZXR1cm4gUlNTRXhwYW5kZWRSZWFkZXIuY29uc3RydWN0UmVzdWx0KHRoaXMuZGVjb2RlUm93MnBhaXJzKHJvd051bWJlciwgcm93KSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVzZXQoKSB7XG4gICAgICAgICAgICB0aGlzLnBhaXJzLmxlbmd0aCA9IDA7XG4gICAgICAgICAgICB0aGlzLnJvd3MubGVuZ3RoID0gMDtcbiAgICAgICAgfVxuICAgICAgICAvLyBOb3QgcHJpdmF0ZSBmb3IgdGVzdGluZ1xuICAgICAgICBkZWNvZGVSb3cycGFpcnMocm93TnVtYmVyLCByb3cpIHtcbiAgICAgICAgICAgIGxldCBkb25lID0gZmFsc2U7XG4gICAgICAgICAgICB3aGlsZSAoIWRvbmUpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBhaXJzLnB1c2godGhpcy5yZXRyaWV2ZU5leHRQYWlyKHJvdywgdGhpcy5wYWlycywgcm93TnVtYmVyKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBOb3RGb3VuZEV4Y2VwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnBhaXJzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXhpdCB0aGlzIGxvb3Agd2hlbiByZXRyaWV2ZU5leHRQYWlyKCkgZmFpbHMgYW5kIHRocm93c1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBUT0RPOiB2ZXJpZnkgc2VxdWVuY2Ugb2YgZmluZGVyIHBhdHRlcm5zIGFzIGluIGNoZWNrUGFpclNlcXVlbmNlKClcbiAgICAgICAgICAgIGlmICh0aGlzLmNoZWNrQ2hlY2tzdW0oKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBhaXJzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHRyeVN0YWNrZWREZWNvZGU7XG4gICAgICAgICAgICBpZiAodGhpcy5yb3dzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRyeVN0YWNrZWREZWNvZGUgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdHJ5U3RhY2tlZERlY29kZSA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gbGV0IHRyeVN0YWNrZWREZWNvZGUgPSAhdGhpcy5yb3dzLmlzRW1wdHkoKTtcbiAgICAgICAgICAgIHRoaXMuc3RvcmVSb3cocm93TnVtYmVyLCBmYWxzZSk7IC8vIFRPRE86IGRlYWwgd2l0aCByZXZlcnNlZCByb3dzXG4gICAgICAgICAgICBpZiAodHJ5U3RhY2tlZERlY29kZSkge1xuICAgICAgICAgICAgICAgIC8vIFdoZW4gdGhlIGltYWdlIGlzIDE4MC1yb3RhdGVkLCB0aGVuIHJvd3MgYXJlIHNvcnRlZCBpbiB3cm9uZyBkaXJlY3Rpb24uXG4gICAgICAgICAgICAgICAgLy8gVHJ5IHR3aWNlIHdpdGggYm90aCB0aGUgZGlyZWN0aW9ucy5cbiAgICAgICAgICAgICAgICBsZXQgcHMgPSB0aGlzLmNoZWNrUm93c0Jvb2xlYW4oZmFsc2UpO1xuICAgICAgICAgICAgICAgIGlmIChwcyAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcHMgPSB0aGlzLmNoZWNrUm93c0Jvb2xlYW4odHJ1ZSk7XG4gICAgICAgICAgICAgICAgaWYgKHBzICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIC8vIE5lZWQgdG8gVmVyaWZ5XG4gICAgICAgIGNoZWNrUm93c0Jvb2xlYW4ocmV2ZXJzZSkge1xuICAgICAgICAgICAgLy8gTGltaXQgbnVtYmVyIG9mIHJvd3Mgd2UgYXJlIGNoZWNraW5nXG4gICAgICAgICAgICAvLyBXZSB1c2UgcmVjdXJzaXZlIGFsZ29yaXRobSB3aXRoIHB1cmUgY29tcGxleGl0eSBhbmQgZG9uJ3Qgd2FudCBpdCB0byB0YWtlIGZvcmV2ZXJcbiAgICAgICAgICAgIC8vIFN0YWNrZWQgYmFyY29kZSBjYW4gaGF2ZSB1cCB0byAxMSByb3dzLCBzbyAyNSBzZWVtcyByZWFzb25hYmxlIGVub3VnaFxuICAgICAgICAgICAgaWYgKHRoaXMucm93cy5sZW5ndGggPiAyNSkge1xuICAgICAgICAgICAgICAgIHRoaXMucm93cy5sZW5ndGggPSAwOyAvLyBXZSB3aWxsIG5ldmVyIGhhdmUgYSBjaGFuY2UgdG8gZ2V0IHJlc3VsdCwgc28gY2xlYXIgaXRcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucGFpcnMubGVuZ3RoID0gMDtcbiAgICAgICAgICAgIGlmIChyZXZlcnNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yb3dzID0gdGhpcy5yb3dzLnJldmVyc2UoKTtcbiAgICAgICAgICAgICAgICAvLyBDb2xsZWN0aW9ucy5yZXZlcnNlKHRoaXMucm93cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcHMgPSBudWxsO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBwcyA9IHRoaXMuY2hlY2tSb3dzKG5ldyBBcnJheSgpLCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgLy8gT0tcbiAgICAgICAgICAgICAgICBpZiAodGhpcy52ZXJib3NlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyZXZlcnNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yb3dzID0gdGhpcy5yb3dzLnJldmVyc2UoKTtcbiAgICAgICAgICAgICAgICAvLyBDb2xsZWN0aW9ucy5yZXZlcnNlKHRoaXMucm93cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcHM7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVHJ5IHRvIGNvbnN0cnVjdCBhIHZhbGlkIHJvd3Mgc2VxdWVuY2VcbiAgICAgICAgLy8gUmVjdXJzaW9uIGlzIHVzZWQgdG8gaW1wbGVtZW50IGJhY2t0cmFja2luZ1xuICAgICAgICBjaGVja1Jvd3MoY29sbGVjdGVkUm93cywgY3VycmVudFJvdykge1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGN1cnJlbnRSb3c7IGkgPCB0aGlzLnJvd3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgcm93ID0gdGhpcy5yb3dzW2ldO1xuICAgICAgICAgICAgICAgIHRoaXMucGFpcnMubGVuZ3RoID0gMDtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBjb2xsZWN0ZWRSb3cgb2YgY29sbGVjdGVkUm93cykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBhaXJzLnB1c2goY29sbGVjdGVkUm93LmdldFBhaXJzKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnBhaXJzLnB1c2gocm93LmdldFBhaXJzKCkpO1xuICAgICAgICAgICAgICAgIGlmICghUlNTRXhwYW5kZWRSZWFkZXIuaXNWYWxpZFNlcXVlbmNlKHRoaXMucGFpcnMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jaGVja0NoZWNrc3VtKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFpcnM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCBycyA9IG5ldyBBcnJheShjb2xsZWN0ZWRSb3dzKTtcbiAgICAgICAgICAgICAgICBycy5wdXNoKHJvdyk7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVjdXJzaW9uOiB0cnkgdG8gYWRkIG1vcmUgcm93c1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jaGVja1Jvd3MocnMsIGkgKyAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gV2UgZmFpbGVkLCB0cnkgdGhlIG5leHQgY2FuZGlkYXRlXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnZlcmJvc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gV2hldGhlciB0aGUgcGFpcnMgZm9ybSBhIHZhbGlkIGZpbmQgcGF0dGVybiBzZXF1ZW5jZSxcbiAgICAgICAgLy8gZWl0aGVyIGNvbXBsZXRlIG9yIGEgcHJlZml4XG4gICAgICAgIHN0YXRpYyBpc1ZhbGlkU2VxdWVuY2UocGFpcnMpIHtcbiAgICAgICAgICAgIGZvciAobGV0IHNlcXVlbmNlIG9mIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRURVJOX1NFUVVFTkNFUykge1xuICAgICAgICAgICAgICAgIGlmIChwYWlycy5sZW5ndGggPiBzZXF1ZW5jZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCBzdG9wID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHBhaXJzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwYWlyc1tqXS5nZXRGaW5kZXJQYXR0ZXJuKCkuZ2V0VmFsdWUoKSAhPSBzZXF1ZW5jZVtqXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RvcCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHN0b3ApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHN0b3JlUm93KHJvd051bWJlciwgd2FzUmV2ZXJzZWQpIHtcbiAgICAgICAgICAgIC8vIERpc2NhcmQgaWYgZHVwbGljYXRlIGFib3ZlIG9yIGJlbG93OyBvdGhlcndpc2UgaW5zZXJ0IGluIG9yZGVyIGJ5IHJvdyBudW1iZXIuXG4gICAgICAgICAgICBsZXQgaW5zZXJ0UG9zID0gMDtcbiAgICAgICAgICAgIGxldCBwcmV2SXNTYW1lID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgbmV4dElzU2FtZSA9IGZhbHNlO1xuICAgICAgICAgICAgd2hpbGUgKGluc2VydFBvcyA8IHRoaXMucm93cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBsZXQgZXJvdyA9IHRoaXMucm93c1tpbnNlcnRQb3NdO1xuICAgICAgICAgICAgICAgIGlmIChlcm93LmdldFJvd051bWJlcigpID4gcm93TnVtYmVyKSB7XG4gICAgICAgICAgICAgICAgICAgIG5leHRJc1NhbWUgPSBlcm93LmlzRXF1aXZhbGVudCh0aGlzLnBhaXJzKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHByZXZJc1NhbWUgPSBlcm93LmlzRXF1aXZhbGVudCh0aGlzLnBhaXJzKTtcbiAgICAgICAgICAgICAgICBpbnNlcnRQb3MrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChuZXh0SXNTYW1lIHx8IHByZXZJc1NhbWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBXaGVuIHRoZSByb3cgd2FzIHBhcnRpYWxseSBkZWNvZGVkIChlLmcuIDIgcGFpcnMgZm91bmQgaW5zdGVhZCBvZiAzKSxcbiAgICAgICAgICAgIC8vIGl0IHdpbGwgcHJldmVudCB1cyBmcm9tIGRldGVjdGluZyB0aGUgYmFyY29kZS5cbiAgICAgICAgICAgIC8vIFRyeSB0byBtZXJnZSBwYXJ0aWFsIHJvd3NcbiAgICAgICAgICAgIC8vIENoZWNrIHdoZXRoZXIgdGhlIHJvdyBpcyBwYXJ0IG9mIGFuIGFsbHJlYWR5IGRldGVjdGVkIHJvd1xuICAgICAgICAgICAgaWYgKFJTU0V4cGFuZGVkUmVhZGVyLmlzUGFydGlhbFJvdyh0aGlzLnBhaXJzLCB0aGlzLnJvd3MpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yb3dzLnB1c2goaW5zZXJ0UG9zLCBuZXcgRXhwYW5kZWRSb3codGhpcy5wYWlycywgcm93TnVtYmVyLCB3YXNSZXZlcnNlZCkpO1xuICAgICAgICAgICAgdGhpcy5yZW1vdmVQYXJ0aWFsUm93cyh0aGlzLnBhaXJzLCB0aGlzLnJvd3MpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFJlbW92ZSBhbGwgdGhlIHJvd3MgdGhhdCBjb250YWlucyBvbmx5IHNwZWNpZmllZCBwYWlyc1xuICAgICAgICByZW1vdmVQYXJ0aWFsUm93cyhwYWlycywgcm93cykge1xuICAgICAgICAgICAgLy8gZm9yIChJdGVyYXRvcjxFeHBhbmRlZFJvdz4gaXRlcmF0b3IgPSByb3dzLml0ZXJhdG9yKCk7IGl0ZXJhdG9yLmhhc05leHQoKTspIHtcbiAgICAgICAgICAgIC8vICAgRXhwYW5kZWRSb3cgciA9IGl0ZXJhdG9yLm5leHQoKTtcbiAgICAgICAgICAgIC8vICAgaWYgKHIuZ2V0UGFpcnMoKS5zaXplKCkgPT0gcGFpcnMuc2l6ZSgpKSB7XG4gICAgICAgICAgICAvLyAgICAgY29udGludWU7XG4gICAgICAgICAgICAvLyAgIH1cbiAgICAgICAgICAgIC8vICAgYm9vbGVhbiBhbGxGb3VuZCA9IHRydWU7XG4gICAgICAgICAgICAvLyAgIGZvciAoRXhwYW5kZWRQYWlyIHAgOiByLmdldFBhaXJzKCkpIHtcbiAgICAgICAgICAgIC8vICAgICBib29sZWFuIGZvdW5kID0gZmFsc2U7XG4gICAgICAgICAgICAvLyAgICAgZm9yIChFeHBhbmRlZFBhaXIgcHAgOiBwYWlycykge1xuICAgICAgICAgICAgLy8gICAgICAgaWYgKHAuZXF1YWxzKHBwKSkge1xuICAgICAgICAgICAgLy8gICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICAvLyAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgLy8gICAgICAgfVxuICAgICAgICAgICAgLy8gICAgIH1cbiAgICAgICAgICAgIC8vICAgICBpZiAoIWZvdW5kKSB7XG4gICAgICAgICAgICAvLyAgICAgICBhbGxGb3VuZCA9IGZhbHNlO1xuICAgICAgICAgICAgLy8gICAgICAgYnJlYWs7XG4gICAgICAgICAgICAvLyAgICAgfVxuICAgICAgICAgICAgLy8gICB9XG4gICAgICAgICAgICAvLyAgIGlmIChhbGxGb3VuZCkge1xuICAgICAgICAgICAgLy8gICAgIC8vICdwYWlycycgY29udGFpbnMgYWxsIHRoZSBwYWlycyBmcm9tIHRoZSByb3cgJ3InXG4gICAgICAgICAgICAvLyAgICAgaXRlcmF0b3IucmVtb3ZlKCk7XG4gICAgICAgICAgICAvLyAgIH1cbiAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgIGZvciAobGV0IHJvdyBvZiByb3dzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJvdy5nZXRQYWlycygpLmxlbmd0aCA9PT0gcGFpcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKGxldCBwIG9mIHJvdy5nZXRQYWlycygpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IHBwIG9mIHBhaXJzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoRXhwYW5kZWRQYWlyLmVxdWFscyhwLCBwcCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBSZXR1cm5zIHRydWUgd2hlbiBvbmUgb2YgdGhlIHJvd3MgYWxyZWFkeSBjb250YWlucyBhbGwgdGhlIHBhaXJzXG4gICAgICAgIHN0YXRpYyBpc1BhcnRpYWxSb3cocGFpcnMsIHJvd3MpIHtcbiAgICAgICAgICAgIGZvciAobGV0IHIgb2Ygcm93cykge1xuICAgICAgICAgICAgICAgIGxldCBhbGxGb3VuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgcCBvZiBwYWlycykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgcHAgb2Ygci5nZXRQYWlycygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocC5lcXVhbHMocHApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICghZm91bmQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsbEZvdW5kID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYWxsRm91bmQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHJvdyAncicgY29udGFpbiBhbGwgdGhlIHBhaXJzIGZyb20gJ3BhaXJzJ1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gT25seSB1c2VkIGZvciB1bml0IHRlc3RpbmdcbiAgICAgICAgZ2V0Um93cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJvd3M7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTm90IHByaXZhdGUgZm9yIHVuaXQgdGVzdGluZ1xuICAgICAgICBzdGF0aWMgY29uc3RydWN0UmVzdWx0KHBhaXJzKSB7XG4gICAgICAgICAgICBsZXQgYmluYXJ5ID0gQml0QXJyYXlCdWlsZGVyLmJ1aWxkQml0QXJyYXkocGFpcnMpO1xuICAgICAgICAgICAgbGV0IGRlY29kZXIgPSBjcmVhdGVEZWNvZGVyKGJpbmFyeSk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0aW5nU3RyaW5nID0gZGVjb2Rlci5wYXJzZUluZm9ybWF0aW9uKCk7XG4gICAgICAgICAgICBsZXQgZmlyc3RQb2ludHMgPSBwYWlyc1swXS5nZXRGaW5kZXJQYXR0ZXJuKCkuZ2V0UmVzdWx0UG9pbnRzKCk7XG4gICAgICAgICAgICBsZXQgbGFzdFBvaW50cyA9IHBhaXJzW3BhaXJzLmxlbmd0aCAtIDFdLmdldEZpbmRlclBhdHRlcm4oKS5nZXRSZXN1bHRQb2ludHMoKTtcbiAgICAgICAgICAgIGxldCBwb2ludHMgPSBbZmlyc3RQb2ludHNbMF0sIGZpcnN0UG9pbnRzWzFdLCBsYXN0UG9pbnRzWzBdLCBsYXN0UG9pbnRzWzFdXTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUmVzdWx0KHJlc3VsdGluZ1N0cmluZywgbnVsbCwgbnVsbCwgcG9pbnRzLCBCYXJjb2RlRm9ybWF0JDEuUlNTX0VYUEFOREVELCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgICBjaGVja0NoZWNrc3VtKCkge1xuICAgICAgICAgICAgbGV0IGZpcnN0UGFpciA9IHRoaXMucGFpcnMuZ2V0KDApO1xuICAgICAgICAgICAgbGV0IGNoZWNrQ2hhcmFjdGVyID0gZmlyc3RQYWlyLmdldExlZnRDaGFyKCk7XG4gICAgICAgICAgICBsZXQgZmlyc3RDaGFyYWN0ZXIgPSBmaXJzdFBhaXIuZ2V0UmlnaHRDaGFyKCk7XG4gICAgICAgICAgICBpZiAoZmlyc3RDaGFyYWN0ZXIgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBjaGVja3N1bSA9IGZpcnN0Q2hhcmFjdGVyLmdldENoZWNrc3VtUG9ydGlvbigpO1xuICAgICAgICAgICAgbGV0IHMgPSAyO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCB0aGlzLnBhaXJzLnNpemUoKTsgKytpKSB7XG4gICAgICAgICAgICAgICAgbGV0IGN1cnJlbnRQYWlyID0gdGhpcy5wYWlycy5nZXQoaSk7XG4gICAgICAgICAgICAgICAgY2hlY2tzdW0gKz0gY3VycmVudFBhaXIuZ2V0TGVmdENoYXIoKS5nZXRDaGVja3N1bVBvcnRpb24oKTtcbiAgICAgICAgICAgICAgICBzKys7XG4gICAgICAgICAgICAgICAgbGV0IGN1cnJlbnRSaWdodENoYXIgPSBjdXJyZW50UGFpci5nZXRSaWdodENoYXIoKTtcbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudFJpZ2h0Q2hhciAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrc3VtICs9IGN1cnJlbnRSaWdodENoYXIuZ2V0Q2hlY2tzdW1Qb3J0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIHMrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjaGVja3N1bSAlPSAyMTE7XG4gICAgICAgICAgICBsZXQgY2hlY2tDaGFyYWN0ZXJWYWx1ZSA9IDIxMSAqIChzIC0gNCkgKyBjaGVja3N1bTtcbiAgICAgICAgICAgIHJldHVybiBjaGVja0NoYXJhY3RlclZhbHVlID09IGNoZWNrQ2hhcmFjdGVyLmdldFZhbHVlKCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdldE5leHRTZWNvbmRCYXIocm93LCBpbml0aWFsUG9zKSB7XG4gICAgICAgICAgICBsZXQgY3VycmVudFBvcztcbiAgICAgICAgICAgIGlmIChyb3cuZ2V0KGluaXRpYWxQb3MpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudFBvcyA9IHJvdy5nZXROZXh0VW5zZXQoaW5pdGlhbFBvcyk7XG4gICAgICAgICAgICAgICAgY3VycmVudFBvcyA9IHJvdy5nZXROZXh0U2V0KGN1cnJlbnRQb3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY3VycmVudFBvcyA9IHJvdy5nZXROZXh0U2V0KGluaXRpYWxQb3MpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRQb3MgPSByb3cuZ2V0TmV4dFVuc2V0KGN1cnJlbnRQb3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRQb3M7XG4gICAgICAgIH1cbiAgICAgICAgLy8gbm90IHByaXZhdGUgZm9yIHRlc3RpbmdcbiAgICAgICAgcmV0cmlldmVOZXh0UGFpcihyb3csIHByZXZpb3VzUGFpcnMsIHJvd051bWJlcikge1xuICAgICAgICAgICAgbGV0IGlzT2RkUGF0dGVybiA9IHByZXZpb3VzUGFpcnMubGVuZ3RoICUgMiA9PSAwO1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhcnRGcm9tRXZlbikge1xuICAgICAgICAgICAgICAgIGlzT2RkUGF0dGVybiA9ICFpc09kZFBhdHRlcm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcGF0dGVybjtcbiAgICAgICAgICAgIGxldCBrZWVwRmluZGluZyA9IHRydWU7XG4gICAgICAgICAgICBsZXQgZm9yY2VkT2Zmc2V0ID0gLTE7XG4gICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgdGhpcy5maW5kTmV4dFBhaXIocm93LCBwcmV2aW91c1BhaXJzLCBmb3JjZWRPZmZzZXQpO1xuICAgICAgICAgICAgICAgIHBhdHRlcm4gPSB0aGlzLnBhcnNlRm91bmRGaW5kZXJQYXR0ZXJuKHJvdywgcm93TnVtYmVyLCBpc09kZFBhdHRlcm4pO1xuICAgICAgICAgICAgICAgIGlmIChwYXR0ZXJuID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yY2VkT2Zmc2V0ID0gUlNTRXhwYW5kZWRSZWFkZXIuZ2V0TmV4dFNlY29uZEJhcihyb3csIHRoaXMuc3RhcnRFbmRbMF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAga2VlcEZpbmRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IHdoaWxlIChrZWVwRmluZGluZyk7XG4gICAgICAgICAgICAvLyBXaGVuIHN0YWNrZWQgc3ltYm9sIGlzIHNwbGl0IG92ZXIgbXVsdGlwbGUgcm93cywgdGhlcmUncyBubyB3YXkgdG8gZ3Vlc3MgaWYgdGhpcyBwYWlyIGNhbiBiZSBsYXN0IG9yIG5vdC5cbiAgICAgICAgICAgIC8vIGJvb2xlYW4gbWF5QmVMYXN0ID0gY2hlY2tQYWlyU2VxdWVuY2UocHJldmlvdXNQYWlycywgcGF0dGVybik7XG4gICAgICAgICAgICBsZXQgbGVmdENoYXIgPSB0aGlzLmRlY29kZURhdGFDaGFyYWN0ZXIocm93LCBwYXR0ZXJuLCBpc09kZFBhdHRlcm4sIHRydWUpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmlzRW1wdHlQYWlyKHByZXZpb3VzUGFpcnMpICYmIHByZXZpb3VzUGFpcnNbcHJldmlvdXNQYWlycy5sZW5ndGggLSAxXS5tdXN0QmVMYXN0KCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCByaWdodENoYXI7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJpZ2h0Q2hhciA9IHRoaXMuZGVjb2RlRGF0YUNoYXJhY3Rlcihyb3csIHBhdHRlcm4sIGlzT2RkUGF0dGVybiwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByaWdodENoYXIgPSBudWxsO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnZlcmJvc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBFeHBhbmRlZFBhaXIobGVmdENoYXIsIHJpZ2h0Q2hhciwgcGF0dGVybiwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgaXNFbXB0eVBhaXIocGFpcnMpIHtcbiAgICAgICAgICAgIGlmIChwYWlycy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBmaW5kTmV4dFBhaXIocm93LCBwcmV2aW91c1BhaXJzLCBmb3JjZWRPZmZzZXQpIHtcbiAgICAgICAgICAgIGxldCBjb3VudGVycyA9IHRoaXMuZ2V0RGVjb2RlRmluZGVyQ291bnRlcnMoKTtcbiAgICAgICAgICAgIGNvdW50ZXJzWzBdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzFdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzJdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzNdID0gMDtcbiAgICAgICAgICAgIGxldCB3aWR0aCA9IHJvdy5nZXRTaXplKCk7XG4gICAgICAgICAgICBsZXQgcm93T2Zmc2V0O1xuICAgICAgICAgICAgaWYgKGZvcmNlZE9mZnNldCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgcm93T2Zmc2V0ID0gZm9yY2VkT2Zmc2V0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5pc0VtcHR5UGFpcihwcmV2aW91c1BhaXJzKSkge1xuICAgICAgICAgICAgICAgIHJvd09mZnNldCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBsZXQgbGFzdFBhaXIgPSBwcmV2aW91c1BhaXJzW3ByZXZpb3VzUGFpcnMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgcm93T2Zmc2V0ID0gbGFzdFBhaXIuZ2V0RmluZGVyUGF0dGVybigpLmdldFN0YXJ0RW5kKClbMV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc2VhcmNoaW5nRXZlblBhaXIgPSBwcmV2aW91c1BhaXJzLmxlbmd0aCAlIDIgIT0gMDtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXJ0RnJvbUV2ZW4pIHtcbiAgICAgICAgICAgICAgICBzZWFyY2hpbmdFdmVuUGFpciA9ICFzZWFyY2hpbmdFdmVuUGFpcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBpc1doaXRlID0gZmFsc2U7XG4gICAgICAgICAgICB3aGlsZSAocm93T2Zmc2V0IDwgd2lkdGgpIHtcbiAgICAgICAgICAgICAgICBpc1doaXRlID0gIXJvdy5nZXQocm93T2Zmc2V0KTtcbiAgICAgICAgICAgICAgICBpZiAoIWlzV2hpdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJvd09mZnNldCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGNvdW50ZXJQb3NpdGlvbiA9IDA7XG4gICAgICAgICAgICBsZXQgcGF0dGVyblN0YXJ0ID0gcm93T2Zmc2V0O1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IHJvd09mZnNldDsgeCA8IHdpZHRoOyB4KyspIHtcbiAgICAgICAgICAgICAgICBpZiAocm93LmdldCh4KSAhPSBpc1doaXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbl0rKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb3VudGVyUG9zaXRpb24gPT0gMykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlYXJjaGluZ0V2ZW5QYWlyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgUlNTRXhwYW5kZWRSZWFkZXIucmV2ZXJzZUNvdW50ZXJzKGNvdW50ZXJzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChSU1NFeHBhbmRlZFJlYWRlci5pc0ZpbmRlclBhdHRlcm4oY291bnRlcnMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGFydEVuZFswXSA9IHBhdHRlcm5TdGFydDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0RW5kWzFdID0geDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VhcmNoaW5nRXZlblBhaXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBSU1NFeHBhbmRlZFJlYWRlci5yZXZlcnNlQ291bnRlcnMoY291bnRlcnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVyblN0YXJ0ICs9IGNvdW50ZXJzWzBdICsgY291bnRlcnNbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1swXSA9IGNvdW50ZXJzWzJdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbMV0gPSBjb3VudGVyc1szXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzWzJdID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzWzNdID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJQb3NpdGlvbi0tO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlclBvc2l0aW9uKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbY291bnRlclBvc2l0aW9uXSA9IDE7XG4gICAgICAgICAgICAgICAgICAgIGlzV2hpdGUgPSAhaXNXaGl0ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgcmV2ZXJzZUNvdW50ZXJzKGNvdW50ZXJzKSB7XG4gICAgICAgICAgICBsZXQgbGVuZ3RoID0gY291bnRlcnMubGVuZ3RoO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGggLyAyOyArK2kpIHtcbiAgICAgICAgICAgICAgICBsZXQgdG1wID0gY291bnRlcnNbaV07XG4gICAgICAgICAgICAgICAgY291bnRlcnNbaV0gPSBjb3VudGVyc1tsZW5ndGggLSBpIC0gMV07XG4gICAgICAgICAgICAgICAgY291bnRlcnNbbGVuZ3RoIC0gaSAtIDFdID0gdG1wO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHBhcnNlRm91bmRGaW5kZXJQYXR0ZXJuKHJvdywgcm93TnVtYmVyLCBvZGRQYXR0ZXJuKSB7XG4gICAgICAgICAgICAvLyBBY3R1YWxseSB3ZSBmb3VuZCBlbGVtZW50cyAyLTUuXG4gICAgICAgICAgICBsZXQgZmlyc3RDb3VudGVyO1xuICAgICAgICAgICAgbGV0IHN0YXJ0O1xuICAgICAgICAgICAgbGV0IGVuZDtcbiAgICAgICAgICAgIGlmIChvZGRQYXR0ZXJuKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgcGF0dGVybiBudW1iZXIgaXMgb2RkLCB3ZSBuZWVkIHRvIGxvY2F0ZSBlbGVtZW50IDEgKmJlZm9yZSogdGhlIGN1cnJlbnQgYmxvY2suXG4gICAgICAgICAgICAgICAgbGV0IGZpcnN0RWxlbWVudFN0YXJ0ID0gdGhpcy5zdGFydEVuZFswXSAtIDE7XG4gICAgICAgICAgICAgICAgLy8gTG9jYXRlIGVsZW1lbnQgMVxuICAgICAgICAgICAgICAgIHdoaWxlIChmaXJzdEVsZW1lbnRTdGFydCA+PSAwICYmICFyb3cuZ2V0KGZpcnN0RWxlbWVudFN0YXJ0KSkge1xuICAgICAgICAgICAgICAgICAgICBmaXJzdEVsZW1lbnRTdGFydC0tO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmaXJzdEVsZW1lbnRTdGFydCsrO1xuICAgICAgICAgICAgICAgIGZpcnN0Q291bnRlciA9IHRoaXMuc3RhcnRFbmRbMF0gLSBmaXJzdEVsZW1lbnRTdGFydDtcbiAgICAgICAgICAgICAgICBzdGFydCA9IGZpcnN0RWxlbWVudFN0YXJ0O1xuICAgICAgICAgICAgICAgIGVuZCA9IHRoaXMuc3RhcnRFbmRbMV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBJZiBwYXR0ZXJuIG51bWJlciBpcyBldmVuLCB0aGUgcGF0dGVybiBpcyByZXZlcnNlZCwgc28gd2UgbmVlZCB0byBsb2NhdGUgZWxlbWVudCAxICphZnRlciogdGhlIGN1cnJlbnQgYmxvY2suXG4gICAgICAgICAgICAgICAgc3RhcnQgPSB0aGlzLnN0YXJ0RW5kWzBdO1xuICAgICAgICAgICAgICAgIGVuZCA9IHJvdy5nZXROZXh0VW5zZXQodGhpcy5zdGFydEVuZFsxXSArIDEpO1xuICAgICAgICAgICAgICAgIGZpcnN0Q291bnRlciA9IGVuZCAtIHRoaXMuc3RhcnRFbmRbMV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBNYWtlICdjb3VudGVycycgaG9sZCAxLTRcbiAgICAgICAgICAgIGxldCBjb3VudGVycyA9IHRoaXMuZ2V0RGVjb2RlRmluZGVyQ291bnRlcnMoKTtcbiAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkoY291bnRlcnMsIDAsIGNvdW50ZXJzLCAxLCBjb3VudGVycy5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgIGNvdW50ZXJzWzBdID0gZmlyc3RDb3VudGVyO1xuICAgICAgICAgICAgbGV0IHZhbHVlO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMucGFyc2VGaW5kZXJWYWx1ZShjb3VudGVycywgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVFRFUk5TKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyByZXR1cm4gbmV3IEZpbmRlclBhdHRlcm4odmFsdWUsIG5ldyBpbnRbXSB7IHN0YXJ0LCBlbmQgfSwgc3RhcnQsIGVuZCwgcm93TnVtYmVyfSk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEZpbmRlclBhdHRlcm4odmFsdWUsIFtzdGFydCwgZW5kXSwgc3RhcnQsIGVuZCwgcm93TnVtYmVyKTtcbiAgICAgICAgfVxuICAgICAgICBkZWNvZGVEYXRhQ2hhcmFjdGVyKHJvdywgcGF0dGVybiwgaXNPZGRQYXR0ZXJuLCBsZWZ0Q2hhcikge1xuICAgICAgICAgICAgbGV0IGNvdW50ZXJzID0gdGhpcy5nZXREYXRhQ2hhcmFjdGVyQ291bnRlcnMoKTtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgY291bnRlcnMubGVuZ3RoOyB4KyspIHtcbiAgICAgICAgICAgICAgICBjb3VudGVyc1t4XSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobGVmdENoYXIpIHtcbiAgICAgICAgICAgICAgICBSU1NFeHBhbmRlZFJlYWRlci5yZWNvcmRQYXR0ZXJuSW5SZXZlcnNlKHJvdywgcGF0dGVybi5nZXRTdGFydEVuZCgpWzBdLCBjb3VudGVycyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBSU1NFeHBhbmRlZFJlYWRlci5yZWNvcmRQYXR0ZXJuKHJvdywgcGF0dGVybi5nZXRTdGFydEVuZCgpWzFdLCBjb3VudGVycyk7XG4gICAgICAgICAgICAgICAgLy8gcmV2ZXJzZSBpdFxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBqID0gY291bnRlcnMubGVuZ3RoIC0gMTsgaSA8IGo7IGkrKywgai0tKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCB0ZW1wID0gY291bnRlcnNbaV07XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2ldID0gY291bnRlcnNbal07XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2pdID0gdGVtcDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IC8vIGNvdW50ZXJzW10gaGFzIHRoZSBwaXhlbHMgb2YgdGhlIG1vZHVsZVxuICAgICAgICAgICAgbGV0IG51bU1vZHVsZXMgPSAxNzsgLy8gbGVmdCBhbmQgcmlnaHQgZGF0YSBjaGFyYWN0ZXJzIGhhdmUgYWxsIHRoZSBzYW1lIGxlbmd0aFxuICAgICAgICAgICAgbGV0IGVsZW1lbnRXaWR0aCA9IE1hdGhVdGlscy5zdW0obmV3IEludDMyQXJyYXkoY291bnRlcnMpKSAvIG51bU1vZHVsZXM7XG4gICAgICAgICAgICAvLyBTYW5pdHkgY2hlY2s6IGVsZW1lbnQgd2lkdGggZm9yIHBhdHRlcm4gYW5kIHRoZSBjaGFyYWN0ZXIgc2hvdWxkIG1hdGNoXG4gICAgICAgICAgICBsZXQgZXhwZWN0ZWRFbGVtZW50V2lkdGggPSAocGF0dGVybi5nZXRTdGFydEVuZCgpWzFdIC0gcGF0dGVybi5nZXRTdGFydEVuZCgpWzBdKSAvIDE1LjA7XG4gICAgICAgICAgICBpZiAoTWF0aC5hYnMoZWxlbWVudFdpZHRoIC0gZXhwZWN0ZWRFbGVtZW50V2lkdGgpIC8gZXhwZWN0ZWRFbGVtZW50V2lkdGggPiAwLjMpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBvZGRDb3VudHMgPSB0aGlzLmdldE9kZENvdW50cygpO1xuICAgICAgICAgICAgbGV0IGV2ZW5Db3VudHMgPSB0aGlzLmdldEV2ZW5Db3VudHMoKTtcbiAgICAgICAgICAgIGxldCBvZGRSb3VuZGluZ0Vycm9ycyA9IHRoaXMuZ2V0T2RkUm91bmRpbmdFcnJvcnMoKTtcbiAgICAgICAgICAgIGxldCBldmVuUm91bmRpbmdFcnJvcnMgPSB0aGlzLmdldEV2ZW5Sb3VuZGluZ0Vycm9ycygpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudGVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCB2YWx1ZSA9IDEuMCAqIGNvdW50ZXJzW2ldIC8gZWxlbWVudFdpZHRoO1xuICAgICAgICAgICAgICAgIGxldCBjb3VudCA9IHZhbHVlICsgMC41OyAvLyBSb3VuZFxuICAgICAgICAgICAgICAgIGlmIChjb3VudCA8IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlIDwgMC4zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb3VudCA9IDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGNvdW50ID4gOCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUgPiA4LjcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ID0gODtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IG9mZnNldCA9IGkgLyAyO1xuICAgICAgICAgICAgICAgIGlmICgoaSAmIDB4MDEpID09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgb2RkQ291bnRzW29mZnNldF0gPSBjb3VudDtcbiAgICAgICAgICAgICAgICAgICAgb2RkUm91bmRpbmdFcnJvcnNbb2Zmc2V0XSA9IHZhbHVlIC0gY291bnQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBldmVuQ291bnRzW29mZnNldF0gPSBjb3VudDtcbiAgICAgICAgICAgICAgICAgICAgZXZlblJvdW5kaW5nRXJyb3JzW29mZnNldF0gPSB2YWx1ZSAtIGNvdW50O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuYWRqdXN0T2RkRXZlbkNvdW50cyhudW1Nb2R1bGVzKTtcbiAgICAgICAgICAgIGxldCB3ZWlnaHRSb3dOdW1iZXIgPSA0ICogcGF0dGVybi5nZXRWYWx1ZSgpICsgKGlzT2RkUGF0dGVybiA/IDAgOiAyKSArIChsZWZ0Q2hhciA/IDAgOiAxKSAtIDE7XG4gICAgICAgICAgICBsZXQgb2RkU3VtID0gMDtcbiAgICAgICAgICAgIGxldCBvZGRDaGVja3N1bVBvcnRpb24gPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IG9kZENvdW50cy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgICAgIGlmIChSU1NFeHBhbmRlZFJlYWRlci5pc05vdEExbGVmdChwYXR0ZXJuLCBpc09kZFBhdHRlcm4sIGxlZnRDaGFyKSkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgd2VpZ2h0ID0gUlNTRXhwYW5kZWRSZWFkZXIuV0VJR0hUU1t3ZWlnaHRSb3dOdW1iZXJdWzIgKiBpXTtcbiAgICAgICAgICAgICAgICAgICAgb2RkQ2hlY2tzdW1Qb3J0aW9uICs9IG9kZENvdW50c1tpXSAqIHdlaWdodDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgb2RkU3VtICs9IG9kZENvdW50c1tpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBldmVuQ2hlY2tzdW1Qb3J0aW9uID0gMDtcbiAgICAgICAgICAgIC8vIGludCBldmVuU3VtID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBldmVuQ291bnRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICAgICAgaWYgKFJTU0V4cGFuZGVkUmVhZGVyLmlzTm90QTFsZWZ0KHBhdHRlcm4sIGlzT2RkUGF0dGVybiwgbGVmdENoYXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCB3ZWlnaHQgPSBSU1NFeHBhbmRlZFJlYWRlci5XRUlHSFRTW3dlaWdodFJvd051bWJlcl1bMiAqIGkgKyAxXTtcbiAgICAgICAgICAgICAgICAgICAgZXZlbkNoZWNrc3VtUG9ydGlvbiArPSBldmVuQ291bnRzW2ldICogd2VpZ2h0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBldmVuU3VtICs9IGV2ZW5Db3VudHNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgY2hlY2tzdW1Qb3J0aW9uID0gb2RkQ2hlY2tzdW1Qb3J0aW9uICsgZXZlbkNoZWNrc3VtUG9ydGlvbjtcbiAgICAgICAgICAgIGlmICgob2RkU3VtICYgMHgwMSkgIT0gMCB8fCBvZGRTdW0gPiAxMyB8fCBvZGRTdW0gPCA0KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZ3JvdXAgPSAoMTMgLSBvZGRTdW0pIC8gMjtcbiAgICAgICAgICAgIGxldCBvZGRXaWRlc3QgPSBSU1NFeHBhbmRlZFJlYWRlci5TWU1CT0xfV0lERVNUW2dyb3VwXTtcbiAgICAgICAgICAgIGxldCBldmVuV2lkZXN0ID0gOSAtIG9kZFdpZGVzdDtcbiAgICAgICAgICAgIGxldCB2T2RkID0gUlNTVXRpbHMuZ2V0UlNTdmFsdWUob2RkQ291bnRzLCBvZGRXaWRlc3QsIHRydWUpO1xuICAgICAgICAgICAgbGV0IHZFdmVuID0gUlNTVXRpbHMuZ2V0UlNTdmFsdWUoZXZlbkNvdW50cywgZXZlbldpZGVzdCwgZmFsc2UpO1xuICAgICAgICAgICAgbGV0IHRFdmVuID0gUlNTRXhwYW5kZWRSZWFkZXIuRVZFTl9UT1RBTF9TVUJTRVRbZ3JvdXBdO1xuICAgICAgICAgICAgbGV0IGdTdW0gPSBSU1NFeHBhbmRlZFJlYWRlci5HU1VNW2dyb3VwXTtcbiAgICAgICAgICAgIGxldCB2YWx1ZSA9IHZPZGQgKiB0RXZlbiArIHZFdmVuICsgZ1N1bTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRGF0YUNoYXJhY3Rlcih2YWx1ZSwgY2hlY2tzdW1Qb3J0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgaXNOb3RBMWxlZnQocGF0dGVybiwgaXNPZGRQYXR0ZXJuLCBsZWZ0Q2hhcikge1xuICAgICAgICAgICAgLy8gQTE6IHBhdHRlcm4uZ2V0VmFsdWUgaXMgMCAoQSksIGFuZCBpdCdzIGFuIG9kZFBhdHRlcm4sIGFuZCBpdCBpcyBhIGxlZnQgY2hhclxuICAgICAgICAgICAgcmV0dXJuICEocGF0dGVybi5nZXRWYWx1ZSgpID09IDAgJiYgaXNPZGRQYXR0ZXJuICYmIGxlZnRDaGFyKTtcbiAgICAgICAgfVxuICAgICAgICBhZGp1c3RPZGRFdmVuQ291bnRzKG51bU1vZHVsZXMpIHtcbiAgICAgICAgICAgIGxldCBvZGRTdW0gPSBNYXRoVXRpbHMuc3VtKG5ldyBJbnQzMkFycmF5KHRoaXMuZ2V0T2RkQ291bnRzKCkpKTtcbiAgICAgICAgICAgIGxldCBldmVuU3VtID0gTWF0aFV0aWxzLnN1bShuZXcgSW50MzJBcnJheSh0aGlzLmdldEV2ZW5Db3VudHMoKSkpO1xuICAgICAgICAgICAgbGV0IGluY3JlbWVudE9kZCA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGRlY3JlbWVudE9kZCA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKG9kZFN1bSA+IDEzKSB7XG4gICAgICAgICAgICAgICAgZGVjcmVtZW50T2RkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKG9kZFN1bSA8IDQpIHtcbiAgICAgICAgICAgICAgICBpbmNyZW1lbnRPZGQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGluY3JlbWVudEV2ZW4gPSBmYWxzZTtcbiAgICAgICAgICAgIGxldCBkZWNyZW1lbnRFdmVuID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAoZXZlblN1bSA+IDEzKSB7XG4gICAgICAgICAgICAgICAgZGVjcmVtZW50RXZlbiA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChldmVuU3VtIDwgNCkge1xuICAgICAgICAgICAgICAgIGluY3JlbWVudEV2ZW4gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IG1pc21hdGNoID0gb2RkU3VtICsgZXZlblN1bSAtIG51bU1vZHVsZXM7XG4gICAgICAgICAgICBsZXQgb2RkUGFyaXR5QmFkID0gKG9kZFN1bSAmIDB4MDEpID09IDE7XG4gICAgICAgICAgICBsZXQgZXZlblBhcml0eUJhZCA9IChldmVuU3VtICYgMHgwMSkgPT0gMDtcbiAgICAgICAgICAgIGlmIChtaXNtYXRjaCA9PSAxKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9kZFBhcml0eUJhZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXZlblBhcml0eUJhZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZGVjcmVtZW50T2RkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZXZlblBhcml0eUJhZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZGVjcmVtZW50RXZlbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAobWlzbWF0Y2ggPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBpZiAob2RkUGFyaXR5QmFkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChldmVuUGFyaXR5QmFkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpbmNyZW1lbnRPZGQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFldmVuUGFyaXR5QmFkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpbmNyZW1lbnRFdmVuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChtaXNtYXRjaCA9PSAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9kZFBhcml0eUJhZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWV2ZW5QYXJpdHlCYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIEJvdGggYmFkXG4gICAgICAgICAgICAgICAgICAgIGlmIChvZGRTdW0gPCBldmVuU3VtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmNyZW1lbnRPZGQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVjcmVtZW50RXZlbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWNyZW1lbnRPZGQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5jcmVtZW50RXZlbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChldmVuUGFyaXR5QmFkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBOb3RoaW5nIHRvIGRvIVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGluY3JlbWVudE9kZCkge1xuICAgICAgICAgICAgICAgIGlmIChkZWNyZW1lbnRPZGQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIFJTU0V4cGFuZGVkUmVhZGVyLmluY3JlbWVudCh0aGlzLmdldE9kZENvdW50cygpLCB0aGlzLmdldE9kZFJvdW5kaW5nRXJyb3JzKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRlY3JlbWVudE9kZCkge1xuICAgICAgICAgICAgICAgIFJTU0V4cGFuZGVkUmVhZGVyLmRlY3JlbWVudCh0aGlzLmdldE9kZENvdW50cygpLCB0aGlzLmdldE9kZFJvdW5kaW5nRXJyb3JzKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGluY3JlbWVudEV2ZW4pIHtcbiAgICAgICAgICAgICAgICBpZiAoZGVjcmVtZW50RXZlbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgUlNTRXhwYW5kZWRSZWFkZXIuaW5jcmVtZW50KHRoaXMuZ2V0RXZlbkNvdW50cygpLCB0aGlzLmdldE9kZFJvdW5kaW5nRXJyb3JzKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRlY3JlbWVudEV2ZW4pIHtcbiAgICAgICAgICAgICAgICBSU1NFeHBhbmRlZFJlYWRlci5kZWNyZW1lbnQodGhpcy5nZXRFdmVuQ291bnRzKCksIHRoaXMuZ2V0RXZlblJvdW5kaW5nRXJyb3JzKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIFJTU0V4cGFuZGVkUmVhZGVyLlNZTUJPTF9XSURFU1QgPSBbNywgNSwgNCwgMywgMV07XG4gICAgUlNTRXhwYW5kZWRSZWFkZXIuRVZFTl9UT1RBTF9TVUJTRVQgPSBbNCwgMjAsIDUyLCAxMDQsIDIwNF07XG4gICAgUlNTRXhwYW5kZWRSZWFkZXIuR1NVTSA9IFswLCAzNDgsIDEzODgsIDI5NDgsIDM5ODhdO1xuICAgIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRURVJOUyA9IFtcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCA4LCA0LCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgNiwgNCwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDQsIDYsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAyLCA4LCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgNiwgNSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDIsIDksIDFdKSAvLyBGXG4gICAgXTtcbiAgICBSU1NFeHBhbmRlZFJlYWRlci5XRUlHSFRTID0gW1xuICAgICAgICBbMSwgMywgOSwgMjcsIDgxLCAzMiwgOTYsIDc3XSxcbiAgICAgICAgWzIwLCA2MCwgMTgwLCAxMTgsIDE0MywgNywgMjEsIDYzXSxcbiAgICAgICAgWzE4OSwgMTQ1LCAxMywgMzksIDExNywgMTQwLCAyMDksIDIwNV0sXG4gICAgICAgIFsxOTMsIDE1NywgNDksIDE0NywgMTksIDU3LCAxNzEsIDkxXSxcbiAgICAgICAgWzYyLCAxODYsIDEzNiwgMTk3LCAxNjksIDg1LCA0NCwgMTMyXSxcbiAgICAgICAgWzE4NSwgMTMzLCAxODgsIDE0MiwgNCwgMTIsIDM2LCAxMDhdLFxuICAgICAgICBbMTEzLCAxMjgsIDE3MywgOTcsIDgwLCAyOSwgODcsIDUwXSxcbiAgICAgICAgWzE1MCwgMjgsIDg0LCA0MSwgMTIzLCAxNTgsIDUyLCAxNTZdLFxuICAgICAgICBbNDYsIDEzOCwgMjAzLCAxODcsIDEzOSwgMjA2LCAxOTYsIDE2Nl0sXG4gICAgICAgIFs3NiwgMTcsIDUxLCAxNTMsIDM3LCAxMTEsIDEyMiwgMTU1XSxcbiAgICAgICAgWzQzLCAxMjksIDE3NiwgMTA2LCAxMDcsIDExMCwgMTE5LCAxNDZdLFxuICAgICAgICBbMTYsIDQ4LCAxNDQsIDEwLCAzMCwgOTAsIDU5LCAxNzddLFxuICAgICAgICBbMTA5LCAxMTYsIDEzNywgMjAwLCAxNzgsIDExMiwgMTI1LCAxNjRdLFxuICAgICAgICBbNzAsIDIxMCwgMjA4LCAyMDIsIDE4NCwgMTMwLCAxNzksIDExNV0sXG4gICAgICAgIFsxMzQsIDE5MSwgMTUxLCAzMSwgOTMsIDY4LCAyMDQsIDE5MF0sXG4gICAgICAgIFsxNDgsIDIyLCA2NiwgMTk4LCAxNzIsIDk0LCA3MSwgMl0sXG4gICAgICAgIFs2LCAxOCwgNTQsIDE2MiwgNjQsIDE5MiwgMTU0LCA0MF0sXG4gICAgICAgIFsxMjAsIDE0OSwgMjUsIDc1LCAxNCwgNDIsIDEyNiwgMTY3XSxcbiAgICAgICAgWzc5LCAyNiwgNzgsIDIzLCA2OSwgMjA3LCAxOTksIDE3NV0sXG4gICAgICAgIFsxMDMsIDk4LCA4MywgMzgsIDExNCwgMTMxLCAxODIsIDEyNF0sXG4gICAgICAgIFsxNjEsIDYxLCAxODMsIDEyNywgMTcwLCA4OCwgNTMsIDE1OV0sXG4gICAgICAgIFs1NSwgMTY1LCA3MywgOCwgMjQsIDcyLCA1LCAxNV0sXG4gICAgICAgIFs0NSwgMTM1LCAxOTQsIDE2MCwgNTgsIDE3NCwgMTAwLCA4OV1cbiAgICBdO1xuICAgIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQSA9IDA7XG4gICAgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9CID0gMTtcbiAgICBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0MgPSAyO1xuICAgIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRCA9IDM7XG4gICAgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9FID0gNDtcbiAgICBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0YgPSA1O1xuICAgIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRURVJOX1NFUVVFTkNFUyA9IFtcbiAgICAgICAgW1JTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQSwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9BXSxcbiAgICAgICAgW1JTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQSwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9CLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0JdLFxuICAgICAgICBbUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9BLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0MsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQiwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9EXSxcbiAgICAgICAgW1JTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQSwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9FLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0IsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRCwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9DXSxcbiAgICAgICAgW1JTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQSwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9FLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0IsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRCwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9ELCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0ZdLFxuICAgICAgICBbUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9BLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0UsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQiwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9ELCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0UsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRiwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9GXSxcbiAgICAgICAgW1JTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQSwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9BLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0IsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQiwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9DLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0MsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRCwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9EXSxcbiAgICAgICAgW1JTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQSwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9BLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0IsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQiwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9DLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0MsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRCwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9FLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0VdLFxuICAgICAgICBbUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9BLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0EsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQiwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9CLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0MsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQywgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9ELCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0UsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRiwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9GXSxcbiAgICAgICAgW1JTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQSwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9BLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0IsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfQiwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9DLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0QsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRCwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9FLCBSU1NFeHBhbmRlZFJlYWRlci5GSU5ERVJfUEFUX0UsIFJTU0V4cGFuZGVkUmVhZGVyLkZJTkRFUl9QQVRfRiwgUlNTRXhwYW5kZWRSZWFkZXIuRklOREVSX1BBVF9GXSxcbiAgICBdO1xuICAgIFJTU0V4cGFuZGVkUmVhZGVyLk1BWF9QQUlSUyA9IDExO1xuXG4gICAgY2xhc3MgUGFpciBleHRlbmRzIERhdGFDaGFyYWN0ZXIge1xuICAgICAgICBjb25zdHJ1Y3Rvcih2YWx1ZSwgY2hlY2tzdW1Qb3J0aW9uLCBmaW5kZXJQYXR0ZXJuKSB7XG4gICAgICAgICAgICBzdXBlcih2YWx1ZSwgY2hlY2tzdW1Qb3J0aW9uKTtcbiAgICAgICAgICAgIHRoaXMuY291bnQgPSAwO1xuICAgICAgICAgICAgdGhpcy5maW5kZXJQYXR0ZXJuID0gZmluZGVyUGF0dGVybjtcbiAgICAgICAgfVxuICAgICAgICBnZXRGaW5kZXJQYXR0ZXJuKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmluZGVyUGF0dGVybjtcbiAgICAgICAgfVxuICAgICAgICBnZXRDb3VudCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvdW50O1xuICAgICAgICB9XG4gICAgICAgIGluY3JlbWVudENvdW50KCkge1xuICAgICAgICAgICAgdGhpcy5jb3VudCsrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xhc3MgUlNTMTRSZWFkZXIgZXh0ZW5kcyBBYnN0cmFjdFJTU1JlYWRlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgICAgIHRoaXMucG9zc2libGVMZWZ0UGFpcnMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMucG9zc2libGVSaWdodFBhaXJzID0gW107XG4gICAgICAgIH1cbiAgICAgICAgZGVjb2RlUm93KHJvd051bWJlciwgcm93LCBoaW50cykge1xuICAgICAgICAgICAgY29uc3QgbGVmdFBhaXIgPSB0aGlzLmRlY29kZVBhaXIocm93LCBmYWxzZSwgcm93TnVtYmVyLCBoaW50cyk7XG4gICAgICAgICAgICBSU1MxNFJlYWRlci5hZGRPclRhbGx5KHRoaXMucG9zc2libGVMZWZ0UGFpcnMsIGxlZnRQYWlyKTtcbiAgICAgICAgICAgIHJvdy5yZXZlcnNlKCk7XG4gICAgICAgICAgICBsZXQgcmlnaHRQYWlyID0gdGhpcy5kZWNvZGVQYWlyKHJvdywgdHJ1ZSwgcm93TnVtYmVyLCBoaW50cyk7XG4gICAgICAgICAgICBSU1MxNFJlYWRlci5hZGRPclRhbGx5KHRoaXMucG9zc2libGVSaWdodFBhaXJzLCByaWdodFBhaXIpO1xuICAgICAgICAgICAgcm93LnJldmVyc2UoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGxlZnQgb2YgdGhpcy5wb3NzaWJsZUxlZnRQYWlycykge1xuICAgICAgICAgICAgICAgIGlmIChsZWZ0LmdldENvdW50KCkgPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IHJpZ2h0IG9mIHRoaXMucG9zc2libGVSaWdodFBhaXJzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHQuZ2V0Q291bnQoKSA+IDEgJiYgUlNTMTRSZWFkZXIuY2hlY2tDaGVja3N1bShsZWZ0LCByaWdodCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gUlNTMTRSZWFkZXIuY29uc3RydWN0UmVzdWx0KGxlZnQsIHJpZ2h0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBhZGRPclRhbGx5KHBvc3NpYmxlUGFpcnMsIHBhaXIpIHtcbiAgICAgICAgICAgIGlmIChwYWlyID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICAgICAgICAgIGZvciAobGV0IG90aGVyIG9mIHBvc3NpYmxlUGFpcnMpIHtcbiAgICAgICAgICAgICAgICBpZiAob3RoZXIuZ2V0VmFsdWUoKSA9PT0gcGFpci5nZXRWYWx1ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIG90aGVyLmluY3JlbWVudENvdW50KCk7XG4gICAgICAgICAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFmb3VuZCkge1xuICAgICAgICAgICAgICAgIHBvc3NpYmxlUGFpcnMucHVzaChwYWlyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXNldCgpIHtcbiAgICAgICAgICAgIHRoaXMucG9zc2libGVMZWZ0UGFpcnMubGVuZ3RoID0gMDtcbiAgICAgICAgICAgIHRoaXMucG9zc2libGVSaWdodFBhaXJzLmxlbmd0aCA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGNvbnN0cnVjdFJlc3VsdChsZWZ0UGFpciwgcmlnaHRQYWlyKSB7XG4gICAgICAgICAgICBsZXQgc3ltYm9sVmFsdWUgPSA0NTM3MDc3ICogbGVmdFBhaXIuZ2V0VmFsdWUoKSArIHJpZ2h0UGFpci5nZXRWYWx1ZSgpO1xuICAgICAgICAgICAgbGV0IHRleHQgPSBuZXcgU3RyaW5nKHN5bWJvbFZhbHVlKS50b1N0cmluZygpO1xuICAgICAgICAgICAgbGV0IGJ1ZmZlciA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMTMgLSB0ZXh0Lmxlbmd0aDsgaSA+IDA7IGktLSkge1xuICAgICAgICAgICAgICAgIGJ1ZmZlci5hcHBlbmQoJzAnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJ1ZmZlci5hcHBlbmQodGV4dCk7XG4gICAgICAgICAgICBsZXQgY2hlY2tEaWdpdCA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDEzOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgZGlnaXQgPSBidWZmZXIuY2hhckF0KGkpLmNoYXJDb2RlQXQoMCkgLSAnMCcuY2hhckNvZGVBdCgwKTtcbiAgICAgICAgICAgICAgICBjaGVja0RpZ2l0ICs9ICgoaSAmIDB4MDEpID09PSAwKSA/IDMgKiBkaWdpdCA6IGRpZ2l0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2hlY2tEaWdpdCA9IDEwIC0gKGNoZWNrRGlnaXQgJSAxMCk7XG4gICAgICAgICAgICBpZiAoY2hlY2tEaWdpdCA9PT0gMTApIHtcbiAgICAgICAgICAgICAgICBjaGVja0RpZ2l0ID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJ1ZmZlci5hcHBlbmQoY2hlY2tEaWdpdC50b1N0cmluZygpKTtcbiAgICAgICAgICAgIGxldCBsZWZ0UG9pbnRzID0gbGVmdFBhaXIuZ2V0RmluZGVyUGF0dGVybigpLmdldFJlc3VsdFBvaW50cygpO1xuICAgICAgICAgICAgbGV0IHJpZ2h0UG9pbnRzID0gcmlnaHRQYWlyLmdldEZpbmRlclBhdHRlcm4oKS5nZXRSZXN1bHRQb2ludHMoKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUmVzdWx0KGJ1ZmZlci50b1N0cmluZygpLCBudWxsLCAwLCBbbGVmdFBvaW50c1swXSwgbGVmdFBvaW50c1sxXSwgcmlnaHRQb2ludHNbMF0sIHJpZ2h0UG9pbnRzWzFdXSwgQmFyY29kZUZvcm1hdCQxLlJTU18xNCwgbmV3IERhdGUoKS5nZXRUaW1lKCkpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBjaGVja0NoZWNrc3VtKGxlZnRQYWlyLCByaWdodFBhaXIpIHtcbiAgICAgICAgICAgIGxldCBjaGVja1ZhbHVlID0gKGxlZnRQYWlyLmdldENoZWNrc3VtUG9ydGlvbigpICsgMTYgKiByaWdodFBhaXIuZ2V0Q2hlY2tzdW1Qb3J0aW9uKCkpICUgNzk7XG4gICAgICAgICAgICBsZXQgdGFyZ2V0Q2hlY2tWYWx1ZSA9IDkgKiBsZWZ0UGFpci5nZXRGaW5kZXJQYXR0ZXJuKCkuZ2V0VmFsdWUoKSArIHJpZ2h0UGFpci5nZXRGaW5kZXJQYXR0ZXJuKCkuZ2V0VmFsdWUoKTtcbiAgICAgICAgICAgIGlmICh0YXJnZXRDaGVja1ZhbHVlID4gNzIpIHtcbiAgICAgICAgICAgICAgICB0YXJnZXRDaGVja1ZhbHVlLS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGFyZ2V0Q2hlY2tWYWx1ZSA+IDgpIHtcbiAgICAgICAgICAgICAgICB0YXJnZXRDaGVja1ZhbHVlLS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY2hlY2tWYWx1ZSA9PT0gdGFyZ2V0Q2hlY2tWYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBkZWNvZGVQYWlyKHJvdywgcmlnaHQsIHJvd051bWJlciwgaGludHMpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbGV0IHN0YXJ0RW5kID0gdGhpcy5maW5kRmluZGVyUGF0dGVybihyb3csIHJpZ2h0KTtcbiAgICAgICAgICAgICAgICBsZXQgcGF0dGVybiA9IHRoaXMucGFyc2VGb3VuZEZpbmRlclBhdHRlcm4ocm93LCByb3dOdW1iZXIsIHJpZ2h0LCBzdGFydEVuZCk7XG4gICAgICAgICAgICAgICAgbGV0IHJlc3VsdFBvaW50Q2FsbGJhY2sgPSBoaW50cyA9PSBudWxsID8gbnVsbCA6IGhpbnRzLmdldChEZWNvZGVIaW50VHlwZSQxLk5FRURfUkVTVUxUX1BPSU5UX0NBTExCQUNLKTtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0UG9pbnRDYWxsYmFjayAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBjZW50ZXIgPSAoc3RhcnRFbmRbMF0gKyBzdGFydEVuZFsxXSkgLyAyLjA7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcm93IGlzIGFjdHVhbGx5IHJldmVyc2VkXG4gICAgICAgICAgICAgICAgICAgICAgICBjZW50ZXIgPSByb3cuZ2V0U2l6ZSgpIC0gMSAtIGNlbnRlcjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXN1bHRQb2ludENhbGxiYWNrLmZvdW5kUG9zc2libGVSZXN1bHRQb2ludChuZXcgUmVzdWx0UG9pbnQoY2VudGVyLCByb3dOdW1iZXIpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IG91dHNpZGUgPSB0aGlzLmRlY29kZURhdGFDaGFyYWN0ZXIocm93LCBwYXR0ZXJuLCB0cnVlKTtcbiAgICAgICAgICAgICAgICBsZXQgaW5zaWRlID0gdGhpcy5kZWNvZGVEYXRhQ2hhcmFjdGVyKHJvdywgcGF0dGVybiwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUGFpcigxNTk3ICogb3V0c2lkZS5nZXRWYWx1ZSgpICsgaW5zaWRlLmdldFZhbHVlKCksIG91dHNpZGUuZ2V0Q2hlY2tzdW1Qb3J0aW9uKCkgKyA0ICogaW5zaWRlLmdldENoZWNrc3VtUG9ydGlvbigpLCBwYXR0ZXJuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBkZWNvZGVEYXRhQ2hhcmFjdGVyKHJvdywgcGF0dGVybiwgb3V0c2lkZUNoYXIpIHtcbiAgICAgICAgICAgIGxldCBjb3VudGVycyA9IHRoaXMuZ2V0RGF0YUNoYXJhY3RlckNvdW50ZXJzKCk7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IGNvdW50ZXJzLmxlbmd0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgY291bnRlcnNbeF0gPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG91dHNpZGVDaGFyKSB7XG4gICAgICAgICAgICAgICAgT25lRFJlYWRlci5yZWNvcmRQYXR0ZXJuSW5SZXZlcnNlKHJvdywgcGF0dGVybi5nZXRTdGFydEVuZCgpWzBdLCBjb3VudGVycyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBPbmVEUmVhZGVyLnJlY29yZFBhdHRlcm4ocm93LCBwYXR0ZXJuLmdldFN0YXJ0RW5kKClbMV0gKyAxLCBjb3VudGVycyk7XG4gICAgICAgICAgICAgICAgLy8gcmV2ZXJzZSBpdFxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBqID0gY291bnRlcnMubGVuZ3RoIC0gMTsgaSA8IGo7IGkrKywgai0tKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCB0ZW1wID0gY291bnRlcnNbaV07XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2ldID0gY291bnRlcnNbal07XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2pdID0gdGVtcDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgbnVtTW9kdWxlcyA9IG91dHNpZGVDaGFyID8gMTYgOiAxNTtcbiAgICAgICAgICAgIGxldCBlbGVtZW50V2lkdGggPSBNYXRoVXRpbHMuc3VtKG5ldyBJbnQzMkFycmF5KGNvdW50ZXJzKSkgLyBudW1Nb2R1bGVzO1xuICAgICAgICAgICAgbGV0IG9kZENvdW50cyA9IHRoaXMuZ2V0T2RkQ291bnRzKCk7XG4gICAgICAgICAgICBsZXQgZXZlbkNvdW50cyA9IHRoaXMuZ2V0RXZlbkNvdW50cygpO1xuICAgICAgICAgICAgbGV0IG9kZFJvdW5kaW5nRXJyb3JzID0gdGhpcy5nZXRPZGRSb3VuZGluZ0Vycm9ycygpO1xuICAgICAgICAgICAgbGV0IGV2ZW5Sb3VuZGluZ0Vycm9ycyA9IHRoaXMuZ2V0RXZlblJvdW5kaW5nRXJyb3JzKCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IHZhbHVlID0gY291bnRlcnNbaV0gLyBlbGVtZW50V2lkdGg7XG4gICAgICAgICAgICAgICAgbGV0IGNvdW50ID0gTWF0aC5mbG9vcih2YWx1ZSArIDAuNSk7XG4gICAgICAgICAgICAgICAgaWYgKGNvdW50IDwgMSkge1xuICAgICAgICAgICAgICAgICAgICBjb3VudCA9IDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGNvdW50ID4gOCkge1xuICAgICAgICAgICAgICAgICAgICBjb3VudCA9IDg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCBvZmZzZXQgPSBNYXRoLmZsb29yKGkgLyAyKTtcbiAgICAgICAgICAgICAgICBpZiAoKGkgJiAweDAxKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBvZGRDb3VudHNbb2Zmc2V0XSA9IGNvdW50O1xuICAgICAgICAgICAgICAgICAgICBvZGRSb3VuZGluZ0Vycm9yc1tvZmZzZXRdID0gdmFsdWUgLSBjb3VudDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW5Db3VudHNbb2Zmc2V0XSA9IGNvdW50O1xuICAgICAgICAgICAgICAgICAgICBldmVuUm91bmRpbmdFcnJvcnNbb2Zmc2V0XSA9IHZhbHVlIC0gY291bnQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5hZGp1c3RPZGRFdmVuQ291bnRzKG91dHNpZGVDaGFyLCBudW1Nb2R1bGVzKTtcbiAgICAgICAgICAgIGxldCBvZGRTdW0gPSAwO1xuICAgICAgICAgICAgbGV0IG9kZENoZWNrc3VtUG9ydGlvbiA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gb2RkQ291bnRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICAgICAgb2RkQ2hlY2tzdW1Qb3J0aW9uICo9IDk7XG4gICAgICAgICAgICAgICAgb2RkQ2hlY2tzdW1Qb3J0aW9uICs9IG9kZENvdW50c1tpXTtcbiAgICAgICAgICAgICAgICBvZGRTdW0gKz0gb2RkQ291bnRzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGV2ZW5DaGVja3N1bVBvcnRpb24gPSAwO1xuICAgICAgICAgICAgbGV0IGV2ZW5TdW0gPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGV2ZW5Db3VudHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgICAgICBldmVuQ2hlY2tzdW1Qb3J0aW9uICo9IDk7XG4gICAgICAgICAgICAgICAgZXZlbkNoZWNrc3VtUG9ydGlvbiArPSBldmVuQ291bnRzW2ldO1xuICAgICAgICAgICAgICAgIGV2ZW5TdW0gKz0gZXZlbkNvdW50c1tpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBjaGVja3N1bVBvcnRpb24gPSBvZGRDaGVja3N1bVBvcnRpb24gKyAzICogZXZlbkNoZWNrc3VtUG9ydGlvbjtcbiAgICAgICAgICAgIGlmIChvdXRzaWRlQ2hhcikge1xuICAgICAgICAgICAgICAgIGlmICgob2RkU3VtICYgMHgwMSkgIT09IDAgfHwgb2RkU3VtID4gMTIgfHwgb2RkU3VtIDwgNCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IGdyb3VwID0gKDEyIC0gb2RkU3VtKSAvIDI7XG4gICAgICAgICAgICAgICAgbGV0IG9kZFdpZGVzdCA9IFJTUzE0UmVhZGVyLk9VVFNJREVfT0REX1dJREVTVFtncm91cF07XG4gICAgICAgICAgICAgICAgbGV0IGV2ZW5XaWRlc3QgPSA5IC0gb2RkV2lkZXN0O1xuICAgICAgICAgICAgICAgIGxldCB2T2RkID0gUlNTVXRpbHMuZ2V0UlNTdmFsdWUob2RkQ291bnRzLCBvZGRXaWRlc3QsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICBsZXQgdkV2ZW4gPSBSU1NVdGlscy5nZXRSU1N2YWx1ZShldmVuQ291bnRzLCBldmVuV2lkZXN0LCB0cnVlKTtcbiAgICAgICAgICAgICAgICBsZXQgdEV2ZW4gPSBSU1MxNFJlYWRlci5PVVRTSURFX0VWRU5fVE9UQUxfU1VCU0VUW2dyb3VwXTtcbiAgICAgICAgICAgICAgICBsZXQgZ1N1bSA9IFJTUzE0UmVhZGVyLk9VVFNJREVfR1NVTVtncm91cF07XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBEYXRhQ2hhcmFjdGVyKHZPZGQgKiB0RXZlbiArIHZFdmVuICsgZ1N1bSwgY2hlY2tzdW1Qb3J0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICgoZXZlblN1bSAmIDB4MDEpICE9PSAwIHx8IGV2ZW5TdW0gPiAxMCB8fCBldmVuU3VtIDwgNCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IGdyb3VwID0gKDEwIC0gZXZlblN1bSkgLyAyO1xuICAgICAgICAgICAgICAgIGxldCBvZGRXaWRlc3QgPSBSU1MxNFJlYWRlci5JTlNJREVfT0REX1dJREVTVFtncm91cF07XG4gICAgICAgICAgICAgICAgbGV0IGV2ZW5XaWRlc3QgPSA5IC0gb2RkV2lkZXN0O1xuICAgICAgICAgICAgICAgIGxldCB2T2RkID0gUlNTVXRpbHMuZ2V0UlNTdmFsdWUob2RkQ291bnRzLCBvZGRXaWRlc3QsIHRydWUpO1xuICAgICAgICAgICAgICAgIGxldCB2RXZlbiA9IFJTU1V0aWxzLmdldFJTU3ZhbHVlKGV2ZW5Db3VudHMsIGV2ZW5XaWRlc3QsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICBsZXQgdE9kZCA9IFJTUzE0UmVhZGVyLklOU0lERV9PRERfVE9UQUxfU1VCU0VUW2dyb3VwXTtcbiAgICAgICAgICAgICAgICBsZXQgZ1N1bSA9IFJTUzE0UmVhZGVyLklOU0lERV9HU1VNW2dyb3VwXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERhdGFDaGFyYWN0ZXIodkV2ZW4gKiB0T2RkICsgdk9kZCArIGdTdW0sIGNoZWNrc3VtUG9ydGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZmluZEZpbmRlclBhdHRlcm4ocm93LCByaWdodEZpbmRlclBhdHRlcm4pIHtcbiAgICAgICAgICAgIGxldCBjb3VudGVycyA9IHRoaXMuZ2V0RGVjb2RlRmluZGVyQ291bnRlcnMoKTtcbiAgICAgICAgICAgIGNvdW50ZXJzWzBdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzFdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzJdID0gMDtcbiAgICAgICAgICAgIGNvdW50ZXJzWzNdID0gMDtcbiAgICAgICAgICAgIGxldCB3aWR0aCA9IHJvdy5nZXRTaXplKCk7XG4gICAgICAgICAgICBsZXQgaXNXaGl0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IHJvd09mZnNldCA9IDA7XG4gICAgICAgICAgICB3aGlsZSAocm93T2Zmc2V0IDwgd2lkdGgpIHtcbiAgICAgICAgICAgICAgICBpc1doaXRlID0gIXJvdy5nZXQocm93T2Zmc2V0KTtcbiAgICAgICAgICAgICAgICBpZiAocmlnaHRGaW5kZXJQYXR0ZXJuID09PSBpc1doaXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdpbGwgZW5jb3VudGVyIHdoaXRlIGZpcnN0IHdoZW4gc2VhcmNoaW5nIGZvciByaWdodCBmaW5kZXIgcGF0dGVyblxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcm93T2Zmc2V0Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgY291bnRlclBvc2l0aW9uID0gMDtcbiAgICAgICAgICAgIGxldCBwYXR0ZXJuU3RhcnQgPSByb3dPZmZzZXQ7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gcm93T2Zmc2V0OyB4IDwgd2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgIGlmIChyb3cuZ2V0KHgpICE9PSBpc1doaXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbl0rKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb3VudGVyUG9zaXRpb24gPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChBYnN0cmFjdFJTU1JlYWRlci5pc0ZpbmRlclBhdHRlcm4oY291bnRlcnMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtwYXR0ZXJuU3RhcnQsIHhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVyblN0YXJ0ICs9IGNvdW50ZXJzWzBdICsgY291bnRlcnNbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1swXSA9IGNvdW50ZXJzWzJdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbMV0gPSBjb3VudGVyc1szXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzWzJdID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzWzNdID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJQb3NpdGlvbi0tO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlclBvc2l0aW9uKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbY291bnRlclBvc2l0aW9uXSA9IDE7XG4gICAgICAgICAgICAgICAgICAgIGlzV2hpdGUgPSAhaXNXaGl0ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgfVxuICAgICAgICBwYXJzZUZvdW5kRmluZGVyUGF0dGVybihyb3csIHJvd051bWJlciwgcmlnaHQsIHN0YXJ0RW5kKSB7XG4gICAgICAgICAgICAvLyBBY3R1YWxseSB3ZSBmb3VuZCBlbGVtZW50cyAyLTVcbiAgICAgICAgICAgIGxldCBmaXJzdElzQmxhY2sgPSByb3cuZ2V0KHN0YXJ0RW5kWzBdKTtcbiAgICAgICAgICAgIGxldCBmaXJzdEVsZW1lbnRTdGFydCA9IHN0YXJ0RW5kWzBdIC0gMTtcbiAgICAgICAgICAgIC8vIExvY2F0ZSBlbGVtZW50IDFcbiAgICAgICAgICAgIHdoaWxlIChmaXJzdEVsZW1lbnRTdGFydCA+PSAwICYmIGZpcnN0SXNCbGFjayAhPT0gcm93LmdldChmaXJzdEVsZW1lbnRTdGFydCkpIHtcbiAgICAgICAgICAgICAgICBmaXJzdEVsZW1lbnRTdGFydC0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZmlyc3RFbGVtZW50U3RhcnQrKztcbiAgICAgICAgICAgIGNvbnN0IGZpcnN0Q291bnRlciA9IHN0YXJ0RW5kWzBdIC0gZmlyc3RFbGVtZW50U3RhcnQ7XG4gICAgICAgICAgICAvLyBNYWtlICdjb3VudGVycycgaG9sZCAxLTRcbiAgICAgICAgICAgIGNvbnN0IGNvdW50ZXJzID0gdGhpcy5nZXREZWNvZGVGaW5kZXJDb3VudGVycygpO1xuICAgICAgICAgICAgY29uc3QgY29weSA9IG5ldyBJbnQzMkFycmF5KGNvdW50ZXJzLmxlbmd0aCk7XG4gICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KGNvdW50ZXJzLCAwLCBjb3B5LCAxLCBjb3VudGVycy5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgIGNvcHlbMF0gPSBmaXJzdENvdW50ZXI7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHRoaXMucGFyc2VGaW5kZXJWYWx1ZShjb3B5LCBSU1MxNFJlYWRlci5GSU5ERVJfUEFUVEVSTlMpO1xuICAgICAgICAgICAgbGV0IHN0YXJ0ID0gZmlyc3RFbGVtZW50U3RhcnQ7XG4gICAgICAgICAgICBsZXQgZW5kID0gc3RhcnRFbmRbMV07XG4gICAgICAgICAgICBpZiAocmlnaHQpIHtcbiAgICAgICAgICAgICAgICAvLyByb3cgaXMgYWN0dWFsbHkgcmV2ZXJzZWRcbiAgICAgICAgICAgICAgICBzdGFydCA9IHJvdy5nZXRTaXplKCkgLSAxIC0gc3RhcnQ7XG4gICAgICAgICAgICAgICAgZW5kID0gcm93LmdldFNpemUoKSAtIDEgLSBlbmQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IEZpbmRlclBhdHRlcm4odmFsdWUsIFtmaXJzdEVsZW1lbnRTdGFydCwgc3RhcnRFbmRbMV1dLCBzdGFydCwgZW5kLCByb3dOdW1iZXIpO1xuICAgICAgICB9XG4gICAgICAgIGFkanVzdE9kZEV2ZW5Db3VudHMob3V0c2lkZUNoYXIsIG51bU1vZHVsZXMpIHtcbiAgICAgICAgICAgIGxldCBvZGRTdW0gPSBNYXRoVXRpbHMuc3VtKG5ldyBJbnQzMkFycmF5KHRoaXMuZ2V0T2RkQ291bnRzKCkpKTtcbiAgICAgICAgICAgIGxldCBldmVuU3VtID0gTWF0aFV0aWxzLnN1bShuZXcgSW50MzJBcnJheSh0aGlzLmdldEV2ZW5Db3VudHMoKSkpO1xuICAgICAgICAgICAgbGV0IGluY3JlbWVudE9kZCA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGRlY3JlbWVudE9kZCA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGluY3JlbWVudEV2ZW4gPSBmYWxzZTtcbiAgICAgICAgICAgIGxldCBkZWNyZW1lbnRFdmVuID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAob3V0c2lkZUNoYXIpIHtcbiAgICAgICAgICAgICAgICBpZiAob2RkU3VtID4gMTIpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVjcmVtZW50T2RkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAob2RkU3VtIDwgNCkge1xuICAgICAgICAgICAgICAgICAgICBpbmNyZW1lbnRPZGQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZXZlblN1bSA+IDEyKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlY3JlbWVudEV2ZW4gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChldmVuU3VtIDwgNCkge1xuICAgICAgICAgICAgICAgICAgICBpbmNyZW1lbnRFdmVuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAob2RkU3VtID4gMTEpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVjcmVtZW50T2RkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAob2RkU3VtIDwgNSkge1xuICAgICAgICAgICAgICAgICAgICBpbmNyZW1lbnRPZGQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZXZlblN1bSA+IDEwKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlY3JlbWVudEV2ZW4gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChldmVuU3VtIDwgNCkge1xuICAgICAgICAgICAgICAgICAgICBpbmNyZW1lbnRFdmVuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgbWlzbWF0Y2ggPSBvZGRTdW0gKyBldmVuU3VtIC0gbnVtTW9kdWxlcztcbiAgICAgICAgICAgIGxldCBvZGRQYXJpdHlCYWQgPSAob2RkU3VtICYgMHgwMSkgPT09IChvdXRzaWRlQ2hhciA/IDEgOiAwKTtcbiAgICAgICAgICAgIGxldCBldmVuUGFyaXR5QmFkID0gKGV2ZW5TdW0gJiAweDAxKSA9PT0gMTtcbiAgICAgICAgICAgIGlmIChtaXNtYXRjaCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIGlmIChvZGRQYXJpdHlCYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW5QYXJpdHlCYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRlY3JlbWVudE9kZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWV2ZW5QYXJpdHlCYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRlY3JlbWVudEV2ZW4gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKG1pc21hdGNoID09PSAtMSkge1xuICAgICAgICAgICAgICAgIGlmIChvZGRQYXJpdHlCYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW5QYXJpdHlCYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGluY3JlbWVudE9kZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWV2ZW5QYXJpdHlCYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGluY3JlbWVudEV2ZW4gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKG1pc21hdGNoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9kZFBhcml0eUJhZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWV2ZW5QYXJpdHlCYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIEJvdGggYmFkXG4gICAgICAgICAgICAgICAgICAgIGlmIChvZGRTdW0gPCBldmVuU3VtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmNyZW1lbnRPZGQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVjcmVtZW50RXZlbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWNyZW1lbnRPZGQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5jcmVtZW50RXZlbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChldmVuUGFyaXR5QmFkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBOb3RoaW5nIHRvIGRvIVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGluY3JlbWVudE9kZCkge1xuICAgICAgICAgICAgICAgIGlmIChkZWNyZW1lbnRPZGQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIEFic3RyYWN0UlNTUmVhZGVyLmluY3JlbWVudCh0aGlzLmdldE9kZENvdW50cygpLCB0aGlzLmdldE9kZFJvdW5kaW5nRXJyb3JzKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRlY3JlbWVudE9kZCkge1xuICAgICAgICAgICAgICAgIEFic3RyYWN0UlNTUmVhZGVyLmRlY3JlbWVudCh0aGlzLmdldE9kZENvdW50cygpLCB0aGlzLmdldE9kZFJvdW5kaW5nRXJyb3JzKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGluY3JlbWVudEV2ZW4pIHtcbiAgICAgICAgICAgICAgICBpZiAoZGVjcmVtZW50RXZlbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgQWJzdHJhY3RSU1NSZWFkZXIuaW5jcmVtZW50KHRoaXMuZ2V0RXZlbkNvdW50cygpLCB0aGlzLmdldE9kZFJvdW5kaW5nRXJyb3JzKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRlY3JlbWVudEV2ZW4pIHtcbiAgICAgICAgICAgICAgICBBYnN0cmFjdFJTU1JlYWRlci5kZWNyZW1lbnQodGhpcy5nZXRFdmVuQ291bnRzKCksIHRoaXMuZ2V0RXZlblJvdW5kaW5nRXJyb3JzKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIFJTUzE0UmVhZGVyLk9VVFNJREVfRVZFTl9UT1RBTF9TVUJTRVQgPSBbMSwgMTAsIDM0LCA3MCwgMTI2XTtcbiAgICBSU1MxNFJlYWRlci5JTlNJREVfT0REX1RPVEFMX1NVQlNFVCA9IFs0LCAyMCwgNDgsIDgxXTtcbiAgICBSU1MxNFJlYWRlci5PVVRTSURFX0dTVU0gPSBbMCwgMTYxLCA5NjEsIDIwMTUsIDI3MTVdO1xuICAgIFJTUzE0UmVhZGVyLklOU0lERV9HU1VNID0gWzAsIDMzNiwgMTAzNiwgMTUxNl07XG4gICAgUlNTMTRSZWFkZXIuT1VUU0lERV9PRERfV0lERVNUID0gWzgsIDYsIDQsIDMsIDFdO1xuICAgIFJTUzE0UmVhZGVyLklOU0lERV9PRERfV0lERVNUID0gWzIsIDQsIDYsIDhdO1xuICAgIFJTUzE0UmVhZGVyLkZJTkRFUl9QQVRURVJOUyA9IFtcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCA4LCAyLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMywgNSwgNSwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDMsIDcsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFszLCAxLCA5LCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMiwgNywgNCwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzIsIDUsIDYsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCAzLCA4LCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgNSwgNywgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDMsIDksIDFdKSxcbiAgICBdO1xuXG4gICAgLyoqXG4gICAgICogQGF1dGhvciBEYW5pZWwgU3dpdGtpbiA8ZHN3aXRraW5AZ29vZ2xlLmNvbT5cbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIE11bHRpRm9ybWF0T25lRFJlYWRlciBleHRlbmRzIE9uZURSZWFkZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcihoaW50cywgdmVyYm9zZSkge1xuICAgICAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgICAgIHRoaXMucmVhZGVycyA9IFtdO1xuICAgICAgICAgICAgdGhpcy52ZXJib3NlID0gKHZlcmJvc2UgPT09IHRydWUpO1xuICAgICAgICAgICAgY29uc3QgcG9zc2libGVGb3JtYXRzID0gIWhpbnRzID8gbnVsbCA6IGhpbnRzLmdldChEZWNvZGVIaW50VHlwZSQxLlBPU1NJQkxFX0ZPUk1BVFMpO1xuICAgICAgICAgICAgY29uc3QgdXNlQ29kZTM5Q2hlY2tEaWdpdCA9IGhpbnRzICYmIGhpbnRzLmdldChEZWNvZGVIaW50VHlwZSQxLkFTU1VNRV9DT0RFXzM5X0NIRUNLX0RJR0lUKSAhPT0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgaWYgKHBvc3NpYmxlRm9ybWF0cykge1xuICAgICAgICAgICAgICAgIGlmIChwb3NzaWJsZUZvcm1hdHMuaW5jbHVkZXMoQmFyY29kZUZvcm1hdCQxLkVBTl8xMykgfHxcbiAgICAgICAgICAgICAgICAgICAgcG9zc2libGVGb3JtYXRzLmluY2x1ZGVzKEJhcmNvZGVGb3JtYXQkMS5VUENfQSkgfHxcbiAgICAgICAgICAgICAgICAgICAgcG9zc2libGVGb3JtYXRzLmluY2x1ZGVzKEJhcmNvZGVGb3JtYXQkMS5FQU5fOCkgfHxcbiAgICAgICAgICAgICAgICAgICAgcG9zc2libGVGb3JtYXRzLmluY2x1ZGVzKEJhcmNvZGVGb3JtYXQkMS5VUENfRSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWFkZXJzLnB1c2gobmV3IE11bHRpRm9ybWF0VVBDRUFOUmVhZGVyKGhpbnRzKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChwb3NzaWJsZUZvcm1hdHMuaW5jbHVkZXMoQmFyY29kZUZvcm1hdCQxLkNPREVfMzkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVhZGVycy5wdXNoKG5ldyBDb2RlMzlSZWFkZXIodXNlQ29kZTM5Q2hlY2tEaWdpdCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBpZiAocG9zc2libGVGb3JtYXRzLmluY2x1ZGVzKEJhcmNvZGVGb3JtYXQuQ09ERV85MykpIHtcbiAgICAgICAgICAgICAgICAvLyAgICB0aGlzLnJlYWRlcnMucHVzaChuZXcgQ29kZTkzUmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgICAgICBpZiAocG9zc2libGVGb3JtYXRzLmluY2x1ZGVzKEJhcmNvZGVGb3JtYXQkMS5DT0RFXzEyOCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWFkZXJzLnB1c2gobmV3IENvZGUxMjhSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChwb3NzaWJsZUZvcm1hdHMuaW5jbHVkZXMoQmFyY29kZUZvcm1hdCQxLklURikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWFkZXJzLnB1c2gobmV3IElURlJlYWRlcigpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gaWYgKHBvc3NpYmxlRm9ybWF0cy5pbmNsdWRlcyhCYXJjb2RlRm9ybWF0LkNPREFCQVIpKSB7XG4gICAgICAgICAgICAgICAgLy8gICAgdGhpcy5yZWFkZXJzLnB1c2gobmV3IENvZGFCYXJSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgLy8gfVxuICAgICAgICAgICAgICAgIGlmIChwb3NzaWJsZUZvcm1hdHMuaW5jbHVkZXMoQmFyY29kZUZvcm1hdCQxLlJTU18xNCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWFkZXJzLnB1c2gobmV3IFJTUzE0UmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocG9zc2libGVGb3JtYXRzLmluY2x1ZGVzKEJhcmNvZGVGb3JtYXQkMS5SU1NfRVhQQU5ERUQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVhZGVycy5wdXNoKG5ldyBSU1NFeHBhbmRlZFJlYWRlcih0aGlzLnZlcmJvc2UpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIENhc2Ugd2hlbiBubyBoaW50cyB3ZXJlIHByb3ZpZGVkIC0+IGFkZCBhbGwuXG4gICAgICAgICAgICAgICAgdGhpcy5yZWFkZXJzLnB1c2gobmV3IE11bHRpRm9ybWF0VVBDRUFOUmVhZGVyKGhpbnRzKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFkZXJzLnB1c2gobmV3IENvZGUzOVJlYWRlcigpKTtcbiAgICAgICAgICAgICAgICAvLyB0aGlzLnJlYWRlcnMucHVzaChuZXcgQ29kYUJhclJlYWRlcigpKTtcbiAgICAgICAgICAgICAgICAvLyB0aGlzLnJlYWRlcnMucHVzaChuZXcgQ29kZTkzUmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVhZGVycy5wdXNoKG5ldyBNdWx0aUZvcm1hdFVQQ0VBTlJlYWRlcihoaW50cykpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVhZGVycy5wdXNoKG5ldyBDb2RlMTI4UmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVhZGVycy5wdXNoKG5ldyBJVEZSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFkZXJzLnB1c2gobmV3IFJTUzE0UmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVhZGVycy5wdXNoKG5ldyBSU1NFeHBhbmRlZFJlYWRlcih0aGlzLnZlcmJvc2UpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBAT3ZlcnJpZGVcbiAgICAgICAgZGVjb2RlUm93KHJvd051bWJlciwgcm93LCBoaW50cykge1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnJlYWRlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yZWFkZXJzW2ldLmRlY29kZVJvdyhyb3dOdW1iZXIsIHJvdywgaGludHMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAocmUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gY29udGludWVcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBAT3ZlcnJpZGVcbiAgICAgICAgcmVzZXQoKSB7XG4gICAgICAgICAgICB0aGlzLnJlYWRlcnMuZm9yRWFjaChyZWFkZXIgPT4gcmVhZGVyLnJlc2V0KCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGRlcHJlY2F0ZWQgTW92aW5nIHRvIEB6eGluZy9icm93c2VyXG4gICAgICpcbiAgICAgKiBCYXJjb2RlIHJlYWRlciByZWFkZXIgdG8gdXNlIGZyb20gYnJvd3Nlci5cbiAgICAgKi9cbiAgICBjbGFzcyBCcm93c2VyQmFyY29kZVJlYWRlciBleHRlbmRzIEJyb3dzZXJDb2RlUmVhZGVyIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgQnJvd3NlckJhcmNvZGVSZWFkZXIuXG4gICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbdGltZUJldHdlZW5TY2Fuc01pbGxpcz01MDBdIHRoZSB0aW1lIGRlbGF5IGJldHdlZW4gc3Vic2VxdWVudCBkZWNvZGUgdHJpZXNcbiAgICAgICAgICogQHBhcmFtIHtNYXA8RGVjb2RlSGludFR5cGUsIGFueT59IGhpbnRzXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3Rvcih0aW1lQmV0d2VlblNjYW5zTWlsbGlzID0gNTAwLCBoaW50cykge1xuICAgICAgICAgICAgc3VwZXIobmV3IE11bHRpRm9ybWF0T25lRFJlYWRlcihoaW50cyksIHRpbWVCZXR3ZWVuU2NhbnNNaWxsaXMsIGhpbnRzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogPHA+RW5jYXBzdWxhdGVzIGEgc2V0IG9mIGVycm9yLWNvcnJlY3Rpb24gYmxvY2tzIGluIG9uZSBzeW1ib2wgdmVyc2lvbi4gTW9zdCB2ZXJzaW9ucyB3aWxsXG4gICAgICogdXNlIGJsb2NrcyBvZiBkaWZmZXJpbmcgc2l6ZXMgd2l0aGluIG9uZSB2ZXJzaW9uLCBzbywgdGhpcyBlbmNhcHN1bGF0ZXMgdGhlIHBhcmFtZXRlcnMgZm9yXG4gICAgICogZWFjaCBzZXQgb2YgYmxvY2tzLiBJdCBhbHNvIGhvbGRzIHRoZSBudW1iZXIgb2YgZXJyb3ItY29ycmVjdGlvbiBjb2Rld29yZHMgcGVyIGJsb2NrIHNpbmNlIGl0XG4gICAgICogd2lsbCBiZSB0aGUgc2FtZSBhY3Jvc3MgYWxsIGJsb2NrcyB3aXRoaW4gb25lIHZlcnNpb24uPC9wPlxuICAgICAqL1xuICAgIGNsYXNzIEVDQmxvY2tzIHtcbiAgICAgICAgY29uc3RydWN0b3IoZWNDb2Rld29yZHMsIGVjQmxvY2tzMSwgZWNCbG9ja3MyKSB7XG4gICAgICAgICAgICB0aGlzLmVjQ29kZXdvcmRzID0gZWNDb2Rld29yZHM7XG4gICAgICAgICAgICB0aGlzLmVjQmxvY2tzID0gW2VjQmxvY2tzMV07XG4gICAgICAgICAgICBlY0Jsb2NrczIgJiYgdGhpcy5lY0Jsb2Nrcy5wdXNoKGVjQmxvY2tzMik7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RUNDb2Rld29yZHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lY0NvZGV3b3JkcztcbiAgICAgICAgfVxuICAgICAgICBnZXRFQ0Jsb2NrcygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVjQmxvY2tzO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIDxwPkVuY2Fwc3VsYXRlcyB0aGUgcGFyYW1ldGVycyBmb3Igb25lIGVycm9yLWNvcnJlY3Rpb24gYmxvY2sgaW4gb25lIHN5bWJvbCB2ZXJzaW9uLlxuICAgICAqIFRoaXMgaW5jbHVkZXMgdGhlIG51bWJlciBvZiBkYXRhIGNvZGV3b3JkcywgYW5kIHRoZSBudW1iZXIgb2YgdGltZXMgYSBibG9jayB3aXRoIHRoZXNlXG4gICAgICogcGFyYW1ldGVycyBpcyB1c2VkIGNvbnNlY3V0aXZlbHkgaW4gdGhlIERhdGEgTWF0cml4IGNvZGUgdmVyc2lvbidzIGZvcm1hdC48L3A+XG4gICAgICovXG4gICAgY2xhc3MgRUNCIHtcbiAgICAgICAgY29uc3RydWN0b3IoY291bnQsIGRhdGFDb2Rld29yZHMpIHtcbiAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudDtcbiAgICAgICAgICAgIHRoaXMuZGF0YUNvZGV3b3JkcyA9IGRhdGFDb2Rld29yZHM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Q291bnQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb3VudDtcbiAgICAgICAgfVxuICAgICAgICBnZXREYXRhQ29kZXdvcmRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0YUNvZGV3b3JkcztcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBUaGUgVmVyc2lvbiBvYmplY3QgZW5jYXBzdWxhdGVzIGF0dHJpYnV0ZXMgYWJvdXQgYSBwYXJ0aWN1bGFyXG4gICAgICogc2l6ZSBEYXRhIE1hdHJpeCBDb2RlLlxuICAgICAqXG4gICAgICogQGF1dGhvciBiYnJvd25AZ29vZ2xlLmNvbSAoQnJpYW4gQnJvd24pXG4gICAgICovXG4gICAgY2xhc3MgVmVyc2lvbiB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHZlcnNpb25OdW1iZXIsIHN5bWJvbFNpemVSb3dzLCBzeW1ib2xTaXplQ29sdW1ucywgZGF0YVJlZ2lvblNpemVSb3dzLCBkYXRhUmVnaW9uU2l6ZUNvbHVtbnMsIGVjQmxvY2tzKSB7XG4gICAgICAgICAgICB0aGlzLnZlcnNpb25OdW1iZXIgPSB2ZXJzaW9uTnVtYmVyO1xuICAgICAgICAgICAgdGhpcy5zeW1ib2xTaXplUm93cyA9IHN5bWJvbFNpemVSb3dzO1xuICAgICAgICAgICAgdGhpcy5zeW1ib2xTaXplQ29sdW1ucyA9IHN5bWJvbFNpemVDb2x1bW5zO1xuICAgICAgICAgICAgdGhpcy5kYXRhUmVnaW9uU2l6ZVJvd3MgPSBkYXRhUmVnaW9uU2l6ZVJvd3M7XG4gICAgICAgICAgICB0aGlzLmRhdGFSZWdpb25TaXplQ29sdW1ucyA9IGRhdGFSZWdpb25TaXplQ29sdW1ucztcbiAgICAgICAgICAgIHRoaXMuZWNCbG9ja3MgPSBlY0Jsb2NrcztcbiAgICAgICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgdG90YWwgbnVtYmVyIG9mIGNvZGV3b3Jkc1xuICAgICAgICAgICAgbGV0IHRvdGFsID0gMDtcbiAgICAgICAgICAgIGNvbnN0IGVjQ29kZXdvcmRzID0gZWNCbG9ja3MuZ2V0RUNDb2Rld29yZHMoKTtcbiAgICAgICAgICAgIGNvbnN0IGVjYkFycmF5ID0gZWNCbG9ja3MuZ2V0RUNCbG9ja3MoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGVjQmxvY2sgb2YgZWNiQXJyYXkpIHtcbiAgICAgICAgICAgICAgICB0b3RhbCArPSBlY0Jsb2NrLmdldENvdW50KCkgKiAoZWNCbG9jay5nZXREYXRhQ29kZXdvcmRzKCkgKyBlY0NvZGV3b3Jkcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnRvdGFsQ29kZXdvcmRzID0gdG90YWw7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0VmVyc2lvbk51bWJlcigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZlcnNpb25OdW1iZXI7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0U3ltYm9sU2l6ZVJvd3MoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zeW1ib2xTaXplUm93cztcbiAgICAgICAgfVxuICAgICAgICBnZXRTeW1ib2xTaXplQ29sdW1ucygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN5bWJvbFNpemVDb2x1bW5zO1xuICAgICAgICB9XG4gICAgICAgIGdldERhdGFSZWdpb25TaXplUm93cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGFSZWdpb25TaXplUm93cztcbiAgICAgICAgfVxuICAgICAgICBnZXREYXRhUmVnaW9uU2l6ZUNvbHVtbnMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRhUmVnaW9uU2l6ZUNvbHVtbnM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0VG90YWxDb2Rld29yZHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50b3RhbENvZGV3b3JkcztcbiAgICAgICAgfVxuICAgICAgICBnZXRFQ0Jsb2NrcygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVjQmxvY2tzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5EZWR1Y2VzIHZlcnNpb24gaW5mb3JtYXRpb24gZnJvbSBEYXRhIE1hdHJpeCBkaW1lbnNpb25zLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIG51bVJvd3MgTnVtYmVyIG9mIHJvd3MgaW4gbW9kdWxlc1xuICAgICAgICAgKiBAcGFyYW0gbnVtQ29sdW1ucyBOdW1iZXIgb2YgY29sdW1ucyBpbiBtb2R1bGVzXG4gICAgICAgICAqIEByZXR1cm4gVmVyc2lvbiBmb3IgYSBEYXRhIE1hdHJpeCBDb2RlIG9mIHRob3NlIGRpbWVuc2lvbnNcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb24gaWYgZGltZW5zaW9ucyBkbyBjb3JyZXNwb25kIHRvIGEgdmFsaWQgRGF0YSBNYXRyaXggc2l6ZVxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGdldFZlcnNpb25Gb3JEaW1lbnNpb25zKG51bVJvd3MsIG51bUNvbHVtbnMpIHtcbiAgICAgICAgICAgIGlmICgobnVtUm93cyAmIDB4MDEpICE9PSAwIHx8IChudW1Db2x1bW5zICYgMHgwMSkgIT09IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCB2ZXJzaW9uIG9mIFZlcnNpb24uVkVSU0lPTlMpIHtcbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvbi5zeW1ib2xTaXplUm93cyA9PT0gbnVtUm93cyAmJiB2ZXJzaW9uLnN5bWJvbFNpemVDb2x1bW5zID09PSBudW1Db2x1bW5zKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2ZXJzaW9uO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgfVxuICAgICAgICAvLyAgQE92ZXJyaWRlXG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgcmV0dXJuICcnICsgdGhpcy52ZXJzaW9uTnVtYmVyO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZWUgSVNPIDE2MDIyOjIwMDYgNS41LjEgVGFibGUgN1xuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGJ1aWxkVmVyc2lvbnMoKSB7XG4gICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDEsIDEwLCAxMCwgOCwgOCwgbmV3IEVDQmxvY2tzKDUsIG5ldyBFQ0IoMSwgMykpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbigyLCAxMiwgMTIsIDEwLCAxMCwgbmV3IEVDQmxvY2tzKDcsIG5ldyBFQ0IoMSwgNSkpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbigzLCAxNCwgMTQsIDEyLCAxMiwgbmV3IEVDQmxvY2tzKDEwLCBuZXcgRUNCKDEsIDgpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oNCwgMTYsIDE2LCAxNCwgMTQsIG5ldyBFQ0Jsb2NrcygxMiwgbmV3IEVDQigxLCAxMikpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbig1LCAxOCwgMTgsIDE2LCAxNiwgbmV3IEVDQmxvY2tzKDE0LCBuZXcgRUNCKDEsIDE4KSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDYsIDIwLCAyMCwgMTgsIDE4LCBuZXcgRUNCbG9ja3MoMTgsIG5ldyBFQ0IoMSwgMjIpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oNywgMjIsIDIyLCAyMCwgMjAsIG5ldyBFQ0Jsb2NrcygyMCwgbmV3IEVDQigxLCAzMCkpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbig4LCAyNCwgMjQsIDIyLCAyMiwgbmV3IEVDQmxvY2tzKDI0LCBuZXcgRUNCKDEsIDM2KSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDksIDI2LCAyNiwgMjQsIDI0LCBuZXcgRUNCbG9ja3MoMjgsIG5ldyBFQ0IoMSwgNDQpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oMTAsIDMyLCAzMiwgMTQsIDE0LCBuZXcgRUNCbG9ja3MoMzYsIG5ldyBFQ0IoMSwgNjIpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oMTEsIDM2LCAzNiwgMTYsIDE2LCBuZXcgRUNCbG9ja3MoNDIsIG5ldyBFQ0IoMSwgODYpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oMTIsIDQwLCA0MCwgMTgsIDE4LCBuZXcgRUNCbG9ja3MoNDgsIG5ldyBFQ0IoMSwgMTE0KSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDEzLCA0NCwgNDQsIDIwLCAyMCwgbmV3IEVDQmxvY2tzKDU2LCBuZXcgRUNCKDEsIDE0NCkpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbigxNCwgNDgsIDQ4LCAyMiwgMjIsIG5ldyBFQ0Jsb2Nrcyg2OCwgbmV3IEVDQigxLCAxNzQpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oMTUsIDUyLCA1MiwgMjQsIDI0LCBuZXcgRUNCbG9ja3MoNDIsIG5ldyBFQ0IoMiwgMTAyKSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDE2LCA2NCwgNjQsIDE0LCAxNCwgbmV3IEVDQmxvY2tzKDU2LCBuZXcgRUNCKDIsIDE0MCkpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbigxNywgNzIsIDcyLCAxNiwgMTYsIG5ldyBFQ0Jsb2NrcygzNiwgbmV3IEVDQig0LCA5MikpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbigxOCwgODAsIDgwLCAxOCwgMTgsIG5ldyBFQ0Jsb2Nrcyg0OCwgbmV3IEVDQig0LCAxMTQpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oMTksIDg4LCA4OCwgMjAsIDIwLCBuZXcgRUNCbG9ja3MoNTYsIG5ldyBFQ0IoNCwgMTQ0KSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDIwLCA5NiwgOTYsIDIyLCAyMiwgbmV3IEVDQmxvY2tzKDY4LCBuZXcgRUNCKDQsIDE3NCkpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbigyMSwgMTA0LCAxMDQsIDI0LCAyNCwgbmV3IEVDQmxvY2tzKDU2LCBuZXcgRUNCKDYsIDEzNikpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbigyMiwgMTIwLCAxMjAsIDE4LCAxOCwgbmV3IEVDQmxvY2tzKDY4LCBuZXcgRUNCKDYsIDE3NSkpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbigyMywgMTMyLCAxMzIsIDIwLCAyMCwgbmV3IEVDQmxvY2tzKDYyLCBuZXcgRUNCKDgsIDE2MykpKSxcbiAgICAgICAgICAgICAgICBuZXcgVmVyc2lvbigyNCwgMTQ0LCAxNDQsIDIyLCAyMiwgbmV3IEVDQmxvY2tzKDYyLCBuZXcgRUNCKDgsIDE1NiksIG5ldyBFQ0IoMiwgMTU1KSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDI1LCA4LCAxOCwgNiwgMTYsIG5ldyBFQ0Jsb2Nrcyg3LCBuZXcgRUNCKDEsIDUpKSksXG4gICAgICAgICAgICAgICAgbmV3IFZlcnNpb24oMjYsIDgsIDMyLCA2LCAxNCwgbmV3IEVDQmxvY2tzKDExLCBuZXcgRUNCKDEsIDEwKSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDI3LCAxMiwgMjYsIDEwLCAyNCwgbmV3IEVDQmxvY2tzKDE0LCBuZXcgRUNCKDEsIDE2KSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDI4LCAxMiwgMzYsIDEwLCAxNiwgbmV3IEVDQmxvY2tzKDE4LCBuZXcgRUNCKDEsIDIyKSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDI5LCAxNiwgMzYsIDE0LCAxNiwgbmV3IEVDQmxvY2tzKDI0LCBuZXcgRUNCKDEsIDMyKSkpLFxuICAgICAgICAgICAgICAgIG5ldyBWZXJzaW9uKDMwLCAxNiwgNDgsIDE0LCAyMiwgbmV3IEVDQmxvY2tzKDI4LCBuZXcgRUNCKDEsIDQ5KSkpXG4gICAgICAgICAgICBdO1xuICAgICAgICB9XG4gICAgfVxuICAgIFZlcnNpb24uVkVSU0lPTlMgPSBWZXJzaW9uLmJ1aWxkVmVyc2lvbnMoKTtcblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogQGF1dGhvciBiYnJvd25AZ29vZ2xlLmNvbSAoQnJpYW4gQnJvd24pXG4gICAgICovXG4gICAgY2xhc3MgQml0TWF0cml4UGFyc2VyIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBiaXRNYXRyaXgge0BsaW5rIEJpdE1hdHJpeH0gdG8gcGFyc2VcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb24gaWYgZGltZW5zaW9uIGlzIDwgOCBvciA+IDE0NCBvciBub3QgMCBtb2QgMlxuICAgICAgICAgKi9cbiAgICAgICAgY29uc3RydWN0b3IoYml0TWF0cml4KSB7XG4gICAgICAgICAgICBjb25zdCBkaW1lbnNpb24gPSBiaXRNYXRyaXguZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICBpZiAoZGltZW5zaW9uIDwgOCB8fCBkaW1lbnNpb24gPiAxNDQgfHwgKGRpbWVuc2lvbiAmIDB4MDEpICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy52ZXJzaW9uID0gQml0TWF0cml4UGFyc2VyLnJlYWRWZXJzaW9uKGJpdE1hdHJpeCk7XG4gICAgICAgICAgICB0aGlzLm1hcHBpbmdCaXRNYXRyaXggPSB0aGlzLmV4dHJhY3REYXRhUmVnaW9uKGJpdE1hdHJpeCk7XG4gICAgICAgICAgICB0aGlzLnJlYWRNYXBwaW5nTWF0cml4ID0gbmV3IEJpdE1hdHJpeCh0aGlzLm1hcHBpbmdCaXRNYXRyaXguZ2V0V2lkdGgoKSwgdGhpcy5tYXBwaW5nQml0TWF0cml4LmdldEhlaWdodCgpKTtcbiAgICAgICAgfVxuICAgICAgICBnZXRWZXJzaW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmVyc2lvbjtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+Q3JlYXRlcyB0aGUgdmVyc2lvbiBvYmplY3QgYmFzZWQgb24gdGhlIGRpbWVuc2lvbiBvZiB0aGUgb3JpZ2luYWwgYml0IG1hdHJpeCBmcm9tXG4gICAgICAgICAqIHRoZSBkYXRhbWF0cml4IGNvZGUuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiA8cD5TZWUgSVNPIDE2MDIyOjIwMDYgVGFibGUgNyAtIEVDQyAyMDAgc3ltYm9sIGF0dHJpYnV0ZXM8L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBiaXRNYXRyaXggT3JpZ2luYWwge0BsaW5rIEJpdE1hdHJpeH0gaW5jbHVkaW5nIGFsaWdubWVudCBwYXR0ZXJuc1xuICAgICAgICAgKiBAcmV0dXJuIHtAbGluayBWZXJzaW9ufSBlbmNhcHN1bGF0aW5nIHRoZSBEYXRhIE1hdHJpeCBDb2RlJ3MgXCJ2ZXJzaW9uXCJcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb24gaWYgdGhlIGRpbWVuc2lvbnMgb2YgdGhlIG1hcHBpbmcgbWF0cml4IGFyZSBub3QgdmFsaWRcbiAgICAgICAgICogRGF0YSBNYXRyaXggZGltZW5zaW9ucy5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyByZWFkVmVyc2lvbihiaXRNYXRyaXgpIHtcbiAgICAgICAgICAgIGNvbnN0IG51bVJvd3MgPSBiaXRNYXRyaXguZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICBjb25zdCBudW1Db2x1bW5zID0gYml0TWF0cml4LmdldFdpZHRoKCk7XG4gICAgICAgICAgICByZXR1cm4gVmVyc2lvbi5nZXRWZXJzaW9uRm9yRGltZW5zaW9ucyhudW1Sb3dzLCBudW1Db2x1bW5zKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+UmVhZHMgdGhlIGJpdHMgaW4gdGhlIHtAbGluayBCaXRNYXRyaXh9IHJlcHJlc2VudGluZyB0aGUgbWFwcGluZyBtYXRyaXggKE5vIGFsaWdubWVudCBwYXR0ZXJucylcbiAgICAgICAgICogaW4gdGhlIGNvcnJlY3Qgb3JkZXIgaW4gb3JkZXIgdG8gcmVjb25zdGl0dXRlIHRoZSBjb2Rld29yZHMgYnl0ZXMgY29udGFpbmVkIHdpdGhpbiB0aGVcbiAgICAgICAgICogRGF0YSBNYXRyaXggQ29kZS48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gYnl0ZXMgZW5jb2RlZCB3aXRoaW4gdGhlIERhdGEgTWF0cml4IENvZGVcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb24gaWYgdGhlIGV4YWN0IG51bWJlciBvZiBieXRlcyBleHBlY3RlZCBpcyBub3QgcmVhZFxuICAgICAgICAgKi9cbiAgICAgICAgcmVhZENvZGV3b3JkcygpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBJbnQ4QXJyYXkodGhpcy52ZXJzaW9uLmdldFRvdGFsQ29kZXdvcmRzKCkpO1xuICAgICAgICAgICAgbGV0IHJlc3VsdE9mZnNldCA9IDA7XG4gICAgICAgICAgICBsZXQgcm93ID0gNDtcbiAgICAgICAgICAgIGxldCBjb2x1bW4gPSAwO1xuICAgICAgICAgICAgY29uc3QgbnVtUm93cyA9IHRoaXMubWFwcGluZ0JpdE1hdHJpeC5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IG51bUNvbHVtbnMgPSB0aGlzLm1hcHBpbmdCaXRNYXRyaXguZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGxldCBjb3JuZXIxUmVhZCA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGNvcm5lcjJSZWFkID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgY29ybmVyM1JlYWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGxldCBjb3JuZXI0UmVhZCA9IGZhbHNlO1xuICAgICAgICAgICAgLy8gUmVhZCBhbGwgb2YgdGhlIGNvZGV3b3Jkc1xuICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgIC8vIENoZWNrIHRoZSBmb3VyIGNvcm5lciBjYXNlc1xuICAgICAgICAgICAgICAgIGlmICgocm93ID09PSBudW1Sb3dzKSAmJiAoY29sdW1uID09PSAwKSAmJiAhY29ybmVyMVJlYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W3Jlc3VsdE9mZnNldCsrXSA9IHRoaXMucmVhZENvcm5lcjEobnVtUm93cywgbnVtQ29sdW1ucykgJiAweGZmO1xuICAgICAgICAgICAgICAgICAgICByb3cgLT0gMjtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uICs9IDI7XG4gICAgICAgICAgICAgICAgICAgIGNvcm5lcjFSZWFkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoKHJvdyA9PT0gbnVtUm93cyAtIDIpICYmIChjb2x1bW4gPT09IDApICYmICgobnVtQ29sdW1ucyAmIDB4MDMpICE9PSAwKSAmJiAhY29ybmVyMlJlYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W3Jlc3VsdE9mZnNldCsrXSA9IHRoaXMucmVhZENvcm5lcjIobnVtUm93cywgbnVtQ29sdW1ucykgJiAweGZmO1xuICAgICAgICAgICAgICAgICAgICByb3cgLT0gMjtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uICs9IDI7XG4gICAgICAgICAgICAgICAgICAgIGNvcm5lcjJSZWFkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoKHJvdyA9PT0gbnVtUm93cyArIDQpICYmIChjb2x1bW4gPT09IDIpICYmICgobnVtQ29sdW1ucyAmIDB4MDcpID09PSAwKSAmJiAhY29ybmVyM1JlYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W3Jlc3VsdE9mZnNldCsrXSA9IHRoaXMucmVhZENvcm5lcjMobnVtUm93cywgbnVtQ29sdW1ucykgJiAweGZmO1xuICAgICAgICAgICAgICAgICAgICByb3cgLT0gMjtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uICs9IDI7XG4gICAgICAgICAgICAgICAgICAgIGNvcm5lcjNSZWFkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoKHJvdyA9PT0gbnVtUm93cyAtIDIpICYmIChjb2x1bW4gPT09IDApICYmICgobnVtQ29sdW1ucyAmIDB4MDcpID09PSA0KSAmJiAhY29ybmVyNFJlYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W3Jlc3VsdE9mZnNldCsrXSA9IHRoaXMucmVhZENvcm5lcjQobnVtUm93cywgbnVtQ29sdW1ucykgJiAweGZmO1xuICAgICAgICAgICAgICAgICAgICByb3cgLT0gMjtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uICs9IDI7XG4gICAgICAgICAgICAgICAgICAgIGNvcm5lcjRSZWFkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFN3ZWVwIHVwd2FyZCBkaWFnb25hbGx5IHRvIHRoZSByaWdodFxuICAgICAgICAgICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoKHJvdyA8IG51bVJvd3MpICYmIChjb2x1bW4gPj0gMCkgJiYgIXRoaXMucmVhZE1hcHBpbmdNYXRyaXguZ2V0KGNvbHVtbiwgcm93KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdFtyZXN1bHRPZmZzZXQrK10gPSB0aGlzLnJlYWRVdGFoKHJvdywgY29sdW1uLCBudW1Sb3dzLCBudW1Db2x1bW5zKSAmIDB4ZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByb3cgLT0gMjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbiArPSAyO1xuICAgICAgICAgICAgICAgICAgICB9IHdoaWxlICgocm93ID49IDApICYmIChjb2x1bW4gPCBudW1Db2x1bW5zKSk7XG4gICAgICAgICAgICAgICAgICAgIHJvdyArPSAxO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW4gKz0gMztcbiAgICAgICAgICAgICAgICAgICAgLy8gU3dlZXAgZG93bndhcmQgZGlhZ29uYWxseSB0byB0aGUgbGVmdFxuICAgICAgICAgICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoKHJvdyA+PSAwKSAmJiAoY29sdW1uIDwgbnVtQ29sdW1ucykgJiYgIXRoaXMucmVhZE1hcHBpbmdNYXRyaXguZ2V0KGNvbHVtbiwgcm93KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdFtyZXN1bHRPZmZzZXQrK10gPSB0aGlzLnJlYWRVdGFoKHJvdywgY29sdW1uLCBudW1Sb3dzLCBudW1Db2x1bW5zKSAmIDB4ZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByb3cgKz0gMjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbiAtPSAyO1xuICAgICAgICAgICAgICAgICAgICB9IHdoaWxlICgocm93IDwgbnVtUm93cykgJiYgKGNvbHVtbiA+PSAwKSk7XG4gICAgICAgICAgICAgICAgICAgIHJvdyArPSAzO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW4gKz0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IHdoaWxlICgocm93IDwgbnVtUm93cykgfHwgKGNvbHVtbiA8IG51bUNvbHVtbnMpKTtcbiAgICAgICAgICAgIGlmIChyZXN1bHRPZmZzZXQgIT09IHRoaXMudmVyc2lvbi5nZXRUb3RhbENvZGV3b3JkcygpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+UmVhZHMgYSBiaXQgb2YgdGhlIG1hcHBpbmcgbWF0cml4IGFjY291bnRpbmcgZm9yIGJvdW5kYXJ5IHdyYXBwaW5nLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHJvdyBSb3cgdG8gcmVhZCBpbiB0aGUgbWFwcGluZyBtYXRyaXhcbiAgICAgICAgICogQHBhcmFtIGNvbHVtbiBDb2x1bW4gdG8gcmVhZCBpbiB0aGUgbWFwcGluZyBtYXRyaXhcbiAgICAgICAgICogQHBhcmFtIG51bVJvd3MgTnVtYmVyIG9mIHJvd3MgaW4gdGhlIG1hcHBpbmcgbWF0cml4XG4gICAgICAgICAqIEBwYXJhbSBudW1Db2x1bW5zIE51bWJlciBvZiBjb2x1bW5zIGluIHRoZSBtYXBwaW5nIG1hdHJpeFxuICAgICAgICAgKiBAcmV0dXJuIHZhbHVlIG9mIHRoZSBnaXZlbiBiaXQgaW4gdGhlIG1hcHBpbmcgbWF0cml4XG4gICAgICAgICAqL1xuICAgICAgICByZWFkTW9kdWxlKHJvdywgY29sdW1uLCBudW1Sb3dzLCBudW1Db2x1bW5zKSB7XG4gICAgICAgICAgICAvLyBBZGp1c3QgdGhlIHJvdyBhbmQgY29sdW1uIGluZGljZXMgYmFzZWQgb24gYm91bmRhcnkgd3JhcHBpbmdcbiAgICAgICAgICAgIGlmIChyb3cgPCAwKSB7XG4gICAgICAgICAgICAgICAgcm93ICs9IG51bVJvd3M7XG4gICAgICAgICAgICAgICAgY29sdW1uICs9IDQgLSAoKG51bVJvd3MgKyA0KSAmIDB4MDcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvbHVtbiA8IDApIHtcbiAgICAgICAgICAgICAgICBjb2x1bW4gKz0gbnVtQ29sdW1ucztcbiAgICAgICAgICAgICAgICByb3cgKz0gNCAtICgobnVtQ29sdW1ucyArIDQpICYgMHgwNyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnJlYWRNYXBwaW5nTWF0cml4LnNldChjb2x1bW4sIHJvdyk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXBwaW5nQml0TWF0cml4LmdldChjb2x1bW4sIHJvdyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPlJlYWRzIHRoZSA4IGJpdHMgb2YgdGhlIHN0YW5kYXJkIFV0YWgtc2hhcGVkIHBhdHRlcm4uPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiA8cD5TZWUgSVNPIDE2MDIyOjIwMDYsIDUuOC4xIEZpZ3VyZSA2PC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gcm93IEN1cnJlbnQgcm93IGluIHRoZSBtYXBwaW5nIG1hdHJpeCwgYW5jaG9yZWQgYXQgdGhlIDh0aCBiaXQgKExTQikgb2YgdGhlIHBhdHRlcm5cbiAgICAgICAgICogQHBhcmFtIGNvbHVtbiBDdXJyZW50IGNvbHVtbiBpbiB0aGUgbWFwcGluZyBtYXRyaXgsIGFuY2hvcmVkIGF0IHRoZSA4dGggYml0IChMU0IpIG9mIHRoZSBwYXR0ZXJuXG4gICAgICAgICAqIEBwYXJhbSBudW1Sb3dzIE51bWJlciBvZiByb3dzIGluIHRoZSBtYXBwaW5nIG1hdHJpeFxuICAgICAgICAgKiBAcGFyYW0gbnVtQ29sdW1ucyBOdW1iZXIgb2YgY29sdW1ucyBpbiB0aGUgbWFwcGluZyBtYXRyaXhcbiAgICAgICAgICogQHJldHVybiBieXRlIGZyb20gdGhlIHV0YWggc2hhcGVcbiAgICAgICAgICovXG4gICAgICAgIHJlYWRVdGFoKHJvdywgY29sdW1uLCBudW1Sb3dzLCBudW1Db2x1bW5zKSB7XG4gICAgICAgICAgICBsZXQgY3VycmVudEJ5dGUgPSAwO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZShyb3cgLSAyLCBjb2x1bW4gLSAyLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUocm93IC0gMiwgY29sdW1uIC0gMSwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKHJvdyAtIDEsIGNvbHVtbiAtIDIsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZShyb3cgLSAxLCBjb2x1bW4gLSAxLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUocm93IC0gMSwgY29sdW1uLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUocm93LCBjb2x1bW4gLSAyLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUocm93LCBjb2x1bW4gLSAxLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUocm93LCBjb2x1bW4sIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50Qnl0ZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+UmVhZHMgdGhlIDggYml0cyBvZiB0aGUgc3BlY2lhbCBjb3JuZXIgY29uZGl0aW9uIDEuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiA8cD5TZWUgSVNPIDE2MDIyOjIwMDYsIEZpZ3VyZSBGLjM8L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBudW1Sb3dzIE51bWJlciBvZiByb3dzIGluIHRoZSBtYXBwaW5nIG1hdHJpeFxuICAgICAgICAgKiBAcGFyYW0gbnVtQ29sdW1ucyBOdW1iZXIgb2YgY29sdW1ucyBpbiB0aGUgbWFwcGluZyBtYXRyaXhcbiAgICAgICAgICogQHJldHVybiBieXRlIGZyb20gdGhlIENvcm5lciBjb25kaXRpb24gMVxuICAgICAgICAgKi9cbiAgICAgICAgcmVhZENvcm5lcjEobnVtUm93cywgbnVtQ29sdW1ucykge1xuICAgICAgICAgICAgbGV0IGN1cnJlbnRCeXRlID0gMDtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUobnVtUm93cyAtIDEsIDAsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZShudW1Sb3dzIC0gMSwgMSwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKG51bVJvd3MgLSAxLCAyLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUoMCwgbnVtQ29sdW1ucyAtIDIsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZSgwLCBudW1Db2x1bW5zIC0gMSwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKDEsIG51bUNvbHVtbnMgLSAxLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUoMiwgbnVtQ29sdW1ucyAtIDEsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZSgzLCBudW1Db2x1bW5zIC0gMSwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRCeXRlO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5SZWFkcyB0aGUgOCBiaXRzIG9mIHRoZSBzcGVjaWFsIGNvcm5lciBjb25kaXRpb24gMi48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIDxwPlNlZSBJU08gMTYwMjI6MjAwNiwgRmlndXJlIEYuNDwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIG51bVJvd3MgTnVtYmVyIG9mIHJvd3MgaW4gdGhlIG1hcHBpbmcgbWF0cml4XG4gICAgICAgICAqIEBwYXJhbSBudW1Db2x1bW5zIE51bWJlciBvZiBjb2x1bW5zIGluIHRoZSBtYXBwaW5nIG1hdHJpeFxuICAgICAgICAgKiBAcmV0dXJuIGJ5dGUgZnJvbSB0aGUgQ29ybmVyIGNvbmRpdGlvbiAyXG4gICAgICAgICAqL1xuICAgICAgICByZWFkQ29ybmVyMihudW1Sb3dzLCBudW1Db2x1bW5zKSB7XG4gICAgICAgICAgICBsZXQgY3VycmVudEJ5dGUgPSAwO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZShudW1Sb3dzIC0gMywgMCwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKG51bVJvd3MgLSAyLCAwLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUobnVtUm93cyAtIDEsIDAsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZSgwLCBudW1Db2x1bW5zIC0gNCwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKDAsIG51bUNvbHVtbnMgLSAzLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUoMCwgbnVtQ29sdW1ucyAtIDIsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZSgwLCBudW1Db2x1bW5zIC0gMSwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKDEsIG51bUNvbHVtbnMgLSAxLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY3VycmVudEJ5dGU7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPlJlYWRzIHRoZSA4IGJpdHMgb2YgdGhlIHNwZWNpYWwgY29ybmVyIGNvbmRpdGlvbiAzLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogPHA+U2VlIElTTyAxNjAyMjoyMDA2LCBGaWd1cmUgRi41PC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gbnVtUm93cyBOdW1iZXIgb2Ygcm93cyBpbiB0aGUgbWFwcGluZyBtYXRyaXhcbiAgICAgICAgICogQHBhcmFtIG51bUNvbHVtbnMgTnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhlIG1hcHBpbmcgbWF0cml4XG4gICAgICAgICAqIEByZXR1cm4gYnl0ZSBmcm9tIHRoZSBDb3JuZXIgY29uZGl0aW9uIDNcbiAgICAgICAgICovXG4gICAgICAgIHJlYWRDb3JuZXIzKG51bVJvd3MsIG51bUNvbHVtbnMpIHtcbiAgICAgICAgICAgIGxldCBjdXJyZW50Qnl0ZSA9IDA7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKG51bVJvd3MgLSAxLCAwLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUobnVtUm93cyAtIDEsIG51bUNvbHVtbnMgLSAxLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUoMCwgbnVtQ29sdW1ucyAtIDMsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZSgwLCBudW1Db2x1bW5zIC0gMiwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKDAsIG51bUNvbHVtbnMgLSAxLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUoMSwgbnVtQ29sdW1ucyAtIDMsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZSgxLCBudW1Db2x1bW5zIC0gMiwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKDEsIG51bUNvbHVtbnMgLSAxLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY3VycmVudEJ5dGU7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPlJlYWRzIHRoZSA4IGJpdHMgb2YgdGhlIHNwZWNpYWwgY29ybmVyIGNvbmRpdGlvbiA0LjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogPHA+U2VlIElTTyAxNjAyMjoyMDA2LCBGaWd1cmUgRi42PC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gbnVtUm93cyBOdW1iZXIgb2Ygcm93cyBpbiB0aGUgbWFwcGluZyBtYXRyaXhcbiAgICAgICAgICogQHBhcmFtIG51bUNvbHVtbnMgTnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhlIG1hcHBpbmcgbWF0cml4XG4gICAgICAgICAqIEByZXR1cm4gYnl0ZSBmcm9tIHRoZSBDb3JuZXIgY29uZGl0aW9uIDRcbiAgICAgICAgICovXG4gICAgICAgIHJlYWRDb3JuZXI0KG51bVJvd3MsIG51bUNvbHVtbnMpIHtcbiAgICAgICAgICAgIGxldCBjdXJyZW50Qnl0ZSA9IDA7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKG51bVJvd3MgLSAzLCAwLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUobnVtUm93cyAtIDIsIDAsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZShudW1Sb3dzIC0gMSwgMCwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKDAsIG51bUNvbHVtbnMgLSAyLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUoMCwgbnVtQ29sdW1ucyAtIDEsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE1vZHVsZSgxLCBudW1Db2x1bW5zIC0gMSwgbnVtUm93cywgbnVtQ29sdW1ucykpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSB8PSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEJ5dGUgPDw9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkTW9kdWxlKDIsIG51bUNvbHVtbnMgLSAxLCBudW1Sb3dzLCBudW1Db2x1bW5zKSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIHw9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50Qnl0ZSA8PD0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRNb2R1bGUoMywgbnVtQ29sdW1ucyAtIDEsIG51bVJvd3MsIG51bUNvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBjdXJyZW50Qnl0ZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+RXh0cmFjdHMgdGhlIGRhdGEgcmVnaW9uIGZyb20gYSB7QGxpbmsgQml0TWF0cml4fSB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAqIGFsaWdubWVudCBwYXR0ZXJucy48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBiaXRNYXRyaXggT3JpZ2luYWwge0BsaW5rIEJpdE1hdHJpeH0gd2l0aCBhbGlnbm1lbnQgcGF0dGVybnNcbiAgICAgICAgICogQHJldHVybiBCaXRNYXRyaXggdGhhdCBoYXMgdGhlIGFsaWdubWVudCBwYXR0ZXJucyByZW1vdmVkXG4gICAgICAgICAqL1xuICAgICAgICBleHRyYWN0RGF0YVJlZ2lvbihiaXRNYXRyaXgpIHtcbiAgICAgICAgICAgIGNvbnN0IHN5bWJvbFNpemVSb3dzID0gdGhpcy52ZXJzaW9uLmdldFN5bWJvbFNpemVSb3dzKCk7XG4gICAgICAgICAgICBjb25zdCBzeW1ib2xTaXplQ29sdW1ucyA9IHRoaXMudmVyc2lvbi5nZXRTeW1ib2xTaXplQ29sdW1ucygpO1xuICAgICAgICAgICAgaWYgKGJpdE1hdHJpeC5nZXRIZWlnaHQoKSAhPT0gc3ltYm9sU2l6ZVJvd3MpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdEaW1lbnNpb24gb2YgYml0TWF0cml4IG11c3QgbWF0Y2ggdGhlIHZlcnNpb24gc2l6ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZGF0YVJlZ2lvblNpemVSb3dzID0gdGhpcy52ZXJzaW9uLmdldERhdGFSZWdpb25TaXplUm93cygpO1xuICAgICAgICAgICAgY29uc3QgZGF0YVJlZ2lvblNpemVDb2x1bW5zID0gdGhpcy52ZXJzaW9uLmdldERhdGFSZWdpb25TaXplQ29sdW1ucygpO1xuICAgICAgICAgICAgY29uc3QgbnVtRGF0YVJlZ2lvbnNSb3cgPSBzeW1ib2xTaXplUm93cyAvIGRhdGFSZWdpb25TaXplUm93cyB8IDA7XG4gICAgICAgICAgICBjb25zdCBudW1EYXRhUmVnaW9uc0NvbHVtbiA9IHN5bWJvbFNpemVDb2x1bW5zIC8gZGF0YVJlZ2lvblNpemVDb2x1bW5zIHwgMDtcbiAgICAgICAgICAgIGNvbnN0IHNpemVEYXRhUmVnaW9uUm93ID0gbnVtRGF0YVJlZ2lvbnNSb3cgKiBkYXRhUmVnaW9uU2l6ZVJvd3M7XG4gICAgICAgICAgICBjb25zdCBzaXplRGF0YVJlZ2lvbkNvbHVtbiA9IG51bURhdGFSZWdpb25zQ29sdW1uICogZGF0YVJlZ2lvblNpemVDb2x1bW5zO1xuICAgICAgICAgICAgY29uc3QgYml0TWF0cml4V2l0aG91dEFsaWdubWVudCA9IG5ldyBCaXRNYXRyaXgoc2l6ZURhdGFSZWdpb25Db2x1bW4sIHNpemVEYXRhUmVnaW9uUm93KTtcbiAgICAgICAgICAgIGZvciAobGV0IGRhdGFSZWdpb25Sb3cgPSAwOyBkYXRhUmVnaW9uUm93IDwgbnVtRGF0YVJlZ2lvbnNSb3c7ICsrZGF0YVJlZ2lvblJvdykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGFSZWdpb25Sb3dPZmZzZXQgPSBkYXRhUmVnaW9uUm93ICogZGF0YVJlZ2lvblNpemVSb3dzO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGRhdGFSZWdpb25Db2x1bW4gPSAwOyBkYXRhUmVnaW9uQ29sdW1uIDwgbnVtRGF0YVJlZ2lvbnNDb2x1bW47ICsrZGF0YVJlZ2lvbkNvbHVtbikge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRhUmVnaW9uQ29sdW1uT2Zmc2V0ID0gZGF0YVJlZ2lvbkNvbHVtbiAqIGRhdGFSZWdpb25TaXplQ29sdW1ucztcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhUmVnaW9uU2l6ZVJvd3M7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVhZFJvd09mZnNldCA9IGRhdGFSZWdpb25Sb3cgKiAoZGF0YVJlZ2lvblNpemVSb3dzICsgMikgKyAxICsgaTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdyaXRlUm93T2Zmc2V0ID0gZGF0YVJlZ2lvblJvd09mZnNldCArIGk7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGRhdGFSZWdpb25TaXplQ29sdW1uczsgKytqKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVhZENvbHVtbk9mZnNldCA9IGRhdGFSZWdpb25Db2x1bW4gKiAoZGF0YVJlZ2lvblNpemVDb2x1bW5zICsgMikgKyAxICsgajtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYml0TWF0cml4LmdldChyZWFkQ29sdW1uT2Zmc2V0LCByZWFkUm93T2Zmc2V0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3cml0ZUNvbHVtbk9mZnNldCA9IGRhdGFSZWdpb25Db2x1bW5PZmZzZXQgKyBqO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaXRNYXRyaXhXaXRob3V0QWxpZ25tZW50LnNldCh3cml0ZUNvbHVtbk9mZnNldCwgd3JpdGVSb3dPZmZzZXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBiaXRNYXRyaXhXaXRob3V0QWxpZ25tZW50O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogPHA+RW5jYXBzdWxhdGVzIGEgYmxvY2sgb2YgZGF0YSB3aXRoaW4gYSBEYXRhIE1hdHJpeCBDb2RlLiBEYXRhIE1hdHJpeCBDb2RlcyBtYXkgc3BsaXQgdGhlaXIgZGF0YSBpbnRvXG4gICAgICogbXVsdGlwbGUgYmxvY2tzLCBlYWNoIG9mIHdoaWNoIGlzIGEgdW5pdCBvZiBkYXRhIGFuZCBlcnJvci1jb3JyZWN0aW9uIGNvZGV3b3Jkcy4gRWFjaFxuICAgICAqIGlzIHJlcHJlc2VudGVkIGJ5IGFuIGluc3RhbmNlIG9mIHRoaXMgY2xhc3MuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBiYnJvd25AZ29vZ2xlLmNvbSAoQnJpYW4gQnJvd24pXG4gICAgICovXG4gICAgY2xhc3MgRGF0YUJsb2NrIHtcbiAgICAgICAgY29uc3RydWN0b3IobnVtRGF0YUNvZGV3b3JkcywgY29kZXdvcmRzKSB7XG4gICAgICAgICAgICB0aGlzLm51bURhdGFDb2Rld29yZHMgPSBudW1EYXRhQ29kZXdvcmRzO1xuICAgICAgICAgICAgdGhpcy5jb2Rld29yZHMgPSBjb2Rld29yZHM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPldoZW4gRGF0YSBNYXRyaXggQ29kZXMgdXNlIG11bHRpcGxlIGRhdGEgYmxvY2tzLCB0aGV5IGFjdHVhbGx5IGludGVybGVhdmUgdGhlIGJ5dGVzIG9mIGVhY2ggb2YgdGhlbS5cbiAgICAgICAgICogVGhhdCBpcywgdGhlIGZpcnN0IGJ5dGUgb2YgZGF0YSBibG9jayAxIHRvIG4gaXMgd3JpdHRlbiwgdGhlbiB0aGUgc2Vjb25kIGJ5dGVzLCBhbmQgc28gb24uIFRoaXNcbiAgICAgICAgICogbWV0aG9kIHdpbGwgc2VwYXJhdGUgdGhlIGRhdGEgaW50byBvcmlnaW5hbCBibG9ja3MuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gcmF3Q29kZXdvcmRzIGJ5dGVzIGFzIHJlYWQgZGlyZWN0bHkgZnJvbSB0aGUgRGF0YSBNYXRyaXggQ29kZVxuICAgICAgICAgKiBAcGFyYW0gdmVyc2lvbiB2ZXJzaW9uIG9mIHRoZSBEYXRhIE1hdHJpeCBDb2RlXG4gICAgICAgICAqIEByZXR1cm4gRGF0YUJsb2NrcyBjb250YWluaW5nIG9yaWdpbmFsIGJ5dGVzLCBcImRlLWludGVybGVhdmVkXCIgZnJvbSByZXByZXNlbnRhdGlvbiBpbiB0aGVcbiAgICAgICAgICogICAgICAgICBEYXRhIE1hdHJpeCBDb2RlXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZ2V0RGF0YUJsb2NrcyhyYXdDb2Rld29yZHMsIHZlcnNpb24pIHtcbiAgICAgICAgICAgIC8vIEZpZ3VyZSBvdXQgdGhlIG51bWJlciBhbmQgc2l6ZSBvZiBkYXRhIGJsb2NrcyB1c2VkIGJ5IHRoaXMgdmVyc2lvblxuICAgICAgICAgICAgY29uc3QgZWNCbG9ja3MgPSB2ZXJzaW9uLmdldEVDQmxvY2tzKCk7XG4gICAgICAgICAgICAvLyBGaXJzdCBjb3VudCB0aGUgdG90YWwgbnVtYmVyIG9mIGRhdGEgYmxvY2tzXG4gICAgICAgICAgICBsZXQgdG90YWxCbG9ja3MgPSAwO1xuICAgICAgICAgICAgY29uc3QgZWNCbG9ja0FycmF5ID0gZWNCbG9ja3MuZ2V0RUNCbG9ja3MoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGVjQmxvY2sgb2YgZWNCbG9ja0FycmF5KSB7XG4gICAgICAgICAgICAgICAgdG90YWxCbG9ja3MgKz0gZWNCbG9jay5nZXRDb3VudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gTm93IGVzdGFibGlzaCBEYXRhQmxvY2tzIG9mIHRoZSBhcHByb3ByaWF0ZSBzaXplIGFuZCBudW1iZXIgb2YgZGF0YSBjb2Rld29yZHNcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBBcnJheSh0b3RhbEJsb2Nrcyk7XG4gICAgICAgICAgICBsZXQgbnVtUmVzdWx0QmxvY2tzID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGVjQmxvY2sgb2YgZWNCbG9ja0FycmF5KSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBlY0Jsb2NrLmdldENvdW50KCk7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBudW1EYXRhQ29kZXdvcmRzID0gZWNCbG9jay5nZXREYXRhQ29kZXdvcmRzKCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG51bUJsb2NrQ29kZXdvcmRzID0gZWNCbG9ja3MuZ2V0RUNDb2Rld29yZHMoKSArIG51bURhdGFDb2Rld29yZHM7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtudW1SZXN1bHRCbG9ja3MrK10gPSBuZXcgRGF0YUJsb2NrKG51bURhdGFDb2Rld29yZHMsIG5ldyBVaW50OEFycmF5KG51bUJsb2NrQ29kZXdvcmRzKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQWxsIGJsb2NrcyBoYXZlIHRoZSBzYW1lIGFtb3VudCBvZiBkYXRhLCBleGNlcHQgdGhhdCB0aGUgbGFzdCBuXG4gICAgICAgICAgICAvLyAod2hlcmUgbiBtYXkgYmUgMCkgaGF2ZSAxIGxlc3MgYnl0ZS4gRmlndXJlIG91dCB3aGVyZSB0aGVzZSBzdGFydC5cbiAgICAgICAgICAgIC8vIFRPRE8oYmJyb3duKTogVGhlcmUgaXMgb25seSBvbmUgY2FzZSB3aGVyZSB0aGVyZSBpcyBhIGRpZmZlcmVuY2UgZm9yIERhdGEgTWF0cml4IGZvciBzaXplIDE0NFxuICAgICAgICAgICAgY29uc3QgbG9uZ2VyQmxvY2tzVG90YWxDb2Rld29yZHMgPSByZXN1bHRbMF0uY29kZXdvcmRzLmxlbmd0aDtcbiAgICAgICAgICAgIC8vIGludCBzaG9ydGVyQmxvY2tzVG90YWxDb2Rld29yZHMgPSBsb25nZXJCbG9ja3NUb3RhbENvZGV3b3JkcyAtIDE7XG4gICAgICAgICAgICBjb25zdCBsb25nZXJCbG9ja3NOdW1EYXRhQ29kZXdvcmRzID0gbG9uZ2VyQmxvY2tzVG90YWxDb2Rld29yZHMgLSBlY0Jsb2Nrcy5nZXRFQ0NvZGV3b3JkcygpO1xuICAgICAgICAgICAgY29uc3Qgc2hvcnRlckJsb2Nrc051bURhdGFDb2Rld29yZHMgPSBsb25nZXJCbG9ja3NOdW1EYXRhQ29kZXdvcmRzIC0gMTtcbiAgICAgICAgICAgIC8vIFRoZSBsYXN0IGVsZW1lbnRzIG9mIHJlc3VsdCBtYXkgYmUgMSBlbGVtZW50IHNob3J0ZXIgZm9yIDE0NCBtYXRyaXhcbiAgICAgICAgICAgIC8vIGZpcnN0IGZpbGwgb3V0IGFzIG1hbnkgZWxlbWVudHMgYXMgYWxsIG9mIHRoZW0gaGF2ZSBtaW51cyAxXG4gICAgICAgICAgICBsZXQgcmF3Q29kZXdvcmRzT2Zmc2V0ID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2hvcnRlckJsb2Nrc051bURhdGFDb2Rld29yZHM7IGkrKykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgbnVtUmVzdWx0QmxvY2tzOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2pdLmNvZGV3b3Jkc1tpXSA9IHJhd0NvZGV3b3Jkc1tyYXdDb2Rld29yZHNPZmZzZXQrK107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRmlsbCBvdXQgdGhlIGxhc3QgZGF0YSBibG9jayBpbiB0aGUgbG9uZ2VyIG9uZXNcbiAgICAgICAgICAgIGNvbnN0IHNwZWNpYWxWZXJzaW9uID0gdmVyc2lvbi5nZXRWZXJzaW9uTnVtYmVyKCkgPT09IDI0O1xuICAgICAgICAgICAgY29uc3QgbnVtTG9uZ2VyQmxvY2tzID0gc3BlY2lhbFZlcnNpb24gPyA4IDogbnVtUmVzdWx0QmxvY2tzO1xuICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBudW1Mb25nZXJCbG9ja3M7IGorKykge1xuICAgICAgICAgICAgICAgIHJlc3VsdFtqXS5jb2Rld29yZHNbbG9uZ2VyQmxvY2tzTnVtRGF0YUNvZGV3b3JkcyAtIDFdID0gcmF3Q29kZXdvcmRzW3Jhd0NvZGV3b3Jkc09mZnNldCsrXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE5vdyBhZGQgaW4gZXJyb3IgY29ycmVjdGlvbiBibG9ja3NcbiAgICAgICAgICAgIGNvbnN0IG1heCA9IHJlc3VsdFswXS5jb2Rld29yZHMubGVuZ3RoO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGxvbmdlckJsb2Nrc051bURhdGFDb2Rld29yZHM7IGkgPCBtYXg7IGkrKykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgbnVtUmVzdWx0QmxvY2tzOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgak9mZnNldCA9IHNwZWNpYWxWZXJzaW9uID8gKGogKyA4KSAlIG51bVJlc3VsdEJsb2NrcyA6IGo7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGlPZmZzZXQgPSBzcGVjaWFsVmVyc2lvbiAmJiBqT2Zmc2V0ID4gNyA/IGkgLSAxIDogaTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2pPZmZzZXRdLmNvZGV3b3Jkc1tpT2Zmc2V0XSA9IHJhd0NvZGV3b3Jkc1tyYXdDb2Rld29yZHNPZmZzZXQrK107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJhd0NvZGV3b3Jkc09mZnNldCAhPT0gcmF3Q29kZXdvcmRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0TnVtRGF0YUNvZGV3b3JkcygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm51bURhdGFDb2Rld29yZHM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Q29kZXdvcmRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29kZXdvcmRzO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiA8cD5UaGlzIHByb3ZpZGVzIGFuIGVhc3kgYWJzdHJhY3Rpb24gdG8gcmVhZCBiaXRzIGF0IGEgdGltZSBmcm9tIGEgc2VxdWVuY2Ugb2YgYnl0ZXMsIHdoZXJlIHRoZVxuICAgICAqIG51bWJlciBvZiBiaXRzIHJlYWQgaXMgbm90IG9mdGVuIGEgbXVsdGlwbGUgb2YgOC48L3A+XG4gICAgICpcbiAgICAgKiA8cD5UaGlzIGNsYXNzIGlzIHRocmVhZC1zYWZlIGJ1dCBub3QgcmVlbnRyYW50IC0tIHVubGVzcyB0aGUgY2FsbGVyIG1vZGlmaWVzIHRoZSBieXRlcyBhcnJheVxuICAgICAqIGl0IHBhc3NlZCBpbiwgaW4gd2hpY2ggY2FzZSBhbGwgYmV0cyBhcmUgb2ZmLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgQml0U291cmNlIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBieXRlcyBieXRlcyBmcm9tIHdoaWNoIHRoaXMgd2lsbCByZWFkIGJpdHMuIEJpdHMgd2lsbCBiZSByZWFkIGZyb20gdGhlIGZpcnN0IGJ5dGUgZmlyc3QuXG4gICAgICAgICAqIEJpdHMgYXJlIHJlYWQgd2l0aGluIGEgYnl0ZSBmcm9tIG1vc3Qtc2lnbmlmaWNhbnQgdG8gbGVhc3Qtc2lnbmlmaWNhbnQgYml0LlxuICAgICAgICAgKi9cbiAgICAgICAgY29uc3RydWN0b3IoYnl0ZXMpIHtcbiAgICAgICAgICAgIHRoaXMuYnl0ZXMgPSBieXRlcztcbiAgICAgICAgICAgIHRoaXMuYnl0ZU9mZnNldCA9IDA7XG4gICAgICAgICAgICB0aGlzLmJpdE9mZnNldCA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gaW5kZXggb2YgbmV4dCBiaXQgaW4gY3VycmVudCBieXRlIHdoaWNoIHdvdWxkIGJlIHJlYWQgYnkgdGhlIG5leHQgY2FsbCB0byB7QGxpbmsgI3JlYWRCaXRzKGludCl9LlxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0Qml0T2Zmc2V0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYml0T2Zmc2V0O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIGluZGV4IG9mIG5leHQgYnl0ZSBpbiBpbnB1dCBieXRlIGFycmF5IHdoaWNoIHdvdWxkIGJlIHJlYWQgYnkgdGhlIG5leHQgY2FsbCB0byB7QGxpbmsgI3JlYWRCaXRzKGludCl9LlxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0Qnl0ZU9mZnNldCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJ5dGVPZmZzZXQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBudW1CaXRzIG51bWJlciBvZiBiaXRzIHRvIHJlYWRcbiAgICAgICAgICogQHJldHVybiBpbnQgcmVwcmVzZW50aW5nIHRoZSBiaXRzIHJlYWQuIFRoZSBiaXRzIHdpbGwgYXBwZWFyIGFzIHRoZSBsZWFzdC1zaWduaWZpY2FudFxuICAgICAgICAgKiAgICAgICAgIGJpdHMgb2YgdGhlIGludFxuICAgICAgICAgKiBAdGhyb3dzIElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbiBpZiBudW1CaXRzIGlzbid0IGluIFsxLDMyXSBvciBtb3JlIHRoYW4gaXMgYXZhaWxhYmxlXG4gICAgICAgICAqL1xuICAgICAgICByZWFkQml0cyhudW1CaXRzIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGlmIChudW1CaXRzIDwgMSB8fCBudW1CaXRzID4gMzIgfHwgbnVtQml0cyA+IHRoaXMuYXZhaWxhYmxlKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCcnICsgbnVtQml0cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gMDtcbiAgICAgICAgICAgIGxldCBiaXRPZmZzZXQgPSB0aGlzLmJpdE9mZnNldDtcbiAgICAgICAgICAgIGxldCBieXRlT2Zmc2V0ID0gdGhpcy5ieXRlT2Zmc2V0O1xuICAgICAgICAgICAgY29uc3QgYnl0ZXMgPSB0aGlzLmJ5dGVzO1xuICAgICAgICAgICAgLy8gRmlyc3QsIHJlYWQgcmVtYWluZGVyIGZyb20gY3VycmVudCBieXRlXG4gICAgICAgICAgICBpZiAoYml0T2Zmc2V0ID4gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGJpdHNMZWZ0ID0gOCAtIGJpdE9mZnNldDtcbiAgICAgICAgICAgICAgICBjb25zdCB0b1JlYWQgPSBudW1CaXRzIDwgYml0c0xlZnQgPyBudW1CaXRzIDogYml0c0xlZnQ7XG4gICAgICAgICAgICAgICAgY29uc3QgYml0c1RvTm90UmVhZCA9IGJpdHNMZWZ0IC0gdG9SZWFkO1xuICAgICAgICAgICAgICAgIGNvbnN0IG1hc2sgPSAoMHhGRiA+PiAoOCAtIHRvUmVhZCkpIDw8IGJpdHNUb05vdFJlYWQ7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gKGJ5dGVzW2J5dGVPZmZzZXRdICYgbWFzaykgPj4gYml0c1RvTm90UmVhZDtcbiAgICAgICAgICAgICAgICBudW1CaXRzIC09IHRvUmVhZDtcbiAgICAgICAgICAgICAgICBiaXRPZmZzZXQgKz0gdG9SZWFkO1xuICAgICAgICAgICAgICAgIGlmIChiaXRPZmZzZXQgPT09IDgpIHtcbiAgICAgICAgICAgICAgICAgICAgYml0T2Zmc2V0ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgYnl0ZU9mZnNldCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE5leHQgcmVhZCB3aG9sZSBieXRlc1xuICAgICAgICAgICAgaWYgKG51bUJpdHMgPiAwKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKG51bUJpdHMgPj0gOCkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSAocmVzdWx0IDw8IDgpIHwgKGJ5dGVzW2J5dGVPZmZzZXRdICYgMHhGRik7XG4gICAgICAgICAgICAgICAgICAgIGJ5dGVPZmZzZXQrKztcbiAgICAgICAgICAgICAgICAgICAgbnVtQml0cyAtPSA4O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBGaW5hbGx5IHJlYWQgYSBwYXJ0aWFsIGJ5dGVcbiAgICAgICAgICAgICAgICBpZiAobnVtQml0cyA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYml0c1RvTm90UmVhZCA9IDggLSBudW1CaXRzO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXNrID0gKDB4RkYgPj4gYml0c1RvTm90UmVhZCkgPDwgYml0c1RvTm90UmVhZDtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gKHJlc3VsdCA8PCBudW1CaXRzKSB8ICgoYnl0ZXNbYnl0ZU9mZnNldF0gJiBtYXNrKSA+PiBiaXRzVG9Ob3RSZWFkKTtcbiAgICAgICAgICAgICAgICAgICAgYml0T2Zmc2V0ICs9IG51bUJpdHM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5iaXRPZmZzZXQgPSBiaXRPZmZzZXQ7XG4gICAgICAgICAgICB0aGlzLmJ5dGVPZmZzZXQgPSBieXRlT2Zmc2V0O1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBudW1iZXIgb2YgYml0cyB0aGF0IGNhbiBiZSByZWFkIHN1Y2Nlc3NmdWxseVxuICAgICAgICAgKi9cbiAgICAgICAgYXZhaWxhYmxlKCkge1xuICAgICAgICAgICAgcmV0dXJuIDggKiAodGhpcy5ieXRlcy5sZW5ndGggLSB0aGlzLmJ5dGVPZmZzZXQpIC0gdGhpcy5iaXRPZmZzZXQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgTW9kZTtcbiAgICAoZnVuY3Rpb24gKE1vZGUpIHtcbiAgICAgICAgTW9kZVtNb2RlW1wiUEFEX0VOQ09ERVwiXSA9IDBdID0gXCJQQURfRU5DT0RFXCI7XG4gICAgICAgIE1vZGVbTW9kZVtcIkFTQ0lJX0VOQ09ERVwiXSA9IDFdID0gXCJBU0NJSV9FTkNPREVcIjtcbiAgICAgICAgTW9kZVtNb2RlW1wiQzQwX0VOQ09ERVwiXSA9IDJdID0gXCJDNDBfRU5DT0RFXCI7XG4gICAgICAgIE1vZGVbTW9kZVtcIlRFWFRfRU5DT0RFXCJdID0gM10gPSBcIlRFWFRfRU5DT0RFXCI7XG4gICAgICAgIE1vZGVbTW9kZVtcIkFOU0lYMTJfRU5DT0RFXCJdID0gNF0gPSBcIkFOU0lYMTJfRU5DT0RFXCI7XG4gICAgICAgIE1vZGVbTW9kZVtcIkVESUZBQ1RfRU5DT0RFXCJdID0gNV0gPSBcIkVESUZBQ1RfRU5DT0RFXCI7XG4gICAgICAgIE1vZGVbTW9kZVtcIkJBU0UyNTZfRU5DT0RFXCJdID0gNl0gPSBcIkJBU0UyNTZfRU5DT0RFXCI7XG4gICAgfSkoTW9kZSB8fCAoTW9kZSA9IHt9KSk7XG4gICAgLyoqXG4gICAgICogPHA+RGF0YSBNYXRyaXggQ29kZXMgY2FuIGVuY29kZSB0ZXh0IGFzIGJpdHMgaW4gb25lIG9mIHNldmVyYWwgbW9kZXMsIGFuZCBjYW4gdXNlIG11bHRpcGxlIG1vZGVzXG4gICAgICogaW4gb25lIERhdGEgTWF0cml4IENvZGUuIFRoaXMgY2xhc3MgZGVjb2RlcyB0aGUgYml0cyBiYWNrIGludG8gdGV4dC48L3A+XG4gICAgICpcbiAgICAgKiA8cD5TZWUgSVNPIDE2MDIyOjIwMDYsIDUuMi4xIC0gNS4yLjkuMjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgYmJyb3duQGdvb2dsZS5jb20gKEJyaWFuIEJyb3duKVxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciB7XG4gICAgICAgIHN0YXRpYyBkZWNvZGUoYnl0ZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IGJpdHMgPSBuZXcgQml0U291cmNlKGJ5dGVzKTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICBjb25zdCByZXN1bHRUcmFpbGVyID0gbmV3IFN0cmluZ0J1aWxkZXIoKTtcbiAgICAgICAgICAgIGNvbnN0IGJ5dGVTZWdtZW50cyA9IG5ldyBBcnJheSgpO1xuICAgICAgICAgICAgbGV0IG1vZGUgPSBNb2RlLkFTQ0lJX0VOQ09ERTtcbiAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICBpZiAobW9kZSA9PT0gTW9kZS5BU0NJSV9FTkNPREUpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kZSA9IHRoaXMuZGVjb2RlQXNjaWlTZWdtZW50KGJpdHMsIHJlc3VsdCwgcmVzdWx0VHJhaWxlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKG1vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgTW9kZS5DNDBfRU5DT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVjb2RlQzQwU2VnbWVudChiaXRzLCByZXN1bHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBNb2RlLlRFWFRfRU5DT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVjb2RlVGV4dFNlZ21lbnQoYml0cywgcmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgTW9kZS5BTlNJWDEyX0VOQ09ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlY29kZUFuc2lYMTJTZWdtZW50KGJpdHMsIHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIE1vZGUuRURJRkFDVF9FTkNPREU6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWNvZGVFZGlmYWN0U2VnbWVudChiaXRzLCByZXN1bHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBNb2RlLkJBU0UyNTZfRU5DT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVjb2RlQmFzZTI1NlNlZ21lbnQoYml0cywgcmVzdWx0LCBieXRlU2VnbWVudHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbW9kZSA9IE1vZGUuQVNDSUlfRU5DT0RFO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gd2hpbGUgKG1vZGUgIT09IE1vZGUuUEFEX0VOQ09ERSAmJiBiaXRzLmF2YWlsYWJsZSgpID4gMCk7XG4gICAgICAgICAgICBpZiAocmVzdWx0VHJhaWxlci5sZW5ndGgoKSA+IDApIHtcbiAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKHJlc3VsdFRyYWlsZXIudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IERlY29kZXJSZXN1bHQoYnl0ZXMsIHJlc3VsdC50b1N0cmluZygpLCBieXRlU2VnbWVudHMubGVuZ3RoID09PSAwID8gbnVsbCA6IGJ5dGVTZWdtZW50cywgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNlZSBJU08gMTYwMjI6MjAwNiwgNS4yLjMgYW5kIEFubmV4IEMsIFRhYmxlIEMuMlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGRlY29kZUFzY2lpU2VnbWVudChiaXRzLCByZXN1bHQsIHJlc3VsdFRyYWlsZXIpIHtcbiAgICAgICAgICAgIGxldCB1cHBlclNoaWZ0ID0gZmFsc2U7XG4gICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgbGV0IG9uZUJ5dGUgPSBiaXRzLnJlYWRCaXRzKDgpO1xuICAgICAgICAgICAgICAgIGlmIChvbmVCeXRlID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAob25lQnl0ZSA8PSAxMjgpIHsgLy8gQVNDSUkgZGF0YSAoQVNDSUkgdmFsdWUgKyAxKVxuICAgICAgICAgICAgICAgICAgICBpZiAodXBwZXJTaGlmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb25lQnl0ZSArPSAxMjg7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB1cHBlclNoaWZ0ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChTdHJpbmcuZnJvbUNoYXJDb2RlKG9uZUJ5dGUgLSAxKSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBNb2RlLkFTQ0lJX0VOQ09ERTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAob25lQnl0ZSA9PT0gMTI5KSB7IC8vIFBhZFxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gTW9kZS5QQURfRU5DT0RFO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChvbmVCeXRlIDw9IDIyOSkgeyAvLyAyLWRpZ2l0IGRhdGEgMDAtOTkgKE51bWVyaWMgVmFsdWUgKyAxMzApXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gb25lQnl0ZSAtIDEzMDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlIDwgMTApIHsgLy8gcGFkIHdpdGggJzAnIGZvciBzaW5nbGUgZGlnaXQgdmFsdWVzXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCcwJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnJyArIHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAob25lQnl0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyMzA6IC8vIExhdGNoIHRvIEM0MCBlbmNvZGF0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE1vZGUuQzQwX0VOQ09ERTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjMxOiAvLyBMYXRjaCB0byBCYXNlIDI1NiBlbmNvZGF0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE1vZGUuQkFTRTI1Nl9FTkNPREU7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDIzMjogLy8gRk5DMVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoU3RyaW5nLmZyb21DaGFyQ29kZSgyOSkpOyAvLyB0cmFuc2xhdGUgYXMgQVNDSUkgMjlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjMzOiAvLyBTdHJ1Y3R1cmVkIEFwcGVuZFxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyMzQ6IC8vIFJlYWRlciBQcm9ncmFtbWluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElnbm9yZSB0aGVzZSBzeW1ib2xzIGZvciBub3dcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aHJvdyBSZWFkZXJFeGNlcHRpb24uZ2V0SW5zdGFuY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjM1OiAvLyBVcHBlciBTaGlmdCAoc2hpZnQgdG8gRXh0ZW5kZWQgQVNDSUkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBwZXJTaGlmdCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDIzNjogLy8gMDUgTWFjcm9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCdbKT5cXHUwMDFFMDVcXHUwMDFEJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0VHJhaWxlci5pbnNlcnQoMCwgJ1xcdTAwMUVcXHUwMDA0Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDIzNzogLy8gMDYgTWFjcm9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCdbKT5cXHUwMDFFMDZcXHUwMDFEJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0VHJhaWxlci5pbnNlcnQoMCwgJ1xcdTAwMUVcXHUwMDA0Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDIzODogLy8gTGF0Y2ggdG8gQU5TSSBYMTIgZW5jb2RhdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBNb2RlLkFOU0lYMTJfRU5DT0RFO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyMzk6IC8vIExhdGNoIHRvIFRleHQgZW5jb2RhdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBNb2RlLlRFWFRfRU5DT0RFO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyNDA6IC8vIExhdGNoIHRvIEVESUZBQ1QgZW5jb2RhdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBNb2RlLkVESUZBQ1RfRU5DT0RFO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyNDE6IC8vIEVDSSBDaGFyYWN0ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUT0RPKGJicm93bik6IEkgdGhpbmsgd2UgbmVlZCB0byBzdXBwb3J0IEVDSVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRocm93IFJlYWRlckV4Y2VwdGlvbi5nZXRJbnN0YW5jZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElnbm9yZSB0aGlzIHN5bWJvbCBmb3Igbm93XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5vdCB0byBiZSB1c2VkIGluIEFTQ0lJIGVuY29kYXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBidXQgd29yayBhcm91bmQgZW5jb2RlcnMgdGhhdCBlbmQgd2l0aCAyNTQsIGxhdGNoIGJhY2sgdG8gQVNDSUlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob25lQnl0ZSAhPT0gMjU0IHx8IGJpdHMuYXZhaWxhYmxlKCkgIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gd2hpbGUgKGJpdHMuYXZhaWxhYmxlKCkgPiAwKTtcbiAgICAgICAgICAgIHJldHVybiBNb2RlLkFTQ0lJX0VOQ09ERTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogU2VlIElTTyAxNjAyMjoyMDA2LCA1LjIuNSBhbmQgQW5uZXggQywgVGFibGUgQy4xXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGVjb2RlQzQwU2VnbWVudChiaXRzLCByZXN1bHQpIHtcbiAgICAgICAgICAgIC8vIFRocmVlIEM0MCB2YWx1ZXMgYXJlIGVuY29kZWQgaW4gYSAxNi1iaXQgdmFsdWUgYXNcbiAgICAgICAgICAgIC8vICgxNjAwICogQzEpICsgKDQwICogQzIpICsgQzMgKyAxXG4gICAgICAgICAgICAvLyBUT0RPKGJicm93bik6IFRoZSBVcHBlciBTaGlmdCB3aXRoIEM0MCBkb2Vzbid0IHdvcmsgaW4gdGhlIDQgdmFsdWUgc2NlbmFyaW8gYWxsIHRoZSB0aW1lXG4gICAgICAgICAgICBsZXQgdXBwZXJTaGlmdCA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3QgY1ZhbHVlcyA9IFtdO1xuICAgICAgICAgICAgbGV0IHNoaWZ0ID0gMDtcbiAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGVyZSBpcyBvbmx5IG9uZSBieXRlIGxlZnQgdGhlbiBpdCB3aWxsIGJlIGVuY29kZWQgYXMgQVNDSUlcbiAgICAgICAgICAgICAgICBpZiAoYml0cy5hdmFpbGFibGUoKSA9PT0gOCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGZpcnN0Qnl0ZSA9IGJpdHMucmVhZEJpdHMoOCk7XG4gICAgICAgICAgICAgICAgaWYgKGZpcnN0Qnl0ZSA9PT0gMjU0KSB7IC8vIFVubGF0Y2ggY29kZXdvcmRcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnBhcnNlVHdvQnl0ZXMoZmlyc3RCeXRlLCBiaXRzLnJlYWRCaXRzKDgpLCBjVmFsdWVzKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDM7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjVmFsdWUgPSBjVmFsdWVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHNoaWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNWYWx1ZSA8IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hpZnQgPSBjVmFsdWUgKyAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChjVmFsdWUgPCB0aGlzLkM0MF9CQVNJQ19TRVRfQ0hBUlMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGM0MGNoYXIgPSB0aGlzLkM0MF9CQVNJQ19TRVRfQ0hBUlNbY1ZhbHVlXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHVwcGVyU2hpZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoU3RyaW5nLmZyb21DaGFyQ29kZShjNDBjaGFyLmNoYXJDb2RlQXQoMCkgKyAxMjgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwcGVyU2hpZnQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoYzQwY2hhcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHVwcGVyU2hpZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChTdHJpbmcuZnJvbUNoYXJDb2RlKGNWYWx1ZSArIDEyOCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cHBlclNoaWZ0ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKFN0cmluZy5mcm9tQ2hhckNvZGUoY1ZhbHVlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoaWZ0ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY1ZhbHVlIDwgdGhpcy5DNDBfU0hJRlQyX1NFVF9DSEFSUy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYzQwY2hhciA9IHRoaXMuQzQwX1NISUZUMl9TRVRfQ0hBUlNbY1ZhbHVlXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHVwcGVyU2hpZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoU3RyaW5nLmZyb21DaGFyQ29kZShjNDBjaGFyLmNoYXJDb2RlQXQoMCkgKyAxMjgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwcGVyU2hpZnQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoYzQwY2hhcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoY1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDI3OiAvLyBGTkMxXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChTdHJpbmcuZnJvbUNoYXJDb2RlKDI5KSk7IC8vIHRyYW5zbGF0ZSBhcyBBU0NJSSAyOVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAzMDogLy8gVXBwZXIgU2hpZnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cHBlclNoaWZ0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoaWZ0ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodXBwZXJTaGlmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKFN0cmluZy5mcm9tQ2hhckNvZGUoY1ZhbHVlICsgMjI0KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwcGVyU2hpZnQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoU3RyaW5nLmZyb21DaGFyQ29kZShjVmFsdWUgKyA5NikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaGlmdCA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gd2hpbGUgKGJpdHMuYXZhaWxhYmxlKCkgPiAwKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogU2VlIElTTyAxNjAyMjoyMDA2LCA1LjIuNiBhbmQgQW5uZXggQywgVGFibGUgQy4yXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGVjb2RlVGV4dFNlZ21lbnQoYml0cywgcmVzdWx0KSB7XG4gICAgICAgICAgICAvLyBUaHJlZSBUZXh0IHZhbHVlcyBhcmUgZW5jb2RlZCBpbiBhIDE2LWJpdCB2YWx1ZSBhc1xuICAgICAgICAgICAgLy8gKDE2MDAgKiBDMSkgKyAoNDAgKiBDMikgKyBDMyArIDFcbiAgICAgICAgICAgIC8vIFRPRE8oYmJyb3duKTogVGhlIFVwcGVyIFNoaWZ0IHdpdGggVGV4dCBkb2Vzbid0IHdvcmsgaW4gdGhlIDQgdmFsdWUgc2NlbmFyaW8gYWxsIHRoZSB0aW1lXG4gICAgICAgICAgICBsZXQgdXBwZXJTaGlmdCA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGNWYWx1ZXMgPSBbXTtcbiAgICAgICAgICAgIGxldCBzaGlmdCA9IDA7XG4gICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlcmUgaXMgb25seSBvbmUgYnl0ZSBsZWZ0IHRoZW4gaXQgd2lsbCBiZSBlbmNvZGVkIGFzIEFTQ0lJXG4gICAgICAgICAgICAgICAgaWYgKGJpdHMuYXZhaWxhYmxlKCkgPT09IDgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBmaXJzdEJ5dGUgPSBiaXRzLnJlYWRCaXRzKDgpO1xuICAgICAgICAgICAgICAgIGlmIChmaXJzdEJ5dGUgPT09IDI1NCkgeyAvLyBVbmxhdGNoIGNvZGV3b3JkXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5wYXJzZVR3b0J5dGVzKGZpcnN0Qnl0ZSwgYml0cy5yZWFkQml0cyg4KSwgY1ZhbHVlcyk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY1ZhbHVlID0gY1ZhbHVlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChzaGlmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjVmFsdWUgPCAzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoaWZ0ID0gY1ZhbHVlICsgMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoY1ZhbHVlIDwgdGhpcy5URVhUX0JBU0lDX1NFVF9DSEFSUy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGV4dENoYXIgPSB0aGlzLlRFWFRfQkFTSUNfU0VUX0NIQVJTW2NWYWx1ZV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh1cHBlclNoaWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKFN0cmluZy5mcm9tQ2hhckNvZGUodGV4dENoYXIuY2hhckNvZGVBdCgwKSArIDEyOCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBwZXJTaGlmdCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCh0ZXh0Q2hhcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHVwcGVyU2hpZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChTdHJpbmcuZnJvbUNoYXJDb2RlKGNWYWx1ZSArIDEyOCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cHBlclNoaWZ0ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKFN0cmluZy5mcm9tQ2hhckNvZGUoY1ZhbHVlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoaWZ0ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaGlmdCAyIGZvciBUZXh0IGlzIHRoZSBzYW1lIGVuY29kaW5nIGFzIEM0MFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjVmFsdWUgPCB0aGlzLlRFWFRfU0hJRlQyX1NFVF9DSEFSUy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGV4dENoYXIgPSB0aGlzLlRFWFRfU0hJRlQyX1NFVF9DSEFSU1tjVmFsdWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodXBwZXJTaGlmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChTdHJpbmcuZnJvbUNoYXJDb2RlKHRleHRDaGFyLmNoYXJDb2RlQXQoMCkgKyAxMjgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwcGVyU2hpZnQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQodGV4dENoYXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyNzogLy8gRk5DMVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoU3RyaW5nLmZyb21DaGFyQ29kZSgyOSkpOyAvLyB0cmFuc2xhdGUgYXMgQVNDSUkgMjlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMzA6IC8vIFVwcGVyIFNoaWZ0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBwZXJTaGlmdCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaGlmdCA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNWYWx1ZSA8IHRoaXMuVEVYVF9TSElGVDNfU0VUX0NIQVJTLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZXh0Q2hhciA9IHRoaXMuVEVYVF9TSElGVDNfU0VUX0NIQVJTW2NWYWx1ZV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh1cHBlclNoaWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKFN0cmluZy5mcm9tQ2hhckNvZGUodGV4dENoYXIuY2hhckNvZGVBdCgwKSArIDEyOCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBwZXJTaGlmdCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCh0ZXh0Q2hhcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hpZnQgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSB3aGlsZSAoYml0cy5hdmFpbGFibGUoKSA+IDApO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZWUgSVNPIDE2MDIyOjIwMDYsIDUuMi43XG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGVjb2RlQW5zaVgxMlNlZ21lbnQoYml0cywgcmVzdWx0KSB7XG4gICAgICAgICAgICAvLyBUaHJlZSBBTlNJIFgxMiB2YWx1ZXMgYXJlIGVuY29kZWQgaW4gYSAxNi1iaXQgdmFsdWUgYXNcbiAgICAgICAgICAgIC8vICgxNjAwICogQzEpICsgKDQwICogQzIpICsgQzMgKyAxXG4gICAgICAgICAgICBjb25zdCBjVmFsdWVzID0gW107XG4gICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlcmUgaXMgb25seSBvbmUgYnl0ZSBsZWZ0IHRoZW4gaXQgd2lsbCBiZSBlbmNvZGVkIGFzIEFTQ0lJXG4gICAgICAgICAgICAgICAgaWYgKGJpdHMuYXZhaWxhYmxlKCkgPT09IDgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBmaXJzdEJ5dGUgPSBiaXRzLnJlYWRCaXRzKDgpO1xuICAgICAgICAgICAgICAgIGlmIChmaXJzdEJ5dGUgPT09IDI1NCkgeyAvLyBVbmxhdGNoIGNvZGV3b3JkXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5wYXJzZVR3b0J5dGVzKGZpcnN0Qnl0ZSwgYml0cy5yZWFkQml0cyg4KSwgY1ZhbHVlcyk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY1ZhbHVlID0gY1ZhbHVlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChjVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMDogLy8gWDEyIHNlZ21lbnQgdGVybWluYXRvciA8Q1I+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnXFxyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDE6IC8vIFgxMiBzZWdtZW50IHNlcGFyYXRvciAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnKicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyOiAvLyBYMTIgc3ViLWVsZW1lbnQgc2VwYXJhdG9yID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCc+Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDM6IC8vIHNwYWNlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnICcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY1ZhbHVlIDwgMTQpIHsgLy8gMCAtIDlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChTdHJpbmcuZnJvbUNoYXJDb2RlKGNWYWx1ZSArIDQ0KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGNWYWx1ZSA8IDQwKSB7IC8vIEEgLSBaXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoU3RyaW5nLmZyb21DaGFyQ29kZShjVmFsdWUgKyA1MSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gd2hpbGUgKGJpdHMuYXZhaWxhYmxlKCkgPiAwKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgcGFyc2VUd29CeXRlcyhmaXJzdEJ5dGUsIHNlY29uZEJ5dGUsIHJlc3VsdCkge1xuICAgICAgICAgICAgbGV0IGZ1bGxCaXRWYWx1ZSA9IChmaXJzdEJ5dGUgPDwgOCkgKyBzZWNvbmRCeXRlIC0gMTtcbiAgICAgICAgICAgIGxldCB0ZW1wID0gTWF0aC5mbG9vcihmdWxsQml0VmFsdWUgLyAxNjAwKTtcbiAgICAgICAgICAgIHJlc3VsdFswXSA9IHRlbXA7XG4gICAgICAgICAgICBmdWxsQml0VmFsdWUgLT0gdGVtcCAqIDE2MDA7XG4gICAgICAgICAgICB0ZW1wID0gTWF0aC5mbG9vcihmdWxsQml0VmFsdWUgLyA0MCk7XG4gICAgICAgICAgICByZXN1bHRbMV0gPSB0ZW1wO1xuICAgICAgICAgICAgcmVzdWx0WzJdID0gZnVsbEJpdFZhbHVlIC0gdGVtcCAqIDQwO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZWUgSVNPIDE2MDIyOjIwMDYsIDUuMi44IGFuZCBBbm5leCBDIFRhYmxlIEMuM1xuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGRlY29kZUVkaWZhY3RTZWdtZW50KGJpdHMsIHJlc3VsdCkge1xuICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZXJlIGlzIG9ubHkgdHdvIG9yIGxlc3MgYnl0ZXMgbGVmdCB0aGVuIGl0IHdpbGwgYmUgZW5jb2RlZCBhcyBBU0NJSVxuICAgICAgICAgICAgICAgIGlmIChiaXRzLmF2YWlsYWJsZSgpIDw9IDE2KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCA0OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGVkaWZhY3RWYWx1ZSA9IGJpdHMucmVhZEJpdHMoNik7XG4gICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIGZvciB0aGUgdW5sYXRjaCBjaGFyYWN0ZXJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVkaWZhY3RWYWx1ZSA9PT0gMHgxRikgeyAvLyAwMTExMTFcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlYWQgcmVzdCBvZiBieXRlLCB3aGljaCBzaG91bGQgYmUgMCwgYW5kIHN0b3BcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJpdHNMZWZ0ID0gOCAtIGJpdHMuZ2V0Qml0T2Zmc2V0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYml0c0xlZnQgIT09IDgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaXRzLnJlYWRCaXRzKGJpdHNMZWZ0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoKGVkaWZhY3RWYWx1ZSAmIDB4MjApID09PSAwKSB7IC8vIG5vIDEgaW4gdGhlIGxlYWRpbmcgKDZ0aCkgYml0XG4gICAgICAgICAgICAgICAgICAgICAgICBlZGlmYWN0VmFsdWUgfD0gMHg0MDsgLy8gQWRkIGEgbGVhZGluZyAwMSB0byB0aGUgNiBiaXQgYmluYXJ5IHZhbHVlXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChTdHJpbmcuZnJvbUNoYXJDb2RlKGVkaWZhY3RWYWx1ZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gd2hpbGUgKGJpdHMuYXZhaWxhYmxlKCkgPiAwKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogU2VlIElTTyAxNjAyMjoyMDA2LCA1LjIuOSBhbmQgQW5uZXggQiwgQi4yXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGVjb2RlQmFzZTI1NlNlZ21lbnQoYml0cywgcmVzdWx0LCBieXRlU2VnbWVudHMpIHtcbiAgICAgICAgICAgIC8vIEZpZ3VyZSBvdXQgaG93IGxvbmcgdGhlIEJhc2UgMjU2IFNlZ21lbnQgaXMuXG4gICAgICAgICAgICBsZXQgY29kZXdvcmRQb3NpdGlvbiA9IDEgKyBiaXRzLmdldEJ5dGVPZmZzZXQoKTsgLy8gcG9zaXRpb24gaXMgMS1pbmRleGVkXG4gICAgICAgICAgICBjb25zdCBkMSA9IHRoaXMudW5yYW5kb21pemUyNTVTdGF0ZShiaXRzLnJlYWRCaXRzKDgpLCBjb2Rld29yZFBvc2l0aW9uKyspO1xuICAgICAgICAgICAgbGV0IGNvdW50O1xuICAgICAgICAgICAgaWYgKGQxID09PSAwKSB7IC8vIFJlYWQgdGhlIHJlbWFpbmRlciBvZiB0aGUgc3ltYm9sXG4gICAgICAgICAgICAgICAgY291bnQgPSBiaXRzLmF2YWlsYWJsZSgpIC8gOCB8IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChkMSA8IDI1MCkge1xuICAgICAgICAgICAgICAgIGNvdW50ID0gZDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb3VudCA9IDI1MCAqIChkMSAtIDI0OSkgKyB0aGlzLnVucmFuZG9taXplMjU1U3RhdGUoYml0cy5yZWFkQml0cyg4KSwgY29kZXdvcmRQb3NpdGlvbisrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFdlJ3JlIHNlZWluZyBOZWdhdGl2ZUFycmF5U2l6ZUV4Y2VwdGlvbiBlcnJvcnMgZnJvbSB1c2Vycy5cbiAgICAgICAgICAgIGlmIChjb3VudCA8IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBieXRlcyA9IG5ldyBVaW50OEFycmF5KGNvdW50KTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgIC8vIEhhdmUgc2VlbiB0aGlzIHBhcnRpY3VsYXIgZXJyb3IgaW4gdGhlIHdpbGQsIHN1Y2ggYXMgYXRcbiAgICAgICAgICAgICAgICAvLyBodHRwOi8vd3d3LmJjZ2VuLmNvbS9kZW1vL0lEQXV0b21hdGlvblN0cmVhbWluZ0RhdGFNYXRyaXguYXNweD9NT0RFPTMmRD1GcmVkJlBGTVQ9MyZQVD1GJlg9MC4zJk89MCZMTT0wLjJcbiAgICAgICAgICAgICAgICBpZiAoYml0cy5hdmFpbGFibGUoKSA8IDgpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBieXRlc1tpXSA9IHRoaXMudW5yYW5kb21pemUyNTVTdGF0ZShiaXRzLnJlYWRCaXRzKDgpLCBjb2Rld29yZFBvc2l0aW9uKyspO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnl0ZVNlZ21lbnRzLnB1c2goYnl0ZXMpO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKFN0cmluZ0VuY29kaW5nLmRlY29kZShieXRlcywgU3RyaW5nVXRpbHMuSVNPODg1OTEpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoICh1ZWUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCdQbGF0Zm9ybSBkb2VzIG5vdCBzdXBwb3J0IHJlcXVpcmVkIGVuY29kaW5nOiAnICsgdWVlLm1lc3NhZ2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZWUgSVNPIDE2MDIyOjIwMDYsIEFubmV4IEIsIEIuMlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIHVucmFuZG9taXplMjU1U3RhdGUocmFuZG9taXplZEJhc2UyNTZDb2Rld29yZCwgYmFzZTI1NkNvZGV3b3JkUG9zaXRpb24pIHtcbiAgICAgICAgICAgIGNvbnN0IHBzZXVkb1JhbmRvbU51bWJlciA9ICgoMTQ5ICogYmFzZTI1NkNvZGV3b3JkUG9zaXRpb24pICUgMjU1KSArIDE7XG4gICAgICAgICAgICBjb25zdCB0ZW1wVmFyaWFibGUgPSByYW5kb21pemVkQmFzZTI1NkNvZGV3b3JkIC0gcHNldWRvUmFuZG9tTnVtYmVyO1xuICAgICAgICAgICAgcmV0dXJuIHRlbXBWYXJpYWJsZSA+PSAwID8gdGVtcFZhcmlhYmxlIDogdGVtcFZhcmlhYmxlICsgMjU2O1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNlZSBJU08gMTYwMjI6MjAwNiwgQW5uZXggQyBUYWJsZSBDLjFcbiAgICAgKiBUaGUgQzQwIEJhc2ljIENoYXJhY3RlciBTZXQgKConcyB1c2VkIGZvciBwbGFjZWhvbGRlcnMgZm9yIHRoZSBzaGlmdCB2YWx1ZXMpXG4gICAgICovXG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlci5DNDBfQkFTSUNfU0VUX0NIQVJTID0gW1xuICAgICAgICAnKicsICcqJywgJyonLCAnICcsICcwJywgJzEnLCAnMicsICczJywgJzQnLCAnNScsICc2JywgJzcnLCAnOCcsICc5JyxcbiAgICAgICAgJ0EnLCAnQicsICdDJywgJ0QnLCAnRScsICdGJywgJ0cnLCAnSCcsICdJJywgJ0onLCAnSycsICdMJywgJ00nLCAnTicsXG4gICAgICAgICdPJywgJ1AnLCAnUScsICdSJywgJ1MnLCAnVCcsICdVJywgJ1YnLCAnVycsICdYJywgJ1knLCAnWidcbiAgICBdO1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIuQzQwX1NISUZUMl9TRVRfQ0hBUlMgPSBbXG4gICAgICAgICchJywgJ1wiJywgJyMnLCAnJCcsICclJywgJyYnLCAnXFwnJywgJygnLCAnKScsICcqJywgJysnLCAnLCcsICctJywgJy4nLFxuICAgICAgICAnLycsICc6JywgJzsnLCAnPCcsICc9JywgJz4nLCAnPycsICdAJywgJ1snLCAnXFxcXCcsICddJywgJ14nLCAnXydcbiAgICBdO1xuICAgIC8qKlxuICAgICAqIFNlZSBJU08gMTYwMjI6MjAwNiwgQW5uZXggQyBUYWJsZSBDLjJcbiAgICAgKiBUaGUgVGV4dCBCYXNpYyBDaGFyYWN0ZXIgU2V0ICgqJ3MgdXNlZCBmb3IgcGxhY2Vob2xkZXJzIGZvciB0aGUgc2hpZnQgdmFsdWVzKVxuICAgICAqL1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIuVEVYVF9CQVNJQ19TRVRfQ0hBUlMgPSBbXG4gICAgICAgICcqJywgJyonLCAnKicsICcgJywgJzAnLCAnMScsICcyJywgJzMnLCAnNCcsICc1JywgJzYnLCAnNycsICc4JywgJzknLFxuICAgICAgICAnYScsICdiJywgJ2MnLCAnZCcsICdlJywgJ2YnLCAnZycsICdoJywgJ2knLCAnaicsICdrJywgJ2wnLCAnbScsICduJyxcbiAgICAgICAgJ28nLCAncCcsICdxJywgJ3InLCAncycsICd0JywgJ3UnLCAndicsICd3JywgJ3gnLCAneScsICd6J1xuICAgIF07XG4gICAgLy8gU2hpZnQgMiBmb3IgVGV4dCBpcyB0aGUgc2FtZSBlbmNvZGluZyBhcyBDNDBcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyLlRFWFRfU0hJRlQyX1NFVF9DSEFSUyA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIuQzQwX1NISUZUMl9TRVRfQ0hBUlM7XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlci5URVhUX1NISUZUM19TRVRfQ0hBUlMgPSBbXG4gICAgICAgICdgJywgJ0EnLCAnQicsICdDJywgJ0QnLCAnRScsICdGJywgJ0cnLCAnSCcsICdJJywgJ0onLCAnSycsICdMJywgJ00nLCAnTicsXG4gICAgICAgICdPJywgJ1AnLCAnUScsICdSJywgJ1MnLCAnVCcsICdVJywgJ1YnLCAnVycsICdYJywgJ1knLCAnWicsICd7JywgJ3wnLCAnfScsICd+JywgU3RyaW5nLmZyb21DaGFyQ29kZSgxMjcpXG4gICAgXTtcblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogPHA+VGhlIG1haW4gY2xhc3Mgd2hpY2ggaW1wbGVtZW50cyBEYXRhIE1hdHJpeCBDb2RlIGRlY29kaW5nIC0tIGFzIG9wcG9zZWQgdG8gbG9jYXRpbmcgYW5kIGV4dHJhY3RpbmdcbiAgICAgKiB0aGUgRGF0YSBNYXRyaXggQ29kZSBmcm9tIGFuIGltYWdlLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgYmJyb3duQGdvb2dsZS5jb20gKEJyaWFuIEJyb3duKVxuICAgICAqL1xuICAgIGNsYXNzIERlY29kZXIkMSB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgdGhpcy5yc0RlY29kZXIgPSBuZXcgUmVlZFNvbG9tb25EZWNvZGVyKEdlbmVyaWNHRi5EQVRBX01BVFJJWF9GSUVMRF8yNTYpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5EZWNvZGVzIGEgRGF0YSBNYXRyaXggQ29kZSByZXByZXNlbnRlZCBhcyBhIHtAbGluayBCaXRNYXRyaXh9LiBBIDEgb3IgXCJ0cnVlXCIgaXMgdGFrZW5cbiAgICAgICAgICogdG8gbWVhbiBhIGJsYWNrIG1vZHVsZS48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBiaXRzIGJvb2xlYW5zIHJlcHJlc2VudGluZyB3aGl0ZS9ibGFjayBEYXRhIE1hdHJpeCBDb2RlIG1vZHVsZXNcbiAgICAgICAgICogQHJldHVybiB0ZXh0IGFuZCBieXRlcyBlbmNvZGVkIHdpdGhpbiB0aGUgRGF0YSBNYXRyaXggQ29kZVxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvbiBpZiB0aGUgRGF0YSBNYXRyaXggQ29kZSBjYW5ub3QgYmUgZGVjb2RlZFxuICAgICAgICAgKiBAdGhyb3dzIENoZWNrc3VtRXhjZXB0aW9uIGlmIGVycm9yIGNvcnJlY3Rpb24gZmFpbHNcbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZShiaXRzKSB7XG4gICAgICAgICAgICAvLyBDb25zdHJ1Y3QgYSBwYXJzZXIgYW5kIHJlYWQgdmVyc2lvbiwgZXJyb3ItY29ycmVjdGlvbiBsZXZlbFxuICAgICAgICAgICAgY29uc3QgcGFyc2VyID0gbmV3IEJpdE1hdHJpeFBhcnNlcihiaXRzKTtcbiAgICAgICAgICAgIGNvbnN0IHZlcnNpb24gPSBwYXJzZXIuZ2V0VmVyc2lvbigpO1xuICAgICAgICAgICAgLy8gUmVhZCBjb2Rld29yZHNcbiAgICAgICAgICAgIGNvbnN0IGNvZGV3b3JkcyA9IHBhcnNlci5yZWFkQ29kZXdvcmRzKCk7XG4gICAgICAgICAgICAvLyBTZXBhcmF0ZSBpbnRvIGRhdGEgYmxvY2tzXG4gICAgICAgICAgICBjb25zdCBkYXRhQmxvY2tzID0gRGF0YUJsb2NrLmdldERhdGFCbG9ja3MoY29kZXdvcmRzLCB2ZXJzaW9uKTtcbiAgICAgICAgICAgIC8vIENvdW50IHRvdGFsIG51bWJlciBvZiBkYXRhIGJ5dGVzXG4gICAgICAgICAgICBsZXQgdG90YWxCeXRlcyA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBkYiBvZiBkYXRhQmxvY2tzKSB7XG4gICAgICAgICAgICAgICAgdG90YWxCeXRlcyArPSBkYi5nZXROdW1EYXRhQ29kZXdvcmRzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXN1bHRCeXRlcyA9IG5ldyBVaW50OEFycmF5KHRvdGFsQnl0ZXMpO1xuICAgICAgICAgICAgY29uc3QgZGF0YUJsb2Nrc0NvdW50ID0gZGF0YUJsb2Nrcy5sZW5ndGg7XG4gICAgICAgICAgICAvLyBFcnJvci1jb3JyZWN0IGFuZCBjb3B5IGRhdGEgYmxvY2tzIHRvZ2V0aGVyIGludG8gYSBzdHJlYW0gb2YgYnl0ZXNcbiAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgZGF0YUJsb2Nrc0NvdW50OyBqKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhQmxvY2sgPSBkYXRhQmxvY2tzW2pdO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvZGV3b3JkQnl0ZXMgPSBkYXRhQmxvY2suZ2V0Q29kZXdvcmRzKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgbnVtRGF0YUNvZGV3b3JkcyA9IGRhdGFCbG9jay5nZXROdW1EYXRhQ29kZXdvcmRzKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5jb3JyZWN0RXJyb3JzKGNvZGV3b3JkQnl0ZXMsIG51bURhdGFDb2Rld29yZHMpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtRGF0YUNvZGV3b3JkczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIERlLWludGVybGFjZSBkYXRhIGJsb2Nrcy5cbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0Qnl0ZXNbaSAqIGRhdGFCbG9ja3NDb3VudCArIGpdID0gY29kZXdvcmRCeXRlc1tpXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBEZWNvZGUgdGhlIGNvbnRlbnRzIG9mIHRoYXQgc3RyZWFtIG9mIGJ5dGVzXG4gICAgICAgICAgICByZXR1cm4gRGVjb2RlZEJpdFN0cmVhbVBhcnNlci5kZWNvZGUocmVzdWx0Qnl0ZXMpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5HaXZlbiBkYXRhIGFuZCBlcnJvci1jb3JyZWN0aW9uIGNvZGV3b3JkcyByZWNlaXZlZCwgcG9zc2libHkgY29ycnVwdGVkIGJ5IGVycm9ycywgYXR0ZW1wdHMgdG9cbiAgICAgICAgICogY29ycmVjdCB0aGUgZXJyb3JzIGluLXBsYWNlIHVzaW5nIFJlZWQtU29sb21vbiBlcnJvciBjb3JyZWN0aW9uLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGNvZGV3b3JkQnl0ZXMgZGF0YSBhbmQgZXJyb3IgY29ycmVjdGlvbiBjb2Rld29yZHNcbiAgICAgICAgICogQHBhcmFtIG51bURhdGFDb2Rld29yZHMgbnVtYmVyIG9mIGNvZGV3b3JkcyB0aGF0IGFyZSBkYXRhIGJ5dGVzXG4gICAgICAgICAqIEB0aHJvd3MgQ2hlY2tzdW1FeGNlcHRpb24gaWYgZXJyb3IgY29ycmVjdGlvbiBmYWlsc1xuICAgICAgICAgKi9cbiAgICAgICAgY29ycmVjdEVycm9ycyhjb2Rld29yZEJ5dGVzLCBudW1EYXRhQ29kZXdvcmRzKSB7XG4gICAgICAgICAgICAvLyBjb25zdCBudW1Db2Rld29yZHMgPSBjb2Rld29yZEJ5dGVzLmxlbmd0aDtcbiAgICAgICAgICAgIC8vIEZpcnN0IHJlYWQgaW50byBhbiBhcnJheSBvZiBpbnRzXG4gICAgICAgICAgICBjb25zdCBjb2Rld29yZHNJbnRzID0gbmV3IEludDMyQXJyYXkoY29kZXdvcmRCeXRlcyk7XG4gICAgICAgICAgICAvLyBmb3IgKGxldCBpID0gMDsgaSA8IG51bUNvZGV3b3JkczsgaSsrKSB7XG4gICAgICAgICAgICAvLyAgIGNvZGV3b3Jkc0ludHNbaV0gPSBjb2Rld29yZEJ5dGVzW2ldICYgMHhGRjtcbiAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yc0RlY29kZXIuZGVjb2RlKGNvZGV3b3Jkc0ludHMsIGNvZGV3b3JkQnl0ZXMubGVuZ3RoIC0gbnVtRGF0YUNvZGV3b3Jkcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoaWdub3JlZCAvKiBSZWVkU29sb21vbkV4Y2VwdGlvbiAqLykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBDaGVja3N1bUV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQ29weSBiYWNrIGludG8gYXJyYXkgb2YgYnl0ZXMgLS0gb25seSBuZWVkIHRvIHdvcnJ5IGFib3V0IHRoZSBieXRlcyB0aGF0IHdlcmUgZGF0YVxuICAgICAgICAgICAgLy8gV2UgZG9uJ3QgY2FyZSBhYm91dCBlcnJvcnMgaW4gdGhlIGVycm9yLWNvcnJlY3Rpb24gY29kZXdvcmRzXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bURhdGFDb2Rld29yZHM7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvZGV3b3JkQnl0ZXNbaV0gPSBjb2Rld29yZHNJbnRzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogPHA+RW5jYXBzdWxhdGVzIGxvZ2ljIHRoYXQgY2FuIGRldGVjdCBhIERhdGEgTWF0cml4IENvZGUgaW4gYW4gaW1hZ2UsIGV2ZW4gaWYgdGhlIERhdGEgTWF0cml4IENvZGVcbiAgICAgKiBpcyByb3RhdGVkIG9yIHNrZXdlZCwgb3IgcGFydGlhbGx5IG9ic2N1cmVkLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgRGV0ZWN0b3IkMSB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGltYWdlKSB7XG4gICAgICAgICAgICB0aGlzLmltYWdlID0gaW1hZ2U7XG4gICAgICAgICAgICB0aGlzLnJlY3RhbmdsZURldGVjdG9yID0gbmV3IFdoaXRlUmVjdGFuZ2xlRGV0ZWN0b3IodGhpcy5pbWFnZSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkRldGVjdHMgYSBEYXRhIE1hdHJpeCBDb2RlIGluIGFuIGltYWdlLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiB7QGxpbmsgRGV0ZWN0b3JSZXN1bHR9IGVuY2Fwc3VsYXRpbmcgcmVzdWx0cyBvZiBkZXRlY3RpbmcgYSBEYXRhIE1hdHJpeCBDb2RlXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gaWYgbm8gRGF0YSBNYXRyaXggQ29kZSBjYW4gYmUgZm91bmRcbiAgICAgICAgICovXG4gICAgICAgIGRldGVjdCgpIHtcbiAgICAgICAgICAgIGNvbnN0IGNvcm5lclBvaW50cyA9IHRoaXMucmVjdGFuZ2xlRGV0ZWN0b3IuZGV0ZWN0KCk7XG4gICAgICAgICAgICBsZXQgcG9pbnRzID0gdGhpcy5kZXRlY3RTb2xpZDEoY29ybmVyUG9pbnRzKTtcbiAgICAgICAgICAgIHBvaW50cyA9IHRoaXMuZGV0ZWN0U29saWQyKHBvaW50cyk7XG4gICAgICAgICAgICBwb2ludHNbM10gPSB0aGlzLmNvcnJlY3RUb3BSaWdodChwb2ludHMpO1xuICAgICAgICAgICAgaWYgKCFwb2ludHNbM10pIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBvaW50cyA9IHRoaXMuc2hpZnRUb01vZHVsZUNlbnRlcihwb2ludHMpO1xuICAgICAgICAgICAgY29uc3QgdG9wTGVmdCA9IHBvaW50c1swXTtcbiAgICAgICAgICAgIGNvbnN0IGJvdHRvbUxlZnQgPSBwb2ludHNbMV07XG4gICAgICAgICAgICBjb25zdCBib3R0b21SaWdodCA9IHBvaW50c1syXTtcbiAgICAgICAgICAgIGNvbnN0IHRvcFJpZ2h0ID0gcG9pbnRzWzNdO1xuICAgICAgICAgICAgbGV0IGRpbWVuc2lvblRvcCA9IHRoaXMudHJhbnNpdGlvbnNCZXR3ZWVuKHRvcExlZnQsIHRvcFJpZ2h0KSArIDE7XG4gICAgICAgICAgICBsZXQgZGltZW5zaW9uUmlnaHQgPSB0aGlzLnRyYW5zaXRpb25zQmV0d2Vlbihib3R0b21SaWdodCwgdG9wUmlnaHQpICsgMTtcbiAgICAgICAgICAgIGlmICgoZGltZW5zaW9uVG9wICYgMHgwMSkgPT09IDEpIHtcbiAgICAgICAgICAgICAgICBkaW1lbnNpb25Ub3AgKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgoZGltZW5zaW9uUmlnaHQgJiAweDAxKSA9PT0gMSkge1xuICAgICAgICAgICAgICAgIGRpbWVuc2lvblJpZ2h0ICs9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoNCAqIGRpbWVuc2lvblRvcCA8IDcgKiBkaW1lbnNpb25SaWdodCAmJiA0ICogZGltZW5zaW9uUmlnaHQgPCA3ICogZGltZW5zaW9uVG9wKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlIG1hdHJpeCBpcyBzcXVhcmVcbiAgICAgICAgICAgICAgICBkaW1lbnNpb25Ub3AgPSBkaW1lbnNpb25SaWdodCA9IE1hdGgubWF4KGRpbWVuc2lvblRvcCwgZGltZW5zaW9uUmlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGJpdHMgPSBEZXRlY3RvciQxLnNhbXBsZUdyaWQodGhpcy5pbWFnZSwgdG9wTGVmdCwgYm90dG9tTGVmdCwgYm90dG9tUmlnaHQsIHRvcFJpZ2h0LCBkaW1lbnNpb25Ub3AsIGRpbWVuc2lvblJpZ2h0KTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRGV0ZWN0b3JSZXN1bHQoYml0cywgW3RvcExlZnQsIGJvdHRvbUxlZnQsIGJvdHRvbVJpZ2h0LCB0b3BSaWdodF0pO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBzaGlmdFBvaW50KHBvaW50LCB0bywgZGl2KSB7XG4gICAgICAgICAgICBsZXQgeCA9ICh0by5nZXRYKCkgLSBwb2ludC5nZXRYKCkpIC8gKGRpdiArIDEpO1xuICAgICAgICAgICAgbGV0IHkgPSAodG8uZ2V0WSgpIC0gcG9pbnQuZ2V0WSgpKSAvIChkaXYgKyAxKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUmVzdWx0UG9pbnQocG9pbnQuZ2V0WCgpICsgeCwgcG9pbnQuZ2V0WSgpICsgeSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIG1vdmVBd2F5KHBvaW50LCBmcm9tWCwgZnJvbVkpIHtcbiAgICAgICAgICAgIGxldCB4ID0gcG9pbnQuZ2V0WCgpO1xuICAgICAgICAgICAgbGV0IHkgPSBwb2ludC5nZXRZKCk7XG4gICAgICAgICAgICBpZiAoeCA8IGZyb21YKSB7XG4gICAgICAgICAgICAgICAgeCAtPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgeCArPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHkgPCBmcm9tWSkge1xuICAgICAgICAgICAgICAgIHkgLT0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHkgKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgUmVzdWx0UG9pbnQoeCwgeSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERldGVjdCBhIHNvbGlkIHNpZGUgd2hpY2ggaGFzIG1pbmltdW0gdHJhbnNpdGlvbi5cbiAgICAgICAgICovXG4gICAgICAgIGRldGVjdFNvbGlkMShjb3JuZXJQb2ludHMpIHtcbiAgICAgICAgICAgIC8vIDAgIDJcbiAgICAgICAgICAgIC8vIDEgIDNcbiAgICAgICAgICAgIGxldCBwb2ludEEgPSBjb3JuZXJQb2ludHNbMF07XG4gICAgICAgICAgICBsZXQgcG9pbnRCID0gY29ybmVyUG9pbnRzWzFdO1xuICAgICAgICAgICAgbGV0IHBvaW50QyA9IGNvcm5lclBvaW50c1szXTtcbiAgICAgICAgICAgIGxldCBwb2ludEQgPSBjb3JuZXJQb2ludHNbMl07XG4gICAgICAgICAgICBsZXQgdHJBQiA9IHRoaXMudHJhbnNpdGlvbnNCZXR3ZWVuKHBvaW50QSwgcG9pbnRCKTtcbiAgICAgICAgICAgIGxldCB0ckJDID0gdGhpcy50cmFuc2l0aW9uc0JldHdlZW4ocG9pbnRCLCBwb2ludEMpO1xuICAgICAgICAgICAgbGV0IHRyQ0QgPSB0aGlzLnRyYW5zaXRpb25zQmV0d2Vlbihwb2ludEMsIHBvaW50RCk7XG4gICAgICAgICAgICBsZXQgdHJEQSA9IHRoaXMudHJhbnNpdGlvbnNCZXR3ZWVuKHBvaW50RCwgcG9pbnRBKTtcbiAgICAgICAgICAgIC8vIDAuLjNcbiAgICAgICAgICAgIC8vIDogIDpcbiAgICAgICAgICAgIC8vIDEtLTJcbiAgICAgICAgICAgIGxldCBtaW4gPSB0ckFCO1xuICAgICAgICAgICAgbGV0IHBvaW50cyA9IFtwb2ludEQsIHBvaW50QSwgcG9pbnRCLCBwb2ludENdO1xuICAgICAgICAgICAgaWYgKG1pbiA+IHRyQkMpIHtcbiAgICAgICAgICAgICAgICBtaW4gPSB0ckJDO1xuICAgICAgICAgICAgICAgIHBvaW50c1swXSA9IHBvaW50QTtcbiAgICAgICAgICAgICAgICBwb2ludHNbMV0gPSBwb2ludEI7XG4gICAgICAgICAgICAgICAgcG9pbnRzWzJdID0gcG9pbnRDO1xuICAgICAgICAgICAgICAgIHBvaW50c1szXSA9IHBvaW50RDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtaW4gPiB0ckNEKSB7XG4gICAgICAgICAgICAgICAgbWluID0gdHJDRDtcbiAgICAgICAgICAgICAgICBwb2ludHNbMF0gPSBwb2ludEI7XG4gICAgICAgICAgICAgICAgcG9pbnRzWzFdID0gcG9pbnRDO1xuICAgICAgICAgICAgICAgIHBvaW50c1syXSA9IHBvaW50RDtcbiAgICAgICAgICAgICAgICBwb2ludHNbM10gPSBwb2ludEE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWluID4gdHJEQSkge1xuICAgICAgICAgICAgICAgIHBvaW50c1swXSA9IHBvaW50QztcbiAgICAgICAgICAgICAgICBwb2ludHNbMV0gPSBwb2ludEQ7XG4gICAgICAgICAgICAgICAgcG9pbnRzWzJdID0gcG9pbnRBO1xuICAgICAgICAgICAgICAgIHBvaW50c1szXSA9IHBvaW50QjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBwb2ludHM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERldGVjdCBhIHNlY29uZCBzb2xpZCBzaWRlIG5leHQgdG8gZmlyc3Qgc29saWQgc2lkZS5cbiAgICAgICAgICovXG4gICAgICAgIGRldGVjdFNvbGlkMihwb2ludHMpIHtcbiAgICAgICAgICAgIC8vIEEuLkRcbiAgICAgICAgICAgIC8vIDogIDpcbiAgICAgICAgICAgIC8vIEItLUNcbiAgICAgICAgICAgIGxldCBwb2ludEEgPSBwb2ludHNbMF07XG4gICAgICAgICAgICBsZXQgcG9pbnRCID0gcG9pbnRzWzFdO1xuICAgICAgICAgICAgbGV0IHBvaW50QyA9IHBvaW50c1syXTtcbiAgICAgICAgICAgIGxldCBwb2ludEQgPSBwb2ludHNbM107XG4gICAgICAgICAgICAvLyBUcmFuc2l0aW9uIGRldGVjdGlvbiBvbiB0aGUgZWRnZSBpcyBub3Qgc3RhYmxlLlxuICAgICAgICAgICAgLy8gVG8gc2FmZWx5IGRldGVjdCwgc2hpZnQgdGhlIHBvaW50cyB0byB0aGUgbW9kdWxlIGNlbnRlci5cbiAgICAgICAgICAgIGxldCB0ciA9IHRoaXMudHJhbnNpdGlvbnNCZXR3ZWVuKHBvaW50QSwgcG9pbnREKTtcbiAgICAgICAgICAgIGxldCBwb2ludEJzID0gRGV0ZWN0b3IkMS5zaGlmdFBvaW50KHBvaW50QiwgcG9pbnRDLCAodHIgKyAxKSAqIDQpO1xuICAgICAgICAgICAgbGV0IHBvaW50Q3MgPSBEZXRlY3RvciQxLnNoaWZ0UG9pbnQocG9pbnRDLCBwb2ludEIsICh0ciArIDEpICogNCk7XG4gICAgICAgICAgICBsZXQgdHJCQSA9IHRoaXMudHJhbnNpdGlvbnNCZXR3ZWVuKHBvaW50QnMsIHBvaW50QSk7XG4gICAgICAgICAgICBsZXQgdHJDRCA9IHRoaXMudHJhbnNpdGlvbnNCZXR3ZWVuKHBvaW50Q3MsIHBvaW50RCk7XG4gICAgICAgICAgICAvLyAwLi4zXG4gICAgICAgICAgICAvLyB8ICA6XG4gICAgICAgICAgICAvLyAxLS0yXG4gICAgICAgICAgICBpZiAodHJCQSA8IHRyQ0QpIHtcbiAgICAgICAgICAgICAgICAvLyBzb2xpZCBzaWRlczogQS1CLUNcbiAgICAgICAgICAgICAgICBwb2ludHNbMF0gPSBwb2ludEE7XG4gICAgICAgICAgICAgICAgcG9pbnRzWzFdID0gcG9pbnRCO1xuICAgICAgICAgICAgICAgIHBvaW50c1syXSA9IHBvaW50QztcbiAgICAgICAgICAgICAgICBwb2ludHNbM10gPSBwb2ludEQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBzb2xpZCBzaWRlczogQi1DLURcbiAgICAgICAgICAgICAgICBwb2ludHNbMF0gPSBwb2ludEI7XG4gICAgICAgICAgICAgICAgcG9pbnRzWzFdID0gcG9pbnRDO1xuICAgICAgICAgICAgICAgIHBvaW50c1syXSA9IHBvaW50RDtcbiAgICAgICAgICAgICAgICBwb2ludHNbM10gPSBwb2ludEE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcG9pbnRzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDYWxjdWxhdGVzIHRoZSBjb3JuZXIgcG9zaXRpb24gb2YgdGhlIHdoaXRlIHRvcCByaWdodCBtb2R1bGUuXG4gICAgICAgICAqL1xuICAgICAgICBjb3JyZWN0VG9wUmlnaHQocG9pbnRzKSB7XG4gICAgICAgICAgICAvLyBBLi5EXG4gICAgICAgICAgICAvLyB8ICA6XG4gICAgICAgICAgICAvLyBCLS1DXG4gICAgICAgICAgICBsZXQgcG9pbnRBID0gcG9pbnRzWzBdO1xuICAgICAgICAgICAgbGV0IHBvaW50QiA9IHBvaW50c1sxXTtcbiAgICAgICAgICAgIGxldCBwb2ludEMgPSBwb2ludHNbMl07XG4gICAgICAgICAgICBsZXQgcG9pbnREID0gcG9pbnRzWzNdO1xuICAgICAgICAgICAgLy8gc2hpZnQgcG9pbnRzIGZvciBzYWZlIHRyYW5zaXRpb24gZGV0ZWN0aW9uLlxuICAgICAgICAgICAgbGV0IHRyVG9wID0gdGhpcy50cmFuc2l0aW9uc0JldHdlZW4ocG9pbnRBLCBwb2ludEQpO1xuICAgICAgICAgICAgbGV0IHRyUmlnaHQgPSB0aGlzLnRyYW5zaXRpb25zQmV0d2Vlbihwb2ludEIsIHBvaW50RCk7XG4gICAgICAgICAgICBsZXQgcG9pbnRBcyA9IERldGVjdG9yJDEuc2hpZnRQb2ludChwb2ludEEsIHBvaW50QiwgKHRyUmlnaHQgKyAxKSAqIDQpO1xuICAgICAgICAgICAgbGV0IHBvaW50Q3MgPSBEZXRlY3RvciQxLnNoaWZ0UG9pbnQocG9pbnRDLCBwb2ludEIsICh0clRvcCArIDEpICogNCk7XG4gICAgICAgICAgICB0clRvcCA9IHRoaXMudHJhbnNpdGlvbnNCZXR3ZWVuKHBvaW50QXMsIHBvaW50RCk7XG4gICAgICAgICAgICB0clJpZ2h0ID0gdGhpcy50cmFuc2l0aW9uc0JldHdlZW4ocG9pbnRDcywgcG9pbnREKTtcbiAgICAgICAgICAgIGxldCBjYW5kaWRhdGUxID0gbmV3IFJlc3VsdFBvaW50KHBvaW50RC5nZXRYKCkgKyAocG9pbnRDLmdldFgoKSAtIHBvaW50Qi5nZXRYKCkpIC8gKHRyVG9wICsgMSksIHBvaW50RC5nZXRZKCkgKyAocG9pbnRDLmdldFkoKSAtIHBvaW50Qi5nZXRZKCkpIC8gKHRyVG9wICsgMSkpO1xuICAgICAgICAgICAgbGV0IGNhbmRpZGF0ZTIgPSBuZXcgUmVzdWx0UG9pbnQocG9pbnRELmdldFgoKSArIChwb2ludEEuZ2V0WCgpIC0gcG9pbnRCLmdldFgoKSkgLyAodHJSaWdodCArIDEpLCBwb2ludEQuZ2V0WSgpICsgKHBvaW50QS5nZXRZKCkgLSBwb2ludEIuZ2V0WSgpKSAvICh0clJpZ2h0ICsgMSkpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoY2FuZGlkYXRlMSkpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc1ZhbGlkKGNhbmRpZGF0ZTIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjYW5kaWRhdGUyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKGNhbmRpZGF0ZTIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNhbmRpZGF0ZTE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc3VtYzEgPSB0aGlzLnRyYW5zaXRpb25zQmV0d2Vlbihwb2ludEFzLCBjYW5kaWRhdGUxKSArIHRoaXMudHJhbnNpdGlvbnNCZXR3ZWVuKHBvaW50Q3MsIGNhbmRpZGF0ZTEpO1xuICAgICAgICAgICAgbGV0IHN1bWMyID0gdGhpcy50cmFuc2l0aW9uc0JldHdlZW4ocG9pbnRBcywgY2FuZGlkYXRlMikgKyB0aGlzLnRyYW5zaXRpb25zQmV0d2Vlbihwb2ludENzLCBjYW5kaWRhdGUyKTtcbiAgICAgICAgICAgIGlmIChzdW1jMSA+IHN1bWMyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNhbmRpZGF0ZTE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2FuZGlkYXRlMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogU2hpZnQgdGhlIGVkZ2UgcG9pbnRzIHRvIHRoZSBtb2R1bGUgY2VudGVyLlxuICAgICAgICAgKi9cbiAgICAgICAgc2hpZnRUb01vZHVsZUNlbnRlcihwb2ludHMpIHtcbiAgICAgICAgICAgIC8vIEEuLkRcbiAgICAgICAgICAgIC8vIHwgIDpcbiAgICAgICAgICAgIC8vIEItLUNcbiAgICAgICAgICAgIGxldCBwb2ludEEgPSBwb2ludHNbMF07XG4gICAgICAgICAgICBsZXQgcG9pbnRCID0gcG9pbnRzWzFdO1xuICAgICAgICAgICAgbGV0IHBvaW50QyA9IHBvaW50c1syXTtcbiAgICAgICAgICAgIGxldCBwb2ludEQgPSBwb2ludHNbM107XG4gICAgICAgICAgICAvLyBjYWxjdWxhdGUgcHNldWRvIGRpbWVuc2lvbnNcbiAgICAgICAgICAgIGxldCBkaW1IID0gdGhpcy50cmFuc2l0aW9uc0JldHdlZW4ocG9pbnRBLCBwb2ludEQpICsgMTtcbiAgICAgICAgICAgIGxldCBkaW1WID0gdGhpcy50cmFuc2l0aW9uc0JldHdlZW4ocG9pbnRDLCBwb2ludEQpICsgMTtcbiAgICAgICAgICAgIC8vIHNoaWZ0IHBvaW50cyBmb3Igc2FmZSBkaW1lbnNpb24gZGV0ZWN0aW9uXG4gICAgICAgICAgICBsZXQgcG9pbnRBcyA9IERldGVjdG9yJDEuc2hpZnRQb2ludChwb2ludEEsIHBvaW50QiwgZGltViAqIDQpO1xuICAgICAgICAgICAgbGV0IHBvaW50Q3MgPSBEZXRlY3RvciQxLnNoaWZ0UG9pbnQocG9pbnRDLCBwb2ludEIsIGRpbUggKiA0KTtcbiAgICAgICAgICAgIC8vICBjYWxjdWxhdGUgbW9yZSBwcmVjaXNlIGRpbWVuc2lvbnNcbiAgICAgICAgICAgIGRpbUggPSB0aGlzLnRyYW5zaXRpb25zQmV0d2Vlbihwb2ludEFzLCBwb2ludEQpICsgMTtcbiAgICAgICAgICAgIGRpbVYgPSB0aGlzLnRyYW5zaXRpb25zQmV0d2Vlbihwb2ludENzLCBwb2ludEQpICsgMTtcbiAgICAgICAgICAgIGlmICgoZGltSCAmIDB4MDEpID09PSAxKSB7XG4gICAgICAgICAgICAgICAgZGltSCArPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKChkaW1WICYgMHgwMSkgPT09IDEpIHtcbiAgICAgICAgICAgICAgICBkaW1WICs9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBXaGl0ZVJlY3RhbmdsZURldGVjdG9yIHJldHVybnMgcG9pbnRzIGluc2lkZSBvZiB0aGUgcmVjdGFuZ2xlLlxuICAgICAgICAgICAgLy8gSSB3YW50IHBvaW50cyBvbiB0aGUgZWRnZXMuXG4gICAgICAgICAgICBsZXQgY2VudGVyWCA9IChwb2ludEEuZ2V0WCgpICsgcG9pbnRCLmdldFgoKSArIHBvaW50Qy5nZXRYKCkgKyBwb2ludEQuZ2V0WCgpKSAvIDQ7XG4gICAgICAgICAgICBsZXQgY2VudGVyWSA9IChwb2ludEEuZ2V0WSgpICsgcG9pbnRCLmdldFkoKSArIHBvaW50Qy5nZXRZKCkgKyBwb2ludEQuZ2V0WSgpKSAvIDQ7XG4gICAgICAgICAgICBwb2ludEEgPSBEZXRlY3RvciQxLm1vdmVBd2F5KHBvaW50QSwgY2VudGVyWCwgY2VudGVyWSk7XG4gICAgICAgICAgICBwb2ludEIgPSBEZXRlY3RvciQxLm1vdmVBd2F5KHBvaW50QiwgY2VudGVyWCwgY2VudGVyWSk7XG4gICAgICAgICAgICBwb2ludEMgPSBEZXRlY3RvciQxLm1vdmVBd2F5KHBvaW50QywgY2VudGVyWCwgY2VudGVyWSk7XG4gICAgICAgICAgICBwb2ludEQgPSBEZXRlY3RvciQxLm1vdmVBd2F5KHBvaW50RCwgY2VudGVyWCwgY2VudGVyWSk7XG4gICAgICAgICAgICBsZXQgcG9pbnRCcztcbiAgICAgICAgICAgIGxldCBwb2ludERzO1xuICAgICAgICAgICAgLy8gc2hpZnQgcG9pbnRzIHRvIHRoZSBjZW50ZXIgb2YgZWFjaCBtb2R1bGVzXG4gICAgICAgICAgICBwb2ludEFzID0gRGV0ZWN0b3IkMS5zaGlmdFBvaW50KHBvaW50QSwgcG9pbnRCLCBkaW1WICogNCk7XG4gICAgICAgICAgICBwb2ludEFzID0gRGV0ZWN0b3IkMS5zaGlmdFBvaW50KHBvaW50QXMsIHBvaW50RCwgZGltSCAqIDQpO1xuICAgICAgICAgICAgcG9pbnRCcyA9IERldGVjdG9yJDEuc2hpZnRQb2ludChwb2ludEIsIHBvaW50QSwgZGltViAqIDQpO1xuICAgICAgICAgICAgcG9pbnRCcyA9IERldGVjdG9yJDEuc2hpZnRQb2ludChwb2ludEJzLCBwb2ludEMsIGRpbUggKiA0KTtcbiAgICAgICAgICAgIHBvaW50Q3MgPSBEZXRlY3RvciQxLnNoaWZ0UG9pbnQocG9pbnRDLCBwb2ludEQsIGRpbVYgKiA0KTtcbiAgICAgICAgICAgIHBvaW50Q3MgPSBEZXRlY3RvciQxLnNoaWZ0UG9pbnQocG9pbnRDcywgcG9pbnRCLCBkaW1IICogNCk7XG4gICAgICAgICAgICBwb2ludERzID0gRGV0ZWN0b3IkMS5zaGlmdFBvaW50KHBvaW50RCwgcG9pbnRDLCBkaW1WICogNCk7XG4gICAgICAgICAgICBwb2ludERzID0gRGV0ZWN0b3IkMS5zaGlmdFBvaW50KHBvaW50RHMsIHBvaW50QSwgZGltSCAqIDQpO1xuICAgICAgICAgICAgcmV0dXJuIFtwb2ludEFzLCBwb2ludEJzLCBwb2ludENzLCBwb2ludERzXTtcbiAgICAgICAgfVxuICAgICAgICBpc1ZhbGlkKHApIHtcbiAgICAgICAgICAgIHJldHVybiBwLmdldFgoKSA+PSAwICYmIHAuZ2V0WCgpIDwgdGhpcy5pbWFnZS5nZXRXaWR0aCgpICYmIHAuZ2V0WSgpID4gMCAmJiBwLmdldFkoKSA8IHRoaXMuaW1hZ2UuZ2V0SGVpZ2h0KCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHNhbXBsZUdyaWQoaW1hZ2UsIHRvcExlZnQsIGJvdHRvbUxlZnQsIGJvdHRvbVJpZ2h0LCB0b3BSaWdodCwgZGltZW5zaW9uWCwgZGltZW5zaW9uWSkge1xuICAgICAgICAgICAgY29uc3Qgc2FtcGxlciA9IEdyaWRTYW1wbGVySW5zdGFuY2UuZ2V0SW5zdGFuY2UoKTtcbiAgICAgICAgICAgIHJldHVybiBzYW1wbGVyLnNhbXBsZUdyaWQoaW1hZ2UsIGRpbWVuc2lvblgsIGRpbWVuc2lvblksIDAuNSwgMC41LCBkaW1lbnNpb25YIC0gMC41LCAwLjUsIGRpbWVuc2lvblggLSAwLjUsIGRpbWVuc2lvblkgLSAwLjUsIDAuNSwgZGltZW5zaW9uWSAtIDAuNSwgdG9wTGVmdC5nZXRYKCksIHRvcExlZnQuZ2V0WSgpLCB0b3BSaWdodC5nZXRYKCksIHRvcFJpZ2h0LmdldFkoKSwgYm90dG9tUmlnaHQuZ2V0WCgpLCBib3R0b21SaWdodC5nZXRZKCksIGJvdHRvbUxlZnQuZ2V0WCgpLCBib3R0b21MZWZ0LmdldFkoKSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvdW50cyB0aGUgbnVtYmVyIG9mIGJsYWNrL3doaXRlIHRyYW5zaXRpb25zIGJldHdlZW4gdHdvIHBvaW50cywgdXNpbmcgc29tZXRoaW5nIGxpa2UgQnJlc2VuaGFtJ3MgYWxnb3JpdGhtLlxuICAgICAgICAgKi9cbiAgICAgICAgdHJhbnNpdGlvbnNCZXR3ZWVuKGZyb20sIHRvKSB7XG4gICAgICAgICAgICAvLyBTZWUgUVIgQ29kZSBEZXRlY3Rvciwgc2l6ZU9mQmxhY2tXaGl0ZUJsYWNrUnVuKClcbiAgICAgICAgICAgIGxldCBmcm9tWCA9IE1hdGgudHJ1bmMoZnJvbS5nZXRYKCkpO1xuICAgICAgICAgICAgbGV0IGZyb21ZID0gTWF0aC50cnVuYyhmcm9tLmdldFkoKSk7XG4gICAgICAgICAgICBsZXQgdG9YID0gTWF0aC50cnVuYyh0by5nZXRYKCkpO1xuICAgICAgICAgICAgbGV0IHRvWSA9IE1hdGgudHJ1bmModG8uZ2V0WSgpKTtcbiAgICAgICAgICAgIGxldCBzdGVlcCA9IE1hdGguYWJzKHRvWSAtIGZyb21ZKSA+IE1hdGguYWJzKHRvWCAtIGZyb21YKTtcbiAgICAgICAgICAgIGlmIChzdGVlcCkge1xuICAgICAgICAgICAgICAgIGxldCB0ZW1wID0gZnJvbVg7XG4gICAgICAgICAgICAgICAgZnJvbVggPSBmcm9tWTtcbiAgICAgICAgICAgICAgICBmcm9tWSA9IHRlbXA7XG4gICAgICAgICAgICAgICAgdGVtcCA9IHRvWDtcbiAgICAgICAgICAgICAgICB0b1ggPSB0b1k7XG4gICAgICAgICAgICAgICAgdG9ZID0gdGVtcDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBkeCA9IE1hdGguYWJzKHRvWCAtIGZyb21YKTtcbiAgICAgICAgICAgIGxldCBkeSA9IE1hdGguYWJzKHRvWSAtIGZyb21ZKTtcbiAgICAgICAgICAgIGxldCBlcnJvciA9IC1keCAvIDI7XG4gICAgICAgICAgICBsZXQgeXN0ZXAgPSBmcm9tWSA8IHRvWSA/IDEgOiAtMTtcbiAgICAgICAgICAgIGxldCB4c3RlcCA9IGZyb21YIDwgdG9YID8gMSA6IC0xO1xuICAgICAgICAgICAgbGV0IHRyYW5zaXRpb25zID0gMDtcbiAgICAgICAgICAgIGxldCBpbkJsYWNrID0gdGhpcy5pbWFnZS5nZXQoc3RlZXAgPyBmcm9tWSA6IGZyb21YLCBzdGVlcCA/IGZyb21YIDogZnJvbVkpO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IGZyb21YLCB5ID0gZnJvbVk7IHggIT09IHRvWDsgeCArPSB4c3RlcCkge1xuICAgICAgICAgICAgICAgIGxldCBpc0JsYWNrID0gdGhpcy5pbWFnZS5nZXQoc3RlZXAgPyB5IDogeCwgc3RlZXAgPyB4IDogeSk7XG4gICAgICAgICAgICAgICAgaWYgKGlzQmxhY2sgIT09IGluQmxhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNpdGlvbnMrKztcbiAgICAgICAgICAgICAgICAgICAgaW5CbGFjayA9IGlzQmxhY2s7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVycm9yICs9IGR5O1xuICAgICAgICAgICAgICAgIGlmIChlcnJvciA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHkgPT09IHRvWSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgeSArPSB5c3RlcDtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3IgLT0gZHg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRyYW5zaXRpb25zO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiBUaGlzIGltcGxlbWVudGF0aW9uIGNhbiBkZXRlY3QgYW5kIGRlY29kZSBEYXRhIE1hdHJpeCBjb2RlcyBpbiBhbiBpbWFnZS5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgYmJyb3duQGdvb2dsZS5jb20gKEJyaWFuIEJyb3duKVxuICAgICAqL1xuICAgIGNsYXNzIERhdGFNYXRyaXhSZWFkZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICAgIHRoaXMuZGVjb2RlciA9IG5ldyBEZWNvZGVyJDEoKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogTG9jYXRlcyBhbmQgZGVjb2RlcyBhIERhdGEgTWF0cml4IGNvZGUgaW4gYW4gaW1hZ2UuXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gYSBTdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBjb250ZW50IGVuY29kZWQgYnkgdGhlIERhdGEgTWF0cml4IGNvZGVcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBpZiBhIERhdGEgTWF0cml4IGNvZGUgY2Fubm90IGJlIGZvdW5kXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uIGlmIGEgRGF0YSBNYXRyaXggY29kZSBjYW5ub3QgYmUgZGVjb2RlZFxuICAgICAgICAgKiBAdGhyb3dzIENoZWNrc3VtRXhjZXB0aW9uIGlmIGVycm9yIGNvcnJlY3Rpb24gZmFpbHNcbiAgICAgICAgICovXG4gICAgICAgIC8vIEBPdmVycmlkZVxuICAgICAgICAvLyBwdWJsaWMgUmVzdWx0IGRlY29kZShCaW5hcnlCaXRtYXAgaW1hZ2UpIHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiwgQ2hlY2tzdW1FeGNlcHRpb24sIEZvcm1hdEV4Y2VwdGlvbiB7XG4gICAgICAgIC8vICAgcmV0dXJuIGRlY29kZShpbWFnZSwgbnVsbCk7XG4gICAgICAgIC8vIH1cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIGRlY29kZShpbWFnZSwgaGludHMgPSBudWxsKSB7XG4gICAgICAgICAgICBsZXQgZGVjb2RlclJlc3VsdDtcbiAgICAgICAgICAgIGxldCBwb2ludHM7XG4gICAgICAgICAgICBpZiAoaGludHMgIT0gbnVsbCAmJiBoaW50cy5oYXMoRGVjb2RlSGludFR5cGUkMS5QVVJFX0JBUkNPREUpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYml0cyA9IERhdGFNYXRyaXhSZWFkZXIuZXh0cmFjdFB1cmVCaXRzKGltYWdlLmdldEJsYWNrTWF0cml4KCkpO1xuICAgICAgICAgICAgICAgIGRlY29kZXJSZXN1bHQgPSB0aGlzLmRlY29kZXIuZGVjb2RlKGJpdHMpO1xuICAgICAgICAgICAgICAgIHBvaW50cyA9IERhdGFNYXRyaXhSZWFkZXIuTk9fUE9JTlRTO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGV0ZWN0b3JSZXN1bHQgPSBuZXcgRGV0ZWN0b3IkMShpbWFnZS5nZXRCbGFja01hdHJpeCgpKS5kZXRlY3QoKTtcbiAgICAgICAgICAgICAgICBkZWNvZGVyUmVzdWx0ID0gdGhpcy5kZWNvZGVyLmRlY29kZShkZXRlY3RvclJlc3VsdC5nZXRCaXRzKCkpO1xuICAgICAgICAgICAgICAgIHBvaW50cyA9IGRldGVjdG9yUmVzdWx0LmdldFBvaW50cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmF3Qnl0ZXMgPSBkZWNvZGVyUmVzdWx0LmdldFJhd0J5dGVzKCk7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgUmVzdWx0KGRlY29kZXJSZXN1bHQuZ2V0VGV4dCgpLCByYXdCeXRlcywgOCAqIHJhd0J5dGVzLmxlbmd0aCwgcG9pbnRzLCBCYXJjb2RlRm9ybWF0JDEuREFUQV9NQVRSSVgsIFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpKTtcbiAgICAgICAgICAgIGNvbnN0IGJ5dGVTZWdtZW50cyA9IGRlY29kZXJSZXN1bHQuZ2V0Qnl0ZVNlZ21lbnRzKCk7XG4gICAgICAgICAgICBpZiAoYnl0ZVNlZ21lbnRzICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQucHV0TWV0YWRhdGEoUmVzdWx0TWV0YWRhdGFUeXBlJDEuQllURV9TRUdNRU5UUywgYnl0ZVNlZ21lbnRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGVjTGV2ZWwgPSBkZWNvZGVyUmVzdWx0LmdldEVDTGV2ZWwoKTtcbiAgICAgICAgICAgIGlmIChlY0xldmVsICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQucHV0TWV0YWRhdGEoUmVzdWx0TWV0YWRhdGFUeXBlJDEuRVJST1JfQ09SUkVDVElPTl9MRVZFTCwgZWNMZXZlbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIC8vIEBPdmVycmlkZVxuICAgICAgICByZXNldCgpIHtcbiAgICAgICAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogVGhpcyBtZXRob2QgZGV0ZWN0cyBhIGNvZGUgaW4gYSBcInB1cmVcIiBpbWFnZSAtLSB0aGF0IGlzLCBwdXJlIG1vbm9jaHJvbWUgaW1hZ2VcbiAgICAgICAgICogd2hpY2ggY29udGFpbnMgb25seSBhbiB1bnJvdGF0ZWQsIHVuc2tld2VkLCBpbWFnZSBvZiBhIGNvZGUsIHdpdGggc29tZSB3aGl0ZSBib3JkZXJcbiAgICAgICAgICogYXJvdW5kIGl0LiBUaGlzIGlzIGEgc3BlY2lhbGl6ZWQgbWV0aG9kIHRoYXQgd29ya3MgZXhjZXB0aW9uYWxseSBmYXN0IGluIHRoaXMgc3BlY2lhbFxuICAgICAgICAgKiBjYXNlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAc2VlIGNvbS5nb29nbGUuenhpbmcucXJjb2RlLlFSQ29kZVJlYWRlciNleHRyYWN0UHVyZUJpdHMoQml0TWF0cml4KVxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGV4dHJhY3RQdXJlQml0cyhpbWFnZSkge1xuICAgICAgICAgICAgY29uc3QgbGVmdFRvcEJsYWNrID0gaW1hZ2UuZ2V0VG9wTGVmdE9uQml0KCk7XG4gICAgICAgICAgICBjb25zdCByaWdodEJvdHRvbUJsYWNrID0gaW1hZ2UuZ2V0Qm90dG9tUmlnaHRPbkJpdCgpO1xuICAgICAgICAgICAgaWYgKGxlZnRUb3BCbGFjayA9PSBudWxsIHx8IHJpZ2h0Qm90dG9tQmxhY2sgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbW9kdWxlU2l6ZSA9IHRoaXMubW9kdWxlU2l6ZShsZWZ0VG9wQmxhY2ssIGltYWdlKTtcbiAgICAgICAgICAgIGxldCB0b3AgPSBsZWZ0VG9wQmxhY2tbMV07XG4gICAgICAgICAgICBjb25zdCBib3R0b20gPSByaWdodEJvdHRvbUJsYWNrWzFdO1xuICAgICAgICAgICAgbGV0IGxlZnQgPSBsZWZ0VG9wQmxhY2tbMF07XG4gICAgICAgICAgICBjb25zdCByaWdodCA9IHJpZ2h0Qm90dG9tQmxhY2tbMF07XG4gICAgICAgICAgICBjb25zdCBtYXRyaXhXaWR0aCA9IChyaWdodCAtIGxlZnQgKyAxKSAvIG1vZHVsZVNpemU7XG4gICAgICAgICAgICBjb25zdCBtYXRyaXhIZWlnaHQgPSAoYm90dG9tIC0gdG9wICsgMSkgLyBtb2R1bGVTaXplO1xuICAgICAgICAgICAgaWYgKG1hdHJpeFdpZHRoIDw9IDAgfHwgbWF0cml4SGVpZ2h0IDw9IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFB1c2ggaW4gdGhlIFwiYm9yZGVyXCIgYnkgaGFsZiB0aGUgbW9kdWxlIHdpZHRoIHNvIHRoYXQgd2Ugc3RhcnRcbiAgICAgICAgICAgIC8vIHNhbXBsaW5nIGluIHRoZSBtaWRkbGUgb2YgdGhlIG1vZHVsZS4gSnVzdCBpbiBjYXNlIHRoZSBpbWFnZSBpcyBhXG4gICAgICAgICAgICAvLyBsaXR0bGUgb2ZmLCB0aGlzIHdpbGwgaGVscCByZWNvdmVyLlxuICAgICAgICAgICAgY29uc3QgbnVkZ2UgPSBtb2R1bGVTaXplIC8gMjtcbiAgICAgICAgICAgIHRvcCArPSBudWRnZTtcbiAgICAgICAgICAgIGxlZnQgKz0gbnVkZ2U7XG4gICAgICAgICAgICAvLyBOb3cganVzdCByZWFkIG9mZiB0aGUgYml0c1xuICAgICAgICAgICAgY29uc3QgYml0cyA9IG5ldyBCaXRNYXRyaXgobWF0cml4V2lkdGgsIG1hdHJpeEhlaWdodCk7XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IG1hdHJpeEhlaWdodDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaU9mZnNldCA9IHRvcCArIHkgKiBtb2R1bGVTaXplO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgbWF0cml4V2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW1hZ2UuZ2V0KGxlZnQgKyB4ICogbW9kdWxlU2l6ZSwgaU9mZnNldCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJpdHMuc2V0KHgsIHkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGJpdHM7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIG1vZHVsZVNpemUobGVmdFRvcEJsYWNrLCBpbWFnZSkge1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBpbWFnZS5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgbGV0IHggPSBsZWZ0VG9wQmxhY2tbMF07XG4gICAgICAgICAgICBjb25zdCB5ID0gbGVmdFRvcEJsYWNrWzFdO1xuICAgICAgICAgICAgd2hpbGUgKHggPCB3aWR0aCAmJiBpbWFnZS5nZXQoeCwgeSkpIHtcbiAgICAgICAgICAgICAgICB4Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoeCA9PT0gd2lkdGgpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG1vZHVsZVNpemUgPSB4IC0gbGVmdFRvcEJsYWNrWzBdO1xuICAgICAgICAgICAgaWYgKG1vZHVsZVNpemUgPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtb2R1bGVTaXplO1xuICAgICAgICB9XG4gICAgfVxuICAgIERhdGFNYXRyaXhSZWFkZXIuTk9fUE9JTlRTID0gW107XG5cbiAgICAvKipcbiAgICAgKiBAZGVwcmVjYXRlZCBNb3ZpbmcgdG8gQHp4aW5nL2Jyb3dzZXJcbiAgICAgKlxuICAgICAqIFFSIENvZGUgcmVhZGVyIHRvIHVzZSBmcm9tIGJyb3dzZXIuXG4gICAgICovXG4gICAgY2xhc3MgQnJvd3NlckRhdGFtYXRyaXhDb2RlUmVhZGVyIGV4dGVuZHMgQnJvd3NlckNvZGVSZWFkZXIge1xuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBCcm93c2VyUVJDb2RlUmVhZGVyLlxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gW3RpbWVCZXR3ZWVuU2NhbnNNaWxsaXM9NTAwXSB0aGUgdGltZSBkZWxheSBiZXR3ZWVuIHN1YnNlcXVlbnQgZGVjb2RlIHRyaWVzXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3Rvcih0aW1lQmV0d2VlblNjYW5zTWlsbGlzID0gNTAwKSB7XG4gICAgICAgICAgICBzdXBlcihuZXcgRGF0YU1hdHJpeFJlYWRlcigpLCB0aW1lQmV0d2VlblNjYW5zTWlsbGlzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgdmFyIEVycm9yQ29ycmVjdGlvbkxldmVsVmFsdWVzO1xuICAgIChmdW5jdGlvbiAoRXJyb3JDb3JyZWN0aW9uTGV2ZWxWYWx1ZXMpIHtcbiAgICAgICAgRXJyb3JDb3JyZWN0aW9uTGV2ZWxWYWx1ZXNbRXJyb3JDb3JyZWN0aW9uTGV2ZWxWYWx1ZXNbXCJMXCJdID0gMF0gPSBcIkxcIjtcbiAgICAgICAgRXJyb3JDb3JyZWN0aW9uTGV2ZWxWYWx1ZXNbRXJyb3JDb3JyZWN0aW9uTGV2ZWxWYWx1ZXNbXCJNXCJdID0gMV0gPSBcIk1cIjtcbiAgICAgICAgRXJyb3JDb3JyZWN0aW9uTGV2ZWxWYWx1ZXNbRXJyb3JDb3JyZWN0aW9uTGV2ZWxWYWx1ZXNbXCJRXCJdID0gMl0gPSBcIlFcIjtcbiAgICAgICAgRXJyb3JDb3JyZWN0aW9uTGV2ZWxWYWx1ZXNbRXJyb3JDb3JyZWN0aW9uTGV2ZWxWYWx1ZXNbXCJIXCJdID0gM10gPSBcIkhcIjtcbiAgICB9KShFcnJvckNvcnJlY3Rpb25MZXZlbFZhbHVlcyB8fCAoRXJyb3JDb3JyZWN0aW9uTGV2ZWxWYWx1ZXMgPSB7fSkpO1xuICAgIC8qKlxuICAgICAqIDxwPlNlZSBJU08gMTgwMDQ6MjAwNiwgNi41LjEuIFRoaXMgZW51bSBlbmNhcHN1bGF0ZXMgdGhlIGZvdXIgZXJyb3IgY29ycmVjdGlvbiBsZXZlbHNcbiAgICAgKiBkZWZpbmVkIGJ5IHRoZSBRUiBjb2RlIHN0YW5kYXJkLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgRXJyb3JDb3JyZWN0aW9uTGV2ZWwge1xuICAgICAgICBjb25zdHJ1Y3Rvcih2YWx1ZSwgc3RyaW5nVmFsdWUsIGJpdHMgLyppbnQqLykge1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgdGhpcy5zdHJpbmdWYWx1ZSA9IHN0cmluZ1ZhbHVlO1xuICAgICAgICAgICAgdGhpcy5iaXRzID0gYml0cztcbiAgICAgICAgICAgIEVycm9yQ29ycmVjdGlvbkxldmVsLkZPUl9CSVRTLnNldChiaXRzLCB0aGlzKTtcbiAgICAgICAgICAgIEVycm9yQ29ycmVjdGlvbkxldmVsLkZPUl9WQUxVRS5zZXQodmFsdWUsIHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIGdldFZhbHVlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Qml0cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJpdHM7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGZyb21TdHJpbmcocykge1xuICAgICAgICAgICAgc3dpdGNoIChzKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAnTCc6IHJldHVybiBFcnJvckNvcnJlY3Rpb25MZXZlbC5MO1xuICAgICAgICAgICAgICAgIGNhc2UgJ00nOiByZXR1cm4gRXJyb3JDb3JyZWN0aW9uTGV2ZWwuTTtcbiAgICAgICAgICAgICAgICBjYXNlICdRJzogcmV0dXJuIEVycm9yQ29ycmVjdGlvbkxldmVsLlE7XG4gICAgICAgICAgICAgICAgY2FzZSAnSCc6IHJldHVybiBFcnJvckNvcnJlY3Rpb25MZXZlbC5IO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHRocm93IG5ldyBBcmd1bWVudEV4Y2VwdGlvbihzICsgJ25vdCBhdmFpbGFibGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0b1N0cmluZygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0cmluZ1ZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGVxdWFscyhvKSB7XG4gICAgICAgICAgICBpZiAoIShvIGluc3RhbmNlb2YgRXJyb3JDb3JyZWN0aW9uTGV2ZWwpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgb3RoZXIgPSBvO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWUgPT09IG90aGVyLnZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gYml0cyBpbnQgY29udGFpbmluZyB0aGUgdHdvIGJpdHMgZW5jb2RpbmcgYSBRUiBDb2RlJ3MgZXJyb3IgY29ycmVjdGlvbiBsZXZlbFxuICAgICAgICAgKiBAcmV0dXJuIEVycm9yQ29ycmVjdGlvbkxldmVsIHJlcHJlc2VudGluZyB0aGUgZW5jb2RlZCBlcnJvciBjb3JyZWN0aW9uIGxldmVsXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZm9yQml0cyhiaXRzIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGlmIChiaXRzIDwgMCB8fCBiaXRzID49IEVycm9yQ29ycmVjdGlvbkxldmVsLkZPUl9CSVRTLnNpemUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gRXJyb3JDb3JyZWN0aW9uTGV2ZWwuRk9SX0JJVFMuZ2V0KGJpdHMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIEVycm9yQ29ycmVjdGlvbkxldmVsLkZPUl9CSVRTID0gbmV3IE1hcCgpO1xuICAgIEVycm9yQ29ycmVjdGlvbkxldmVsLkZPUl9WQUxVRSA9IG5ldyBNYXAoKTtcbiAgICAvKiogTCA9IH43JSBjb3JyZWN0aW9uICovXG4gICAgRXJyb3JDb3JyZWN0aW9uTGV2ZWwuTCA9IG5ldyBFcnJvckNvcnJlY3Rpb25MZXZlbChFcnJvckNvcnJlY3Rpb25MZXZlbFZhbHVlcy5MLCAnTCcsIDB4MDEpO1xuICAgIC8qKiBNID0gfjE1JSBjb3JyZWN0aW9uICovXG4gICAgRXJyb3JDb3JyZWN0aW9uTGV2ZWwuTSA9IG5ldyBFcnJvckNvcnJlY3Rpb25MZXZlbChFcnJvckNvcnJlY3Rpb25MZXZlbFZhbHVlcy5NLCAnTScsIDB4MDApO1xuICAgIC8qKiBRID0gfjI1JSBjb3JyZWN0aW9uICovXG4gICAgRXJyb3JDb3JyZWN0aW9uTGV2ZWwuUSA9IG5ldyBFcnJvckNvcnJlY3Rpb25MZXZlbChFcnJvckNvcnJlY3Rpb25MZXZlbFZhbHVlcy5RLCAnUScsIDB4MDMpO1xuICAgIC8qKiBIID0gfjMwJSBjb3JyZWN0aW9uICovXG4gICAgRXJyb3JDb3JyZWN0aW9uTGV2ZWwuSCA9IG5ldyBFcnJvckNvcnJlY3Rpb25MZXZlbChFcnJvckNvcnJlY3Rpb25MZXZlbFZhbHVlcy5ILCAnSCcsIDB4MDIpO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiA8cD5FbmNhcHN1bGF0ZXMgYSBRUiBDb2RlJ3MgZm9ybWF0IGluZm9ybWF0aW9uLCBpbmNsdWRpbmcgdGhlIGRhdGEgbWFzayB1c2VkIGFuZFxuICAgICAqIGVycm9yIGNvcnJlY3Rpb24gbGV2ZWwuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKiBAc2VlIERhdGFNYXNrXG4gICAgICogQHNlZSBFcnJvckNvcnJlY3Rpb25MZXZlbFxuICAgICAqL1xuICAgIGNsYXNzIEZvcm1hdEluZm9ybWF0aW9uIHtcbiAgICAgICAgY29uc3RydWN0b3IoZm9ybWF0SW5mbyAvKmludCovKSB7XG4gICAgICAgICAgICAvLyBCaXRzIDMsNFxuICAgICAgICAgICAgdGhpcy5lcnJvckNvcnJlY3Rpb25MZXZlbCA9IEVycm9yQ29ycmVjdGlvbkxldmVsLmZvckJpdHMoKGZvcm1hdEluZm8gPj4gMykgJiAweDAzKTtcbiAgICAgICAgICAgIC8vIEJvdHRvbSAzIGJpdHNcbiAgICAgICAgICAgIHRoaXMuZGF0YU1hc2sgPSAvKihieXRlKSAqLyAoZm9ybWF0SW5mbyAmIDB4MDcpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBudW1CaXRzRGlmZmVyaW5nKGEgLyppbnQqLywgYiAvKmludCovKSB7XG4gICAgICAgICAgICByZXR1cm4gSW50ZWdlci5iaXRDb3VudChhIF4gYik7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBtYXNrZWRGb3JtYXRJbmZvMSBmb3JtYXQgaW5mbyBpbmRpY2F0b3IsIHdpdGggbWFzayBzdGlsbCBhcHBsaWVkXG4gICAgICAgICAqIEBwYXJhbSBtYXNrZWRGb3JtYXRJbmZvMiBzZWNvbmQgY29weSBvZiBzYW1lIGluZm87IGJvdGggYXJlIGNoZWNrZWQgYXQgdGhlIHNhbWUgdGltZVxuICAgICAgICAgKiAgdG8gZXN0YWJsaXNoIGJlc3QgbWF0Y2hcbiAgICAgICAgICogQHJldHVybiBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZm9ybWF0IGl0IHNwZWNpZmllcywgb3Ige0Bjb2RlIG51bGx9XG4gICAgICAgICAqICBpZiBkb2Vzbid0IHNlZW0gdG8gbWF0Y2ggYW55IGtub3duIHBhdHRlcm5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBkZWNvZGVGb3JtYXRJbmZvcm1hdGlvbihtYXNrZWRGb3JtYXRJbmZvMSAvKmludCovLCBtYXNrZWRGb3JtYXRJbmZvMiAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBmb3JtYXRJbmZvID0gRm9ybWF0SW5mb3JtYXRpb24uZG9EZWNvZGVGb3JtYXRJbmZvcm1hdGlvbihtYXNrZWRGb3JtYXRJbmZvMSwgbWFza2VkRm9ybWF0SW5mbzIpO1xuICAgICAgICAgICAgaWYgKGZvcm1hdEluZm8gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZm9ybWF0SW5mbztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFNob3VsZCByZXR1cm4gbnVsbCwgYnV0LCBzb21lIFFSIGNvZGVzIGFwcGFyZW50bHlcbiAgICAgICAgICAgIC8vIGRvIG5vdCBtYXNrIHRoaXMgaW5mby4gVHJ5IGFnYWluIGJ5IGFjdHVhbGx5IG1hc2tpbmcgdGhlIHBhdHRlcm5cbiAgICAgICAgICAgIC8vIGZpcnN0XG4gICAgICAgICAgICByZXR1cm4gRm9ybWF0SW5mb3JtYXRpb24uZG9EZWNvZGVGb3JtYXRJbmZvcm1hdGlvbihtYXNrZWRGb3JtYXRJbmZvMSBeIEZvcm1hdEluZm9ybWF0aW9uLkZPUk1BVF9JTkZPX01BU0tfUVIsIG1hc2tlZEZvcm1hdEluZm8yIF4gRm9ybWF0SW5mb3JtYXRpb24uRk9STUFUX0lORk9fTUFTS19RUik7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGRvRGVjb2RlRm9ybWF0SW5mb3JtYXRpb24obWFza2VkRm9ybWF0SW5mbzEgLyppbnQqLywgbWFza2VkRm9ybWF0SW5mbzIgLyppbnQqLykge1xuICAgICAgICAgICAgLy8gRmluZCB0aGUgaW50IGluIEZPUk1BVF9JTkZPX0RFQ09ERV9MT09LVVAgd2l0aCBmZXdlc3QgYml0cyBkaWZmZXJpbmdcbiAgICAgICAgICAgIGxldCBiZXN0RGlmZmVyZW5jZSA9IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSO1xuICAgICAgICAgICAgbGV0IGJlc3RGb3JtYXRJbmZvID0gMDtcbiAgICAgICAgICAgIGZvciAoY29uc3QgZGVjb2RlSW5mbyBvZiBGb3JtYXRJbmZvcm1hdGlvbi5GT1JNQVRfSU5GT19ERUNPREVfTE9PS1VQKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0SW5mbyA9IGRlY29kZUluZm9bMF07XG4gICAgICAgICAgICAgICAgaWYgKHRhcmdldEluZm8gPT09IG1hc2tlZEZvcm1hdEluZm8xIHx8IHRhcmdldEluZm8gPT09IG1hc2tlZEZvcm1hdEluZm8yKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEZvdW5kIGFuIGV4YWN0IG1hdGNoXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRm9ybWF0SW5mb3JtYXRpb24oZGVjb2RlSW5mb1sxXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCBiaXRzRGlmZmVyZW5jZSA9IEZvcm1hdEluZm9ybWF0aW9uLm51bUJpdHNEaWZmZXJpbmcobWFza2VkRm9ybWF0SW5mbzEsIHRhcmdldEluZm8pO1xuICAgICAgICAgICAgICAgIGlmIChiaXRzRGlmZmVyZW5jZSA8IGJlc3REaWZmZXJlbmNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RGb3JtYXRJbmZvID0gZGVjb2RlSW5mb1sxXTtcbiAgICAgICAgICAgICAgICAgICAgYmVzdERpZmZlcmVuY2UgPSBiaXRzRGlmZmVyZW5jZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG1hc2tlZEZvcm1hdEluZm8xICE9PSBtYXNrZWRGb3JtYXRJbmZvMikge1xuICAgICAgICAgICAgICAgICAgICAvLyBhbHNvIHRyeSB0aGUgb3RoZXIgb3B0aW9uXG4gICAgICAgICAgICAgICAgICAgIGJpdHNEaWZmZXJlbmNlID0gRm9ybWF0SW5mb3JtYXRpb24ubnVtQml0c0RpZmZlcmluZyhtYXNrZWRGb3JtYXRJbmZvMiwgdGFyZ2V0SW5mbyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChiaXRzRGlmZmVyZW5jZSA8IGJlc3REaWZmZXJlbmNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBiZXN0Rm9ybWF0SW5mbyA9IGRlY29kZUluZm9bMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBiZXN0RGlmZmVyZW5jZSA9IGJpdHNEaWZmZXJlbmNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSGFtbWluZyBkaXN0YW5jZSBvZiB0aGUgMzIgbWFza2VkIGNvZGVzIGlzIDcsIGJ5IGNvbnN0cnVjdGlvbiwgc28gPD0gMyBiaXRzXG4gICAgICAgICAgICAvLyBkaWZmZXJpbmcgbWVhbnMgd2UgZm91bmQgYSBtYXRjaFxuICAgICAgICAgICAgaWYgKGJlc3REaWZmZXJlbmNlIDw9IDMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEZvcm1hdEluZm9ybWF0aW9uKGJlc3RGb3JtYXRJbmZvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGdldEVycm9yQ29ycmVjdGlvbkxldmVsKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXJyb3JDb3JyZWN0aW9uTGV2ZWw7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RGF0YU1hc2soKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRhTWFzaztcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGhhc2hDb2RlKCkge1xuICAgICAgICAgICAgcmV0dXJuICh0aGlzLmVycm9yQ29ycmVjdGlvbkxldmVsLmdldEJpdHMoKSA8PCAzKSB8IHRoaXMuZGF0YU1hc2s7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBlcXVhbHMobykge1xuICAgICAgICAgICAgaWYgKCEobyBpbnN0YW5jZW9mIEZvcm1hdEluZm9ybWF0aW9uKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG90aGVyID0gbztcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVycm9yQ29ycmVjdGlvbkxldmVsID09PSBvdGhlci5lcnJvckNvcnJlY3Rpb25MZXZlbCAmJlxuICAgICAgICAgICAgICAgIHRoaXMuZGF0YU1hc2sgPT09IG90aGVyLmRhdGFNYXNrO1xuICAgICAgICB9XG4gICAgfVxuICAgIEZvcm1hdEluZm9ybWF0aW9uLkZPUk1BVF9JTkZPX01BU0tfUVIgPSAweDU0MTI7XG4gICAgLyoqXG4gICAgICogU2VlIElTTyAxODAwNDoyMDA2LCBBbm5leCBDLCBUYWJsZSBDLjFcbiAgICAgKi9cbiAgICBGb3JtYXRJbmZvcm1hdGlvbi5GT1JNQVRfSU5GT19ERUNPREVfTE9PS1VQID0gW1xuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4NTQxMiwgMHgwMF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4NTEyNSwgMHgwMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4NUU3QywgMHgwMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4NUI0QiwgMHgwM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4NDVGOSwgMHgwNF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4NDBDRSwgMHgwNV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4NEY5NywgMHgwNl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4NEFBMCwgMHgwN10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4NzdDNCwgMHgwOF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4NzJGMywgMHgwOV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4N0RBQSwgMHgwQV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4Nzg5RCwgMHgwQl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4NjYyRiwgMHgwQ10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4NjMxOCwgMHgwRF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4NkM0MSwgMHgwRV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4Njk3NiwgMHgwRl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4MTY4OSwgMHgxMF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4MTNCRSwgMHgxMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4MUNFNywgMHgxMl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4MTlEMCwgMHgxM10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4MDc2MiwgMHgxNF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4MDI1NSwgMHgxNV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4MEQwQywgMHgxNl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4MDgzQiwgMHgxN10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4MzU1RiwgMHgxOF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4MzA2OCwgMHgxOV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4M0YzMSwgMHgxQV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4M0EwNiwgMHgxQl0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4MjRCNCwgMHgxQ10pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4MjE4MywgMHgxRF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4MkVEQSwgMHgxRV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzB4MkJFRCwgMHgxRl0pLFxuICAgIF07XG5cbiAgICAvKipcbiAgICAgKiA8cD5FbmNhcHN1bGF0ZXMgYSBzZXQgb2YgZXJyb3ItY29ycmVjdGlvbiBibG9ja3MgaW4gb25lIHN5bWJvbCB2ZXJzaW9uLiBNb3N0IHZlcnNpb25zIHdpbGxcbiAgICAgKiB1c2UgYmxvY2tzIG9mIGRpZmZlcmluZyBzaXplcyB3aXRoaW4gb25lIHZlcnNpb24sIHNvLCB0aGlzIGVuY2Fwc3VsYXRlcyB0aGUgcGFyYW1ldGVycyBmb3JcbiAgICAgKiBlYWNoIHNldCBvZiBibG9ja3MuIEl0IGFsc28gaG9sZHMgdGhlIG51bWJlciBvZiBlcnJvci1jb3JyZWN0aW9uIGNvZGV3b3JkcyBwZXIgYmxvY2sgc2luY2UgaXRcbiAgICAgKiB3aWxsIGJlIHRoZSBzYW1lIGFjcm9zcyBhbGwgYmxvY2tzIHdpdGhpbiBvbmUgdmVyc2lvbi48L3A+XG4gICAgICovXG4gICAgY2xhc3MgRUNCbG9ja3MkMSB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGVjQ29kZXdvcmRzUGVyQmxvY2sgLyppbnQqLywgLi4uZWNCbG9ja3MpIHtcbiAgICAgICAgICAgIHRoaXMuZWNDb2Rld29yZHNQZXJCbG9jayA9IGVjQ29kZXdvcmRzUGVyQmxvY2s7XG4gICAgICAgICAgICB0aGlzLmVjQmxvY2tzID0gZWNCbG9ja3M7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RUNDb2Rld29yZHNQZXJCbG9jaygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVjQ29kZXdvcmRzUGVyQmxvY2s7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0TnVtQmxvY2tzKCkge1xuICAgICAgICAgICAgbGV0IHRvdGFsID0gMDtcbiAgICAgICAgICAgIGNvbnN0IGVjQmxvY2tzID0gdGhpcy5lY0Jsb2NrcztcbiAgICAgICAgICAgIGZvciAoY29uc3QgZWNCbG9jayBvZiBlY0Jsb2Nrcykge1xuICAgICAgICAgICAgICAgIHRvdGFsICs9IGVjQmxvY2suZ2V0Q291bnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0b3RhbDtcbiAgICAgICAgfVxuICAgICAgICBnZXRUb3RhbEVDQ29kZXdvcmRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWNDb2Rld29yZHNQZXJCbG9jayAqIHRoaXMuZ2V0TnVtQmxvY2tzKCk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RUNCbG9ja3MoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lY0Jsb2NrcztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDxwPkVuY2Fwc3VsYXRlcyB0aGUgcGFyYW1ldGVycyBmb3Igb25lIGVycm9yLWNvcnJlY3Rpb24gYmxvY2sgaW4gb25lIHN5bWJvbCB2ZXJzaW9uLlxuICAgICAqIFRoaXMgaW5jbHVkZXMgdGhlIG51bWJlciBvZiBkYXRhIGNvZGV3b3JkcywgYW5kIHRoZSBudW1iZXIgb2YgdGltZXMgYSBibG9jayB3aXRoIHRoZXNlXG4gICAgICogcGFyYW1ldGVycyBpcyB1c2VkIGNvbnNlY3V0aXZlbHkgaW4gdGhlIFFSIGNvZGUgdmVyc2lvbidzIGZvcm1hdC48L3A+XG4gICAgICovXG4gICAgY2xhc3MgRUNCJDEge1xuICAgICAgICBjb25zdHJ1Y3Rvcihjb3VudCAvKmludCovLCBkYXRhQ29kZXdvcmRzIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudDtcbiAgICAgICAgICAgIHRoaXMuZGF0YUNvZGV3b3JkcyA9IGRhdGFDb2Rld29yZHM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Q291bnQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb3VudDtcbiAgICAgICAgfVxuICAgICAgICBnZXREYXRhQ29kZXdvcmRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0YUNvZGV3b3JkcztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogU2VlIElTTyAxODAwNDoyMDA2IEFubmV4IERcbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgVmVyc2lvbiQxIHtcbiAgICAgICAgY29uc3RydWN0b3IodmVyc2lvbk51bWJlciAvKmludCovLCBhbGlnbm1lbnRQYXR0ZXJuQ2VudGVycywgLi4uZWNCbG9ja3MpIHtcbiAgICAgICAgICAgIHRoaXMudmVyc2lvbk51bWJlciA9IHZlcnNpb25OdW1iZXI7XG4gICAgICAgICAgICB0aGlzLmFsaWdubWVudFBhdHRlcm5DZW50ZXJzID0gYWxpZ25tZW50UGF0dGVybkNlbnRlcnM7XG4gICAgICAgICAgICB0aGlzLmVjQmxvY2tzID0gZWNCbG9ja3M7XG4gICAgICAgICAgICBsZXQgdG90YWwgPSAwO1xuICAgICAgICAgICAgY29uc3QgZWNDb2Rld29yZHMgPSBlY0Jsb2Nrc1swXS5nZXRFQ0NvZGV3b3Jkc1BlckJsb2NrKCk7XG4gICAgICAgICAgICBjb25zdCBlY2JBcnJheSA9IGVjQmxvY2tzWzBdLmdldEVDQmxvY2tzKCk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGVjQmxvY2sgb2YgZWNiQXJyYXkpIHtcbiAgICAgICAgICAgICAgICB0b3RhbCArPSBlY0Jsb2NrLmdldENvdW50KCkgKiAoZWNCbG9jay5nZXREYXRhQ29kZXdvcmRzKCkgKyBlY0NvZGV3b3Jkcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnRvdGFsQ29kZXdvcmRzID0gdG90YWw7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0VmVyc2lvbk51bWJlcigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZlcnNpb25OdW1iZXI7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0QWxpZ25tZW50UGF0dGVybkNlbnRlcnMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hbGlnbm1lbnRQYXR0ZXJuQ2VudGVycztcbiAgICAgICAgfVxuICAgICAgICBnZXRUb3RhbENvZGV3b3JkcygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRvdGFsQ29kZXdvcmRzO1xuICAgICAgICB9XG4gICAgICAgIGdldERpbWVuc2lvbkZvclZlcnNpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gMTcgKyA0ICogdGhpcy52ZXJzaW9uTnVtYmVyO1xuICAgICAgICB9XG4gICAgICAgIGdldEVDQmxvY2tzRm9yTGV2ZWwoZWNMZXZlbCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWNCbG9ja3NbZWNMZXZlbC5nZXRWYWx1ZSgpXTtcbiAgICAgICAgICAgIC8vIFRZUEVTQ1JJUFRQT1JUOiBvcmlnaW5hbCB3YXMgdXNpbmcgb3JkaW5hbCwgYW5kIHVzaW5nIHRoZSBvcmRlciBvZiBsZXZlbHMgYXMgZGVmaW5lZCBpbiBFcnJvckNvcnJlY3Rpb25MZXZlbCBlbnVtIChMTVFIKVxuICAgICAgICAgICAgLy8gSSB3aWxsIHVzZSB0aGUgZGlyZWN0IHZhbHVlIGZyb20gRXJyb3JDb3JyZWN0aW9uTGV2ZWxWYWx1ZXMgZW51bSB3aGljaCBpbiB0eXBlc2NyaXB0IGdvZXMgdG8gYSBudW1iZXJcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+RGVkdWNlcyB2ZXJzaW9uIGluZm9ybWF0aW9uIHB1cmVseSBmcm9tIFFSIENvZGUgZGltZW5zaW9ucy48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBkaW1lbnNpb24gZGltZW5zaW9uIGluIG1vZHVsZXNcbiAgICAgICAgICogQHJldHVybiBWZXJzaW9uIGZvciBhIFFSIENvZGUgb2YgdGhhdCBkaW1lbnNpb25cbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb24gaWYgZGltZW5zaW9uIGlzIG5vdCAxIG1vZCA0XG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZ2V0UHJvdmlzaW9uYWxWZXJzaW9uRm9yRGltZW5zaW9uKGRpbWVuc2lvbiAvKmludCovKSB7XG4gICAgICAgICAgICBpZiAoZGltZW5zaW9uICUgNCAhPT0gMSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0VmVyc2lvbkZvck51bWJlcigoZGltZW5zaW9uIC0gMTcpIC8gNCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoaWdub3JlZCAvKjogSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKi8pIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdldFZlcnNpb25Gb3JOdW1iZXIodmVyc2lvbk51bWJlciAvKmludCovKSB7XG4gICAgICAgICAgICBpZiAodmVyc2lvbk51bWJlciA8IDEgfHwgdmVyc2lvbk51bWJlciA+IDQwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIFZlcnNpb24kMS5WRVJTSU9OU1t2ZXJzaW9uTnVtYmVyIC0gMV07XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGRlY29kZVZlcnNpb25JbmZvcm1hdGlvbih2ZXJzaW9uQml0cyAvKmludCovKSB7XG4gICAgICAgICAgICBsZXQgYmVzdERpZmZlcmVuY2UgPSBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUjtcbiAgICAgICAgICAgIGxldCBiZXN0VmVyc2lvbiA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IFZlcnNpb24kMS5WRVJTSU9OX0RFQ09ERV9JTkZPLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0VmVyc2lvbiA9IFZlcnNpb24kMS5WRVJTSU9OX0RFQ09ERV9JTkZPW2ldO1xuICAgICAgICAgICAgICAgIC8vIERvIHRoZSB2ZXJzaW9uIGluZm8gYml0cyBtYXRjaCBleGFjdGx5PyBkb25lLlxuICAgICAgICAgICAgICAgIGlmICh0YXJnZXRWZXJzaW9uID09PSB2ZXJzaW9uQml0cykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gVmVyc2lvbiQxLmdldFZlcnNpb25Gb3JOdW1iZXIoaSArIDcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2Ugc2VlIGlmIHRoaXMgaXMgdGhlIGNsb3Nlc3QgdG8gYSByZWFsIHZlcnNpb24gaW5mbyBiaXQgc3RyaW5nXG4gICAgICAgICAgICAgICAgLy8gd2UgaGF2ZSBzZWVuIHNvIGZhclxuICAgICAgICAgICAgICAgIGNvbnN0IGJpdHNEaWZmZXJlbmNlID0gRm9ybWF0SW5mb3JtYXRpb24ubnVtQml0c0RpZmZlcmluZyh2ZXJzaW9uQml0cywgdGFyZ2V0VmVyc2lvbik7XG4gICAgICAgICAgICAgICAgaWYgKGJpdHNEaWZmZXJlbmNlIDwgYmVzdERpZmZlcmVuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgYmVzdFZlcnNpb24gPSBpICsgNztcbiAgICAgICAgICAgICAgICAgICAgYmVzdERpZmZlcmVuY2UgPSBiaXRzRGlmZmVyZW5jZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBXZSBjYW4gdG9sZXJhdGUgdXAgdG8gMyBiaXRzIG9mIGVycm9yIHNpbmNlIG5vIHR3byB2ZXJzaW9uIGluZm8gY29kZXdvcmRzIHdpbGxcbiAgICAgICAgICAgIC8vIGRpZmZlciBpbiBsZXNzIHRoYW4gOCBiaXRzLlxuICAgICAgICAgICAgaWYgKGJlc3REaWZmZXJlbmNlIDw9IDMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gVmVyc2lvbiQxLmdldFZlcnNpb25Gb3JOdW1iZXIoYmVzdFZlcnNpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSWYgd2UgZGlkbid0IGZpbmQgYSBjbG9zZSBlbm91Z2ggbWF0Y2gsIGZhaWxcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZWUgSVNPIDE4MDA0OjIwMDYgQW5uZXggRVxuICAgICAgICAgKi9cbiAgICAgICAgYnVpbGRGdW5jdGlvblBhdHRlcm4oKSB7XG4gICAgICAgICAgICBjb25zdCBkaW1lbnNpb24gPSB0aGlzLmdldERpbWVuc2lvbkZvclZlcnNpb24oKTtcbiAgICAgICAgICAgIGNvbnN0IGJpdE1hdHJpeCA9IG5ldyBCaXRNYXRyaXgoZGltZW5zaW9uKTtcbiAgICAgICAgICAgIC8vIFRvcCBsZWZ0IGZpbmRlciBwYXR0ZXJuICsgc2VwYXJhdG9yICsgZm9ybWF0XG4gICAgICAgICAgICBiaXRNYXRyaXguc2V0UmVnaW9uKDAsIDAsIDksIDkpO1xuICAgICAgICAgICAgLy8gVG9wIHJpZ2h0IGZpbmRlciBwYXR0ZXJuICsgc2VwYXJhdG9yICsgZm9ybWF0XG4gICAgICAgICAgICBiaXRNYXRyaXguc2V0UmVnaW9uKGRpbWVuc2lvbiAtIDgsIDAsIDgsIDkpO1xuICAgICAgICAgICAgLy8gQm90dG9tIGxlZnQgZmluZGVyIHBhdHRlcm4gKyBzZXBhcmF0b3IgKyBmb3JtYXRcbiAgICAgICAgICAgIGJpdE1hdHJpeC5zZXRSZWdpb24oMCwgZGltZW5zaW9uIC0gOCwgOSwgOCk7XG4gICAgICAgICAgICAvLyBBbGlnbm1lbnQgcGF0dGVybnNcbiAgICAgICAgICAgIGNvbnN0IG1heCA9IHRoaXMuYWxpZ25tZW50UGF0dGVybkNlbnRlcnMubGVuZ3RoO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCBtYXg7IHgrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGkgPSB0aGlzLmFsaWdubWVudFBhdHRlcm5DZW50ZXJzW3hdIC0gMjtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IG1heDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICgoeCA9PT0gMCAmJiAoeSA9PT0gMCB8fCB5ID09PSBtYXggLSAxKSkgfHwgKHggPT09IG1heCAtIDEgJiYgeSA9PT0gMCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5vIGFsaWdubWVudCBwYXR0ZXJucyBuZWFyIHRoZSB0aHJlZSBmaW5kZXIgcGF0dGVybnNcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJpdE1hdHJpeC5zZXRSZWdpb24odGhpcy5hbGlnbm1lbnRQYXR0ZXJuQ2VudGVyc1t5XSAtIDIsIGksIDUsIDUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFZlcnRpY2FsIHRpbWluZyBwYXR0ZXJuXG4gICAgICAgICAgICBiaXRNYXRyaXguc2V0UmVnaW9uKDYsIDksIDEsIGRpbWVuc2lvbiAtIDE3KTtcbiAgICAgICAgICAgIC8vIEhvcml6b250YWwgdGltaW5nIHBhdHRlcm5cbiAgICAgICAgICAgIGJpdE1hdHJpeC5zZXRSZWdpb24oOSwgNiwgZGltZW5zaW9uIC0gMTcsIDEpO1xuICAgICAgICAgICAgaWYgKHRoaXMudmVyc2lvbk51bWJlciA+IDYpIHtcbiAgICAgICAgICAgICAgICAvLyBWZXJzaW9uIGluZm8sIHRvcCByaWdodFxuICAgICAgICAgICAgICAgIGJpdE1hdHJpeC5zZXRSZWdpb24oZGltZW5zaW9uIC0gMTEsIDAsIDMsIDYpO1xuICAgICAgICAgICAgICAgIC8vIFZlcnNpb24gaW5mbywgYm90dG9tIGxlZnRcbiAgICAgICAgICAgICAgICBiaXRNYXRyaXguc2V0UmVnaW9uKDAsIGRpbWVuc2lvbiAtIDExLCA2LCAzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBiaXRNYXRyaXg7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICB0b1N0cmluZygpIHtcbiAgICAgICAgICAgIHJldHVybiAnJyArIHRoaXMudmVyc2lvbk51bWJlcjtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgICAqIFNlZSBJU08gMTgwMDQ6MjAwNiBBbm5leCBELlxuICAgICAgICogRWxlbWVudCBpIHJlcHJlc2VudHMgdGhlIHJhdyB2ZXJzaW9uIGJpdHMgdGhhdCBzcGVjaWZ5IHZlcnNpb24gaSArIDdcbiAgICAgICAqL1xuICAgIFZlcnNpb24kMS5WRVJTSU9OX0RFQ09ERV9JTkZPID0gSW50MzJBcnJheS5mcm9tKFtcbiAgICAgICAgMHgwN0M5NCwgMHgwODVCQywgMHgwOUE5OSwgMHgwQTREMywgMHgwQkJGNixcbiAgICAgICAgMHgwQzc2MiwgMHgwRDg0NywgMHgwRTYwRCwgMHgwRjkyOCwgMHgxMEI3OCxcbiAgICAgICAgMHgxMTQ1RCwgMHgxMkExNywgMHgxMzUzMiwgMHgxNDlBNiwgMHgxNTY4MyxcbiAgICAgICAgMHgxNjhDOSwgMHgxNzdFQywgMHgxOEVDNCwgMHgxOTFFMSwgMHgxQUZBQixcbiAgICAgICAgMHgxQjA4RSwgMHgxQ0MxQSwgMHgxRDMzRiwgMHgxRUQ3NSwgMHgxRjI1MCxcbiAgICAgICAgMHgyMDlENSwgMHgyMTZGMCwgMHgyMjhCQSwgMHgyMzc5RiwgMHgyNEIwQixcbiAgICAgICAgMHgyNTQyRSwgMHgyNkE2NCwgMHgyNzU0MSwgMHgyOEM2OVxuICAgIF0pO1xuICAgIC8qKlxuICAgICAgICogU2VlIElTTyAxODAwNDoyMDA2IDYuNS4xIFRhYmxlIDlcbiAgICAgICAqL1xuICAgIFZlcnNpb24kMS5WRVJTSU9OUyA9IFtcbiAgICAgICAgbmV3IFZlcnNpb24kMSgxLCBuZXcgSW50MzJBcnJheSgwKSwgbmV3IEVDQmxvY2tzJDEoNywgbmV3IEVDQiQxKDEsIDE5KSksIG5ldyBFQ0Jsb2NrcyQxKDEwLCBuZXcgRUNCJDEoMSwgMTYpKSwgbmV3IEVDQmxvY2tzJDEoMTMsIG5ldyBFQ0IkMSgxLCAxMykpLCBuZXcgRUNCbG9ja3MkMSgxNywgbmV3IEVDQiQxKDEsIDkpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMiwgSW50MzJBcnJheS5mcm9tKFs2LCAxOF0pLCBuZXcgRUNCbG9ja3MkMSgxMCwgbmV3IEVDQiQxKDEsIDM0KSksIG5ldyBFQ0Jsb2NrcyQxKDE2LCBuZXcgRUNCJDEoMSwgMjgpKSwgbmV3IEVDQmxvY2tzJDEoMjIsIG5ldyBFQ0IkMSgxLCAyMikpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDEsIDE2KSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDMsIEludDMyQXJyYXkuZnJvbShbNiwgMjJdKSwgbmV3IEVDQmxvY2tzJDEoMTUsIG5ldyBFQ0IkMSgxLCA1NSkpLCBuZXcgRUNCbG9ja3MkMSgyNiwgbmV3IEVDQiQxKDEsIDQ0KSksIG5ldyBFQ0Jsb2NrcyQxKDE4LCBuZXcgRUNCJDEoMiwgMTcpKSwgbmV3IEVDQmxvY2tzJDEoMjIsIG5ldyBFQ0IkMSgyLCAxMykpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSg0LCBJbnQzMkFycmF5LmZyb20oWzYsIDI2XSksIG5ldyBFQ0Jsb2NrcyQxKDIwLCBuZXcgRUNCJDEoMSwgODApKSwgbmV3IEVDQmxvY2tzJDEoMTgsIG5ldyBFQ0IkMSgyLCAzMikpLCBuZXcgRUNCbG9ja3MkMSgyNiwgbmV3IEVDQiQxKDIsIDI0KSksIG5ldyBFQ0Jsb2NrcyQxKDE2LCBuZXcgRUNCJDEoNCwgOSkpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSg1LCBJbnQzMkFycmF5LmZyb20oWzYsIDMwXSksIG5ldyBFQ0Jsb2NrcyQxKDI2LCBuZXcgRUNCJDEoMSwgMTA4KSksIG5ldyBFQ0Jsb2NrcyQxKDI0LCBuZXcgRUNCJDEoMiwgNDMpKSwgbmV3IEVDQmxvY2tzJDEoMTgsIG5ldyBFQ0IkMSgyLCAxNSksIG5ldyBFQ0IkMSgyLCAxNikpLCBuZXcgRUNCbG9ja3MkMSgyMiwgbmV3IEVDQiQxKDIsIDExKSwgbmV3IEVDQiQxKDIsIDEyKSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDYsIEludDMyQXJyYXkuZnJvbShbNiwgMzRdKSwgbmV3IEVDQmxvY2tzJDEoMTgsIG5ldyBFQ0IkMSgyLCA2OCkpLCBuZXcgRUNCbG9ja3MkMSgxNiwgbmV3IEVDQiQxKDQsIDI3KSksIG5ldyBFQ0Jsb2NrcyQxKDI0LCBuZXcgRUNCJDEoNCwgMTkpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSg0LCAxNSkpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSg3LCBJbnQzMkFycmF5LmZyb20oWzYsIDIyLCAzOF0pLCBuZXcgRUNCbG9ja3MkMSgyMCwgbmV3IEVDQiQxKDIsIDc4KSksIG5ldyBFQ0Jsb2NrcyQxKDE4LCBuZXcgRUNCJDEoNCwgMzEpKSwgbmV3IEVDQmxvY2tzJDEoMTgsIG5ldyBFQ0IkMSgyLCAxNCksIG5ldyBFQ0IkMSg0LCAxNSkpLCBuZXcgRUNCbG9ja3MkMSgyNiwgbmV3IEVDQiQxKDQsIDEzKSwgbmV3IEVDQiQxKDEsIDE0KSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDgsIEludDMyQXJyYXkuZnJvbShbNiwgMjQsIDQyXSksIG5ldyBFQ0Jsb2NrcyQxKDI0LCBuZXcgRUNCJDEoMiwgOTcpKSwgbmV3IEVDQmxvY2tzJDEoMjIsIG5ldyBFQ0IkMSgyLCAzOCksIG5ldyBFQ0IkMSgyLCAzOSkpLCBuZXcgRUNCbG9ja3MkMSgyMiwgbmV3IEVDQiQxKDQsIDE4KSwgbmV3IEVDQiQxKDIsIDE5KSksIG5ldyBFQ0Jsb2NrcyQxKDI2LCBuZXcgRUNCJDEoNCwgMTQpLCBuZXcgRUNCJDEoMiwgMTUpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoOSwgSW50MzJBcnJheS5mcm9tKFs2LCAyNiwgNDZdKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgyLCAxMTYpKSwgbmV3IEVDQmxvY2tzJDEoMjIsIG5ldyBFQ0IkMSgzLCAzNiksIG5ldyBFQ0IkMSgyLCAzNykpLCBuZXcgRUNCbG9ja3MkMSgyMCwgbmV3IEVDQiQxKDQsIDE2KSwgbmV3IEVDQiQxKDQsIDE3KSksIG5ldyBFQ0Jsb2NrcyQxKDI0LCBuZXcgRUNCJDEoNCwgMTIpLCBuZXcgRUNCJDEoNCwgMTMpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMTAsIEludDMyQXJyYXkuZnJvbShbNiwgMjgsIDUwXSksIG5ldyBFQ0Jsb2NrcyQxKDE4LCBuZXcgRUNCJDEoMiwgNjgpLCBuZXcgRUNCJDEoMiwgNjkpKSwgbmV3IEVDQmxvY2tzJDEoMjYsIG5ldyBFQ0IkMSg0LCA0MyksIG5ldyBFQ0IkMSgxLCA0NCkpLCBuZXcgRUNCbG9ja3MkMSgyNCwgbmV3IEVDQiQxKDYsIDE5KSwgbmV3IEVDQiQxKDIsIDIwKSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoNiwgMTUpLCBuZXcgRUNCJDEoMiwgMTYpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMTEsIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIDU0XSksIG5ldyBFQ0Jsb2NrcyQxKDIwLCBuZXcgRUNCJDEoNCwgODEpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgxLCA1MCksIG5ldyBFQ0IkMSg0LCA1MSkpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDQsIDIyKSwgbmV3IEVDQiQxKDQsIDIzKSksIG5ldyBFQ0Jsb2NrcyQxKDI0LCBuZXcgRUNCJDEoMywgMTIpLCBuZXcgRUNCJDEoOCwgMTMpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMTIsIEludDMyQXJyYXkuZnJvbShbNiwgMzIsIDU4XSksIG5ldyBFQ0Jsb2NrcyQxKDI0LCBuZXcgRUNCJDEoMiwgOTIpLCBuZXcgRUNCJDEoMiwgOTMpKSwgbmV3IEVDQmxvY2tzJDEoMjIsIG5ldyBFQ0IkMSg2LCAzNiksIG5ldyBFQ0IkMSgyLCAzNykpLCBuZXcgRUNCbG9ja3MkMSgyNiwgbmV3IEVDQiQxKDQsIDIwKSwgbmV3IEVDQiQxKDYsIDIxKSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoNywgMTQpLCBuZXcgRUNCJDEoNCwgMTUpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMTMsIEludDMyQXJyYXkuZnJvbShbNiwgMzQsIDYyXSksIG5ldyBFQ0Jsb2NrcyQxKDI2LCBuZXcgRUNCJDEoNCwgMTA3KSksIG5ldyBFQ0Jsb2NrcyQxKDIyLCBuZXcgRUNCJDEoOCwgMzcpLCBuZXcgRUNCJDEoMSwgMzgpKSwgbmV3IEVDQmxvY2tzJDEoMjQsIG5ldyBFQ0IkMSg4LCAyMCksIG5ldyBFQ0IkMSg0LCAyMSkpLCBuZXcgRUNCbG9ja3MkMSgyMiwgbmV3IEVDQiQxKDEyLCAxMSksIG5ldyBFQ0IkMSg0LCAxMikpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgxNCwgSW50MzJBcnJheS5mcm9tKFs2LCAyNiwgNDYsIDY2XSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMywgMTE1KSwgbmV3IEVDQiQxKDEsIDExNikpLCBuZXcgRUNCbG9ja3MkMSgyNCwgbmV3IEVDQiQxKDQsIDQwKSwgbmV3IEVDQiQxKDUsIDQxKSksIG5ldyBFQ0Jsb2NrcyQxKDIwLCBuZXcgRUNCJDEoMTEsIDE2KSwgbmV3IEVDQiQxKDUsIDE3KSksIG5ldyBFQ0Jsb2NrcyQxKDI0LCBuZXcgRUNCJDEoMTEsIDEyKSwgbmV3IEVDQiQxKDUsIDEzKSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDE1LCBJbnQzMkFycmF5LmZyb20oWzYsIDI2LCA0OCwgNzBdKSwgbmV3IEVDQmxvY2tzJDEoMjIsIG5ldyBFQ0IkMSg1LCA4NyksIG5ldyBFQ0IkMSgxLCA4OCkpLCBuZXcgRUNCbG9ja3MkMSgyNCwgbmV3IEVDQiQxKDUsIDQxKSwgbmV3IEVDQiQxKDUsIDQyKSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoNSwgMjQpLCBuZXcgRUNCJDEoNywgMjUpKSwgbmV3IEVDQmxvY2tzJDEoMjQsIG5ldyBFQ0IkMSgxMSwgMTIpLCBuZXcgRUNCJDEoNywgMTMpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMTYsIEludDMyQXJyYXkuZnJvbShbNiwgMjYsIDUwLCA3NF0pLCBuZXcgRUNCbG9ja3MkMSgyNCwgbmV3IEVDQiQxKDUsIDk4KSwgbmV3IEVDQiQxKDEsIDk5KSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoNywgNDUpLCBuZXcgRUNCJDEoMywgNDYpKSwgbmV3IEVDQmxvY2tzJDEoMjQsIG5ldyBFQ0IkMSgxNSwgMTkpLCBuZXcgRUNCJDEoMiwgMjApKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgzLCAxNSksIG5ldyBFQ0IkMSgxMywgMTYpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMTcsIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIDU0LCA3OF0pLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDEsIDEwNyksIG5ldyBFQ0IkMSg1LCAxMDgpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgxMCwgNDYpLCBuZXcgRUNCJDEoMSwgNDcpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgxLCAyMiksIG5ldyBFQ0IkMSgxNSwgMjMpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgyLCAxNCksIG5ldyBFQ0IkMSgxNywgMTUpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMTgsIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIDU2LCA4Ml0pLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDUsIDEyMCksIG5ldyBFQ0IkMSgxLCAxMjEpKSwgbmV3IEVDQmxvY2tzJDEoMjYsIG5ldyBFQ0IkMSg5LCA0MyksIG5ldyBFQ0IkMSg0LCA0NCkpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDE3LCAyMiksIG5ldyBFQ0IkMSgxLCAyMykpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDIsIDE0KSwgbmV3IEVDQiQxKDE5LCAxNSkpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgxOSwgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTgsIDg2XSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMywgMTEzKSwgbmV3IEVDQiQxKDQsIDExNCkpLCBuZXcgRUNCbG9ja3MkMSgyNiwgbmV3IEVDQiQxKDMsIDQ0KSwgbmV3IEVDQiQxKDExLCA0NSkpLCBuZXcgRUNCbG9ja3MkMSgyNiwgbmV3IEVDQiQxKDE3LCAyMSksIG5ldyBFQ0IkMSg0LCAyMikpLCBuZXcgRUNCbG9ja3MkMSgyNiwgbmV3IEVDQiQxKDksIDEzKSwgbmV3IEVDQiQxKDE2LCAxNCkpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgyMCwgSW50MzJBcnJheS5mcm9tKFs2LCAzNCwgNjIsIDkwXSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMywgMTA3KSwgbmV3IEVDQiQxKDUsIDEwOCkpLCBuZXcgRUNCbG9ja3MkMSgyNiwgbmV3IEVDQiQxKDMsIDQxKSwgbmV3IEVDQiQxKDEzLCA0MikpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDE1LCAyNCksIG5ldyBFQ0IkMSg1LCAyNSkpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDE1LCAxNSksIG5ldyBFQ0IkMSgxMCwgMTYpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMjEsIEludDMyQXJyYXkuZnJvbShbNiwgMjgsIDUwLCA3MiwgOTRdKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSg0LCAxMTYpLCBuZXcgRUNCJDEoNCwgMTE3KSksIG5ldyBFQ0Jsb2NrcyQxKDI2LCBuZXcgRUNCJDEoMTcsIDQyKSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMTcsIDIyKSwgbmV3IEVDQiQxKDYsIDIzKSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMTksIDE2KSwgbmV3IEVDQiQxKDYsIDE3KSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDIyLCBJbnQzMkFycmF5LmZyb20oWzYsIDI2LCA1MCwgNzQsIDk4XSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMiwgMTExKSwgbmV3IEVDQiQxKDcsIDExMikpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDE3LCA0NikpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDcsIDI0KSwgbmV3IEVDQiQxKDE2LCAyNSkpLCBuZXcgRUNCbG9ja3MkMSgyNCwgbmV3IEVDQiQxKDM0LCAxMykpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgyMywgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTQsIDc4LCAxMDJdKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSg0LCAxMjEpLCBuZXcgRUNCJDEoNSwgMTIyKSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoNCwgNDcpLCBuZXcgRUNCJDEoMTQsIDQ4KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMTEsIDI0KSwgbmV3IEVDQiQxKDE0LCAyNSkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDE2LCAxNSksIG5ldyBFQ0IkMSgxNCwgMTYpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMjQsIEludDMyQXJyYXkuZnJvbShbNiwgMjgsIDU0LCA4MCwgMTA2XSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoNiwgMTE3KSwgbmV3IEVDQiQxKDQsIDExOCkpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDYsIDQ1KSwgbmV3IEVDQiQxKDE0LCA0NikpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDExLCAyNCksIG5ldyBFQ0IkMSgxNiwgMjUpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgzMCwgMTYpLCBuZXcgRUNCJDEoMiwgMTcpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMjUsIEludDMyQXJyYXkuZnJvbShbNiwgMzIsIDU4LCA4NCwgMTEwXSksIG5ldyBFQ0Jsb2NrcyQxKDI2LCBuZXcgRUNCJDEoOCwgMTA2KSwgbmV3IEVDQiQxKDQsIDEwNykpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDgsIDQ3KSwgbmV3IEVDQiQxKDEzLCA0OCkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDcsIDI0KSwgbmV3IEVDQiQxKDIyLCAyNSkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDIyLCAxNSksIG5ldyBFQ0IkMSgxMywgMTYpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMjYsIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIDU4LCA4NiwgMTE0XSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMTAsIDExNCksIG5ldyBFQ0IkMSgyLCAxMTUpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgxOSwgNDYpLCBuZXcgRUNCJDEoNCwgNDcpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgyOCwgMjIpLCBuZXcgRUNCJDEoNiwgMjMpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgzMywgMTYpLCBuZXcgRUNCJDEoNCwgMTcpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMjcsIEludDMyQXJyYXkuZnJvbShbNiwgMzQsIDYyLCA5MCwgMTE4XSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoOCwgMTIyKSwgbmV3IEVDQiQxKDQsIDEyMykpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDIyLCA0NSksIG5ldyBFQ0IkMSgzLCA0NikpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDgsIDIzKSwgbmV3IEVDQiQxKDI2LCAyNCkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDEyLCAxNSksIG5ldyBFQ0IkMSgyOCwgMTYpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMjgsIEludDMyQXJyYXkuZnJvbShbNiwgMjYsIDUwLCA3NCwgOTgsIDEyMl0pLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDMsIDExNyksIG5ldyBFQ0IkMSgxMCwgMTE4KSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMywgNDUpLCBuZXcgRUNCJDEoMjMsIDQ2KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoNCwgMjQpLCBuZXcgRUNCJDEoMzEsIDI1KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMTEsIDE1KSwgbmV3IEVDQiQxKDMxLCAxNikpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgyOSwgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTQsIDc4LCAxMDIsIDEyNl0pLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDcsIDExNiksIG5ldyBFQ0IkMSg3LCAxMTcpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgyMSwgNDUpLCBuZXcgRUNCJDEoNywgNDYpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgxLCAyMyksIG5ldyBFQ0IkMSgzNywgMjQpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgxOSwgMTUpLCBuZXcgRUNCJDEoMjYsIDE2KSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDMwLCBJbnQzMkFycmF5LmZyb20oWzYsIDI2LCA1MiwgNzgsIDEwNCwgMTMwXSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoNSwgMTE1KSwgbmV3IEVDQiQxKDEwLCAxMTYpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgxOSwgNDcpLCBuZXcgRUNCJDEoMTAsIDQ4KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMTUsIDI0KSwgbmV3IEVDQiQxKDI1LCAyNSkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDIzLCAxNSksIG5ldyBFQ0IkMSgyNSwgMTYpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMzEsIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIDU2LCA4MiwgMTA4LCAxMzRdKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgxMywgMTE1KSwgbmV3IEVDQiQxKDMsIDExNikpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDIsIDQ2KSwgbmV3IEVDQiQxKDI5LCA0NykpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDQyLCAyNCksIG5ldyBFQ0IkMSgxLCAyNSkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDIzLCAxNSksIG5ldyBFQ0IkMSgyOCwgMTYpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMzIsIEludDMyQXJyYXkuZnJvbShbNiwgMzQsIDYwLCA4NiwgMTEyLCAxMzhdKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgxNywgMTE1KSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMTAsIDQ2KSwgbmV3IEVDQiQxKDIzLCA0NykpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDEwLCAyNCksIG5ldyBFQ0IkMSgzNSwgMjUpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgxOSwgMTUpLCBuZXcgRUNCJDEoMzUsIDE2KSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDMzLCBJbnQzMkFycmF5LmZyb20oWzYsIDMwLCA1OCwgODYsIDExNCwgMTQyXSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMTcsIDExNSksIG5ldyBFQ0IkMSgxLCAxMTYpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgxNCwgNDYpLCBuZXcgRUNCJDEoMjEsIDQ3KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMjksIDI0KSwgbmV3IEVDQiQxKDE5LCAyNSkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDExLCAxNSksIG5ldyBFQ0IkMSg0NiwgMTYpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMzQsIEludDMyQXJyYXkuZnJvbShbNiwgMzQsIDYyLCA5MCwgMTE4LCAxNDZdKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgxMywgMTE1KSwgbmV3IEVDQiQxKDYsIDExNikpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDE0LCA0NiksIG5ldyBFQ0IkMSgyMywgNDcpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSg0NCwgMjQpLCBuZXcgRUNCJDEoNywgMjUpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSg1OSwgMTYpLCBuZXcgRUNCJDEoMSwgMTcpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMzUsIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIDU0LCA3OCwgMTAyLCAxMjYsIDE1MF0pLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDEyLCAxMjEpLCBuZXcgRUNCJDEoNywgMTIyKSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMTIsIDQ3KSwgbmV3IEVDQiQxKDI2LCA0OCkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDM5LCAyNCksIG5ldyBFQ0IkMSgxNCwgMjUpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgyMiwgMTUpLCBuZXcgRUNCJDEoNDEsIDE2KSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDM2LCBJbnQzMkFycmF5LmZyb20oWzYsIDI0LCA1MCwgNzYsIDEwMiwgMTI4LCAxNTRdKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSg2LCAxMjEpLCBuZXcgRUNCJDEoMTQsIDEyMikpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDYsIDQ3KSwgbmV3IEVDQiQxKDM0LCA0OCkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDQ2LCAyNCksIG5ldyBFQ0IkMSgxMCwgMjUpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgyLCAxNSksIG5ldyBFQ0IkMSg2NCwgMTYpKSksXG4gICAgICAgIG5ldyBWZXJzaW9uJDEoMzcsIEludDMyQXJyYXkuZnJvbShbNiwgMjgsIDU0LCA4MCwgMTA2LCAxMzIsIDE1OF0pLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDE3LCAxMjIpLCBuZXcgRUNCJDEoNCwgMTIzKSksIG5ldyBFQ0Jsb2NrcyQxKDI4LCBuZXcgRUNCJDEoMjksIDQ2KSwgbmV3IEVDQiQxKDE0LCA0NykpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDQ5LCAyNCksIG5ldyBFQ0IkMSgxMCwgMjUpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSgyNCwgMTUpLCBuZXcgRUNCJDEoNDYsIDE2KSkpLFxuICAgICAgICBuZXcgVmVyc2lvbiQxKDM4LCBJbnQzMkFycmF5LmZyb20oWzYsIDMyLCA1OCwgODQsIDExMCwgMTM2LCAxNjJdKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSg0LCAxMjIpLCBuZXcgRUNCJDEoMTgsIDEyMykpLCBuZXcgRUNCbG9ja3MkMSgyOCwgbmV3IEVDQiQxKDEzLCA0NiksIG5ldyBFQ0IkMSgzMiwgNDcpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSg0OCwgMjQpLCBuZXcgRUNCJDEoMTQsIDI1KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoNDIsIDE1KSwgbmV3IEVDQiQxKDMyLCAxNikpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSgzOSwgSW50MzJBcnJheS5mcm9tKFs2LCAyNiwgNTQsIDgyLCAxMTAsIDEzOCwgMTY2XSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMjAsIDExNyksIG5ldyBFQ0IkMSg0LCAxMTgpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSg0MCwgNDcpLCBuZXcgRUNCJDEoNywgNDgpKSwgbmV3IEVDQmxvY2tzJDEoMzAsIG5ldyBFQ0IkMSg0MywgMjQpLCBuZXcgRUNCJDEoMjIsIDI1KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMTAsIDE1KSwgbmV3IEVDQiQxKDY3LCAxNikpKSxcbiAgICAgICAgbmV3IFZlcnNpb24kMSg0MCwgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTgsIDg2LCAxMTQsIDE0MiwgMTcwXSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMTksIDExOCksIG5ldyBFQ0IkMSg2LCAxMTkpKSwgbmV3IEVDQmxvY2tzJDEoMjgsIG5ldyBFQ0IkMSgxOCwgNDcpLCBuZXcgRUNCJDEoMzEsIDQ4KSksIG5ldyBFQ0Jsb2NrcyQxKDMwLCBuZXcgRUNCJDEoMzQsIDI0KSwgbmV3IEVDQiQxKDM0LCAyNSkpLCBuZXcgRUNCbG9ja3MkMSgzMCwgbmV3IEVDQiQxKDIwLCAxNSksIG5ldyBFQ0IkMSg2MSwgMTYpKSlcbiAgICBdO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICB2YXIgRGF0YU1hc2tWYWx1ZXM7XG4gICAgKGZ1bmN0aW9uIChEYXRhTWFza1ZhbHVlcykge1xuICAgICAgICBEYXRhTWFza1ZhbHVlc1tEYXRhTWFza1ZhbHVlc1tcIkRBVEFfTUFTS18wMDBcIl0gPSAwXSA9IFwiREFUQV9NQVNLXzAwMFwiO1xuICAgICAgICBEYXRhTWFza1ZhbHVlc1tEYXRhTWFza1ZhbHVlc1tcIkRBVEFfTUFTS18wMDFcIl0gPSAxXSA9IFwiREFUQV9NQVNLXzAwMVwiO1xuICAgICAgICBEYXRhTWFza1ZhbHVlc1tEYXRhTWFza1ZhbHVlc1tcIkRBVEFfTUFTS18wMTBcIl0gPSAyXSA9IFwiREFUQV9NQVNLXzAxMFwiO1xuICAgICAgICBEYXRhTWFza1ZhbHVlc1tEYXRhTWFza1ZhbHVlc1tcIkRBVEFfTUFTS18wMTFcIl0gPSAzXSA9IFwiREFUQV9NQVNLXzAxMVwiO1xuICAgICAgICBEYXRhTWFza1ZhbHVlc1tEYXRhTWFza1ZhbHVlc1tcIkRBVEFfTUFTS18xMDBcIl0gPSA0XSA9IFwiREFUQV9NQVNLXzEwMFwiO1xuICAgICAgICBEYXRhTWFza1ZhbHVlc1tEYXRhTWFza1ZhbHVlc1tcIkRBVEFfTUFTS18xMDFcIl0gPSA1XSA9IFwiREFUQV9NQVNLXzEwMVwiO1xuICAgICAgICBEYXRhTWFza1ZhbHVlc1tEYXRhTWFza1ZhbHVlc1tcIkRBVEFfTUFTS18xMTBcIl0gPSA2XSA9IFwiREFUQV9NQVNLXzExMFwiO1xuICAgICAgICBEYXRhTWFza1ZhbHVlc1tEYXRhTWFza1ZhbHVlc1tcIkRBVEFfTUFTS18xMTFcIl0gPSA3XSA9IFwiREFUQV9NQVNLXzExMVwiO1xuICAgIH0pKERhdGFNYXNrVmFsdWVzIHx8IChEYXRhTWFza1ZhbHVlcyA9IHt9KSk7XG4gICAgLyoqXG4gICAgICogPHA+RW5jYXBzdWxhdGVzIGRhdGEgbWFza3MgZm9yIHRoZSBkYXRhIGJpdHMgaW4gYSBRUiBjb2RlLCBwZXIgSVNPIDE4MDA0OjIwMDYgNi44LiBJbXBsZW1lbnRhdGlvbnNcbiAgICAgKiBvZiB0aGlzIGNsYXNzIGNhbiB1bi1tYXNrIGEgcmF3IEJpdE1hdHJpeC4gRm9yIHNpbXBsaWNpdHksIHRoZXkgd2lsbCB1bm1hc2sgdGhlIGVudGlyZSBCaXRNYXRyaXgsXG4gICAgICogaW5jbHVkaW5nIGFyZWFzIHVzZWQgZm9yIGZpbmRlciBwYXR0ZXJucywgdGltaW5nIHBhdHRlcm5zLCBldGMuIFRoZXNlIGFyZWFzIHNob3VsZCBiZSB1bnVzZWRcbiAgICAgKiBhZnRlciB0aGUgcG9pbnQgdGhleSBhcmUgdW5tYXNrZWQgYW55d2F5LjwvcD5cbiAgICAgKlxuICAgICAqIDxwPk5vdGUgdGhhdCB0aGUgZGlhZ3JhbSBpbiBzZWN0aW9uIDYuOC4xIGlzIG1pc2xlYWRpbmcgc2luY2UgaXQgaW5kaWNhdGVzIHRoYXQgaSBpcyBjb2x1bW4gcG9zaXRpb25cbiAgICAgKiBhbmQgaiBpcyByb3cgcG9zaXRpb24uIEluIGZhY3QsIGFzIHRoZSB0ZXh0IHNheXMsIGkgaXMgcm93IHBvc2l0aW9uIGFuZCBqIGlzIGNvbHVtbiBwb3NpdGlvbi48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIERhdGFNYXNrIHtcbiAgICAgICAgLy8gU2VlIElTTyAxODAwNDoyMDA2IDYuOC4xXG4gICAgICAgIGNvbnN0cnVjdG9yKHZhbHVlLCBpc01hc2tlZCkge1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgdGhpcy5pc01hc2tlZCA9IGlzTWFza2VkO1xuICAgICAgICB9XG4gICAgICAgIC8vIEVuZCBvZiBlbnVtIGNvbnN0YW50cy5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkltcGxlbWVudGF0aW9ucyBvZiB0aGlzIG1ldGhvZCByZXZlcnNlIHRoZSBkYXRhIG1hc2tpbmcgcHJvY2VzcyBhcHBsaWVkIHRvIGEgUVIgQ29kZSBhbmRcbiAgICAgICAgICogbWFrZSBpdHMgYml0cyByZWFkeSB0byByZWFkLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGJpdHMgcmVwcmVzZW50YXRpb24gb2YgUVIgQ29kZSBiaXRzXG4gICAgICAgICAqIEBwYXJhbSBkaW1lbnNpb24gZGltZW5zaW9uIG9mIFFSIENvZGUsIHJlcHJlc2VudGVkIGJ5IGJpdHMsIGJlaW5nIHVubWFza2VkXG4gICAgICAgICAqL1xuICAgICAgICB1bm1hc2tCaXRNYXRyaXgoYml0cywgZGltZW5zaW9uIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGltZW5zaW9uOyBpKyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGRpbWVuc2lvbjsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzTWFza2VkKGksIGopKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBiaXRzLmZsaXAoaiwgaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgRGF0YU1hc2sudmFsdWVzID0gbmV3IE1hcChbXG4gICAgICAgIC8qKlxuICAgICAgICAgKiAwMDA6IG1hc2sgYml0cyBmb3Igd2hpY2ggKHggKyB5KSBtb2QgMiA9PSAwXG4gICAgICAgICAqL1xuICAgICAgICBbRGF0YU1hc2tWYWx1ZXMuREFUQV9NQVNLXzAwMCwgbmV3IERhdGFNYXNrKERhdGFNYXNrVmFsdWVzLkRBVEFfTUFTS18wMDAsIChpIC8qaW50Ki8sIGogLyppbnQqLykgPT4geyByZXR1cm4gKChpICsgaikgJiAweDAxKSA9PT0gMDsgfSldLFxuICAgICAgICAvKipcbiAgICAgICAgICogMDAxOiBtYXNrIGJpdHMgZm9yIHdoaWNoIHggbW9kIDIgPT0gMFxuICAgICAgICAgKi9cbiAgICAgICAgW0RhdGFNYXNrVmFsdWVzLkRBVEFfTUFTS18wMDEsIG5ldyBEYXRhTWFzayhEYXRhTWFza1ZhbHVlcy5EQVRBX01BU0tfMDAxLCAoaSAvKmludCovLCBqIC8qaW50Ki8pID0+IHsgcmV0dXJuIChpICYgMHgwMSkgPT09IDA7IH0pXSxcbiAgICAgICAgLyoqXG4gICAgICAgICAqIDAxMDogbWFzayBiaXRzIGZvciB3aGljaCB5IG1vZCAzID09IDBcbiAgICAgICAgICovXG4gICAgICAgIFtEYXRhTWFza1ZhbHVlcy5EQVRBX01BU0tfMDEwLCBuZXcgRGF0YU1hc2soRGF0YU1hc2tWYWx1ZXMuREFUQV9NQVNLXzAxMCwgKGkgLyppbnQqLywgaiAvKmludCovKSA9PiB7IHJldHVybiBqICUgMyA9PT0gMDsgfSldLFxuICAgICAgICAvKipcbiAgICAgICAgICogMDExOiBtYXNrIGJpdHMgZm9yIHdoaWNoICh4ICsgeSkgbW9kIDMgPT0gMFxuICAgICAgICAgKi9cbiAgICAgICAgW0RhdGFNYXNrVmFsdWVzLkRBVEFfTUFTS18wMTEsIG5ldyBEYXRhTWFzayhEYXRhTWFza1ZhbHVlcy5EQVRBX01BU0tfMDExLCAoaSAvKmludCovLCBqIC8qaW50Ki8pID0+IHsgcmV0dXJuIChpICsgaikgJSAzID09PSAwOyB9KV0sXG4gICAgICAgIC8qKlxuICAgICAgICAgKiAxMDA6IG1hc2sgYml0cyBmb3Igd2hpY2ggKHgvMiArIHkvMykgbW9kIDIgPT0gMFxuICAgICAgICAgKi9cbiAgICAgICAgW0RhdGFNYXNrVmFsdWVzLkRBVEFfTUFTS18xMDAsIG5ldyBEYXRhTWFzayhEYXRhTWFza1ZhbHVlcy5EQVRBX01BU0tfMTAwLCAoaSAvKmludCovLCBqIC8qaW50Ki8pID0+IHsgcmV0dXJuICgoTWF0aC5mbG9vcihpIC8gMikgKyBNYXRoLmZsb29yKGogLyAzKSkgJiAweDAxKSA9PT0gMDsgfSldLFxuICAgICAgICAvKipcbiAgICAgICAgICogMTAxOiBtYXNrIGJpdHMgZm9yIHdoaWNoIHh5IG1vZCAyICsgeHkgbW9kIDMgPT0gMFxuICAgICAgICAgKiBlcXVpdmFsZW50bHksIHN1Y2ggdGhhdCB4eSBtb2QgNiA9PSAwXG4gICAgICAgICAqL1xuICAgICAgICBbRGF0YU1hc2tWYWx1ZXMuREFUQV9NQVNLXzEwMSwgbmV3IERhdGFNYXNrKERhdGFNYXNrVmFsdWVzLkRBVEFfTUFTS18xMDEsIChpIC8qaW50Ki8sIGogLyppbnQqLykgPT4geyByZXR1cm4gKGkgKiBqKSAlIDYgPT09IDA7IH0pXSxcbiAgICAgICAgLyoqXG4gICAgICAgICAqIDExMDogbWFzayBiaXRzIGZvciB3aGljaCAoeHkgbW9kIDIgKyB4eSBtb2QgMykgbW9kIDIgPT0gMFxuICAgICAgICAgKiBlcXVpdmFsZW50bHksIHN1Y2ggdGhhdCB4eSBtb2QgNiA8IDNcbiAgICAgICAgICovXG4gICAgICAgIFtEYXRhTWFza1ZhbHVlcy5EQVRBX01BU0tfMTEwLCBuZXcgRGF0YU1hc2soRGF0YU1hc2tWYWx1ZXMuREFUQV9NQVNLXzExMCwgKGkgLyppbnQqLywgaiAvKmludCovKSA9PiB7IHJldHVybiAoKGkgKiBqKSAlIDYpIDwgMzsgfSldLFxuICAgICAgICAvKipcbiAgICAgICAgICogMTExOiBtYXNrIGJpdHMgZm9yIHdoaWNoICgoeCt5KW1vZCAyICsgeHkgbW9kIDMpIG1vZCAyID09IDBcbiAgICAgICAgICogZXF1aXZhbGVudGx5LCBzdWNoIHRoYXQgKHggKyB5ICsgeHkgbW9kIDMpIG1vZCAyID09IDBcbiAgICAgICAgICovXG4gICAgICAgIFtEYXRhTWFza1ZhbHVlcy5EQVRBX01BU0tfMTExLCBuZXcgRGF0YU1hc2soRGF0YU1hc2tWYWx1ZXMuREFUQV9NQVNLXzExMSwgKGkgLyppbnQqLywgaiAvKmludCovKSA9PiB7IHJldHVybiAoKGkgKyBqICsgKChpICogaikgJSAzKSkgJiAweDAxKSA9PT0gMDsgfSldLFxuICAgIF0pO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIEJpdE1hdHJpeFBhcnNlciQxIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBiaXRNYXRyaXgge0BsaW5rIEJpdE1hdHJpeH0gdG8gcGFyc2VcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb24gaWYgZGltZW5zaW9uIGlzIG5vdCA+PSAyMSBhbmQgMSBtb2QgNFxuICAgICAgICAgKi9cbiAgICAgICAgY29uc3RydWN0b3IoYml0TWF0cml4KSB7XG4gICAgICAgICAgICBjb25zdCBkaW1lbnNpb24gPSBiaXRNYXRyaXguZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICBpZiAoZGltZW5zaW9uIDwgMjEgfHwgKGRpbWVuc2lvbiAmIDB4MDMpICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5iaXRNYXRyaXggPSBiaXRNYXRyaXg7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPlJlYWRzIGZvcm1hdCBpbmZvcm1hdGlvbiBmcm9tIG9uZSBvZiBpdHMgdHdvIGxvY2F0aW9ucyB3aXRoaW4gdGhlIFFSIENvZGUuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIHtAbGluayBGb3JtYXRJbmZvcm1hdGlvbn0gZW5jYXBzdWxhdGluZyB0aGUgUVIgQ29kZSdzIGZvcm1hdCBpbmZvXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uIGlmIGJvdGggZm9ybWF0IGluZm9ybWF0aW9uIGxvY2F0aW9ucyBjYW5ub3QgYmUgcGFyc2VkIGFzXG4gICAgICAgICAqIHRoZSB2YWxpZCBlbmNvZGluZyBvZiBmb3JtYXQgaW5mb3JtYXRpb25cbiAgICAgICAgICovXG4gICAgICAgIHJlYWRGb3JtYXRJbmZvcm1hdGlvbigpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBhcnNlZEZvcm1hdEluZm8gIT09IG51bGwgJiYgdGhpcy5wYXJzZWRGb3JtYXRJbmZvICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJzZWRGb3JtYXRJbmZvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gUmVhZCB0b3AtbGVmdCBmb3JtYXQgaW5mbyBiaXRzXG4gICAgICAgICAgICBsZXQgZm9ybWF0SW5mb0JpdHMxID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgZm9ybWF0SW5mb0JpdHMxID0gdGhpcy5jb3B5Qml0KGksIDgsIGZvcm1hdEluZm9CaXRzMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyAuLiBhbmQgc2tpcCBhIGJpdCBpbiB0aGUgdGltaW5nIHBhdHRlcm4gLi4uXG4gICAgICAgICAgICBmb3JtYXRJbmZvQml0czEgPSB0aGlzLmNvcHlCaXQoNywgOCwgZm9ybWF0SW5mb0JpdHMxKTtcbiAgICAgICAgICAgIGZvcm1hdEluZm9CaXRzMSA9IHRoaXMuY29weUJpdCg4LCA4LCBmb3JtYXRJbmZvQml0czEpO1xuICAgICAgICAgICAgZm9ybWF0SW5mb0JpdHMxID0gdGhpcy5jb3B5Qml0KDgsIDcsIGZvcm1hdEluZm9CaXRzMSk7XG4gICAgICAgICAgICAvLyAuLiBhbmQgc2tpcCBhIGJpdCBpbiB0aGUgdGltaW5nIHBhdHRlcm4gLi4uXG4gICAgICAgICAgICBmb3IgKGxldCBqID0gNTsgaiA+PSAwOyBqLS0pIHtcbiAgICAgICAgICAgICAgICBmb3JtYXRJbmZvQml0czEgPSB0aGlzLmNvcHlCaXQoOCwgaiwgZm9ybWF0SW5mb0JpdHMxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFJlYWQgdGhlIHRvcC1yaWdodC9ib3R0b20tbGVmdCBwYXR0ZXJuIHRvb1xuICAgICAgICAgICAgY29uc3QgZGltZW5zaW9uID0gdGhpcy5iaXRNYXRyaXguZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICBsZXQgZm9ybWF0SW5mb0JpdHMyID0gMDtcbiAgICAgICAgICAgIGNvbnN0IGpNaW4gPSBkaW1lbnNpb24gLSA3O1xuICAgICAgICAgICAgZm9yIChsZXQgaiA9IGRpbWVuc2lvbiAtIDE7IGogPj0gak1pbjsgai0tKSB7XG4gICAgICAgICAgICAgICAgZm9ybWF0SW5mb0JpdHMyID0gdGhpcy5jb3B5Qml0KDgsIGosIGZvcm1hdEluZm9CaXRzMik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gZGltZW5zaW9uIC0gODsgaSA8IGRpbWVuc2lvbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgZm9ybWF0SW5mb0JpdHMyID0gdGhpcy5jb3B5Qml0KGksIDgsIGZvcm1hdEluZm9CaXRzMik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnBhcnNlZEZvcm1hdEluZm8gPSBGb3JtYXRJbmZvcm1hdGlvbi5kZWNvZGVGb3JtYXRJbmZvcm1hdGlvbihmb3JtYXRJbmZvQml0czEsIGZvcm1hdEluZm9CaXRzMik7XG4gICAgICAgICAgICBpZiAodGhpcy5wYXJzZWRGb3JtYXRJbmZvICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyc2VkRm9ybWF0SW5mbztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+UmVhZHMgdmVyc2lvbiBpbmZvcm1hdGlvbiBmcm9tIG9uZSBvZiBpdHMgdHdvIGxvY2F0aW9ucyB3aXRoaW4gdGhlIFFSIENvZGUuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIHtAbGluayBWZXJzaW9ufSBlbmNhcHN1bGF0aW5nIHRoZSBRUiBDb2RlJ3MgdmVyc2lvblxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvbiBpZiBib3RoIHZlcnNpb24gaW5mb3JtYXRpb24gbG9jYXRpb25zIGNhbm5vdCBiZSBwYXJzZWQgYXNcbiAgICAgICAgICogdGhlIHZhbGlkIGVuY29kaW5nIG9mIHZlcnNpb24gaW5mb3JtYXRpb25cbiAgICAgICAgICovXG4gICAgICAgIHJlYWRWZXJzaW9uKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMucGFyc2VkVmVyc2lvbiAhPT0gbnVsbCAmJiB0aGlzLnBhcnNlZFZlcnNpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcnNlZFZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBkaW1lbnNpb24gPSB0aGlzLmJpdE1hdHJpeC5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IHByb3Zpc2lvbmFsVmVyc2lvbiA9IE1hdGguZmxvb3IoKGRpbWVuc2lvbiAtIDE3KSAvIDQpO1xuICAgICAgICAgICAgaWYgKHByb3Zpc2lvbmFsVmVyc2lvbiA8PSA2KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFZlcnNpb24kMS5nZXRWZXJzaW9uRm9yTnVtYmVyKHByb3Zpc2lvbmFsVmVyc2lvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBSZWFkIHRvcC1yaWdodCB2ZXJzaW9uIGluZm86IDMgd2lkZSBieSA2IHRhbGxcbiAgICAgICAgICAgIGxldCB2ZXJzaW9uQml0cyA9IDA7XG4gICAgICAgICAgICBjb25zdCBpak1pbiA9IGRpbWVuc2lvbiAtIDExO1xuICAgICAgICAgICAgZm9yIChsZXQgaiA9IDU7IGogPj0gMDsgai0tKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IGRpbWVuc2lvbiAtIDk7IGkgPj0gaWpNaW47IGktLSkge1xuICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uQml0cyA9IHRoaXMuY29weUJpdChpLCBqLCB2ZXJzaW9uQml0cyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHRoZVBhcnNlZFZlcnNpb24gPSBWZXJzaW9uJDEuZGVjb2RlVmVyc2lvbkluZm9ybWF0aW9uKHZlcnNpb25CaXRzKTtcbiAgICAgICAgICAgIGlmICh0aGVQYXJzZWRWZXJzaW9uICE9PSBudWxsICYmIHRoZVBhcnNlZFZlcnNpb24uZ2V0RGltZW5zaW9uRm9yVmVyc2lvbigpID09PSBkaW1lbnNpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBhcnNlZFZlcnNpb24gPSB0aGVQYXJzZWRWZXJzaW9uO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGVQYXJzZWRWZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSG1tLCBmYWlsZWQuIFRyeSBib3R0b20gbGVmdDogNiB3aWRlIGJ5IDMgdGFsbFxuICAgICAgICAgICAgdmVyc2lvbkJpdHMgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDU7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IGRpbWVuc2lvbiAtIDk7IGogPj0gaWpNaW47IGotLSkge1xuICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uQml0cyA9IHRoaXMuY29weUJpdChpLCBqLCB2ZXJzaW9uQml0cyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhlUGFyc2VkVmVyc2lvbiA9IFZlcnNpb24kMS5kZWNvZGVWZXJzaW9uSW5mb3JtYXRpb24odmVyc2lvbkJpdHMpO1xuICAgICAgICAgICAgaWYgKHRoZVBhcnNlZFZlcnNpb24gIT09IG51bGwgJiYgdGhlUGFyc2VkVmVyc2lvbi5nZXREaW1lbnNpb25Gb3JWZXJzaW9uKCkgPT09IGRpbWVuc2lvbikge1xuICAgICAgICAgICAgICAgIHRoaXMucGFyc2VkVmVyc2lvbiA9IHRoZVBhcnNlZFZlcnNpb247XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoZVBhcnNlZFZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgY29weUJpdChpIC8qaW50Ki8sIGogLyppbnQqLywgdmVyc2lvbkJpdHMgLyppbnQqLykge1xuICAgICAgICAgICAgY29uc3QgYml0ID0gdGhpcy5pc01pcnJvciA/IHRoaXMuYml0TWF0cml4LmdldChqLCBpKSA6IHRoaXMuYml0TWF0cml4LmdldChpLCBqKTtcbiAgICAgICAgICAgIHJldHVybiBiaXQgPyAodmVyc2lvbkJpdHMgPDwgMSkgfCAweDEgOiB2ZXJzaW9uQml0cyA8PCAxO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5SZWFkcyB0aGUgYml0cyBpbiB0aGUge0BsaW5rIEJpdE1hdHJpeH0gcmVwcmVzZW50aW5nIHRoZSBmaW5kZXIgcGF0dGVybiBpbiB0aGVcbiAgICAgICAgICogY29ycmVjdCBvcmRlciBpbiBvcmRlciB0byByZWNvbnN0cnVjdCB0aGUgY29kZXdvcmRzIGJ5dGVzIGNvbnRhaW5lZCB3aXRoaW4gdGhlXG4gICAgICAgICAqIFFSIENvZGUuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIGJ5dGVzIGVuY29kZWQgd2l0aGluIHRoZSBRUiBDb2RlXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uIGlmIHRoZSBleGFjdCBudW1iZXIgb2YgYnl0ZXMgZXhwZWN0ZWQgaXMgbm90IHJlYWRcbiAgICAgICAgICovXG4gICAgICAgIHJlYWRDb2Rld29yZHMoKSB7XG4gICAgICAgICAgICBjb25zdCBmb3JtYXRJbmZvID0gdGhpcy5yZWFkRm9ybWF0SW5mb3JtYXRpb24oKTtcbiAgICAgICAgICAgIGNvbnN0IHZlcnNpb24gPSB0aGlzLnJlYWRWZXJzaW9uKCk7XG4gICAgICAgICAgICAvLyBHZXQgdGhlIGRhdGEgbWFzayBmb3IgdGhlIGZvcm1hdCB1c2VkIGluIHRoaXMgUVIgQ29kZS4gVGhpcyB3aWxsIGV4Y2x1ZGVcbiAgICAgICAgICAgIC8vIHNvbWUgYml0cyBmcm9tIHJlYWRpbmcgYXMgd2Ugd2luZCB0aHJvdWdoIHRoZSBiaXQgbWF0cml4LlxuICAgICAgICAgICAgY29uc3QgZGF0YU1hc2sgPSBEYXRhTWFzay52YWx1ZXMuZ2V0KGZvcm1hdEluZm8uZ2V0RGF0YU1hc2soKSk7XG4gICAgICAgICAgICBjb25zdCBkaW1lbnNpb24gPSB0aGlzLmJpdE1hdHJpeC5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGRhdGFNYXNrLnVubWFza0JpdE1hdHJpeCh0aGlzLmJpdE1hdHJpeCwgZGltZW5zaW9uKTtcbiAgICAgICAgICAgIGNvbnN0IGZ1bmN0aW9uUGF0dGVybiA9IHZlcnNpb24uYnVpbGRGdW5jdGlvblBhdHRlcm4oKTtcbiAgICAgICAgICAgIGxldCByZWFkaW5nVXAgPSB0cnVlO1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IFVpbnQ4QXJyYXkodmVyc2lvbi5nZXRUb3RhbENvZGV3b3JkcygpKTtcbiAgICAgICAgICAgIGxldCByZXN1bHRPZmZzZXQgPSAwO1xuICAgICAgICAgICAgbGV0IGN1cnJlbnRCeXRlID0gMDtcbiAgICAgICAgICAgIGxldCBiaXRzUmVhZCA9IDA7XG4gICAgICAgICAgICAvLyBSZWFkIGNvbHVtbnMgaW4gcGFpcnMsIGZyb20gcmlnaHQgdG8gbGVmdFxuICAgICAgICAgICAgZm9yIChsZXQgaiA9IGRpbWVuc2lvbiAtIDE7IGogPiAwOyBqIC09IDIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaiA9PT0gNikge1xuICAgICAgICAgICAgICAgICAgICAvLyBTa2lwIHdob2xlIGNvbHVtbiB3aXRoIHZlcnRpY2FsIGFsaWdubWVudCBwYXR0ZXJuXG4gICAgICAgICAgICAgICAgICAgIC8vIHNhdmVzIHRpbWUgYW5kIG1ha2VzIHRoZSBvdGhlciBjb2RlIHByb2NlZWQgbW9yZSBjbGVhbmx5XG4gICAgICAgICAgICAgICAgICAgIGotLTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gUmVhZCBhbHRlcm5hdGluZ2x5IGZyb20gYm90dG9tIHRvIHRvcCB0aGVuIHRvcCB0byBib3R0b21cbiAgICAgICAgICAgICAgICBmb3IgKGxldCBjb3VudCA9IDA7IGNvdW50IDwgZGltZW5zaW9uOyBjb3VudCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGkgPSByZWFkaW5nVXAgPyBkaW1lbnNpb24gLSAxIC0gY291bnQgOiBjb3VudDtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgY29sID0gMDsgY29sIDwgMjsgY29sKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElnbm9yZSBiaXRzIGNvdmVyZWQgYnkgdGhlIGZ1bmN0aW9uIHBhdHRlcm5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZnVuY3Rpb25QYXR0ZXJuLmdldChqIC0gY29sLCBpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlYWQgYSBiaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaXRzUmVhZCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRCeXRlIDw8PSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmJpdE1hdHJpeC5nZXQoaiAtIGNvbCwgaSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudEJ5dGUgfD0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgd2UndmUgbWFkZSBhIHdob2xlIGJ5dGUsIHNhdmUgaXQgb2ZmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJpdHNSZWFkID09PSA4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdFtyZXN1bHRPZmZzZXQrK10gPSAvKihieXRlKSAqLyBjdXJyZW50Qnl0ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYml0c1JlYWQgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50Qnl0ZSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlYWRpbmdVcCA9ICFyZWFkaW5nVXA7IC8vIHJlYWRpbmdVcCBePSB0cnVlOyAvLyByZWFkaW5nVXAgPSAhcmVhZGluZ1VwOyAvLyBzd2l0Y2ggZGlyZWN0aW9uc1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJlc3VsdE9mZnNldCAhPT0gdmVyc2lvbi5nZXRUb3RhbENvZGV3b3JkcygpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogUmV2ZXJ0IHRoZSBtYXNrIHJlbW92YWwgZG9uZSB3aGlsZSByZWFkaW5nIHRoZSBjb2RlIHdvcmRzLiBUaGUgYml0IG1hdHJpeCBzaG91bGQgcmV2ZXJ0IHRvIGl0cyBvcmlnaW5hbCBzdGF0ZS5cbiAgICAgICAgICovXG4gICAgICAgIHJlbWFzaygpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBhcnNlZEZvcm1hdEluZm8gPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47IC8vIFdlIGhhdmUgbm8gZm9ybWF0IGluZm9ybWF0aW9uLCBhbmQgaGF2ZSBubyBkYXRhIG1hc2tcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGRhdGFNYXNrID0gRGF0YU1hc2sudmFsdWVzW3RoaXMucGFyc2VkRm9ybWF0SW5mby5nZXREYXRhTWFzaygpXTtcbiAgICAgICAgICAgIGNvbnN0IGRpbWVuc2lvbiA9IHRoaXMuYml0TWF0cml4LmdldEhlaWdodCgpO1xuICAgICAgICAgICAgZGF0YU1hc2sudW5tYXNrQml0TWF0cml4KHRoaXMuYml0TWF0cml4LCBkaW1lbnNpb24pO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQcmVwYXJlIHRoZSBwYXJzZXIgZm9yIGEgbWlycm9yZWQgb3BlcmF0aW9uLlxuICAgICAgICAgKiBUaGlzIGZsYWcgaGFzIGVmZmVjdCBvbmx5IG9uIHRoZSB7QGxpbmsgI3JlYWRGb3JtYXRJbmZvcm1hdGlvbigpfSBhbmQgdGhlXG4gICAgICAgICAqIHtAbGluayAjcmVhZFZlcnNpb24oKX0uIEJlZm9yZSBwcm9jZWVkaW5nIHdpdGgge0BsaW5rICNyZWFkQ29kZXdvcmRzKCl9IHRoZVxuICAgICAgICAgKiB7QGxpbmsgI21pcnJvcigpfSBtZXRob2Qgc2hvdWxkIGJlIGNhbGxlZC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIG1pcnJvciBXaGV0aGVyIHRvIHJlYWQgdmVyc2lvbiBhbmQgZm9ybWF0IGluZm9ybWF0aW9uIG1pcnJvcmVkLlxuICAgICAgICAgKi9cbiAgICAgICAgc2V0TWlycm9yKGlzTWlycm9yKSB7XG4gICAgICAgICAgICB0aGlzLnBhcnNlZFZlcnNpb24gPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5wYXJzZWRGb3JtYXRJbmZvID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuaXNNaXJyb3IgPSBpc01pcnJvcjtcbiAgICAgICAgfVxuICAgICAgICAvKiogTWlycm9yIHRoZSBiaXQgbWF0cml4IGluIG9yZGVyIHRvIGF0dGVtcHQgYSBzZWNvbmQgcmVhZGluZy4gKi9cbiAgICAgICAgbWlycm9yKCkge1xuICAgICAgICAgICAgY29uc3QgYml0TWF0cml4ID0gdGhpcy5iaXRNYXRyaXg7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gMCwgd2lkdGggPSBiaXRNYXRyaXguZ2V0V2lkdGgoKTsgeCA8IHdpZHRoOyB4KyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB5ID0geCArIDEsIGhlaWdodCA9IGJpdE1hdHJpeC5nZXRIZWlnaHQoKTsgeSA8IGhlaWdodDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChiaXRNYXRyaXguZ2V0KHgsIHkpICE9PSBiaXRNYXRyaXguZ2V0KHksIHgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBiaXRNYXRyaXguZmxpcCh5LCB4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJpdE1hdHJpeC5mbGlwKHgsIHkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiA8cD5FbmNhcHN1bGF0ZXMgYSBibG9jayBvZiBkYXRhIHdpdGhpbiBhIFFSIENvZGUuIFFSIENvZGVzIG1heSBzcGxpdCB0aGVpciBkYXRhIGludG9cbiAgICAgKiBtdWx0aXBsZSBibG9ja3MsIGVhY2ggb2Ygd2hpY2ggaXMgYSB1bml0IG9mIGRhdGEgYW5kIGVycm9yLWNvcnJlY3Rpb24gY29kZXdvcmRzLiBFYWNoXG4gICAgICogaXMgcmVwcmVzZW50ZWQgYnkgYW4gaW5zdGFuY2Ugb2YgdGhpcyBjbGFzcy48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIERhdGFCbG9jayQxIHtcbiAgICAgICAgY29uc3RydWN0b3IobnVtRGF0YUNvZGV3b3JkcyAvKmludCovLCBjb2Rld29yZHMpIHtcbiAgICAgICAgICAgIHRoaXMubnVtRGF0YUNvZGV3b3JkcyA9IG51bURhdGFDb2Rld29yZHM7XG4gICAgICAgICAgICB0aGlzLmNvZGV3b3JkcyA9IGNvZGV3b3JkcztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+V2hlbiBRUiBDb2RlcyB1c2UgbXVsdGlwbGUgZGF0YSBibG9ja3MsIHRoZXkgYXJlIGFjdHVhbGx5IGludGVybGVhdmVkLlxuICAgICAgICAgKiBUaGF0IGlzLCB0aGUgZmlyc3QgYnl0ZSBvZiBkYXRhIGJsb2NrIDEgdG8gbiBpcyB3cml0dGVuLCB0aGVuIHRoZSBzZWNvbmQgYnl0ZXMsIGFuZCBzbyBvbi4gVGhpc1xuICAgICAgICAgKiBtZXRob2Qgd2lsbCBzZXBhcmF0ZSB0aGUgZGF0YSBpbnRvIG9yaWdpbmFsIGJsb2Nrcy48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSByYXdDb2Rld29yZHMgYnl0ZXMgYXMgcmVhZCBkaXJlY3RseSBmcm9tIHRoZSBRUiBDb2RlXG4gICAgICAgICAqIEBwYXJhbSB2ZXJzaW9uIHZlcnNpb24gb2YgdGhlIFFSIENvZGVcbiAgICAgICAgICogQHBhcmFtIGVjTGV2ZWwgZXJyb3ItY29ycmVjdGlvbiBsZXZlbCBvZiB0aGUgUVIgQ29kZVxuICAgICAgICAgKiBAcmV0dXJuIERhdGFCbG9ja3MgY29udGFpbmluZyBvcmlnaW5hbCBieXRlcywgXCJkZS1pbnRlcmxlYXZlZFwiIGZyb20gcmVwcmVzZW50YXRpb24gaW4gdGhlXG4gICAgICAgICAqICAgICAgICAgUVIgQ29kZVxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGdldERhdGFCbG9ja3MocmF3Q29kZXdvcmRzLCB2ZXJzaW9uLCBlY0xldmVsKSB7XG4gICAgICAgICAgICBpZiAocmF3Q29kZXdvcmRzLmxlbmd0aCAhPT0gdmVyc2lvbi5nZXRUb3RhbENvZGV3b3JkcygpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRmlndXJlIG91dCB0aGUgbnVtYmVyIGFuZCBzaXplIG9mIGRhdGEgYmxvY2tzIHVzZWQgYnkgdGhpcyB2ZXJzaW9uIGFuZFxuICAgICAgICAgICAgLy8gZXJyb3IgY29ycmVjdGlvbiBsZXZlbFxuICAgICAgICAgICAgY29uc3QgZWNCbG9ja3MgPSB2ZXJzaW9uLmdldEVDQmxvY2tzRm9yTGV2ZWwoZWNMZXZlbCk7XG4gICAgICAgICAgICAvLyBGaXJzdCBjb3VudCB0aGUgdG90YWwgbnVtYmVyIG9mIGRhdGEgYmxvY2tzXG4gICAgICAgICAgICBsZXQgdG90YWxCbG9ja3MgPSAwO1xuICAgICAgICAgICAgY29uc3QgZWNCbG9ja0FycmF5ID0gZWNCbG9ja3MuZ2V0RUNCbG9ja3MoKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgZWNCbG9jayBvZiBlY0Jsb2NrQXJyYXkpIHtcbiAgICAgICAgICAgICAgICB0b3RhbEJsb2NrcyArPSBlY0Jsb2NrLmdldENvdW50KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBOb3cgZXN0YWJsaXNoIERhdGFCbG9ja3Mgb2YgdGhlIGFwcHJvcHJpYXRlIHNpemUgYW5kIG51bWJlciBvZiBkYXRhIGNvZGV3b3Jkc1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IEFycmF5KHRvdGFsQmxvY2tzKTtcbiAgICAgICAgICAgIGxldCBudW1SZXN1bHRCbG9ja3MgPSAwO1xuICAgICAgICAgICAgZm9yIChjb25zdCBlY0Jsb2NrIG9mIGVjQmxvY2tBcnJheSkge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZWNCbG9jay5nZXRDb3VudCgpOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbnVtRGF0YUNvZGV3b3JkcyA9IGVjQmxvY2suZ2V0RGF0YUNvZGV3b3JkcygpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBudW1CbG9ja0NvZGV3b3JkcyA9IGVjQmxvY2tzLmdldEVDQ29kZXdvcmRzUGVyQmxvY2soKSArIG51bURhdGFDb2Rld29yZHM7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtudW1SZXN1bHRCbG9ja3MrK10gPSBuZXcgRGF0YUJsb2NrJDEobnVtRGF0YUNvZGV3b3JkcywgbmV3IFVpbnQ4QXJyYXkobnVtQmxvY2tDb2Rld29yZHMpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBBbGwgYmxvY2tzIGhhdmUgdGhlIHNhbWUgYW1vdW50IG9mIGRhdGEsIGV4Y2VwdCB0aGF0IHRoZSBsYXN0IG5cbiAgICAgICAgICAgIC8vICh3aGVyZSBuIG1heSBiZSAwKSBoYXZlIDEgbW9yZSBieXRlLiBGaWd1cmUgb3V0IHdoZXJlIHRoZXNlIHN0YXJ0LlxuICAgICAgICAgICAgY29uc3Qgc2hvcnRlckJsb2Nrc1RvdGFsQ29kZXdvcmRzID0gcmVzdWx0WzBdLmNvZGV3b3Jkcy5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgbG9uZ2VyQmxvY2tzU3RhcnRBdCA9IHJlc3VsdC5sZW5ndGggLSAxO1xuICAgICAgICAgICAgLy8gVFlQRVNDUklQVFBPUlQ6IGNoZWNrIGxlbmd0aCBpcyBjb3JyZWN0IGhlcmVcbiAgICAgICAgICAgIHdoaWxlIChsb25nZXJCbG9ja3NTdGFydEF0ID49IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBudW1Db2Rld29yZHMgPSByZXN1bHRbbG9uZ2VyQmxvY2tzU3RhcnRBdF0uY29kZXdvcmRzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBpZiAobnVtQ29kZXdvcmRzID09PSBzaG9ydGVyQmxvY2tzVG90YWxDb2Rld29yZHMpIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxvbmdlckJsb2Nrc1N0YXJ0QXQtLTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxvbmdlckJsb2Nrc1N0YXJ0QXQrKztcbiAgICAgICAgICAgIGNvbnN0IHNob3J0ZXJCbG9ja3NOdW1EYXRhQ29kZXdvcmRzID0gc2hvcnRlckJsb2Nrc1RvdGFsQ29kZXdvcmRzIC0gZWNCbG9ja3MuZ2V0RUNDb2Rld29yZHNQZXJCbG9jaygpO1xuICAgICAgICAgICAgLy8gVGhlIGxhc3QgZWxlbWVudHMgb2YgcmVzdWx0IG1heSBiZSAxIGVsZW1lbnQgbG9uZ2VyXG4gICAgICAgICAgICAvLyBmaXJzdCBmaWxsIG91dCBhcyBtYW55IGVsZW1lbnRzIGFzIGFsbCBvZiB0aGVtIGhhdmVcbiAgICAgICAgICAgIGxldCByYXdDb2Rld29yZHNPZmZzZXQgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaG9ydGVyQmxvY2tzTnVtRGF0YUNvZGV3b3JkczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBudW1SZXN1bHRCbG9ja3M7IGorKykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRbal0uY29kZXdvcmRzW2ldID0gcmF3Q29kZXdvcmRzW3Jhd0NvZGV3b3Jkc09mZnNldCsrXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBGaWxsIG91dCB0aGUgbGFzdCBkYXRhIGJsb2NrIGluIHRoZSBsb25nZXIgb25lc1xuICAgICAgICAgICAgZm9yIChsZXQgaiA9IGxvbmdlckJsb2Nrc1N0YXJ0QXQ7IGogPCBudW1SZXN1bHRCbG9ja3M7IGorKykge1xuICAgICAgICAgICAgICAgIHJlc3VsdFtqXS5jb2Rld29yZHNbc2hvcnRlckJsb2Nrc051bURhdGFDb2Rld29yZHNdID0gcmF3Q29kZXdvcmRzW3Jhd0NvZGV3b3Jkc09mZnNldCsrXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE5vdyBhZGQgaW4gZXJyb3IgY29ycmVjdGlvbiBibG9ja3NcbiAgICAgICAgICAgIGNvbnN0IG1heCA9IHJlc3VsdFswXS5jb2Rld29yZHMubGVuZ3RoO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IHNob3J0ZXJCbG9ja3NOdW1EYXRhQ29kZXdvcmRzOyBpIDwgbWF4OyBpKyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IG51bVJlc3VsdEJsb2NrczsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGlPZmZzZXQgPSBqIDwgbG9uZ2VyQmxvY2tzU3RhcnRBdCA/IGkgOiBpICsgMTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2pdLmNvZGV3b3Jkc1tpT2Zmc2V0XSA9IHJhd0NvZGV3b3Jkc1tyYXdDb2Rld29yZHNPZmZzZXQrK107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBnZXROdW1EYXRhQ29kZXdvcmRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubnVtRGF0YUNvZGV3b3JkcztcbiAgICAgICAgfVxuICAgICAgICBnZXRDb2Rld29yZHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2Rld29yZHM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIHZhciBNb2RlVmFsdWVzO1xuICAgIChmdW5jdGlvbiAoTW9kZVZhbHVlcykge1xuICAgICAgICBNb2RlVmFsdWVzW01vZGVWYWx1ZXNbXCJURVJNSU5BVE9SXCJdID0gMF0gPSBcIlRFUk1JTkFUT1JcIjtcbiAgICAgICAgTW9kZVZhbHVlc1tNb2RlVmFsdWVzW1wiTlVNRVJJQ1wiXSA9IDFdID0gXCJOVU1FUklDXCI7XG4gICAgICAgIE1vZGVWYWx1ZXNbTW9kZVZhbHVlc1tcIkFMUEhBTlVNRVJJQ1wiXSA9IDJdID0gXCJBTFBIQU5VTUVSSUNcIjtcbiAgICAgICAgTW9kZVZhbHVlc1tNb2RlVmFsdWVzW1wiU1RSVUNUVVJFRF9BUFBFTkRcIl0gPSAzXSA9IFwiU1RSVUNUVVJFRF9BUFBFTkRcIjtcbiAgICAgICAgTW9kZVZhbHVlc1tNb2RlVmFsdWVzW1wiQllURVwiXSA9IDRdID0gXCJCWVRFXCI7XG4gICAgICAgIE1vZGVWYWx1ZXNbTW9kZVZhbHVlc1tcIkVDSVwiXSA9IDVdID0gXCJFQ0lcIjtcbiAgICAgICAgTW9kZVZhbHVlc1tNb2RlVmFsdWVzW1wiS0FOSklcIl0gPSA2XSA9IFwiS0FOSklcIjtcbiAgICAgICAgTW9kZVZhbHVlc1tNb2RlVmFsdWVzW1wiRk5DMV9GSVJTVF9QT1NJVElPTlwiXSA9IDddID0gXCJGTkMxX0ZJUlNUX1BPU0lUSU9OXCI7XG4gICAgICAgIE1vZGVWYWx1ZXNbTW9kZVZhbHVlc1tcIkZOQzFfU0VDT05EX1BPU0lUSU9OXCJdID0gOF0gPSBcIkZOQzFfU0VDT05EX1BPU0lUSU9OXCI7XG4gICAgICAgIC8qKiBTZWUgR0JUIDE4Mjg0LTIwMDA7IFwiSGFuemlcIiBpcyBhIHRyYW5zbGl0ZXJhdGlvbiBvZiB0aGlzIG1vZGUgbmFtZS4gKi9cbiAgICAgICAgTW9kZVZhbHVlc1tNb2RlVmFsdWVzW1wiSEFOWklcIl0gPSA5XSA9IFwiSEFOWklcIjtcbiAgICB9KShNb2RlVmFsdWVzIHx8IChNb2RlVmFsdWVzID0ge30pKTtcbiAgICAvKipcbiAgICAgKiA8cD5TZWUgSVNPIDE4MDA0OjIwMDYsIDYuNC4xLCBUYWJsZXMgMiBhbmQgMy4gVGhpcyBlbnVtIGVuY2Fwc3VsYXRlcyB0aGUgdmFyaW91cyBtb2RlcyBpbiB3aGljaFxuICAgICAqIGRhdGEgY2FuIGJlIGVuY29kZWQgdG8gYml0cyBpbiB0aGUgUVIgY29kZSBzdGFuZGFyZC48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIE1vZGUkMSB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHZhbHVlLCBzdHJpbmdWYWx1ZSwgY2hhcmFjdGVyQ291bnRCaXRzRm9yVmVyc2lvbnMsIGJpdHMgLyppbnQqLykge1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgdGhpcy5zdHJpbmdWYWx1ZSA9IHN0cmluZ1ZhbHVlO1xuICAgICAgICAgICAgdGhpcy5jaGFyYWN0ZXJDb3VudEJpdHNGb3JWZXJzaW9ucyA9IGNoYXJhY3RlckNvdW50Qml0c0ZvclZlcnNpb25zO1xuICAgICAgICAgICAgdGhpcy5iaXRzID0gYml0cztcbiAgICAgICAgICAgIE1vZGUkMS5GT1JfQklUUy5zZXQoYml0cywgdGhpcyk7XG4gICAgICAgICAgICBNb2RlJDEuRk9SX1ZBTFVFLnNldCh2YWx1ZSwgdGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBiaXRzIGZvdXIgYml0cyBlbmNvZGluZyBhIFFSIENvZGUgZGF0YSBtb2RlXG4gICAgICAgICAqIEByZXR1cm4gTW9kZSBlbmNvZGVkIGJ5IHRoZXNlIGJpdHNcbiAgICAgICAgICogQHRocm93cyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24gaWYgYml0cyBkbyBub3QgY29ycmVzcG9uZCB0byBhIGtub3duIG1vZGVcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBmb3JCaXRzKGJpdHMgLyppbnQqLykge1xuICAgICAgICAgICAgY29uc3QgbW9kZSA9IE1vZGUkMS5GT1JfQklUUy5nZXQoYml0cyk7XG4gICAgICAgICAgICBpZiAodW5kZWZpbmVkID09PSBtb2RlKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1vZGU7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB2ZXJzaW9uIHZlcnNpb24gaW4gcXVlc3Rpb25cbiAgICAgICAgICogQHJldHVybiBudW1iZXIgb2YgYml0cyB1c2VkLCBpbiB0aGlzIFFSIENvZGUgc3ltYm9sIHtAbGluayBWZXJzaW9ufSwgdG8gZW5jb2RlIHRoZVxuICAgICAgICAgKiAgICAgICAgIGNvdW50IG9mIGNoYXJhY3RlcnMgdGhhdCB3aWxsIGZvbGxvdyBlbmNvZGVkIGluIHRoaXMgTW9kZVxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0Q2hhcmFjdGVyQ291bnRCaXRzKHZlcnNpb24pIHtcbiAgICAgICAgICAgIGNvbnN0IHZlcnNpb25OdW1iZXIgPSB2ZXJzaW9uLmdldFZlcnNpb25OdW1iZXIoKTtcbiAgICAgICAgICAgIGxldCBvZmZzZXQ7XG4gICAgICAgICAgICBpZiAodmVyc2lvbk51bWJlciA8PSA5KSB7XG4gICAgICAgICAgICAgICAgb2Zmc2V0ID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHZlcnNpb25OdW1iZXIgPD0gMjYpIHtcbiAgICAgICAgICAgICAgICBvZmZzZXQgPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgb2Zmc2V0ID0gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNoYXJhY3RlckNvdW50Qml0c0ZvclZlcnNpb25zW29mZnNldF07XG4gICAgICAgIH1cbiAgICAgICAgZ2V0VmFsdWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRCaXRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYml0cztcbiAgICAgICAgfVxuICAgICAgICBlcXVhbHMobykge1xuICAgICAgICAgICAgaWYgKCEobyBpbnN0YW5jZW9mIE1vZGUkMSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBvdGhlciA9IG87XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZSA9PT0gb3RoZXIudmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zdHJpbmdWYWx1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBNb2RlJDEuRk9SX0JJVFMgPSBuZXcgTWFwKCk7XG4gICAgTW9kZSQxLkZPUl9WQUxVRSA9IG5ldyBNYXAoKTtcbiAgICBNb2RlJDEuVEVSTUlOQVRPUiA9IG5ldyBNb2RlJDEoTW9kZVZhbHVlcy5URVJNSU5BVE9SLCAnVEVSTUlOQVRPUicsIEludDMyQXJyYXkuZnJvbShbMCwgMCwgMF0pLCAweDAwKTsgLy8gTm90IHJlYWxseSBhIG1vZGUuLi5cbiAgICBNb2RlJDEuTlVNRVJJQyA9IG5ldyBNb2RlJDEoTW9kZVZhbHVlcy5OVU1FUklDLCAnTlVNRVJJQycsIEludDMyQXJyYXkuZnJvbShbMTAsIDEyLCAxNF0pLCAweDAxKTtcbiAgICBNb2RlJDEuQUxQSEFOVU1FUklDID0gbmV3IE1vZGUkMShNb2RlVmFsdWVzLkFMUEhBTlVNRVJJQywgJ0FMUEhBTlVNRVJJQycsIEludDMyQXJyYXkuZnJvbShbOSwgMTEsIDEzXSksIDB4MDIpO1xuICAgIE1vZGUkMS5TVFJVQ1RVUkVEX0FQUEVORCA9IG5ldyBNb2RlJDEoTW9kZVZhbHVlcy5TVFJVQ1RVUkVEX0FQUEVORCwgJ1NUUlVDVFVSRURfQVBQRU5EJywgSW50MzJBcnJheS5mcm9tKFswLCAwLCAwXSksIDB4MDMpOyAvLyBOb3Qgc3VwcG9ydGVkXG4gICAgTW9kZSQxLkJZVEUgPSBuZXcgTW9kZSQxKE1vZGVWYWx1ZXMuQllURSwgJ0JZVEUnLCBJbnQzMkFycmF5LmZyb20oWzgsIDE2LCAxNl0pLCAweDA0KTtcbiAgICBNb2RlJDEuRUNJID0gbmV3IE1vZGUkMShNb2RlVmFsdWVzLkVDSSwgJ0VDSScsIEludDMyQXJyYXkuZnJvbShbMCwgMCwgMF0pLCAweDA3KTsgLy8gY2hhcmFjdGVyIGNvdW50cyBkb24ndCBhcHBseVxuICAgIE1vZGUkMS5LQU5KSSA9IG5ldyBNb2RlJDEoTW9kZVZhbHVlcy5LQU5KSSwgJ0tBTkpJJywgSW50MzJBcnJheS5mcm9tKFs4LCAxMCwgMTJdKSwgMHgwOCk7XG4gICAgTW9kZSQxLkZOQzFfRklSU1RfUE9TSVRJT04gPSBuZXcgTW9kZSQxKE1vZGVWYWx1ZXMuRk5DMV9GSVJTVF9QT1NJVElPTiwgJ0ZOQzFfRklSU1RfUE9TSVRJT04nLCBJbnQzMkFycmF5LmZyb20oWzAsIDAsIDBdKSwgMHgwNSk7XG4gICAgTW9kZSQxLkZOQzFfU0VDT05EX1BPU0lUSU9OID0gbmV3IE1vZGUkMShNb2RlVmFsdWVzLkZOQzFfU0VDT05EX1BPU0lUSU9OLCAnRk5DMV9TRUNPTkRfUE9TSVRJT04nLCBJbnQzMkFycmF5LmZyb20oWzAsIDAsIDBdKSwgMHgwOSk7XG4gICAgLyoqIFNlZSBHQlQgMTgyODQtMjAwMDsgXCJIYW56aVwiIGlzIGEgdHJhbnNsaXRlcmF0aW9uIG9mIHRoaXMgbW9kZSBuYW1lLiAqL1xuICAgIE1vZGUkMS5IQU5aSSA9IG5ldyBNb2RlJDEoTW9kZVZhbHVlcy5IQU5aSSwgJ0hBTlpJJywgSW50MzJBcnJheS5mcm9tKFs4LCAxMCwgMTJdKSwgMHgwRCk7XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qaW1wb3J0IGphdmEuaW8uVW5zdXBwb3J0ZWRFbmNvZGluZ0V4Y2VwdGlvbjsqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7Ki9cbiAgICAvKmltcG9ydCBqYXZhLnV0aWwuQ29sbGVjdGlvbjsqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5MaXN0OyovXG4gICAgLyppbXBvcnQgamF2YS51dGlsLk1hcDsqL1xuICAgIC8qKlxuICAgICAqIDxwPlFSIENvZGVzIGNhbiBlbmNvZGUgdGV4dCBhcyBiaXRzIGluIG9uZSBvZiBzZXZlcmFsIG1vZGVzLCBhbmQgY2FuIHVzZSBtdWx0aXBsZSBtb2Rlc1xuICAgICAqIGluIG9uZSBRUiBDb2RlLiBUaGlzIGNsYXNzIGRlY29kZXMgdGhlIGJpdHMgYmFjayBpbnRvIHRleHQuPC9wPlxuICAgICAqXG4gICAgICogPHA+U2VlIElTTyAxODAwNDoyMDA2LCA2LjQuMyAtIDYuNC43PC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDEge1xuICAgICAgICBzdGF0aWMgZGVjb2RlKGJ5dGVzLCB2ZXJzaW9uLCBlY0xldmVsLCBoaW50cykge1xuICAgICAgICAgICAgY29uc3QgYml0cyA9IG5ldyBCaXRTb3VyY2UoYnl0ZXMpO1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICBjb25zdCBieXRlU2VnbWVudHMgPSBuZXcgQXJyYXkoKTsgLy8gMVxuICAgICAgICAgICAgLy8gVFlQRVNDUklQVFBPUlQ6IEkgZG8gbm90IHVzZSBjb25zdHJ1Y3RvciB3aXRoIHNpemUgMSBhcyBpbiBvcmlnaW5hbCBKYXZhIG1lYW5zIGNhcGFjaXR5IGFuZCB0aGUgYXJyYXkgbGVuZ3RoIGlzIGNoZWNrZWQgYmVsb3dcbiAgICAgICAgICAgIGxldCBzeW1ib2xTZXF1ZW5jZSA9IC0xO1xuICAgICAgICAgICAgbGV0IHBhcml0eURhdGEgPSAtMTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbGV0IGN1cnJlbnRDaGFyYWN0ZXJTZXRFQ0kgPSBudWxsO1xuICAgICAgICAgICAgICAgIGxldCBmYzFJbkVmZmVjdCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGxldCBtb2RlO1xuICAgICAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gV2hpbGUgc3RpbGwgYW5vdGhlciBzZWdtZW50IHRvIHJlYWQuLi5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGJpdHMuYXZhaWxhYmxlKCkgPCA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBPSywgYXNzdW1lIHdlJ3JlIGRvbmUuIFJlYWxseSwgYSBURVJNSU5BVE9SIG1vZGUgc2hvdWxkIGhhdmUgYmVlbiByZWNvcmRlZCBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICBtb2RlID0gTW9kZSQxLlRFUk1JTkFUT1I7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtb2RlQml0cyA9IGJpdHMucmVhZEJpdHMoNCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBtb2RlID0gTW9kZSQxLmZvckJpdHMobW9kZUJpdHMpOyAvLyBtb2RlIGlzIGVuY29kZWQgYnkgNCBiaXRzXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChtb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIE1vZGUkMS5URVJNSU5BVE9SOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBNb2RlJDEuRk5DMV9GSVJTVF9QT1NJVElPTjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgTW9kZSQxLkZOQzFfU0VDT05EX1BPU0lUSU9OOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGRvIGxpdHRsZSB3aXRoIEZOQzEgZXhjZXB0IGFsdGVyIHRoZSBwYXJzZWQgcmVzdWx0IGEgYml0IGFjY29yZGluZyB0byB0aGUgc3BlY1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZjMUluRWZmZWN0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgTW9kZSQxLlNUUlVDVFVSRURfQVBQRU5EOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiaXRzLmF2YWlsYWJsZSgpIDwgMTYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBzZXF1ZW5jZSBudW1iZXIgYW5kIHBhcml0eSBpcyBhZGRlZCBsYXRlciB0byB0aGUgcmVzdWx0IG1ldGFkYXRhXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVhZCBuZXh0IDggYml0cyAoc3ltYm9sIHNlcXVlbmNlICMpIGFuZCA4IGJpdHMgKGRhdGE6IHBhcml0eSksIHRoZW4gY29udGludWVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzeW1ib2xTZXF1ZW5jZSA9IGJpdHMucmVhZEJpdHMoOCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyaXR5RGF0YSA9IGJpdHMucmVhZEJpdHMoOCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIE1vZGUkMS5FQ0k6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ291bnQgZG9lc24ndCBhcHBseSB0byBFQ0lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS5wYXJzZUVDSVZhbHVlKGJpdHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRDaGFyYWN0ZXJTZXRFQ0kgPSBDaGFyYWN0ZXJTZXRFQ0kuZ2V0Q2hhcmFjdGVyU2V0RUNJQnlWYWx1ZSh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRDaGFyYWN0ZXJTZXRFQ0kgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgTW9kZSQxLkhBTlpJOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpcnN0IGhhbmRsZSBIYW56aSBtb2RlIHdoaWNoIGRvZXMgbm90IHN0YXJ0IHdpdGggY2hhcmFjdGVyIGNvdW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hpbmVzZSBtb2RlIGNvbnRhaW5zIGEgc3ViIHNldCBpbmRpY2F0b3IgcmlnaHQgYWZ0ZXIgbW9kZSBpbmRpY2F0b3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdWJzZXQgPSBiaXRzLnJlYWRCaXRzKDQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvdW50SGFuemkgPSBiaXRzLnJlYWRCaXRzKG1vZGUuZ2V0Q2hhcmFjdGVyQ291bnRCaXRzKHZlcnNpb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3Vic2V0ID09PSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDEuR0IyMzEyX1NVQlNFVCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDEuZGVjb2RlSGFuemlTZWdtZW50KGJpdHMsIHJlc3VsdCwgY291bnRIYW56aSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBcIk5vcm1hbFwiIFFSIGNvZGUgbW9kZXM6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSG93IG1hbnkgY2hhcmFjdGVycyB3aWxsIGZvbGxvdywgZW5jb2RlZCBpbiB0aGlzIG1vZGU/XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY291bnQgPSBiaXRzLnJlYWRCaXRzKG1vZGUuZ2V0Q2hhcmFjdGVyQ291bnRCaXRzKHZlcnNpb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKG1vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBNb2RlJDEuTlVNRVJJQzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS5kZWNvZGVOdW1lcmljU2VnbWVudChiaXRzLCByZXN1bHQsIGNvdW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIE1vZGUkMS5BTFBIQU5VTUVSSUM6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDEuZGVjb2RlQWxwaGFudW1lcmljU2VnbWVudChiaXRzLCByZXN1bHQsIGNvdW50LCBmYzFJbkVmZmVjdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBNb2RlJDEuQllURTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS5kZWNvZGVCeXRlU2VnbWVudChiaXRzLCByZXN1bHQsIGNvdW50LCBjdXJyZW50Q2hhcmFjdGVyU2V0RUNJLCBieXRlU2VnbWVudHMsIGhpbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIE1vZGUkMS5LQU5KSTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS5kZWNvZGVLYW5qaVNlZ21lbnQoYml0cywgcmVzdWx0LCBjb3VudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IHdoaWxlIChtb2RlICE9PSBNb2RlJDEuVEVSTUlOQVRPUik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoaWFlIC8qOiBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24qLykge1xuICAgICAgICAgICAgICAgIC8vIGZyb20gcmVhZEJpdHMoKSBjYWxsc1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgRGVjb2RlclJlc3VsdChieXRlcywgcmVzdWx0LnRvU3RyaW5nKCksIGJ5dGVTZWdtZW50cy5sZW5ndGggPT09IDAgPyBudWxsIDogYnl0ZVNlZ21lbnRzLCBlY0xldmVsID09PSBudWxsID8gbnVsbCA6IGVjTGV2ZWwudG9TdHJpbmcoKSwgc3ltYm9sU2VxdWVuY2UsIHBhcml0eURhdGEpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZWUgc3BlY2lmaWNhdGlvbiBHQlQgMTgyODQtMjAwMFxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGRlY29kZUhhbnppU2VnbWVudChiaXRzLCByZXN1bHQsIGNvdW50IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIC8vIERvbid0IGNyYXNoIHRyeWluZyB0byByZWFkIG1vcmUgYml0cyB0aGFuIHdlIGhhdmUgYXZhaWxhYmxlLlxuICAgICAgICAgICAgaWYgKGNvdW50ICogMTMgPiBiaXRzLmF2YWlsYWJsZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRWFjaCBjaGFyYWN0ZXIgd2lsbCByZXF1aXJlIDIgYnl0ZXMuIFJlYWQgdGhlIGNoYXJhY3RlcnMgYXMgMi1ieXRlIHBhaXJzXG4gICAgICAgICAgICAvLyBhbmQgZGVjb2RlIGFzIEdCMjMxMiBhZnRlcndhcmRzXG4gICAgICAgICAgICBjb25zdCBidWZmZXIgPSBuZXcgVWludDhBcnJheSgyICogY291bnQpO1xuICAgICAgICAgICAgbGV0IG9mZnNldCA9IDA7XG4gICAgICAgICAgICB3aGlsZSAoY291bnQgPiAwKSB7XG4gICAgICAgICAgICAgICAgLy8gRWFjaCAxMyBiaXRzIGVuY29kZXMgYSAyLWJ5dGUgY2hhcmFjdGVyXG4gICAgICAgICAgICAgICAgY29uc3QgdHdvQnl0ZXMgPSBiaXRzLnJlYWRCaXRzKDEzKTtcbiAgICAgICAgICAgICAgICBsZXQgYXNzZW1ibGVkVHdvQnl0ZXMgPSAoKCh0d29CeXRlcyAvIDB4MDYwKSA8PCA4KSAmIDB4RkZGRkZGRkYpIHwgKHR3b0J5dGVzICUgMHgwNjApO1xuICAgICAgICAgICAgICAgIGlmIChhc3NlbWJsZWRUd29CeXRlcyA8IDB4MDAzQkYpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSW4gdGhlIDB4QTFBMSB0byAweEFBRkUgcmFuZ2VcbiAgICAgICAgICAgICAgICAgICAgYXNzZW1ibGVkVHdvQnl0ZXMgKz0gMHgwQTFBMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEluIHRoZSAweEIwQTEgdG8gMHhGQUZFIHJhbmdlXG4gICAgICAgICAgICAgICAgICAgIGFzc2VtYmxlZFR3b0J5dGVzICs9IDB4MEE2QTE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJ1ZmZlcltvZmZzZXRdID0gLyooYnl0ZSkgKi8gKChhc3NlbWJsZWRUd29CeXRlcyA+PiA4KSAmIDB4RkYpO1xuICAgICAgICAgICAgICAgIGJ1ZmZlcltvZmZzZXQgKyAxXSA9IC8qKGJ5dGUpICovIChhc3NlbWJsZWRUd29CeXRlcyAmIDB4RkYpO1xuICAgICAgICAgICAgICAgIG9mZnNldCArPSAyO1xuICAgICAgICAgICAgICAgIGNvdW50LS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoU3RyaW5nRW5jb2RpbmcuZGVjb2RlKGJ1ZmZlciwgU3RyaW5nVXRpbHMuR0IyMzEyKSk7XG4gICAgICAgICAgICAgICAgLy8gVFlQRVNDUklQVFBPUlQ6IFRPRE86IGltcGxlbWVudCBHQjIzMTIgZGVjb2RlLiBTdHJpbmdWaWV3IGZyb20gTUROIGNvdWxkIGJlIGEgc3RhcnRpbmcgcG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChpZ25vcmVkIC8qOiBVbnN1cHBvcnRlZEVuY29kaW5nRXhjZXB0aW9uKi8pIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKGlnbm9yZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBkZWNvZGVLYW5qaVNlZ21lbnQoYml0cywgcmVzdWx0LCBjb3VudCAvKmludCovKSB7XG4gICAgICAgICAgICAvLyBEb24ndCBjcmFzaCB0cnlpbmcgdG8gcmVhZCBtb3JlIGJpdHMgdGhhbiB3ZSBoYXZlIGF2YWlsYWJsZS5cbiAgICAgICAgICAgIGlmIChjb3VudCAqIDEzID4gYml0cy5hdmFpbGFibGUoKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEVhY2ggY2hhcmFjdGVyIHdpbGwgcmVxdWlyZSAyIGJ5dGVzLiBSZWFkIHRoZSBjaGFyYWN0ZXJzIGFzIDItYnl0ZSBwYWlyc1xuICAgICAgICAgICAgLy8gYW5kIGRlY29kZSBhcyBTaGlmdF9KSVMgYWZ0ZXJ3YXJkc1xuICAgICAgICAgICAgY29uc3QgYnVmZmVyID0gbmV3IFVpbnQ4QXJyYXkoMiAqIGNvdW50KTtcbiAgICAgICAgICAgIGxldCBvZmZzZXQgPSAwO1xuICAgICAgICAgICAgd2hpbGUgKGNvdW50ID4gMCkge1xuICAgICAgICAgICAgICAgIC8vIEVhY2ggMTMgYml0cyBlbmNvZGVzIGEgMi1ieXRlIGNoYXJhY3RlclxuICAgICAgICAgICAgICAgIGNvbnN0IHR3b0J5dGVzID0gYml0cy5yZWFkQml0cygxMyk7XG4gICAgICAgICAgICAgICAgbGV0IGFzc2VtYmxlZFR3b0J5dGVzID0gKCgodHdvQnl0ZXMgLyAweDBDMCkgPDwgOCkgJiAweEZGRkZGRkZGKSB8ICh0d29CeXRlcyAlIDB4MEMwKTtcbiAgICAgICAgICAgICAgICBpZiAoYXNzZW1ibGVkVHdvQnl0ZXMgPCAweDAxRjAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEluIHRoZSAweDgxNDAgdG8gMHg5RkZDIHJhbmdlXG4gICAgICAgICAgICAgICAgICAgIGFzc2VtYmxlZFR3b0J5dGVzICs9IDB4MDgxNDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBJbiB0aGUgMHhFMDQwIHRvIDB4RUJCRiByYW5nZVxuICAgICAgICAgICAgICAgICAgICBhc3NlbWJsZWRUd29CeXRlcyArPSAweDBDMTQwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBidWZmZXJbb2Zmc2V0XSA9IC8qKGJ5dGUpICovIChhc3NlbWJsZWRUd29CeXRlcyA+PiA4KTtcbiAgICAgICAgICAgICAgICBidWZmZXJbb2Zmc2V0ICsgMV0gPSAvKihieXRlKSAqLyBhc3NlbWJsZWRUd29CeXRlcztcbiAgICAgICAgICAgICAgICBvZmZzZXQgKz0gMjtcbiAgICAgICAgICAgICAgICBjb3VudC0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gU2hpZnRfSklTIG1heSBub3QgYmUgc3VwcG9ydGVkIGluIHNvbWUgZW52aXJvbm1lbnRzOlxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKFN0cmluZ0VuY29kaW5nLmRlY29kZShidWZmZXIsIFN0cmluZ1V0aWxzLlNISUZUX0pJUykpO1xuICAgICAgICAgICAgICAgIC8vIFRZUEVTQ1JJUFRQT1JUOiBUT0RPOiBpbXBsZW1lbnQgU0hJRlRfSklTIGRlY29kZS4gU3RyaW5nVmlldyBmcm9tIE1ETiBjb3VsZCBiZSBhIHN0YXJ0aW5nIHBvaW50XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoaWdub3JlZCAvKjogVW5zdXBwb3J0ZWRFbmNvZGluZ0V4Y2VwdGlvbiovKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbihpZ25vcmVkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZGVjb2RlQnl0ZVNlZ21lbnQoYml0cywgcmVzdWx0LCBjb3VudCAvKmludCovLCBjdXJyZW50Q2hhcmFjdGVyU2V0RUNJLCBieXRlU2VnbWVudHMsIGhpbnRzKSB7XG4gICAgICAgICAgICAvLyBEb24ndCBjcmFzaCB0cnlpbmcgdG8gcmVhZCBtb3JlIGJpdHMgdGhhbiB3ZSBoYXZlIGF2YWlsYWJsZS5cbiAgICAgICAgICAgIGlmICg4ICogY291bnQgPiBiaXRzLmF2YWlsYWJsZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmVhZEJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoY291bnQpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcmVhZEJ5dGVzW2ldID0gLyooYnl0ZSkgKi8gYml0cy5yZWFkQml0cyg4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBlbmNvZGluZztcbiAgICAgICAgICAgIGlmIChjdXJyZW50Q2hhcmFjdGVyU2V0RUNJID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlIHNwZWMgaXNuJ3QgY2xlYXIgb24gdGhpcyBtb2RlOyBzZWVcbiAgICAgICAgICAgICAgICAvLyBzZWN0aW9uIDYuNC41OiB0IGRvZXMgbm90IHNheSB3aGljaCBlbmNvZGluZyB0byBhc3N1bWluZ1xuICAgICAgICAgICAgICAgIC8vIHVwb24gZGVjb2RpbmcuIEkgaGF2ZSBzZWVuIElTTy04ODU5LTEgdXNlZCBhcyB3ZWxsIGFzXG4gICAgICAgICAgICAgICAgLy8gU2hpZnRfSklTIC0tIHdpdGhvdXQgYW55dGhpbmcgbGlrZSBhbiBFQ0kgZGVzaWduYXRvciB0b1xuICAgICAgICAgICAgICAgIC8vIGdpdmUgYSBoaW50LlxuICAgICAgICAgICAgICAgIGVuY29kaW5nID0gU3RyaW5nVXRpbHMuZ3Vlc3NFbmNvZGluZyhyZWFkQnl0ZXMsIGhpbnRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGVuY29kaW5nID0gY3VycmVudENoYXJhY3RlclNldEVDSS5nZXROYW1lKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoU3RyaW5nRW5jb2RpbmcuZGVjb2RlKHJlYWRCeXRlcywgZW5jb2RpbmcpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChpZ25vcmVkIC8qOiBVbnN1cHBvcnRlZEVuY29kaW5nRXhjZXB0aW9uKi8pIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKGlnbm9yZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnl0ZVNlZ21lbnRzLnB1c2gocmVhZEJ5dGVzKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgdG9BbHBoYU51bWVyaWNDaGFyKHZhbHVlIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZSA+PSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDEuQUxQSEFOVU1FUklDX0NIQVJTLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDEuQUxQSEFOVU1FUklDX0NIQVJTW3ZhbHVlXTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZGVjb2RlQWxwaGFudW1lcmljU2VnbWVudChiaXRzLCByZXN1bHQsIGNvdW50IC8qaW50Ki8sIGZjMUluRWZmZWN0KSB7XG4gICAgICAgICAgICAvLyBSZWFkIHR3byBjaGFyYWN0ZXJzIGF0IGEgdGltZVxuICAgICAgICAgICAgY29uc3Qgc3RhcnQgPSByZXN1bHQubGVuZ3RoKCk7XG4gICAgICAgICAgICB3aGlsZSAoY291bnQgPiAxKSB7XG4gICAgICAgICAgICAgICAgaWYgKGJpdHMuYXZhaWxhYmxlKCkgPCAxMSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IG5leHRUd29DaGFyc0JpdHMgPSBiaXRzLnJlYWRCaXRzKDExKTtcbiAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS50b0FscGhhTnVtZXJpY0NoYXIoTWF0aC5mbG9vcihuZXh0VHdvQ2hhcnNCaXRzIC8gNDUpKSk7XG4gICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDEudG9BbHBoYU51bWVyaWNDaGFyKG5leHRUd29DaGFyc0JpdHMgJSA0NSkpO1xuICAgICAgICAgICAgICAgIGNvdW50IC09IDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY291bnQgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAvLyBzcGVjaWFsIGNhc2U6IG9uZSBjaGFyYWN0ZXIgbGVmdFxuICAgICAgICAgICAgICAgIGlmIChiaXRzLmF2YWlsYWJsZSgpIDwgNikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQxLnRvQWxwaGFOdW1lcmljQ2hhcihiaXRzLnJlYWRCaXRzKDYpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBTZWUgc2VjdGlvbiA2LjQuOC4xLCA2LjQuOC4yXG4gICAgICAgICAgICBpZiAoZmMxSW5FZmZlY3QpIHtcbiAgICAgICAgICAgICAgICAvLyBXZSBuZWVkIHRvIG1hc3NhZ2UgdGhlIHJlc3VsdCBhIGJpdCBpZiBpbiBhbiBGTkMxIG1vZGU6XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDwgcmVzdWx0Lmxlbmd0aCgpOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdC5jaGFyQXQoaSkgPT09ICclJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGkgPCByZXN1bHQubGVuZ3RoKCkgLSAxICYmIHJlc3VsdC5jaGFyQXQoaSArIDEpID09PSAnJScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAlJSBpcyByZW5kZXJlZCBhcyAlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmRlbGV0ZUNoYXJBdChpICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbiBhbHBoYSBtb2RlLCAlIHNob3VsZCBiZSBjb252ZXJ0ZWQgdG8gRk5DMSBzZXBhcmF0b3IgMHgxRFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5zZXRDaGFyQXQoaSwgU3RyaW5nLmZyb21DaGFyQ29kZSgweDFEKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGRlY29kZU51bWVyaWNTZWdtZW50KGJpdHMsIHJlc3VsdCwgY291bnQgLyppbnQqLykge1xuICAgICAgICAgICAgLy8gUmVhZCB0aHJlZSBkaWdpdHMgYXQgYSB0aW1lXG4gICAgICAgICAgICB3aGlsZSAoY291bnQgPj0gMykge1xuICAgICAgICAgICAgICAgIC8vIEVhY2ggMTAgYml0cyBlbmNvZGVzIHRocmVlIGRpZ2l0c1xuICAgICAgICAgICAgICAgIGlmIChiaXRzLmF2YWlsYWJsZSgpIDwgMTApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCB0aHJlZURpZ2l0c0JpdHMgPSBiaXRzLnJlYWRCaXRzKDEwKTtcbiAgICAgICAgICAgICAgICBpZiAodGhyZWVEaWdpdHNCaXRzID49IDEwMDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS50b0FscGhhTnVtZXJpY0NoYXIoTWF0aC5mbG9vcih0aHJlZURpZ2l0c0JpdHMgLyAxMDApKSk7XG4gICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDEudG9BbHBoYU51bWVyaWNDaGFyKE1hdGguZmxvb3IodGhyZWVEaWdpdHNCaXRzIC8gMTApICUgMTApKTtcbiAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS50b0FscGhhTnVtZXJpY0NoYXIodGhyZWVEaWdpdHNCaXRzICUgMTApKTtcbiAgICAgICAgICAgICAgICBjb3VudCAtPSAzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvdW50ID09PSAyKSB7XG4gICAgICAgICAgICAgICAgLy8gVHdvIGRpZ2l0cyBsZWZ0IG92ZXIgdG8gcmVhZCwgZW5jb2RlZCBpbiA3IGJpdHNcbiAgICAgICAgICAgICAgICBpZiAoYml0cy5hdmFpbGFibGUoKSA8IDcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCB0d29EaWdpdHNCaXRzID0gYml0cy5yZWFkQml0cyg3KTtcbiAgICAgICAgICAgICAgICBpZiAodHdvRGlnaXRzQml0cyA+PSAxMDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS50b0FscGhhTnVtZXJpY0NoYXIoTWF0aC5mbG9vcih0d29EaWdpdHNCaXRzIC8gMTApKSk7XG4gICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDEudG9BbHBoYU51bWVyaWNDaGFyKHR3b0RpZ2l0c0JpdHMgJSAxMCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY291bnQgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAvLyBPbmUgZGlnaXQgbGVmdCBvdmVyIHRvIHJlYWRcbiAgICAgICAgICAgICAgICBpZiAoYml0cy5hdmFpbGFibGUoKSA8IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBkaWdpdEJpdHMgPSBiaXRzLnJlYWRCaXRzKDQpO1xuICAgICAgICAgICAgICAgIGlmIChkaWdpdEJpdHMgPj0gMTApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS50b0FscGhhTnVtZXJpY0NoYXIoZGlnaXRCaXRzKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHBhcnNlRUNJVmFsdWUoYml0cykge1xuICAgICAgICAgICAgY29uc3QgZmlyc3RCeXRlID0gYml0cy5yZWFkQml0cyg4KTtcbiAgICAgICAgICAgIGlmICgoZmlyc3RCeXRlICYgMHg4MCkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyBqdXN0IG9uZSBieXRlXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZpcnN0Qnl0ZSAmIDB4N0Y7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoKGZpcnN0Qnl0ZSAmIDB4QzApID09PSAweDgwKSB7XG4gICAgICAgICAgICAgICAgLy8gdHdvIGJ5dGVzXG4gICAgICAgICAgICAgICAgY29uc3Qgc2Vjb25kQnl0ZSA9IGJpdHMucmVhZEJpdHMoOCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuICgoKGZpcnN0Qnl0ZSAmIDB4M0YpIDw8IDgpICYgMHhGRkZGRkZGRikgfCBzZWNvbmRCeXRlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKChmaXJzdEJ5dGUgJiAweEUwKSA9PT0gMHhDMCkge1xuICAgICAgICAgICAgICAgIC8vIHRocmVlIGJ5dGVzXG4gICAgICAgICAgICAgICAgY29uc3Qgc2Vjb25kVGhpcmRCeXRlcyA9IGJpdHMucmVhZEJpdHMoMTYpO1xuICAgICAgICAgICAgICAgIHJldHVybiAoKChmaXJzdEJ5dGUgJiAweDFGKSA8PCAxNikgJiAweEZGRkZGRkZGKSB8IHNlY29uZFRoaXJkQnl0ZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXhjZXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogU2VlIElTTyAxODAwNDoyMDA2LCA2LjQuNCBUYWJsZSA1XG4gICAgICovXG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQxLkFMUEhBTlVNRVJJQ19DSEFSUyA9ICcwMTIzNDU2Nzg5QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVogJCUqKy0uLzonO1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMS5HQjIzMTJfU1VCU0VUID0gMTtcbiAgICAvLyBmdW5jdGlvbiBVaW50OEFycmF5VG9TdHJpbmcoYTogVWludDhBcnJheSk6IHN0cmluZyB7XG4gICAgLy8gICAgIGNvbnN0IENIVU5LX1NaID0gMHg4MDAwO1xuICAgIC8vICAgICBjb25zdCBjID0gbmV3IFN0cmluZ0J1aWxkZXIoKTtcbiAgICAvLyAgICAgZm9yIChsZXQgaSA9IDAsIGxlbmd0aCA9IGEubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpICs9IENIVU5LX1NaKSB7XG4gICAgLy8gICAgICAgICBjLmFwcGVuZChTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIGEuc3ViYXJyYXkoaSwgaSArIENIVU5LX1NaKSkpO1xuICAgIC8vICAgICB9XG4gICAgLy8gICAgIHJldHVybiBjLnRvU3RyaW5nKCk7XG4gICAgLy8gfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAxMyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiBNZXRhLWRhdGEgY29udGFpbmVyIGZvciBRUiBDb2RlIGRlY29kaW5nLiBJbnN0YW5jZXMgb2YgdGhpcyBjbGFzcyBtYXkgYmUgdXNlZCB0byBjb252ZXkgaW5mb3JtYXRpb24gYmFjayB0byB0aGVcbiAgICAgKiBkZWNvZGluZyBjYWxsZXIuIENhbGxlcnMgYXJlIGV4cGVjdGVkIHRvIHByb2Nlc3MgdGhpcy5cbiAgICAgKlxuICAgICAqIEBzZWUgY29tLmdvb2dsZS56eGluZy5jb21tb24uRGVjb2RlclJlc3VsdCNnZXRPdGhlcigpXG4gICAgICovXG4gICAgY2xhc3MgUVJDb2RlRGVjb2Rlck1ldGFEYXRhIHtcbiAgICAgICAgY29uc3RydWN0b3IobWlycm9yZWQpIHtcbiAgICAgICAgICAgIHRoaXMubWlycm9yZWQgPSBtaXJyb3JlZDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB0cnVlIGlmIHRoZSBRUiBDb2RlIHdhcyBtaXJyb3JlZC5cbiAgICAgICAgICovXG4gICAgICAgIGlzTWlycm9yZWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5taXJyb3JlZDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQXBwbHkgdGhlIHJlc3VsdCBwb2ludHMnIG9yZGVyIGNvcnJlY3Rpb24gZHVlIHRvIG1pcnJvcmluZy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHBvaW50cyBBcnJheSBvZiBwb2ludHMgdG8gYXBwbHkgbWlycm9yIGNvcnJlY3Rpb24gdG8uXG4gICAgICAgICAqL1xuICAgICAgICBhcHBseU1pcnJvcmVkQ29ycmVjdGlvbihwb2ludHMpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5taXJyb3JlZCB8fCBwb2ludHMgPT09IG51bGwgfHwgcG9pbnRzLmxlbmd0aCA8IDMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBib3R0b21MZWZ0ID0gcG9pbnRzWzBdO1xuICAgICAgICAgICAgcG9pbnRzWzBdID0gcG9pbnRzWzJdO1xuICAgICAgICAgICAgcG9pbnRzWzJdID0gYm90dG9tTGVmdDtcbiAgICAgICAgICAgIC8vIE5vIG5lZWQgdG8gJ2ZpeCcgdG9wLWxlZnQgYW5kIGFsaWdubWVudCBwYXR0ZXJuLlxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKmltcG9ydCBqYXZhLnV0aWwuTWFwOyovXG4gICAgLyoqXG4gICAgICogPHA+VGhlIG1haW4gY2xhc3Mgd2hpY2ggaW1wbGVtZW50cyBRUiBDb2RlIGRlY29kaW5nIC0tIGFzIG9wcG9zZWQgdG8gbG9jYXRpbmcgYW5kIGV4dHJhY3RpbmdcbiAgICAgKiB0aGUgUVIgQ29kZSBmcm9tIGFuIGltYWdlLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgRGVjb2RlciQyIHtcbiAgICAgICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgICAgICB0aGlzLnJzRGVjb2RlciA9IG5ldyBSZWVkU29sb21vbkRlY29kZXIoR2VuZXJpY0dGLlFSX0NPREVfRklFTERfMjU2KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBwdWJsaWMgZGVjb2RlKGltYWdlOiBib29sZWFuW11bXSk6IERlY29kZXJSZXN1bHQgLyp0aHJvd3MgQ2hlY2tzdW1FeGNlcHRpb24sIEZvcm1hdEV4Y2VwdGlvbiovIHtcbiAgICAgICAgLy8gICByZXR1cm4gZGVjb2RlKGltYWdlLCBudWxsKVxuICAgICAgICAvLyB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5Db252ZW5pZW5jZSBtZXRob2QgdGhhdCBjYW4gZGVjb2RlIGEgUVIgQ29kZSByZXByZXNlbnRlZCBhcyBhIDJEIGFycmF5IG9mIGJvb2xlYW5zLlxuICAgICAgICAgKiBcInRydWVcIiBpcyB0YWtlbiB0byBtZWFuIGEgYmxhY2sgbW9kdWxlLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGltYWdlIGJvb2xlYW5zIHJlcHJlc2VudGluZyB3aGl0ZS9ibGFjayBRUiBDb2RlIG1vZHVsZXNcbiAgICAgICAgICogQHBhcmFtIGhpbnRzIGRlY29kaW5nIGhpbnRzIHRoYXQgc2hvdWxkIGJlIHVzZWQgdG8gaW5mbHVlbmNlIGRlY29kaW5nXG4gICAgICAgICAqIEByZXR1cm4gdGV4dCBhbmQgYnl0ZXMgZW5jb2RlZCB3aXRoaW4gdGhlIFFSIENvZGVcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb24gaWYgdGhlIFFSIENvZGUgY2Fubm90IGJlIGRlY29kZWRcbiAgICAgICAgICogQHRocm93cyBDaGVja3N1bUV4Y2VwdGlvbiBpZiBlcnJvciBjb3JyZWN0aW9uIGZhaWxzXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGVCb29sZWFuQXJyYXkoaW1hZ2UsIGhpbnRzKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGVCaXRNYXRyaXgoQml0TWF0cml4LnBhcnNlRnJvbUJvb2xlYW5BcnJheShpbWFnZSksIGhpbnRzKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBwdWJsaWMgZGVjb2RlQml0TWF0cml4KGJpdHM6IEJpdE1hdHJpeCk6IERlY29kZXJSZXN1bHQgLyp0aHJvd3MgQ2hlY2tzdW1FeGNlcHRpb24sIEZvcm1hdEV4Y2VwdGlvbiovIHtcbiAgICAgICAgLy8gICByZXR1cm4gZGVjb2RlKGJpdHMsIG51bGwpXG4gICAgICAgIC8vIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkRlY29kZXMgYSBRUiBDb2RlIHJlcHJlc2VudGVkIGFzIGEge0BsaW5rIEJpdE1hdHJpeH0uIEEgMSBvciBcInRydWVcIiBpcyB0YWtlbiB0byBtZWFuIGEgYmxhY2sgbW9kdWxlLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGJpdHMgYm9vbGVhbnMgcmVwcmVzZW50aW5nIHdoaXRlL2JsYWNrIFFSIENvZGUgbW9kdWxlc1xuICAgICAgICAgKiBAcGFyYW0gaGludHMgZGVjb2RpbmcgaGludHMgdGhhdCBzaG91bGQgYmUgdXNlZCB0byBpbmZsdWVuY2UgZGVjb2RpbmdcbiAgICAgICAgICogQHJldHVybiB0ZXh0IGFuZCBieXRlcyBlbmNvZGVkIHdpdGhpbiB0aGUgUVIgQ29kZVxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvbiBpZiB0aGUgUVIgQ29kZSBjYW5ub3QgYmUgZGVjb2RlZFxuICAgICAgICAgKiBAdGhyb3dzIENoZWNrc3VtRXhjZXB0aW9uIGlmIGVycm9yIGNvcnJlY3Rpb24gZmFpbHNcbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZUJpdE1hdHJpeChiaXRzLCBoaW50cykge1xuICAgICAgICAgICAgLy8gQ29uc3RydWN0IGEgcGFyc2VyIGFuZCByZWFkIHZlcnNpb24sIGVycm9yLWNvcnJlY3Rpb24gbGV2ZWxcbiAgICAgICAgICAgIGNvbnN0IHBhcnNlciA9IG5ldyBCaXRNYXRyaXhQYXJzZXIkMShiaXRzKTtcbiAgICAgICAgICAgIGxldCBleCA9IG51bGw7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZUJpdE1hdHJpeFBhcnNlcihwYXJzZXIsIGhpbnRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlIC8qOiBGb3JtYXRFeGNlcHRpb24sIENoZWNrc3VtRXhjZXB0aW9uKi8pIHtcbiAgICAgICAgICAgICAgICBleCA9IGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIC8vIFJldmVydCB0aGUgYml0IG1hdHJpeFxuICAgICAgICAgICAgICAgIHBhcnNlci5yZW1hc2soKTtcbiAgICAgICAgICAgICAgICAvLyBXaWxsIGJlIGF0dGVtcHRpbmcgYSBtaXJyb3JlZCByZWFkaW5nIG9mIHRoZSB2ZXJzaW9uIGFuZCBmb3JtYXQgaW5mby5cbiAgICAgICAgICAgICAgICBwYXJzZXIuc2V0TWlycm9yKHRydWUpO1xuICAgICAgICAgICAgICAgIC8vIFByZWVtcHRpdmVseSByZWFkIHRoZSB2ZXJzaW9uLlxuICAgICAgICAgICAgICAgIHBhcnNlci5yZWFkVmVyc2lvbigpO1xuICAgICAgICAgICAgICAgIC8vIFByZWVtcHRpdmVseSByZWFkIHRoZSBmb3JtYXQgaW5mb3JtYXRpb24uXG4gICAgICAgICAgICAgICAgcGFyc2VyLnJlYWRGb3JtYXRJbmZvcm1hdGlvbigpO1xuICAgICAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgICAgICogU2luY2Ugd2UncmUgaGVyZSwgdGhpcyBtZWFucyB3ZSBoYXZlIHN1Y2Nlc3NmdWxseSBkZXRlY3RlZCBzb21lIGtpbmRcbiAgICAgICAgICAgICAgICAgKiBvZiB2ZXJzaW9uIGFuZCBmb3JtYXQgaW5mb3JtYXRpb24gd2hlbiBtaXJyb3JlZC4gVGhpcyBpcyBhIGdvb2Qgc2lnbixcbiAgICAgICAgICAgICAgICAgKiB0aGF0IHRoZSBRUiBjb2RlIG1heSBiZSBtaXJyb3JlZCwgYW5kIHdlIHNob3VsZCB0cnkgb25jZSBtb3JlIHdpdGggYVxuICAgICAgICAgICAgICAgICAqIG1pcnJvcmVkIGNvbnRlbnQuXG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgLy8gUHJlcGFyZSBmb3IgYSBtaXJyb3JlZCByZWFkaW5nLlxuICAgICAgICAgICAgICAgIHBhcnNlci5taXJyb3IoKTtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLmRlY29kZUJpdE1hdHJpeFBhcnNlcihwYXJzZXIsIGhpbnRzKTtcbiAgICAgICAgICAgICAgICAvLyBTdWNjZXNzISBOb3RpZnkgdGhlIGNhbGxlciB0aGF0IHRoZSBjb2RlIHdhcyBtaXJyb3JlZC5cbiAgICAgICAgICAgICAgICByZXN1bHQuc2V0T3RoZXIobmV3IFFSQ29kZURlY29kZXJNZXRhRGF0YSh0cnVlKSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlIC8qRm9ybWF0RXhjZXB0aW9uIHwgQ2hlY2tzdW1FeGNlcHRpb24qLykge1xuICAgICAgICAgICAgICAgIC8vIFRocm93IHRoZSBleGNlcHRpb24gZnJvbSB0aGUgb3JpZ2luYWwgcmVhZGluZ1xuICAgICAgICAgICAgICAgIGlmIChleCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBkZWNvZGVCaXRNYXRyaXhQYXJzZXIocGFyc2VyLCBoaW50cykge1xuICAgICAgICAgICAgY29uc3QgdmVyc2lvbiA9IHBhcnNlci5yZWFkVmVyc2lvbigpO1xuICAgICAgICAgICAgY29uc3QgZWNMZXZlbCA9IHBhcnNlci5yZWFkRm9ybWF0SW5mb3JtYXRpb24oKS5nZXRFcnJvckNvcnJlY3Rpb25MZXZlbCgpO1xuICAgICAgICAgICAgLy8gUmVhZCBjb2Rld29yZHNcbiAgICAgICAgICAgIGNvbnN0IGNvZGV3b3JkcyA9IHBhcnNlci5yZWFkQ29kZXdvcmRzKCk7XG4gICAgICAgICAgICAvLyBTZXBhcmF0ZSBpbnRvIGRhdGEgYmxvY2tzXG4gICAgICAgICAgICBjb25zdCBkYXRhQmxvY2tzID0gRGF0YUJsb2NrJDEuZ2V0RGF0YUJsb2Nrcyhjb2Rld29yZHMsIHZlcnNpb24sIGVjTGV2ZWwpO1xuICAgICAgICAgICAgLy8gQ291bnQgdG90YWwgbnVtYmVyIG9mIGRhdGEgYnl0ZXNcbiAgICAgICAgICAgIGxldCB0b3RhbEJ5dGVzID0gMDtcbiAgICAgICAgICAgIGZvciAoY29uc3QgZGF0YUJsb2NrIG9mIGRhdGFCbG9ja3MpIHtcbiAgICAgICAgICAgICAgICB0b3RhbEJ5dGVzICs9IGRhdGFCbG9jay5nZXROdW1EYXRhQ29kZXdvcmRzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXN1bHRCeXRlcyA9IG5ldyBVaW50OEFycmF5KHRvdGFsQnl0ZXMpO1xuICAgICAgICAgICAgbGV0IHJlc3VsdE9mZnNldCA9IDA7XG4gICAgICAgICAgICAvLyBFcnJvci1jb3JyZWN0IGFuZCBjb3B5IGRhdGEgYmxvY2tzIHRvZ2V0aGVyIGludG8gYSBzdHJlYW0gb2YgYnl0ZXNcbiAgICAgICAgICAgIGZvciAoY29uc3QgZGF0YUJsb2NrIG9mIGRhdGFCbG9ja3MpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb2Rld29yZEJ5dGVzID0gZGF0YUJsb2NrLmdldENvZGV3b3JkcygpO1xuICAgICAgICAgICAgICAgIGNvbnN0IG51bURhdGFDb2Rld29yZHMgPSBkYXRhQmxvY2suZ2V0TnVtRGF0YUNvZGV3b3JkcygpO1xuICAgICAgICAgICAgICAgIHRoaXMuY29ycmVjdEVycm9ycyhjb2Rld29yZEJ5dGVzLCBudW1EYXRhQ29kZXdvcmRzKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bURhdGFDb2Rld29yZHM7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRCeXRlc1tyZXN1bHRPZmZzZXQrK10gPSBjb2Rld29yZEJ5dGVzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIERlY29kZSB0aGUgY29udGVudHMgb2YgdGhhdCBzdHJlYW0gb2YgYnl0ZXNcbiAgICAgICAgICAgIHJldHVybiBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDEuZGVjb2RlKHJlc3VsdEJ5dGVzLCB2ZXJzaW9uLCBlY0xldmVsLCBoaW50cyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkdpdmVuIGRhdGEgYW5kIGVycm9yLWNvcnJlY3Rpb24gY29kZXdvcmRzIHJlY2VpdmVkLCBwb3NzaWJseSBjb3JydXB0ZWQgYnkgZXJyb3JzLCBhdHRlbXB0cyB0b1xuICAgICAgICAgKiBjb3JyZWN0IHRoZSBlcnJvcnMgaW4tcGxhY2UgdXNpbmcgUmVlZC1Tb2xvbW9uIGVycm9yIGNvcnJlY3Rpb24uPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gY29kZXdvcmRCeXRlcyBkYXRhIGFuZCBlcnJvciBjb3JyZWN0aW9uIGNvZGV3b3Jkc1xuICAgICAgICAgKiBAcGFyYW0gbnVtRGF0YUNvZGV3b3JkcyBudW1iZXIgb2YgY29kZXdvcmRzIHRoYXQgYXJlIGRhdGEgYnl0ZXNcbiAgICAgICAgICogQHRocm93cyBDaGVja3N1bUV4Y2VwdGlvbiBpZiBlcnJvciBjb3JyZWN0aW9uIGZhaWxzXG4gICAgICAgICAqL1xuICAgICAgICBjb3JyZWN0RXJyb3JzKGNvZGV3b3JkQnl0ZXMsIG51bURhdGFDb2Rld29yZHMgLyppbnQqLykge1xuICAgICAgICAgICAgLy8gY29uc3QgbnVtQ29kZXdvcmRzID0gY29kZXdvcmRCeXRlcy5sZW5ndGg7XG4gICAgICAgICAgICAvLyBGaXJzdCByZWFkIGludG8gYW4gYXJyYXkgb2YgaW50c1xuICAgICAgICAgICAgY29uc3QgY29kZXdvcmRzSW50cyA9IG5ldyBJbnQzMkFycmF5KGNvZGV3b3JkQnl0ZXMpO1xuICAgICAgICAgICAgLy8gVFlQRVNDUklQVFBPUlQ6IG5vdCByZWFseSBuZWNlc3NhcnkgdG8gdHJhbnNmb3JtIHRvIGludHM/IGNvdWxkIHJlZGVzaWduIGV2ZXJ5dGhpbmcgdG8gd29yayB3aXRoIHVuc2lnbmVkIGJ5dGVzP1xuICAgICAgICAgICAgLy8gY29uc3QgY29kZXdvcmRzSW50cyA9IG5ldyBJbnQzMkFycmF5KG51bUNvZGV3b3JkcylcbiAgICAgICAgICAgIC8vIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtQ29kZXdvcmRzOyBpKyspIHtcbiAgICAgICAgICAgIC8vICAgY29kZXdvcmRzSW50c1tpXSA9IGNvZGV3b3JkQnl0ZXNbaV0gJiAweEZGXG4gICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHRoaXMucnNEZWNvZGVyLmRlY29kZShjb2Rld29yZHNJbnRzLCBjb2Rld29yZEJ5dGVzLmxlbmd0aCAtIG51bURhdGFDb2Rld29yZHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGlnbm9yZWQgLyo6IFJlZWRTb2xvbW9uRXhjZXB0aW9uKi8pIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQ2hlY2tzdW1FeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIENvcHkgYmFjayBpbnRvIGFycmF5IG9mIGJ5dGVzIC0tIG9ubHkgbmVlZCB0byB3b3JyeSBhYm91dCB0aGUgYnl0ZXMgdGhhdCB3ZXJlIGRhdGFcbiAgICAgICAgICAgIC8vIFdlIGRvbid0IGNhcmUgYWJvdXQgZXJyb3JzIGluIHRoZSBlcnJvci1jb3JyZWN0aW9uIGNvZGV3b3Jkc1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1EYXRhQ29kZXdvcmRzOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb2Rld29yZEJ5dGVzW2ldID0gLyooYnl0ZSkgKi8gY29kZXdvcmRzSW50c1tpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogPHA+RW5jYXBzdWxhdGVzIGFuIGFsaWdubWVudCBwYXR0ZXJuLCB3aGljaCBhcmUgdGhlIHNtYWxsZXIgc3F1YXJlIHBhdHRlcm5zIGZvdW5kIGluXG4gICAgICogYWxsIGJ1dCB0aGUgc2ltcGxlc3QgUVIgQ29kZXMuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBBbGlnbm1lbnRQYXR0ZXJuIGV4dGVuZHMgUmVzdWx0UG9pbnQge1xuICAgICAgICBjb25zdHJ1Y3Rvcihwb3NYIC8qZmxvYXQqLywgcG9zWSAvKmZsb2F0Ki8sIGVzdGltYXRlZE1vZHVsZVNpemUgLypmbG9hdCovKSB7XG4gICAgICAgICAgICBzdXBlcihwb3NYLCBwb3NZKTtcbiAgICAgICAgICAgIHRoaXMuZXN0aW1hdGVkTW9kdWxlU2l6ZSA9IGVzdGltYXRlZE1vZHVsZVNpemU7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkRldGVybWluZXMgaWYgdGhpcyBhbGlnbm1lbnQgcGF0dGVybiBcImFib3V0IGVxdWFsc1wiIGFuIGFsaWdubWVudCBwYXR0ZXJuIGF0IHRoZSBzdGF0ZWRcbiAgICAgICAgICogcG9zaXRpb24gYW5kIHNpemUgLS0gbWVhbmluZywgaXQgaXMgYXQgbmVhcmx5IHRoZSBzYW1lIGNlbnRlciB3aXRoIG5lYXJseSB0aGUgc2FtZSBzaXplLjwvcD5cbiAgICAgICAgICovXG4gICAgICAgIGFib3V0RXF1YWxzKG1vZHVsZVNpemUgLypmbG9hdCovLCBpIC8qZmxvYXQqLywgaiAvKmZsb2F0Ki8pIHtcbiAgICAgICAgICAgIGlmIChNYXRoLmFicyhpIC0gdGhpcy5nZXRZKCkpIDw9IG1vZHVsZVNpemUgJiYgTWF0aC5hYnMoaiAtIHRoaXMuZ2V0WCgpKSA8PSBtb2R1bGVTaXplKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbW9kdWxlU2l6ZURpZmYgPSBNYXRoLmFicyhtb2R1bGVTaXplIC0gdGhpcy5lc3RpbWF0ZWRNb2R1bGVTaXplKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9kdWxlU2l6ZURpZmYgPD0gMS4wIHx8IG1vZHVsZVNpemVEaWZmIDw9IHRoaXMuZXN0aW1hdGVkTW9kdWxlU2l6ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ29tYmluZXMgdGhpcyBvYmplY3QncyBjdXJyZW50IGVzdGltYXRlIG9mIGEgZmluZGVyIHBhdHRlcm4gcG9zaXRpb24gYW5kIG1vZHVsZSBzaXplXG4gICAgICAgICAqIHdpdGggYSBuZXcgZXN0aW1hdGUuIEl0IHJldHVybnMgYSBuZXcge0Bjb2RlIEZpbmRlclBhdHRlcm59IGNvbnRhaW5pbmcgYW4gYXZlcmFnZSBvZiB0aGUgdHdvLlxuICAgICAgICAgKi9cbiAgICAgICAgY29tYmluZUVzdGltYXRlKGkgLypmbG9hdCovLCBqIC8qZmxvYXQqLywgbmV3TW9kdWxlU2l6ZSAvKmZsb2F0Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IGNvbWJpbmVkWCA9ICh0aGlzLmdldFgoKSArIGopIC8gMi4wO1xuICAgICAgICAgICAgY29uc3QgY29tYmluZWRZID0gKHRoaXMuZ2V0WSgpICsgaSkgLyAyLjA7XG4gICAgICAgICAgICBjb25zdCBjb21iaW5lZE1vZHVsZVNpemUgPSAodGhpcy5lc3RpbWF0ZWRNb2R1bGVTaXplICsgbmV3TW9kdWxlU2l6ZSkgLyAyLjA7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEFsaWdubWVudFBhdHRlcm4oY29tYmluZWRYLCBjb21iaW5lZFksIGNvbWJpbmVkTW9kdWxlU2l6ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7Ki9cbiAgICAvKmltcG9ydCBqYXZhLnV0aWwuTGlzdDsqL1xuICAgIC8qKlxuICAgICAqIDxwPlRoaXMgY2xhc3MgYXR0ZW1wdHMgdG8gZmluZCBhbGlnbm1lbnQgcGF0dGVybnMgaW4gYSBRUiBDb2RlLiBBbGlnbm1lbnQgcGF0dGVybnMgbG9vayBsaWtlIGZpbmRlclxuICAgICAqIHBhdHRlcm5zIGJ1dCBhcmUgc21hbGxlciBhbmQgYXBwZWFyIGF0IHJlZ3VsYXIgaW50ZXJ2YWxzIHRocm91Z2hvdXQgdGhlIGltYWdlLjwvcD5cbiAgICAgKlxuICAgICAqIDxwPkF0IHRoZSBtb21lbnQgdGhpcyBvbmx5IGxvb2tzIGZvciB0aGUgYm90dG9tLXJpZ2h0IGFsaWdubWVudCBwYXR0ZXJuLjwvcD5cbiAgICAgKlxuICAgICAqIDxwPlRoaXMgaXMgbW9zdGx5IGEgc2ltcGxpZmllZCBjb3B5IG9mIHtAbGluayBGaW5kZXJQYXR0ZXJuRmluZGVyfS4gSXQgaXMgY29waWVkLFxuICAgICAqIHBhc3RlZCBhbmQgc3RyaXBwZWQgZG93biBoZXJlIGZvciBtYXhpbXVtIHBlcmZvcm1hbmNlIGJ1dCBkb2VzIHVuZm9ydHVuYXRlbHkgZHVwbGljYXRlXG4gICAgICogc29tZSBjb2RlLjwvcD5cbiAgICAgKlxuICAgICAqIDxwPlRoaXMgY2xhc3MgaXMgdGhyZWFkLXNhZmUgYnV0IG5vdCByZWVudHJhbnQuIEVhY2ggdGhyZWFkIG11c3QgYWxsb2NhdGUgaXRzIG93biBvYmplY3QuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBBbGlnbm1lbnRQYXR0ZXJuRmluZGVyIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkNyZWF0ZXMgYSBmaW5kZXIgdGhhdCB3aWxsIGxvb2sgaW4gYSBwb3J0aW9uIG9mIHRoZSB3aG9sZSBpbWFnZS48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBpbWFnZSBpbWFnZSB0byBzZWFyY2hcbiAgICAgICAgICogQHBhcmFtIHN0YXJ0WCBsZWZ0IGNvbHVtbiBmcm9tIHdoaWNoIHRvIHN0YXJ0IHNlYXJjaGluZ1xuICAgICAgICAgKiBAcGFyYW0gc3RhcnRZIHRvcCByb3cgZnJvbSB3aGljaCB0byBzdGFydCBzZWFyY2hpbmdcbiAgICAgICAgICogQHBhcmFtIHdpZHRoIHdpZHRoIG9mIHJlZ2lvbiB0byBzZWFyY2hcbiAgICAgICAgICogQHBhcmFtIGhlaWdodCBoZWlnaHQgb2YgcmVnaW9uIHRvIHNlYXJjaFxuICAgICAgICAgKiBAcGFyYW0gbW9kdWxlU2l6ZSBlc3RpbWF0ZWQgbW9kdWxlIHNpemUgc28gZmFyXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3RvcihpbWFnZSwgc3RhcnRYIC8qaW50Ki8sIHN0YXJ0WSAvKmludCovLCB3aWR0aCAvKmludCovLCBoZWlnaHQgLyppbnQqLywgbW9kdWxlU2l6ZSAvKmZsb2F0Ki8sIHJlc3VsdFBvaW50Q2FsbGJhY2spIHtcbiAgICAgICAgICAgIHRoaXMuaW1hZ2UgPSBpbWFnZTtcbiAgICAgICAgICAgIHRoaXMuc3RhcnRYID0gc3RhcnRYO1xuICAgICAgICAgICAgdGhpcy5zdGFydFkgPSBzdGFydFk7XG4gICAgICAgICAgICB0aGlzLndpZHRoID0gd2lkdGg7XG4gICAgICAgICAgICB0aGlzLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgICAgIHRoaXMubW9kdWxlU2l6ZSA9IG1vZHVsZVNpemU7XG4gICAgICAgICAgICB0aGlzLnJlc3VsdFBvaW50Q2FsbGJhY2sgPSByZXN1bHRQb2ludENhbGxiYWNrO1xuICAgICAgICAgICAgdGhpcy5wb3NzaWJsZUNlbnRlcnMgPSBbXTsgLy8gbmV3IEFycmF5PGFueT4oNSkpXG4gICAgICAgICAgICAvLyBUWVBFU0NSSVBUUE9SVDogYXJyYXkgaW5pdGlhbGl6YXRpb24gd2l0aG91dCBzaXplIGFzIHRoZSBsZW5ndGggaXMgY2hlY2tlZCBiZWxvd1xuICAgICAgICAgICAgdGhpcy5jcm9zc0NoZWNrU3RhdGVDb3VudCA9IG5ldyBJbnQzMkFycmF5KDMpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5UaGlzIG1ldGhvZCBhdHRlbXB0cyB0byBmaW5kIHRoZSBib3R0b20tcmlnaHQgYWxpZ25tZW50IHBhdHRlcm4gaW4gdGhlIGltYWdlLiBJdCBpcyBhIGJpdCBtZXNzeSBzaW5jZVxuICAgICAgICAgKiBpdCdzIHByZXR0eSBwZXJmb3JtYW5jZS1jcml0aWNhbCBhbmQgc28gaXMgd3JpdHRlbiB0byBiZSBmYXN0IGZvcmVtb3N0LjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiB7QGxpbmsgQWxpZ25tZW50UGF0dGVybn0gaWYgZm91bmRcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBpZiBub3QgZm91bmRcbiAgICAgICAgICovXG4gICAgICAgIGZpbmQoKSB7XG4gICAgICAgICAgICBjb25zdCBzdGFydFggPSB0aGlzLnN0YXJ0WDtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuaGVpZ2h0O1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSB0aGlzLndpZHRoO1xuICAgICAgICAgICAgY29uc3QgbWF4SiA9IHN0YXJ0WCArIHdpZHRoO1xuICAgICAgICAgICAgY29uc3QgbWlkZGxlSSA9IHRoaXMuc3RhcnRZICsgKGhlaWdodCAvIDIpO1xuICAgICAgICAgICAgLy8gV2UgYXJlIGxvb2tpbmcgZm9yIGJsYWNrL3doaXRlL2JsYWNrIG1vZHVsZXMgaW4gMToxOjEgcmF0aW9cbiAgICAgICAgICAgIC8vIHRoaXMgdHJhY2tzIHRoZSBudW1iZXIgb2YgYmxhY2svd2hpdGUvYmxhY2sgbW9kdWxlcyBzZWVuIHNvIGZhclxuICAgICAgICAgICAgY29uc3Qgc3RhdGVDb3VudCA9IG5ldyBJbnQzMkFycmF5KDMpO1xuICAgICAgICAgICAgY29uc3QgaW1hZ2UgPSB0aGlzLmltYWdlO1xuICAgICAgICAgICAgZm9yIChsZXQgaUdlbiA9IDA7IGlHZW4gPCBoZWlnaHQ7IGlHZW4rKykge1xuICAgICAgICAgICAgICAgIC8vIFNlYXJjaCBmcm9tIG1pZGRsZSBvdXR3YXJkc1xuICAgICAgICAgICAgICAgIGNvbnN0IGkgPSBtaWRkbGVJICsgKChpR2VuICYgMHgwMSkgPT09IDAgPyBNYXRoLmZsb29yKChpR2VuICsgMSkgLyAyKSA6IC1NYXRoLmZsb29yKChpR2VuICsgMSkgLyAyKSk7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFswXSA9IDA7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFsxXSA9IDA7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFsyXSA9IDA7XG4gICAgICAgICAgICAgICAgbGV0IGogPSBzdGFydFg7XG4gICAgICAgICAgICAgICAgLy8gQnVybiBvZmYgbGVhZGluZyB3aGl0ZSBwaXhlbHMgYmVmb3JlIGFueXRoaW5nIGVsc2U7IGlmIHdlIHN0YXJ0IGluIHRoZSBtaWRkbGUgb2ZcbiAgICAgICAgICAgICAgICAvLyBhIHdoaXRlIHJ1biwgaXQgZG9lc24ndCBtYWtlIHNlbnNlIHRvIGNvdW50IGl0cyBsZW5ndGgsIHNpbmNlIHdlIGRvbid0IGtub3cgaWYgdGhlXG4gICAgICAgICAgICAgICAgLy8gd2hpdGUgcnVuIGNvbnRpbnVlZCB0byB0aGUgbGVmdCBvZiB0aGUgc3RhcnQgcG9pbnRcbiAgICAgICAgICAgICAgICB3aGlsZSAoaiA8IG1heEogJiYgIWltYWdlLmdldChqLCBpKSkge1xuICAgICAgICAgICAgICAgICAgICBqKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCBjdXJyZW50U3RhdGUgPSAwO1xuICAgICAgICAgICAgICAgIHdoaWxlIChqIDwgbWF4Sikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW1hZ2UuZ2V0KGosIGkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBCbGFjayBwaXhlbFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRTdGF0ZSA9PT0gMSkgeyAvLyBDb3VudGluZyBibGFjayBwaXhlbHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzFdKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHsgLy8gQ291bnRpbmcgd2hpdGUgcGl4ZWxzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRTdGF0ZSA9PT0gMikgeyAvLyBBIHdpbm5lcj9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZm91bmRQYXR0ZXJuQ3Jvc3Moc3RhdGVDb3VudCkpIHsgLy8gWWVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25maXJtZWQgPSB0aGlzLmhhbmRsZVBvc3NpYmxlQ2VudGVyKHN0YXRlQ291bnQsIGksIGopO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbmZpcm1lZCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjb25maXJtZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFswXSA9IHN0YXRlQ291bnRbMl07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMV0gPSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzJdID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFN0YXRlID0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbKytjdXJyZW50U3RhdGVdKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgeyAvLyBXaGl0ZSBwaXhlbFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRTdGF0ZSA9PT0gMSkgeyAvLyBDb3VudGluZyBibGFjayBwaXhlbHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50U3RhdGUrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbY3VycmVudFN0YXRlXSsrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGorKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZm91bmRQYXR0ZXJuQ3Jvc3Moc3RhdGVDb3VudCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29uZmlybWVkID0gdGhpcy5oYW5kbGVQb3NzaWJsZUNlbnRlcihzdGF0ZUNvdW50LCBpLCBtYXhKKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvbmZpcm1lZCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvbmZpcm1lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEhtbSwgbm90aGluZyB3ZSBzYXcgd2FzIG9ic2VydmVkIGFuZCBjb25maXJtZWQgdHdpY2UuIElmIHdlIGhhZFxuICAgICAgICAgICAgLy8gYW55IGd1ZXNzIGF0IGFsbCwgcmV0dXJuIGl0LlxuICAgICAgICAgICAgaWYgKHRoaXMucG9zc2libGVDZW50ZXJzLmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBvc3NpYmxlQ2VudGVyc1swXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHaXZlbiBhIGNvdW50IG9mIGJsYWNrL3doaXRlL2JsYWNrIHBpeGVscyBqdXN0IHNlZW4gYW5kIGFuIGVuZCBwb3NpdGlvbixcbiAgICAgICAgICogZmlndXJlcyB0aGUgbG9jYXRpb24gb2YgdGhlIGNlbnRlciBvZiB0aGlzIGJsYWNrL3doaXRlL2JsYWNrIHJ1bi5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBjZW50ZXJGcm9tRW5kKHN0YXRlQ291bnQsIGVuZCAvKmludCovKSB7XG4gICAgICAgICAgICByZXR1cm4gKGVuZCAtIHN0YXRlQ291bnRbMl0pIC0gc3RhdGVDb3VudFsxXSAvIDIuMDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHN0YXRlQ291bnQgY291bnQgb2YgYmxhY2svd2hpdGUvYmxhY2sgcGl4ZWxzIGp1c3QgcmVhZFxuICAgICAgICAgKiBAcmV0dXJuIHRydWUgaWZmIHRoZSBwcm9wb3J0aW9ucyBvZiB0aGUgY291bnRzIGlzIGNsb3NlIGVub3VnaCB0byB0aGUgMS8xLzEgcmF0aW9zXG4gICAgICAgICAqICAgICAgICAgdXNlZCBieSBhbGlnbm1lbnQgcGF0dGVybnMgdG8gYmUgY29uc2lkZXJlZCBhIG1hdGNoXG4gICAgICAgICAqL1xuICAgICAgICBmb3VuZFBhdHRlcm5Dcm9zcyhzdGF0ZUNvdW50KSB7XG4gICAgICAgICAgICBjb25zdCBtb2R1bGVTaXplID0gdGhpcy5tb2R1bGVTaXplO1xuICAgICAgICAgICAgY29uc3QgbWF4VmFyaWFuY2UgPSBtb2R1bGVTaXplIC8gMi4wO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoTWF0aC5hYnMobW9kdWxlU2l6ZSAtIHN0YXRlQ291bnRbaV0pID49IG1heFZhcmlhbmNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+QWZ0ZXIgYSBob3Jpem9udGFsIHNjYW4gZmluZHMgYSBwb3RlbnRpYWwgYWxpZ25tZW50IHBhdHRlcm4sIHRoaXMgbWV0aG9kXG4gICAgICAgICAqIFwiY3Jvc3MtY2hlY2tzXCIgYnkgc2Nhbm5pbmcgZG93biB2ZXJ0aWNhbGx5IHRocm91Z2ggdGhlIGNlbnRlciBvZiB0aGUgcG9zc2libGVcbiAgICAgICAgICogYWxpZ25tZW50IHBhdHRlcm4gdG8gc2VlIGlmIHRoZSBzYW1lIHByb3BvcnRpb24gaXMgZGV0ZWN0ZWQuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gc3RhcnRJIHJvdyB3aGVyZSBhbiBhbGlnbm1lbnQgcGF0dGVybiB3YXMgZGV0ZWN0ZWRcbiAgICAgICAgICogQHBhcmFtIGNlbnRlckogY2VudGVyIG9mIHRoZSBzZWN0aW9uIHRoYXQgYXBwZWFycyB0byBjcm9zcyBhbiBhbGlnbm1lbnQgcGF0dGVyblxuICAgICAgICAgKiBAcGFyYW0gbWF4Q291bnQgbWF4aW11bSByZWFzb25hYmxlIG51bWJlciBvZiBtb2R1bGVzIHRoYXQgc2hvdWxkIGJlXG4gICAgICAgICAqIG9ic2VydmVkIGluIGFueSByZWFkaW5nIHN0YXRlLCBiYXNlZCBvbiB0aGUgcmVzdWx0cyBvZiB0aGUgaG9yaXpvbnRhbCBzY2FuXG4gICAgICAgICAqIEByZXR1cm4gdmVydGljYWwgY2VudGVyIG9mIGFsaWdubWVudCBwYXR0ZXJuLCBvciB7QGxpbmsgRmxvYXQjTmFOfSBpZiBub3QgZm91bmRcbiAgICAgICAgICovXG4gICAgICAgIGNyb3NzQ2hlY2tWZXJ0aWNhbChzdGFydEkgLyppbnQqLywgY2VudGVySiAvKmludCovLCBtYXhDb3VudCAvKmludCovLCBvcmlnaW5hbFN0YXRlQ291bnRUb3RhbCAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBpbWFnZSA9IHRoaXMuaW1hZ2U7XG4gICAgICAgICAgICBjb25zdCBtYXhJID0gaW1hZ2UuZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICBjb25zdCBzdGF0ZUNvdW50ID0gdGhpcy5jcm9zc0NoZWNrU3RhdGVDb3VudDtcbiAgICAgICAgICAgIHN0YXRlQ291bnRbMF0gPSAwO1xuICAgICAgICAgICAgc3RhdGVDb3VudFsxXSA9IDA7XG4gICAgICAgICAgICBzdGF0ZUNvdW50WzJdID0gMDtcbiAgICAgICAgICAgIC8vIFN0YXJ0IGNvdW50aW5nIHVwIGZyb20gY2VudGVyXG4gICAgICAgICAgICBsZXQgaSA9IHN0YXJ0STtcbiAgICAgICAgICAgIHdoaWxlIChpID49IDAgJiYgaW1hZ2UuZ2V0KGNlbnRlckosIGkpICYmIHN0YXRlQ291bnRbMV0gPD0gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzFdKys7XG4gICAgICAgICAgICAgICAgaS0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSWYgYWxyZWFkeSB0b28gbWFueSBtb2R1bGVzIGluIHRoaXMgc3RhdGUgb3IgcmFuIG9mZiB0aGUgZWRnZTpcbiAgICAgICAgICAgIGlmIChpIDwgMCB8fCBzdGF0ZUNvdW50WzFdID4gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2hpbGUgKGkgPj0gMCAmJiAhaW1hZ2UuZ2V0KGNlbnRlckosIGkpICYmIHN0YXRlQ291bnRbMF0gPD0gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzBdKys7XG4gICAgICAgICAgICAgICAgaS0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0YXRlQ291bnRbMF0gPiBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBOb3cgYWxzbyBjb3VudCBkb3duIGZyb20gY2VudGVyXG4gICAgICAgICAgICBpID0gc3RhcnRJICsgMTtcbiAgICAgICAgICAgIHdoaWxlIChpIDwgbWF4SSAmJiBpbWFnZS5nZXQoY2VudGVySiwgaSkgJiYgc3RhdGVDb3VudFsxXSA8PSBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMV0rKztcbiAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaSA9PT0gbWF4SSB8fCBzdGF0ZUNvdW50WzFdID4gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2hpbGUgKGkgPCBtYXhJICYmICFpbWFnZS5nZXQoY2VudGVySiwgaSkgJiYgc3RhdGVDb3VudFsyXSA8PSBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMl0rKztcbiAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RhdGVDb3VudFsyXSA+IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHN0YXRlQ291bnRUb3RhbCA9IHN0YXRlQ291bnRbMF0gKyBzdGF0ZUNvdW50WzFdICsgc3RhdGVDb3VudFsyXTtcbiAgICAgICAgICAgIGlmICg1ICogTWF0aC5hYnMoc3RhdGVDb3VudFRvdGFsIC0gb3JpZ2luYWxTdGF0ZUNvdW50VG90YWwpID49IDIgKiBvcmlnaW5hbFN0YXRlQ291bnRUb3RhbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5mb3VuZFBhdHRlcm5Dcm9zcyhzdGF0ZUNvdW50KSA/IEFsaWdubWVudFBhdHRlcm5GaW5kZXIuY2VudGVyRnJvbUVuZChzdGF0ZUNvdW50LCBpKSA6IE5hTjtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+VGhpcyBpcyBjYWxsZWQgd2hlbiBhIGhvcml6b250YWwgc2NhbiBmaW5kcyBhIHBvc3NpYmxlIGFsaWdubWVudCBwYXR0ZXJuLiBJdCB3aWxsXG4gICAgICAgICAqIGNyb3NzIGNoZWNrIHdpdGggYSB2ZXJ0aWNhbCBzY2FuLCBhbmQgaWYgc3VjY2Vzc2Z1bCwgd2lsbCBzZWUgaWYgdGhpcyBwYXR0ZXJuIGhhZCBiZWVuXG4gICAgICAgICAqIGZvdW5kIG9uIGEgcHJldmlvdXMgaG9yaXpvbnRhbCBzY2FuLiBJZiBzbywgd2UgY29uc2lkZXIgaXQgY29uZmlybWVkIGFuZCBjb25jbHVkZSB3ZSBoYXZlXG4gICAgICAgICAqIGZvdW5kIHRoZSBhbGlnbm1lbnQgcGF0dGVybi48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBzdGF0ZUNvdW50IHJlYWRpbmcgc3RhdGUgbW9kdWxlIGNvdW50cyBmcm9tIGhvcml6b250YWwgc2NhblxuICAgICAgICAgKiBAcGFyYW0gaSByb3cgd2hlcmUgYWxpZ25tZW50IHBhdHRlcm4gbWF5IGJlIGZvdW5kXG4gICAgICAgICAqIEBwYXJhbSBqIGVuZCBvZiBwb3NzaWJsZSBhbGlnbm1lbnQgcGF0dGVybiBpbiByb3dcbiAgICAgICAgICogQHJldHVybiB7QGxpbmsgQWxpZ25tZW50UGF0dGVybn0gaWYgd2UgaGF2ZSBmb3VuZCB0aGUgc2FtZSBwYXR0ZXJuIHR3aWNlLCBvciBudWxsIGlmIG5vdFxuICAgICAgICAgKi9cbiAgICAgICAgaGFuZGxlUG9zc2libGVDZW50ZXIoc3RhdGVDb3VudCwgaSAvKmludCovLCBqIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IHN0YXRlQ291bnRUb3RhbCA9IHN0YXRlQ291bnRbMF0gKyBzdGF0ZUNvdW50WzFdICsgc3RhdGVDb3VudFsyXTtcbiAgICAgICAgICAgIGNvbnN0IGNlbnRlckogPSBBbGlnbm1lbnRQYXR0ZXJuRmluZGVyLmNlbnRlckZyb21FbmQoc3RhdGVDb3VudCwgaik7XG4gICAgICAgICAgICBjb25zdCBjZW50ZXJJID0gdGhpcy5jcm9zc0NoZWNrVmVydGljYWwoaSwgLyooaW50KSAqLyBjZW50ZXJKLCAyICogc3RhdGVDb3VudFsxXSwgc3RhdGVDb3VudFRvdGFsKTtcbiAgICAgICAgICAgIGlmICghaXNOYU4oY2VudGVySSkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBlc3RpbWF0ZWRNb2R1bGVTaXplID0gKHN0YXRlQ291bnRbMF0gKyBzdGF0ZUNvdW50WzFdICsgc3RhdGVDb3VudFsyXSkgLyAzLjA7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBjZW50ZXIgb2YgdGhpcy5wb3NzaWJsZUNlbnRlcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gTG9vayBmb3IgYWJvdXQgdGhlIHNhbWUgY2VudGVyIGFuZCBtb2R1bGUgc2l6ZTpcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNlbnRlci5hYm91dEVxdWFscyhlc3RpbWF0ZWRNb2R1bGVTaXplLCBjZW50ZXJJLCBjZW50ZXJKKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNlbnRlci5jb21iaW5lRXN0aW1hdGUoY2VudGVySSwgY2VudGVySiwgZXN0aW1hdGVkTW9kdWxlU2l6ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gSGFkbid0IGZvdW5kIHRoaXMgYmVmb3JlOyBzYXZlIGl0XG4gICAgICAgICAgICAgICAgY29uc3QgcG9pbnQgPSBuZXcgQWxpZ25tZW50UGF0dGVybihjZW50ZXJKLCBjZW50ZXJJLCBlc3RpbWF0ZWRNb2R1bGVTaXplKTtcbiAgICAgICAgICAgICAgICB0aGlzLnBvc3NpYmxlQ2VudGVycy5wdXNoKHBvaW50KTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5yZXN1bHRQb2ludENhbGxiYWNrICE9PSBudWxsICYmIHRoaXMucmVzdWx0UG9pbnRDYWxsYmFjayAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVzdWx0UG9pbnRDYWxsYmFjay5mb3VuZFBvc3NpYmxlUmVzdWx0UG9pbnQocG9pbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiA8cD5FbmNhcHN1bGF0ZXMgYSBmaW5kZXIgcGF0dGVybiwgd2hpY2ggYXJlIHRoZSB0aHJlZSBzcXVhcmUgcGF0dGVybnMgZm91bmQgaW5cbiAgICAgKiB0aGUgY29ybmVycyBvZiBRUiBDb2Rlcy4gSXQgYWxzbyBlbmNhcHN1bGF0ZXMgYSBjb3VudCBvZiBzaW1pbGFyIGZpbmRlciBwYXR0ZXJucyxcbiAgICAgKiBhcyBhIGNvbnZlbmllbmNlIHRvIHRoZSBmaW5kZXIncyBib29ra2VlcGluZy48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIEZpbmRlclBhdHRlcm4kMSBleHRlbmRzIFJlc3VsdFBvaW50IHtcbiAgICAgICAgLy8gRmluZGVyUGF0dGVybihwb3NYOiBudW1iZXIvKmZsb2F0Ki8sIHBvc1k6IG51bWJlci8qZmxvYXQqLywgZXN0aW1hdGVkTW9kdWxlU2l6ZTogbnVtYmVyLypmbG9hdCovKSB7XG4gICAgICAgIC8vICAgdGhpcyhwb3NYLCBwb3NZLCBlc3RpbWF0ZWRNb2R1bGVTaXplLCAxKVxuICAgICAgICAvLyB9XG4gICAgICAgIGNvbnN0cnVjdG9yKHBvc1ggLypmbG9hdCovLCBwb3NZIC8qZmxvYXQqLywgZXN0aW1hdGVkTW9kdWxlU2l6ZSAvKmZsb2F0Ki8sIGNvdW50IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHN1cGVyKHBvc1gsIHBvc1kpO1xuICAgICAgICAgICAgdGhpcy5lc3RpbWF0ZWRNb2R1bGVTaXplID0gZXN0aW1hdGVkTW9kdWxlU2l6ZTtcbiAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudDtcbiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IGNvdW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb3VudCA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RXN0aW1hdGVkTW9kdWxlU2l6ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVzdGltYXRlZE1vZHVsZVNpemU7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Q291bnQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb3VudDtcbiAgICAgICAgfVxuICAgICAgICAvKlxuICAgICAgICB2b2lkIGluY3JlbWVudENvdW50KCkge1xuICAgICAgICAgIHRoaXMuY291bnQrK1xuICAgICAgICB9XG4gICAgICAgICAqL1xuICAgICAgICAvKipcbiAgICAgICAgICogPHA+RGV0ZXJtaW5lcyBpZiB0aGlzIGZpbmRlciBwYXR0ZXJuIFwiYWJvdXQgZXF1YWxzXCIgYSBmaW5kZXIgcGF0dGVybiBhdCB0aGUgc3RhdGVkXG4gICAgICAgICAqIHBvc2l0aW9uIGFuZCBzaXplIC0tIG1lYW5pbmcsIGl0IGlzIGF0IG5lYXJseSB0aGUgc2FtZSBjZW50ZXIgd2l0aCBuZWFybHkgdGhlIHNhbWUgc2l6ZS48L3A+XG4gICAgICAgICAqL1xuICAgICAgICBhYm91dEVxdWFscyhtb2R1bGVTaXplIC8qZmxvYXQqLywgaSAvKmZsb2F0Ki8sIGogLypmbG9hdCovKSB7XG4gICAgICAgICAgICBpZiAoTWF0aC5hYnMoaSAtIHRoaXMuZ2V0WSgpKSA8PSBtb2R1bGVTaXplICYmIE1hdGguYWJzKGogLSB0aGlzLmdldFgoKSkgPD0gbW9kdWxlU2l6ZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG1vZHVsZVNpemVEaWZmID0gTWF0aC5hYnMobW9kdWxlU2l6ZSAtIHRoaXMuZXN0aW1hdGVkTW9kdWxlU2l6ZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vZHVsZVNpemVEaWZmIDw9IDEuMCB8fCBtb2R1bGVTaXplRGlmZiA8PSB0aGlzLmVzdGltYXRlZE1vZHVsZVNpemU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbWJpbmVzIHRoaXMgb2JqZWN0J3MgY3VycmVudCBlc3RpbWF0ZSBvZiBhIGZpbmRlciBwYXR0ZXJuIHBvc2l0aW9uIGFuZCBtb2R1bGUgc2l6ZVxuICAgICAgICAgKiB3aXRoIGEgbmV3IGVzdGltYXRlLiBJdCByZXR1cm5zIGEgbmV3IHtAY29kZSBGaW5kZXJQYXR0ZXJufSBjb250YWluaW5nIGEgd2VpZ2h0ZWQgYXZlcmFnZVxuICAgICAgICAgKiBiYXNlZCBvbiBjb3VudC5cbiAgICAgICAgICovXG4gICAgICAgIGNvbWJpbmVFc3RpbWF0ZShpIC8qZmxvYXQqLywgaiAvKmZsb2F0Ki8sIG5ld01vZHVsZVNpemUgLypmbG9hdCovKSB7XG4gICAgICAgICAgICBjb25zdCBjb21iaW5lZENvdW50ID0gdGhpcy5jb3VudCArIDE7XG4gICAgICAgICAgICBjb25zdCBjb21iaW5lZFggPSAodGhpcy5jb3VudCAqIHRoaXMuZ2V0WCgpICsgaikgLyBjb21iaW5lZENvdW50O1xuICAgICAgICAgICAgY29uc3QgY29tYmluZWRZID0gKHRoaXMuY291bnQgKiB0aGlzLmdldFkoKSArIGkpIC8gY29tYmluZWRDb3VudDtcbiAgICAgICAgICAgIGNvbnN0IGNvbWJpbmVkTW9kdWxlU2l6ZSA9ICh0aGlzLmNvdW50ICogdGhpcy5lc3RpbWF0ZWRNb2R1bGVTaXplICsgbmV3TW9kdWxlU2l6ZSkgLyBjb21iaW5lZENvdW50O1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBGaW5kZXJQYXR0ZXJuJDEoY29tYmluZWRYLCBjb21iaW5lZFksIGNvbWJpbmVkTW9kdWxlU2l6ZSwgY29tYmluZWRDb3VudCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA3IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIDxwPkVuY2Fwc3VsYXRlcyBpbmZvcm1hdGlvbiBhYm91dCBmaW5kZXIgcGF0dGVybnMgaW4gYW4gaW1hZ2UsIGluY2x1ZGluZyB0aGUgbG9jYXRpb24gb2ZcbiAgICAgKiB0aGUgdGhyZWUgZmluZGVyIHBhdHRlcm5zLCBhbmQgdGhlaXIgZXN0aW1hdGVkIG1vZHVsZSBzaXplLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgRmluZGVyUGF0dGVybkluZm8ge1xuICAgICAgICBjb25zdHJ1Y3RvcihwYXR0ZXJuQ2VudGVycykge1xuICAgICAgICAgICAgdGhpcy5ib3R0b21MZWZ0ID0gcGF0dGVybkNlbnRlcnNbMF07XG4gICAgICAgICAgICB0aGlzLnRvcExlZnQgPSBwYXR0ZXJuQ2VudGVyc1sxXTtcbiAgICAgICAgICAgIHRoaXMudG9wUmlnaHQgPSBwYXR0ZXJuQ2VudGVyc1syXTtcbiAgICAgICAgfVxuICAgICAgICBnZXRCb3R0b21MZWZ0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYm90dG9tTGVmdDtcbiAgICAgICAgfVxuICAgICAgICBnZXRUb3BMZWZ0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9wTGVmdDtcbiAgICAgICAgfVxuICAgICAgICBnZXRUb3BSaWdodCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRvcFJpZ2h0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKmltcG9ydCBqYXZhLmlvLlNlcmlhbGl6YWJsZTsqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7Ki9cbiAgICAvKmltcG9ydCBqYXZhLnV0aWwuQ29sbGVjdGlvbnM7Ki9cbiAgICAvKmltcG9ydCBqYXZhLnV0aWwuQ29tcGFyYXRvcjsqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5MaXN0OyovXG4gICAgLyppbXBvcnQgamF2YS51dGlsLk1hcDsqL1xuICAgIC8qKlxuICAgICAqIDxwPlRoaXMgY2xhc3MgYXR0ZW1wdHMgdG8gZmluZCBmaW5kZXIgcGF0dGVybnMgaW4gYSBRUiBDb2RlLiBGaW5kZXIgcGF0dGVybnMgYXJlIHRoZSBzcXVhcmVcbiAgICAgKiBtYXJrZXJzIGF0IHRocmVlIGNvcm5lcnMgb2YgYSBRUiBDb2RlLjwvcD5cbiAgICAgKlxuICAgICAqIDxwPlRoaXMgY2xhc3MgaXMgdGhyZWFkLXNhZmUgYnV0IG5vdCByZWVudHJhbnQuIEVhY2ggdGhyZWFkIG11c3QgYWxsb2NhdGUgaXRzIG93biBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIEZpbmRlclBhdHRlcm5GaW5kZXIge1xuICAgICAgICAvKipcbiAgICAgICAgICogPHA+Q3JlYXRlcyBhIGZpbmRlciB0aGF0IHdpbGwgc2VhcmNoIHRoZSBpbWFnZSBmb3IgdGhyZWUgZmluZGVyIHBhdHRlcm5zLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGltYWdlIGltYWdlIHRvIHNlYXJjaFxuICAgICAgICAgKi9cbiAgICAgICAgLy8gcHVibGljIGNvbnN0cnVjdG9yKGltYWdlOiBCaXRNYXRyaXgpIHtcbiAgICAgICAgLy8gICB0aGlzKGltYWdlLCBudWxsKVxuICAgICAgICAvLyB9XG4gICAgICAgIGNvbnN0cnVjdG9yKGltYWdlLCByZXN1bHRQb2ludENhbGxiYWNrKSB7XG4gICAgICAgICAgICB0aGlzLmltYWdlID0gaW1hZ2U7XG4gICAgICAgICAgICB0aGlzLnJlc3VsdFBvaW50Q2FsbGJhY2sgPSByZXN1bHRQb2ludENhbGxiYWNrO1xuICAgICAgICAgICAgdGhpcy5wb3NzaWJsZUNlbnRlcnMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuY3Jvc3NDaGVja1N0YXRlQ291bnQgPSBuZXcgSW50MzJBcnJheSg1KTtcbiAgICAgICAgICAgIHRoaXMucmVzdWx0UG9pbnRDYWxsYmFjayA9IHJlc3VsdFBvaW50Q2FsbGJhY2s7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0SW1hZ2UoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5pbWFnZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRQb3NzaWJsZUNlbnRlcnMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wb3NzaWJsZUNlbnRlcnM7XG4gICAgICAgIH1cbiAgICAgICAgZmluZChoaW50cykge1xuICAgICAgICAgICAgY29uc3QgdHJ5SGFyZGVyID0gKGhpbnRzICE9PSBudWxsICYmIGhpbnRzICE9PSB1bmRlZmluZWQpICYmIHVuZGVmaW5lZCAhPT0gaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuVFJZX0hBUkRFUik7XG4gICAgICAgICAgICBjb25zdCBwdXJlQmFyY29kZSA9IChoaW50cyAhPT0gbnVsbCAmJiBoaW50cyAhPT0gdW5kZWZpbmVkKSAmJiB1bmRlZmluZWQgIT09IGhpbnRzLmdldChEZWNvZGVIaW50VHlwZSQxLlBVUkVfQkFSQ09ERSk7XG4gICAgICAgICAgICBjb25zdCBpbWFnZSA9IHRoaXMuaW1hZ2U7XG4gICAgICAgICAgICBjb25zdCBtYXhJID0gaW1hZ2UuZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICBjb25zdCBtYXhKID0gaW1hZ2UuZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIC8vIFdlIGFyZSBsb29raW5nIGZvciBibGFjay93aGl0ZS9ibGFjay93aGl0ZS9ibGFjayBtb2R1bGVzIGluXG4gICAgICAgICAgICAvLyAxOjE6MzoxOjEgcmF0aW87IHRoaXMgdHJhY2tzIHRoZSBudW1iZXIgb2Ygc3VjaCBtb2R1bGVzIHNlZW4gc28gZmFyXG4gICAgICAgICAgICAvLyBMZXQncyBhc3N1bWUgdGhhdCB0aGUgbWF4aW11bSB2ZXJzaW9uIFFSIENvZGUgd2Ugc3VwcG9ydCB0YWtlcyB1cCAxLzQgdGhlIGhlaWdodCBvZiB0aGVcbiAgICAgICAgICAgIC8vIGltYWdlLCBhbmQgdGhlbiBhY2NvdW50IGZvciB0aGUgY2VudGVyIGJlaW5nIDMgbW9kdWxlcyBpbiBzaXplLiBUaGlzIGdpdmVzIHRoZSBzbWFsbGVzdFxuICAgICAgICAgICAgLy8gbnVtYmVyIG9mIHBpeGVscyB0aGUgY2VudGVyIGNvdWxkIGJlLCBzbyBza2lwIHRoaXMgb2Z0ZW4uIFdoZW4gdHJ5aW5nIGhhcmRlciwgbG9vayBmb3IgYWxsXG4gICAgICAgICAgICAvLyBRUiB2ZXJzaW9ucyByZWdhcmRsZXNzIG9mIGhvdyBkZW5zZSB0aGV5IGFyZS5cbiAgICAgICAgICAgIGxldCBpU2tpcCA9IE1hdGguZmxvb3IoKDMgKiBtYXhJKSAvICg0ICogRmluZGVyUGF0dGVybkZpbmRlci5NQVhfTU9EVUxFUykpO1xuICAgICAgICAgICAgaWYgKGlTa2lwIDwgRmluZGVyUGF0dGVybkZpbmRlci5NSU5fU0tJUCB8fCB0cnlIYXJkZXIpIHtcbiAgICAgICAgICAgICAgICBpU2tpcCA9IEZpbmRlclBhdHRlcm5GaW5kZXIuTUlOX1NLSVA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZG9uZSA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3Qgc3RhdGVDb3VudCA9IG5ldyBJbnQzMkFycmF5KDUpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGlTa2lwIC0gMTsgaSA8IG1heEkgJiYgIWRvbmU7IGkgKz0gaVNraXApIHtcbiAgICAgICAgICAgICAgICAvLyBHZXQgYSByb3cgb2YgYmxhY2svd2hpdGUgdmFsdWVzXG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFswXSA9IDA7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFsxXSA9IDA7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFsyXSA9IDA7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFszXSA9IDA7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFs0XSA9IDA7XG4gICAgICAgICAgICAgICAgbGV0IGN1cnJlbnRTdGF0ZSA9IDA7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBtYXhKOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGltYWdlLmdldChqLCBpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQmxhY2sgcGl4ZWxcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoY3VycmVudFN0YXRlICYgMSkgPT09IDEpIHsgLy8gQ291bnRpbmcgd2hpdGUgcGl4ZWxzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFN0YXRlKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50W2N1cnJlbnRTdGF0ZV0rKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHsgLy8gV2hpdGUgcGl4ZWxcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoY3VycmVudFN0YXRlICYgMSkgPT09IDApIHsgLy8gQ291bnRpbmcgYmxhY2sgcGl4ZWxzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRTdGF0ZSA9PT0gNCkgeyAvLyBBIHdpbm5lcj9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEZpbmRlclBhdHRlcm5GaW5kZXIuZm91bmRQYXR0ZXJuQ3Jvc3Moc3RhdGVDb3VudCkpIHsgLy8gWWVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25maXJtZWQgPSB0aGlzLmhhbmRsZVBvc3NpYmxlQ2VudGVyKHN0YXRlQ291bnQsIGksIGosIHB1cmVCYXJjb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb25maXJtZWQgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdGFydCBleGFtaW5pbmcgZXZlcnkgb3RoZXIgbGluZS4gQ2hlY2tpbmcgZWFjaCBsaW5lIHR1cm5lZCBvdXQgdG8gYmUgdG9vXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXhwZW5zaXZlIGFuZCBkaWRuJ3QgaW1wcm92ZSBwZXJmb3JtYW5jZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpU2tpcCA9IDI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaGFzU2tpcHBlZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lID0gdGhpcy5oYXZlTXVsdGlwbHlDb25maXJtZWRDZW50ZXJzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByb3dTa2lwID0gdGhpcy5maW5kUm93U2tpcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocm93U2tpcCA+IHN0YXRlQ291bnRbMl0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNraXAgcm93cyBiZXR3ZWVuIHJvdyBvZiBsb3dlciBjb25maXJtZWQgY2VudGVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhbmQgdG9wIG9mIHByZXN1bWVkIHRoaXJkIGNvbmZpcm1lZCBjZW50ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJ1dCBiYWNrIHVwIGEgYml0IHRvIGdldCBhIGZ1bGwgY2hhbmNlIG9mIGRldGVjdGluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXQsIGVudGlyZSB3aWR0aCBvZiBjZW50ZXIgb2YgZmluZGVyIHBhdHRlcm5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNraXAgYnkgcm93U2tpcCwgYnV0IGJhY2sgb2ZmIGJ5IHN0YXRlQ291bnRbMl0gKHNpemUgb2YgbGFzdCBjZW50ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9mIHBhdHRlcm4gd2Ugc2F3KSB0byBiZSBjb25zZXJ2YXRpdmUsIGFuZCBhbHNvIGJhY2sgb2ZmIGJ5IGlTa2lwIHdoaWNoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpcyBhYm91dCB0byBiZSByZS1hZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaSArPSByb3dTa2lwIC0gc3RhdGVDb3VudFsyXSAtIGlTa2lwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaiA9IG1heEogLSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFswXSA9IHN0YXRlQ291bnRbMl07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFsxXSA9IHN0YXRlQ291bnRbM107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFsyXSA9IHN0YXRlQ291bnRbNF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFszXSA9IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFs0XSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFN0YXRlID0gMztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENsZWFyIHN0YXRlIHRvIHN0YXJ0IGxvb2tpbmcgYWdhaW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTdGF0ZSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzBdID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMV0gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFsyXSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzNdID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbNF0gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgeyAvLyBObywgc2hpZnQgY291bnRzIGJhY2sgYnkgdHdvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzBdID0gc3RhdGVDb3VudFsyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMV0gPSBzdGF0ZUNvdW50WzNdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFsyXSA9IHN0YXRlQ291bnRbNF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzNdID0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbNF0gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFN0YXRlID0gMztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFsrK2N1cnJlbnRTdGF0ZV0rKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHsgLy8gQ291bnRpbmcgd2hpdGUgcGl4ZWxzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVDb3VudFtjdXJyZW50U3RhdGVdKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKEZpbmRlclBhdHRlcm5GaW5kZXIuZm91bmRQYXR0ZXJuQ3Jvc3Moc3RhdGVDb3VudCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29uZmlybWVkID0gdGhpcy5oYW5kbGVQb3NzaWJsZUNlbnRlcihzdGF0ZUNvdW50LCBpLCBtYXhKLCBwdXJlQmFyY29kZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb25maXJtZWQgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlTa2lwID0gc3RhdGVDb3VudFswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmhhc1NraXBwZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGb3VuZCBhIHRoaXJkIG9uZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmUgPSB0aGlzLmhhdmVNdWx0aXBseUNvbmZpcm1lZENlbnRlcnMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHBhdHRlcm5JbmZvID0gdGhpcy5zZWxlY3RCZXN0UGF0dGVybnMoKTtcbiAgICAgICAgICAgIFJlc3VsdFBvaW50Lm9yZGVyQmVzdFBhdHRlcm5zKHBhdHRlcm5JbmZvKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRmluZGVyUGF0dGVybkluZm8ocGF0dGVybkluZm8pO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHaXZlbiBhIGNvdW50IG9mIGJsYWNrL3doaXRlL2JsYWNrL3doaXRlL2JsYWNrIHBpeGVscyBqdXN0IHNlZW4gYW5kIGFuIGVuZCBwb3NpdGlvbixcbiAgICAgICAgICogZmlndXJlcyB0aGUgbG9jYXRpb24gb2YgdGhlIGNlbnRlciBvZiB0aGlzIHJ1bi5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBjZW50ZXJGcm9tRW5kKHN0YXRlQ291bnQsIGVuZCAvKmludCovKSB7XG4gICAgICAgICAgICByZXR1cm4gKGVuZCAtIHN0YXRlQ291bnRbNF0gLSBzdGF0ZUNvdW50WzNdKSAtIHN0YXRlQ291bnRbMl0gLyAyLjA7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBzdGF0ZUNvdW50IGNvdW50IG9mIGJsYWNrL3doaXRlL2JsYWNrL3doaXRlL2JsYWNrIHBpeGVscyBqdXN0IHJlYWRcbiAgICAgICAgICogQHJldHVybiB0cnVlIGlmZiB0aGUgcHJvcG9ydGlvbnMgb2YgdGhlIGNvdW50cyBpcyBjbG9zZSBlbm91Z2ggdG8gdGhlIDEvMS8zLzEvMSByYXRpb3NcbiAgICAgICAgICogICAgICAgICB1c2VkIGJ5IGZpbmRlciBwYXR0ZXJucyB0byBiZSBjb25zaWRlcmVkIGEgbWF0Y2hcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBmb3VuZFBhdHRlcm5Dcm9zcyhzdGF0ZUNvdW50KSB7XG4gICAgICAgICAgICBsZXQgdG90YWxNb2R1bGVTaXplID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY291bnQgPSBzdGF0ZUNvdW50W2ldO1xuICAgICAgICAgICAgICAgIGlmIChjb3VudCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRvdGFsTW9kdWxlU2l6ZSArPSBjb3VudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0b3RhbE1vZHVsZVNpemUgPCA3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbW9kdWxlU2l6ZSA9IHRvdGFsTW9kdWxlU2l6ZSAvIDcuMDtcbiAgICAgICAgICAgIGNvbnN0IG1heFZhcmlhbmNlID0gbW9kdWxlU2l6ZSAvIDIuMDtcbiAgICAgICAgICAgIC8vIEFsbG93IGxlc3MgdGhhbiA1MCUgdmFyaWFuY2UgZnJvbSAxLTEtMy0xLTEgcHJvcG9ydGlvbnNcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmFicyhtb2R1bGVTaXplIC0gc3RhdGVDb3VudFswXSkgPCBtYXhWYXJpYW5jZSAmJlxuICAgICAgICAgICAgICAgIE1hdGguYWJzKG1vZHVsZVNpemUgLSBzdGF0ZUNvdW50WzFdKSA8IG1heFZhcmlhbmNlICYmXG4gICAgICAgICAgICAgICAgTWF0aC5hYnMoMy4wICogbW9kdWxlU2l6ZSAtIHN0YXRlQ291bnRbMl0pIDwgMyAqIG1heFZhcmlhbmNlICYmXG4gICAgICAgICAgICAgICAgTWF0aC5hYnMobW9kdWxlU2l6ZSAtIHN0YXRlQ291bnRbM10pIDwgbWF4VmFyaWFuY2UgJiZcbiAgICAgICAgICAgICAgICBNYXRoLmFicyhtb2R1bGVTaXplIC0gc3RhdGVDb3VudFs0XSkgPCBtYXhWYXJpYW5jZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRDcm9zc0NoZWNrU3RhdGVDb3VudCgpIHtcbiAgICAgICAgICAgIGNvbnN0IGNyb3NzQ2hlY2tTdGF0ZUNvdW50ID0gdGhpcy5jcm9zc0NoZWNrU3RhdGVDb3VudDtcbiAgICAgICAgICAgIGNyb3NzQ2hlY2tTdGF0ZUNvdW50WzBdID0gMDtcbiAgICAgICAgICAgIGNyb3NzQ2hlY2tTdGF0ZUNvdW50WzFdID0gMDtcbiAgICAgICAgICAgIGNyb3NzQ2hlY2tTdGF0ZUNvdW50WzJdID0gMDtcbiAgICAgICAgICAgIGNyb3NzQ2hlY2tTdGF0ZUNvdW50WzNdID0gMDtcbiAgICAgICAgICAgIGNyb3NzQ2hlY2tTdGF0ZUNvdW50WzRdID0gMDtcbiAgICAgICAgICAgIHJldHVybiBjcm9zc0NoZWNrU3RhdGVDb3VudDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQWZ0ZXIgYSB2ZXJ0aWNhbCBhbmQgaG9yaXpvbnRhbCBzY2FuIGZpbmRzIGEgcG90ZW50aWFsIGZpbmRlciBwYXR0ZXJuLCB0aGlzIG1ldGhvZFxuICAgICAgICAgKiBcImNyb3NzLWNyb3NzLWNyb3NzLWNoZWNrc1wiIGJ5IHNjYW5uaW5nIGRvd24gZGlhZ29uYWxseSB0aHJvdWdoIHRoZSBjZW50ZXIgb2YgdGhlIHBvc3NpYmxlXG4gICAgICAgICAqIGZpbmRlciBwYXR0ZXJuIHRvIHNlZSBpZiB0aGUgc2FtZSBwcm9wb3J0aW9uIGlzIGRldGVjdGVkLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gc3RhcnRJIHJvdyB3aGVyZSBhIGZpbmRlciBwYXR0ZXJuIHdhcyBkZXRlY3RlZFxuICAgICAgICAgKiBAcGFyYW0gY2VudGVySiBjZW50ZXIgb2YgdGhlIHNlY3Rpb24gdGhhdCBhcHBlYXJzIHRvIGNyb3NzIGEgZmluZGVyIHBhdHRlcm5cbiAgICAgICAgICogQHBhcmFtIG1heENvdW50IG1heGltdW0gcmVhc29uYWJsZSBudW1iZXIgb2YgbW9kdWxlcyB0aGF0IHNob3VsZCBiZVxuICAgICAgICAgKiAgb2JzZXJ2ZWQgaW4gYW55IHJlYWRpbmcgc3RhdGUsIGJhc2VkIG9uIHRoZSByZXN1bHRzIG9mIHRoZSBob3Jpem9udGFsIHNjYW5cbiAgICAgICAgICogQHBhcmFtIG9yaWdpbmFsU3RhdGVDb3VudFRvdGFsIFRoZSBvcmlnaW5hbCBzdGF0ZSBjb3VudCB0b3RhbC5cbiAgICAgICAgICogQHJldHVybiB0cnVlIGlmIHByb3BvcnRpb25zIGFyZSB3aXRoaW5nIGV4cGVjdGVkIGxpbWl0c1xuICAgICAgICAgKi9cbiAgICAgICAgY3Jvc3NDaGVja0RpYWdvbmFsKHN0YXJ0SSAvKmludCovLCBjZW50ZXJKIC8qaW50Ki8sIG1heENvdW50IC8qaW50Ki8sIG9yaWdpbmFsU3RhdGVDb3VudFRvdGFsIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IHN0YXRlQ291bnQgPSB0aGlzLmdldENyb3NzQ2hlY2tTdGF0ZUNvdW50KCk7XG4gICAgICAgICAgICAvLyBTdGFydCBjb3VudGluZyB1cCwgbGVmdCBmcm9tIGNlbnRlciBmaW5kaW5nIGJsYWNrIGNlbnRlciBtYXNzXG4gICAgICAgICAgICBsZXQgaSA9IDA7XG4gICAgICAgICAgICBjb25zdCBpbWFnZSA9IHRoaXMuaW1hZ2U7XG4gICAgICAgICAgICB3aGlsZSAoc3RhcnRJID49IGkgJiYgY2VudGVySiA+PSBpICYmIGltYWdlLmdldChjZW50ZXJKIC0gaSwgc3RhcnRJIC0gaSkpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzJdKys7XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0YXJ0SSA8IGkgfHwgY2VudGVySiA8IGkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBDb250aW51ZSB1cCwgbGVmdCBmaW5kaW5nIHdoaXRlIHNwYWNlXG4gICAgICAgICAgICB3aGlsZSAoc3RhcnRJID49IGkgJiYgY2VudGVySiA+PSBpICYmICFpbWFnZS5nZXQoY2VudGVySiAtIGksIHN0YXJ0SSAtIGkpICYmXG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFsxXSA8PSBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMV0rKztcbiAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBJZiBhbHJlYWR5IHRvbyBtYW55IG1vZHVsZXMgaW4gdGhpcyBzdGF0ZSBvciByYW4gb2ZmIHRoZSBlZGdlOlxuICAgICAgICAgICAgaWYgKHN0YXJ0SSA8IGkgfHwgY2VudGVySiA8IGkgfHwgc3RhdGVDb3VudFsxXSA+IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQ29udGludWUgdXAsIGxlZnQgZmluZGluZyBibGFjayBib3JkZXJcbiAgICAgICAgICAgIHdoaWxlIChzdGFydEkgPj0gaSAmJiBjZW50ZXJKID49IGkgJiYgaW1hZ2UuZ2V0KGNlbnRlckogLSBpLCBzdGFydEkgLSBpKSAmJlxuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMF0gPD0gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzBdKys7XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0YXRlQ291bnRbMF0gPiBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG1heEkgPSBpbWFnZS5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IG1heEogPSBpbWFnZS5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgLy8gTm93IGFsc28gY291bnQgZG93biwgcmlnaHQgZnJvbSBjZW50ZXJcbiAgICAgICAgICAgIGkgPSAxO1xuICAgICAgICAgICAgd2hpbGUgKHN0YXJ0SSArIGkgPCBtYXhJICYmIGNlbnRlckogKyBpIDwgbWF4SiAmJiBpbWFnZS5nZXQoY2VudGVySiArIGksIHN0YXJ0SSArIGkpKSB7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFsyXSsrO1xuICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFJhbiBvZmYgdGhlIGVkZ2U/XG4gICAgICAgICAgICBpZiAoc3RhcnRJICsgaSA+PSBtYXhJIHx8IGNlbnRlckogKyBpID49IG1heEopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aGlsZSAoc3RhcnRJICsgaSA8IG1heEkgJiYgY2VudGVySiArIGkgPCBtYXhKICYmICFpbWFnZS5nZXQoY2VudGVySiArIGksIHN0YXJ0SSArIGkpICYmXG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFszXSA8IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFszXSsrO1xuICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzdGFydEkgKyBpID49IG1heEkgfHwgY2VudGVySiArIGkgPj0gbWF4SiB8fCBzdGF0ZUNvdW50WzNdID49IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2hpbGUgKHN0YXJ0SSArIGkgPCBtYXhJICYmIGNlbnRlckogKyBpIDwgbWF4SiAmJiBpbWFnZS5nZXQoY2VudGVySiArIGksIHN0YXJ0SSArIGkpICYmXG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFs0XSA8IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFs0XSsrO1xuICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzdGF0ZUNvdW50WzRdID49IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSWYgd2UgZm91bmQgYSBmaW5kZXItcGF0dGVybi1saWtlIHNlY3Rpb24sIGJ1dCBpdHMgc2l6ZSBpcyBtb3JlIHRoYW4gMTAwJSBkaWZmZXJlbnQgdGhhblxuICAgICAgICAgICAgLy8gdGhlIG9yaWdpbmFsLCBhc3N1bWUgaXQncyBhIGZhbHNlIHBvc2l0aXZlXG4gICAgICAgICAgICBjb25zdCBzdGF0ZUNvdW50VG90YWwgPSBzdGF0ZUNvdW50WzBdICsgc3RhdGVDb3VudFsxXSArIHN0YXRlQ291bnRbMl0gKyBzdGF0ZUNvdW50WzNdICsgc3RhdGVDb3VudFs0XTtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmFicyhzdGF0ZUNvdW50VG90YWwgLSBvcmlnaW5hbFN0YXRlQ291bnRUb3RhbCkgPCAyICogb3JpZ2luYWxTdGF0ZUNvdW50VG90YWwgJiZcbiAgICAgICAgICAgICAgICBGaW5kZXJQYXR0ZXJuRmluZGVyLmZvdW5kUGF0dGVybkNyb3NzKHN0YXRlQ291bnQpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5BZnRlciBhIGhvcml6b250YWwgc2NhbiBmaW5kcyBhIHBvdGVudGlhbCBmaW5kZXIgcGF0dGVybiwgdGhpcyBtZXRob2RcbiAgICAgICAgICogXCJjcm9zcy1jaGVja3NcIiBieSBzY2FubmluZyBkb3duIHZlcnRpY2FsbHkgdGhyb3VnaCB0aGUgY2VudGVyIG9mIHRoZSBwb3NzaWJsZVxuICAgICAgICAgKiBmaW5kZXIgcGF0dGVybiB0byBzZWUgaWYgdGhlIHNhbWUgcHJvcG9ydGlvbiBpcyBkZXRlY3RlZC48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBzdGFydEkgcm93IHdoZXJlIGEgZmluZGVyIHBhdHRlcm4gd2FzIGRldGVjdGVkXG4gICAgICAgICAqIEBwYXJhbSBjZW50ZXJKIGNlbnRlciBvZiB0aGUgc2VjdGlvbiB0aGF0IGFwcGVhcnMgdG8gY3Jvc3MgYSBmaW5kZXIgcGF0dGVyblxuICAgICAgICAgKiBAcGFyYW0gbWF4Q291bnQgbWF4aW11bSByZWFzb25hYmxlIG51bWJlciBvZiBtb2R1bGVzIHRoYXQgc2hvdWxkIGJlXG4gICAgICAgICAqIG9ic2VydmVkIGluIGFueSByZWFkaW5nIHN0YXRlLCBiYXNlZCBvbiB0aGUgcmVzdWx0cyBvZiB0aGUgaG9yaXpvbnRhbCBzY2FuXG4gICAgICAgICAqIEByZXR1cm4gdmVydGljYWwgY2VudGVyIG9mIGZpbmRlciBwYXR0ZXJuLCBvciB7QGxpbmsgRmxvYXQjTmFOfSBpZiBub3QgZm91bmRcbiAgICAgICAgICovXG4gICAgICAgIGNyb3NzQ2hlY2tWZXJ0aWNhbChzdGFydEkgLyppbnQqLywgY2VudGVySiAvKmludCovLCBtYXhDb3VudCAvKmludCovLCBvcmlnaW5hbFN0YXRlQ291bnRUb3RhbCAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBpbWFnZSA9IHRoaXMuaW1hZ2U7XG4gICAgICAgICAgICBjb25zdCBtYXhJID0gaW1hZ2UuZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICBjb25zdCBzdGF0ZUNvdW50ID0gdGhpcy5nZXRDcm9zc0NoZWNrU3RhdGVDb3VudCgpO1xuICAgICAgICAgICAgLy8gU3RhcnQgY291bnRpbmcgdXAgZnJvbSBjZW50ZXJcbiAgICAgICAgICAgIGxldCBpID0gc3RhcnRJO1xuICAgICAgICAgICAgd2hpbGUgKGkgPj0gMCAmJiBpbWFnZS5nZXQoY2VudGVySiwgaSkpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzJdKys7XG4gICAgICAgICAgICAgICAgaS0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGkgPCAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdoaWxlIChpID49IDAgJiYgIWltYWdlLmdldChjZW50ZXJKLCBpKSAmJiBzdGF0ZUNvdW50WzFdIDw9IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFsxXSsrO1xuICAgICAgICAgICAgICAgIGktLTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIElmIGFscmVhZHkgdG9vIG1hbnkgbW9kdWxlcyBpbiB0aGlzIHN0YXRlIG9yIHJhbiBvZmYgdGhlIGVkZ2U6XG4gICAgICAgICAgICBpZiAoaSA8IDAgfHwgc3RhdGVDb3VudFsxXSA+IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdoaWxlIChpID49IDAgJiYgaW1hZ2UuZ2V0KGNlbnRlckosIGkpICYmIHN0YXRlQ291bnRbMF0gPD0gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzBdKys7XG4gICAgICAgICAgICAgICAgaS0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0YXRlQ291bnRbMF0gPiBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBOb3cgYWxzbyBjb3VudCBkb3duIGZyb20gY2VudGVyXG4gICAgICAgICAgICBpID0gc3RhcnRJICsgMTtcbiAgICAgICAgICAgIHdoaWxlIChpIDwgbWF4SSAmJiBpbWFnZS5nZXQoY2VudGVySiwgaSkpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzJdKys7XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGkgPT09IG1heEkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2hpbGUgKGkgPCBtYXhJICYmICFpbWFnZS5nZXQoY2VudGVySiwgaSkgJiYgc3RhdGVDb3VudFszXSA8IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFszXSsrO1xuICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpID09PSBtYXhJIHx8IHN0YXRlQ291bnRbM10gPj0gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2hpbGUgKGkgPCBtYXhJICYmIGltYWdlLmdldChjZW50ZXJKLCBpKSAmJiBzdGF0ZUNvdW50WzRdIDwgbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzRdKys7XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0YXRlQ291bnRbNF0gPj0gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSWYgd2UgZm91bmQgYSBmaW5kZXItcGF0dGVybi1saWtlIHNlY3Rpb24sIGJ1dCBpdHMgc2l6ZSBpcyBtb3JlIHRoYW4gNDAlIGRpZmZlcmVudCB0aGFuXG4gICAgICAgICAgICAvLyB0aGUgb3JpZ2luYWwsIGFzc3VtZSBpdCdzIGEgZmFsc2UgcG9zaXRpdmVcbiAgICAgICAgICAgIGNvbnN0IHN0YXRlQ291bnRUb3RhbCA9IHN0YXRlQ291bnRbMF0gKyBzdGF0ZUNvdW50WzFdICsgc3RhdGVDb3VudFsyXSArIHN0YXRlQ291bnRbM10gK1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbNF07XG4gICAgICAgICAgICBpZiAoNSAqIE1hdGguYWJzKHN0YXRlQ291bnRUb3RhbCAtIG9yaWdpbmFsU3RhdGVDb3VudFRvdGFsKSA+PSAyICogb3JpZ2luYWxTdGF0ZUNvdW50VG90YWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIEZpbmRlclBhdHRlcm5GaW5kZXIuZm91bmRQYXR0ZXJuQ3Jvc3Moc3RhdGVDb3VudCkgPyBGaW5kZXJQYXR0ZXJuRmluZGVyLmNlbnRlckZyb21FbmQoc3RhdGVDb3VudCwgaSkgOiBOYU47XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkxpa2Uge0BsaW5rICNjcm9zc0NoZWNrVmVydGljYWwoaW50LCBpbnQsIGludCwgaW50KX0sIGFuZCBpbiBmYWN0IGlzIGJhc2ljYWxseSBpZGVudGljYWwsXG4gICAgICAgICAqIGV4Y2VwdCBpdCByZWFkcyBob3Jpem9udGFsbHkgaW5zdGVhZCBvZiB2ZXJ0aWNhbGx5LiBUaGlzIGlzIHVzZWQgdG8gY3Jvc3MtY3Jvc3NcbiAgICAgICAgICogY2hlY2sgYSB2ZXJ0aWNhbCBjcm9zcyBjaGVjayBhbmQgbG9jYXRlIHRoZSByZWFsIGNlbnRlciBvZiB0aGUgYWxpZ25tZW50IHBhdHRlcm4uPC9wPlxuICAgICAgICAgKi9cbiAgICAgICAgY3Jvc3NDaGVja0hvcml6b250YWwoc3RhcnRKIC8qaW50Ki8sIGNlbnRlckkgLyppbnQqLywgbWF4Q291bnQgLyppbnQqLywgb3JpZ2luYWxTdGF0ZUNvdW50VG90YWwgLyppbnQqLykge1xuICAgICAgICAgICAgY29uc3QgaW1hZ2UgPSB0aGlzLmltYWdlO1xuICAgICAgICAgICAgY29uc3QgbWF4SiA9IGltYWdlLmdldFdpZHRoKCk7XG4gICAgICAgICAgICBjb25zdCBzdGF0ZUNvdW50ID0gdGhpcy5nZXRDcm9zc0NoZWNrU3RhdGVDb3VudCgpO1xuICAgICAgICAgICAgbGV0IGogPSBzdGFydEo7XG4gICAgICAgICAgICB3aGlsZSAoaiA+PSAwICYmIGltYWdlLmdldChqLCBjZW50ZXJJKSkge1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbMl0rKztcbiAgICAgICAgICAgICAgICBqLS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaiA8IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2hpbGUgKGogPj0gMCAmJiAhaW1hZ2UuZ2V0KGosIGNlbnRlckkpICYmIHN0YXRlQ291bnRbMV0gPD0gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzFdKys7XG4gICAgICAgICAgICAgICAgai0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGogPCAwIHx8IHN0YXRlQ291bnRbMV0gPiBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aGlsZSAoaiA+PSAwICYmIGltYWdlLmdldChqLCBjZW50ZXJJKSAmJiBzdGF0ZUNvdW50WzBdIDw9IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFswXSsrO1xuICAgICAgICAgICAgICAgIGotLTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzdGF0ZUNvdW50WzBdID4gbWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaiA9IHN0YXJ0SiArIDE7XG4gICAgICAgICAgICB3aGlsZSAoaiA8IG1heEogJiYgaW1hZ2UuZ2V0KGosIGNlbnRlckkpKSB7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFsyXSsrO1xuICAgICAgICAgICAgICAgIGorKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChqID09PSBtYXhKKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdoaWxlIChqIDwgbWF4SiAmJiAhaW1hZ2UuZ2V0KGosIGNlbnRlckkpICYmIHN0YXRlQ291bnRbM10gPCBtYXhDb3VudCkge1xuICAgICAgICAgICAgICAgIHN0YXRlQ291bnRbM10rKztcbiAgICAgICAgICAgICAgICBqKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaiA9PT0gbWF4SiB8fCBzdGF0ZUNvdW50WzNdID49IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdoaWxlIChqIDwgbWF4SiAmJiBpbWFnZS5nZXQoaiwgY2VudGVySSkgJiYgc3RhdGVDb3VudFs0XSA8IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgc3RhdGVDb3VudFs0XSsrO1xuICAgICAgICAgICAgICAgIGorKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzdGF0ZUNvdW50WzRdID49IG1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIElmIHdlIGZvdW5kIGEgZmluZGVyLXBhdHRlcm4tbGlrZSBzZWN0aW9uLCBidXQgaXRzIHNpemUgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgdGhhblxuICAgICAgICAgICAgLy8gdGhlIG9yaWdpbmFsLCBhc3N1bWUgaXQncyBhIGZhbHNlIHBvc2l0aXZlXG4gICAgICAgICAgICBjb25zdCBzdGF0ZUNvdW50VG90YWwgPSBzdGF0ZUNvdW50WzBdICsgc3RhdGVDb3VudFsxXSArIHN0YXRlQ291bnRbMl0gKyBzdGF0ZUNvdW50WzNdICtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzRdO1xuICAgICAgICAgICAgaWYgKDUgKiBNYXRoLmFicyhzdGF0ZUNvdW50VG90YWwgLSBvcmlnaW5hbFN0YXRlQ291bnRUb3RhbCkgPj0gb3JpZ2luYWxTdGF0ZUNvdW50VG90YWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIEZpbmRlclBhdHRlcm5GaW5kZXIuZm91bmRQYXR0ZXJuQ3Jvc3Moc3RhdGVDb3VudCkgPyBGaW5kZXJQYXR0ZXJuRmluZGVyLmNlbnRlckZyb21FbmQoc3RhdGVDb3VudCwgaikgOiBOYU47XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPlRoaXMgaXMgY2FsbGVkIHdoZW4gYSBob3Jpem9udGFsIHNjYW4gZmluZHMgYSBwb3NzaWJsZSBhbGlnbm1lbnQgcGF0dGVybi4gSXQgd2lsbFxuICAgICAgICAgKiBjcm9zcyBjaGVjayB3aXRoIGEgdmVydGljYWwgc2NhbiwgYW5kIGlmIHN1Y2Nlc3NmdWwsIHdpbGwsIGFoLCBjcm9zcy1jcm9zcy1jaGVja1xuICAgICAgICAgKiB3aXRoIGFub3RoZXIgaG9yaXpvbnRhbCBzY2FuLiBUaGlzIGlzIG5lZWRlZCBwcmltYXJpbHkgdG8gbG9jYXRlIHRoZSByZWFsIGhvcml6b250YWxcbiAgICAgICAgICogY2VudGVyIG9mIHRoZSBwYXR0ZXJuIGluIGNhc2VzIG9mIGV4dHJlbWUgc2tldy5cbiAgICAgICAgICogQW5kIHRoZW4gd2UgY3Jvc3MtY3Jvc3MtY3Jvc3MgY2hlY2sgd2l0aCBhbm90aGVyIGRpYWdvbmFsIHNjYW4uPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiA8cD5JZiB0aGF0IHN1Y2NlZWRzIHRoZSBmaW5kZXIgcGF0dGVybiBsb2NhdGlvbiBpcyBhZGRlZCB0byBhIGxpc3QgdGhhdCB0cmFja3NcbiAgICAgICAgICogdGhlIG51bWJlciBvZiB0aW1lcyBlYWNoIGxvY2F0aW9uIGhhcyBiZWVuIG5lYXJseS1tYXRjaGVkIGFzIGEgZmluZGVyIHBhdHRlcm4uXG4gICAgICAgICAqIEVhY2ggYWRkaXRpb25hbCBmaW5kIGlzIG1vcmUgZXZpZGVuY2UgdGhhdCB0aGUgbG9jYXRpb24gaXMgaW4gZmFjdCBhIGZpbmRlclxuICAgICAgICAgKiBwYXR0ZXJuIGNlbnRlclxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gc3RhdGVDb3VudCByZWFkaW5nIHN0YXRlIG1vZHVsZSBjb3VudHMgZnJvbSBob3Jpem9udGFsIHNjYW5cbiAgICAgICAgICogQHBhcmFtIGkgcm93IHdoZXJlIGZpbmRlciBwYXR0ZXJuIG1heSBiZSBmb3VuZFxuICAgICAgICAgKiBAcGFyYW0gaiBlbmQgb2YgcG9zc2libGUgZmluZGVyIHBhdHRlcm4gaW4gcm93XG4gICAgICAgICAqIEBwYXJhbSBwdXJlQmFyY29kZSB0cnVlIGlmIGluIFwicHVyZSBiYXJjb2RlXCIgbW9kZVxuICAgICAgICAgKiBAcmV0dXJuIHRydWUgaWYgYSBmaW5kZXIgcGF0dGVybiBjYW5kaWRhdGUgd2FzIGZvdW5kIHRoaXMgdGltZVxuICAgICAgICAgKi9cbiAgICAgICAgaGFuZGxlUG9zc2libGVDZW50ZXIoc3RhdGVDb3VudCwgaSAvKmludCovLCBqIC8qaW50Ki8sIHB1cmVCYXJjb2RlKSB7XG4gICAgICAgICAgICBjb25zdCBzdGF0ZUNvdW50VG90YWwgPSBzdGF0ZUNvdW50WzBdICsgc3RhdGVDb3VudFsxXSArIHN0YXRlQ291bnRbMl0gKyBzdGF0ZUNvdW50WzNdICtcbiAgICAgICAgICAgICAgICBzdGF0ZUNvdW50WzRdO1xuICAgICAgICAgICAgbGV0IGNlbnRlckogPSBGaW5kZXJQYXR0ZXJuRmluZGVyLmNlbnRlckZyb21FbmQoc3RhdGVDb3VudCwgaik7XG4gICAgICAgICAgICBsZXQgY2VudGVySSA9IHRoaXMuY3Jvc3NDaGVja1ZlcnRpY2FsKGksIC8qKGludCkgKi8gTWF0aC5mbG9vcihjZW50ZXJKKSwgc3RhdGVDb3VudFsyXSwgc3RhdGVDb3VudFRvdGFsKTtcbiAgICAgICAgICAgIGlmICghaXNOYU4oY2VudGVySSkpIHtcbiAgICAgICAgICAgICAgICAvLyBSZS1jcm9zcyBjaGVja1xuICAgICAgICAgICAgICAgIGNlbnRlckogPSB0aGlzLmNyb3NzQ2hlY2tIb3Jpem9udGFsKC8qKGludCkgKi8gTWF0aC5mbG9vcihjZW50ZXJKKSwgLyooaW50KSAqLyBNYXRoLmZsb29yKGNlbnRlckkpLCBzdGF0ZUNvdW50WzJdLCBzdGF0ZUNvdW50VG90YWwpO1xuICAgICAgICAgICAgICAgIGlmICghaXNOYU4oY2VudGVySikgJiZcbiAgICAgICAgICAgICAgICAgICAgKCFwdXJlQmFyY29kZSB8fCB0aGlzLmNyb3NzQ2hlY2tEaWFnb25hbCgvKihpbnQpICovIE1hdGguZmxvb3IoY2VudGVySSksIC8qKGludCkgKi8gTWF0aC5mbG9vcihjZW50ZXJKKSwgc3RhdGVDb3VudFsyXSwgc3RhdGVDb3VudFRvdGFsKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXN0aW1hdGVkTW9kdWxlU2l6ZSA9IHN0YXRlQ291bnRUb3RhbCAvIDcuMDtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGZvdW5kID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvc3NpYmxlQ2VudGVycyA9IHRoaXMucG9zc2libGVDZW50ZXJzO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpbmRleCA9IDAsIGxlbmd0aCA9IHBvc3NpYmxlQ2VudGVycy5sZW5ndGg7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjZW50ZXIgPSBwb3NzaWJsZUNlbnRlcnNbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTG9vayBmb3IgYWJvdXQgdGhlIHNhbWUgY2VudGVyIGFuZCBtb2R1bGUgc2l6ZTpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjZW50ZXIuYWJvdXRFcXVhbHMoZXN0aW1hdGVkTW9kdWxlU2l6ZSwgY2VudGVySSwgY2VudGVySikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NzaWJsZUNlbnRlcnNbaW5kZXhdID0gY2VudGVyLmNvbWJpbmVFc3RpbWF0ZShjZW50ZXJJLCBjZW50ZXJKLCBlc3RpbWF0ZWRNb2R1bGVTaXplKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFmb3VuZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9pbnQgPSBuZXcgRmluZGVyUGF0dGVybiQxKGNlbnRlckosIGNlbnRlckksIGVzdGltYXRlZE1vZHVsZVNpemUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zc2libGVDZW50ZXJzLnB1c2gocG9pbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMucmVzdWx0UG9pbnRDYWxsYmFjayAhPT0gbnVsbCAmJiB0aGlzLnJlc3VsdFBvaW50Q2FsbGJhY2sgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVzdWx0UG9pbnRDYWxsYmFjay5mb3VuZFBvc3NpYmxlUmVzdWx0UG9pbnQocG9pbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBudW1iZXIgb2Ygcm93cyB3ZSBjb3VsZCBzYWZlbHkgc2tpcCBkdXJpbmcgc2Nhbm5pbmcsIGJhc2VkIG9uIHRoZSBmaXJzdFxuICAgICAgICAgKiAgICAgICAgIHR3byBmaW5kZXIgcGF0dGVybnMgdGhhdCBoYXZlIGJlZW4gbG9jYXRlZC4gSW4gc29tZSBjYXNlcyB0aGVpciBwb3NpdGlvbiB3aWxsXG4gICAgICAgICAqICAgICAgICAgYWxsb3cgdXMgdG8gaW5mZXIgdGhhdCB0aGUgdGhpcmQgcGF0dGVybiBtdXN0IGxpZSBiZWxvdyBhIGNlcnRhaW4gcG9pbnQgZmFydGhlclxuICAgICAgICAgKiAgICAgICAgIGRvd24gaW4gdGhlIGltYWdlLlxuICAgICAgICAgKi9cbiAgICAgICAgZmluZFJvd1NraXAoKSB7XG4gICAgICAgICAgICBjb25zdCBtYXggPSB0aGlzLnBvc3NpYmxlQ2VudGVycy5sZW5ndGg7XG4gICAgICAgICAgICBpZiAobWF4IDw9IDEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBmaXJzdENvbmZpcm1lZENlbnRlciA9IG51bGw7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNlbnRlciBvZiB0aGlzLnBvc3NpYmxlQ2VudGVycykge1xuICAgICAgICAgICAgICAgIGlmIChjZW50ZXIuZ2V0Q291bnQoKSA+PSBGaW5kZXJQYXR0ZXJuRmluZGVyLkNFTlRFUl9RVU9SVU0pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpcnN0Q29uZmlybWVkQ2VudGVyID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpcnN0Q29uZmlybWVkQ2VudGVyID0gY2VudGVyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgaGF2ZSB0d28gY29uZmlybWVkIGNlbnRlcnNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhvdyBmYXIgZG93biBjYW4gd2Ugc2tpcCBiZWZvcmUgcmVzdW1pbmcgbG9va2luZyBmb3IgdGhlIG5leHRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHBhdHRlcm4/IEluIHRoZSB3b3JzdCBjYXNlLCBvbmx5IHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBkaWZmZXJlbmNlIGluIHRoZSB4IC8geSBjb29yZGluYXRlcyBvZiB0aGUgdHdvIGNlbnRlcnMuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIHRoZSBjYXNlIHdoZXJlIHlvdSBmaW5kIHRvcCBsZWZ0IGxhc3QuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhhc1NraXBwZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIC8qKGludCkgKi8gTWF0aC5mbG9vcigoTWF0aC5hYnMoZmlyc3RDb25maXJtZWRDZW50ZXIuZ2V0WCgpIC0gY2VudGVyLmdldFgoKSkgLVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1hdGguYWJzKGZpcnN0Q29uZmlybWVkQ2VudGVyLmdldFkoKSAtIGNlbnRlci5nZXRZKCkpKSAvIDIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gdHJ1ZSBpZmYgd2UgaGF2ZSBmb3VuZCBhdCBsZWFzdCAzIGZpbmRlciBwYXR0ZXJucyB0aGF0IGhhdmUgYmVlbiBkZXRlY3RlZFxuICAgICAgICAgKiAgICAgICAgIGF0IGxlYXN0IHtAbGluayAjQ0VOVEVSX1FVT1JVTX0gdGltZXMgZWFjaCwgYW5kLCB0aGUgZXN0aW1hdGVkIG1vZHVsZSBzaXplIG9mIHRoZVxuICAgICAgICAgKiAgICAgICAgIGNhbmRpZGF0ZXMgaXMgXCJwcmV0dHkgc2ltaWxhclwiXG4gICAgICAgICAqL1xuICAgICAgICBoYXZlTXVsdGlwbHlDb25maXJtZWRDZW50ZXJzKCkge1xuICAgICAgICAgICAgbGV0IGNvbmZpcm1lZENvdW50ID0gMDtcbiAgICAgICAgICAgIGxldCB0b3RhbE1vZHVsZVNpemUgPSAwLjA7XG4gICAgICAgICAgICBjb25zdCBtYXggPSB0aGlzLnBvc3NpYmxlQ2VudGVycy5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHBhdHRlcm4gb2YgdGhpcy5wb3NzaWJsZUNlbnRlcnMpIHtcbiAgICAgICAgICAgICAgICBpZiAocGF0dGVybi5nZXRDb3VudCgpID49IEZpbmRlclBhdHRlcm5GaW5kZXIuQ0VOVEVSX1FVT1JVTSkge1xuICAgICAgICAgICAgICAgICAgICBjb25maXJtZWRDb3VudCsrO1xuICAgICAgICAgICAgICAgICAgICB0b3RhbE1vZHVsZVNpemUgKz0gcGF0dGVybi5nZXRFc3RpbWF0ZWRNb2R1bGVTaXplKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvbmZpcm1lZENvdW50IDwgMykge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE9LLCB3ZSBoYXZlIGF0IGxlYXN0IDMgY29uZmlybWVkIGNlbnRlcnMsIGJ1dCwgaXQncyBwb3NzaWJsZSB0aGF0IG9uZSBpcyBhIFwiZmFsc2UgcG9zaXRpdmVcIlxuICAgICAgICAgICAgLy8gYW5kIHRoYXQgd2UgbmVlZCB0byBrZWVwIGxvb2tpbmcuIFdlIGRldGVjdCB0aGlzIGJ5IGFza2luZyBpZiB0aGUgZXN0aW1hdGVkIG1vZHVsZSBzaXplc1xuICAgICAgICAgICAgLy8gdmFyeSB0b28gbXVjaC4gV2UgYXJiaXRyYXJpbHkgc2F5IHRoYXQgd2hlbiB0aGUgdG90YWwgZGV2aWF0aW9uIGZyb20gYXZlcmFnZSBleGNlZWRzXG4gICAgICAgICAgICAvLyA1JSBvZiB0aGUgdG90YWwgbW9kdWxlIHNpemUgZXN0aW1hdGVzLCBpdCdzIHRvbyBtdWNoLlxuICAgICAgICAgICAgY29uc3QgYXZlcmFnZSA9IHRvdGFsTW9kdWxlU2l6ZSAvIG1heDtcbiAgICAgICAgICAgIGxldCB0b3RhbERldmlhdGlvbiA9IDAuMDtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcGF0dGVybiBvZiB0aGlzLnBvc3NpYmxlQ2VudGVycykge1xuICAgICAgICAgICAgICAgIHRvdGFsRGV2aWF0aW9uICs9IE1hdGguYWJzKHBhdHRlcm4uZ2V0RXN0aW1hdGVkTW9kdWxlU2l6ZSgpIC0gYXZlcmFnZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdG90YWxEZXZpYXRpb24gPD0gMC4wNSAqIHRvdGFsTW9kdWxlU2l6ZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB0aGUgMyBiZXN0IHtAbGluayBGaW5kZXJQYXR0ZXJufXMgZnJvbSBvdXIgbGlzdCBvZiBjYW5kaWRhdGVzLiBUaGUgXCJiZXN0XCIgYXJlXG4gICAgICAgICAqICAgICAgICAgdGhvc2UgdGhhdCBoYXZlIGJlZW4gZGV0ZWN0ZWQgYXQgbGVhc3Qge0BsaW5rICNDRU5URVJfUVVPUlVNfSB0aW1lcywgYW5kIHdob3NlIG1vZHVsZVxuICAgICAgICAgKiAgICAgICAgIHNpemUgZGlmZmVycyBmcm9tIHRoZSBhdmVyYWdlIGFtb25nIHRob3NlIHBhdHRlcm5zIHRoZSBsZWFzdFxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIDMgc3VjaCBmaW5kZXIgcGF0dGVybnMgZG8gbm90IGV4aXN0XG4gICAgICAgICAqL1xuICAgICAgICBzZWxlY3RCZXN0UGF0dGVybnMoKSB7XG4gICAgICAgICAgICBjb25zdCBzdGFydFNpemUgPSB0aGlzLnBvc3NpYmxlQ2VudGVycy5sZW5ndGg7XG4gICAgICAgICAgICBpZiAoc3RhcnRTaXplIDwgMykge1xuICAgICAgICAgICAgICAgIC8vIENvdWxkbid0IGZpbmQgZW5vdWdoIGZpbmRlciBwYXR0ZXJuc1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcG9zc2libGVDZW50ZXJzID0gdGhpcy5wb3NzaWJsZUNlbnRlcnM7XG4gICAgICAgICAgICBsZXQgYXZlcmFnZTtcbiAgICAgICAgICAgIC8vIEZpbHRlciBvdXRsaWVyIHBvc3NpYmlsaXRpZXMgd2hvc2UgbW9kdWxlIHNpemUgaXMgdG9vIGRpZmZlcmVudFxuICAgICAgICAgICAgaWYgKHN0YXJ0U2l6ZSA+IDMpIHtcbiAgICAgICAgICAgICAgICAvLyBCdXQgd2UgY2FuIG9ubHkgYWZmb3JkIHRvIGRvIHNvIGlmIHdlIGhhdmUgYXQgbGVhc3QgNCBwb3NzaWJpbGl0aWVzIHRvIGNob29zZSBmcm9tXG4gICAgICAgICAgICAgICAgbGV0IHRvdGFsTW9kdWxlU2l6ZSA9IDAuMDtcbiAgICAgICAgICAgICAgICBsZXQgc3F1YXJlID0gMC4wO1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgY2VudGVyIG9mIHRoaXMucG9zc2libGVDZW50ZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNpemUgPSBjZW50ZXIuZ2V0RXN0aW1hdGVkTW9kdWxlU2l6ZSgpO1xuICAgICAgICAgICAgICAgICAgICB0b3RhbE1vZHVsZVNpemUgKz0gc2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgc3F1YXJlICs9IHNpemUgKiBzaXplO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhdmVyYWdlID0gdG90YWxNb2R1bGVTaXplIC8gc3RhcnRTaXplO1xuICAgICAgICAgICAgICAgIGxldCBzdGREZXYgPSBNYXRoLnNxcnQoc3F1YXJlIC8gc3RhcnRTaXplIC0gYXZlcmFnZSAqIGF2ZXJhZ2UpO1xuICAgICAgICAgICAgICAgIHBvc3NpYmxlQ2VudGVycy5zb3J0KFxuICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAqIDxwPk9yZGVycyBieSBmdXJ0aGVzdCBmcm9tIGF2ZXJhZ2U8L3A+XG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgLy8gRnVydGhlc3RGcm9tQXZlcmFnZUNvbXBhcmF0b3IgaW1wbGVtZW50cyBDb21wYXJhdG9yPEZpbmRlclBhdHRlcm4+XG4gICAgICAgICAgICAgICAgKGNlbnRlcjEsIGNlbnRlcjIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZEEgPSBNYXRoLmFicyhjZW50ZXIyLmdldEVzdGltYXRlZE1vZHVsZVNpemUoKSAtIGF2ZXJhZ2UpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkQiA9IE1hdGguYWJzKGNlbnRlcjEuZ2V0RXN0aW1hdGVkTW9kdWxlU2l6ZSgpIC0gYXZlcmFnZSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkQSA8IGRCID8gLTEgOiBkQSA+IGRCID8gMSA6IDA7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgY29uc3QgbGltaXQgPSBNYXRoLm1heCgwLjIgKiBhdmVyYWdlLCBzdGREZXYpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcG9zc2libGVDZW50ZXJzLmxlbmd0aCAmJiBwb3NzaWJsZUNlbnRlcnMubGVuZ3RoID4gMzsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhdHRlcm4gPSBwb3NzaWJsZUNlbnRlcnNbaV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChNYXRoLmFicyhwYXR0ZXJuLmdldEVzdGltYXRlZE1vZHVsZVNpemUoKSAtIGF2ZXJhZ2UpID4gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc3NpYmxlQ2VudGVycy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpLS07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocG9zc2libGVDZW50ZXJzLmxlbmd0aCA+IDMpIHtcbiAgICAgICAgICAgICAgICAvLyBUaHJvdyBhd2F5IGFsbCBidXQgdGhvc2UgZmlyc3Qgc2l6ZSBjYW5kaWRhdGUgcG9pbnRzIHdlIGZvdW5kLlxuICAgICAgICAgICAgICAgIGxldCB0b3RhbE1vZHVsZVNpemUgPSAwLjA7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBwb3NzaWJsZUNlbnRlciBvZiBwb3NzaWJsZUNlbnRlcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgdG90YWxNb2R1bGVTaXplICs9IHBvc3NpYmxlQ2VudGVyLmdldEVzdGltYXRlZE1vZHVsZVNpemUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYXZlcmFnZSA9IHRvdGFsTW9kdWxlU2l6ZSAvIHBvc3NpYmxlQ2VudGVycy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgcG9zc2libGVDZW50ZXJzLnNvcnQoXG4gICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICogPHA+T3JkZXJzIGJ5IHtAbGluayBGaW5kZXJQYXR0ZXJuI2dldENvdW50KCl9LCBkZXNjZW5kaW5nLjwvcD5cbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAvLyBDZW50ZXJDb21wYXJhdG9yIGltcGxlbWVudHMgQ29tcGFyYXRvcjxGaW5kZXJQYXR0ZXJuPlxuICAgICAgICAgICAgICAgIChjZW50ZXIxLCBjZW50ZXIyKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjZW50ZXIyLmdldENvdW50KCkgPT09IGNlbnRlcjEuZ2V0Q291bnQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZEEgPSBNYXRoLmFicyhjZW50ZXIyLmdldEVzdGltYXRlZE1vZHVsZVNpemUoKSAtIGF2ZXJhZ2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZEIgPSBNYXRoLmFicyhjZW50ZXIxLmdldEVzdGltYXRlZE1vZHVsZVNpemUoKSAtIGF2ZXJhZ2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRBIDwgZEIgPyAxIDogZEEgPiBkQiA/IC0xIDogMDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjZW50ZXIyLmdldENvdW50KCkgLSBjZW50ZXIxLmdldENvdW50KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBwb3NzaWJsZUNlbnRlcnMuc3BsaWNlKDMpOyAvLyB0aGlzIGlzIG5vdCByZWFseSBuZWNlc3NhcnkgYXMgd2Ugb25seSByZXR1cm4gZmlyc3QgMyBhbnl3YXlcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAgcG9zc2libGVDZW50ZXJzWzBdLFxuICAgICAgICAgICAgICAgIHBvc3NpYmxlQ2VudGVyc1sxXSxcbiAgICAgICAgICAgICAgICBwb3NzaWJsZUNlbnRlcnNbMl1cbiAgICAgICAgICAgIF07XG4gICAgICAgIH1cbiAgICB9XG4gICAgRmluZGVyUGF0dGVybkZpbmRlci5DRU5URVJfUVVPUlVNID0gMjtcbiAgICBGaW5kZXJQYXR0ZXJuRmluZGVyLk1JTl9TS0lQID0gMzsgLy8gMSBwaXhlbC9tb2R1bGUgdGltZXMgMyBtb2R1bGVzL2NlbnRlclxuICAgIEZpbmRlclBhdHRlcm5GaW5kZXIuTUFYX01PRFVMRVMgPSA1NzsgLy8gc3VwcG9ydCB1cCB0byB2ZXJzaW9uIDEwIGZvciBtb2JpbGUgY2xpZW50c1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKmltcG9ydCBqYXZhLnV0aWwuTWFwOyovXG4gICAgLyoqXG4gICAgICogPHA+RW5jYXBzdWxhdGVzIGxvZ2ljIHRoYXQgY2FuIGRldGVjdCBhIFFSIENvZGUgaW4gYW4gaW1hZ2UsIGV2ZW4gaWYgdGhlIFFSIENvZGVcbiAgICAgKiBpcyByb3RhdGVkIG9yIHNrZXdlZCwgb3IgcGFydGlhbGx5IG9ic2N1cmVkLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICovXG4gICAgY2xhc3MgRGV0ZWN0b3IkMiB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGltYWdlKSB7XG4gICAgICAgICAgICB0aGlzLmltYWdlID0gaW1hZ2U7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0SW1hZ2UoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5pbWFnZTtcbiAgICAgICAgfVxuICAgICAgICBnZXRSZXN1bHRQb2ludENhbGxiYWNrKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVzdWx0UG9pbnRDYWxsYmFjaztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+RGV0ZWN0cyBhIFFSIENvZGUgaW4gYW4gaW1hZ2UuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIHtAbGluayBEZXRlY3RvclJlc3VsdH0gZW5jYXBzdWxhdGluZyByZXN1bHRzIG9mIGRldGVjdGluZyBhIFFSIENvZGVcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBpZiBRUiBDb2RlIGNhbm5vdCBiZSBmb3VuZFxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvbiBpZiBhIFFSIENvZGUgY2Fubm90IGJlIGRlY29kZWRcbiAgICAgICAgICovXG4gICAgICAgIC8vIHB1YmxpYyBkZXRlY3QoKTogRGV0ZWN0b3JSZXN1bHQgLyp0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24sIEZvcm1hdEV4Y2VwdGlvbiovIHtcbiAgICAgICAgLy8gICByZXR1cm4gZGV0ZWN0KG51bGwpXG4gICAgICAgIC8vIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkRldGVjdHMgYSBRUiBDb2RlIGluIGFuIGltYWdlLjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGhpbnRzIG9wdGlvbmFsIGhpbnRzIHRvIGRldGVjdG9yXG4gICAgICAgICAqIEByZXR1cm4ge0BsaW5rIERldGVjdG9yUmVzdWx0fSBlbmNhcHN1bGF0aW5nIHJlc3VsdHMgb2YgZGV0ZWN0aW5nIGEgUVIgQ29kZVxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIFFSIENvZGUgY2Fubm90IGJlIGZvdW5kXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uIGlmIGEgUVIgQ29kZSBjYW5ub3QgYmUgZGVjb2RlZFxuICAgICAgICAgKi9cbiAgICAgICAgZGV0ZWN0KGhpbnRzKSB7XG4gICAgICAgICAgICB0aGlzLnJlc3VsdFBvaW50Q2FsbGJhY2sgPSAoaGludHMgPT09IG51bGwgfHwgaGludHMgPT09IHVuZGVmaW5lZCkgPyBudWxsIDpcbiAgICAgICAgICAgICAgICAvKihSZXN1bHRQb2ludENhbGxiYWNrKSAqLyBoaW50cy5nZXQoRGVjb2RlSGludFR5cGUkMS5ORUVEX1JFU1VMVF9QT0lOVF9DQUxMQkFDSyk7XG4gICAgICAgICAgICBjb25zdCBmaW5kZXIgPSBuZXcgRmluZGVyUGF0dGVybkZpbmRlcih0aGlzLmltYWdlLCB0aGlzLnJlc3VsdFBvaW50Q2FsbGJhY2spO1xuICAgICAgICAgICAgY29uc3QgaW5mbyA9IGZpbmRlci5maW5kKGhpbnRzKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnByb2Nlc3NGaW5kZXJQYXR0ZXJuSW5mbyhpbmZvKTtcbiAgICAgICAgfVxuICAgICAgICBwcm9jZXNzRmluZGVyUGF0dGVybkluZm8oaW5mbykge1xuICAgICAgICAgICAgY29uc3QgdG9wTGVmdCA9IGluZm8uZ2V0VG9wTGVmdCgpO1xuICAgICAgICAgICAgY29uc3QgdG9wUmlnaHQgPSBpbmZvLmdldFRvcFJpZ2h0KCk7XG4gICAgICAgICAgICBjb25zdCBib3R0b21MZWZ0ID0gaW5mby5nZXRCb3R0b21MZWZ0KCk7XG4gICAgICAgICAgICBjb25zdCBtb2R1bGVTaXplID0gdGhpcy5jYWxjdWxhdGVNb2R1bGVTaXplKHRvcExlZnQsIHRvcFJpZ2h0LCBib3R0b21MZWZ0KTtcbiAgICAgICAgICAgIGlmIChtb2R1bGVTaXplIDwgMS4wKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCdObyBwYXR0ZXJuIGZvdW5kIGluIHByb2NjZXNzIGZpbmRlci4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGRpbWVuc2lvbiA9IERldGVjdG9yJDIuY29tcHV0ZURpbWVuc2lvbih0b3BMZWZ0LCB0b3BSaWdodCwgYm90dG9tTGVmdCwgbW9kdWxlU2l6ZSk7XG4gICAgICAgICAgICBjb25zdCBwcm92aXNpb25hbFZlcnNpb24gPSBWZXJzaW9uJDEuZ2V0UHJvdmlzaW9uYWxWZXJzaW9uRm9yRGltZW5zaW9uKGRpbWVuc2lvbik7XG4gICAgICAgICAgICBjb25zdCBtb2R1bGVzQmV0d2VlbkZQQ2VudGVycyA9IHByb3Zpc2lvbmFsVmVyc2lvbi5nZXREaW1lbnNpb25Gb3JWZXJzaW9uKCkgLSA3O1xuICAgICAgICAgICAgbGV0IGFsaWdubWVudFBhdHRlcm4gPSBudWxsO1xuICAgICAgICAgICAgLy8gQW55dGhpbmcgYWJvdmUgdmVyc2lvbiAxIGhhcyBhbiBhbGlnbm1lbnQgcGF0dGVyblxuICAgICAgICAgICAgaWYgKHByb3Zpc2lvbmFsVmVyc2lvbi5nZXRBbGlnbm1lbnRQYXR0ZXJuQ2VudGVycygpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAvLyBHdWVzcyB3aGVyZSBhIFwiYm90dG9tIHJpZ2h0XCIgZmluZGVyIHBhdHRlcm4gd291bGQgaGF2ZSBiZWVuXG4gICAgICAgICAgICAgICAgY29uc3QgYm90dG9tUmlnaHRYID0gdG9wUmlnaHQuZ2V0WCgpIC0gdG9wTGVmdC5nZXRYKCkgKyBib3R0b21MZWZ0LmdldFgoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBib3R0b21SaWdodFkgPSB0b3BSaWdodC5nZXRZKCkgLSB0b3BMZWZ0LmdldFkoKSArIGJvdHRvbUxlZnQuZ2V0WSgpO1xuICAgICAgICAgICAgICAgIC8vIEVzdGltYXRlIHRoYXQgYWxpZ25tZW50IHBhdHRlcm4gaXMgY2xvc2VyIGJ5IDMgbW9kdWxlc1xuICAgICAgICAgICAgICAgIC8vIGZyb20gXCJib3R0b20gcmlnaHRcIiB0byBrbm93biB0b3AgbGVmdCBsb2NhdGlvblxuICAgICAgICAgICAgICAgIGNvbnN0IGNvcnJlY3Rpb25Ub1RvcExlZnQgPSAxLjAgLSAzLjAgLyBtb2R1bGVzQmV0d2VlbkZQQ2VudGVycztcbiAgICAgICAgICAgICAgICBjb25zdCBlc3RBbGlnbm1lbnRYID0gLyooaW50KSAqLyBNYXRoLmZsb29yKHRvcExlZnQuZ2V0WCgpICsgY29ycmVjdGlvblRvVG9wTGVmdCAqIChib3R0b21SaWdodFggLSB0b3BMZWZ0LmdldFgoKSkpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGVzdEFsaWdubWVudFkgPSAvKihpbnQpICovIE1hdGguZmxvb3IodG9wTGVmdC5nZXRZKCkgKyBjb3JyZWN0aW9uVG9Ub3BMZWZ0ICogKGJvdHRvbVJpZ2h0WSAtIHRvcExlZnQuZ2V0WSgpKSk7XG4gICAgICAgICAgICAgICAgLy8gS2luZCBvZiBhcmJpdHJhcnkgLS0gZXhwYW5kIHNlYXJjaCByYWRpdXMgYmVmb3JlIGdpdmluZyB1cFxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSA0OyBpIDw9IDE2OyBpIDw8PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbGlnbm1lbnRQYXR0ZXJuID0gdGhpcy5maW5kQWxpZ25tZW50SW5SZWdpb24obW9kdWxlU2l6ZSwgZXN0QWxpZ25tZW50WCwgZXN0QWxpZ25tZW50WSwgaSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjYXRjaCAocmUgLypOb3RGb3VuZEV4Y2VwdGlvbiovKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIShyZSBpbnN0YW5jZW9mIE5vdEZvdW5kRXhjZXB0aW9uKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IHJlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdHJ5IG5leHQgcm91bmRcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBJZiB3ZSBkaWRuJ3QgZmluZCBhbGlnbm1lbnQgcGF0dGVybi4uLiB3ZWxsIHRyeSBhbnl3YXkgd2l0aG91dCBpdFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgdHJhbnNmb3JtID0gRGV0ZWN0b3IkMi5jcmVhdGVUcmFuc2Zvcm0odG9wTGVmdCwgdG9wUmlnaHQsIGJvdHRvbUxlZnQsIGFsaWdubWVudFBhdHRlcm4sIGRpbWVuc2lvbik7XG4gICAgICAgICAgICBjb25zdCBiaXRzID0gRGV0ZWN0b3IkMi5zYW1wbGVHcmlkKHRoaXMuaW1hZ2UsIHRyYW5zZm9ybSwgZGltZW5zaW9uKTtcbiAgICAgICAgICAgIGxldCBwb2ludHM7XG4gICAgICAgICAgICBpZiAoYWxpZ25tZW50UGF0dGVybiA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHBvaW50cyA9IFtib3R0b21MZWZ0LCB0b3BMZWZ0LCB0b3BSaWdodF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBwb2ludHMgPSBbYm90dG9tTGVmdCwgdG9wTGVmdCwgdG9wUmlnaHQsIGFsaWdubWVudFBhdHRlcm5dO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBEZXRlY3RvclJlc3VsdChiaXRzLCBwb2ludHMpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBjcmVhdGVUcmFuc2Zvcm0odG9wTGVmdCwgdG9wUmlnaHQsIGJvdHRvbUxlZnQsIGFsaWdubWVudFBhdHRlcm4sIGRpbWVuc2lvbiAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBkaW1NaW51c1RocmVlID0gZGltZW5zaW9uIC0gMy41O1xuICAgICAgICAgICAgbGV0IGJvdHRvbVJpZ2h0WDsgLypmbG9hdCovXG4gICAgICAgICAgICBsZXQgYm90dG9tUmlnaHRZOyAvKmZsb2F0Ki9cbiAgICAgICAgICAgIGxldCBzb3VyY2VCb3R0b21SaWdodFg7IC8qZmxvYXQqL1xuICAgICAgICAgICAgbGV0IHNvdXJjZUJvdHRvbVJpZ2h0WTsgLypmbG9hdCovXG4gICAgICAgICAgICBpZiAoYWxpZ25tZW50UGF0dGVybiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGJvdHRvbVJpZ2h0WCA9IGFsaWdubWVudFBhdHRlcm4uZ2V0WCgpO1xuICAgICAgICAgICAgICAgIGJvdHRvbVJpZ2h0WSA9IGFsaWdubWVudFBhdHRlcm4uZ2V0WSgpO1xuICAgICAgICAgICAgICAgIHNvdXJjZUJvdHRvbVJpZ2h0WCA9IGRpbU1pbnVzVGhyZWUgLSAzLjA7XG4gICAgICAgICAgICAgICAgc291cmNlQm90dG9tUmlnaHRZID0gc291cmNlQm90dG9tUmlnaHRYO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gRG9uJ3QgaGF2ZSBhbiBhbGlnbm1lbnQgcGF0dGVybiwganVzdCBtYWtlIHVwIHRoZSBib3R0b20tcmlnaHQgcG9pbnRcbiAgICAgICAgICAgICAgICBib3R0b21SaWdodFggPSAodG9wUmlnaHQuZ2V0WCgpIC0gdG9wTGVmdC5nZXRYKCkpICsgYm90dG9tTGVmdC5nZXRYKCk7XG4gICAgICAgICAgICAgICAgYm90dG9tUmlnaHRZID0gKHRvcFJpZ2h0LmdldFkoKSAtIHRvcExlZnQuZ2V0WSgpKSArIGJvdHRvbUxlZnQuZ2V0WSgpO1xuICAgICAgICAgICAgICAgIHNvdXJjZUJvdHRvbVJpZ2h0WCA9IGRpbU1pbnVzVGhyZWU7XG4gICAgICAgICAgICAgICAgc291cmNlQm90dG9tUmlnaHRZID0gZGltTWludXNUaHJlZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBQZXJzcGVjdGl2ZVRyYW5zZm9ybS5xdWFkcmlsYXRlcmFsVG9RdWFkcmlsYXRlcmFsKDMuNSwgMy41LCBkaW1NaW51c1RocmVlLCAzLjUsIHNvdXJjZUJvdHRvbVJpZ2h0WCwgc291cmNlQm90dG9tUmlnaHRZLCAzLjUsIGRpbU1pbnVzVGhyZWUsIHRvcExlZnQuZ2V0WCgpLCB0b3BMZWZ0LmdldFkoKSwgdG9wUmlnaHQuZ2V0WCgpLCB0b3BSaWdodC5nZXRZKCksIGJvdHRvbVJpZ2h0WCwgYm90dG9tUmlnaHRZLCBib3R0b21MZWZ0LmdldFgoKSwgYm90dG9tTGVmdC5nZXRZKCkpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBzYW1wbGVHcmlkKGltYWdlLCB0cmFuc2Zvcm0sIGRpbWVuc2lvbiAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCBzYW1wbGVyID0gR3JpZFNhbXBsZXJJbnN0YW5jZS5nZXRJbnN0YW5jZSgpO1xuICAgICAgICAgICAgcmV0dXJuIHNhbXBsZXIuc2FtcGxlR3JpZFdpdGhUcmFuc2Zvcm0oaW1hZ2UsIGRpbWVuc2lvbiwgZGltZW5zaW9uLCB0cmFuc2Zvcm0pO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5Db21wdXRlcyB0aGUgZGltZW5zaW9uIChudW1iZXIgb2YgbW9kdWxlcyBvbiBhIHNpemUpIG9mIHRoZSBRUiBDb2RlIGJhc2VkIG9uIHRoZSBwb3NpdGlvblxuICAgICAgICAgKiBvZiB0aGUgZmluZGVyIHBhdHRlcm5zIGFuZCBlc3RpbWF0ZWQgbW9kdWxlIHNpemUuPC9wPlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGNvbXB1dGVEaW1lbnNpb24odG9wTGVmdCwgdG9wUmlnaHQsIGJvdHRvbUxlZnQsIG1vZHVsZVNpemUgLypmbG9hdCovKSB7XG4gICAgICAgICAgICBjb25zdCB0bHRyQ2VudGVyc0RpbWVuc2lvbiA9IE1hdGhVdGlscy5yb3VuZChSZXN1bHRQb2ludC5kaXN0YW5jZSh0b3BMZWZ0LCB0b3BSaWdodCkgLyBtb2R1bGVTaXplKTtcbiAgICAgICAgICAgIGNvbnN0IHRsYmxDZW50ZXJzRGltZW5zaW9uID0gTWF0aFV0aWxzLnJvdW5kKFJlc3VsdFBvaW50LmRpc3RhbmNlKHRvcExlZnQsIGJvdHRvbUxlZnQpIC8gbW9kdWxlU2l6ZSk7XG4gICAgICAgICAgICBsZXQgZGltZW5zaW9uID0gTWF0aC5mbG9vcigodGx0ckNlbnRlcnNEaW1lbnNpb24gKyB0bGJsQ2VudGVyc0RpbWVuc2lvbikgLyAyKSArIDc7XG4gICAgICAgICAgICBzd2l0Y2ggKGRpbWVuc2lvbiAmIDB4MDMpIHsgLy8gbW9kIDRcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIGRpbWVuc2lvbisrO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAvLyAxPyBkbyBub3RoaW5nXG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBkaW1lbnNpb24tLTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oJ0RpbWVuc2lvbnMgY291bGQgYmUgbm90IGZvdW5kLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGRpbWVuc2lvbjtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+Q29tcHV0ZXMgYW4gYXZlcmFnZSBlc3RpbWF0ZWQgbW9kdWxlIHNpemUgYmFzZWQgb24gZXN0aW1hdGVkIGRlcml2ZWQgZnJvbSB0aGUgcG9zaXRpb25zXG4gICAgICAgICAqIG9mIHRoZSB0aHJlZSBmaW5kZXIgcGF0dGVybnMuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gdG9wTGVmdCBkZXRlY3RlZCB0b3AtbGVmdCBmaW5kZXIgcGF0dGVybiBjZW50ZXJcbiAgICAgICAgICogQHBhcmFtIHRvcFJpZ2h0IGRldGVjdGVkIHRvcC1yaWdodCBmaW5kZXIgcGF0dGVybiBjZW50ZXJcbiAgICAgICAgICogQHBhcmFtIGJvdHRvbUxlZnQgZGV0ZWN0ZWQgYm90dG9tLWxlZnQgZmluZGVyIHBhdHRlcm4gY2VudGVyXG4gICAgICAgICAqIEByZXR1cm4gZXN0aW1hdGVkIG1vZHVsZSBzaXplXG4gICAgICAgICAqL1xuICAgICAgICBjYWxjdWxhdGVNb2R1bGVTaXplKHRvcExlZnQsIHRvcFJpZ2h0LCBib3R0b21MZWZ0KSB7XG4gICAgICAgICAgICAvLyBUYWtlIHRoZSBhdmVyYWdlXG4gICAgICAgICAgICByZXR1cm4gKHRoaXMuY2FsY3VsYXRlTW9kdWxlU2l6ZU9uZVdheSh0b3BMZWZ0LCB0b3BSaWdodCkgK1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsY3VsYXRlTW9kdWxlU2l6ZU9uZVdheSh0b3BMZWZ0LCBib3R0b21MZWZ0KSkgLyAyLjA7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkVzdGltYXRlcyBtb2R1bGUgc2l6ZSBiYXNlZCBvbiB0d28gZmluZGVyIHBhdHRlcm5zIC0tIGl0IHVzZXNcbiAgICAgICAgICoge0BsaW5rICNzaXplT2ZCbGFja1doaXRlQmxhY2tSdW5Cb3RoV2F5cyhpbnQsIGludCwgaW50LCBpbnQpfSB0byBmaWd1cmUgdGhlXG4gICAgICAgICAqIHdpZHRoIG9mIGVhY2gsIG1lYXN1cmluZyBhbG9uZyB0aGUgYXhpcyBiZXR3ZWVuIHRoZWlyIGNlbnRlcnMuPC9wPlxuICAgICAgICAgKi9cbiAgICAgICAgY2FsY3VsYXRlTW9kdWxlU2l6ZU9uZVdheShwYXR0ZXJuLCBvdGhlclBhdHRlcm4pIHtcbiAgICAgICAgICAgIGNvbnN0IG1vZHVsZVNpemVFc3QxID0gdGhpcy5zaXplT2ZCbGFja1doaXRlQmxhY2tSdW5Cb3RoV2F5cygvKihpbnQpICovIE1hdGguZmxvb3IocGF0dGVybi5nZXRYKCkpLCBcbiAgICAgICAgICAgIC8qKGludCkgKi8gTWF0aC5mbG9vcihwYXR0ZXJuLmdldFkoKSksIFxuICAgICAgICAgICAgLyooaW50KSAqLyBNYXRoLmZsb29yKG90aGVyUGF0dGVybi5nZXRYKCkpLCBcbiAgICAgICAgICAgIC8qKGludCkgKi8gTWF0aC5mbG9vcihvdGhlclBhdHRlcm4uZ2V0WSgpKSk7XG4gICAgICAgICAgICBjb25zdCBtb2R1bGVTaXplRXN0MiA9IHRoaXMuc2l6ZU9mQmxhY2tXaGl0ZUJsYWNrUnVuQm90aFdheXMoLyooaW50KSAqLyBNYXRoLmZsb29yKG90aGVyUGF0dGVybi5nZXRYKCkpLCBcbiAgICAgICAgICAgIC8qKGludCkgKi8gTWF0aC5mbG9vcihvdGhlclBhdHRlcm4uZ2V0WSgpKSwgXG4gICAgICAgICAgICAvKihpbnQpICovIE1hdGguZmxvb3IocGF0dGVybi5nZXRYKCkpLCBcbiAgICAgICAgICAgIC8qKGludCkgKi8gTWF0aC5mbG9vcihwYXR0ZXJuLmdldFkoKSkpO1xuICAgICAgICAgICAgaWYgKGlzTmFOKG1vZHVsZVNpemVFc3QxKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb2R1bGVTaXplRXN0MiAvIDcuMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc05hTihtb2R1bGVTaXplRXN0MikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9kdWxlU2l6ZUVzdDEgLyA3LjA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBBdmVyYWdlIHRoZW0sIGFuZCBkaXZpZGUgYnkgNyBzaW5jZSB3ZSd2ZSBjb3VudGVkIHRoZSB3aWR0aCBvZiAzIGJsYWNrIG1vZHVsZXMsXG4gICAgICAgICAgICAvLyBhbmQgMSB3aGl0ZSBhbmQgMSBibGFjayBtb2R1bGUgb24gZWl0aGVyIHNpZGUuIEVyZ28sIGRpdmlkZSBzdW0gYnkgMTQuXG4gICAgICAgICAgICByZXR1cm4gKG1vZHVsZVNpemVFc3QxICsgbW9kdWxlU2l6ZUVzdDIpIC8gMTQuMDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogU2VlIHtAbGluayAjc2l6ZU9mQmxhY2tXaGl0ZUJsYWNrUnVuKGludCwgaW50LCBpbnQsIGludCl9OyBjb21wdXRlcyB0aGUgdG90YWwgd2lkdGggb2ZcbiAgICAgICAgICogYSBmaW5kZXIgcGF0dGVybiBieSBsb29raW5nIGZvciBhIGJsYWNrLXdoaXRlLWJsYWNrIHJ1biBmcm9tIHRoZSBjZW50ZXIgaW4gdGhlIGRpcmVjdGlvblxuICAgICAgICAgKiBvZiBhbm90aGVyIHBvaW50IChhbm90aGVyIGZpbmRlciBwYXR0ZXJuIGNlbnRlciksIGFuZCBpbiB0aGUgb3Bwb3NpdGUgZGlyZWN0aW9uIHRvby5cbiAgICAgICAgICovXG4gICAgICAgIHNpemVPZkJsYWNrV2hpdGVCbGFja1J1bkJvdGhXYXlzKGZyb21YIC8qaW50Ki8sIGZyb21ZIC8qaW50Ki8sIHRvWCAvKmludCovLCB0b1kgLyppbnQqLykge1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IHRoaXMuc2l6ZU9mQmxhY2tXaGl0ZUJsYWNrUnVuKGZyb21YLCBmcm9tWSwgdG9YLCB0b1kpO1xuICAgICAgICAgICAgLy8gTm93IGNvdW50IG90aGVyIHdheSAtLSBkb24ndCBydW4gb2ZmIGltYWdlIHRob3VnaCBvZiBjb3Vyc2VcbiAgICAgICAgICAgIGxldCBzY2FsZSA9IDEuMDtcbiAgICAgICAgICAgIGxldCBvdGhlclRvWCA9IGZyb21YIC0gKHRvWCAtIGZyb21YKTtcbiAgICAgICAgICAgIGlmIChvdGhlclRvWCA8IDApIHtcbiAgICAgICAgICAgICAgICBzY2FsZSA9IGZyb21YIC8gLyooZmxvYXQpICovIChmcm9tWCAtIG90aGVyVG9YKTtcbiAgICAgICAgICAgICAgICBvdGhlclRvWCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChvdGhlclRvWCA+PSB0aGlzLmltYWdlLmdldFdpZHRoKCkpIHtcbiAgICAgICAgICAgICAgICBzY2FsZSA9ICh0aGlzLmltYWdlLmdldFdpZHRoKCkgLSAxIC0gZnJvbVgpIC8gLyooZmxvYXQpICovIChvdGhlclRvWCAtIGZyb21YKTtcbiAgICAgICAgICAgICAgICBvdGhlclRvWCA9IHRoaXMuaW1hZ2UuZ2V0V2lkdGgoKSAtIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgb3RoZXJUb1kgPSAvKihpbnQpICovIE1hdGguZmxvb3IoZnJvbVkgLSAodG9ZIC0gZnJvbVkpICogc2NhbGUpO1xuICAgICAgICAgICAgc2NhbGUgPSAxLjA7XG4gICAgICAgICAgICBpZiAob3RoZXJUb1kgPCAwKSB7XG4gICAgICAgICAgICAgICAgc2NhbGUgPSBmcm9tWSAvIC8qKGZsb2F0KSAqLyAoZnJvbVkgLSBvdGhlclRvWSk7XG4gICAgICAgICAgICAgICAgb3RoZXJUb1kgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAob3RoZXJUb1kgPj0gdGhpcy5pbWFnZS5nZXRIZWlnaHQoKSkge1xuICAgICAgICAgICAgICAgIHNjYWxlID0gKHRoaXMuaW1hZ2UuZ2V0SGVpZ2h0KCkgLSAxIC0gZnJvbVkpIC8gLyooZmxvYXQpICovIChvdGhlclRvWSAtIGZyb21ZKTtcbiAgICAgICAgICAgICAgICBvdGhlclRvWSA9IHRoaXMuaW1hZ2UuZ2V0SGVpZ2h0KCkgLSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3RoZXJUb1ggPSAvKihpbnQpICovIE1hdGguZmxvb3IoZnJvbVggKyAob3RoZXJUb1ggLSBmcm9tWCkgKiBzY2FsZSk7XG4gICAgICAgICAgICByZXN1bHQgKz0gdGhpcy5zaXplT2ZCbGFja1doaXRlQmxhY2tSdW4oZnJvbVgsIGZyb21ZLCBvdGhlclRvWCwgb3RoZXJUb1kpO1xuICAgICAgICAgICAgLy8gTWlkZGxlIHBpeGVsIGlzIGRvdWJsZS1jb3VudGVkIHRoaXMgd2F5OyBzdWJ0cmFjdCAxXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0IC0gMS4wO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5UaGlzIG1ldGhvZCB0cmFjZXMgYSBsaW5lIGZyb20gYSBwb2ludCBpbiB0aGUgaW1hZ2UsIGluIHRoZSBkaXJlY3Rpb24gdG93YXJkcyBhbm90aGVyIHBvaW50LlxuICAgICAgICAgKiBJdCBiZWdpbnMgaW4gYSBibGFjayByZWdpb24sIGFuZCBrZWVwcyBnb2luZyB1bnRpbCBpdCBmaW5kcyB3aGl0ZSwgdGhlbiBibGFjaywgdGhlbiB3aGl0ZSBhZ2Fpbi5cbiAgICAgICAgICogSXQgcmVwb3J0cyB0aGUgZGlzdGFuY2UgZnJvbSB0aGUgc3RhcnQgdG8gdGhpcyBwb2ludC48L3A+XG4gICAgICAgICAqXG4gICAgICAgICAqIDxwPlRoaXMgaXMgdXNlZCB3aGVuIGZpZ3VyaW5nIG91dCBob3cgd2lkZSBhIGZpbmRlciBwYXR0ZXJuIGlzLCB3aGVuIHRoZSBmaW5kZXIgcGF0dGVyblxuICAgICAgICAgKiBtYXkgYmUgc2tld2VkIG9yIHJvdGF0ZWQuPC9wPlxuICAgICAgICAgKi9cbiAgICAgICAgc2l6ZU9mQmxhY2tXaGl0ZUJsYWNrUnVuKGZyb21YIC8qaW50Ki8sIGZyb21ZIC8qaW50Ki8sIHRvWCAvKmludCovLCB0b1kgLyppbnQqLykge1xuICAgICAgICAgICAgLy8gTWlsZCB2YXJpYW50IG9mIEJyZXNlbmhhbSdzIGFsZ29yaXRobVxuICAgICAgICAgICAgLy8gc2VlIGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQnJlc2VuaGFtJ3NfbGluZV9hbGdvcml0aG1cbiAgICAgICAgICAgIGNvbnN0IHN0ZWVwID0gTWF0aC5hYnModG9ZIC0gZnJvbVkpID4gTWF0aC5hYnModG9YIC0gZnJvbVgpO1xuICAgICAgICAgICAgaWYgKHN0ZWVwKSB7XG4gICAgICAgICAgICAgICAgbGV0IHRlbXAgPSBmcm9tWDtcbiAgICAgICAgICAgICAgICBmcm9tWCA9IGZyb21ZO1xuICAgICAgICAgICAgICAgIGZyb21ZID0gdGVtcDtcbiAgICAgICAgICAgICAgICB0ZW1wID0gdG9YO1xuICAgICAgICAgICAgICAgIHRvWCA9IHRvWTtcbiAgICAgICAgICAgICAgICB0b1kgPSB0ZW1wO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZHggPSBNYXRoLmFicyh0b1ggLSBmcm9tWCk7XG4gICAgICAgICAgICBjb25zdCBkeSA9IE1hdGguYWJzKHRvWSAtIGZyb21ZKTtcbiAgICAgICAgICAgIGxldCBlcnJvciA9IC1keCAvIDI7XG4gICAgICAgICAgICBjb25zdCB4c3RlcCA9IGZyb21YIDwgdG9YID8gMSA6IC0xO1xuICAgICAgICAgICAgY29uc3QgeXN0ZXAgPSBmcm9tWSA8IHRvWSA/IDEgOiAtMTtcbiAgICAgICAgICAgIC8vIEluIGJsYWNrIHBpeGVscywgbG9va2luZyBmb3Igd2hpdGUsIGZpcnN0IG9yIHNlY29uZCB0aW1lLlxuICAgICAgICAgICAgbGV0IHN0YXRlID0gMDtcbiAgICAgICAgICAgIC8vIExvb3AgdXAgdW50aWwgeCA9PSB0b1gsIGJ1dCBub3QgYmV5b25kXG4gICAgICAgICAgICBjb25zdCB4TGltaXQgPSB0b1ggKyB4c3RlcDtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSBmcm9tWCwgeSA9IGZyb21ZOyB4ICE9PSB4TGltaXQ7IHggKz0geHN0ZXApIHtcbiAgICAgICAgICAgICAgICBjb25zdCByZWFsWCA9IHN0ZWVwID8geSA6IHg7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVhbFkgPSBzdGVlcCA/IHggOiB5O1xuICAgICAgICAgICAgICAgIC8vIERvZXMgY3VycmVudCBwaXhlbCBtZWFuIHdlIGhhdmUgbW92ZWQgd2hpdGUgdG8gYmxhY2sgb3IgdmljZSB2ZXJzYT9cbiAgICAgICAgICAgICAgICAvLyBTY2FubmluZyBibGFjayBpbiBzdGF0ZSAwLDIgYW5kIHdoaXRlIGluIHN0YXRlIDEsIHNvIGlmIHdlIGZpbmQgdGhlIHdyb25nXG4gICAgICAgICAgICAgICAgLy8gY29sb3IsIGFkdmFuY2UgdG8gbmV4dCBzdGF0ZSBvciBlbmQgaWYgd2UgYXJlIGluIHN0YXRlIDIgYWxyZWFkeVxuICAgICAgICAgICAgICAgIGlmICgoc3RhdGUgPT09IDEpID09PSB0aGlzLmltYWdlLmdldChyZWFsWCwgcmVhbFkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0ZSA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE1hdGhVdGlscy5kaXN0YW5jZSh4LCB5LCBmcm9tWCwgZnJvbVkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHN0YXRlKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVycm9yICs9IGR5O1xuICAgICAgICAgICAgICAgIGlmIChlcnJvciA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHkgPT09IHRvWSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgeSArPSB5c3RlcDtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3IgLT0gZHg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRm91bmQgYmxhY2std2hpdGUtYmxhY2s7IGdpdmUgdGhlIGJlbmVmaXQgb2YgdGhlIGRvdWJ0IHRoYXQgdGhlIG5leHQgcGl4ZWwgb3V0c2lkZSB0aGUgaW1hZ2VcbiAgICAgICAgICAgIC8vIGlzIFwid2hpdGVcIiBzbyB0aGlzIGxhc3QgcG9pbnQgYXQgKHRvWCt4U3RlcCx0b1kpIGlzIHRoZSByaWdodCBlbmRpbmcuIFRoaXMgaXMgcmVhbGx5IGFcbiAgICAgICAgICAgIC8vIHNtYWxsIGFwcHJveGltYXRpb247ICh0b1greFN0ZXAsdG9ZK3lTdGVwKSBtaWdodCBiZSByZWFsbHkgY29ycmVjdC4gSWdub3JlIHRoaXMuXG4gICAgICAgICAgICBpZiAoc3RhdGUgPT09IDIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTWF0aFV0aWxzLmRpc3RhbmNlKHRvWCArIHhzdGVwLCB0b1ksIGZyb21YLCBmcm9tWSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBlbHNlIHdlIGRpZG4ndCBmaW5kIGV2ZW4gYmxhY2std2hpdGUtYmxhY2s7IG5vIGVzdGltYXRlIGlzIHJlYWxseSBwb3NzaWJsZVxuICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogPHA+QXR0ZW1wdHMgdG8gbG9jYXRlIGFuIGFsaWdubWVudCBwYXR0ZXJuIGluIGEgbGltaXRlZCByZWdpb24gb2YgdGhlIGltYWdlLCB3aGljaCBpc1xuICAgICAgICAgKiBndWVzc2VkIHRvIGNvbnRhaW4gaXQuIFRoaXMgbWV0aG9kIHVzZXMge0BsaW5rIEFsaWdubWVudFBhdHRlcm59LjwvcD5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIG92ZXJhbGxFc3RNb2R1bGVTaXplIGVzdGltYXRlZCBtb2R1bGUgc2l6ZSBzbyBmYXJcbiAgICAgICAgICogQHBhcmFtIGVzdEFsaWdubWVudFggeCBjb29yZGluYXRlIG9mIGNlbnRlciBvZiBhcmVhIHByb2JhYmx5IGNvbnRhaW5pbmcgYWxpZ25tZW50IHBhdHRlcm5cbiAgICAgICAgICogQHBhcmFtIGVzdEFsaWdubWVudFkgeSBjb29yZGluYXRlIG9mIGFib3ZlXG4gICAgICAgICAqIEBwYXJhbSBhbGxvd2FuY2VGYWN0b3IgbnVtYmVyIG9mIHBpeGVscyBpbiBhbGwgZGlyZWN0aW9ucyB0byBzZWFyY2ggZnJvbSB0aGUgY2VudGVyXG4gICAgICAgICAqIEByZXR1cm4ge0BsaW5rIEFsaWdubWVudFBhdHRlcm59IGlmIGZvdW5kLCBvciBudWxsIG90aGVyd2lzZVxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIGFuIHVuZXhwZWN0ZWQgZXJyb3Igb2NjdXJzIGR1cmluZyBkZXRlY3Rpb25cbiAgICAgICAgICovXG4gICAgICAgIGZpbmRBbGlnbm1lbnRJblJlZ2lvbihvdmVyYWxsRXN0TW9kdWxlU2l6ZSAvKmZsb2F0Ki8sIGVzdEFsaWdubWVudFggLyppbnQqLywgZXN0QWxpZ25tZW50WSAvKmludCovLCBhbGxvd2FuY2VGYWN0b3IgLypmbG9hdCovKSB7XG4gICAgICAgICAgICAvLyBMb29rIGZvciBhbiBhbGlnbm1lbnQgcGF0dGVybiAoMyBtb2R1bGVzIGluIHNpemUpIGFyb3VuZCB3aGVyZSBpdFxuICAgICAgICAgICAgLy8gc2hvdWxkIGJlXG4gICAgICAgICAgICBjb25zdCBhbGxvd2FuY2UgPSAvKihpbnQpICovIE1hdGguZmxvb3IoYWxsb3dhbmNlRmFjdG9yICogb3ZlcmFsbEVzdE1vZHVsZVNpemUpO1xuICAgICAgICAgICAgY29uc3QgYWxpZ25tZW50QXJlYUxlZnRYID0gTWF0aC5tYXgoMCwgZXN0QWxpZ25tZW50WCAtIGFsbG93YW5jZSk7XG4gICAgICAgICAgICBjb25zdCBhbGlnbm1lbnRBcmVhUmlnaHRYID0gTWF0aC5taW4odGhpcy5pbWFnZS5nZXRXaWR0aCgpIC0gMSwgZXN0QWxpZ25tZW50WCArIGFsbG93YW5jZSk7XG4gICAgICAgICAgICBpZiAoYWxpZ25tZW50QXJlYVJpZ2h0WCAtIGFsaWdubWVudEFyZWFMZWZ0WCA8IG92ZXJhbGxFc3RNb2R1bGVTaXplICogMykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbignQWxpZ25tZW50IHRvcCBleGNlZWRzIGVzdGltYXRlZCBtb2R1bGUgc2l6ZS4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGFsaWdubWVudEFyZWFUb3BZID0gTWF0aC5tYXgoMCwgZXN0QWxpZ25tZW50WSAtIGFsbG93YW5jZSk7XG4gICAgICAgICAgICBjb25zdCBhbGlnbm1lbnRBcmVhQm90dG9tWSA9IE1hdGgubWluKHRoaXMuaW1hZ2UuZ2V0SGVpZ2h0KCkgLSAxLCBlc3RBbGlnbm1lbnRZICsgYWxsb3dhbmNlKTtcbiAgICAgICAgICAgIGlmIChhbGlnbm1lbnRBcmVhQm90dG9tWSAtIGFsaWdubWVudEFyZWFUb3BZIDwgb3ZlcmFsbEVzdE1vZHVsZVNpemUgKiAzKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCdBbGlnbm1lbnQgYm90dG9tIGV4Y2VlZHMgZXN0aW1hdGVkIG1vZHVsZSBzaXplLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYWxpZ25tZW50RmluZGVyID0gbmV3IEFsaWdubWVudFBhdHRlcm5GaW5kZXIodGhpcy5pbWFnZSwgYWxpZ25tZW50QXJlYUxlZnRYLCBhbGlnbm1lbnRBcmVhVG9wWSwgYWxpZ25tZW50QXJlYVJpZ2h0WCAtIGFsaWdubWVudEFyZWFMZWZ0WCwgYWxpZ25tZW50QXJlYUJvdHRvbVkgLSBhbGlnbm1lbnRBcmVhVG9wWSwgb3ZlcmFsbEVzdE1vZHVsZVNpemUsIHRoaXMucmVzdWx0UG9pbnRDYWxsYmFjayk7XG4gICAgICAgICAgICByZXR1cm4gYWxpZ25tZW50RmluZGVyLmZpbmQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDcgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyppbXBvcnQgamF2YS51dGlsLkxpc3Q7Ki9cbiAgICAvKmltcG9ydCBqYXZhLnV0aWwuTWFwOyovXG4gICAgLyoqXG4gICAgICogVGhpcyBpbXBsZW1lbnRhdGlvbiBjYW4gZGV0ZWN0IGFuZCBkZWNvZGUgUVIgQ29kZXMgaW4gYW4gaW1hZ2UuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqL1xuICAgIGNsYXNzIFFSQ29kZVJlYWRlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgdGhpcy5kZWNvZGVyID0gbmV3IERlY29kZXIkMigpO1xuICAgICAgICB9XG4gICAgICAgIGdldERlY29kZXIoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGVyO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBMb2NhdGVzIGFuZCBkZWNvZGVzIGEgUVIgY29kZSBpbiBhbiBpbWFnZS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiBhIHJlcHJlc2VudGluZzogc3RyaW5nIHRoZSBjb250ZW50IGVuY29kZWQgYnkgdGhlIFFSIGNvZGVcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBpZiBhIFFSIGNvZGUgY2Fubm90IGJlIGZvdW5kXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uIGlmIGEgUVIgY29kZSBjYW5ub3QgYmUgZGVjb2RlZFxuICAgICAgICAgKiBAdGhyb3dzIENoZWNrc3VtRXhjZXB0aW9uIGlmIGVycm9yIGNvcnJlY3Rpb24gZmFpbHNcbiAgICAgICAgICovXG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgLy8gcHVibGljIGRlY29kZShpbWFnZTogQmluYXJ5Qml0bWFwKTogUmVzdWx0IC8qdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uLCBDaGVja3N1bUV4Y2VwdGlvbiwgRm9ybWF0RXhjZXB0aW9uICovIHtcbiAgICAgICAgLy8gICByZXR1cm4gdGhpcy5kZWNvZGUoaW1hZ2UsIG51bGwpXG4gICAgICAgIC8vIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBkZWNvZGUoaW1hZ2UsIGhpbnRzKSB7XG4gICAgICAgICAgICBsZXQgZGVjb2RlclJlc3VsdDtcbiAgICAgICAgICAgIGxldCBwb2ludHM7XG4gICAgICAgICAgICBpZiAoaGludHMgIT09IHVuZGVmaW5lZCAmJiBoaW50cyAhPT0gbnVsbCAmJiB1bmRlZmluZWQgIT09IGhpbnRzLmdldChEZWNvZGVIaW50VHlwZSQxLlBVUkVfQkFSQ09ERSkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBiaXRzID0gUVJDb2RlUmVhZGVyLmV4dHJhY3RQdXJlQml0cyhpbWFnZS5nZXRCbGFja01hdHJpeCgpKTtcbiAgICAgICAgICAgICAgICBkZWNvZGVyUmVzdWx0ID0gdGhpcy5kZWNvZGVyLmRlY29kZUJpdE1hdHJpeChiaXRzLCBoaW50cyk7XG4gICAgICAgICAgICAgICAgcG9pbnRzID0gUVJDb2RlUmVhZGVyLk5PX1BPSU5UUztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRldGVjdG9yUmVzdWx0ID0gbmV3IERldGVjdG9yJDIoaW1hZ2UuZ2V0QmxhY2tNYXRyaXgoKSkuZGV0ZWN0KGhpbnRzKTtcbiAgICAgICAgICAgICAgICBkZWNvZGVyUmVzdWx0ID0gdGhpcy5kZWNvZGVyLmRlY29kZUJpdE1hdHJpeChkZXRlY3RvclJlc3VsdC5nZXRCaXRzKCksIGhpbnRzKTtcbiAgICAgICAgICAgICAgICBwb2ludHMgPSBkZXRlY3RvclJlc3VsdC5nZXRQb2ludHMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIElmIHRoZSBjb2RlIHdhcyBtaXJyb3JlZDogc3dhcCB0aGUgYm90dG9tLWxlZnQgYW5kIHRoZSB0b3AtcmlnaHQgcG9pbnRzLlxuICAgICAgICAgICAgaWYgKGRlY29kZXJSZXN1bHQuZ2V0T3RoZXIoKSBpbnN0YW5jZW9mIFFSQ29kZURlY29kZXJNZXRhRGF0YSkge1xuICAgICAgICAgICAgICAgIGRlY29kZXJSZXN1bHQuZ2V0T3RoZXIoKS5hcHBseU1pcnJvcmVkQ29ycmVjdGlvbihwb2ludHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IFJlc3VsdChkZWNvZGVyUmVzdWx0LmdldFRleHQoKSwgZGVjb2RlclJlc3VsdC5nZXRSYXdCeXRlcygpLCB1bmRlZmluZWQsIHBvaW50cywgQmFyY29kZUZvcm1hdCQxLlFSX0NPREUsIHVuZGVmaW5lZCk7XG4gICAgICAgICAgICBjb25zdCBieXRlU2VnbWVudHMgPSBkZWNvZGVyUmVzdWx0LmdldEJ5dGVTZWdtZW50cygpO1xuICAgICAgICAgICAgaWYgKGJ5dGVTZWdtZW50cyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXRNZXRhZGF0YShSZXN1bHRNZXRhZGF0YVR5cGUkMS5CWVRFX1NFR01FTlRTLCBieXRlU2VnbWVudHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZWNMZXZlbCA9IGRlY29kZXJSZXN1bHQuZ2V0RUNMZXZlbCgpO1xuICAgICAgICAgICAgaWYgKGVjTGV2ZWwgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQucHV0TWV0YWRhdGEoUmVzdWx0TWV0YWRhdGFUeXBlJDEuRVJST1JfQ09SUkVDVElPTl9MRVZFTCwgZWNMZXZlbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZGVjb2RlclJlc3VsdC5oYXNTdHJ1Y3R1cmVkQXBwZW5kKCkpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQucHV0TWV0YWRhdGEoUmVzdWx0TWV0YWRhdGFUeXBlJDEuU1RSVUNUVVJFRF9BUFBFTkRfU0VRVUVOQ0UsIGRlY29kZXJSZXN1bHQuZ2V0U3RydWN0dXJlZEFwcGVuZFNlcXVlbmNlTnVtYmVyKCkpO1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXRNZXRhZGF0YShSZXN1bHRNZXRhZGF0YVR5cGUkMS5TVFJVQ1RVUkVEX0FQUEVORF9QQVJJVFksIGRlY29kZXJSZXN1bHQuZ2V0U3RydWN0dXJlZEFwcGVuZFBhcml0eSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICByZXNldCgpIHtcbiAgICAgICAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogVGhpcyBtZXRob2QgZGV0ZWN0cyBhIGNvZGUgaW4gYSBcInB1cmVcIiBpbWFnZSAtLSB0aGF0IGlzLCBwdXJlIG1vbm9jaHJvbWUgaW1hZ2VcbiAgICAgICAgICogd2hpY2ggY29udGFpbnMgb25seSBhbiB1bnJvdGF0ZWQsIHVuc2tld2VkLCBpbWFnZSBvZiBhIGNvZGUsIHdpdGggc29tZSB3aGl0ZSBib3JkZXJcbiAgICAgICAgICogYXJvdW5kIGl0LiBUaGlzIGlzIGEgc3BlY2lhbGl6ZWQgbWV0aG9kIHRoYXQgd29ya3MgZXhjZXB0aW9uYWxseSBmYXN0IGluIHRoaXMgc3BlY2lhbFxuICAgICAgICAgKiBjYXNlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAc2VlIGNvbS5nb29nbGUuenhpbmcuZGF0YW1hdHJpeC5EYXRhTWF0cml4UmVhZGVyI2V4dHJhY3RQdXJlQml0cyhCaXRNYXRyaXgpXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZXh0cmFjdFB1cmVCaXRzKGltYWdlKSB7XG4gICAgICAgICAgICBjb25zdCBsZWZ0VG9wQmxhY2sgPSBpbWFnZS5nZXRUb3BMZWZ0T25CaXQoKTtcbiAgICAgICAgICAgIGNvbnN0IHJpZ2h0Qm90dG9tQmxhY2sgPSBpbWFnZS5nZXRCb3R0b21SaWdodE9uQml0KCk7XG4gICAgICAgICAgICBpZiAobGVmdFRvcEJsYWNrID09PSBudWxsIHx8IHJpZ2h0Qm90dG9tQmxhY2sgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG1vZHVsZVNpemUgPSB0aGlzLm1vZHVsZVNpemUobGVmdFRvcEJsYWNrLCBpbWFnZSk7XG4gICAgICAgICAgICBsZXQgdG9wID0gbGVmdFRvcEJsYWNrWzFdO1xuICAgICAgICAgICAgbGV0IGJvdHRvbSA9IHJpZ2h0Qm90dG9tQmxhY2tbMV07XG4gICAgICAgICAgICBsZXQgbGVmdCA9IGxlZnRUb3BCbGFja1swXTtcbiAgICAgICAgICAgIGxldCByaWdodCA9IHJpZ2h0Qm90dG9tQmxhY2tbMF07XG4gICAgICAgICAgICAvLyBTYW5pdHkgY2hlY2shXG4gICAgICAgICAgICBpZiAobGVmdCA+PSByaWdodCB8fCB0b3AgPj0gYm90dG9tKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYm90dG9tIC0gdG9wICE9PSByaWdodCAtIGxlZnQpIHtcbiAgICAgICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2UsIHdoZXJlIGJvdHRvbS1yaWdodCBtb2R1bGUgd2Fzbid0IGJsYWNrIHNvIHdlIGZvdW5kIHNvbWV0aGluZyBlbHNlIGluIHRoZSBsYXN0IHJvd1xuICAgICAgICAgICAgICAgIC8vIEFzc3VtZSBpdCdzIGEgc3F1YXJlLCBzbyB1c2UgaGVpZ2h0IGFzIHRoZSB3aWR0aFxuICAgICAgICAgICAgICAgIHJpZ2h0ID0gbGVmdCArIChib3R0b20gLSB0b3ApO1xuICAgICAgICAgICAgICAgIGlmIChyaWdodCA+PSBpbWFnZS5nZXRXaWR0aCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEFib3J0IGlmIHRoYXQgd291bGQgbm90IG1ha2Ugc2Vuc2UgLS0gb2ZmIGltYWdlXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG1hdHJpeFdpZHRoID0gTWF0aC5yb3VuZCgocmlnaHQgLSBsZWZ0ICsgMSkgLyBtb2R1bGVTaXplKTtcbiAgICAgICAgICAgIGNvbnN0IG1hdHJpeEhlaWdodCA9IE1hdGgucm91bmQoKGJvdHRvbSAtIHRvcCArIDEpIC8gbW9kdWxlU2l6ZSk7XG4gICAgICAgICAgICBpZiAobWF0cml4V2lkdGggPD0gMCB8fCBtYXRyaXhIZWlnaHQgPD0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1hdHJpeEhlaWdodCAhPT0gbWF0cml4V2lkdGgpIHtcbiAgICAgICAgICAgICAgICAvLyBPbmx5IHBvc3NpYmx5IGRlY29kZSBzcXVhcmUgcmVnaW9uc1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gUHVzaCBpbiB0aGUgXCJib3JkZXJcIiBieSBoYWxmIHRoZSBtb2R1bGUgd2lkdGggc28gdGhhdCB3ZSBzdGFydFxuICAgICAgICAgICAgLy8gc2FtcGxpbmcgaW4gdGhlIG1pZGRsZSBvZiB0aGUgbW9kdWxlLiBKdXN0IGluIGNhc2UgdGhlIGltYWdlIGlzIGFcbiAgICAgICAgICAgIC8vIGxpdHRsZSBvZmYsIHRoaXMgd2lsbCBoZWxwIHJlY292ZXIuXG4gICAgICAgICAgICBjb25zdCBudWRnZSA9IC8qKGludCkgKi8gTWF0aC5mbG9vcihtb2R1bGVTaXplIC8gMi4wKTtcbiAgICAgICAgICAgIHRvcCArPSBudWRnZTtcbiAgICAgICAgICAgIGxlZnQgKz0gbnVkZ2U7XG4gICAgICAgICAgICAvLyBCdXQgY2FyZWZ1bCB0aGF0IHRoaXMgZG9lcyBub3Qgc2FtcGxlIG9mZiB0aGUgZWRnZVxuICAgICAgICAgICAgLy8gXCJyaWdodFwiIGlzIHRoZSBmYXJ0aGVzdC1yaWdodCB2YWxpZCBwaXhlbCBsb2NhdGlvbiAtLSByaWdodCsxIGlzIG5vdCBuZWNlc3NhcmlseVxuICAgICAgICAgICAgLy8gVGhpcyBpcyBwb3NpdGl2ZSBieSBob3cgbXVjaCB0aGUgaW5uZXIgeCBsb29wIGJlbG93IHdvdWxkIGJlIHRvbyBsYXJnZVxuICAgICAgICAgICAgY29uc3QgbnVkZ2VkVG9vRmFyUmlnaHQgPSBsZWZ0ICsgLyooaW50KSAqLyBNYXRoLmZsb29yKChtYXRyaXhXaWR0aCAtIDEpICogbW9kdWxlU2l6ZSkgLSByaWdodDtcbiAgICAgICAgICAgIGlmIChudWRnZWRUb29GYXJSaWdodCA+IDApIHtcbiAgICAgICAgICAgICAgICBpZiAobnVkZ2VkVG9vRmFyUmlnaHQgPiBudWRnZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBOZWl0aGVyIHdheSBmaXRzOyBhYm9ydFxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGVmdCAtPSBudWRnZWRUb29GYXJSaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFNlZSBsb2dpYyBhYm92ZVxuICAgICAgICAgICAgY29uc3QgbnVkZ2VkVG9vRmFyRG93biA9IHRvcCArIC8qKGludCkgKi8gTWF0aC5mbG9vcigobWF0cml4SGVpZ2h0IC0gMSkgKiBtb2R1bGVTaXplKSAtIGJvdHRvbTtcbiAgICAgICAgICAgIGlmIChudWRnZWRUb29GYXJEb3duID4gMCkge1xuICAgICAgICAgICAgICAgIGlmIChudWRnZWRUb29GYXJEb3duID4gbnVkZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gTmVpdGhlciB3YXkgZml0czsgYWJvcnRcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRvcCAtPSBudWRnZWRUb29GYXJEb3duO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gTm93IGp1c3QgcmVhZCBvZmYgdGhlIGJpdHNcbiAgICAgICAgICAgIGNvbnN0IGJpdHMgPSBuZXcgQml0TWF0cml4KG1hdHJpeFdpZHRoLCBtYXRyaXhIZWlnaHQpO1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCBtYXRyaXhIZWlnaHQ7IHkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGlPZmZzZXQgPSB0b3AgKyAvKihpbnQpICovIE1hdGguZmxvb3IoeSAqIG1vZHVsZVNpemUpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgbWF0cml4V2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW1hZ2UuZ2V0KGxlZnQgKyAvKihpbnQpICovIE1hdGguZmxvb3IoeCAqIG1vZHVsZVNpemUpLCBpT2Zmc2V0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYml0cy5zZXQoeCwgeSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYml0cztcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgbW9kdWxlU2l6ZShsZWZ0VG9wQmxhY2ssIGltYWdlKSB7XG4gICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBpbWFnZS5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gaW1hZ2UuZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGxldCB4ID0gbGVmdFRvcEJsYWNrWzBdO1xuICAgICAgICAgICAgbGV0IHkgPSBsZWZ0VG9wQmxhY2tbMV07XG4gICAgICAgICAgICBsZXQgaW5CbGFjayA9IHRydWU7XG4gICAgICAgICAgICBsZXQgdHJhbnNpdGlvbnMgPSAwO1xuICAgICAgICAgICAgd2hpbGUgKHggPCB3aWR0aCAmJiB5IDwgaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGluQmxhY2sgIT09IGltYWdlLmdldCh4LCB5KSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoKyt0cmFuc2l0aW9ucyA9PT0gNSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaW5CbGFjayA9ICFpbkJsYWNrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB4Kys7XG4gICAgICAgICAgICAgICAgeSsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHggPT09IHdpZHRoIHx8IHkgPT09IGhlaWdodCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICh4IC0gbGVmdFRvcEJsYWNrWzBdKSAvIDcuMDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBRUkNvZGVSZWFkZXIuTk9fUE9JTlRTID0gbmV3IEFycmF5KCk7XG5cbiAgICAvKlxuICAgICogQ29weXJpZ2h0IDIwMDkgWlhpbmcgYXV0aG9yc1xuICAgICpcbiAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAqXG4gICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICpcbiAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgKi9cbiAgICAvKipcbiAgICAgKiBAYXV0aG9yIFNJVEEgTGFiIChrZXZpbi5vc3VsbGl2YW5Ac2l0YS5hZXJvKVxuICAgICAqIEBhdXRob3IgR3VlbnRoZXIgR3JhdVxuICAgICAqL1xuICAgIC8qcHVibGljIGZpbmFsKi8gY2xhc3MgUERGNDE3Q29tbW9uIHtcbiAgICAgICAgUERGNDE3Q29tbW9uKCkge1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gbW9kdWxlQml0Q291bnQgdmFsdWVzIHRvIHN1bVxuICAgICAgICAgKiBAcmV0dXJuIHN1bSBvZiB2YWx1ZXNcbiAgICAgICAgICogQGRlcHJlY2F0ZWQgY2FsbCB7QGxpbmsgTWF0aFV0aWxzI3N1bShpbnRbXSl9XG4gICAgICAgICAqL1xuICAgICAgICAvLyBARGVwcmVjYXRlZFxuICAgICAgICBzdGF0aWMgZ2V0Qml0Q291bnRTdW0obW9kdWxlQml0Q291bnQpIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoVXRpbHMuc3VtKG1vZHVsZUJpdENvdW50KTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgdG9JbnRBcnJheShsaXN0KSB7XG4gICAgICAgICAgICBpZiAobGlzdCA9PSBudWxsIHx8ICFsaXN0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBQREY0MTdDb21tb24uRU1QVFlfSU5UX0FSUkFZO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IEludDMyQXJyYXkobGlzdC5sZW5ndGgpO1xuICAgICAgICAgICAgbGV0IGkgPSAwO1xuICAgICAgICAgICAgZm9yIChjb25zdCBpbnRlZ2VyIG9mIGxpc3QpIHtcbiAgICAgICAgICAgICAgICByZXN1bHRbaSsrXSA9IGludGVnZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gc3ltYm9sIGVuY29kZWQgc3ltYm9sIHRvIHRyYW5zbGF0ZSB0byBhIGNvZGV3b3JkXG4gICAgICAgICAqIEByZXR1cm4gdGhlIGNvZGV3b3JkIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHN5bWJvbC5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBnZXRDb2Rld29yZChzeW1ib2wgLyppbnQqLykge1xuICAgICAgICAgICAgY29uc3QgaSA9IEFycmF5cy5iaW5hcnlTZWFyY2goUERGNDE3Q29tbW9uLlNZTUJPTF9UQUJMRSwgc3ltYm9sICYgMHgzRkZGRik7XG4gICAgICAgICAgICBpZiAoaSA8IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gKFBERjQxN0NvbW1vbi5DT0RFV09SRF9UQUJMRVtpXSAtIDEpICUgUERGNDE3Q29tbW9uLk5VTUJFUl9PRl9DT0RFV09SRFM7XG4gICAgICAgIH1cbiAgICB9XG4gICAgUERGNDE3Q29tbW9uLk5VTUJFUl9PRl9DT0RFV09SRFMgPSA5Mjk7XG4gICAgLy8gTWF4aW11bSBDb2Rld29yZHMgKERhdGEgKyBFcnJvcikuXG4gICAgUERGNDE3Q29tbW9uLk1BWF9DT0RFV09SRFNfSU5fQkFSQ09ERSA9IFBERjQxN0NvbW1vbi5OVU1CRVJfT0ZfQ09ERVdPUkRTIC0gMTtcbiAgICBQREY0MTdDb21tb24uTUlOX1JPV1NfSU5fQkFSQ09ERSA9IDM7XG4gICAgUERGNDE3Q29tbW9uLk1BWF9ST1dTX0lOX0JBUkNPREUgPSA5MDtcbiAgICAvLyBPbmUgbGVmdCByb3cgaW5kaWNhdGlvbiBjb2x1bW4gKyBtYXggMzAgZGF0YSBjb2x1bW5zICsgb25lIHJpZ2h0IHJvdyBpbmRpY2F0b3IgY29sdW1uXG4gICAgLy8gcHVibGljIHN0YXRpYyAvKmZpbmFsKi8gTUFYX0NPREVXT1JEU19JTl9ST1c6IC8qaW50Ki8gbnVtYmVyID0gMzI7XG4gICAgUERGNDE3Q29tbW9uLk1PRFVMRVNfSU5fQ09ERVdPUkQgPSAxNztcbiAgICBQREY0MTdDb21tb24uTU9EVUxFU19JTl9TVE9QX1BBVFRFUk4gPSAxODtcbiAgICBQREY0MTdDb21tb24uQkFSU19JTl9NT0RVTEUgPSA4O1xuICAgIFBERjQxN0NvbW1vbi5FTVBUWV9JTlRfQVJSQVkgPSBuZXcgSW50MzJBcnJheShbXSk7XG4gICAgLyoqXG4gICAgICogVGhlIHNvcnRlZCB0YWJsZSBvZiBhbGwgcG9zc2libGUgc3ltYm9scy4gRXh0cmFjdGVkIGZyb20gdGhlIFBERjQxN1xuICAgICAqIHNwZWNpZmljYXRpb24uIFRoZSBpbmRleCBvZiBhIHN5bWJvbCBpbiB0aGlzIHRhYmxlIGNvcnJlc3BvbmRzIHRvIHRoZVxuICAgICAqIGluZGV4IGludG8gdGhlIGNvZGV3b3JkIHRhYmxlLlxuICAgICAqL1xuICAgIFBERjQxN0NvbW1vbi5TWU1CT0xfVEFCTEUgPSBJbnQzMkFycmF5LmZyb20oW1xuICAgICAgICAweDEwMjVlLCAweDEwMjdhLCAweDEwMjllLCAweDEwMmJjLCAweDEwMmYyLCAweDEwMmY0LCAweDEwMzJlLCAweDEwMzRlLCAweDEwMzVjLCAweDEwMzk2LCAweDEwM2E2LCAweDEwM2FjLFxuICAgICAgICAweDEwNDIyLCAweDEwNDI4LCAweDEwNDM2LCAweDEwNDQyLCAweDEwNDQ0LCAweDEwNDQ4LCAweDEwNDUwLCAweDEwNDVlLCAweDEwNDY2LCAweDEwNDZjLCAweDEwNDdhLCAweDEwNDgyLFxuICAgICAgICAweDEwNDllLCAweDEwNGEwLCAweDEwNGJjLCAweDEwNGM2LCAweDEwNGQ4LCAweDEwNGVlLCAweDEwNGYyLCAweDEwNGY0LCAweDEwNTA0LCAweDEwNTA4LCAweDEwNTEwLCAweDEwNTFlLFxuICAgICAgICAweDEwNTIwLCAweDEwNTNjLCAweDEwNTQwLCAweDEwNTc4LCAweDEwNTg2LCAweDEwNThjLCAweDEwNTk4LCAweDEwNWIwLCAweDEwNWJlLCAweDEwNWNlLCAweDEwNWRjLCAweDEwNWUyLFxuICAgICAgICAweDEwNWU0LCAweDEwNWU4LCAweDEwNWY2LCAweDEwNjJlLCAweDEwNjRlLCAweDEwNjVjLCAweDEwNjhlLCAweDEwNjljLCAweDEwNmI4LCAweDEwNmRlLCAweDEwNmZhLCAweDEwNzE2LFxuICAgICAgICAweDEwNzI2LCAweDEwNzJjLCAweDEwNzQ2LCAweDEwNzRjLCAweDEwNzU4LCAweDEwNzZlLCAweDEwNzkyLCAweDEwNzk0LCAweDEwN2EyLCAweDEwN2E0LCAweDEwN2E4LCAweDEwN2I2LFxuICAgICAgICAweDEwODIyLCAweDEwODI4LCAweDEwODQyLCAweDEwODQ4LCAweDEwODUwLCAweDEwODVlLCAweDEwODY2LCAweDEwODZjLCAweDEwODdhLCAweDEwODgyLCAweDEwODg0LCAweDEwODkwLFxuICAgICAgICAweDEwODllLCAweDEwOGEwLCAweDEwOGJjLCAweDEwOGM2LCAweDEwOGNjLCAweDEwOGQ4LCAweDEwOGVlLCAweDEwOGYyLCAweDEwOGY0LCAweDEwOTAyLCAweDEwOTA4LCAweDEwOTFlLFxuICAgICAgICAweDEwOTIwLCAweDEwOTNjLCAweDEwOTQwLCAweDEwOTc4LCAweDEwOTg2LCAweDEwOTk4LCAweDEwOWIwLCAweDEwOWJlLCAweDEwOWNlLCAweDEwOWRjLCAweDEwOWUyLCAweDEwOWU0LFxuICAgICAgICAweDEwOWU4LCAweDEwOWY2LCAweDEwYTA4LCAweDEwYTEwLCAweDEwYTFlLCAweDEwYTIwLCAweDEwYTNjLCAweDEwYTQwLCAweDEwYTc4LCAweDEwYWYwLCAweDEwYjA2LCAweDEwYjBjLFxuICAgICAgICAweDEwYjE4LCAweDEwYjMwLCAweDEwYjNlLCAweDEwYjYwLCAweDEwYjdjLCAweDEwYjhlLCAweDEwYjljLCAweDEwYmI4LCAweDEwYmMyLCAweDEwYmM0LCAweDEwYmM4LCAweDEwYmQwLFxuICAgICAgICAweDEwYmRlLCAweDEwYmU2LCAweDEwYmVjLCAweDEwYzJlLCAweDEwYzRlLCAweDEwYzVjLCAweDEwYzYyLCAweDEwYzY0LCAweDEwYzY4LCAweDEwYzc2LCAweDEwYzhlLCAweDEwYzljLFxuICAgICAgICAweDEwY2I4LCAweDEwY2MyLCAweDEwY2M0LCAweDEwY2M4LCAweDEwY2QwLCAweDEwY2RlLCAweDEwY2U2LCAweDEwY2VjLCAweDEwY2ZhLCAweDEwZDBlLCAweDEwZDFjLCAweDEwZDM4LFxuICAgICAgICAweDEwZDcwLCAweDEwZDdlLCAweDEwZDgyLCAweDEwZDg0LCAweDEwZDg4LCAweDEwZDkwLCAweDEwZDllLCAweDEwZGEwLCAweDEwZGJjLCAweDEwZGM2LCAweDEwZGNjLCAweDEwZGQ4LFxuICAgICAgICAweDEwZGVlLCAweDEwZGYyLCAweDEwZGY0LCAweDEwZTE2LCAweDEwZTI2LCAweDEwZTJjLCAweDEwZTQ2LCAweDEwZTU4LCAweDEwZTZlLCAweDEwZTg2LCAweDEwZThjLCAweDEwZTk4LFxuICAgICAgICAweDEwZWIwLCAweDEwZWJlLCAweDEwZWNlLCAweDEwZWRjLCAweDEwZjBhLCAweDEwZjEyLCAweDEwZjE0LCAweDEwZjIyLCAweDEwZjI4LCAweDEwZjM2LCAweDEwZjQyLCAweDEwZjQ0LFxuICAgICAgICAweDEwZjQ4LCAweDEwZjUwLCAweDEwZjVlLCAweDEwZjY2LCAweDEwZjZjLCAweDEwZmIyLCAweDEwZmI0LCAweDExMDIyLCAweDExMDI4LCAweDExMDQyLCAweDExMDQ4LCAweDExMDUwLFxuICAgICAgICAweDExMDVlLCAweDExMDdhLCAweDExMDgyLCAweDExMDg0LCAweDExMDkwLCAweDExMDllLCAweDExMGEwLCAweDExMGJjLCAweDExMGM2LCAweDExMGNjLCAweDExMGQ4LCAweDExMGVlLFxuICAgICAgICAweDExMGYyLCAweDExMGY0LCAweDExMTAyLCAweDExMTFlLCAweDExMTIwLCAweDExMTNjLCAweDExMTQwLCAweDExMTc4LCAweDExMTg2LCAweDExMTk4LCAweDExMWIwLCAweDExMWJlLFxuICAgICAgICAweDExMWNlLCAweDExMWRjLCAweDExMWUyLCAweDExMWU0LCAweDExMWU4LCAweDExMWY2LCAweDExMjA4LCAweDExMjFlLCAweDExMjIwLCAweDExMjc4LCAweDExMmYwLCAweDExMzBjLFxuICAgICAgICAweDExMzMwLCAweDExMzNlLCAweDExMzYwLCAweDExMzdjLCAweDExMzhlLCAweDExMzljLCAweDExM2I4LCAweDExM2MyLCAweDExM2M4LCAweDExM2QwLCAweDExM2RlLCAweDExM2U2LFxuICAgICAgICAweDExM2VjLCAweDExNDA4LCAweDExNDEwLCAweDExNDFlLCAweDExNDIwLCAweDExNDNjLCAweDExNDQwLCAweDExNDc4LCAweDExNGYwLCAweDExNWUwLCAweDExNjBjLCAweDExNjE4LFxuICAgICAgICAweDExNjMwLCAweDExNjNlLCAweDExNjYwLCAweDExNjdjLCAweDExNmMwLCAweDExNmY4LCAweDExNzFjLCAweDExNzM4LCAweDExNzcwLCAweDExNzdlLCAweDExNzgyLCAweDExNzg0LFxuICAgICAgICAweDExNzg4LCAweDExNzkwLCAweDExNzllLCAweDExN2EwLCAweDExN2JjLCAweDExN2M2LCAweDExN2NjLCAweDExN2Q4LCAweDExN2VlLCAweDExODJlLCAweDExODM0LCAweDExODRlLFxuICAgICAgICAweDExODVjLCAweDExODYyLCAweDExODY0LCAweDExODY4LCAweDExODc2LCAweDExODhlLCAweDExODljLCAweDExOGI4LCAweDExOGMyLCAweDExOGM4LCAweDExOGQwLCAweDExOGRlLFxuICAgICAgICAweDExOGU2LCAweDExOGVjLCAweDExOGZhLCAweDExOTBlLCAweDExOTFjLCAweDExOTM4LCAweDExOTcwLCAweDExOTdlLCAweDExOTgyLCAweDExOTg0LCAweDExOTkwLCAweDExOTllLFxuICAgICAgICAweDExOWEwLCAweDExOWJjLCAweDExOWM2LCAweDExOWNjLCAweDExOWQ4LCAweDExOWVlLCAweDExOWYyLCAweDExOWY0LCAweDExYTBlLCAweDExYTFjLCAweDExYTM4LCAweDExYTcwLFxuICAgICAgICAweDExYTdlLCAweDExYWUwLCAweDExYWZjLCAweDExYjA4LCAweDExYjEwLCAweDExYjFlLCAweDExYjIwLCAweDExYjNjLCAweDExYjQwLCAweDExYjc4LCAweDExYjhjLCAweDExYjk4LFxuICAgICAgICAweDExYmIwLCAweDExYmJlLCAweDExYmNlLCAweDExYmRjLCAweDExYmUyLCAweDExYmU0LCAweDExYmU4LCAweDExYmY2LCAweDExYzE2LCAweDExYzI2LCAweDExYzJjLCAweDExYzQ2LFxuICAgICAgICAweDExYzRjLCAweDExYzU4LCAweDExYzZlLCAweDExYzg2LCAweDExYzk4LCAweDExY2IwLCAweDExY2JlLCAweDExY2NlLCAweDExY2RjLCAweDExY2UyLCAweDExY2U0LCAweDExY2U4LFxuICAgICAgICAweDExY2Y2LCAweDExZDA2LCAweDExZDBjLCAweDExZDE4LCAweDExZDMwLCAweDExZDNlLCAweDExZDYwLCAweDExZDdjLCAweDExZDhlLCAweDExZDljLCAweDExZGI4LCAweDExZGM0LFxuICAgICAgICAweDExZGM4LCAweDExZGQwLCAweDExZGRlLCAweDExZGU2LCAweDExZGVjLCAweDExZGZhLCAweDExZTBhLCAweDExZTEyLCAweDExZTE0LCAweDExZTIyLCAweDExZTI0LCAweDExZTI4LFxuICAgICAgICAweDExZTM2LCAweDExZTQyLCAweDExZTQ0LCAweDExZTUwLCAweDExZTVlLCAweDExZTY2LCAweDExZTZjLCAweDExZTgyLCAweDExZTg0LCAweDExZTg4LCAweDExZTkwLCAweDExZTllLFxuICAgICAgICAweDExZWEwLCAweDExZWJjLCAweDExZWM2LCAweDExZWNjLCAweDExZWQ4LCAweDExZWVlLCAweDExZjFhLCAweDExZjJlLCAweDExZjMyLCAweDExZjM0LCAweDExZjRlLCAweDExZjVjLFxuICAgICAgICAweDExZjYyLCAweDExZjY0LCAweDExZjY4LCAweDExZjc2LCAweDEyMDQ4LCAweDEyMDVlLCAweDEyMDgyLCAweDEyMDg0LCAweDEyMDkwLCAweDEyMDllLCAweDEyMGEwLCAweDEyMGJjLFxuICAgICAgICAweDEyMGQ4LCAweDEyMGYyLCAweDEyMGY0LCAweDEyMTA4LCAweDEyMTFlLCAweDEyMTIwLCAweDEyMTNjLCAweDEyMTQwLCAweDEyMTc4LCAweDEyMTg2LCAweDEyMTk4LCAweDEyMWIwLFxuICAgICAgICAweDEyMWJlLCAweDEyMWUyLCAweDEyMWU0LCAweDEyMWU4LCAweDEyMWY2LCAweDEyMjA0LCAweDEyMjEwLCAweDEyMjFlLCAweDEyMjIwLCAweDEyMjc4LCAweDEyMmYwLCAweDEyMzA2LFxuICAgICAgICAweDEyMzBjLCAweDEyMzMwLCAweDEyMzNlLCAweDEyMzYwLCAweDEyMzdjLCAweDEyMzhlLCAweDEyMzljLCAweDEyM2I4LCAweDEyM2MyLCAweDEyM2M4LCAweDEyM2QwLCAweDEyM2U2LFxuICAgICAgICAweDEyM2VjLCAweDEyNDFlLCAweDEyNDIwLCAweDEyNDNjLCAweDEyNGYwLCAweDEyNWUwLCAweDEyNjE4LCAweDEyNjNlLCAweDEyNjYwLCAweDEyNjdjLCAweDEyNmMwLCAweDEyNmY4LFxuICAgICAgICAweDEyNzM4LCAweDEyNzcwLCAweDEyNzdlLCAweDEyNzgyLCAweDEyNzg0LCAweDEyNzkwLCAweDEyNzllLCAweDEyN2EwLCAweDEyN2JjLCAweDEyN2M2LCAweDEyN2NjLCAweDEyN2Q4LFxuICAgICAgICAweDEyN2VlLCAweDEyODIwLCAweDEyODNjLCAweDEyODQwLCAweDEyODc4LCAweDEyOGYwLCAweDEyOWUwLCAweDEyYmMwLCAweDEyYzE4LCAweDEyYzMwLCAweDEyYzNlLCAweDEyYzYwLFxuICAgICAgICAweDEyYzdjLCAweDEyY2MwLCAweDEyY2Y4LCAweDEyZGYwLCAweDEyZTFjLCAweDEyZTM4LCAweDEyZTcwLCAweDEyZTdlLCAweDEyZWUwLCAweDEyZWZjLCAweDEyZjA0LCAweDEyZjA4LFxuICAgICAgICAweDEyZjEwLCAweDEyZjIwLCAweDEyZjNjLCAweDEyZjQwLCAweDEyZjc4LCAweDEyZjg2LCAweDEyZjhjLCAweDEyZjk4LCAweDEyZmIwLCAweDEyZmJlLCAweDEyZmNlLCAweDEyZmRjLFxuICAgICAgICAweDEzMDJlLCAweDEzMDRlLCAweDEzMDVjLCAweDEzMDYyLCAweDEzMDY4LCAweDEzMDhlLCAweDEzMDljLCAweDEzMGI4LCAweDEzMGMyLCAweDEzMGM4LCAweDEzMGQwLCAweDEzMGRlLFxuICAgICAgICAweDEzMGVjLCAweDEzMGZhLCAweDEzMTBlLCAweDEzMTM4LCAweDEzMTcwLCAweDEzMTdlLCAweDEzMTgyLCAweDEzMTg0LCAweDEzMTkwLCAweDEzMTllLCAweDEzMWEwLCAweDEzMWJjLFxuICAgICAgICAweDEzMWM2LCAweDEzMWNjLCAweDEzMWQ4LCAweDEzMWYyLCAweDEzMWY0LCAweDEzMjBlLCAweDEzMjFjLCAweDEzMjcwLCAweDEzMjdlLCAweDEzMmUwLCAweDEzMmZjLCAweDEzMzA4LFxuICAgICAgICAweDEzMzFlLCAweDEzMzIwLCAweDEzMzNjLCAweDEzMzQwLCAweDEzMzc4LCAweDEzMzg2LCAweDEzMzk4LCAweDEzM2IwLCAweDEzM2JlLCAweDEzM2NlLCAweDEzM2RjLCAweDEzM2UyLFxuICAgICAgICAweDEzM2U0LCAweDEzM2U4LCAweDEzM2Y2LCAweDEzNDBlLCAweDEzNDFjLCAweDEzNDM4LCAweDEzNDcwLCAweDEzNDdlLCAweDEzNGUwLCAweDEzNGZjLCAweDEzNWMwLCAweDEzNWY4LFxuICAgICAgICAweDEzNjA4LCAweDEzNjEwLCAweDEzNjFlLCAweDEzNjIwLCAweDEzNjNjLCAweDEzNjQwLCAweDEzNjc4LCAweDEzNmYwLCAweDEzNzBjLCAweDEzNzE4LCAweDEzNzMwLCAweDEzNzNlLFxuICAgICAgICAweDEzNzYwLCAweDEzNzdjLCAweDEzNzljLCAweDEzN2I4LCAweDEzN2MyLCAweDEzN2M0LCAweDEzN2M4LCAweDEzN2QwLCAweDEzN2RlLCAweDEzN2U2LCAweDEzN2VjLCAweDEzODE2LFxuICAgICAgICAweDEzODI2LCAweDEzODJjLCAweDEzODQ2LCAweDEzODRjLCAweDEzODU4LCAweDEzODZlLCAweDEzODc0LCAweDEzODg2LCAweDEzODk4LCAweDEzOGIwLCAweDEzOGJlLCAweDEzOGNlLFxuICAgICAgICAweDEzOGRjLCAweDEzOGUyLCAweDEzOGU0LCAweDEzOGU4LCAweDEzOTA2LCAweDEzOTBjLCAweDEzOTMwLCAweDEzOTNlLCAweDEzOTYwLCAweDEzOTdjLCAweDEzOThlLCAweDEzOTljLFxuICAgICAgICAweDEzOWI4LCAweDEzOWM4LCAweDEzOWQwLCAweDEzOWRlLCAweDEzOWU2LCAweDEzOWVjLCAweDEzOWZhLCAweDEzYTA2LCAweDEzYTBjLCAweDEzYTE4LCAweDEzYTMwLCAweDEzYTNlLFxuICAgICAgICAweDEzYTYwLCAweDEzYTdjLCAweDEzYWMwLCAweDEzYWY4LCAweDEzYjBlLCAweDEzYjFjLCAweDEzYjM4LCAweDEzYjcwLCAweDEzYjdlLCAweDEzYjg4LCAweDEzYjkwLCAweDEzYjllLFxuICAgICAgICAweDEzYmEwLCAweDEzYmJjLCAweDEzYmNjLCAweDEzYmQ4LCAweDEzYmVlLCAweDEzYmYyLCAweDEzYmY0LCAweDEzYzEyLCAweDEzYzE0LCAweDEzYzIyLCAweDEzYzI0LCAweDEzYzI4LFxuICAgICAgICAweDEzYzM2LCAweDEzYzQyLCAweDEzYzQ4LCAweDEzYzUwLCAweDEzYzVlLCAweDEzYzY2LCAweDEzYzZjLCAweDEzYzgyLCAweDEzYzg0LCAweDEzYzkwLCAweDEzYzllLCAweDEzY2EwLFxuICAgICAgICAweDEzY2JjLCAweDEzY2M2LCAweDEzY2NjLCAweDEzY2Q4LCAweDEzY2VlLCAweDEzZDAyLCAweDEzZDA0LCAweDEzZDA4LCAweDEzZDEwLCAweDEzZDFlLCAweDEzZDIwLCAweDEzZDNjLFxuICAgICAgICAweDEzZDQwLCAweDEzZDc4LCAweDEzZDg2LCAweDEzZDhjLCAweDEzZDk4LCAweDEzZGIwLCAweDEzZGJlLCAweDEzZGNlLCAweDEzZGRjLCAweDEzZGU0LCAweDEzZGU4LCAweDEzZGY2LFxuICAgICAgICAweDEzZTFhLCAweDEzZTJlLCAweDEzZTMyLCAweDEzZTM0LCAweDEzZTRlLCAweDEzZTVjLCAweDEzZTYyLCAweDEzZTY0LCAweDEzZTY4LCAweDEzZTc2LCAweDEzZThlLCAweDEzZTljLFxuICAgICAgICAweDEzZWI4LCAweDEzZWMyLCAweDEzZWM0LCAweDEzZWM4LCAweDEzZWQwLCAweDEzZWRlLCAweDEzZWU2LCAweDEzZWVjLCAweDEzZjI2LCAweDEzZjJjLCAweDEzZjNhLCAweDEzZjQ2LFxuICAgICAgICAweDEzZjRjLCAweDEzZjU4LCAweDEzZjZlLCAweDEzZjcyLCAweDEzZjc0LCAweDE0MDgyLCAweDE0MDllLCAweDE0MGEwLCAweDE0MGJjLCAweDE0MTA0LCAweDE0MTA4LCAweDE0MTEwLFxuICAgICAgICAweDE0MTFlLCAweDE0MTIwLCAweDE0MTNjLCAweDE0MTQwLCAweDE0MTc4LCAweDE0MThjLCAweDE0MTk4LCAweDE0MWIwLCAweDE0MWJlLCAweDE0MWUyLCAweDE0MWU0LCAweDE0MWU4LFxuICAgICAgICAweDE0MjA4LCAweDE0MjEwLCAweDE0MjFlLCAweDE0MjIwLCAweDE0MjNjLCAweDE0MjQwLCAweDE0Mjc4LCAweDE0MmYwLCAweDE0MzA2LCAweDE0MzBjLCAweDE0MzE4LCAweDE0MzMwLFxuICAgICAgICAweDE0MzNlLCAweDE0MzYwLCAweDE0MzdjLCAweDE0MzhlLCAweDE0M2MyLCAweDE0M2M0LCAweDE0M2M4LCAweDE0M2QwLCAweDE0M2U2LCAweDE0M2VjLCAweDE0NDA4LCAweDE0NDEwLFxuICAgICAgICAweDE0NDFlLCAweDE0NDIwLCAweDE0NDNjLCAweDE0NDQwLCAweDE0NDc4LCAweDE0NGYwLCAweDE0NWUwLCAweDE0NjBjLCAweDE0NjE4LCAweDE0NjMwLCAweDE0NjNlLCAweDE0NjYwLFxuICAgICAgICAweDE0NjdjLCAweDE0NmMwLCAweDE0NmY4LCAweDE0NzFjLCAweDE0NzM4LCAweDE0NzcwLCAweDE0NzdlLCAweDE0NzgyLCAweDE0Nzg0LCAweDE0Nzg4LCAweDE0NzkwLCAweDE0N2EwLFxuICAgICAgICAweDE0N2JjLCAweDE0N2M2LCAweDE0N2NjLCAweDE0N2Q4LCAweDE0N2VlLCAweDE0ODEwLCAweDE0ODIwLCAweDE0ODNjLCAweDE0ODQwLCAweDE0ODc4LCAweDE0OGYwLCAweDE0OWUwLFxuICAgICAgICAweDE0YmMwLCAweDE0YzMwLCAweDE0YzNlLCAweDE0YzYwLCAweDE0YzdjLCAweDE0Y2MwLCAweDE0Y2Y4LCAweDE0ZGYwLCAweDE0ZTM4LCAweDE0ZTcwLCAweDE0ZTdlLCAweDE0ZWUwLFxuICAgICAgICAweDE0ZWZjLCAweDE0ZjA0LCAweDE0ZjA4LCAweDE0ZjEwLCAweDE0ZjFlLCAweDE0ZjIwLCAweDE0ZjNjLCAweDE0ZjQwLCAweDE0Zjc4LCAweDE0Zjg2LCAweDE0ZjhjLCAweDE0Zjk4LFxuICAgICAgICAweDE0ZmIwLCAweDE0ZmNlLCAweDE0ZmRjLCAweDE1MDIwLCAweDE1MDQwLCAweDE1MDc4LCAweDE1MGYwLCAweDE1MWUwLCAweDE1M2MwLCAweDE1ODYwLCAweDE1ODdjLCAweDE1OGMwLFxuICAgICAgICAweDE1OGY4LCAweDE1OWYwLCAweDE1YmUwLCAweDE1YzcwLCAweDE1YzdlLCAweDE1Y2UwLCAweDE1Y2ZjLCAweDE1ZGMwLCAweDE1ZGY4LCAweDE1ZTA4LCAweDE1ZTEwLCAweDE1ZTIwLFxuICAgICAgICAweDE1ZTQwLCAweDE1ZTc4LCAweDE1ZWYwLCAweDE1ZjBjLCAweDE1ZjE4LCAweDE1ZjMwLCAweDE1ZjYwLCAweDE1ZjdjLCAweDE1ZjhlLCAweDE1ZjljLCAweDE1ZmI4LCAweDE2MDRlLFxuICAgICAgICAweDE2MDVjLCAweDE2MDhlLCAweDE2MDljLCAweDE2MGI4LCAweDE2MGMyLCAweDE2MGM0LCAweDE2MGM4LCAweDE2MGRlLCAweDE2MTBlLCAweDE2MTFjLCAweDE2MTM4LCAweDE2MTcwLFxuICAgICAgICAweDE2MTdlLCAweDE2MTg0LCAweDE2MTg4LCAweDE2MTkwLCAweDE2MTllLCAweDE2MWEwLCAweDE2MWJjLCAweDE2MWM2LCAweDE2MWNjLCAweDE2MWQ4LCAweDE2MWYyLCAweDE2MWY0LFxuICAgICAgICAweDE2MjBlLCAweDE2MjFjLCAweDE2MjM4LCAweDE2MjcwLCAweDE2MjdlLCAweDE2MmUwLCAweDE2MmZjLCAweDE2MzA0LCAweDE2MzA4LCAweDE2MzEwLCAweDE2MzFlLCAweDE2MzIwLFxuICAgICAgICAweDE2MzNjLCAweDE2MzQwLCAweDE2Mzc4LCAweDE2Mzg2LCAweDE2MzhjLCAweDE2Mzk4LCAweDE2M2IwLCAweDE2M2JlLCAweDE2M2NlLCAweDE2M2RjLCAweDE2M2UyLCAweDE2M2U0LFxuICAgICAgICAweDE2M2U4LCAweDE2M2Y2LCAweDE2NDBlLCAweDE2NDFjLCAweDE2NDM4LCAweDE2NDcwLCAweDE2NDdlLCAweDE2NGUwLCAweDE2NGZjLCAweDE2NWMwLCAweDE2NWY4LCAweDE2NjEwLFxuICAgICAgICAweDE2NjFlLCAweDE2NjIwLCAweDE2NjNjLCAweDE2NjQwLCAweDE2Njc4LCAweDE2NmYwLCAweDE2NzE4LCAweDE2NzMwLCAweDE2NzNlLCAweDE2NzYwLCAweDE2NzdjLCAweDE2NzhlLFxuICAgICAgICAweDE2NzljLCAweDE2N2I4LCAweDE2N2MyLCAweDE2N2M0LCAweDE2N2M4LCAweDE2N2QwLCAweDE2N2RlLCAweDE2N2U2LCAweDE2N2VjLCAweDE2ODFjLCAweDE2ODM4LCAweDE2ODcwLFxuICAgICAgICAweDE2OGUwLCAweDE2OGZjLCAweDE2OWMwLCAweDE2OWY4LCAweDE2YmYwLCAweDE2YzEwLCAweDE2YzFlLCAweDE2YzIwLCAweDE2YzNjLCAweDE2YzQwLCAweDE2Yzc4LCAweDE2Y2YwLFxuICAgICAgICAweDE2ZGUwLCAweDE2ZTE4LCAweDE2ZTMwLCAweDE2ZTNlLCAweDE2ZTYwLCAweDE2ZTdjLCAweDE2ZWMwLCAweDE2ZWY4LCAweDE2ZjFjLCAweDE2ZjM4LCAweDE2ZjcwLCAweDE2ZjdlLFxuICAgICAgICAweDE2Zjg0LCAweDE2Zjg4LCAweDE2ZjkwLCAweDE2ZjllLCAweDE2ZmEwLCAweDE2ZmJjLCAweDE2ZmM2LCAweDE2ZmNjLCAweDE2ZmQ4LCAweDE3MDI2LCAweDE3MDJjLCAweDE3MDQ2LFxuICAgICAgICAweDE3MDRjLCAweDE3MDU4LCAweDE3MDZlLCAweDE3MDg2LCAweDE3MDhjLCAweDE3MDk4LCAweDE3MGIwLCAweDE3MGJlLCAweDE3MGNlLCAweDE3MGRjLCAweDE3MGU4LCAweDE3MTA2LFxuICAgICAgICAweDE3MTBjLCAweDE3MTE4LCAweDE3MTMwLCAweDE3MTNlLCAweDE3MTYwLCAweDE3MTdjLCAweDE3MThlLCAweDE3MTljLCAweDE3MWI4LCAweDE3MWMyLCAweDE3MWM0LCAweDE3MWM4LFxuICAgICAgICAweDE3MWQwLCAweDE3MWRlLCAweDE3MWU2LCAweDE3MWVjLCAweDE3MWZhLCAweDE3MjA2LCAweDE3MjBjLCAweDE3MjE4LCAweDE3MjMwLCAweDE3MjNlLCAweDE3MjYwLCAweDE3MjdjLFxuICAgICAgICAweDE3MmMwLCAweDE3MmY4LCAweDE3MzBlLCAweDE3MzFjLCAweDE3MzM4LCAweDE3MzcwLCAweDE3MzdlLCAweDE3Mzg4LCAweDE3MzkwLCAweDE3MzllLCAweDE3M2EwLCAweDE3M2JjLFxuICAgICAgICAweDE3M2NjLCAweDE3M2Q4LCAweDE3M2VlLCAweDE3M2YyLCAweDE3M2Y0LCAweDE3NDBjLCAweDE3NDE4LCAweDE3NDMwLCAweDE3NDNlLCAweDE3NDYwLCAweDE3NDdjLCAweDE3NGMwLFxuICAgICAgICAweDE3NGY4LCAweDE3NWYwLCAweDE3NjBlLCAweDE3NjFjLCAweDE3NjM4LCAweDE3NjcwLCAweDE3NjdlLCAweDE3NmUwLCAweDE3NmZjLCAweDE3NzA4LCAweDE3NzEwLCAweDE3NzFlLFxuICAgICAgICAweDE3NzIwLCAweDE3NzNjLCAweDE3NzQwLCAweDE3Nzc4LCAweDE3Nzk4LCAweDE3N2IwLCAweDE3N2JlLCAweDE3N2RjLCAweDE3N2UyLCAweDE3N2U0LCAweDE3N2U4LCAweDE3ODIyLFxuICAgICAgICAweDE3ODI0LCAweDE3ODI4LCAweDE3ODM2LCAweDE3ODQyLCAweDE3ODQ0LCAweDE3ODQ4LCAweDE3ODUwLCAweDE3ODVlLCAweDE3ODY2LCAweDE3ODZjLCAweDE3ODgyLCAweDE3ODg0LFxuICAgICAgICAweDE3ODg4LCAweDE3ODkwLCAweDE3ODllLCAweDE3OGEwLCAweDE3OGJjLCAweDE3OGM2LCAweDE3OGNjLCAweDE3OGQ4LCAweDE3OGVlLCAweDE3OGYyLCAweDE3OGY0LCAweDE3OTAyLFxuICAgICAgICAweDE3OTA0LCAweDE3OTA4LCAweDE3OTEwLCAweDE3OTFlLCAweDE3OTIwLCAweDE3OTNjLCAweDE3OTQwLCAweDE3OTc4LCAweDE3OTg2LCAweDE3OThjLCAweDE3OTk4LCAweDE3OWIwLFxuICAgICAgICAweDE3OWJlLCAweDE3OWNlLCAweDE3OWRjLCAweDE3OWUyLCAweDE3OWU0LCAweDE3OWU4LCAweDE3OWY2LCAweDE3YTA0LCAweDE3YTA4LCAweDE3YTEwLCAweDE3YTFlLCAweDE3YTIwLFxuICAgICAgICAweDE3YTNjLCAweDE3YTQwLCAweDE3YTc4LCAweDE3YWYwLCAweDE3YjA2LCAweDE3YjBjLCAweDE3YjE4LCAweDE3YjMwLCAweDE3YjNlLCAweDE3YjYwLCAweDE3YjdjLCAweDE3YjhlLFxuICAgICAgICAweDE3YjljLCAweDE3YmI4LCAweDE3YmM0LCAweDE3YmM4LCAweDE3YmQwLCAweDE3YmRlLCAweDE3YmU2LCAweDE3YmVjLCAweDE3YzJlLCAweDE3YzMyLCAweDE3YzM0LCAweDE3YzRlLFxuICAgICAgICAweDE3YzVjLCAweDE3YzYyLCAweDE3YzY0LCAweDE3YzY4LCAweDE3Yzc2LCAweDE3YzhlLCAweDE3YzljLCAweDE3Y2I4LCAweDE3Y2MyLCAweDE3Y2M0LCAweDE3Y2M4LCAweDE3Y2QwLFxuICAgICAgICAweDE3Y2RlLCAweDE3Y2U2LCAweDE3Y2VjLCAweDE3ZDBlLCAweDE3ZDFjLCAweDE3ZDM4LCAweDE3ZDcwLCAweDE3ZDgyLCAweDE3ZDg0LCAweDE3ZDg4LCAweDE3ZDkwLCAweDE3ZDllLFxuICAgICAgICAweDE3ZGEwLCAweDE3ZGJjLCAweDE3ZGM2LCAweDE3ZGNjLCAweDE3ZGQ4LCAweDE3ZGVlLCAweDE3ZTI2LCAweDE3ZTJjLCAweDE3ZTNhLCAweDE3ZTQ2LCAweDE3ZTRjLCAweDE3ZTU4LFxuICAgICAgICAweDE3ZTZlLCAweDE3ZTcyLCAweDE3ZTc0LCAweDE3ZTg2LCAweDE3ZThjLCAweDE3ZTk4LCAweDE3ZWIwLCAweDE3ZWNlLCAweDE3ZWRjLCAweDE3ZWUyLCAweDE3ZWU0LCAweDE3ZWU4LFxuICAgICAgICAweDE3ZWY2LCAweDE4MTNhLCAweDE4MTcyLCAweDE4MTc0LCAweDE4MjE2LCAweDE4MjI2LCAweDE4MjNhLCAweDE4MjRjLCAweDE4MjU4LCAweDE4MjZlLCAweDE4MjcyLCAweDE4Mjc0LFxuICAgICAgICAweDE4Mjk4LCAweDE4MmJlLCAweDE4MmUyLCAweDE4MmU0LCAweDE4MmU4LCAweDE4MmY2LCAweDE4MzVlLCAweDE4MzdhLCAweDE4M2FlLCAweDE4M2Q2LCAweDE4NDE2LCAweDE4NDI2LFxuICAgICAgICAweDE4NDJjLCAweDE4NDNhLCAweDE4NDQ2LCAweDE4NDU4LCAweDE4NDZlLCAweDE4NDcyLCAweDE4NDc0LCAweDE4NDg2LCAweDE4NGIwLCAweDE4NGJlLCAweDE4NGNlLCAweDE4NGRjLFxuICAgICAgICAweDE4NGUyLCAweDE4NGU0LCAweDE4NGU4LCAweDE4NGY2LCAweDE4NTA2LCAweDE4NTBjLCAweDE4NTE4LCAweDE4NTMwLCAweDE4NTNlLCAweDE4NTYwLCAweDE4NTdjLCAweDE4NThlLFxuICAgICAgICAweDE4NTljLCAweDE4NWI4LCAweDE4NWMyLCAweDE4NWM0LCAweDE4NWM4LCAweDE4NWQwLCAweDE4NWRlLCAweDE4NWU2LCAweDE4NWVjLCAweDE4NWZhLCAweDE4NjEyLCAweDE4NjE0LFxuICAgICAgICAweDE4NjIyLCAweDE4NjI4LCAweDE4NjM2LCAweDE4NjQyLCAweDE4NjUwLCAweDE4NjVlLCAweDE4NjdhLCAweDE4NjgyLCAweDE4Njg0LCAweDE4Njg4LCAweDE4NjkwLCAweDE4NjllLFxuICAgICAgICAweDE4NmEwLCAweDE4NmJjLCAweDE4NmM2LCAweDE4NmNjLCAweDE4NmQ4LCAweDE4NmVlLCAweDE4NmYyLCAweDE4NmY0LCAweDE4NzJlLCAweDE4NzRlLCAweDE4NzVjLCAweDE4Nzk2LFxuICAgICAgICAweDE4N2E2LCAweDE4N2FjLCAweDE4N2QyLCAweDE4N2Q0LCAweDE4ODI2LCAweDE4ODJjLCAweDE4ODNhLCAweDE4ODQ2LCAweDE4ODRjLCAweDE4ODU4LCAweDE4ODZlLCAweDE4ODcyLFxuICAgICAgICAweDE4ODc0LCAweDE4ODg2LCAweDE4ODk4LCAweDE4OGIwLCAweDE4OGJlLCAweDE4OGNlLCAweDE4OGRjLCAweDE4OGUyLCAweDE4OGU0LCAweDE4OGU4LCAweDE4OGY2LCAweDE4OTBjLFxuICAgICAgICAweDE4OTMwLCAweDE4OTNlLCAweDE4OTYwLCAweDE4OTdjLCAweDE4OThlLCAweDE4OWI4LCAweDE4OWMyLCAweDE4OWM4LCAweDE4OWQwLCAweDE4OWRlLCAweDE4OWU2LCAweDE4OWVjLFxuICAgICAgICAweDE4OWZhLCAweDE4YTE4LCAweDE4YTMwLCAweDE4YTNlLCAweDE4YTYwLCAweDE4YTdjLCAweDE4YWMwLCAweDE4YWY4LCAweDE4YjFjLCAweDE4YjM4LCAweDE4YjcwLCAweDE4YjdlLFxuICAgICAgICAweDE4YjgyLCAweDE4Yjg0LCAweDE4Yjg4LCAweDE4YjkwLCAweDE4YjllLCAweDE4YmEwLCAweDE4YmJjLCAweDE4YmM2LCAweDE4YmNjLCAweDE4YmQ4LCAweDE4YmVlLCAweDE4YmYyLFxuICAgICAgICAweDE4YmY0LCAweDE4YzIyLCAweDE4YzI0LCAweDE4YzI4LCAweDE4YzM2LCAweDE4YzQyLCAweDE4YzQ4LCAweDE4YzUwLCAweDE4YzVlLCAweDE4YzY2LCAweDE4YzdhLCAweDE4YzgyLFxuICAgICAgICAweDE4Yzg0LCAweDE4YzkwLCAweDE4YzllLCAweDE4Y2EwLCAweDE4Y2JjLCAweDE4Y2NjLCAweDE4Y2YyLCAweDE4Y2Y0LCAweDE4ZDA0LCAweDE4ZDA4LCAweDE4ZDEwLCAweDE4ZDFlLFxuICAgICAgICAweDE4ZDIwLCAweDE4ZDNjLCAweDE4ZDQwLCAweDE4ZDc4LCAweDE4ZDg2LCAweDE4ZDk4LCAweDE4ZGNlLCAweDE4ZGUyLCAweDE4ZGU0LCAweDE4ZGU4LCAweDE4ZTJlLCAweDE4ZTMyLFxuICAgICAgICAweDE4ZTM0LCAweDE4ZTRlLCAweDE4ZTVjLCAweDE4ZTYyLCAweDE4ZTY0LCAweDE4ZTY4LCAweDE4ZThlLCAweDE4ZTljLCAweDE4ZWI4LCAweDE4ZWMyLCAweDE4ZWM0LCAweDE4ZWM4LFxuICAgICAgICAweDE4ZWQwLCAweDE4ZWZhLCAweDE4ZjE2LCAweDE4ZjI2LCAweDE4ZjJjLCAweDE4ZjQ2LCAweDE4ZjRjLCAweDE4ZjU4LCAweDE4ZjZlLCAweDE4ZjhhLCAweDE4ZjkyLCAweDE4Zjk0LFxuICAgICAgICAweDE4ZmEyLCAweDE4ZmE0LCAweDE4ZmE4LCAweDE4ZmI2LCAweDE5MDJjLCAweDE5MDNhLCAweDE5MDQ2LCAweDE5MDRjLCAweDE5MDU4LCAweDE5MDcyLCAweDE5MDc0LCAweDE5MDg2LFxuICAgICAgICAweDE5MDk4LCAweDE5MGIwLCAweDE5MGJlLCAweDE5MGNlLCAweDE5MGRjLCAweDE5MGUyLCAweDE5MGU4LCAweDE5MGY2LCAweDE5MTA2LCAweDE5MTBjLCAweDE5MTMwLCAweDE5MTNlLFxuICAgICAgICAweDE5MTYwLCAweDE5MTdjLCAweDE5MThlLCAweDE5MTljLCAweDE5MWI4LCAweDE5MWMyLCAweDE5MWM4LCAweDE5MWQwLCAweDE5MWRlLCAweDE5MWU2LCAweDE5MWVjLCAweDE5MWZhLFxuICAgICAgICAweDE5MjE4LCAweDE5MjNlLCAweDE5MjYwLCAweDE5MjdjLCAweDE5MmMwLCAweDE5MmY4LCAweDE5MzM4LCAweDE5MzcwLCAweDE5MzdlLCAweDE5MzgyLCAweDE5Mzg0LCAweDE5MzkwLFxuICAgICAgICAweDE5MzllLCAweDE5M2EwLCAweDE5M2JjLCAweDE5M2M2LCAweDE5M2NjLCAweDE5M2Q4LCAweDE5M2VlLCAweDE5M2YyLCAweDE5M2Y0LCAweDE5NDMwLCAweDE5NDNlLCAweDE5NDYwLFxuICAgICAgICAweDE5NDdjLCAweDE5NGMwLCAweDE5NGY4LCAweDE5NWYwLCAweDE5NjM4LCAweDE5NjcwLCAweDE5NjdlLCAweDE5NmUwLCAweDE5NmZjLCAweDE5NzAyLCAweDE5NzA0LCAweDE5NzA4LFxuICAgICAgICAweDE5NzEwLCAweDE5NzIwLCAweDE5NzNjLCAweDE5NzQwLCAweDE5Nzc4LCAweDE5Nzg2LCAweDE5NzhjLCAweDE5Nzk4LCAweDE5N2IwLCAweDE5N2JlLCAweDE5N2NlLCAweDE5N2RjLFxuICAgICAgICAweDE5N2UyLCAweDE5N2U0LCAweDE5N2U4LCAweDE5ODIyLCAweDE5ODI0LCAweDE5ODQyLCAweDE5ODQ4LCAweDE5ODUwLCAweDE5ODVlLCAweDE5ODY2LCAweDE5ODdhLCAweDE5ODgyLFxuICAgICAgICAweDE5ODg0LCAweDE5ODkwLCAweDE5ODllLCAweDE5OGEwLCAweDE5OGJjLCAweDE5OGNjLCAweDE5OGYyLCAweDE5OGY0LCAweDE5OTAyLCAweDE5OTA4LCAweDE5OTFlLCAweDE5OTIwLFxuICAgICAgICAweDE5OTNjLCAweDE5OTQwLCAweDE5OTc4LCAweDE5OTg2LCAweDE5OTk4LCAweDE5OWNlLCAweDE5OWUyLCAweDE5OWU0LCAweDE5OWU4LCAweDE5YTA4LCAweDE5YTEwLCAweDE5YTFlLFxuICAgICAgICAweDE5YTIwLCAweDE5YTNjLCAweDE5YTQwLCAweDE5YTc4LCAweDE5YWYwLCAweDE5YjE4LCAweDE5YjNlLCAweDE5YjYwLCAweDE5YjljLCAweDE5YmMyLCAweDE5YmM0LCAweDE5YmM4LFxuICAgICAgICAweDE5YmQwLCAweDE5YmU2LCAweDE5YzJlLCAweDE5YzM0LCAweDE5YzRlLCAweDE5YzVjLCAweDE5YzYyLCAweDE5YzY0LCAweDE5YzY4LCAweDE5YzhlLCAweDE5YzljLCAweDE5Y2I4LFxuICAgICAgICAweDE5Y2MyLCAweDE5Y2M4LCAweDE5Y2QwLCAweDE5Y2U2LCAweDE5Y2ZhLCAweDE5ZDBlLCAweDE5ZDFjLCAweDE5ZDM4LCAweDE5ZDcwLCAweDE5ZDdlLCAweDE5ZDgyLCAweDE5ZDg0LFxuICAgICAgICAweDE5ZDg4LCAweDE5ZDkwLCAweDE5ZGEwLCAweDE5ZGNjLCAweDE5ZGYyLCAweDE5ZGY0LCAweDE5ZTE2LCAweDE5ZTI2LCAweDE5ZTJjLCAweDE5ZTQ2LCAweDE5ZTRjLCAweDE5ZTU4LFxuICAgICAgICAweDE5ZTc0LCAweDE5ZTg2LCAweDE5ZThjLCAweDE5ZTk4LCAweDE5ZWIwLCAweDE5ZWJlLCAweDE5ZWNlLCAweDE5ZWUyLCAweDE5ZWU0LCAweDE5ZWU4LCAweDE5ZjBhLCAweDE5ZjEyLFxuICAgICAgICAweDE5ZjE0LCAweDE5ZjIyLCAweDE5ZjI0LCAweDE5ZjI4LCAweDE5ZjQyLCAweDE5ZjQ0LCAweDE5ZjQ4LCAweDE5ZjUwLCAweDE5ZjVlLCAweDE5ZjZjLCAweDE5ZjlhLCAweDE5ZmFlLFxuICAgICAgICAweDE5ZmIyLCAweDE5ZmI0LCAweDFhMDQ2LCAweDFhMDRjLCAweDFhMDcyLCAweDFhMDc0LCAweDFhMDg2LCAweDFhMDhjLCAweDFhMDk4LCAweDFhMGIwLCAweDFhMGJlLCAweDFhMGUyLFxuICAgICAgICAweDFhMGU0LCAweDFhMGU4LCAweDFhMGY2LCAweDFhMTA2LCAweDFhMTBjLCAweDFhMTE4LCAweDFhMTMwLCAweDFhMTNlLCAweDFhMTYwLCAweDFhMTdjLCAweDFhMThlLCAweDFhMTljLFxuICAgICAgICAweDFhMWI4LCAweDFhMWMyLCAweDFhMWM0LCAweDFhMWM4LCAweDFhMWQwLCAweDFhMWRlLCAweDFhMWU2LCAweDFhMWVjLCAweDFhMjE4LCAweDFhMjMwLCAweDFhMjNlLCAweDFhMjYwLFxuICAgICAgICAweDFhMjdjLCAweDFhMmMwLCAweDFhMmY4LCAweDFhMzFjLCAweDFhMzM4LCAweDFhMzcwLCAweDFhMzdlLCAweDFhMzgyLCAweDFhMzg0LCAweDFhMzg4LCAweDFhMzkwLCAweDFhMzllLFxuICAgICAgICAweDFhM2EwLCAweDFhM2JjLCAweDFhM2M2LCAweDFhM2NjLCAweDFhM2Q4LCAweDFhM2VlLCAweDFhM2YyLCAweDFhM2Y0LCAweDFhNDE4LCAweDFhNDMwLCAweDFhNDNlLCAweDFhNDYwLFxuICAgICAgICAweDFhNDdjLCAweDFhNGMwLCAweDFhNGY4LCAweDFhNWYwLCAweDFhNjFjLCAweDFhNjM4LCAweDFhNjcwLCAweDFhNjdlLCAweDFhNmUwLCAweDFhNmZjLCAweDFhNzAyLCAweDFhNzA0LFxuICAgICAgICAweDFhNzA4LCAweDFhNzEwLCAweDFhNzFlLCAweDFhNzIwLCAweDFhNzNjLCAweDFhNzQwLCAweDFhNzc4LCAweDFhNzg2LCAweDFhNzhjLCAweDFhNzk4LCAweDFhN2IwLCAweDFhN2JlLFxuICAgICAgICAweDFhN2NlLCAweDFhN2RjLCAweDFhN2UyLCAweDFhN2U0LCAweDFhN2U4LCAweDFhODMwLCAweDFhODYwLCAweDFhODdjLCAweDFhOGMwLCAweDFhOGY4LCAweDFhOWYwLCAweDFhYmUwLFxuICAgICAgICAweDFhYzcwLCAweDFhYzdlLCAweDFhY2UwLCAweDFhY2ZjLCAweDFhZGMwLCAweDFhZGY4LCAweDFhZTA0LCAweDFhZTA4LCAweDFhZTEwLCAweDFhZTIwLCAweDFhZTNjLCAweDFhZTQwLFxuICAgICAgICAweDFhZTc4LCAweDFhZWYwLCAweDFhZjA2LCAweDFhZjBjLCAweDFhZjE4LCAweDFhZjMwLCAweDFhZjNlLCAweDFhZjYwLCAweDFhZjdjLCAweDFhZjhlLCAweDFhZjljLCAweDFhZmI4LFxuICAgICAgICAweDFhZmM0LCAweDFhZmM4LCAweDFhZmQwLCAweDFhZmRlLCAweDFiMDQyLCAweDFiMDVlLCAweDFiMDdhLCAweDFiMDgyLCAweDFiMDg0LCAweDFiMDg4LCAweDFiMDkwLCAweDFiMDllLFxuICAgICAgICAweDFiMGEwLCAweDFiMGJjLCAweDFiMGNjLCAweDFiMGYyLCAweDFiMGY0LCAweDFiMTAyLCAweDFiMTA0LCAweDFiMTA4LCAweDFiMTEwLCAweDFiMTFlLCAweDFiMTIwLCAweDFiMTNjLFxuICAgICAgICAweDFiMTQwLCAweDFiMTc4LCAweDFiMTg2LCAweDFiMTk4LCAweDFiMWNlLCAweDFiMWUyLCAweDFiMWU0LCAweDFiMWU4LCAweDFiMjA0LCAweDFiMjA4LCAweDFiMjEwLCAweDFiMjFlLFxuICAgICAgICAweDFiMjIwLCAweDFiMjNjLCAweDFiMjQwLCAweDFiMjc4LCAweDFiMmYwLCAweDFiMzBjLCAweDFiMzNlLCAweDFiMzYwLCAweDFiMzljLCAweDFiM2MyLCAweDFiM2M0LCAweDFiM2M4LFxuICAgICAgICAweDFiM2QwLCAweDFiM2U2LCAweDFiNDEwLCAweDFiNDFlLCAweDFiNDIwLCAweDFiNDNjLCAweDFiNDQwLCAweDFiNDc4LCAweDFiNGYwLCAweDFiNWUwLCAweDFiNjE4LCAweDFiNjYwLFxuICAgICAgICAweDFiNjdjLCAweDFiNmMwLCAweDFiNzM4LCAweDFiNzgyLCAweDFiNzg0LCAweDFiNzg4LCAweDFiNzkwLCAweDFiNzllLCAweDFiN2EwLCAweDFiN2NjLCAweDFiODJlLCAweDFiODRlLFxuICAgICAgICAweDFiODVjLCAweDFiODhlLCAweDFiODljLCAweDFiOGI4LCAweDFiOGMyLCAweDFiOGM0LCAweDFiOGM4LCAweDFiOGQwLCAweDFiOGU2LCAweDFiOGZhLCAweDFiOTBlLCAweDFiOTFjLFxuICAgICAgICAweDFiOTM4LCAweDFiOTcwLCAweDFiOTdlLCAweDFiOTgyLCAweDFiOTg0LCAweDFiOTg4LCAweDFiOTkwLCAweDFiOTllLCAweDFiOWEwLCAweDFiOWNjLCAweDFiOWYyLCAweDFiOWY0LFxuICAgICAgICAweDFiYTBlLCAweDFiYTFjLCAweDFiYTM4LCAweDFiYTcwLCAweDFiYTdlLCAweDFiYWUwLCAweDFiYWZjLCAweDFiYjA4LCAweDFiYjEwLCAweDFiYjIwLCAweDFiYjNjLCAweDFiYjQwLFxuICAgICAgICAweDFiYjk4LCAweDFiYmNlLCAweDFiYmUyLCAweDFiYmU0LCAweDFiYmU4LCAweDFiYzE2LCAweDFiYzI2LCAweDFiYzJjLCAweDFiYzQ2LCAweDFiYzRjLCAweDFiYzU4LCAweDFiYzcyLFxuICAgICAgICAweDFiYzc0LCAweDFiYzg2LCAweDFiYzhjLCAweDFiYzk4LCAweDFiY2IwLCAweDFiY2JlLCAweDFiY2NlLCAweDFiY2UyLCAweDFiY2U0LCAweDFiY2U4LCAweDFiZDA2LCAweDFiZDBjLFxuICAgICAgICAweDFiZDE4LCAweDFiZDMwLCAweDFiZDNlLCAweDFiZDYwLCAweDFiZDdjLCAweDFiZDljLCAweDFiZGMyLCAweDFiZGM0LCAweDFiZGM4LCAweDFiZGQwLCAweDFiZGU2LCAweDFiZGZhLFxuICAgICAgICAweDFiZTEyLCAweDFiZTE0LCAweDFiZTIyLCAweDFiZTI0LCAweDFiZTI4LCAweDFiZTQyLCAweDFiZTQ0LCAweDFiZTQ4LCAweDFiZTUwLCAweDFiZTVlLCAweDFiZTY2LCAweDFiZTgyLFxuICAgICAgICAweDFiZTg0LCAweDFiZTg4LCAweDFiZTkwLCAweDFiZTllLCAweDFiZWEwLCAweDFiZWJjLCAweDFiZWNjLCAweDFiZWY0LCAweDFiZjFhLCAweDFiZjJlLCAweDFiZjMyLCAweDFiZjM0LFxuICAgICAgICAweDFiZjRlLCAweDFiZjVjLCAweDFiZjYyLCAweDFiZjY0LCAweDFiZjY4LCAweDFjMDlhLCAweDFjMGIyLCAweDFjMGI0LCAweDFjMTFhLCAweDFjMTMyLCAweDFjMTM0LCAweDFjMTYyLFxuICAgICAgICAweDFjMTY0LCAweDFjMTY4LCAweDFjMTc2LCAweDFjMWJhLCAweDFjMjFhLCAweDFjMjMyLCAweDFjMjM0LCAweDFjMjRlLCAweDFjMjVjLCAweDFjMjYyLCAweDFjMjY0LCAweDFjMjY4LFxuICAgICAgICAweDFjMjc2LCAweDFjMjhlLCAweDFjMmMyLCAweDFjMmM0LCAweDFjMmM4LCAweDFjMmQwLCAweDFjMmRlLCAweDFjMmU2LCAweDFjMmVjLCAweDFjMmZhLCAweDFjMzE2LCAweDFjMzI2LFxuICAgICAgICAweDFjMzNhLCAweDFjMzQ2LCAweDFjMzRjLCAweDFjMzcyLCAweDFjMzc0LCAweDFjNDFhLCAweDFjNDJlLCAweDFjNDMyLCAweDFjNDM0LCAweDFjNDRlLCAweDFjNDVjLCAweDFjNDYyLFxuICAgICAgICAweDFjNDY0LCAweDFjNDY4LCAweDFjNDc2LCAweDFjNDhlLCAweDFjNDljLCAweDFjNGI4LCAweDFjNGMyLCAweDFjNGM4LCAweDFjNGQwLCAweDFjNGRlLCAweDFjNGU2LCAweDFjNGVjLFxuICAgICAgICAweDFjNGZhLCAweDFjNTFjLCAweDFjNTM4LCAweDFjNTcwLCAweDFjNTdlLCAweDFjNTgyLCAweDFjNTg0LCAweDFjNTg4LCAweDFjNTkwLCAweDFjNTllLCAweDFjNWEwLCAweDFjNWJjLFxuICAgICAgICAweDFjNWM2LCAweDFjNWNjLCAweDFjNWQ4LCAweDFjNWVlLCAweDFjNWYyLCAweDFjNWY0LCAweDFjNjE2LCAweDFjNjI2LCAweDFjNjJjLCAweDFjNjNhLCAweDFjNjQ2LCAweDFjNjRjLFxuICAgICAgICAweDFjNjU4LCAweDFjNjZlLCAweDFjNjcyLCAweDFjNjc0LCAweDFjNjg2LCAweDFjNjhjLCAweDFjNjk4LCAweDFjNmIwLCAweDFjNmJlLCAweDFjNmNlLCAweDFjNmRjLCAweDFjNmUyLFxuICAgICAgICAweDFjNmU0LCAweDFjNmU4LCAweDFjNzEyLCAweDFjNzE0LCAweDFjNzIyLCAweDFjNzI4LCAweDFjNzM2LCAweDFjNzQyLCAweDFjNzQ0LCAweDFjNzQ4LCAweDFjNzUwLCAweDFjNzVlLFxuICAgICAgICAweDFjNzY2LCAweDFjNzZjLCAweDFjNzdhLCAweDFjN2FlLCAweDFjN2Q2LCAweDFjN2VhLCAweDFjODFhLCAweDFjODJlLCAweDFjODMyLCAweDFjODM0LCAweDFjODRlLCAweDFjODVjLFxuICAgICAgICAweDFjODYyLCAweDFjODY0LCAweDFjODY4LCAweDFjODc2LCAweDFjODhlLCAweDFjODljLCAweDFjOGI4LCAweDFjOGMyLCAweDFjOGM4LCAweDFjOGQwLCAweDFjOGRlLCAweDFjOGU2LFxuICAgICAgICAweDFjOGVjLCAweDFjOGZhLCAweDFjOTBlLCAweDFjOTM4LCAweDFjOTcwLCAweDFjOTdlLCAweDFjOTgyLCAweDFjOTg0LCAweDFjOTkwLCAweDFjOTllLCAweDFjOWEwLCAweDFjOWJjLFxuICAgICAgICAweDFjOWM2LCAweDFjOWNjLCAweDFjOWQ4LCAweDFjOWVlLCAweDFjOWYyLCAweDFjOWY0LCAweDFjYTM4LCAweDFjYTcwLCAweDFjYTdlLCAweDFjYWUwLCAweDFjYWZjLCAweDFjYjAyLFxuICAgICAgICAweDFjYjA0LCAweDFjYjA4LCAweDFjYjEwLCAweDFjYjIwLCAweDFjYjNjLCAweDFjYjQwLCAweDFjYjc4LCAweDFjYjg2LCAweDFjYjhjLCAweDFjYjk4LCAweDFjYmIwLCAweDFjYmJlLFxuICAgICAgICAweDFjYmNlLCAweDFjYmRjLCAweDFjYmUyLCAweDFjYmU0LCAweDFjYmU4LCAweDFjYmY2LCAweDFjYzE2LCAweDFjYzI2LCAweDFjYzJjLCAweDFjYzNhLCAweDFjYzQ2LCAweDFjYzU4LFxuICAgICAgICAweDFjYzcyLCAweDFjYzc0LCAweDFjYzg2LCAweDFjY2IwLCAweDFjY2JlLCAweDFjY2NlLCAweDFjY2UyLCAweDFjY2U0LCAweDFjY2U4LCAweDFjZDA2LCAweDFjZDBjLCAweDFjZDE4LFxuICAgICAgICAweDFjZDMwLCAweDFjZDNlLCAweDFjZDYwLCAweDFjZDdjLCAweDFjZDljLCAweDFjZGMyLCAweDFjZGM0LCAweDFjZGM4LCAweDFjZGQwLCAweDFjZGRlLCAweDFjZGU2LCAweDFjZGZhLFxuICAgICAgICAweDFjZTIyLCAweDFjZTI4LCAweDFjZTQyLCAweDFjZTUwLCAweDFjZTVlLCAweDFjZTY2LCAweDFjZTdhLCAweDFjZTgyLCAweDFjZTg0LCAweDFjZTg4LCAweDFjZTkwLCAweDFjZTllLFxuICAgICAgICAweDFjZWEwLCAweDFjZWJjLCAweDFjZWNjLCAweDFjZWYyLCAweDFjZWY0LCAweDFjZjJlLCAweDFjZjMyLCAweDFjZjM0LCAweDFjZjRlLCAweDFjZjVjLCAweDFjZjYyLCAweDFjZjY0LFxuICAgICAgICAweDFjZjY4LCAweDFjZjk2LCAweDFjZmE2LCAweDFjZmFjLCAweDFjZmNhLCAweDFjZmQyLCAweDFjZmQ0LCAweDFkMDJlLCAweDFkMDMyLCAweDFkMDM0LCAweDFkMDRlLCAweDFkMDVjLFxuICAgICAgICAweDFkMDYyLCAweDFkMDY0LCAweDFkMDY4LCAweDFkMDc2LCAweDFkMDhlLCAweDFkMDljLCAweDFkMGI4LCAweDFkMGMyLCAweDFkMGM0LCAweDFkMGM4LCAweDFkMGQwLCAweDFkMGRlLFxuICAgICAgICAweDFkMGU2LCAweDFkMGVjLCAweDFkMGZhLCAweDFkMTFjLCAweDFkMTM4LCAweDFkMTcwLCAweDFkMTdlLCAweDFkMTgyLCAweDFkMTg0LCAweDFkMTg4LCAweDFkMTkwLCAweDFkMTllLFxuICAgICAgICAweDFkMWEwLCAweDFkMWJjLCAweDFkMWM2LCAweDFkMWNjLCAweDFkMWQ4LCAweDFkMWVlLCAweDFkMWYyLCAweDFkMWY0LCAweDFkMjFjLCAweDFkMjM4LCAweDFkMjcwLCAweDFkMjdlLFxuICAgICAgICAweDFkMmUwLCAweDFkMmZjLCAweDFkMzAyLCAweDFkMzA0LCAweDFkMzA4LCAweDFkMzEwLCAweDFkMzFlLCAweDFkMzIwLCAweDFkMzNjLCAweDFkMzQwLCAweDFkMzc4LCAweDFkMzg2LFxuICAgICAgICAweDFkMzhjLCAweDFkMzk4LCAweDFkM2IwLCAweDFkM2JlLCAweDFkM2NlLCAweDFkM2RjLCAweDFkM2UyLCAweDFkM2U0LCAweDFkM2U4LCAweDFkM2Y2LCAweDFkNDcwLCAweDFkNDdlLFxuICAgICAgICAweDFkNGUwLCAweDFkNGZjLCAweDFkNWMwLCAweDFkNWY4LCAweDFkNjA0LCAweDFkNjA4LCAweDFkNjEwLCAweDFkNjIwLCAweDFkNjQwLCAweDFkNjc4LCAweDFkNmYwLCAweDFkNzA2LFxuICAgICAgICAweDFkNzBjLCAweDFkNzE4LCAweDFkNzMwLCAweDFkNzNlLCAweDFkNzYwLCAweDFkNzdjLCAweDFkNzhlLCAweDFkNzljLCAweDFkN2I4LCAweDFkN2MyLCAweDFkN2M0LCAweDFkN2M4LFxuICAgICAgICAweDFkN2QwLCAweDFkN2RlLCAweDFkN2U2LCAweDFkN2VjLCAweDFkODI2LCAweDFkODJjLCAweDFkODNhLCAweDFkODQ2LCAweDFkODRjLCAweDFkODU4LCAweDFkODcyLCAweDFkODc0LFxuICAgICAgICAweDFkODg2LCAweDFkODhjLCAweDFkODk4LCAweDFkOGIwLCAweDFkOGJlLCAweDFkOGNlLCAweDFkOGUyLCAweDFkOGU0LCAweDFkOGU4LCAweDFkOGY2LCAweDFkOTBjLCAweDFkOTE4LFxuICAgICAgICAweDFkOTMwLCAweDFkOTNlLCAweDFkOTYwLCAweDFkOTdjLCAweDFkOTljLCAweDFkOWMyLCAweDFkOWM0LCAweDFkOWM4LCAweDFkOWQwLCAweDFkOWU2LCAweDFkOWZhLCAweDFkYTBjLFxuICAgICAgICAweDFkYTE4LCAweDFkYTMwLCAweDFkYTNlLCAweDFkYTYwLCAweDFkYTdjLCAweDFkYWMwLCAweDFkYWY4LCAweDFkYjM4LCAweDFkYjgyLCAweDFkYjg0LCAweDFkYjg4LCAweDFkYjkwLFxuICAgICAgICAweDFkYjllLCAweDFkYmEwLCAweDFkYmNjLCAweDFkYmYyLCAweDFkYmY0LCAweDFkYzIyLCAweDFkYzQyLCAweDFkYzQ0LCAweDFkYzQ4LCAweDFkYzUwLCAweDFkYzVlLCAweDFkYzY2LFxuICAgICAgICAweDFkYzdhLCAweDFkYzgyLCAweDFkYzg0LCAweDFkYzg4LCAweDFkYzkwLCAweDFkYzllLCAweDFkY2EwLCAweDFkY2JjLCAweDFkY2NjLCAweDFkY2YyLCAweDFkY2Y0LCAweDFkZDA0LFxuICAgICAgICAweDFkZDA4LCAweDFkZDEwLCAweDFkZDFlLCAweDFkZDIwLCAweDFkZDNjLCAweDFkZDQwLCAweDFkZDc4LCAweDFkZDg2LCAweDFkZDk4LCAweDFkZGNlLCAweDFkZGUyLCAweDFkZGU0LFxuICAgICAgICAweDFkZGU4LCAweDFkZTJlLCAweDFkZTMyLCAweDFkZTM0LCAweDFkZTRlLCAweDFkZTVjLCAweDFkZTYyLCAweDFkZTY0LCAweDFkZTY4LCAweDFkZThlLCAweDFkZTljLCAweDFkZWI4LFxuICAgICAgICAweDFkZWMyLCAweDFkZWM0LCAweDFkZWM4LCAweDFkZWQwLCAweDFkZWU2LCAweDFkZWZhLCAweDFkZjE2LCAweDFkZjI2LCAweDFkZjJjLCAweDFkZjQ2LCAweDFkZjRjLCAweDFkZjU4LFxuICAgICAgICAweDFkZjcyLCAweDFkZjc0LCAweDFkZjhhLCAweDFkZjkyLCAweDFkZjk0LCAweDFkZmEyLCAweDFkZmE0LCAweDFkZmE4LCAweDFlMDhhLCAweDFlMDkyLCAweDFlMDk0LCAweDFlMGEyLFxuICAgICAgICAweDFlMGE0LCAweDFlMGE4LCAweDFlMGI2LCAweDFlMGRhLCAweDFlMTBhLCAweDFlMTEyLCAweDFlMTE0LCAweDFlMTIyLCAweDFlMTI0LCAweDFlMTI4LCAweDFlMTM2LCAweDFlMTQyLFxuICAgICAgICAweDFlMTQ0LCAweDFlMTQ4LCAweDFlMTUwLCAweDFlMTY2LCAweDFlMTZjLCAweDFlMTdhLCAweDFlMTlhLCAweDFlMWIyLCAweDFlMWI0LCAweDFlMjBhLCAweDFlMjEyLCAweDFlMjE0LFxuICAgICAgICAweDFlMjIyLCAweDFlMjI0LCAweDFlMjI4LCAweDFlMjM2LCAweDFlMjQyLCAweDFlMjQ4LCAweDFlMjUwLCAweDFlMjVlLCAweDFlMjY2LCAweDFlMjZjLCAweDFlMjdhLCAweDFlMjgyLFxuICAgICAgICAweDFlMjg0LCAweDFlMjg4LCAweDFlMjkwLCAweDFlMmEwLCAweDFlMmJjLCAweDFlMmM2LCAweDFlMmNjLCAweDFlMmQ4LCAweDFlMmVlLCAweDFlMmYyLCAweDFlMmY0LCAweDFlMzFhLFxuICAgICAgICAweDFlMzMyLCAweDFlMzM0LCAweDFlMzVjLCAweDFlMzYyLCAweDFlMzY0LCAweDFlMzY4LCAweDFlM2JhLCAweDFlNDBhLCAweDFlNDEyLCAweDFlNDE0LCAweDFlNDIyLCAweDFlNDI4LFxuICAgICAgICAweDFlNDM2LCAweDFlNDQyLCAweDFlNDQ4LCAweDFlNDUwLCAweDFlNDVlLCAweDFlNDY2LCAweDFlNDZjLCAweDFlNDdhLCAweDFlNDgyLCAweDFlNDg0LCAweDFlNDkwLCAweDFlNDllLFxuICAgICAgICAweDFlNGEwLCAweDFlNGJjLCAweDFlNGM2LCAweDFlNGNjLCAweDFlNGQ4LCAweDFlNGVlLCAweDFlNGYyLCAweDFlNGY0LCAweDFlNTAyLCAweDFlNTA0LCAweDFlNTA4LCAweDFlNTEwLFxuICAgICAgICAweDFlNTFlLCAweDFlNTIwLCAweDFlNTNjLCAweDFlNTQwLCAweDFlNTc4LCAweDFlNTg2LCAweDFlNThjLCAweDFlNTk4LCAweDFlNWIwLCAweDFlNWJlLCAweDFlNWNlLCAweDFlNWRjLFxuICAgICAgICAweDFlNWUyLCAweDFlNWU0LCAweDFlNWU4LCAweDFlNWY2LCAweDFlNjFhLCAweDFlNjJlLCAweDFlNjMyLCAweDFlNjM0LCAweDFlNjRlLCAweDFlNjVjLCAweDFlNjYyLCAweDFlNjY4LFxuICAgICAgICAweDFlNjhlLCAweDFlNjljLCAweDFlNmI4LCAweDFlNmMyLCAweDFlNmM0LCAweDFlNmM4LCAweDFlNmQwLCAweDFlNmU2LCAweDFlNmZhLCAweDFlNzE2LCAweDFlNzI2LCAweDFlNzJjLFxuICAgICAgICAweDFlNzNhLCAweDFlNzQ2LCAweDFlNzRjLCAweDFlNzU4LCAweDFlNzcyLCAweDFlNzc0LCAweDFlNzkyLCAweDFlNzk0LCAweDFlN2EyLCAweDFlN2E0LCAweDFlN2E4LCAweDFlN2I2LFxuICAgICAgICAweDFlODEyLCAweDFlODE0LCAweDFlODIyLCAweDFlODI0LCAweDFlODI4LCAweDFlODM2LCAweDFlODQyLCAweDFlODQ0LCAweDFlODQ4LCAweDFlODUwLCAweDFlODVlLCAweDFlODY2LFxuICAgICAgICAweDFlODZjLCAweDFlODdhLCAweDFlODgyLCAweDFlODg0LCAweDFlODg4LCAweDFlODkwLCAweDFlODllLCAweDFlOGEwLCAweDFlOGJjLCAweDFlOGM2LCAweDFlOGNjLCAweDFlOGQ4LFxuICAgICAgICAweDFlOGVlLCAweDFlOGYyLCAweDFlOGY0LCAweDFlOTAyLCAweDFlOTA0LCAweDFlOTA4LCAweDFlOTEwLCAweDFlOTIwLCAweDFlOTNjLCAweDFlOTQwLCAweDFlOTc4LCAweDFlOTg2LFxuICAgICAgICAweDFlOThjLCAweDFlOTk4LCAweDFlOWIwLCAweDFlOWJlLCAweDFlOWNlLCAweDFlOWRjLCAweDFlOWUyLCAweDFlOWU0LCAweDFlOWU4LCAweDFlOWY2LCAweDFlYTA0LCAweDFlYTA4LFxuICAgICAgICAweDFlYTEwLCAweDFlYTIwLCAweDFlYTQwLCAweDFlYTc4LCAweDFlYWYwLCAweDFlYjA2LCAweDFlYjBjLCAweDFlYjE4LCAweDFlYjMwLCAweDFlYjNlLCAweDFlYjYwLCAweDFlYjdjLFxuICAgICAgICAweDFlYjhlLCAweDFlYjljLCAweDFlYmI4LCAweDFlYmMyLCAweDFlYmM0LCAweDFlYmM4LCAweDFlYmQwLCAweDFlYmRlLCAweDFlYmU2LCAweDFlYmVjLCAweDFlYzFhLCAweDFlYzJlLFxuICAgICAgICAweDFlYzMyLCAweDFlYzM0LCAweDFlYzRlLCAweDFlYzVjLCAweDFlYzYyLCAweDFlYzY0LCAweDFlYzY4LCAweDFlYzhlLCAweDFlYzljLCAweDFlY2I4LCAweDFlY2MyLCAweDFlY2M0LFxuICAgICAgICAweDFlY2M4LCAweDFlY2QwLCAweDFlY2U2LCAweDFlY2ZhLCAweDFlZDBlLCAweDFlZDFjLCAweDFlZDM4LCAweDFlZDcwLCAweDFlZDdlLCAweDFlZDgyLCAweDFlZDg0LCAweDFlZDg4LFxuICAgICAgICAweDFlZDkwLCAweDFlZDllLCAweDFlZGEwLCAweDFlZGNjLCAweDFlZGYyLCAweDFlZGY0LCAweDFlZTE2LCAweDFlZTI2LCAweDFlZTJjLCAweDFlZTNhLCAweDFlZTQ2LCAweDFlZTRjLFxuICAgICAgICAweDFlZTU4LCAweDFlZTZlLCAweDFlZTcyLCAweDFlZTc0LCAweDFlZTg2LCAweDFlZThjLCAweDFlZTk4LCAweDFlZWIwLCAweDFlZWJlLCAweDFlZWNlLCAweDFlZWRjLCAweDFlZWUyLFxuICAgICAgICAweDFlZWU0LCAweDFlZWU4LCAweDFlZjEyLCAweDFlZjIyLCAweDFlZjI0LCAweDFlZjI4LCAweDFlZjM2LCAweDFlZjQyLCAweDFlZjQ0LCAweDFlZjQ4LCAweDFlZjUwLCAweDFlZjVlLFxuICAgICAgICAweDFlZjY2LCAweDFlZjZjLCAweDFlZjdhLCAweDFlZmFlLCAweDFlZmIyLCAweDFlZmI0LCAweDFlZmQ2LCAweDFmMDk2LCAweDFmMGE2LCAweDFmMGFjLCAweDFmMGJhLCAweDFmMGNhLFxuICAgICAgICAweDFmMGQyLCAweDFmMGQ0LCAweDFmMTE2LCAweDFmMTI2LCAweDFmMTJjLCAweDFmMTNhLCAweDFmMTQ2LCAweDFmMTRjLCAweDFmMTU4LCAweDFmMTZlLCAweDFmMTcyLCAweDFmMTc0LFxuICAgICAgICAweDFmMThhLCAweDFmMTkyLCAweDFmMTk0LCAweDFmMWEyLCAweDFmMWE0LCAweDFmMWE4LCAweDFmMWRhLCAweDFmMjE2LCAweDFmMjI2LCAweDFmMjJjLCAweDFmMjNhLCAweDFmMjQ2LFxuICAgICAgICAweDFmMjU4LCAweDFmMjZlLCAweDFmMjcyLCAweDFmMjc0LCAweDFmMjg2LCAweDFmMjhjLCAweDFmMjk4LCAweDFmMmIwLCAweDFmMmJlLCAweDFmMmNlLCAweDFmMmRjLCAweDFmMmUyLFxuICAgICAgICAweDFmMmU0LCAweDFmMmU4LCAweDFmMmY2LCAweDFmMzBhLCAweDFmMzEyLCAweDFmMzE0LCAweDFmMzIyLCAweDFmMzI4LCAweDFmMzQyLCAweDFmMzQ0LCAweDFmMzQ4LCAweDFmMzUwLFxuICAgICAgICAweDFmMzVlLCAweDFmMzY2LCAweDFmMzdhLCAweDFmMzlhLCAweDFmM2FlLCAweDFmM2IyLCAweDFmM2I0LCAweDFmNDE2LCAweDFmNDI2LCAweDFmNDJjLCAweDFmNDNhLCAweDFmNDQ2LFxuICAgICAgICAweDFmNDRjLCAweDFmNDU4LCAweDFmNDZlLCAweDFmNDcyLCAweDFmNDc0LCAweDFmNDg2LCAweDFmNDhjLCAweDFmNDk4LCAweDFmNGIwLCAweDFmNGJlLCAweDFmNGNlLCAweDFmNGRjLFxuICAgICAgICAweDFmNGUyLCAweDFmNGU0LCAweDFmNGU4LCAweDFmNGY2LCAweDFmNTA2LCAweDFmNTBjLCAweDFmNTE4LCAweDFmNTMwLCAweDFmNTNlLCAweDFmNTYwLCAweDFmNTdjLCAweDFmNThlLFxuICAgICAgICAweDFmNTljLCAweDFmNWI4LCAweDFmNWMyLCAweDFmNWM0LCAweDFmNWM4LCAweDFmNWQwLCAweDFmNWRlLCAweDFmNWU2LCAweDFmNWVjLCAweDFmNWZhLCAweDFmNjBhLCAweDFmNjEyLFxuICAgICAgICAweDFmNjE0LCAweDFmNjIyLCAweDFmNjI0LCAweDFmNjI4LCAweDFmNjM2LCAweDFmNjQyLCAweDFmNjQ0LCAweDFmNjQ4LCAweDFmNjUwLCAweDFmNjVlLCAweDFmNjY2LCAweDFmNjdhLFxuICAgICAgICAweDFmNjgyLCAweDFmNjg0LCAweDFmNjg4LCAweDFmNjkwLCAweDFmNjllLCAweDFmNmEwLCAweDFmNmJjLCAweDFmNmNjLCAweDFmNmYyLCAweDFmNmY0LCAweDFmNzFhLCAweDFmNzJlLFxuICAgICAgICAweDFmNzMyLCAweDFmNzM0LCAweDFmNzRlLCAweDFmNzVjLCAweDFmNzYyLCAweDFmNzY0LCAweDFmNzY4LCAweDFmNzc2LCAweDFmNzk2LCAweDFmN2E2LCAweDFmN2FjLCAweDFmN2JhLFxuICAgICAgICAweDFmN2QyLCAweDFmN2Q0LCAweDFmODlhLCAweDFmOGFlLCAweDFmOGIyLCAweDFmOGI0LCAweDFmOGQ2LCAweDFmOGVhLCAweDFmOTFhLCAweDFmOTJlLCAweDFmOTMyLCAweDFmOTM0LFxuICAgICAgICAweDFmOTRlLCAweDFmOTVjLCAweDFmOTYyLCAweDFmOTY0LCAweDFmOTY4LCAweDFmOTc2LCAweDFmOTk2LCAweDFmOWE2LCAweDFmOWFjLCAweDFmOWJhLCAweDFmOWNhLCAweDFmOWQyLFxuICAgICAgICAweDFmOWQ0LCAweDFmYTFhLCAweDFmYTJlLCAweDFmYTMyLCAweDFmYTM0LCAweDFmYTRlLCAweDFmYTVjLCAweDFmYTYyLCAweDFmYTY0LCAweDFmYTY4LCAweDFmYTc2LCAweDFmYThlLFxuICAgICAgICAweDFmYTljLCAweDFmYWI4LCAweDFmYWMyLCAweDFmYWM0LCAweDFmYWM4LCAweDFmYWQwLCAweDFmYWRlLCAweDFmYWU2LCAweDFmYWVjLCAweDFmYjE2LCAweDFmYjI2LCAweDFmYjJjLFxuICAgICAgICAweDFmYjNhLCAweDFmYjQ2LCAweDFmYjRjLCAweDFmYjU4LCAweDFmYjZlLCAweDFmYjcyLCAweDFmYjc0LCAweDFmYjhhLCAweDFmYjkyLCAweDFmYjk0LCAweDFmYmEyLCAweDFmYmE0LFxuICAgICAgICAweDFmYmE4LCAweDFmYmI2LCAweDFmYmRhXG4gICAgXSk7XG4gICAgLyoqXG4gICAgICogVGhpcyB0YWJsZSBjb250YWlucyB0byBjb2Rld29yZHMgZm9yIGFsbCBzeW1ib2xzLlxuICAgICAqL1xuICAgIFBERjQxN0NvbW1vbi5DT0RFV09SRF9UQUJMRSA9IEludDMyQXJyYXkuZnJvbShbXG4gICAgICAgIDI2MjcsIDE4MTksIDI2MjIsIDI2MjEsIDE4MTMsIDE4MTIsIDI3MjksIDI3MjQsIDI3MjMsIDI3NzksIDI3NzQsIDI3NzMsIDkwMiwgODk2LCA5MDgsIDg2OCwgODY1LCA4NjEsIDg1OSwgMjUxMSxcbiAgICAgICAgODczLCA4NzEsIDE3ODAsIDgzNSwgMjQ5MywgODI1LCAyNDkxLCA4NDIsIDgzNywgODQ0LCAxNzY0LCAxNzYyLCA4MTEsIDgxMCwgODA5LCAyNDgzLCA4MDcsIDI0ODIsIDgwNiwgMjQ4MCwgODE1LFxuICAgICAgICA4MTQsIDgxMywgODEyLCAyNDg0LCA4MTcsIDgxNiwgMTc0NSwgMTc0NCwgMTc0MiwgMTc0NiwgMjY1NSwgMjYzNywgMjYzNSwgMjYyNiwgMjYyNSwgMjYyMywgMjYyOCwgMTgyMCwgMjc1MixcbiAgICAgICAgMjczOSwgMjczNywgMjcyOCwgMjcyNywgMjcyNSwgMjczMCwgMjc4NSwgMjc4MywgMjc3OCwgMjc3NywgMjc3NSwgMjc4MCwgNzg3LCA3ODEsIDc0NywgNzM5LCA3MzYsIDI0MTMsIDc1NCwgNzUyLFxuICAgICAgICAxNzE5LCA2OTIsIDY4OSwgNjgxLCAyMzcxLCA2NzgsIDIzNjksIDcwMCwgNjk3LCA2OTQsIDcwMywgMTY4OCwgMTY4NiwgNjQyLCA2MzgsIDIzNDMsIDYzMSwgMjM0MSwgNjI3LCAyMzM4LCA2NTEsXG4gICAgICAgIDY0NiwgNjQzLCAyMzQ1LCA2NTQsIDY1MiwgMTY1MiwgMTY1MCwgMTY0NywgMTY1NCwgNjAxLCA1OTksIDIzMjIsIDU5NiwgMjMyMSwgNTk0LCAyMzE5LCAyMzE3LCA2MTEsIDYxMCwgNjA4LCA2MDYsXG4gICAgICAgIDIzMjQsIDYwMywgMjMyMywgNjE1LCA2MTQsIDYxMiwgMTYxNywgMTYxNiwgMTYxNCwgMTYxMiwgNjE2LCAxNjE5LCAxNjE4LCAyNTc1LCAyNTM4LCAyNTM2LCA5MDUsIDkwMSwgODk4LCA5MDksXG4gICAgICAgIDI1MDksIDI1MDcsIDI1MDQsIDg3MCwgODY3LCA4NjQsIDg2MCwgMjUxMiwgODc1LCA4NzIsIDE3ODEsIDI0OTAsIDI0ODksIDI0ODcsIDI0ODUsIDE3NDgsIDgzNiwgODM0LCA4MzIsIDgzMCxcbiAgICAgICAgMjQ5NCwgODI3LCAyNDkyLCA4NDMsIDg0MSwgODM5LCA4NDUsIDE3NjUsIDE3NjMsIDI3MDEsIDI2NzYsIDI2NzQsIDI2NTMsIDI2NDgsIDI2NTYsIDI2MzQsIDI2MzMsIDI2MzEsIDI2MjksXG4gICAgICAgIDE4MjEsIDI2MzgsIDI2MzYsIDI3NzAsIDI3NjMsIDI3NjEsIDI3NTAsIDI3NDUsIDI3NTMsIDI3MzYsIDI3MzUsIDI3MzMsIDI3MzEsIDE4NDgsIDI3NDAsIDI3MzgsIDI3ODYsIDI3ODQsIDU5MSxcbiAgICAgICAgNTg4LCA1NzYsIDU2OSwgNTY2LCAyMjk2LCAxNTkwLCA1MzcsIDUzNCwgNTI2LCAyMjc2LCA1MjIsIDIyNzQsIDU0NSwgNTQyLCA1MzksIDU0OCwgMTU3MiwgMTU3MCwgNDgxLCAyMjQ1LCA0NjYsXG4gICAgICAgIDIyNDIsIDQ2MiwgMjIzOSwgNDkyLCA0ODUsIDQ4MiwgMjI0OSwgNDk2LCA0OTQsIDE1MzQsIDE1MzEsIDE1MjgsIDE1MzgsIDQxMywgMjE5NiwgNDA2LCAyMTkxLCAyMTg4LCA0MjUsIDQxOSxcbiAgICAgICAgMjIwMiwgNDE1LCAyMTk5LCA0MzIsIDQzMCwgNDI3LCAxNDcyLCAxNDY3LCAxNDY0LCA0MzMsIDE0NzYsIDE0NzQsIDM2OCwgMzY3LCAyMTYwLCAzNjUsIDIxNTksIDM2MiwgMjE1NywgMjE1NSxcbiAgICAgICAgMjE1MiwgMzc4LCAzNzcsIDM3NSwgMjE2NiwgMzcyLCAyMTY1LCAzNjksIDIxNjIsIDM4MywgMzgxLCAzNzksIDIxNjgsIDE0MTksIDE0MTgsIDE0MTYsIDE0MTQsIDM4NSwgMTQxMSwgMzg0LFxuICAgICAgICAxNDIzLCAxNDIyLCAxNDIwLCAxNDI0LCAyNDYxLCA4MDIsIDI0NDEsIDI0MzksIDc5MCwgNzg2LCA3ODMsIDc5NCwgMjQwOSwgMjQwNiwgMjQwMywgNzUwLCA3NDIsIDczOCwgMjQxNCwgNzU2LFxuICAgICAgICA3NTMsIDE3MjAsIDIzNjcsIDIzNjUsIDIzNjIsIDIzNTksIDE2NjMsIDY5MywgNjkxLCA2ODQsIDIzNzMsIDY4MCwgMjM3MCwgNzAyLCA2OTksIDY5NiwgNzA0LCAxNjkwLCAxNjg3LCAyMzM3LFxuICAgICAgICAyMzM2LCAyMzM0LCAyMzMyLCAxNjI0LCAyMzI5LCAxNjIyLCA2NDAsIDYzNywgMjM0NCwgNjM0LCAyMzQyLCA2MzAsIDIzNDAsIDY1MCwgNjQ4LCA2NDUsIDIzNDYsIDY1NSwgNjUzLCAxNjUzLFxuICAgICAgICAxNjUxLCAxNjQ5LCAxNjU1LCAyNjEyLCAyNTk3LCAyNTk1LCAyNTcxLCAyNTY4LCAyNTY1LCAyNTc2LCAyNTM0LCAyNTI5LCAyNTI2LCAxNzg3LCAyNTQwLCAyNTM3LCA5MDcsIDkwNCwgOTAwLFxuICAgICAgICA5MTAsIDI1MDMsIDI1MDIsIDI1MDAsIDI0OTgsIDE3NjgsIDI0OTUsIDE3NjcsIDI1MTAsIDI1MDgsIDI1MDYsIDg2OSwgODY2LCA4NjMsIDI1MTMsIDg3NiwgODc0LCAxNzgyLCAyNzIwLCAyNzEzLFxuICAgICAgICAyNzExLCAyNjk3LCAyNjk0LCAyNjkxLCAyNzAyLCAyNjcyLCAyNjcwLCAyNjY0LCAxODI4LCAyNjc4LCAyNjc1LCAyNjQ3LCAyNjQ2LCAyNjQ0LCAyNjQyLCAxODIzLCAyNjM5LCAxODIyLCAyNjU0LFxuICAgICAgICAyNjUyLCAyNjUwLCAyNjU3LCAyNzcxLCAxODU1LCAyNzY1LCAyNzYyLCAxODUwLCAxODQ5LCAyNzUxLCAyNzQ5LCAyNzQ3LCAyNzU0LCAzNTMsIDIxNDgsIDM0NCwgMzQyLCAzMzYsIDIxNDIsXG4gICAgICAgIDMzMiwgMjE0MCwgMzQ1LCAxMzc1LCAxMzczLCAzMDYsIDIxMzAsIDI5OSwgMjEyOCwgMjk1LCAyMTI1LCAzMTksIDMxNCwgMzExLCAyMTMyLCAxMzU0LCAxMzUyLCAxMzQ5LCAxMzU2LCAyNjIsXG4gICAgICAgIDI1NywgMjEwMSwgMjUzLCAyMDk2LCAyMDkzLCAyNzQsIDI3MywgMjY3LCAyMTA3LCAyNjMsIDIxMDQsIDI4MCwgMjc4LCAyNzUsIDEzMTYsIDEzMTEsIDEzMDgsIDEzMjAsIDEzMTgsIDIwNTIsXG4gICAgICAgIDIwMiwgMjA1MCwgMjA0NCwgMjA0MCwgMjE5LCAyMDYzLCAyMTIsIDIwNjAsIDIwOCwgMjA1NSwgMjI0LCAyMjEsIDIwNjYsIDEyNjAsIDEyNTgsIDEyNTIsIDIzMSwgMTI0OCwgMjI5LCAxMjY2LFxuICAgICAgICAxMjY0LCAxMjYxLCAxMjY4LCAxNTUsIDE5OTgsIDE1MywgMTk5NiwgMTk5NCwgMTk5MSwgMTk4OCwgMTY1LCAxNjQsIDIwMDcsIDE2MiwgMjAwNiwgMTU5LCAyMDAzLCAyMDAwLCAxNzIsIDE3MSxcbiAgICAgICAgMTY5LCAyMDEyLCAxNjYsIDIwMTAsIDExODYsIDExODQsIDExODIsIDExNzksIDE3NSwgMTE3NiwgMTczLCAxMTkyLCAxMTkxLCAxMTg5LCAxMTg3LCAxNzYsIDExOTQsIDExOTMsIDIzMTMsXG4gICAgICAgIDIzMDcsIDIzMDUsIDU5MiwgNTg5LCAyMjk0LCAyMjkyLCAyMjg5LCA1NzgsIDU3MiwgNTY4LCAyMjk3LCA1ODAsIDE1OTEsIDIyNzIsIDIyNjcsIDIyNjQsIDE1NDcsIDUzOCwgNTM2LCA1MjksXG4gICAgICAgIDIyNzgsIDUyNSwgMjI3NSwgNTQ3LCA1NDQsIDU0MSwgMTU3NCwgMTU3MSwgMjIzNywgMjIzNSwgMjIyOSwgMTQ5MywgMjIyNSwgMTQ4OSwgNDc4LCAyMjQ3LCA0NzAsIDIyNDQsIDQ2NSwgMjI0MSxcbiAgICAgICAgNDkzLCA0ODgsIDQ4NCwgMjI1MCwgNDk4LCA0OTUsIDE1MzYsIDE1MzMsIDE1MzAsIDE1MzksIDIxODcsIDIxODYsIDIxODQsIDIxODIsIDE0MzIsIDIxNzksIDE0MzAsIDIxNzYsIDE0MjcsIDQxNCxcbiAgICAgICAgNDEyLCAyMTk3LCA0MDksIDIxOTUsIDQwNSwgMjE5MywgMjE5MCwgNDI2LCA0MjQsIDQyMSwgMjIwMywgNDE4LCAyMjAxLCA0MzEsIDQyOSwgMTQ3MywgMTQ3MSwgMTQ2OSwgMTQ2NiwgNDM0LFxuICAgICAgICAxNDc3LCAxNDc1LCAyNDc4LCAyNDcyLCAyNDcwLCAyNDU5LCAyNDU3LCAyNDU0LCAyNDYyLCA4MDMsIDI0MzcsIDI0MzIsIDI0MjksIDE3MjYsIDI0NDMsIDI0NDAsIDc5MiwgNzg5LCA3ODUsXG4gICAgICAgIDI0MDEsIDIzOTksIDIzOTMsIDE3MDIsIDIzODksIDE2OTksIDI0MTEsIDI0MDgsIDI0MDUsIDc0NSwgNzQxLCAyNDE1LCA3NTgsIDc1NSwgMTcyMSwgMjM1OCwgMjM1NywgMjM1NSwgMjM1MyxcbiAgICAgICAgMTY2MSwgMjM1MCwgMTY2MCwgMjM0NywgMTY1NywgMjM2OCwgMjM2NiwgMjM2NCwgMjM2MSwgMTY2NiwgNjkwLCA2ODcsIDIzNzQsIDY4MywgMjM3MiwgNzAxLCA2OTgsIDcwNSwgMTY5MSwgMTY4OSxcbiAgICAgICAgMjYxOSwgMjYxNywgMjYxMCwgMjYwOCwgMjYwNSwgMjYxMywgMjU5MywgMjU4OCwgMjU4NSwgMTgwMywgMjU5OSwgMjU5NiwgMjU2MywgMjU2MSwgMjU1NSwgMTc5NywgMjU1MSwgMTc5NSwgMjU3MyxcbiAgICAgICAgMjU3MCwgMjU2NywgMjU3NywgMjUyNSwgMjUyNCwgMjUyMiwgMjUyMCwgMTc4NiwgMjUxNywgMTc4NSwgMjUxNCwgMTc4MywgMjUzNSwgMjUzMywgMjUzMSwgMjUyOCwgMTc4OCwgMjU0MSwgMjUzOSxcbiAgICAgICAgOTA2LCA5MDMsIDkxMSwgMjcyMSwgMTg0NCwgMjcxNSwgMjcxMiwgMTgzOCwgMTgzNiwgMjY5OSwgMjY5NiwgMjY5MywgMjcwMywgMTgyNywgMTgyNiwgMTgyNCwgMjY3MywgMjY3MSwgMjY2OSxcbiAgICAgICAgMjY2NiwgMTgyOSwgMjY3OSwgMjY3NywgMTg1OCwgMTg1NywgMjc3MiwgMTg1NCwgMTg1MywgMTg1MSwgMTg1NiwgMjc2NiwgMjc2NCwgMTQzLCAxOTg3LCAxMzksIDE5ODYsIDEzNSwgMTMzLFxuICAgICAgICAxMzEsIDE5ODQsIDEyOCwgMTk4MywgMTI1LCAxOTgxLCAxMzgsIDEzNywgMTM2LCAxOTg1LCAxMTMzLCAxMTMyLCAxMTMwLCAxMTIsIDExMCwgMTk3NCwgMTA3LCAxOTczLCAxMDQsIDE5NzEsXG4gICAgICAgIDE5NjksIDEyMiwgMTIxLCAxMTksIDExNywgMTk3NywgMTE0LCAxOTc2LCAxMjQsIDExMTUsIDExMTQsIDExMTIsIDExMTAsIDExMTcsIDExMTYsIDg0LCA4MywgMTk1MywgODEsIDE5NTIsIDc4LFxuICAgICAgICAxOTUwLCAxOTQ4LCAxOTQ1LCA5NCwgOTMsIDkxLCAxOTU5LCA4OCwgMTk1OCwgODUsIDE5NTUsIDk5LCA5NywgOTUsIDE5NjEsIDEwODYsIDEwODUsIDEwODMsIDEwODEsIDEwNzgsIDEwMCxcbiAgICAgICAgMTA5MCwgMTA4OSwgMTA4NywgMTA5MSwgNDksIDQ3LCAxOTE3LCA0NCwgMTkxNSwgMTkxMywgMTkxMCwgMTkwNywgNTksIDE5MjYsIDU2LCAxOTI1LCA1MywgMTkyMiwgMTkxOSwgNjYsIDY0LFxuICAgICAgICAxOTMxLCA2MSwgMTkyOSwgMTA0MiwgMTA0MCwgMTAzOCwgNzEsIDEwMzUsIDcwLCAxMDMyLCA2OCwgMTA0OCwgMTA0NywgMTA0NSwgMTA0MywgMTA1MCwgMTA0OSwgMTIsIDEwLCAxODY5LCAxODY3LFxuICAgICAgICAxODY0LCAxODYxLCAyMSwgMTg4MCwgMTksIDE4NzcsIDE4NzQsIDE4NzEsIDI4LCAxODg4LCAyNSwgMTg4NiwgMjIsIDE4ODMsIDk4MiwgOTgwLCA5NzcsIDk3NCwgMzIsIDMwLCA5OTEsIDk4OSxcbiAgICAgICAgOTg3LCA5ODQsIDM0LCA5OTUsIDk5NCwgOTkyLCAyMTUxLCAyMTUwLCAyMTQ3LCAyMTQ2LCAyMTQ0LCAzNTYsIDM1NSwgMzU0LCAyMTQ5LCAyMTM5LCAyMTM4LCAyMTM2LCAyMTM0LCAxMzU5LFxuICAgICAgICAzNDMsIDM0MSwgMzM4LCAyMTQzLCAzMzUsIDIxNDEsIDM0OCwgMzQ3LCAzNDYsIDEzNzYsIDEzNzQsIDIxMjQsIDIxMjMsIDIxMjEsIDIxMTksIDEzMjYsIDIxMTYsIDEzMjQsIDMxMCwgMzA4LFxuICAgICAgICAzMDUsIDIxMzEsIDMwMiwgMjEyOSwgMjk4LCAyMTI3LCAzMjAsIDMxOCwgMzE2LCAzMTMsIDIxMzMsIDMyMiwgMzIxLCAxMzU1LCAxMzUzLCAxMzUxLCAxMzU3LCAyMDkyLCAyMDkxLCAyMDg5LFxuICAgICAgICAyMDg3LCAxMjc2LCAyMDg0LCAxMjc0LCAyMDgxLCAxMjcxLCAyNTksIDIxMDIsIDI1NiwgMjEwMCwgMjUyLCAyMDk4LCAyMDk1LCAyNzIsIDI2OSwgMjEwOCwgMjY2LCAyMTA2LCAyODEsIDI3OSxcbiAgICAgICAgMjc3LCAxMzE3LCAxMzE1LCAxMzEzLCAxMzEwLCAyODIsIDEzMjEsIDEzMTksIDIwMzksIDIwMzcsIDIwMzUsIDIwMzIsIDEyMDMsIDIwMjksIDEyMDAsIDExOTcsIDIwNywgMjA1MywgMjA1LFxuICAgICAgICAyMDUxLCAyMDEsIDIwNDksIDIwNDYsIDIwNDMsIDIyMCwgMjE4LCAyMDY0LCAyMTUsIDIwNjIsIDIxMSwgMjA1OSwgMjI4LCAyMjYsIDIyMywgMjA2OSwgMTI1OSwgMTI1NywgMTI1NCwgMjMyLFxuICAgICAgICAxMjUxLCAyMzAsIDEyNjcsIDEyNjUsIDEyNjMsIDIzMTYsIDIzMTUsIDIzMTIsIDIzMTEsIDIzMDksIDIzMTQsIDIzMDQsIDIzMDMsIDIzMDEsIDIyOTksIDE1OTMsIDIzMDgsIDIzMDYsIDU5MCxcbiAgICAgICAgMjI4OCwgMjI4NywgMjI4NSwgMjI4MywgMTU3OCwgMjI4MCwgMTU3NywgMjI5NSwgMjI5MywgMjI5MSwgNTc5LCA1NzcsIDU3NCwgNTcxLCAyMjk4LCA1ODIsIDU4MSwgMTU5MiwgMjI2MywgMjI2MixcbiAgICAgICAgMjI2MCwgMjI1OCwgMTU0NSwgMjI1NSwgMTU0NCwgMjI1MiwgMTU0MSwgMjI3MywgMjI3MSwgMjI2OSwgMjI2NiwgMTU1MCwgNTM1LCA1MzIsIDIyNzksIDUyOCwgMjI3NywgNTQ2LCA1NDMsIDU0OSxcbiAgICAgICAgMTU3NSwgMTU3MywgMjIyNCwgMjIyMiwgMjIyMCwgMTQ4NiwgMjIxNywgMTQ4NSwgMjIxNCwgMTQ4MiwgMTQ3OSwgMjIzOCwgMjIzNiwgMjIzNCwgMjIzMSwgMTQ5NiwgMjIyOCwgMTQ5MiwgNDgwLFxuICAgICAgICA0NzcsIDIyNDgsIDQ3MywgMjI0NiwgNDY5LCAyMjQzLCA0OTAsIDQ4NywgMjI1MSwgNDk3LCAxNTM3LCAxNTM1LCAxNTMyLCAyNDc3LCAyNDc2LCAyNDc0LCAyNDc5LCAyNDY5LCAyNDY4LCAyNDY2LFxuICAgICAgICAyNDY0LCAxNzMwLCAyNDczLCAyNDcxLCAyNDUzLCAyNDUyLCAyNDUwLCAyNDQ4LCAxNzI5LCAyNDQ1LCAxNzI4LCAyNDYwLCAyNDU4LCAyNDU2LCAyNDYzLCA4MDUsIDgwNCwgMjQyOCwgMjQyNyxcbiAgICAgICAgMjQyNSwgMjQyMywgMTcyNSwgMjQyMCwgMTcyNCwgMjQxNywgMTcyMiwgMjQzOCwgMjQzNiwgMjQzNCwgMjQzMSwgMTcyNywgMjQ0NCwgMjQ0MiwgNzkzLCA3OTEsIDc4OCwgNzk1LCAyMzg4LFxuICAgICAgICAyMzg2LCAyMzg0LCAxNjk3LCAyMzgxLCAxNjk2LCAyMzc4LCAxNjk0LCAxNjkyLCAyNDAyLCAyNDAwLCAyMzk4LCAyMzk1LCAxNzAzLCAyMzkyLCAxNzAxLCAyNDEyLCAyNDEwLCAyNDA3LCA3NTEsXG4gICAgICAgIDc0OCwgNzQ0LCAyNDE2LCA3NTksIDc1NywgMTgwNywgMjYyMCwgMjYxOCwgMTgwNiwgMTgwNSwgMjYxMSwgMjYwOSwgMjYwNywgMjYxNCwgMTgwMiwgMTgwMSwgMTc5OSwgMjU5NCwgMjU5MixcbiAgICAgICAgMjU5MCwgMjU4NywgMTgwNCwgMjYwMCwgMjU5OCwgMTc5NCwgMTc5MywgMTc5MSwgMTc4OSwgMjU2NCwgMjU2MiwgMjU2MCwgMjU1NywgMTc5OCwgMjU1NCwgMTc5NiwgMjU3NCwgMjU3MiwgMjU2OSxcbiAgICAgICAgMjU3OCwgMTg0NywgMTg0NiwgMjcyMiwgMTg0MywgMTg0MiwgMTg0MCwgMTg0NSwgMjcxNiwgMjcxNCwgMTgzNSwgMTgzNCwgMTgzMiwgMTgzMCwgMTgzOSwgMTgzNywgMjcwMCwgMjY5OCwgMjY5NSxcbiAgICAgICAgMjcwNCwgMTgxNywgMTgxMSwgMTgxMCwgODk3LCA4NjIsIDE3NzcsIDgyOSwgODI2LCA4MzgsIDE3NjAsIDE3NTgsIDgwOCwgMjQ4MSwgMTc0MSwgMTc0MCwgMTczOCwgMTc0MywgMjYyNCwgMTgxOCxcbiAgICAgICAgMjcyNiwgMjc3NiwgNzgyLCA3NDAsIDczNywgMTcxNSwgNjg2LCA2NzksIDY5NSwgMTY4MiwgMTY4MCwgNjM5LCA2MjgsIDIzMzksIDY0NywgNjQ0LCAxNjQ1LCAxNjQzLCAxNjQwLCAxNjQ4LFxuICAgICAgICA2MDIsIDYwMCwgNTk3LCA1OTUsIDIzMjAsIDU5MywgMjMxOCwgNjA5LCA2MDcsIDYwNCwgMTYxMSwgMTYxMCwgMTYwOCwgMTYwNiwgNjEzLCAxNjE1LCAxNjEzLCAyMzI4LCA5MjYsIDkyNCwgODkyLFxuICAgICAgICA4ODYsIDg5OSwgODU3LCA4NTAsIDI1MDUsIDE3NzgsIDgyNCwgODIzLCA4MjEsIDgxOSwgMjQ4OCwgODE4LCAyNDg2LCA4MzMsIDgzMSwgODI4LCA4NDAsIDE3NjEsIDE3NTksIDI2NDksIDI2MzIsXG4gICAgICAgIDI2MzAsIDI3NDYsIDI3MzQsIDI3MzIsIDI3ODIsIDI3ODEsIDU3MCwgNTY3LCAxNTg3LCA1MzEsIDUyNywgNTIzLCA1NDAsIDE1NjYsIDE1NjQsIDQ3NiwgNDY3LCA0NjMsIDIyNDAsIDQ4NixcbiAgICAgICAgNDgzLCAxNTI0LCAxNTIxLCAxNTE4LCAxNTI5LCA0MTEsIDQwMywgMjE5MiwgMzk5LCAyMTg5LCA0MjMsIDQxNiwgMTQ2MiwgMTQ1NywgMTQ1NCwgNDI4LCAxNDY4LCAxNDY1LCAyMjEwLCAzNjYsXG4gICAgICAgIDM2MywgMjE1OCwgMzYwLCAyMTU2LCAzNTcsIDIxNTMsIDM3NiwgMzczLCAzNzAsIDIxNjMsIDE0MTAsIDE0MDksIDE0MDcsIDE0MDUsIDM4MiwgMTQwMiwgMzgwLCAxNDE3LCAxNDE1LCAxNDEyLFxuICAgICAgICAxNDIxLCAyMTc1LCAyMTc0LCA3NzcsIDc3NCwgNzcxLCA3ODQsIDczMiwgNzI1LCA3MjIsIDI0MDQsIDc0MywgMTcxNiwgNjc2LCA2NzQsIDY2OCwgMjM2MywgNjY1LCAyMzYwLCA2ODUsIDE2ODQsXG4gICAgICAgIDE2ODEsIDYyNiwgNjI0LCA2MjIsIDIzMzUsIDYyMCwgMjMzMywgNjE3LCAyMzMwLCA2NDEsIDYzNSwgNjQ5LCAxNjQ2LCAxNjQ0LCAxNjQyLCAyNTY2LCA5MjgsIDkyNSwgMjUzMCwgMjUyNyxcbiAgICAgICAgODk0LCA4OTEsIDg4OCwgMjUwMSwgMjQ5OSwgMjQ5NiwgODU4LCA4NTYsIDg1NCwgODUxLCAxNzc5LCAyNjkyLCAyNjY4LCAyNjY1LCAyNjQ1LCAyNjQzLCAyNjQwLCAyNjUxLCAyNzY4LCAyNzU5LFxuICAgICAgICAyNzU3LCAyNzQ0LCAyNzQzLCAyNzQxLCAyNzQ4LCAzNTIsIDEzODIsIDM0MCwgMzM3LCAzMzMsIDEzNzEsIDEzNjksIDMwNywgMzAwLCAyOTYsIDIxMjYsIDMxNSwgMzEyLCAxMzQ3LCAxMzQyLFxuICAgICAgICAxMzUwLCAyNjEsIDI1OCwgMjUwLCAyMDk3LCAyNDYsIDIwOTQsIDI3MSwgMjY4LCAyNjQsIDEzMDYsIDEzMDEsIDEyOTgsIDI3NiwgMTMxMiwgMTMwOSwgMjExNSwgMjAzLCAyMDQ4LCAxOTUsXG4gICAgICAgIDIwNDUsIDE5MSwgMjA0MSwgMjEzLCAyMDksIDIwNTYsIDEyNDYsIDEyNDQsIDEyMzgsIDIyNSwgMTIzNCwgMjIyLCAxMjU2LCAxMjUzLCAxMjQ5LCAxMjYyLCAyMDgwLCAyMDc5LCAxNTQsIDE5OTcsXG4gICAgICAgIDE1MCwgMTk5NSwgMTQ3LCAxOTkyLCAxOTg5LCAxNjMsIDE2MCwgMjAwNCwgMTU2LCAyMDAxLCAxMTc1LCAxMTc0LCAxMTcyLCAxMTcwLCAxMTY3LCAxNzAsIDExNjQsIDE2NywgMTE4NSwgMTE4MyxcbiAgICAgICAgMTE4MCwgMTE3NywgMTc0LCAxMTkwLCAxMTg4LCAyMDI1LCAyMDI0LCAyMDIyLCA1ODcsIDU4NiwgNTY0LCA1NTksIDU1NiwgMjI5MCwgNTczLCAxNTg4LCA1MjAsIDUxOCwgNTEyLCAyMjY4LFxuICAgICAgICA1MDgsIDIyNjUsIDUzMCwgMTU2OCwgMTU2NSwgNDYxLCA0NTcsIDIyMzMsIDQ1MCwgMjIzMCwgNDQ2LCAyMjI2LCA0NzksIDQ3MSwgNDg5LCAxNTI2LCAxNTIzLCAxNTIwLCAzOTcsIDM5NSxcbiAgICAgICAgMjE4NSwgMzkyLCAyMTgzLCAzODksIDIxODAsIDIxNzcsIDQxMCwgMjE5NCwgNDAyLCA0MjIsIDE0NjMsIDE0NjEsIDE0NTksIDE0NTYsIDE0NzAsIDI0NTUsIDc5OSwgMjQzMywgMjQzMCwgNzc5LFxuICAgICAgICA3NzYsIDc3MywgMjM5NywgMjM5NCwgMjM5MCwgNzM0LCA3MjgsIDcyNCwgNzQ2LCAxNzE3LCAyMzU2LCAyMzU0LCAyMzUxLCAyMzQ4LCAxNjU4LCA2NzcsIDY3NSwgNjczLCA2NzAsIDY2NywgNjg4LFxuICAgICAgICAxNjg1LCAxNjgzLCAyNjA2LCAyNTg5LCAyNTg2LCAyNTU5LCAyNTU2LCAyNTUyLCA5MjcsIDI1MjMsIDI1MjEsIDI1MTgsIDI1MTUsIDE3ODQsIDI1MzIsIDg5NSwgODkzLCA4OTAsIDI3MTgsXG4gICAgICAgIDI3MDksIDI3MDcsIDI2ODksIDI2ODcsIDI2ODQsIDI2NjMsIDI2NjIsIDI2NjAsIDI2NTgsIDE4MjUsIDI2NjcsIDI3NjksIDE4NTIsIDI3NjAsIDI3NTgsIDE0MiwgMTQxLCAxMTM5LCAxMTM4LFxuICAgICAgICAxMzQsIDEzMiwgMTI5LCAxMjYsIDE5ODIsIDExMjksIDExMjgsIDExMjYsIDExMzEsIDExMywgMTExLCAxMDgsIDEwNSwgMTk3MiwgMTAxLCAxOTcwLCAxMjAsIDExOCwgMTE1LCAxMTA5LCAxMTA4LFxuICAgICAgICAxMTA2LCAxMTA0LCAxMjMsIDExMTMsIDExMTEsIDgyLCA3OSwgMTk1MSwgNzUsIDE5NDksIDcyLCAxOTQ2LCA5MiwgODksIDg2LCAxOTU2LCAxMDc3LCAxMDc2LCAxMDc0LCAxMDcyLCA5OCxcbiAgICAgICAgMTA2OSwgOTYsIDEwODQsIDEwODIsIDEwNzksIDEwODgsIDE5NjgsIDE5NjcsIDQ4LCA0NSwgMTkxNiwgNDIsIDE5MTQsIDM5LCAxOTExLCAxOTA4LCA2MCwgNTcsIDU0LCAxOTIzLCA1MCwgMTkyMCxcbiAgICAgICAgMTAzMSwgMTAzMCwgMTAyOCwgMTAyNiwgNjcsIDEwMjMsIDY1LCAxMDIwLCA2MiwgMTA0MSwgMTAzOSwgMTAzNiwgMTAzMywgNjksIDEwNDYsIDEwNDQsIDE5NDQsIDE5NDMsIDE5NDEsIDExLCA5LFxuICAgICAgICAxODY4LCA3LCAxODY1LCAxODYyLCAxODU5LCAyMCwgMTg3OCwgMTYsIDE4NzUsIDEzLCAxODcyLCA5NzAsIDk2OCwgOTY2LCA5NjMsIDI5LCA5NjAsIDI2LCAyMywgOTgzLCA5ODEsIDk3OCwgOTc1LFxuICAgICAgICAzMywgOTcxLCAzMSwgOTkwLCA5ODgsIDk4NSwgMTkwNiwgMTkwNCwgMTkwMiwgOTkzLCAzNTEsIDIxNDUsIDEzODMsIDMzMSwgMzMwLCAzMjgsIDMyNiwgMjEzNywgMzIzLCAyMTM1LCAzMzksXG4gICAgICAgIDEzNzIsIDEzNzAsIDI5NCwgMjkzLCAyOTEsIDI4OSwgMjEyMiwgMjg2LCAyMTIwLCAyODMsIDIxMTcsIDMwOSwgMzAzLCAzMTcsIDEzNDgsIDEzNDYsIDEzNDQsIDI0NSwgMjQ0LCAyNDIsIDIwOTAsXG4gICAgICAgIDIzOSwgMjA4OCwgMjM2LCAyMDg1LCAyMDgyLCAyNjAsIDIwOTksIDI0OSwgMjcwLCAxMzA3LCAxMzA1LCAxMzAzLCAxMzAwLCAxMzE0LCAxODksIDIwMzgsIDE4NiwgMjAzNiwgMTgzLCAyMDMzLFxuICAgICAgICAyMDMwLCAyMDI2LCAyMDYsIDE5OCwgMjA0NywgMTk0LCAyMTYsIDEyNDcsIDEyNDUsIDEyNDMsIDEyNDAsIDIyNywgMTIzNywgMTI1NSwgMjMxMCwgMjMwMiwgMjMwMCwgMjI4NiwgMjI4NCxcbiAgICAgICAgMjI4MSwgNTY1LCA1NjMsIDU2MSwgNTU4LCA1NzUsIDE1ODksIDIyNjEsIDIyNTksIDIyNTYsIDIyNTMsIDE1NDIsIDUyMSwgNTE5LCA1MTcsIDUxNCwgMjI3MCwgNTExLCA1MzMsIDE1NjksXG4gICAgICAgIDE1NjcsIDIyMjMsIDIyMjEsIDIyMTgsIDIyMTUsIDE0ODMsIDIyMTEsIDE0ODAsIDQ1OSwgNDU2LCA0NTMsIDIyMzIsIDQ0OSwgNDc0LCA0OTEsIDE1MjcsIDE1MjUsIDE1MjIsIDI0NzUsIDI0NjcsXG4gICAgICAgIDI0NjUsIDI0NTEsIDI0NDksIDI0NDYsIDgwMSwgODAwLCAyNDI2LCAyNDI0LCAyNDIxLCAyNDE4LCAxNzIzLCAyNDM1LCA3ODAsIDc3OCwgNzc1LCAyMzg3LCAyMzg1LCAyMzgyLCAyMzc5LFxuICAgICAgICAxNjk1LCAyMzc1LCAxNjkzLCAyMzk2LCA3MzUsIDczMywgNzMwLCA3MjcsIDc0OSwgMTcxOCwgMjYxNiwgMjYxNSwgMjYwNCwgMjYwMywgMjYwMSwgMjU4NCwgMjU4MywgMjU4MSwgMjU3OSxcbiAgICAgICAgMTgwMCwgMjU5MSwgMjU1MCwgMjU0OSwgMjU0NywgMjU0NSwgMTc5MiwgMjU0MiwgMTc5MCwgMjU1OCwgOTI5LCAyNzE5LCAxODQxLCAyNzEwLCAyNzA4LCAxODMzLCAxODMxLCAyNjkwLCAyNjg4LFxuICAgICAgICAyNjg2LCAxODE1LCAxODA5LCAxODA4LCAxNzc0LCAxNzU2LCAxNzU0LCAxNzM3LCAxNzM2LCAxNzM0LCAxNzM5LCAxODE2LCAxNzExLCAxNjc2LCAxNjc0LCA2MzMsIDYyOSwgMTYzOCwgMTYzNixcbiAgICAgICAgMTYzMywgMTY0MSwgNTk4LCAxNjA1LCAxNjA0LCAxNjAyLCAxNjAwLCA2MDUsIDE2MDksIDE2MDcsIDIzMjcsIDg4NywgODUzLCAxNzc1LCA4MjIsIDgyMCwgMTc1NywgMTc1NSwgMTU4NCwgNTI0LFxuICAgICAgICAxNTYwLCAxNTU4LCA0NjgsIDQ2NCwgMTUxNCwgMTUxMSwgMTUwOCwgMTUxOSwgNDA4LCA0MDQsIDQwMCwgMTQ1MiwgMTQ0NywgMTQ0NCwgNDE3LCAxNDU4LCAxNDU1LCAyMjA4LCAzNjQsIDM2MSxcbiAgICAgICAgMzU4LCAyMTU0LCAxNDAxLCAxNDAwLCAxMzk4LCAxMzk2LCAzNzQsIDEzOTMsIDM3MSwgMTQwOCwgMTQwNiwgMTQwMywgMTQxMywgMjE3MywgMjE3MiwgNzcyLCA3MjYsIDcyMywgMTcxMiwgNjcyLFxuICAgICAgICA2NjksIDY2NiwgNjgyLCAxNjc4LCAxNjc1LCA2MjUsIDYyMywgNjIxLCA2MTgsIDIzMzEsIDYzNiwgNjMyLCAxNjM5LCAxNjM3LCAxNjM1LCA5MjAsIDkxOCwgODg0LCA4ODAsIDg4OSwgODQ5LFxuICAgICAgICA4NDgsIDg0NywgODQ2LCAyNDk3LCA4NTUsIDg1MiwgMTc3NiwgMjY0MSwgMjc0MiwgMjc4NywgMTM4MCwgMzM0LCAxMzY3LCAxMzY1LCAzMDEsIDI5NywgMTM0MCwgMTMzOCwgMTMzNSwgMTM0MyxcbiAgICAgICAgMjU1LCAyNTEsIDI0NywgMTI5NiwgMTI5MSwgMTI4OCwgMjY1LCAxMzAyLCAxMjk5LCAyMTEzLCAyMDQsIDE5NiwgMTkyLCAyMDQyLCAxMjMyLCAxMjMwLCAxMjI0LCAyMTQsIDEyMjAsIDIxMCxcbiAgICAgICAgMTI0MiwgMTIzOSwgMTIzNSwgMTI1MCwgMjA3NywgMjA3NSwgMTUxLCAxNDgsIDE5OTMsIDE0NCwgMTk5MCwgMTE2MywgMTE2MiwgMTE2MCwgMTE1OCwgMTE1NSwgMTYxLCAxMTUyLCAxNTcsXG4gICAgICAgIDExNzMsIDExNzEsIDExNjgsIDExNjUsIDE2OCwgMTE4MSwgMTE3OCwgMjAyMSwgMjAyMCwgMjAxOCwgMjAyMywgNTg1LCA1NjAsIDU1NywgMTU4NSwgNTE2LCA1MDksIDE1NjIsIDE1NTksIDQ1OCxcbiAgICAgICAgNDQ3LCAyMjI3LCA0NzIsIDE1MTYsIDE1MTMsIDE1MTAsIDM5OCwgMzk2LCAzOTMsIDM5MCwgMjE4MSwgMzg2LCAyMTc4LCA0MDcsIDE0NTMsIDE0NTEsIDE0NDksIDE0NDYsIDQyMCwgMTQ2MCxcbiAgICAgICAgMjIwOSwgNzY5LCA3NjQsIDcyMCwgNzEyLCAyMzkxLCA3MjksIDE3MTMsIDY2NCwgNjYzLCA2NjEsIDY1OSwgMjM1MiwgNjU2LCAyMzQ5LCA2NzEsIDE2NzksIDE2NzcsIDI1NTMsIDkyMiwgOTE5LFxuICAgICAgICAyNTE5LCAyNTE2LCA4ODUsIDg4MywgODgxLCAyNjg1LCAyNjYxLCAyNjU5LCAyNzY3LCAyNzU2LCAyNzU1LCAxNDAsIDExMzcsIDExMzYsIDEzMCwgMTI3LCAxMTI1LCAxMTI0LCAxMTIyLCAxMTI3LFxuICAgICAgICAxMDksIDEwNiwgMTAyLCAxMTAzLCAxMTAyLCAxMTAwLCAxMDk4LCAxMTYsIDExMDcsIDExMDUsIDE5ODAsIDgwLCA3NiwgNzMsIDE5NDcsIDEwNjgsIDEwNjcsIDEwNjUsIDEwNjMsIDkwLCAxMDYwLFxuICAgICAgICA4NywgMTA3NSwgMTA3MywgMTA3MCwgMTA4MCwgMTk2NiwgMTk2NSwgNDYsIDQzLCA0MCwgMTkxMiwgMzYsIDE5MDksIDEwMTksIDEwMTgsIDEwMTYsIDEwMTQsIDU4LCAxMDExLCA1NSwgMTAwOCxcbiAgICAgICAgNTEsIDEwMjksIDEwMjcsIDEwMjQsIDEwMjEsIDYzLCAxMDM3LCAxMDM0LCAxOTQwLCAxOTM5LCAxOTM3LCAxOTQyLCA4LCAxODY2LCA0LCAxODYzLCAxLCAxODYwLCA5NTYsIDk1NCwgOTUyLFxuICAgICAgICA5NDksIDk0NiwgMTcsIDE0LCA5NjksIDk2NywgOTY0LCA5NjEsIDI3LCA5NTcsIDI0LCA5NzksIDk3NiwgOTcyLCAxOTAxLCAxOTAwLCAxODk4LCAxODk2LCA5ODYsIDE5MDUsIDE5MDMsIDM1MCxcbiAgICAgICAgMzQ5LCAxMzgxLCAzMjksIDMyNywgMzI0LCAxMzY4LCAxMzY2LCAyOTIsIDI5MCwgMjg3LCAyODQsIDIxMTgsIDMwNCwgMTM0MSwgMTMzOSwgMTMzNywgMTM0NSwgMjQzLCAyNDAsIDIzNywgMjA4NixcbiAgICAgICAgMjMzLCAyMDgzLCAyNTQsIDEyOTcsIDEyOTUsIDEyOTMsIDEyOTAsIDEzMDQsIDIxMTQsIDE5MCwgMTg3LCAxODQsIDIwMzQsIDE4MCwgMjAzMSwgMTc3LCAyMDI3LCAxOTksIDEyMzMsIDEyMzEsXG4gICAgICAgIDEyMjksIDEyMjYsIDIxNywgMTIyMywgMTI0MSwgMjA3OCwgMjA3NiwgNTg0LCA1NTUsIDU1NCwgNTUyLCA1NTAsIDIyODIsIDU2MiwgMTU4NiwgNTA3LCA1MDYsIDUwNCwgNTAyLCAyMjU3LCA0OTksXG4gICAgICAgIDIyNTQsIDUxNSwgMTU2MywgMTU2MSwgNDQ1LCA0NDMsIDQ0MSwgMjIxOSwgNDM4LCAyMjE2LCA0MzUsIDIyMTIsIDQ2MCwgNDU0LCA0NzUsIDE1MTcsIDE1MTUsIDE1MTIsIDI0NDcsIDc5OCxcbiAgICAgICAgNzk3LCAyNDIyLCAyNDE5LCA3NzAsIDc2OCwgNzY2LCAyMzgzLCAyMzgwLCAyMzc2LCA3MjEsIDcxOSwgNzE3LCA3MTQsIDczMSwgMTcxNCwgMjYwMiwgMjU4MiwgMjU4MCwgMjU0OCwgMjU0NixcbiAgICAgICAgMjU0MywgOTIzLCA5MjEsIDI3MTcsIDI3MDYsIDI3MDUsIDI2ODMsIDI2ODIsIDI2ODAsIDE3NzEsIDE3NTIsIDE3NTAsIDE3MzMsIDE3MzIsIDE3MzEsIDE3MzUsIDE4MTQsIDE3MDcsIDE2NzAsXG4gICAgICAgIDE2NjgsIDE2MzEsIDE2MjksIDE2MjYsIDE2MzQsIDE1OTksIDE1OTgsIDE1OTYsIDE1OTQsIDE2MDMsIDE2MDEsIDIzMjYsIDE3NzIsIDE3NTMsIDE3NTEsIDE1ODEsIDE1NTQsIDE1NTIsIDE1MDQsXG4gICAgICAgIDE1MDEsIDE0OTgsIDE1MDksIDE0NDIsIDE0MzcsIDE0MzQsIDQwMSwgMTQ0OCwgMTQ0NSwgMjIwNiwgMTM5MiwgMTM5MSwgMTM4OSwgMTM4NywgMTM4NCwgMzU5LCAxMzk5LCAxMzk3LCAxMzk0LFxuICAgICAgICAxNDA0LCAyMTcxLCAyMTcwLCAxNzA4LCAxNjcyLCAxNjY5LCA2MTksIDE2MzIsIDE2MzAsIDE2MjgsIDE3NzMsIDEzNzgsIDEzNjMsIDEzNjEsIDEzMzMsIDEzMjgsIDEzMzYsIDEyODYsIDEyODEsXG4gICAgICAgIDEyNzgsIDI0OCwgMTI5MiwgMTI4OSwgMjExMSwgMTIxOCwgMTIxNiwgMTIxMCwgMTk3LCAxMjA2LCAxOTMsIDEyMjgsIDEyMjUsIDEyMjEsIDEyMzYsIDIwNzMsIDIwNzEsIDExNTEsIDExNTAsXG4gICAgICAgIDExNDgsIDExNDYsIDE1MiwgMTE0MywgMTQ5LCAxMTQwLCAxNDUsIDExNjEsIDExNTksIDExNTYsIDExNTMsIDE1OCwgMTE2OSwgMTE2NiwgMjAxNywgMjAxNiwgMjAxNCwgMjAxOSwgMTU4MixcbiAgICAgICAgNTEwLCAxNTU2LCAxNTUzLCA0NTIsIDQ0OCwgMTUwNiwgMTUwMCwgMzk0LCAzOTEsIDM4NywgMTQ0MywgMTQ0MSwgMTQzOSwgMTQzNiwgMTQ1MCwgMjIwNywgNzY1LCA3MTYsIDcxMywgMTcwOSxcbiAgICAgICAgNjYyLCA2NjAsIDY1NywgMTY3MywgMTY3MSwgOTE2LCA5MTQsIDg3OSwgODc4LCA4NzcsIDg4MiwgMTEzNSwgMTEzNCwgMTEyMSwgMTEyMCwgMTExOCwgMTEyMywgMTA5NywgMTA5NiwgMTA5NCxcbiAgICAgICAgMTA5MiwgMTAzLCAxMTAxLCAxMDk5LCAxOTc5LCAxMDU5LCAxMDU4LCAxMDU2LCAxMDU0LCA3NywgMTA1MSwgNzQsIDEwNjYsIDEwNjQsIDEwNjEsIDEwNzEsIDE5NjQsIDE5NjMsIDEwMDcsXG4gICAgICAgIDEwMDYsIDEwMDQsIDEwMDIsIDk5OSwgNDEsIDk5NiwgMzcsIDEwMTcsIDEwMTUsIDEwMTIsIDEwMDksIDUyLCAxMDI1LCAxMDIyLCAxOTM2LCAxOTM1LCAxOTMzLCAxOTM4LCA5NDIsIDk0MCxcbiAgICAgICAgOTM4LCA5MzUsIDkzMiwgNSwgMiwgOTU1LCA5NTMsIDk1MCwgOTQ3LCAxOCwgOTQzLCAxNSwgOTY1LCA5NjIsIDk1OCwgMTg5NSwgMTg5NCwgMTg5MiwgMTg5MCwgOTczLCAxODk5LCAxODk3LFxuICAgICAgICAxMzc5LCAzMjUsIDEzNjQsIDEzNjIsIDI4OCwgMjg1LCAxMzM0LCAxMzMyLCAxMzMwLCAyNDEsIDIzOCwgMjM0LCAxMjg3LCAxMjg1LCAxMjgzLCAxMjgwLCAxMjk0LCAyMTEyLCAxODgsIDE4NSxcbiAgICAgICAgMTgxLCAxNzgsIDIwMjgsIDEyMTksIDEyMTcsIDEyMTUsIDEyMTIsIDIwMCwgMTIwOSwgMTIyNywgMjA3NCwgMjA3MiwgNTgzLCA1NTMsIDU1MSwgMTU4MywgNTA1LCA1MDMsIDUwMCwgNTEzLFxuICAgICAgICAxNTU3LCAxNTU1LCA0NDQsIDQ0MiwgNDM5LCA0MzYsIDIyMTMsIDQ1NSwgNDUxLCAxNTA3LCAxNTA1LCAxNTAyLCA3OTYsIDc2MywgNzYyLCA3NjAsIDc2NywgNzExLCA3MTAsIDcwOCwgNzA2LFxuICAgICAgICAyMzc3LCA3MTgsIDcxNSwgMTcxMCwgMjU0NCwgOTE3LCA5MTUsIDI2ODEsIDE2MjcsIDE1OTcsIDE1OTUsIDIzMjUsIDE3NjksIDE3NDksIDE3NDcsIDE0OTksIDE0MzgsIDE0MzUsIDIyMDQsXG4gICAgICAgIDEzOTAsIDEzODgsIDEzODUsIDEzOTUsIDIxNjksIDIxNjcsIDE3MDQsIDE2NjUsIDE2NjIsIDE2MjUsIDE2MjMsIDE2MjAsIDE3NzAsIDEzMjksIDEyODIsIDEyNzksIDIxMDksIDEyMTQsIDEyMDcsXG4gICAgICAgIDEyMjIsIDIwNjgsIDIwNjUsIDExNDksIDExNDcsIDExNDQsIDExNDEsIDE0NiwgMTE1NywgMTE1NCwgMjAxMywgMjAxMSwgMjAwOCwgMjAxNSwgMTU3OSwgMTU0OSwgMTU0NiwgMTQ5NSwgMTQ4NyxcbiAgICAgICAgMTQzMywgMTQzMSwgMTQyOCwgMTQyNSwgMzg4LCAxNDQwLCAyMjA1LCAxNzA1LCA2NTgsIDE2NjcsIDE2NjQsIDExMTksIDEwOTUsIDEwOTMsIDE5NzgsIDEwNTcsIDEwNTUsIDEwNTIsIDEwNjIsXG4gICAgICAgIDE5NjIsIDE5NjAsIDEwMDUsIDEwMDMsIDEwMDAsIDk5NywgMzgsIDEwMTMsIDEwMTAsIDE5MzIsIDE5MzAsIDE5MjcsIDE5MzQsIDk0MSwgOTM5LCA5MzYsIDkzMywgNiwgOTMwLCAzLCA5NTEsXG4gICAgICAgIDk0OCwgOTQ0LCAxODg5LCAxODg3LCAxODg0LCAxODgxLCA5NTksIDE4OTMsIDE4OTEsIDM1LCAxMzc3LCAxMzYwLCAxMzU4LCAxMzI3LCAxMzI1LCAxMzIyLCAxMzMxLCAxMjc3LCAxMjc1LFxuICAgICAgICAxMjcyLCAxMjY5LCAyMzUsIDEyODQsIDIxMTAsIDEyMDUsIDEyMDQsIDEyMDEsIDExOTgsIDE4MiwgMTE5NSwgMTc5LCAxMjEzLCAyMDcwLCAyMDY3LCAxNTgwLCA1MDEsIDE1NTEsIDE1NDgsXG4gICAgICAgIDQ0MCwgNDM3LCAxNDk3LCAxNDk0LCAxNDkwLCAxNTAzLCA3NjEsIDcwOSwgNzA3LCAxNzA2LCA5MTMsIDkxMiwgMjE5OCwgMTM4NiwgMjE2NCwgMjE2MSwgMTYyMSwgMTc2NiwgMjEwMywgMTIwOCxcbiAgICAgICAgMjA1OCwgMjA1NCwgMTE0NSwgMTE0MiwgMjAwNSwgMjAwMiwgMTk5OSwgMjAwOSwgMTQ4OCwgMTQyOSwgMTQyNiwgMjIwMCwgMTY5OCwgMTY1OSwgMTY1NiwgMTk3NSwgMTA1MywgMTk1NywgMTk1NCxcbiAgICAgICAgMTAwMSwgOTk4LCAxOTI0LCAxOTIxLCAxOTE4LCAxOTI4LCA5MzcsIDkzNCwgOTMxLCAxODc5LCAxODc2LCAxODczLCAxODcwLCA5NDUsIDE4ODUsIDE4ODIsIDEzMjMsIDEyNzMsIDEyNzAsXG4gICAgICAgIDIxMDUsIDEyMDIsIDExOTksIDExOTYsIDEyMTEsIDIwNjEsIDIwNTcsIDE1NzYsIDE1NDMsIDE1NDAsIDE0ODQsIDE0ODEsIDE0NzgsIDE0OTEsIDE3MDBcbiAgICBdKTtcblxuICAgIC8qXG4gICAgKiBDb3B5cmlnaHQgMjAwNyBaWGluZyBhdXRob3JzXG4gICAgKlxuICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICpcbiAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgKlxuICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAqL1xuICAgIC8vIGltcG9ydCBqYXZhLnV0aWwuTGlzdDtcbiAgICAvKipcbiAgICAgKiBAYXV0aG9yIEd1ZW50aGVyIEdyYXVcbiAgICAgKi9cbiAgICAvKnB1YmxpYyBmaW5hbCovIGNsYXNzIFBERjQxN0RldGVjdG9yUmVzdWx0IHtcbiAgICAgICAgY29uc3RydWN0b3IoYml0cywgcG9pbnRzKSB7XG4gICAgICAgICAgICB0aGlzLmJpdHMgPSBiaXRzO1xuICAgICAgICAgICAgdGhpcy5wb2ludHMgPSBwb2ludHM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Qml0cygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJpdHM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0UG9pbnRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucG9pbnRzO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAqIENvcHlyaWdodCAyMDA5IFpYaW5nIGF1dGhvcnNcbiAgICAqXG4gICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgKlxuICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAqXG4gICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICovXG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7XG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5BcnJheXM7XG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5MaXN0O1xuICAgIC8vIGltcG9ydCBqYXZhLnV0aWwuTWFwO1xuICAgIC8qKlxuICAgICAqIDxwPkVuY2Fwc3VsYXRlcyBsb2dpYyB0aGF0IGNhbiBkZXRlY3QgYSBQREY0MTcgQ29kZSBpbiBhbiBpbWFnZSwgZXZlbiBpZiB0aGVcbiAgICAgKiBQREY0MTcgQ29kZSBpcyByb3RhdGVkIG9yIHNrZXdlZCwgb3IgcGFydGlhbGx5IG9ic2N1cmVkLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU0lUQSBMYWIgKGtldmluLm9zdWxsaXZhbkBzaXRhLmFlcm8pXG4gICAgICogQGF1dGhvciBkc3dpdGtpbkBnb29nbGUuY29tIChEYW5pZWwgU3dpdGtpbilcbiAgICAgKiBAYXV0aG9yIEd1ZW50aGVyIEdyYXVcbiAgICAgKi9cbiAgICAvKnB1YmxpYyovIC8qZmluYWwqLyBjbGFzcyBEZXRlY3RvciQzIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkRldGVjdHMgYSBQREY0MTcgQ29kZSBpbiBhbiBpbWFnZS4gT25seSBjaGVja3MgMCBhbmQgMTgwIGRlZ3JlZSByb3RhdGlvbnMuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gaW1hZ2UgYmFyY29kZSBpbWFnZSB0byBkZWNvZGVcbiAgICAgICAgICogQHBhcmFtIGhpbnRzIG9wdGlvbmFsIGhpbnRzIHRvIGRldGVjdG9yXG4gICAgICAgICAqIEBwYXJhbSBtdWx0aXBsZSBpZiB0cnVlLCB0aGVuIHRoZSBpbWFnZSBpcyBzZWFyY2hlZCBmb3IgbXVsdGlwbGUgY29kZXMuIElmIGZhbHNlLCB0aGVuIGF0IG1vc3Qgb25lIGNvZGUgd2lsbFxuICAgICAgICAgKiBiZSBmb3VuZCBhbmQgcmV0dXJuZWRcbiAgICAgICAgICogQHJldHVybiB7QGxpbmsgUERGNDE3RGV0ZWN0b3JSZXN1bHR9IGVuY2Fwc3VsYXRpbmcgcmVzdWx0cyBvZiBkZXRlY3RpbmcgYSBQREY0MTcgY29kZVxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIGlmIG5vIFBERjQxNyBDb2RlIGNhbiBiZSBmb3VuZFxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGRldGVjdE11bHRpcGxlKGltYWdlLCBoaW50cywgbXVsdGlwbGUpIHtcbiAgICAgICAgICAgIC8vIFRPRE8gZGV0ZWN0aW9uIGltcHJvdmVtZW50LCB0cnlIYXJkZXIgY291bGQgdHJ5IHNldmVyYWwgZGlmZmVyZW50IGx1bWluYW5jZSB0aHJlc2hvbGRzL2JsYWNrcG9pbnRzIG9yIGV2ZW5cbiAgICAgICAgICAgIC8vIGRpZmZlcmVudCBiaW5hcml6ZXJzXG4gICAgICAgICAgICAvLyBib29sZWFuIHRyeUhhcmRlciA9IGhpbnRzICE9IG51bGwgJiYgaGludHMuY29udGFpbnNLZXkoRGVjb2RlSGludFR5cGUuVFJZX0hBUkRFUik7XG4gICAgICAgICAgICBsZXQgYml0TWF0cml4ID0gaW1hZ2UuZ2V0QmxhY2tNYXRyaXgoKTtcbiAgICAgICAgICAgIGxldCBiYXJjb2RlQ29vcmRpbmF0ZXMgPSBEZXRlY3RvciQzLmRldGVjdChtdWx0aXBsZSwgYml0TWF0cml4KTtcbiAgICAgICAgICAgIGlmICghYmFyY29kZUNvb3JkaW5hdGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGJpdE1hdHJpeCA9IGJpdE1hdHJpeC5jbG9uZSgpO1xuICAgICAgICAgICAgICAgIGJpdE1hdHJpeC5yb3RhdGUxODAoKTtcbiAgICAgICAgICAgICAgICBiYXJjb2RlQ29vcmRpbmF0ZXMgPSBEZXRlY3RvciQzLmRldGVjdChtdWx0aXBsZSwgYml0TWF0cml4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgUERGNDE3RGV0ZWN0b3JSZXN1bHQoYml0TWF0cml4LCBiYXJjb2RlQ29vcmRpbmF0ZXMpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZXRlY3RzIFBERjQxNyBjb2RlcyBpbiBhbiBpbWFnZS4gT25seSBjaGVja3MgMCBkZWdyZWUgcm90YXRpb25cbiAgICAgICAgICogQHBhcmFtIG11bHRpcGxlIGlmIHRydWUsIHRoZW4gdGhlIGltYWdlIGlzIHNlYXJjaGVkIGZvciBtdWx0aXBsZSBjb2Rlcy4gSWYgZmFsc2UsIHRoZW4gYXQgbW9zdCBvbmUgY29kZSB3aWxsXG4gICAgICAgICAqIGJlIGZvdW5kIGFuZCByZXR1cm5lZFxuICAgICAgICAgKiBAcGFyYW0gYml0TWF0cml4IGJpdCBtYXRyaXggdG8gZGV0ZWN0IGJhcmNvZGVzIGluXG4gICAgICAgICAqIEByZXR1cm4gTGlzdCBvZiBSZXN1bHRQb2ludCBhcnJheXMgY29udGFpbmluZyB0aGUgY29vcmRpbmF0ZXMgb2YgZm91bmQgYmFyY29kZXNcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBkZXRlY3QobXVsdGlwbGUsIGJpdE1hdHJpeCkge1xuICAgICAgICAgICAgY29uc3QgYmFyY29kZUNvb3JkaW5hdGVzID0gbmV3IEFycmF5KCk7XG4gICAgICAgICAgICBsZXQgcm93ID0gMDtcbiAgICAgICAgICAgIGxldCBjb2x1bW4gPSAwO1xuICAgICAgICAgICAgbGV0IGZvdW5kQmFyY29kZUluUm93ID0gZmFsc2U7XG4gICAgICAgICAgICB3aGlsZSAocm93IDwgYml0TWF0cml4LmdldEhlaWdodCgpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdmVydGljZXMgPSBEZXRlY3RvciQzLmZpbmRWZXJ0aWNlcyhiaXRNYXRyaXgsIHJvdywgY29sdW1uKTtcbiAgICAgICAgICAgICAgICBpZiAodmVydGljZXNbMF0gPT0gbnVsbCAmJiB2ZXJ0aWNlc1szXSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZm91bmRCYXJjb2RlSW5Sb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdlIGRpZG4ndCBmaW5kIGFueSBiYXJjb2RlIHNvIHRoYXQncyB0aGUgZW5kIG9mIHNlYXJjaGluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gd2UgZGlkbid0IGZpbmQgYSBiYXJjb2RlIHN0YXJ0aW5nIGF0IHRoZSBnaXZlbiBjb2x1bW4gYW5kIHJvdy4gVHJ5IGFnYWluIGZyb20gdGhlIGZpcnN0IGNvbHVtbiBhbmQgc2xpZ2h0bHlcbiAgICAgICAgICAgICAgICAgICAgLy8gYmVsb3cgdGhlIGxvd2VzdCBiYXJjb2RlIHdlIGZvdW5kIHNvIGZhci5cbiAgICAgICAgICAgICAgICAgICAgZm91bmRCYXJjb2RlSW5Sb3cgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uID0gMDtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBiYXJjb2RlQ29vcmRpbmF0ZSBvZiBiYXJjb2RlQ29vcmRpbmF0ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiYXJjb2RlQ29vcmRpbmF0ZVsxXSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93ID0gTWF0aC50cnVuYyhNYXRoLm1heChyb3csIGJhcmNvZGVDb29yZGluYXRlWzFdLmdldFkoKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJhcmNvZGVDb29yZGluYXRlWzNdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cgPSBNYXRoLm1heChyb3csIE1hdGgudHJ1bmMoYmFyY29kZUNvb3JkaW5hdGVbM10uZ2V0WSgpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcm93ICs9IERldGVjdG9yJDMuUk9XX1NURVA7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3VuZEJhcmNvZGVJblJvdyA9IHRydWU7XG4gICAgICAgICAgICAgICAgYmFyY29kZUNvb3JkaW5hdGVzLnB1c2godmVydGljZXMpO1xuICAgICAgICAgICAgICAgIGlmICghbXVsdGlwbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGlmIHdlIGRpZG4ndCBmaW5kIGEgcmlnaHQgcm93IGluZGljYXRvciBjb2x1bW4sIHRoZW4gY29udGludWUgdGhlIHNlYXJjaCBmb3IgdGhlIG5leHQgYmFyY29kZSBhZnRlciB0aGVcbiAgICAgICAgICAgICAgICAvLyBzdGFydCBwYXR0ZXJuIG9mIHRoZSBiYXJjb2RlIGp1c3QgZm91bmQuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnRpY2VzWzJdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uID0gTWF0aC50cnVuYyh2ZXJ0aWNlc1syXS5nZXRYKCkpO1xuICAgICAgICAgICAgICAgICAgICByb3cgPSBNYXRoLnRydW5jKHZlcnRpY2VzWzJdLmdldFkoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW4gPSBNYXRoLnRydW5jKHZlcnRpY2VzWzRdLmdldFgoKSk7XG4gICAgICAgICAgICAgICAgICAgIHJvdyA9IE1hdGgudHJ1bmModmVydGljZXNbNF0uZ2V0WSgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYmFyY29kZUNvb3JkaW5hdGVzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBMb2NhdGUgdGhlIHZlcnRpY2VzIGFuZCB0aGUgY29kZXdvcmRzIGFyZWEgb2YgYSBibGFjayBibG9iIHVzaW5nIHRoZSBTdGFydFxuICAgICAgICAgKiBhbmQgU3RvcCBwYXR0ZXJucyBhcyBsb2NhdG9ycy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIG1hdHJpeCB0aGUgc2Nhbm5lZCBiYXJjb2RlIGltYWdlLlxuICAgICAgICAgKiBAcmV0dXJuIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIHZlcnRpY2VzOlxuICAgICAgICAgKiAgICAgICAgICAgdmVydGljZXNbMF0geCwgeSB0b3AgbGVmdCBiYXJjb2RlXG4gICAgICAgICAqICAgICAgICAgICB2ZXJ0aWNlc1sxXSB4LCB5IGJvdHRvbSBsZWZ0IGJhcmNvZGVcbiAgICAgICAgICogICAgICAgICAgIHZlcnRpY2VzWzJdIHgsIHkgdG9wIHJpZ2h0IGJhcmNvZGVcbiAgICAgICAgICogICAgICAgICAgIHZlcnRpY2VzWzNdIHgsIHkgYm90dG9tIHJpZ2h0IGJhcmNvZGVcbiAgICAgICAgICogICAgICAgICAgIHZlcnRpY2VzWzRdIHgsIHkgdG9wIGxlZnQgY29kZXdvcmQgYXJlYVxuICAgICAgICAgKiAgICAgICAgICAgdmVydGljZXNbNV0geCwgeSBib3R0b20gbGVmdCBjb2Rld29yZCBhcmVhXG4gICAgICAgICAqICAgICAgICAgICB2ZXJ0aWNlc1s2XSB4LCB5IHRvcCByaWdodCBjb2Rld29yZCBhcmVhXG4gICAgICAgICAqICAgICAgICAgICB2ZXJ0aWNlc1s3XSB4LCB5IGJvdHRvbSByaWdodCBjb2Rld29yZCBhcmVhXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZmluZFZlcnRpY2VzKG1hdHJpeCwgc3RhcnRSb3csIHN0YXJ0Q29sdW1uKSB7XG4gICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBtYXRyaXguZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IG1hdHJpeC5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgLy8gY29uc3QgcmVzdWx0ID0gbmV3IFJlc3VsdFBvaW50WzhdO1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IEFycmF5KDgpO1xuICAgICAgICAgICAgRGV0ZWN0b3IkMy5jb3B5VG9SZXN1bHQocmVzdWx0LCBEZXRlY3RvciQzLmZpbmRSb3dzV2l0aFBhdHRlcm4obWF0cml4LCBoZWlnaHQsIHdpZHRoLCBzdGFydFJvdywgc3RhcnRDb2x1bW4sIERldGVjdG9yJDMuU1RBUlRfUEFUVEVSTiksIERldGVjdG9yJDMuSU5ERVhFU19TVEFSVF9QQVRURVJOKTtcbiAgICAgICAgICAgIGlmIChyZXN1bHRbNF0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHN0YXJ0Q29sdW1uID0gTWF0aC50cnVuYyhyZXN1bHRbNF0uZ2V0WCgpKTtcbiAgICAgICAgICAgICAgICBzdGFydFJvdyA9IE1hdGgudHJ1bmMocmVzdWx0WzRdLmdldFkoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBEZXRlY3RvciQzLmNvcHlUb1Jlc3VsdChyZXN1bHQsIERldGVjdG9yJDMuZmluZFJvd3NXaXRoUGF0dGVybihtYXRyaXgsIGhlaWdodCwgd2lkdGgsIHN0YXJ0Um93LCBzdGFydENvbHVtbiwgRGV0ZWN0b3IkMy5TVE9QX1BBVFRFUk4pLCBEZXRlY3RvciQzLklOREVYRVNfU1RPUF9QQVRURVJOKTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGNvcHlUb1Jlc3VsdChyZXN1bHQsIHRtcFJlc3VsdCwgZGVzdGluYXRpb25JbmRleGVzKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRlc3RpbmF0aW9uSW5kZXhlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHJlc3VsdFtkZXN0aW5hdGlvbkluZGV4ZXNbaV1dID0gdG1wUmVzdWx0W2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBmaW5kUm93c1dpdGhQYXR0ZXJuKG1hdHJpeCwgaGVpZ2h0LCB3aWR0aCwgc3RhcnRSb3csIHN0YXJ0Q29sdW1uLCBwYXR0ZXJuKSB7XG4gICAgICAgICAgICAvLyBjb25zdCByZXN1bHQgPSBuZXcgUmVzdWx0UG9pbnRbNF07XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgQXJyYXkoNCk7XG4gICAgICAgICAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICAgICAgICAgIGNvbnN0IGNvdW50ZXJzID0gbmV3IEludDMyQXJyYXkocGF0dGVybi5sZW5ndGgpO1xuICAgICAgICAgICAgZm9yICg7IHN0YXJ0Um93IDwgaGVpZ2h0OyBzdGFydFJvdyArPSBEZXRlY3RvciQzLlJPV19TVEVQKSB7XG4gICAgICAgICAgICAgICAgbGV0IGxvYyA9IERldGVjdG9yJDMuZmluZEd1YXJkUGF0dGVybihtYXRyaXgsIHN0YXJ0Q29sdW1uLCBzdGFydFJvdywgd2lkdGgsIGZhbHNlLCBwYXR0ZXJuLCBjb3VudGVycyk7XG4gICAgICAgICAgICAgICAgaWYgKGxvYyAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzdGFydFJvdyA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHByZXZpb3VzUm93TG9jID0gRGV0ZWN0b3IkMy5maW5kR3VhcmRQYXR0ZXJuKG1hdHJpeCwgc3RhcnRDb2x1bW4sIC0tc3RhcnRSb3csIHdpZHRoLCBmYWxzZSwgcGF0dGVybiwgY291bnRlcnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzUm93TG9jICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2MgPSBwcmV2aW91c1Jvd0xvYztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0Um93Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0WzBdID0gbmV3IFJlc3VsdFBvaW50KGxvY1swXSwgc3RhcnRSb3cpO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRbMV0gPSBuZXcgUmVzdWx0UG9pbnQobG9jWzFdLCBzdGFydFJvdyk7XG4gICAgICAgICAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHN0b3BSb3cgPSBzdGFydFJvdyArIDE7XG4gICAgICAgICAgICAvLyBMYXN0IHJvdyBvZiB0aGUgY3VycmVudCBzeW1ib2wgdGhhdCBjb250YWlucyBwYXR0ZXJuXG4gICAgICAgICAgICBpZiAoZm91bmQpIHtcbiAgICAgICAgICAgICAgICBsZXQgc2tpcHBlZFJvd0NvdW50ID0gMDtcbiAgICAgICAgICAgICAgICBsZXQgcHJldmlvdXNSb3dMb2MgPSBJbnQzMkFycmF5LmZyb20oW01hdGgudHJ1bmMocmVzdWx0WzBdLmdldFgoKSksIE1hdGgudHJ1bmMocmVzdWx0WzFdLmdldFgoKSldKTtcbiAgICAgICAgICAgICAgICBmb3IgKDsgc3RvcFJvdyA8IGhlaWdodDsgc3RvcFJvdysrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvYyA9IERldGVjdG9yJDMuZmluZEd1YXJkUGF0dGVybihtYXRyaXgsIHByZXZpb3VzUm93TG9jWzBdLCBzdG9wUm93LCB3aWR0aCwgZmFsc2UsIHBhdHRlcm4sIGNvdW50ZXJzKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gYSBmb3VuZCBwYXR0ZXJuIGlzIG9ubHkgY29uc2lkZXJlZCB0byBiZWxvbmcgdG8gdGhlIHNhbWUgYmFyY29kZSBpZiB0aGUgc3RhcnQgYW5kIGVuZCBwb3NpdGlvbnNcbiAgICAgICAgICAgICAgICAgICAgLy8gZG9uJ3QgZGlmZmVyIHRvbyBtdWNoLiBQYXR0ZXJuIGRyaWZ0IHNob3VsZCBiZSBub3QgYmlnZ2VyIHRoYW4gdHdvIGZvciBjb25zZWN1dGl2ZSByb3dzLiBXaXRoXG4gICAgICAgICAgICAgICAgICAgIC8vIGEgaGlnaGVyIG51bWJlciBvZiBza2lwcGVkIHJvd3MgZHJpZnQgY291bGQgYmUgbGFyZ2VyLiBUbyBrZWVwIGl0IHNpbXBsZSBmb3Igbm93LCB3ZSBhbGxvdyBhIHNsaWdodGx5XG4gICAgICAgICAgICAgICAgICAgIC8vIGxhcmdlciBkcmlmdCBhbmQgZG9uJ3QgY2hlY2sgZm9yIHNraXBwZWQgcm93cy5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxvYyAhPSBudWxsICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBNYXRoLmFicyhwcmV2aW91c1Jvd0xvY1swXSAtIGxvY1swXSkgPCBEZXRlY3RvciQzLk1BWF9QQVRURVJOX0RSSUZUICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBNYXRoLmFicyhwcmV2aW91c1Jvd0xvY1sxXSAtIGxvY1sxXSkgPCBEZXRlY3RvciQzLk1BWF9QQVRURVJOX0RSSUZUKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1Jvd0xvYyA9IGxvYztcbiAgICAgICAgICAgICAgICAgICAgICAgIHNraXBwZWRSb3dDb3VudCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2tpcHBlZFJvd0NvdW50ID4gRGV0ZWN0b3IkMy5TS0lQUEVEX1JPV19DT1VOVF9NQVgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNraXBwZWRSb3dDb3VudCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN0b3BSb3cgLT0gc2tpcHBlZFJvd0NvdW50ICsgMTtcbiAgICAgICAgICAgICAgICByZXN1bHRbMl0gPSBuZXcgUmVzdWx0UG9pbnQocHJldmlvdXNSb3dMb2NbMF0sIHN0b3BSb3cpO1xuICAgICAgICAgICAgICAgIHJlc3VsdFszXSA9IG5ldyBSZXN1bHRQb2ludChwcmV2aW91c1Jvd0xvY1sxXSwgc3RvcFJvdyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RvcFJvdyAtIHN0YXJ0Um93IDwgRGV0ZWN0b3IkMy5CQVJDT0RFX01JTl9IRUlHSFQpIHtcbiAgICAgICAgICAgICAgICBBcnJheXMuZmlsbChyZXN1bHQsIG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIG1hdHJpeCByb3cgb2YgYmxhY2svd2hpdGUgdmFsdWVzIHRvIHNlYXJjaFxuICAgICAgICAgKiBAcGFyYW0gY29sdW1uIHggcG9zaXRpb24gdG8gc3RhcnQgc2VhcmNoXG4gICAgICAgICAqIEBwYXJhbSByb3cgeSBwb3NpdGlvbiB0byBzdGFydCBzZWFyY2hcbiAgICAgICAgICogQHBhcmFtIHdpZHRoIHRoZSBudW1iZXIgb2YgcGl4ZWxzIHRvIHNlYXJjaCBvbiB0aGlzIHJvd1xuICAgICAgICAgKiBAcGFyYW0gcGF0dGVybiBwYXR0ZXJuIG9mIGNvdW50cyBvZiBudW1iZXIgb2YgYmxhY2sgYW5kIHdoaXRlIHBpeGVscyB0aGF0IGFyZVxuICAgICAgICAgKiAgICAgICAgICAgICAgICAgYmVpbmcgc2VhcmNoZWQgZm9yIGFzIGEgcGF0dGVyblxuICAgICAgICAgKiBAcGFyYW0gY291bnRlcnMgYXJyYXkgb2YgY291bnRlcnMsIGFzIGxvbmcgYXMgcGF0dGVybiwgdG8gcmUtdXNlXG4gICAgICAgICAqIEByZXR1cm4gc3RhcnQvZW5kIGhvcml6b250YWwgb2Zmc2V0IG9mIGd1YXJkIHBhdHRlcm4sIGFzIGFuIGFycmF5IG9mIHR3byBpbnRzLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGZpbmRHdWFyZFBhdHRlcm4obWF0cml4LCBjb2x1bW4sIHJvdywgd2lkdGgsIHdoaXRlRmlyc3QsIHBhdHRlcm4sIGNvdW50ZXJzKSB7XG4gICAgICAgICAgICBBcnJheXMuZmlsbFdpdGhpbihjb3VudGVycywgMCwgY291bnRlcnMubGVuZ3RoLCAwKTtcbiAgICAgICAgICAgIGxldCBwYXR0ZXJuU3RhcnQgPSBjb2x1bW47XG4gICAgICAgICAgICBsZXQgcGl4ZWxEcmlmdCA9IDA7XG4gICAgICAgICAgICAvLyBpZiB0aGVyZSBhcmUgYmxhY2sgcGl4ZWxzIGxlZnQgb2YgdGhlIGN1cnJlbnQgcGl4ZWwgc2hpZnQgdG8gdGhlIGxlZnQsIGJ1dCBvbmx5IGZvciBNQVhfUElYRUxfRFJJRlQgcGl4ZWxzXG4gICAgICAgICAgICB3aGlsZSAobWF0cml4LmdldChwYXR0ZXJuU3RhcnQsIHJvdykgJiYgcGF0dGVyblN0YXJ0ID4gMCAmJiBwaXhlbERyaWZ0KysgPCBEZXRlY3RvciQzLk1BWF9QSVhFTF9EUklGVCkge1xuICAgICAgICAgICAgICAgIHBhdHRlcm5TdGFydC0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHggPSBwYXR0ZXJuU3RhcnQ7XG4gICAgICAgICAgICBsZXQgY291bnRlclBvc2l0aW9uID0gMDtcbiAgICAgICAgICAgIGxldCBwYXR0ZXJuTGVuZ3RoID0gcGF0dGVybi5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGxldCBpc1doaXRlID0gd2hpdGVGaXJzdDsgeCA8IHdpZHRoOyB4KyspIHtcbiAgICAgICAgICAgICAgICBsZXQgcGl4ZWwgPSBtYXRyaXguZ2V0KHgsIHJvdyk7XG4gICAgICAgICAgICAgICAgaWYgKHBpeGVsICE9PSBpc1doaXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvdW50ZXJzW2NvdW50ZXJQb3NpdGlvbl0rKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb3VudGVyUG9zaXRpb24gPT09IHBhdHRlcm5MZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoRGV0ZWN0b3IkMy5wYXR0ZXJuTWF0Y2hWYXJpYW5jZShjb3VudGVycywgcGF0dGVybiwgRGV0ZWN0b3IkMy5NQVhfSU5ESVZJRFVBTF9WQVJJQU5DRSkgPCBEZXRlY3RvciQzLk1BWF9BVkdfVkFSSUFOQ0UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEludDMyQXJyYXkoW3BhdHRlcm5TdGFydCwgeF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVyblN0YXJ0ICs9IGNvdW50ZXJzWzBdICsgY291bnRlcnNbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KGNvdW50ZXJzLCAyLCBjb3VudGVycywgMCwgY291bnRlclBvc2l0aW9uIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb24gLSAxXSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyc1tjb3VudGVyUG9zaXRpb25dID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ZXJQb3NpdGlvbi0tO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnRlclBvc2l0aW9uKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY291bnRlcnNbY291bnRlclBvc2l0aW9uXSA9IDE7XG4gICAgICAgICAgICAgICAgICAgIGlzV2hpdGUgPSAhaXNXaGl0ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY291bnRlclBvc2l0aW9uID09PSBwYXR0ZXJuTGVuZ3RoIC0gMSAmJlxuICAgICAgICAgICAgICAgIERldGVjdG9yJDMucGF0dGVybk1hdGNoVmFyaWFuY2UoY291bnRlcnMsIHBhdHRlcm4sIERldGVjdG9yJDMuTUFYX0lORElWSURVQUxfVkFSSUFOQ0UpIDwgRGV0ZWN0b3IkMy5NQVhfQVZHX1ZBUklBTkNFKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBJbnQzMkFycmF5KFtwYXR0ZXJuU3RhcnQsIHggLSAxXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGV0ZXJtaW5lcyBob3cgY2xvc2VseSBhIHNldCBvZiBvYnNlcnZlZCBjb3VudHMgb2YgcnVucyBvZiBibGFjay93aGl0ZVxuICAgICAgICAgKiB2YWx1ZXMgbWF0Y2hlcyBhIGdpdmVuIHRhcmdldCBwYXR0ZXJuLiBUaGlzIGlzIHJlcG9ydGVkIGFzIHRoZSByYXRpbyBvZlxuICAgICAgICAgKiB0aGUgdG90YWwgdmFyaWFuY2UgZnJvbSB0aGUgZXhwZWN0ZWQgcGF0dGVybiBwcm9wb3J0aW9ucyBhY3Jvc3MgYWxsXG4gICAgICAgICAqIHBhdHRlcm4gZWxlbWVudHMsIHRvIHRoZSBsZW5ndGggb2YgdGhlIHBhdHRlcm4uXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBjb3VudGVycyBvYnNlcnZlZCBjb3VudGVyc1xuICAgICAgICAgKiBAcGFyYW0gcGF0dGVybiBleHBlY3RlZCBwYXR0ZXJuXG4gICAgICAgICAqIEBwYXJhbSBtYXhJbmRpdmlkdWFsVmFyaWFuY2UgVGhlIG1vc3QgYW55IGNvdW50ZXIgY2FuIGRpZmZlciBiZWZvcmUgd2UgZ2l2ZSB1cFxuICAgICAgICAgKiBAcmV0dXJuIHJhdGlvIG9mIHRvdGFsIHZhcmlhbmNlIGJldHdlZW4gY291bnRlcnMgYW5kIHBhdHRlcm4gY29tcGFyZWQgdG8gdG90YWwgcGF0dGVybiBzaXplXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgcGF0dGVybk1hdGNoVmFyaWFuY2UoY291bnRlcnMsIHBhdHRlcm4sIG1heEluZGl2aWR1YWxWYXJpYW5jZSkge1xuICAgICAgICAgICAgbGV0IG51bUNvdW50ZXJzID0gY291bnRlcnMubGVuZ3RoO1xuICAgICAgICAgICAgbGV0IHRvdGFsID0gMDtcbiAgICAgICAgICAgIGxldCBwYXR0ZXJuTGVuZ3RoID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtQ291bnRlcnM7IGkrKykge1xuICAgICAgICAgICAgICAgIHRvdGFsICs9IGNvdW50ZXJzW2ldO1xuICAgICAgICAgICAgICAgIHBhdHRlcm5MZW5ndGggKz0gcGF0dGVybltpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0b3RhbCA8IHBhdHRlcm5MZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB3ZSBkb24ndCBldmVuIGhhdmUgb25lIHBpeGVsIHBlciB1bml0IG9mIGJhciB3aWR0aCwgYXNzdW1lIHRoaXNcbiAgICAgICAgICAgICAgICAvLyBpcyB0b28gc21hbGwgdG8gcmVsaWFibHkgbWF0Y2gsIHNvIGZhaWw6XG4gICAgICAgICAgICAgICAgcmV0dXJuIC8qRmxvYXQuUE9TSVRJVkVfSU5GSU5JVFkqLyBJbmZpbml0eTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFdlJ3JlIGdvaW5nIHRvIGZha2UgZmxvYXRpbmctcG9pbnQgbWF0aCBpbiBpbnRlZ2Vycy4gV2UganVzdCBuZWVkIHRvIHVzZSBtb3JlIGJpdHMuXG4gICAgICAgICAgICAvLyBTY2FsZSB1cCBwYXR0ZXJuTGVuZ3RoIHNvIHRoYXQgaW50ZXJtZWRpYXRlIHZhbHVlcyBiZWxvdyBsaWtlIHNjYWxlZENvdW50ZXIgd2lsbCBoYXZlXG4gICAgICAgICAgICAvLyBtb3JlIFwic2lnbmlmaWNhbnQgZGlnaXRzXCIuXG4gICAgICAgICAgICBsZXQgdW5pdEJhcldpZHRoID0gdG90YWwgLyBwYXR0ZXJuTGVuZ3RoO1xuICAgICAgICAgICAgbWF4SW5kaXZpZHVhbFZhcmlhbmNlICo9IHVuaXRCYXJXaWR0aDtcbiAgICAgICAgICAgIGxldCB0b3RhbFZhcmlhbmNlID0gMC4wO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCBudW1Db3VudGVyczsgeCsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IGNvdW50ZXIgPSBjb3VudGVyc1t4XTtcbiAgICAgICAgICAgICAgICBsZXQgc2NhbGVkUGF0dGVybiA9IHBhdHRlcm5beF0gKiB1bml0QmFyV2lkdGg7XG4gICAgICAgICAgICAgICAgbGV0IHZhcmlhbmNlID0gY291bnRlciA+IHNjYWxlZFBhdHRlcm4gPyBjb3VudGVyIC0gc2NhbGVkUGF0dGVybiA6IHNjYWxlZFBhdHRlcm4gLSBjb3VudGVyO1xuICAgICAgICAgICAgICAgIGlmICh2YXJpYW5jZSA+IG1heEluZGl2aWR1YWxWYXJpYW5jZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gLypGbG9hdC5QT1NJVElWRV9JTkZJTklUWSovIEluZmluaXR5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0b3RhbFZhcmlhbmNlICs9IHZhcmlhbmNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRvdGFsVmFyaWFuY2UgLyB0b3RhbDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBEZXRlY3RvciQzLklOREVYRVNfU1RBUlRfUEFUVEVSTiA9IEludDMyQXJyYXkuZnJvbShbMCwgNCwgMSwgNV0pO1xuICAgIERldGVjdG9yJDMuSU5ERVhFU19TVE9QX1BBVFRFUk4gPSBJbnQzMkFycmF5LmZyb20oWzYsIDIsIDcsIDNdKTtcbiAgICBEZXRlY3RvciQzLk1BWF9BVkdfVkFSSUFOQ0UgPSAwLjQyO1xuICAgIERldGVjdG9yJDMuTUFYX0lORElWSURVQUxfVkFSSUFOQ0UgPSAwLjg7XG4gICAgLy8gQiBTIEIgUyBCIFMgQiBTIEJhci9TcGFjZSBwYXR0ZXJuXG4gICAgLy8gMTExMTExMTEgMCAxIDAgMSAwIDEgMDAwXG4gICAgRGV0ZWN0b3IkMy5TVEFSVF9QQVRURVJOID0gSW50MzJBcnJheS5mcm9tKFs4LCAxLCAxLCAxLCAxLCAxLCAxLCAzXSk7XG4gICAgLy8gMTExMTExMSAwIDEgMDAwIDEgMCAxIDAwIDFcbiAgICBEZXRlY3RvciQzLlNUT1BfUEFUVEVSTiA9IEludDMyQXJyYXkuZnJvbShbNywgMSwgMSwgMywgMSwgMSwgMSwgMiwgMV0pO1xuICAgIERldGVjdG9yJDMuTUFYX1BJWEVMX0RSSUZUID0gMztcbiAgICBEZXRlY3RvciQzLk1BWF9QQVRURVJOX0RSSUZUID0gNTtcbiAgICAvLyBpZiB3ZSBzZXQgdGhlIHZhbHVlIHRvbyBsb3csIHRoZW4gd2UgZG9uJ3QgZGV0ZWN0IHRoZSBjb3JyZWN0IGhlaWdodCBvZiB0aGUgYmFyIGlmIHRoZSBzdGFydCBwYXR0ZXJucyBhcmUgZGFtYWdlZC5cbiAgICAvLyBpZiB3ZSBzZXQgdGhlIHZhbHVlIHRvbyBoaWdoLCB0aGVuIHdlIG1pZ2h0IGRldGVjdCB0aGUgc3RhcnQgcGF0dGVybiBmcm9tIGEgbmVpZ2hib3IgYmFyY29kZS5cbiAgICBEZXRlY3RvciQzLlNLSVBQRURfUk9XX0NPVU5UX01BWCA9IDI1O1xuICAgIC8vIEEgUERGNDcxIGJhcmNvZGUgc2hvdWxkIGhhdmUgYXQgbGVhc3QgMyByb3dzLCB3aXRoIGVhY2ggcm93IGJlaW5nID49IDMgdGltZXMgdGhlIG1vZHVsZSB3aWR0aC4gVGhlcmVmb3JlIGl0IHNob3VsZCBiZSBhdCBsZWFzdFxuICAgIC8vIDkgcGl4ZWxzIHRhbGwuIFRvIGJlIGNvbnNlcnZhdGl2ZSwgd2UgdXNlIGFib3V0IGhhbGYgdGhlIHNpemUgdG8gZW5zdXJlIHdlIGRvbid0IG1pc3MgaXQuXG4gICAgRGV0ZWN0b3IkMy5ST1dfU1RFUCA9IDU7XG4gICAgRGV0ZWN0b3IkMy5CQVJDT0RFX01JTl9IRUlHSFQgPSAxMDtcblxuICAgIC8qXG4gICAgKiBDb3B5cmlnaHQgMjAxMiBaWGluZyBhdXRob3JzXG4gICAgKlxuICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICpcbiAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgKlxuICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAqL1xuICAgIC8qKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICogQHNlZSBjb20uZ29vZ2xlLnp4aW5nLmNvbW1vbi5yZWVkc29sb21vbi5HZW5lcmljR0ZQb2x5XG4gICAgICovXG4gICAgLypmaW5hbCovIGNsYXNzIE1vZHVsdXNQb2x5IHtcbiAgICAgICAgY29uc3RydWN0b3IoZmllbGQsIGNvZWZmaWNpZW50cykge1xuICAgICAgICAgICAgaWYgKGNvZWZmaWNpZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmZpZWxkID0gZmllbGQ7XG4gICAgICAgICAgICBsZXQgY29lZmZpY2llbnRzTGVuZ3RoID0gLyppbnQqLyBjb2VmZmljaWVudHMubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKGNvZWZmaWNpZW50c0xlbmd0aCA+IDEgJiYgY29lZmZpY2llbnRzWzBdID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gTGVhZGluZyB0ZXJtIG11c3QgYmUgbm9uLXplcm8gZm9yIGFueXRoaW5nIGV4Y2VwdCB0aGUgY29uc3RhbnQgcG9seW5vbWlhbCBcIjBcIlxuICAgICAgICAgICAgICAgIGxldCBmaXJzdE5vblplcm8gPSAvKmludCovIDE7XG4gICAgICAgICAgICAgICAgd2hpbGUgKGZpcnN0Tm9uWmVybyA8IGNvZWZmaWNpZW50c0xlbmd0aCAmJiBjb2VmZmljaWVudHNbZmlyc3ROb25aZXJvXSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBmaXJzdE5vblplcm8rKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGZpcnN0Tm9uWmVybyA9PT0gY29lZmZpY2llbnRzTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29lZmZpY2llbnRzID0gbmV3IEludDMyQXJyYXkoWzBdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29lZmZpY2llbnRzID0gbmV3IEludDMyQXJyYXkoY29lZmZpY2llbnRzTGVuZ3RoIC0gZmlyc3ROb25aZXJvKTtcbiAgICAgICAgICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weShjb2VmZmljaWVudHMsIGZpcnN0Tm9uWmVybywgdGhpcy5jb2VmZmljaWVudHMsIDAsIHRoaXMuY29lZmZpY2llbnRzLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb2VmZmljaWVudHMgPSBjb2VmZmljaWVudHM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Q29lZmZpY2llbnRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29lZmZpY2llbnRzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIGRlZ3JlZSBvZiB0aGlzIHBvbHlub21pYWxcbiAgICAgICAgICovXG4gICAgICAgIGdldERlZ3JlZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvZWZmaWNpZW50cy5sZW5ndGggLSAxO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHRydWUgaWZmIHRoaXMgcG9seW5vbWlhbCBpcyB0aGUgbW9ub21pYWwgXCIwXCJcbiAgICAgICAgICovXG4gICAgICAgIGlzWmVybygpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvZWZmaWNpZW50c1swXSA9PT0gMDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiBjb2VmZmljaWVudCBvZiB4XmRlZ3JlZSB0ZXJtIGluIHRoaXMgcG9seW5vbWlhbFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0Q29lZmZpY2llbnQoZGVncmVlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2VmZmljaWVudHNbdGhpcy5jb2VmZmljaWVudHMubGVuZ3RoIC0gMSAtIGRlZ3JlZV07XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gZXZhbHVhdGlvbiBvZiB0aGlzIHBvbHlub21pYWwgYXQgYSBnaXZlbiBwb2ludFxuICAgICAgICAgKi9cbiAgICAgICAgZXZhbHVhdGVBdChhKSB7XG4gICAgICAgICAgICBpZiAoYSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIC8vIEp1c3QgcmV0dXJuIHRoZSB4XjAgY29lZmZpY2llbnRcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRDb2VmZmljaWVudCgwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChhID09PSAxKSB7XG4gICAgICAgICAgICAgICAgLy8gSnVzdCB0aGUgc3VtIG9mIHRoZSBjb2VmZmljaWVudHNcbiAgICAgICAgICAgICAgICBsZXQgc3VtID0gLyppbnQqLyAwO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGNvZWZmaWNpZW50IC8qaW50Ki8gb2YgdGhpcy5jb2VmZmljaWVudHMpIHtcbiAgICAgICAgICAgICAgICAgICAgc3VtID0gdGhpcy5maWVsZC5hZGQoc3VtLCBjb2VmZmljaWVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBzdW07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gLyppbnQqLyB0aGlzLmNvZWZmaWNpZW50c1swXTtcbiAgICAgICAgICAgIGxldCBzaXplID0gLyppbnQqLyB0aGlzLmNvZWZmaWNpZW50cy5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAxOyBpIDwgc2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy5maWVsZC5hZGQodGhpcy5maWVsZC5tdWx0aXBseShhLCByZXN1bHQpLCB0aGlzLmNvZWZmaWNpZW50c1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIGFkZChvdGhlcikge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmZpZWxkLmVxdWFscyhvdGhlci5maWVsZCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdNb2R1bHVzUG9seXMgZG8gbm90IGhhdmUgc2FtZSBNb2R1bHVzR0YgZmllbGQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmlzWmVybygpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG90aGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG90aGVyLmlzWmVybygpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc21hbGxlckNvZWZmaWNpZW50cyA9IHRoaXMuY29lZmZpY2llbnRzO1xuICAgICAgICAgICAgbGV0IGxhcmdlckNvZWZmaWNpZW50cyA9IG90aGVyLmNvZWZmaWNpZW50cztcbiAgICAgICAgICAgIGlmIChzbWFsbGVyQ29lZmZpY2llbnRzLmxlbmd0aCA+IGxhcmdlckNvZWZmaWNpZW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBsZXQgdGVtcCA9IHNtYWxsZXJDb2VmZmljaWVudHM7XG4gICAgICAgICAgICAgICAgc21hbGxlckNvZWZmaWNpZW50cyA9IGxhcmdlckNvZWZmaWNpZW50cztcbiAgICAgICAgICAgICAgICBsYXJnZXJDb2VmZmljaWVudHMgPSB0ZW1wO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHN1bURpZmYgPSBuZXcgSW50MzJBcnJheShsYXJnZXJDb2VmZmljaWVudHMubGVuZ3RoKTtcbiAgICAgICAgICAgIGxldCBsZW5ndGhEaWZmID0gLyppbnQqLyBsYXJnZXJDb2VmZmljaWVudHMubGVuZ3RoIC0gc21hbGxlckNvZWZmaWNpZW50cy5sZW5ndGg7XG4gICAgICAgICAgICAvLyBDb3B5IGhpZ2gtb3JkZXIgdGVybXMgb25seSBmb3VuZCBpbiBoaWdoZXItZGVncmVlIHBvbHlub21pYWwncyBjb2VmZmljaWVudHNcbiAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkobGFyZ2VyQ29lZmZpY2llbnRzLCAwLCBzdW1EaWZmLCAwLCBsZW5ndGhEaWZmKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IGxlbmd0aERpZmY7IGkgPCBsYXJnZXJDb2VmZmljaWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBzdW1EaWZmW2ldID0gdGhpcy5maWVsZC5hZGQoc21hbGxlckNvZWZmaWNpZW50c1tpIC0gbGVuZ3RoRGlmZl0sIGxhcmdlckNvZWZmaWNpZW50c1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IE1vZHVsdXNQb2x5KHRoaXMuZmllbGQsIHN1bURpZmYpO1xuICAgICAgICB9XG4gICAgICAgIHN1YnRyYWN0KG90aGVyKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZmllbGQuZXF1YWxzKG90aGVyLmZpZWxkKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ01vZHVsdXNQb2x5cyBkbyBub3QgaGF2ZSBzYW1lIE1vZHVsdXNHRiBmaWVsZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG90aGVyLmlzWmVybygpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hZGQob3RoZXIubmVnYXRpdmUoKSk7XG4gICAgICAgIH1cbiAgICAgICAgbXVsdGlwbHkob3RoZXIpIHtcbiAgICAgICAgICAgIGlmIChvdGhlciBpbnN0YW5jZW9mIE1vZHVsdXNQb2x5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubXVsdGlwbHlPdGhlcihvdGhlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tdWx0aXBseVNjYWxhcihvdGhlcik7XG4gICAgICAgIH1cbiAgICAgICAgbXVsdGlwbHlPdGhlcihvdGhlcikge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmZpZWxkLmVxdWFscyhvdGhlci5maWVsZCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdNb2R1bHVzUG9seXMgZG8gbm90IGhhdmUgc2FtZSBNb2R1bHVzR0YgZmllbGQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmlzWmVybygpIHx8IG90aGVyLmlzWmVybygpKSB7XG4gICAgICAgICAgICAgICAgLy8gcmV0dXJuIHRoaXMuZmllbGQuZ2V0WmVybygpO1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgTW9kdWx1c1BvbHkodGhpcy5maWVsZCwgbmV3IEludDMyQXJyYXkoWzBdKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgYUNvZWZmaWNpZW50cyA9IHRoaXMuY29lZmZpY2llbnRzO1xuICAgICAgICAgICAgbGV0IGFMZW5ndGggPSAvKmludCovIGFDb2VmZmljaWVudHMubGVuZ3RoO1xuICAgICAgICAgICAgbGV0IGJDb2VmZmljaWVudHMgPSBvdGhlci5jb2VmZmljaWVudHM7XG4gICAgICAgICAgICBsZXQgYkxlbmd0aCA9IC8qaW50Ki8gYkNvZWZmaWNpZW50cy5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgcHJvZHVjdCA9IG5ldyBJbnQzMkFycmF5KGFMZW5ndGggKyBiTGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAwOyBpIDwgYUxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IGFDb2VmZiA9IC8qaW50Ki8gYUNvZWZmaWNpZW50c1tpXTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqIC8qaW50Ki8gPSAwOyBqIDwgYkxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb2R1Y3RbaSArIGpdID0gdGhpcy5maWVsZC5hZGQocHJvZHVjdFtpICsgal0sIHRoaXMuZmllbGQubXVsdGlwbHkoYUNvZWZmLCBiQ29lZmZpY2llbnRzW2pdKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBNb2R1bHVzUG9seSh0aGlzLmZpZWxkLCBwcm9kdWN0KTtcbiAgICAgICAgfVxuICAgICAgICBuZWdhdGl2ZSgpIHtcbiAgICAgICAgICAgIGxldCBzaXplID0gLyppbnQqLyB0aGlzLmNvZWZmaWNpZW50cy5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgbmVnYXRpdmVDb2VmZmljaWVudHMgPSBuZXcgSW50MzJBcnJheShzaXplKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgICAgICAgICAgICBuZWdhdGl2ZUNvZWZmaWNpZW50c1tpXSA9IHRoaXMuZmllbGQuc3VidHJhY3QoMCwgdGhpcy5jb2VmZmljaWVudHNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBNb2R1bHVzUG9seSh0aGlzLmZpZWxkLCBuZWdhdGl2ZUNvZWZmaWNpZW50cyk7XG4gICAgICAgIH1cbiAgICAgICAgbXVsdGlwbHlTY2FsYXIoc2NhbGFyKSB7XG4gICAgICAgICAgICBpZiAoc2NhbGFyID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBNb2R1bHVzUG9seSh0aGlzLmZpZWxkLCBuZXcgSW50MzJBcnJheShbMF0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzY2FsYXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBzaXplID0gLyppbnQqLyB0aGlzLmNvZWZmaWNpZW50cy5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgcHJvZHVjdCA9IG5ldyBJbnQzMkFycmF5KHNpemUpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMDsgaSA8IHNpemU7IGkrKykge1xuICAgICAgICAgICAgICAgIHByb2R1Y3RbaV0gPSB0aGlzLmZpZWxkLm11bHRpcGx5KHRoaXMuY29lZmZpY2llbnRzW2ldLCBzY2FsYXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBNb2R1bHVzUG9seSh0aGlzLmZpZWxkLCBwcm9kdWN0KTtcbiAgICAgICAgfVxuICAgICAgICBtdWx0aXBseUJ5TW9ub21pYWwoZGVncmVlLCBjb2VmZmljaWVudCkge1xuICAgICAgICAgICAgaWYgKGRlZ3JlZSA8IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29lZmZpY2llbnQgPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IE1vZHVsdXNQb2x5KHRoaXMuZmllbGQsIG5ldyBJbnQzMkFycmF5KFswXSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHNpemUgPSAvKmludCovIHRoaXMuY29lZmZpY2llbnRzLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBwcm9kdWN0ID0gbmV3IEludDMyQXJyYXkoc2l6ZSArIGRlZ3JlZSk7XG4gICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAwOyBpIDwgc2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcHJvZHVjdFtpXSA9IHRoaXMuZmllbGQubXVsdGlwbHkodGhpcy5jb2VmZmljaWVudHNbaV0sIGNvZWZmaWNpZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgTW9kdWx1c1BvbHkodGhpcy5maWVsZCwgcHJvZHVjdCk7XG4gICAgICAgIH1cbiAgICAgICAgLypcbiAgICAgICAgTW9kdWx1c1BvbHlbXSBkaXZpZGUob3RoZXI6IE1vZHVsdXNQb2x5KSB7XG4gICAgICAgICAgaWYgKCFmaWVsZC5lcXVhbHMob3RoZXIuZmllbGQpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKFwiTW9kdWx1c1BvbHlzIGRvIG5vdCBoYXZlIHNhbWUgTW9kdWx1c0dGIGZpZWxkXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAob3RoZXIuaXNaZXJvKCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oXCJEaXZpZGUgYnkgMFwiKTtcbiAgICAgICAgICB9XG4gICAgICBcbiAgICAgICAgICBsZXQgcXVvdGllbnQ6IE1vZHVsdXNQb2x5ID0gZmllbGQuZ2V0WmVybygpO1xuICAgICAgICAgIGxldCByZW1haW5kZXI6IE1vZHVsdXNQb2x5ID0gdGhpcztcbiAgICAgIFxuICAgICAgICAgIGxldCBkZW5vbWluYXRvckxlYWRpbmdUZXJtOiAvKmludC8gbnVtYmVyID0gb3RoZXIuZ2V0Q29lZmZpY2llbnQob3RoZXIuZ2V0RGVncmVlKCkpO1xuICAgICAgICAgIGxldCBpbnZlcnNlRGVub21pbmF0b3JMZWFkaW5nVGVybTogLyppbnQvIG51bWJlciA9IGZpZWxkLmludmVyc2UoZGVub21pbmF0b3JMZWFkaW5nVGVybSk7XG4gICAgICBcbiAgICAgICAgICB3aGlsZSAocmVtYWluZGVyLmdldERlZ3JlZSgpID49IG90aGVyLmdldERlZ3JlZSgpICYmICFyZW1haW5kZXIuaXNaZXJvKCkpIHtcbiAgICAgICAgICAgIGxldCBkZWdyZWVEaWZmZXJlbmNlOiAvKmludC8gbnVtYmVyID0gcmVtYWluZGVyLmdldERlZ3JlZSgpIC0gb3RoZXIuZ2V0RGVncmVlKCk7XG4gICAgICAgICAgICBsZXQgc2NhbGU6IC8qaW50LyBudW1iZXIgPSBmaWVsZC5tdWx0aXBseShyZW1haW5kZXIuZ2V0Q29lZmZpY2llbnQocmVtYWluZGVyLmdldERlZ3JlZSgpKSwgaW52ZXJzZURlbm9taW5hdG9yTGVhZGluZ1Rlcm0pO1xuICAgICAgICAgICAgbGV0IHRlcm06IE1vZHVsdXNQb2x5ID0gb3RoZXIubXVsdGlwbHlCeU1vbm9taWFsKGRlZ3JlZURpZmZlcmVuY2UsIHNjYWxlKTtcbiAgICAgICAgICAgIGxldCBpdGVyYXRpb25RdW90aWVudDogTW9kdWx1c1BvbHkgPSBmaWVsZC5idWlsZE1vbm9taWFsKGRlZ3JlZURpZmZlcmVuY2UsIHNjYWxlKTtcbiAgICAgICAgICAgIHF1b3RpZW50ID0gcXVvdGllbnQuYWRkKGl0ZXJhdGlvblF1b3RpZW50KTtcbiAgICAgICAgICAgIHJlbWFpbmRlciA9IHJlbWFpbmRlci5zdWJ0cmFjdCh0ZXJtKTtcbiAgICAgICAgICB9XG4gICAgICBcbiAgICAgICAgICByZXR1cm4gbmV3IE1vZHVsdXNQb2x5W10geyBxdW90aWVudCwgcmVtYWluZGVyIH07XG4gICAgICAgIH1cbiAgICAgICAgKi9cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IG5ldyBTdHJpbmdCdWlsZGVyKCAvKjggKiB0aGlzLmdldERlZ3JlZSgpKi8pOyAvLyBkeW5hbWljIHN0cmluZyBzaXplIGluIEpTXG4gICAgICAgICAgICBmb3IgKGxldCBkZWdyZWUgLyppbnQqLyA9IHRoaXMuZ2V0RGVncmVlKCk7IGRlZ3JlZSA+PSAwOyBkZWdyZWUtLSkge1xuICAgICAgICAgICAgICAgIGxldCBjb2VmZmljaWVudCA9IC8qaW50Ki8gdGhpcy5nZXRDb2VmZmljaWVudChkZWdyZWUpO1xuICAgICAgICAgICAgICAgIGlmIChjb2VmZmljaWVudCAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29lZmZpY2llbnQgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCcgLSAnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZWZmaWNpZW50ID0gLWNvZWZmaWNpZW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdC5sZW5ndGgoKSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCcgKyAnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZGVncmVlID09PSAwIHx8IGNvZWZmaWNpZW50ICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKGNvZWZmaWNpZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZGVncmVlICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGVncmVlID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgneCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgneF4nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKGRlZ3JlZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0LnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjbGFzcyBNb2R1bHVzQmFzZSB7XG4gICAgICAgIGFkZChhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gKGEgKyBiKSAlIHRoaXMubW9kdWx1cztcbiAgICAgICAgfVxuICAgICAgICBzdWJ0cmFjdChhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gKHRoaXMubW9kdWx1cyArIGEgLSBiKSAlIHRoaXMubW9kdWx1cztcbiAgICAgICAgfVxuICAgICAgICBleHAoYSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXhwVGFibGVbYV07XG4gICAgICAgIH1cbiAgICAgICAgbG9nKGEpIHtcbiAgICAgICAgICAgIGlmIChhID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubG9nVGFibGVbYV07XG4gICAgICAgIH1cbiAgICAgICAgaW52ZXJzZShhKSB7XG4gICAgICAgICAgICBpZiAoYSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBBcml0aG1ldGljRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5leHBUYWJsZVt0aGlzLm1vZHVsdXMgLSB0aGlzLmxvZ1RhYmxlW2FdIC0gMV07XG4gICAgICAgIH1cbiAgICAgICAgbXVsdGlwbHkoYSwgYikge1xuICAgICAgICAgICAgaWYgKGEgPT09IDAgfHwgYiA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXhwVGFibGVbKHRoaXMubG9nVGFibGVbYV0gKyB0aGlzLmxvZ1RhYmxlW2JdKSAlICh0aGlzLm1vZHVsdXMgLSAxKV07XG4gICAgICAgIH1cbiAgICAgICAgZ2V0U2l6ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1vZHVsdXM7XG4gICAgICAgIH1cbiAgICAgICAgZXF1YWxzKG8pIHtcbiAgICAgICAgICAgIHJldHVybiBvID09PSB0aGlzO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAxMiBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiA8cD5BIGZpZWxkIGJhc2VkIG9uIHBvd2VycyBvZiBhIGdlbmVyYXRvciBpbnRlZ2VyLCBtb2R1bG8gc29tZSBtb2R1bHVzLjwvcD5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgU2VhbiBPd2VuXG4gICAgICogQHNlZSBjb20uZ29vZ2xlLnp4aW5nLmNvbW1vbi5yZWVkc29sb21vbi5HZW5lcmljR0ZcbiAgICAgKi9cbiAgICAvKnB1YmxpYyBmaW5hbCovIGNsYXNzIE1vZHVsdXNHRiBleHRlbmRzIE1vZHVsdXNCYXNlIHtcbiAgICAgICAgLy8gcHJpdmF0ZSAvKmZpbmFsKi8gbW9kdWx1czogLyppbnQqLyBudW1iZXI7XG4gICAgICAgIGNvbnN0cnVjdG9yKG1vZHVsdXMsIGdlbmVyYXRvcikge1xuICAgICAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgICAgIHRoaXMubW9kdWx1cyA9IG1vZHVsdXM7XG4gICAgICAgICAgICB0aGlzLmV4cFRhYmxlID0gbmV3IEludDMyQXJyYXkobW9kdWx1cyk7XG4gICAgICAgICAgICB0aGlzLmxvZ1RhYmxlID0gbmV3IEludDMyQXJyYXkobW9kdWx1cyk7XG4gICAgICAgICAgICBsZXQgeCA9IC8qaW50Ki8gMTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCBtb2R1bHVzOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLmV4cFRhYmxlW2ldID0geDtcbiAgICAgICAgICAgICAgICB4ID0gKHggKiBnZW5lcmF0b3IpICUgbW9kdWx1cztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCBtb2R1bHVzIC0gMTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2dUYWJsZVt0aGlzLmV4cFRhYmxlW2ldXSA9IGk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBsb2dUYWJsZVswXSA9PSAwIGJ1dCB0aGlzIHNob3VsZCBuZXZlciBiZSB1c2VkXG4gICAgICAgICAgICB0aGlzLnplcm8gPSBuZXcgTW9kdWx1c1BvbHkodGhpcywgbmV3IEludDMyQXJyYXkoWzBdKSk7XG4gICAgICAgICAgICB0aGlzLm9uZSA9IG5ldyBNb2R1bHVzUG9seSh0aGlzLCBuZXcgSW50MzJBcnJheShbMV0pKTtcbiAgICAgICAgfVxuICAgICAgICBnZXRaZXJvKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuemVybztcbiAgICAgICAgfVxuICAgICAgICBnZXRPbmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vbmU7XG4gICAgICAgIH1cbiAgICAgICAgYnVpbGRNb25vbWlhbChkZWdyZWUsIGNvZWZmaWNpZW50KSB7XG4gICAgICAgICAgICBpZiAoZGVncmVlIDwgMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjb2VmZmljaWVudCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnplcm87XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgY29lZmZpY2llbnRzID0gbmV3IEludDMyQXJyYXkoZGVncmVlICsgMSk7XG4gICAgICAgICAgICBjb2VmZmljaWVudHNbMF0gPSBjb2VmZmljaWVudDtcbiAgICAgICAgICAgIHJldHVybiBuZXcgTW9kdWx1c1BvbHkodGhpcywgY29lZmZpY2llbnRzKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBNb2R1bHVzR0YuUERGNDE3X0dGID0gbmV3IE1vZHVsdXNHRihQREY0MTdDb21tb24uTlVNQkVSX09GX0NPREVXT1JEUywgMyk7XG5cbiAgICAvKlxuICAgICogQ29weXJpZ2h0IDIwMTIgWlhpbmcgYXV0aG9yc1xuICAgICpcbiAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAqXG4gICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICpcbiAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgKi9cbiAgICAvKipcbiAgICAgKiA8cD5QREY0MTcgZXJyb3IgY29ycmVjdGlvbiBpbXBsZW1lbnRhdGlvbi48L3A+XG4gICAgICpcbiAgICAgKiA8cD5UaGlzIDxhIGhyZWY9XCJodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1JlZWQlRTIlODAlOTNTb2xvbW9uX2Vycm9yX2NvcnJlY3Rpb24jRXhhbXBsZVwiPmV4YW1wbGU8L2E+XG4gICAgICogaXMgcXVpdGUgdXNlZnVsIGluIHVuZGVyc3RhbmRpbmcgdGhlIGFsZ29yaXRobS48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNlYW4gT3dlblxuICAgICAqIEBzZWUgY29tLmdvb2dsZS56eGluZy5jb21tb24ucmVlZHNvbG9tb24uUmVlZFNvbG9tb25EZWNvZGVyXG4gICAgICovXG4gICAgLypwdWJsaWMgZmluYWwqLyBjbGFzcyBFcnJvckNvcnJlY3Rpb24ge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICAgIHRoaXMuZmllbGQgPSBNb2R1bHVzR0YuUERGNDE3X0dGO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gcmVjZWl2ZWQgcmVjZWl2ZWQgY29kZXdvcmRzXG4gICAgICAgICAqIEBwYXJhbSBudW1FQ0NvZGV3b3JkcyBudW1iZXIgb2YgdGhvc2UgY29kZXdvcmRzIHVzZWQgZm9yIEVDXG4gICAgICAgICAqIEBwYXJhbSBlcmFzdXJlcyBsb2NhdGlvbiBvZiBlcmFzdXJlc1xuICAgICAgICAgKiBAcmV0dXJuIG51bWJlciBvZiBlcnJvcnNcbiAgICAgICAgICogQHRocm93cyBDaGVja3N1bUV4Y2VwdGlvbiBpZiBlcnJvcnMgY2Fubm90IGJlIGNvcnJlY3RlZCwgbWF5YmUgYmVjYXVzZSBvZiB0b28gbWFueSBlcnJvcnNcbiAgICAgICAgICovXG4gICAgICAgIGRlY29kZShyZWNlaXZlZCwgbnVtRUNDb2Rld29yZHMsIGVyYXN1cmVzKSB7XG4gICAgICAgICAgICBsZXQgcG9seSA9IG5ldyBNb2R1bHVzUG9seSh0aGlzLmZpZWxkLCByZWNlaXZlZCk7XG4gICAgICAgICAgICBsZXQgUyA9IG5ldyBJbnQzMkFycmF5KG51bUVDQ29kZXdvcmRzKTtcbiAgICAgICAgICAgIGxldCBlcnJvciA9IGZhbHNlO1xuICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gbnVtRUNDb2Rld29yZHM7IGkgPiAwOyBpLS0pIHtcbiAgICAgICAgICAgICAgICBsZXQgZXZhbHVhdGlvbiA9IHBvbHkuZXZhbHVhdGVBdCh0aGlzLmZpZWxkLmV4cChpKSk7XG4gICAgICAgICAgICAgICAgU1tudW1FQ0NvZGV3b3JkcyAtIGldID0gZXZhbHVhdGlvbjtcbiAgICAgICAgICAgICAgICBpZiAoZXZhbHVhdGlvbiAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBlcnJvciA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFlcnJvcikge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGtub3duRXJyb3JzID0gdGhpcy5maWVsZC5nZXRPbmUoKTtcbiAgICAgICAgICAgIGlmIChlcmFzdXJlcyAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBlcmFzdXJlIG9mIGVyYXN1cmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBiID0gdGhpcy5maWVsZC5leHAocmVjZWl2ZWQubGVuZ3RoIC0gMSAtIGVyYXN1cmUpO1xuICAgICAgICAgICAgICAgICAgICAvLyBBZGQgKDEgLSBieCkgdGVybTpcbiAgICAgICAgICAgICAgICAgICAgbGV0IHRlcm0gPSBuZXcgTW9kdWx1c1BvbHkodGhpcy5maWVsZCwgbmV3IEludDMyQXJyYXkoW3RoaXMuZmllbGQuc3VidHJhY3QoMCwgYiksIDFdKSk7XG4gICAgICAgICAgICAgICAgICAgIGtub3duRXJyb3JzID0ga25vd25FcnJvcnMubXVsdGlwbHkodGVybSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHN5bmRyb21lID0gbmV3IE1vZHVsdXNQb2x5KHRoaXMuZmllbGQsIFMpO1xuICAgICAgICAgICAgLy8gc3luZHJvbWUgPSBzeW5kcm9tZS5tdWx0aXBseShrbm93bkVycm9ycyk7XG4gICAgICAgICAgICBsZXQgc2lnbWFPbWVnYSA9IHRoaXMucnVuRXVjbGlkZWFuQWxnb3JpdGhtKHRoaXMuZmllbGQuYnVpbGRNb25vbWlhbChudW1FQ0NvZGV3b3JkcywgMSksIHN5bmRyb21lLCBudW1FQ0NvZGV3b3Jkcyk7XG4gICAgICAgICAgICBsZXQgc2lnbWEgPSBzaWdtYU9tZWdhWzBdO1xuICAgICAgICAgICAgbGV0IG9tZWdhID0gc2lnbWFPbWVnYVsxXTtcbiAgICAgICAgICAgIC8vIHNpZ21hID0gc2lnbWEubXVsdGlwbHkoa25vd25FcnJvcnMpO1xuICAgICAgICAgICAgbGV0IGVycm9yTG9jYXRpb25zID0gdGhpcy5maW5kRXJyb3JMb2NhdGlvbnMoc2lnbWEpO1xuICAgICAgICAgICAgbGV0IGVycm9yTWFnbml0dWRlcyA9IHRoaXMuZmluZEVycm9yTWFnbml0dWRlcyhvbWVnYSwgc2lnbWEsIGVycm9yTG9jYXRpb25zKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCBlcnJvckxvY2F0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCBwb3NpdGlvbiA9IHJlY2VpdmVkLmxlbmd0aCAtIDEgLSB0aGlzLmZpZWxkLmxvZyhlcnJvckxvY2F0aW9uc1tpXSk7XG4gICAgICAgICAgICAgICAgaWYgKHBvc2l0aW9uIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBDaGVja3N1bUV4Y2VwdGlvbi5nZXRDaGVja3N1bUluc3RhbmNlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlY2VpdmVkW3Bvc2l0aW9uXSA9IHRoaXMuZmllbGQuc3VidHJhY3QocmVjZWl2ZWRbcG9zaXRpb25dLCBlcnJvck1hZ25pdHVkZXNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGVycm9yTG9jYXRpb25zLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIE1vZHVsdXNQb2x5XG4gICAgICAgICAqIEBwYXJhbSBhXG4gICAgICAgICAqIEBwYXJhbSBNb2R1bHVzUG9seVxuICAgICAgICAgKiBAcGFyYW0gYlxuICAgICAgICAgKiBAcGFyYW0gaW50XG4gICAgICAgICAqIEBwYXJhbSBSXG4gICAgICAgICAqIEB0aHJvd3MgQ2hlY2tzdW1FeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIHJ1bkV1Y2xpZGVhbkFsZ29yaXRobShhLCBiLCBSKSB7XG4gICAgICAgICAgICAvLyBBc3N1bWUgYSdzIGRlZ3JlZSBpcyA+PSBiJ3NcbiAgICAgICAgICAgIGlmIChhLmdldERlZ3JlZSgpIDwgYi5nZXREZWdyZWUoKSkge1xuICAgICAgICAgICAgICAgIGxldCB0ZW1wID0gYTtcbiAgICAgICAgICAgICAgICBhID0gYjtcbiAgICAgICAgICAgICAgICBiID0gdGVtcDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCByTGFzdCA9IGE7XG4gICAgICAgICAgICBsZXQgciA9IGI7XG4gICAgICAgICAgICBsZXQgdExhc3QgPSB0aGlzLmZpZWxkLmdldFplcm8oKTtcbiAgICAgICAgICAgIGxldCB0ID0gdGhpcy5maWVsZC5nZXRPbmUoKTtcbiAgICAgICAgICAgIC8vIFJ1biBFdWNsaWRlYW4gYWxnb3JpdGhtIHVudGlsIHIncyBkZWdyZWUgaXMgbGVzcyB0aGFuIFIvMlxuICAgICAgICAgICAgd2hpbGUgKHIuZ2V0RGVncmVlKCkgPj0gTWF0aC5yb3VuZChSIC8gMikpIHtcbiAgICAgICAgICAgICAgICBsZXQgckxhc3RMYXN0ID0gckxhc3Q7XG4gICAgICAgICAgICAgICAgbGV0IHRMYXN0TGFzdCA9IHRMYXN0O1xuICAgICAgICAgICAgICAgIHJMYXN0ID0gcjtcbiAgICAgICAgICAgICAgICB0TGFzdCA9IHQ7XG4gICAgICAgICAgICAgICAgLy8gRGl2aWRlIHJMYXN0TGFzdCBieSByTGFzdCwgd2l0aCBxdW90aWVudCBpbiBxIGFuZCByZW1haW5kZXIgaW4gclxuICAgICAgICAgICAgICAgIGlmIChyTGFzdC5pc1plcm8oKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBPb3BzLCBFdWNsaWRlYW4gYWxnb3JpdGhtIGFscmVhZHkgdGVybWluYXRlZD9cbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgQ2hlY2tzdW1FeGNlcHRpb24uZ2V0Q2hlY2tzdW1JbnN0YW5jZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByID0gckxhc3RMYXN0O1xuICAgICAgICAgICAgICAgIGxldCBxID0gdGhpcy5maWVsZC5nZXRaZXJvKCk7XG4gICAgICAgICAgICAgICAgbGV0IGRlbm9taW5hdG9yTGVhZGluZ1Rlcm0gPSByTGFzdC5nZXRDb2VmZmljaWVudChyTGFzdC5nZXREZWdyZWUoKSk7XG4gICAgICAgICAgICAgICAgbGV0IGRsdEludmVyc2UgPSB0aGlzLmZpZWxkLmludmVyc2UoZGVub21pbmF0b3JMZWFkaW5nVGVybSk7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHIuZ2V0RGVncmVlKCkgPj0gckxhc3QuZ2V0RGVncmVlKCkgJiYgIXIuaXNaZXJvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGRlZ3JlZURpZmYgPSByLmdldERlZ3JlZSgpIC0gckxhc3QuZ2V0RGVncmVlKCk7XG4gICAgICAgICAgICAgICAgICAgIGxldCBzY2FsZSA9IHRoaXMuZmllbGQubXVsdGlwbHkoci5nZXRDb2VmZmljaWVudChyLmdldERlZ3JlZSgpKSwgZGx0SW52ZXJzZSk7XG4gICAgICAgICAgICAgICAgICAgIHEgPSBxLmFkZCh0aGlzLmZpZWxkLmJ1aWxkTW9ub21pYWwoZGVncmVlRGlmZiwgc2NhbGUpKTtcbiAgICAgICAgICAgICAgICAgICAgciA9IHIuc3VidHJhY3Qockxhc3QubXVsdGlwbHlCeU1vbm9taWFsKGRlZ3JlZURpZmYsIHNjYWxlKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHQgPSBxLm11bHRpcGx5KHRMYXN0KS5zdWJ0cmFjdCh0TGFzdExhc3QpLm5lZ2F0aXZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc2lnbWFUaWxkZUF0WmVybyA9IHQuZ2V0Q29lZmZpY2llbnQoMCk7XG4gICAgICAgICAgICBpZiAoc2lnbWFUaWxkZUF0WmVybyA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IENoZWNrc3VtRXhjZXB0aW9uLmdldENoZWNrc3VtSW5zdGFuY2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBpbnZlcnNlID0gdGhpcy5maWVsZC5pbnZlcnNlKHNpZ21hVGlsZGVBdFplcm8pO1xuICAgICAgICAgICAgbGV0IHNpZ21hID0gdC5tdWx0aXBseShpbnZlcnNlKTtcbiAgICAgICAgICAgIGxldCBvbWVnYSA9IHIubXVsdGlwbHkoaW52ZXJzZSk7XG4gICAgICAgICAgICByZXR1cm4gW3NpZ21hLCBvbWVnYV07XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBlcnJvckxvY2F0b3JcbiAgICAgICAgICogQHRocm93cyBDaGVja3N1bUV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgZmluZEVycm9yTG9jYXRpb25zKGVycm9yTG9jYXRvcikge1xuICAgICAgICAgICAgLy8gVGhpcyBpcyBhIGRpcmVjdCBhcHBsaWNhdGlvbiBvZiBDaGllbidzIHNlYXJjaFxuICAgICAgICAgICAgbGV0IG51bUVycm9ycyA9IGVycm9yTG9jYXRvci5nZXREZWdyZWUoKTtcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSBuZXcgSW50MzJBcnJheShudW1FcnJvcnMpO1xuICAgICAgICAgICAgbGV0IGUgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMTsgaSA8IHRoaXMuZmllbGQuZ2V0U2l6ZSgpICYmIGUgPCBudW1FcnJvcnM7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvckxvY2F0b3IuZXZhbHVhdGVBdChpKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRbZV0gPSB0aGlzLmZpZWxkLmludmVyc2UoaSk7XG4gICAgICAgICAgICAgICAgICAgIGUrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZSAhPT0gbnVtRXJyb3JzKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgQ2hlY2tzdW1FeGNlcHRpb24uZ2V0Q2hlY2tzdW1JbnN0YW5jZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBmaW5kRXJyb3JNYWduaXR1ZGVzKGVycm9yRXZhbHVhdG9yLCBlcnJvckxvY2F0b3IsIGVycm9yTG9jYXRpb25zKSB7XG4gICAgICAgICAgICBsZXQgZXJyb3JMb2NhdG9yRGVncmVlID0gZXJyb3JMb2NhdG9yLmdldERlZ3JlZSgpO1xuICAgICAgICAgICAgbGV0IGZvcm1hbERlcml2YXRpdmVDb2VmZmljaWVudHMgPSBuZXcgSW50MzJBcnJheShlcnJvckxvY2F0b3JEZWdyZWUpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMTsgaSA8PSBlcnJvckxvY2F0b3JEZWdyZWU7IGkrKykge1xuICAgICAgICAgICAgICAgIGZvcm1hbERlcml2YXRpdmVDb2VmZmljaWVudHNbZXJyb3JMb2NhdG9yRGVncmVlIC0gaV0gPVxuICAgICAgICAgICAgICAgICAgICB0aGlzLmZpZWxkLm11bHRpcGx5KGksIGVycm9yTG9jYXRvci5nZXRDb2VmZmljaWVudChpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZm9ybWFsRGVyaXZhdGl2ZSA9IG5ldyBNb2R1bHVzUG9seSh0aGlzLmZpZWxkLCBmb3JtYWxEZXJpdmF0aXZlQ29lZmZpY2llbnRzKTtcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgZGlyZWN0bHkgYXBwbHlpbmcgRm9ybmV5J3MgRm9ybXVsYVxuICAgICAgICAgICAgbGV0IHMgPSBlcnJvckxvY2F0aW9ucy5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gbmV3IEludDMyQXJyYXkocyk7XG4gICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAwOyBpIDwgczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IHhpSW52ZXJzZSA9IHRoaXMuZmllbGQuaW52ZXJzZShlcnJvckxvY2F0aW9uc1tpXSk7XG4gICAgICAgICAgICAgICAgbGV0IG51bWVyYXRvciA9IHRoaXMuZmllbGQuc3VidHJhY3QoMCwgZXJyb3JFdmFsdWF0b3IuZXZhbHVhdGVBdCh4aUludmVyc2UpKTtcbiAgICAgICAgICAgICAgICBsZXQgZGVub21pbmF0b3IgPSB0aGlzLmZpZWxkLmludmVyc2UoZm9ybWFsRGVyaXZhdGl2ZS5ldmFsdWF0ZUF0KHhpSW52ZXJzZSkpO1xuICAgICAgICAgICAgICAgIHJlc3VsdFtpXSA9IHRoaXMuZmllbGQubXVsdGlwbHkobnVtZXJhdG9yLCBkZW5vbWluYXRvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAqIENvcHlyaWdodCAyMDEzIFpYaW5nIGF1dGhvcnNcbiAgICAqXG4gICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgKlxuICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAqXG4gICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICovXG4gICAgLyoqXG4gICAgICogQGF1dGhvciBHdWVudGhlciBHcmF1XG4gICAgICovXG4gICAgLypmaW5hbCovIGNsYXNzIEJvdW5kaW5nQm94IHtcbiAgICAgICAgY29uc3RydWN0b3IoaW1hZ2UsIHRvcExlZnQsIGJvdHRvbUxlZnQsIHRvcFJpZ2h0LCBib3R0b21SaWdodCkge1xuICAgICAgICAgICAgaWYgKGltYWdlIGluc3RhbmNlb2YgQm91bmRpbmdCb3gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnN0cnVjdG9yXzIoaW1hZ2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvcl8xKGltYWdlLCB0b3BMZWZ0LCBib3R0b21MZWZ0LCB0b3BSaWdodCwgYm90dG9tUmlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gaW1hZ2VcbiAgICAgICAgICogQHBhcmFtIHRvcExlZnRcbiAgICAgICAgICogQHBhcmFtIGJvdHRvbUxlZnRcbiAgICAgICAgICogQHBhcmFtIHRvcFJpZ2h0XG4gICAgICAgICAqIEBwYXJhbSBib3R0b21SaWdodFxuICAgICAgICAgKlxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3Rvcl8xKGltYWdlLCB0b3BMZWZ0LCBib3R0b21MZWZ0LCB0b3BSaWdodCwgYm90dG9tUmlnaHQpIHtcbiAgICAgICAgICAgIGNvbnN0IGxlZnRVbnNwZWNpZmllZCA9IHRvcExlZnQgPT0gbnVsbCB8fCBib3R0b21MZWZ0ID09IG51bGw7XG4gICAgICAgICAgICBjb25zdCByaWdodFVuc3BlY2lmaWVkID0gdG9wUmlnaHQgPT0gbnVsbCB8fCBib3R0b21SaWdodCA9PSBudWxsO1xuICAgICAgICAgICAgaWYgKGxlZnRVbnNwZWNpZmllZCAmJiByaWdodFVuc3BlY2lmaWVkKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobGVmdFVuc3BlY2lmaWVkKSB7XG4gICAgICAgICAgICAgICAgdG9wTGVmdCA9IG5ldyBSZXN1bHRQb2ludCgwLCB0b3BSaWdodC5nZXRZKCkpO1xuICAgICAgICAgICAgICAgIGJvdHRvbUxlZnQgPSBuZXcgUmVzdWx0UG9pbnQoMCwgYm90dG9tUmlnaHQuZ2V0WSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHJpZ2h0VW5zcGVjaWZpZWQpIHtcbiAgICAgICAgICAgICAgICB0b3BSaWdodCA9IG5ldyBSZXN1bHRQb2ludChpbWFnZS5nZXRXaWR0aCgpIC0gMSwgdG9wTGVmdC5nZXRZKCkpO1xuICAgICAgICAgICAgICAgIGJvdHRvbVJpZ2h0ID0gbmV3IFJlc3VsdFBvaW50KGltYWdlLmdldFdpZHRoKCkgLSAxLCBib3R0b21MZWZ0LmdldFkoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmltYWdlID0gaW1hZ2U7XG4gICAgICAgICAgICB0aGlzLnRvcExlZnQgPSB0b3BMZWZ0O1xuICAgICAgICAgICAgdGhpcy5ib3R0b21MZWZ0ID0gYm90dG9tTGVmdDtcbiAgICAgICAgICAgIHRoaXMudG9wUmlnaHQgPSB0b3BSaWdodDtcbiAgICAgICAgICAgIHRoaXMuYm90dG9tUmlnaHQgPSBib3R0b21SaWdodDtcbiAgICAgICAgICAgIHRoaXMubWluWCA9IE1hdGgudHJ1bmMoTWF0aC5taW4odG9wTGVmdC5nZXRYKCksIGJvdHRvbUxlZnQuZ2V0WCgpKSk7XG4gICAgICAgICAgICB0aGlzLm1heFggPSBNYXRoLnRydW5jKE1hdGgubWF4KHRvcFJpZ2h0LmdldFgoKSwgYm90dG9tUmlnaHQuZ2V0WCgpKSk7XG4gICAgICAgICAgICB0aGlzLm1pblkgPSBNYXRoLnRydW5jKE1hdGgubWluKHRvcExlZnQuZ2V0WSgpLCB0b3BSaWdodC5nZXRZKCkpKTtcbiAgICAgICAgICAgIHRoaXMubWF4WSA9IE1hdGgudHJ1bmMoTWF0aC5tYXgoYm90dG9tTGVmdC5nZXRZKCksIGJvdHRvbVJpZ2h0LmdldFkoKSkpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0cnVjdG9yXzIoYm91bmRpbmdCb3gpIHtcbiAgICAgICAgICAgIHRoaXMuaW1hZ2UgPSBib3VuZGluZ0JveC5pbWFnZTtcbiAgICAgICAgICAgIHRoaXMudG9wTGVmdCA9IGJvdW5kaW5nQm94LmdldFRvcExlZnQoKTtcbiAgICAgICAgICAgIHRoaXMuYm90dG9tTGVmdCA9IGJvdW5kaW5nQm94LmdldEJvdHRvbUxlZnQoKTtcbiAgICAgICAgICAgIHRoaXMudG9wUmlnaHQgPSBib3VuZGluZ0JveC5nZXRUb3BSaWdodCgpO1xuICAgICAgICAgICAgdGhpcy5ib3R0b21SaWdodCA9IGJvdW5kaW5nQm94LmdldEJvdHRvbVJpZ2h0KCk7XG4gICAgICAgICAgICB0aGlzLm1pblggPSBib3VuZGluZ0JveC5nZXRNaW5YKCk7XG4gICAgICAgICAgICB0aGlzLm1heFggPSBib3VuZGluZ0JveC5nZXRNYXhYKCk7XG4gICAgICAgICAgICB0aGlzLm1pblkgPSBib3VuZGluZ0JveC5nZXRNaW5ZKCk7XG4gICAgICAgICAgICB0aGlzLm1heFkgPSBib3VuZGluZ0JveC5nZXRNYXhZKCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBtZXJnZShsZWZ0Qm94LCByaWdodEJveCkge1xuICAgICAgICAgICAgaWYgKGxlZnRCb3ggPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiByaWdodEJveDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyaWdodEJveCA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxlZnRCb3g7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IEJvdW5kaW5nQm94KGxlZnRCb3guaW1hZ2UsIGxlZnRCb3gudG9wTGVmdCwgbGVmdEJveC5ib3R0b21MZWZ0LCByaWdodEJveC50b3BSaWdodCwgcmlnaHRCb3guYm90dG9tUmlnaHQpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBhZGRNaXNzaW5nUm93cyhtaXNzaW5nU3RhcnRSb3dzLCBtaXNzaW5nRW5kUm93cywgaXNMZWZ0KSB7XG4gICAgICAgICAgICBsZXQgbmV3VG9wTGVmdCA9IHRoaXMudG9wTGVmdDtcbiAgICAgICAgICAgIGxldCBuZXdCb3R0b21MZWZ0ID0gdGhpcy5ib3R0b21MZWZ0O1xuICAgICAgICAgICAgbGV0IG5ld1RvcFJpZ2h0ID0gdGhpcy50b3BSaWdodDtcbiAgICAgICAgICAgIGxldCBuZXdCb3R0b21SaWdodCA9IHRoaXMuYm90dG9tUmlnaHQ7XG4gICAgICAgICAgICBpZiAobWlzc2luZ1N0YXJ0Um93cyA+IDApIHtcbiAgICAgICAgICAgICAgICBsZXQgdG9wID0gaXNMZWZ0ID8gdGhpcy50b3BMZWZ0IDogdGhpcy50b3BSaWdodDtcbiAgICAgICAgICAgICAgICBsZXQgbmV3TWluWSA9IE1hdGgudHJ1bmModG9wLmdldFkoKSAtIG1pc3NpbmdTdGFydFJvd3MpO1xuICAgICAgICAgICAgICAgIGlmIChuZXdNaW5ZIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICBuZXdNaW5ZID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IG5ld1RvcCA9IG5ldyBSZXN1bHRQb2ludCh0b3AuZ2V0WCgpLCBuZXdNaW5ZKTtcbiAgICAgICAgICAgICAgICBpZiAoaXNMZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld1RvcExlZnQgPSBuZXdUb3A7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdUb3BSaWdodCA9IG5ld1RvcDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWlzc2luZ0VuZFJvd3MgPiAwKSB7XG4gICAgICAgICAgICAgICAgbGV0IGJvdHRvbSA9IGlzTGVmdCA/IHRoaXMuYm90dG9tTGVmdCA6IHRoaXMuYm90dG9tUmlnaHQ7XG4gICAgICAgICAgICAgICAgbGV0IG5ld01heFkgPSBNYXRoLnRydW5jKGJvdHRvbS5nZXRZKCkgKyBtaXNzaW5nRW5kUm93cyk7XG4gICAgICAgICAgICAgICAgaWYgKG5ld01heFkgPj0gdGhpcy5pbWFnZS5nZXRIZWlnaHQoKSkge1xuICAgICAgICAgICAgICAgICAgICBuZXdNYXhZID0gdGhpcy5pbWFnZS5nZXRIZWlnaHQoKSAtIDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCBuZXdCb3R0b20gPSBuZXcgUmVzdWx0UG9pbnQoYm90dG9tLmdldFgoKSwgbmV3TWF4WSk7XG4gICAgICAgICAgICAgICAgaWYgKGlzTGVmdCkge1xuICAgICAgICAgICAgICAgICAgICBuZXdCb3R0b21MZWZ0ID0gbmV3Qm90dG9tO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Qm90dG9tUmlnaHQgPSBuZXdCb3R0b207XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBCb3VuZGluZ0JveCh0aGlzLmltYWdlLCBuZXdUb3BMZWZ0LCBuZXdCb3R0b21MZWZ0LCBuZXdUb3BSaWdodCwgbmV3Qm90dG9tUmlnaHQpO1xuICAgICAgICB9XG4gICAgICAgIGdldE1pblgoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5taW5YO1xuICAgICAgICB9XG4gICAgICAgIGdldE1heFgoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXhYO1xuICAgICAgICB9XG4gICAgICAgIGdldE1pblkoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5taW5ZO1xuICAgICAgICB9XG4gICAgICAgIGdldE1heFkoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXhZO1xuICAgICAgICB9XG4gICAgICAgIGdldFRvcExlZnQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50b3BMZWZ0O1xuICAgICAgICB9XG4gICAgICAgIGdldFRvcFJpZ2h0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9wUmlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Qm90dG9tTGVmdCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJvdHRvbUxlZnQ7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Qm90dG9tUmlnaHQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ib3R0b21SaWdodDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMTMgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLy8gcGFja2FnZSBjb20uZ29vZ2xlLnp4aW5nLnBkZjQxNy5kZWNvZGVyO1xuICAgIC8qKlxuICAgICAqIEBhdXRob3IgR3VlbnRoZXIgR3JhdVxuICAgICAqL1xuICAgIC8qZmluYWwqLyBjbGFzcyBCYXJjb2RlTWV0YWRhdGEge1xuICAgICAgICBjb25zdHJ1Y3Rvcihjb2x1bW5Db3VudCwgcm93Q291bnRVcHBlclBhcnQsIHJvd0NvdW50TG93ZXJQYXJ0LCBlcnJvckNvcnJlY3Rpb25MZXZlbCkge1xuICAgICAgICAgICAgdGhpcy5jb2x1bW5Db3VudCA9IGNvbHVtbkNvdW50O1xuICAgICAgICAgICAgdGhpcy5lcnJvckNvcnJlY3Rpb25MZXZlbCA9IGVycm9yQ29ycmVjdGlvbkxldmVsO1xuICAgICAgICAgICAgdGhpcy5yb3dDb3VudFVwcGVyUGFydCA9IHJvd0NvdW50VXBwZXJQYXJ0O1xuICAgICAgICAgICAgdGhpcy5yb3dDb3VudExvd2VyUGFydCA9IHJvd0NvdW50TG93ZXJQYXJ0O1xuICAgICAgICAgICAgdGhpcy5yb3dDb3VudCA9IHJvd0NvdW50VXBwZXJQYXJ0ICsgcm93Q291bnRMb3dlclBhcnQ7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Q29sdW1uQ291bnQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2x1bW5Db3VudDtcbiAgICAgICAgfVxuICAgICAgICBnZXRFcnJvckNvcnJlY3Rpb25MZXZlbCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVycm9yQ29ycmVjdGlvbkxldmVsO1xuICAgICAgICB9XG4gICAgICAgIGdldFJvd0NvdW50KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucm93Q291bnQ7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Um93Q291bnRVcHBlclBhcnQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yb3dDb3VudFVwcGVyUGFydDtcbiAgICAgICAgfVxuICAgICAgICBnZXRSb3dDb3VudExvd2VyUGFydCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJvd0NvdW50TG93ZXJQYXJ0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSmF2YSBGb3JtYXR0ZXIgY2xhc3MgcG9seWZpbGwgdGhhdCB3b3JrcyBpbiB0aGUgSlMgd2F5LlxuICAgICAqL1xuICAgIGNsYXNzIEZvcm1hdHRlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgdGhpcy5idWZmZXIgPSAnJztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICpcbiAgICAgICAgICogQHNlZSBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMTM0Mzk3MTEvNDM2NzY4M1xuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gc3RyXG4gICAgICAgICAqIEBwYXJhbSBhcnJcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBmb3JtKHN0ciwgYXJyKSB7XG4gICAgICAgICAgICBsZXQgaSA9IC0xO1xuICAgICAgICAgICAgZnVuY3Rpb24gY2FsbGJhY2soZXhwLCBwMCwgcDEsIHAyLCBwMywgcDQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXhwID09PSAnJSUnKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJyUnO1xuICAgICAgICAgICAgICAgIGlmIChhcnJbKytpXSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGV4cCA9IHAyID8gcGFyc2VJbnQocDIuc3Vic3RyKDEpKSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICBsZXQgYmFzZSA9IHAzID8gcGFyc2VJbnQocDMuc3Vic3RyKDEpKSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICBsZXQgdmFsO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAocDQpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAncyc6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWwgPSBhcnJbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnYyc6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWwgPSBhcnJbaV1bMF07XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnZic6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWwgPSBwYXJzZUZsb2F0KGFycltpXSkudG9GaXhlZChleHApO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3AnOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsID0gcGFyc2VGbG9hdChhcnJbaV0pLnRvUHJlY2lzaW9uKGV4cCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWwgPSBwYXJzZUZsb2F0KGFycltpXSkudG9FeHBvbmVudGlhbChleHApO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3gnOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsID0gcGFyc2VJbnQoYXJyW2ldKS50b1N0cmluZyhiYXNlID8gYmFzZSA6IDE2KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbCA9IHBhcnNlRmxvYXQocGFyc2VJbnQoYXJyW2ldLCBiYXNlID8gYmFzZSA6IDEwKS50b1ByZWNpc2lvbihleHApKS50b0ZpeGVkKDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhbCA9IHR5cGVvZiB2YWwgPT09ICdvYmplY3QnID8gSlNPTi5zdHJpbmdpZnkodmFsKSA6ICgrdmFsKS50b1N0cmluZyhiYXNlKTtcbiAgICAgICAgICAgICAgICBsZXQgc2l6ZSA9IHBhcnNlSW50KHAxKTsgLyogcGFkZGluZyBzaXplICovXG4gICAgICAgICAgICAgICAgbGV0IGNoID0gcDEgJiYgKHAxWzBdICsgJycpID09PSAnMCcgPyAnMCcgOiAnICc7IC8qIGlzbnVsbD8gKi9cbiAgICAgICAgICAgICAgICB3aGlsZSAodmFsLmxlbmd0aCA8IHNpemUpXG4gICAgICAgICAgICAgICAgICAgIHZhbCA9IHAwICE9PSB1bmRlZmluZWQgPyB2YWwgKyBjaCA6IGNoICsgdmFsOyAvKiBpc21pbnVzPyAqL1xuICAgICAgICAgICAgICAgIHJldHVybiB2YWw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcmVnZXggPSAvJSgtKT8oMD9bMC05XSspPyhbLl1bMC05XSspPyhbI11bMC05XSspPyhbc2NmcGV4ZCVdKS9nO1xuICAgICAgICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKHJlZ2V4LCBjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBhcHBlbmQgVGhlIG5ldyBzdHJpbmcgdG8gYXBwZW5kLlxuICAgICAgICAgKiBAcGFyYW0gYXJncyBBcmd1bWV0cyB2YWx1ZXMgdG8gYmUgZm9ybWF0ZWQuXG4gICAgICAgICAqL1xuICAgICAgICBmb3JtYXQoYXBwZW5kLCAuLi5hcmdzKSB7XG4gICAgICAgICAgICB0aGlzLmJ1ZmZlciArPSBGb3JtYXR0ZXIuZm9ybShhcHBlbmQsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXR1cm5zIHRoZSBGb3JtYXR0ZXIgc3RyaW5nIHZhbHVlLlxuICAgICAgICAgKi9cbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5idWZmZXI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDEzIFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIEBhdXRob3IgR3VlbnRoZXIgR3JhdVxuICAgICAqL1xuICAgIGNsYXNzIERldGVjdGlvblJlc3VsdENvbHVtbiB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGJvdW5kaW5nQm94KSB7XG4gICAgICAgICAgICB0aGlzLmJvdW5kaW5nQm94ID0gbmV3IEJvdW5kaW5nQm94KGJvdW5kaW5nQm94KTtcbiAgICAgICAgICAgIC8vIHRoaXMuY29kZXdvcmRzID0gbmV3IENvZGV3b3JkW2JvdW5kaW5nQm94LmdldE1heFkoKSAtIGJvdW5kaW5nQm94LmdldE1pblkoKSArIDFdO1xuICAgICAgICAgICAgdGhpcy5jb2Rld29yZHMgPSBuZXcgQXJyYXkoYm91bmRpbmdCb3guZ2V0TWF4WSgpIC0gYm91bmRpbmdCb3guZ2V0TWluWSgpICsgMSk7XG4gICAgICAgIH1cbiAgICAgICAgLypmaW5hbCovIGdldENvZGV3b3JkTmVhcmJ5KGltYWdlUm93KSB7XG4gICAgICAgICAgICBsZXQgY29kZXdvcmQgPSB0aGlzLmdldENvZGV3b3JkKGltYWdlUm93KTtcbiAgICAgICAgICAgIGlmIChjb2Rld29yZCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvZGV3b3JkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBEZXRlY3Rpb25SZXN1bHRDb2x1bW4uTUFYX05FQVJCWV9ESVNUQU5DRTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IG5lYXJJbWFnZVJvdyA9IHRoaXMuaW1hZ2VSb3dUb0NvZGV3b3JkSW5kZXgoaW1hZ2VSb3cpIC0gaTtcbiAgICAgICAgICAgICAgICBpZiAobmVhckltYWdlUm93ID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgY29kZXdvcmQgPSB0aGlzLmNvZGV3b3Jkc1tuZWFySW1hZ2VSb3ddO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvZGV3b3JkO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG5lYXJJbWFnZVJvdyA9IHRoaXMuaW1hZ2VSb3dUb0NvZGV3b3JkSW5kZXgoaW1hZ2VSb3cpICsgaTtcbiAgICAgICAgICAgICAgICBpZiAobmVhckltYWdlUm93IDwgdGhpcy5jb2Rld29yZHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvZGV3b3JkID0gdGhpcy5jb2Rld29yZHNbbmVhckltYWdlUm93XTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvZGV3b3JkICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjb2Rld29yZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIC8qZmluYWwgaW50Ki8gaW1hZ2VSb3dUb0NvZGV3b3JkSW5kZXgoaW1hZ2VSb3cpIHtcbiAgICAgICAgICAgIHJldHVybiBpbWFnZVJvdyAtIHRoaXMuYm91bmRpbmdCb3guZ2V0TWluWSgpO1xuICAgICAgICB9XG4gICAgICAgIC8qZmluYWwgdm9pZCovIHNldENvZGV3b3JkKGltYWdlUm93LCBjb2Rld29yZCkge1xuICAgICAgICAgICAgdGhpcy5jb2Rld29yZHNbdGhpcy5pbWFnZVJvd1RvQ29kZXdvcmRJbmRleChpbWFnZVJvdyldID0gY29kZXdvcmQ7XG4gICAgICAgIH1cbiAgICAgICAgLypmaW5hbCovIGdldENvZGV3b3JkKGltYWdlUm93KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2Rld29yZHNbdGhpcy5pbWFnZVJvd1RvQ29kZXdvcmRJbmRleChpbWFnZVJvdyldO1xuICAgICAgICB9XG4gICAgICAgIC8qZmluYWwqLyBnZXRCb3VuZGluZ0JveCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJvdW5kaW5nQm94O1xuICAgICAgICB9XG4gICAgICAgIC8qZmluYWwqLyBnZXRDb2Rld29yZHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2Rld29yZHM7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgY29uc3QgZm9ybWF0dGVyID0gbmV3IEZvcm1hdHRlcigpO1xuICAgICAgICAgICAgbGV0IHJvdyA9IDA7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvZGV3b3JkIG9mIHRoaXMuY29kZXdvcmRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvZGV3b3JkID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9ybWF0dGVyLmZvcm1hdCgnJTNkOiAgICB8ICAgJW4nLCByb3crKyk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3JtYXR0ZXIuZm9ybWF0KCclM2Q6ICUzZHwlM2QlbicsIHJvdysrLCBjb2Rld29yZC5nZXRSb3dOdW1iZXIoKSwgY29kZXdvcmQuZ2V0VmFsdWUoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZm9ybWF0dGVyLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgRGV0ZWN0aW9uUmVzdWx0Q29sdW1uLk1BWF9ORUFSQllfRElTVEFOQ0UgPSA1O1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAxMyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLkFycmF5TGlzdDtcbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLkNvbGxlY3Rpb247XG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5IYXNoTWFwO1xuICAgIC8vIGltcG9ydCBqYXZhLnV0aWwuTWFwO1xuICAgIC8vIGltcG9ydCBqYXZhLnV0aWwuTWFwLkVudHJ5O1xuICAgIC8qKlxuICAgICAqIEBhdXRob3IgR3VlbnRoZXIgR3JhdVxuICAgICAqL1xuICAgIC8qZmluYWwqLyBjbGFzcyBCYXJjb2RlVmFsdWUge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWVzID0gbmV3IE1hcCgpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBZGQgYW4gb2NjdXJyZW5jZSBvZiBhIHZhbHVlXG4gICAgICAgICAqL1xuICAgICAgICBzZXRWYWx1ZSh2YWx1ZSkge1xuICAgICAgICAgICAgdmFsdWUgPSBNYXRoLnRydW5jKHZhbHVlKTtcbiAgICAgICAgICAgIGxldCBjb25maWRlbmNlID0gdGhpcy52YWx1ZXMuZ2V0KHZhbHVlKTtcbiAgICAgICAgICAgIGlmIChjb25maWRlbmNlID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBjb25maWRlbmNlID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbmZpZGVuY2UrKztcbiAgICAgICAgICAgIHRoaXMudmFsdWVzLnNldCh2YWx1ZSwgY29uZmlkZW5jZSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERldGVybWluZXMgdGhlIG1heGltdW0gb2NjdXJyZW5jZSBvZiBhIHNldCB2YWx1ZSBhbmQgcmV0dXJucyBhbGwgdmFsdWVzIHdoaWNoIHdlcmUgc2V0IHdpdGggdGhpcyBvY2N1cnJlbmNlLlxuICAgICAgICAgKiBAcmV0dXJuIGFuIGFycmF5IG9mIGludCwgY29udGFpbmluZyB0aGUgdmFsdWVzIHdpdGggdGhlIGhpZ2hlc3Qgb2NjdXJyZW5jZSwgb3IgbnVsbCwgaWYgbm8gdmFsdWUgd2FzIHNldFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0VmFsdWUoKSB7XG4gICAgICAgICAgICBsZXQgbWF4Q29uZmlkZW5jZSA9IC0xO1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IG5ldyBBcnJheSgpO1xuICAgICAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgdGhpcy52YWx1ZXMuZW50cmllcygpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZW50cnkgPSB7XG4gICAgICAgICAgICAgICAgICAgIGdldEtleTogKCkgPT4ga2V5LFxuICAgICAgICAgICAgICAgICAgICBnZXRWYWx1ZTogKCkgPT4gdmFsdWUsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBpZiAoZW50cnkuZ2V0VmFsdWUoKSA+IG1heENvbmZpZGVuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgbWF4Q29uZmlkZW5jZSA9IGVudHJ5LmdldFZhbHVlKCk7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IFtdO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChlbnRyeS5nZXRLZXkoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGVudHJ5LmdldFZhbHVlKCkgPT09IG1heENvbmZpZGVuY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goZW50cnkuZ2V0S2V5KCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBQREY0MTdDb21tb24udG9JbnRBcnJheShyZXN1bHQpO1xuICAgICAgICB9XG4gICAgICAgIGdldENvbmZpZGVuY2UodmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlcy5nZXQodmFsdWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAxMyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiBAYXV0aG9yIEd1ZW50aGVyIEdyYXVcbiAgICAgKi9cbiAgICAvKmZpbmFsKi8gY2xhc3MgRGV0ZWN0aW9uUmVzdWx0Um93SW5kaWNhdG9yQ29sdW1uIGV4dGVuZHMgRGV0ZWN0aW9uUmVzdWx0Q29sdW1uIHtcbiAgICAgICAgY29uc3RydWN0b3IoYm91bmRpbmdCb3gsIGlzTGVmdCkge1xuICAgICAgICAgICAgc3VwZXIoYm91bmRpbmdCb3gpO1xuICAgICAgICAgICAgdGhpcy5faXNMZWZ0ID0gaXNMZWZ0O1xuICAgICAgICB9XG4gICAgICAgIHNldFJvd051bWJlcnMoKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBjb2Rld29yZCAvKkNvZGV3b3JkKi8gb2YgdGhpcy5nZXRDb2Rld29yZHMoKSkge1xuICAgICAgICAgICAgICAgIGlmIChjb2Rld29yZCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvZGV3b3JkLnNldFJvd051bWJlckFzUm93SW5kaWNhdG9yQ29sdW1uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIFRPRE8gaW1wbGVtZW50IHByb3Blcmx5XG4gICAgICAgIC8vIFRPRE8gbWF5YmUgd2Ugc2hvdWxkIGFkZCBtaXNzaW5nIGNvZGV3b3JkcyB0byBzdG9yZSB0aGUgY29ycmVjdCByb3cgbnVtYmVyIHRvIG1ha2VcbiAgICAgICAgLy8gZmluZGluZyByb3cgbnVtYmVycyBmb3Igb3RoZXIgY29sdW1ucyBlYXNpZXJcbiAgICAgICAgLy8gdXNlIHJvdyBoZWlnaHQgY291bnQgdG8gbWFrZSBkZXRlY3Rpb24gb2YgaW52YWxpZCByb3cgbnVtYmVycyBtb3JlIHJlbGlhYmxlXG4gICAgICAgIGFkanVzdENvbXBsZXRlSW5kaWNhdG9yQ29sdW1uUm93TnVtYmVycyhiYXJjb2RlTWV0YWRhdGEpIHtcbiAgICAgICAgICAgIGxldCBjb2Rld29yZHMgPSB0aGlzLmdldENvZGV3b3JkcygpO1xuICAgICAgICAgICAgdGhpcy5zZXRSb3dOdW1iZXJzKCk7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZUluY29ycmVjdENvZGV3b3Jkcyhjb2Rld29yZHMsIGJhcmNvZGVNZXRhZGF0YSk7XG4gICAgICAgICAgICBsZXQgYm91bmRpbmdCb3ggPSB0aGlzLmdldEJvdW5kaW5nQm94KCk7XG4gICAgICAgICAgICBsZXQgdG9wID0gdGhpcy5faXNMZWZ0ID8gYm91bmRpbmdCb3guZ2V0VG9wTGVmdCgpIDogYm91bmRpbmdCb3guZ2V0VG9wUmlnaHQoKTtcbiAgICAgICAgICAgIGxldCBib3R0b20gPSB0aGlzLl9pc0xlZnQgPyBib3VuZGluZ0JveC5nZXRCb3R0b21MZWZ0KCkgOiBib3VuZGluZ0JveC5nZXRCb3R0b21SaWdodCgpO1xuICAgICAgICAgICAgbGV0IGZpcnN0Um93ID0gdGhpcy5pbWFnZVJvd1RvQ29kZXdvcmRJbmRleChNYXRoLnRydW5jKHRvcC5nZXRZKCkpKTtcbiAgICAgICAgICAgIGxldCBsYXN0Um93ID0gdGhpcy5pbWFnZVJvd1RvQ29kZXdvcmRJbmRleChNYXRoLnRydW5jKGJvdHRvbS5nZXRZKCkpKTtcbiAgICAgICAgICAgIC8vIFdlIG5lZWQgdG8gYmUgY2FyZWZ1bCB1c2luZyB0aGUgYXZlcmFnZSByb3cgaGVpZ2h0LiBCYXJjb2RlIGNvdWxkIGJlIHNrZXdlZCBzbyB0aGF0IHdlIGhhdmUgc21hbGxlciBhbmRcbiAgICAgICAgICAgIC8vIHRhbGxlciByb3dzXG4gICAgICAgICAgICAvLyBmbG9hdCBhdmVyYWdlUm93SGVpZ2h0ID0gKGxhc3RSb3cgLSBmaXJzdFJvdykgLyAvKihmbG9hdCkqLyBiYXJjb2RlTWV0YWRhdGEuZ2V0Um93Q291bnQoKTtcbiAgICAgICAgICAgIGxldCBiYXJjb2RlUm93ID0gLTE7XG4gICAgICAgICAgICBsZXQgbWF4Um93SGVpZ2h0ID0gMTtcbiAgICAgICAgICAgIGxldCBjdXJyZW50Um93SGVpZ2h0ID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGNvZGV3b3Jkc1JvdyAvKmludCovID0gZmlyc3RSb3c7IGNvZGV3b3Jkc1JvdyA8IGxhc3RSb3c7IGNvZGV3b3Jkc1JvdysrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvZGV3b3Jkc1tjb2Rld29yZHNSb3ddID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCBjb2Rld29yZCA9IGNvZGV3b3Jkc1tjb2Rld29yZHNSb3ddO1xuICAgICAgICAgICAgICAgIC8vICAgICAgZmxvYXQgZXhwZWN0ZWRSb3dOdW1iZXIgPSAoY29kZXdvcmRzUm93IC0gZmlyc3RSb3cpIC8gYXZlcmFnZVJvd0hlaWdodDtcbiAgICAgICAgICAgICAgICAvLyAgICAgIGlmIChNYXRoLmFicyhjb2Rld29yZC5nZXRSb3dOdW1iZXIoKSAtIGV4cGVjdGVkUm93TnVtYmVyKSA+IDIpIHtcbiAgICAgICAgICAgICAgICAvLyAgICAgICAgU2ltcGxlTG9nLmxvZyhMRVZFTC5XQVJOSU5HLFxuICAgICAgICAgICAgICAgIC8vICAgICAgICAgICAgXCJSZW1vdmluZyBjb2Rld29yZCwgcm93TnVtYmVyU2tldyB0b28gaGlnaCwgY29kZXdvcmRbXCIgKyBjb2Rld29yZHNSb3cgKyBcIl06IEV4cGVjdGVkIFJvdzogXCIgK1xuICAgICAgICAgICAgICAgIC8vICAgICAgICAgICAgICAgIGV4cGVjdGVkUm93TnVtYmVyICsgXCIsIFJlYWxSb3c6IFwiICsgY29kZXdvcmQuZ2V0Um93TnVtYmVyKCkgKyBcIiwgdmFsdWU6IFwiICsgY29kZXdvcmQuZ2V0VmFsdWUoKSk7XG4gICAgICAgICAgICAgICAgLy8gICAgICAgIGNvZGV3b3Jkc1tjb2Rld29yZHNSb3ddID0gbnVsbDtcbiAgICAgICAgICAgICAgICAvLyAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgcm93RGlmZmVyZW5jZSA9IGNvZGV3b3JkLmdldFJvd051bWJlcigpIC0gYmFyY29kZVJvdztcbiAgICAgICAgICAgICAgICAvLyBUT0RPIGltcHJvdmUgaGFuZGxpbmcgd2l0aCBjYXNlIHdoZXJlIGZpcnN0IHJvdyBpbmRpY2F0b3IgZG9lc24ndCBzdGFydCB3aXRoIDBcbiAgICAgICAgICAgICAgICBpZiAocm93RGlmZmVyZW5jZSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50Um93SGVpZ2h0Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHJvd0RpZmZlcmVuY2UgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgbWF4Um93SGVpZ2h0ID0gTWF0aC5tYXgobWF4Um93SGVpZ2h0LCBjdXJyZW50Um93SGVpZ2h0KTtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudFJvd0hlaWdodCA9IDE7XG4gICAgICAgICAgICAgICAgICAgIGJhcmNvZGVSb3cgPSBjb2Rld29yZC5nZXRSb3dOdW1iZXIoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAocm93RGlmZmVyZW5jZSA8IDAgfHxcbiAgICAgICAgICAgICAgICAgICAgY29kZXdvcmQuZ2V0Um93TnVtYmVyKCkgPj0gYmFyY29kZU1ldGFkYXRhLmdldFJvd0NvdW50KCkgfHxcbiAgICAgICAgICAgICAgICAgICAgcm93RGlmZmVyZW5jZSA+IGNvZGV3b3Jkc1Jvdykge1xuICAgICAgICAgICAgICAgICAgICBjb2Rld29yZHNbY29kZXdvcmRzUm93XSA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsZXQgY2hlY2tlZFJvd3M7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtYXhSb3dIZWlnaHQgPiAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGVja2VkUm93cyA9IChtYXhSb3dIZWlnaHQgLSAyKSAqIHJvd0RpZmZlcmVuY2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGVja2VkUm93cyA9IHJvd0RpZmZlcmVuY2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbGV0IGNsb3NlUHJldmlvdXNDb2Rld29yZEZvdW5kID0gY2hlY2tlZFJvd3MgPj0gY29kZXdvcmRzUm93O1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAxOyBpIDw9IGNoZWNrZWRSb3dzICYmICFjbG9zZVByZXZpb3VzQ29kZXdvcmRGb3VuZDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGVyZSBtdXN0IGJlIChoZWlnaHQgKiByb3dEaWZmZXJlbmNlKSBudW1iZXIgb2YgY29kZXdvcmRzIG1pc3NpbmcuIEZvciBub3cgd2UgYXNzdW1lIGhlaWdodCA9IDEuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHNob3VsZCBob3BlZnVsbHkgZ2V0IHJpZCBvZiBtb3N0IHByb2JsZW1zIGFscmVhZHkuXG4gICAgICAgICAgICAgICAgICAgICAgICBjbG9zZVByZXZpb3VzQ29kZXdvcmRGb3VuZCA9IGNvZGV3b3Jkc1tjb2Rld29yZHNSb3cgLSBpXSAhPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChjbG9zZVByZXZpb3VzQ29kZXdvcmRGb3VuZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29kZXdvcmRzW2NvZGV3b3Jkc1Jvd10gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYmFyY29kZVJvdyA9IGNvZGV3b3JkLmdldFJvd051bWJlcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFJvd0hlaWdodCA9IDE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyByZXR1cm4gKGludCkgKGF2ZXJhZ2VSb3dIZWlnaHQgKyAwLjUpO1xuICAgICAgICB9XG4gICAgICAgIGdldFJvd0hlaWdodHMoKSB7XG4gICAgICAgICAgICBsZXQgYmFyY29kZU1ldGFkYXRhID0gdGhpcy5nZXRCYXJjb2RlTWV0YWRhdGEoKTtcbiAgICAgICAgICAgIGlmIChiYXJjb2RlTWV0YWRhdGEgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5hZGp1c3RJbmNvbXBsZXRlSW5kaWNhdG9yQ29sdW1uUm93TnVtYmVycyhiYXJjb2RlTWV0YWRhdGEpO1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IG5ldyBJbnQzMkFycmF5KGJhcmNvZGVNZXRhZGF0YS5nZXRSb3dDb3VudCgpKTtcbiAgICAgICAgICAgIGZvciAobGV0IGNvZGV3b3JkIC8qQ29kZXdvcmQqLyBvZiB0aGlzLmdldENvZGV3b3JkcygpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvZGV3b3JkICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHJvd051bWJlciA9IGNvZGV3b3JkLmdldFJvd051bWJlcigpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocm93TnVtYmVyID49IHJlc3VsdC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGhhdmUgbW9yZSByb3dzIHRoYW4gdGhlIGJhcmNvZGUgbWV0YWRhdGEgYWxsb3dzIGZvciwgaWdub3JlIHRoZW0uXG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXN1bHRbcm93TnVtYmVyXSsrO1xuICAgICAgICAgICAgICAgIH0gLy8gZWxzZSB0aHJvdyBleGNlcHRpb24/XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIC8vIFRPRE8gbWF5YmUgd2Ugc2hvdWxkIGFkZCBtaXNzaW5nIGNvZGV3b3JkcyB0byBzdG9yZSB0aGUgY29ycmVjdCByb3cgbnVtYmVyIHRvIG1ha2VcbiAgICAgICAgLy8gZmluZGluZyByb3cgbnVtYmVycyBmb3Igb3RoZXIgY29sdW1ucyBlYXNpZXJcbiAgICAgICAgLy8gdXNlIHJvdyBoZWlnaHQgY291bnQgdG8gbWFrZSBkZXRlY3Rpb24gb2YgaW52YWxpZCByb3cgbnVtYmVycyBtb3JlIHJlbGlhYmxlXG4gICAgICAgIGFkanVzdEluY29tcGxldGVJbmRpY2F0b3JDb2x1bW5Sb3dOdW1iZXJzKGJhcmNvZGVNZXRhZGF0YSkge1xuICAgICAgICAgICAgbGV0IGJvdW5kaW5nQm94ID0gdGhpcy5nZXRCb3VuZGluZ0JveCgpO1xuICAgICAgICAgICAgbGV0IHRvcCA9IHRoaXMuX2lzTGVmdCA/IGJvdW5kaW5nQm94LmdldFRvcExlZnQoKSA6IGJvdW5kaW5nQm94LmdldFRvcFJpZ2h0KCk7XG4gICAgICAgICAgICBsZXQgYm90dG9tID0gdGhpcy5faXNMZWZ0ID8gYm91bmRpbmdCb3guZ2V0Qm90dG9tTGVmdCgpIDogYm91bmRpbmdCb3guZ2V0Qm90dG9tUmlnaHQoKTtcbiAgICAgICAgICAgIGxldCBmaXJzdFJvdyA9IHRoaXMuaW1hZ2VSb3dUb0NvZGV3b3JkSW5kZXgoTWF0aC50cnVuYyh0b3AuZ2V0WSgpKSk7XG4gICAgICAgICAgICBsZXQgbGFzdFJvdyA9IHRoaXMuaW1hZ2VSb3dUb0NvZGV3b3JkSW5kZXgoTWF0aC50cnVuYyhib3R0b20uZ2V0WSgpKSk7XG4gICAgICAgICAgICAvLyBmbG9hdCBhdmVyYWdlUm93SGVpZ2h0ID0gKGxhc3RSb3cgLSBmaXJzdFJvdykgLyAvKihmbG9hdCkqLyBiYXJjb2RlTWV0YWRhdGEuZ2V0Um93Q291bnQoKTtcbiAgICAgICAgICAgIGxldCBjb2Rld29yZHMgPSB0aGlzLmdldENvZGV3b3JkcygpO1xuICAgICAgICAgICAgbGV0IGJhcmNvZGVSb3cgPSAtMTtcbiAgICAgICAgICAgIGZvciAobGV0IGNvZGV3b3Jkc1JvdyAvKmludCovID0gZmlyc3RSb3c7IGNvZGV3b3Jkc1JvdyA8IGxhc3RSb3c7IGNvZGV3b3Jkc1JvdysrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvZGV3b3Jkc1tjb2Rld29yZHNSb3ddID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCBjb2Rld29yZCA9IGNvZGV3b3Jkc1tjb2Rld29yZHNSb3ddO1xuICAgICAgICAgICAgICAgIGNvZGV3b3JkLnNldFJvd051bWJlckFzUm93SW5kaWNhdG9yQ29sdW1uKCk7XG4gICAgICAgICAgICAgICAgbGV0IHJvd0RpZmZlcmVuY2UgPSBjb2Rld29yZC5nZXRSb3dOdW1iZXIoKSAtIGJhcmNvZGVSb3c7XG4gICAgICAgICAgICAgICAgLy8gVE9ETyBpbXByb3ZlIGhhbmRsaW5nIHdpdGggY2FzZSB3aGVyZSBmaXJzdCByb3cgaW5kaWNhdG9yIGRvZXNuJ3Qgc3RhcnQgd2l0aCAwXG4gICAgICAgICAgICAgICAgaWYgKHJvd0RpZmZlcmVuY2UgPT09IDApIDtcbiAgICAgICAgICAgICAgICBlbHNlIGlmIChyb3dEaWZmZXJlbmNlID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGJhcmNvZGVSb3cgPSBjb2Rld29yZC5nZXRSb3dOdW1iZXIoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoY29kZXdvcmQuZ2V0Um93TnVtYmVyKCkgPj0gYmFyY29kZU1ldGFkYXRhLmdldFJvd0NvdW50KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29kZXdvcmRzW2NvZGV3b3Jkc1Jvd10gPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYmFyY29kZVJvdyA9IGNvZGV3b3JkLmdldFJvd051bWJlcigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHJldHVybiAoaW50KSAoYXZlcmFnZVJvd0hlaWdodCArIDAuNSk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0QmFyY29kZU1ldGFkYXRhKCkge1xuICAgICAgICAgICAgbGV0IGNvZGV3b3JkcyA9IHRoaXMuZ2V0Q29kZXdvcmRzKCk7XG4gICAgICAgICAgICBsZXQgYmFyY29kZUNvbHVtbkNvdW50ID0gbmV3IEJhcmNvZGVWYWx1ZSgpO1xuICAgICAgICAgICAgbGV0IGJhcmNvZGVSb3dDb3VudFVwcGVyUGFydCA9IG5ldyBCYXJjb2RlVmFsdWUoKTtcbiAgICAgICAgICAgIGxldCBiYXJjb2RlUm93Q291bnRMb3dlclBhcnQgPSBuZXcgQmFyY29kZVZhbHVlKCk7XG4gICAgICAgICAgICBsZXQgYmFyY29kZUVDTGV2ZWwgPSBuZXcgQmFyY29kZVZhbHVlKCk7XG4gICAgICAgICAgICBmb3IgKGxldCBjb2Rld29yZCAvKkNvZGV3b3JkKi8gb2YgY29kZXdvcmRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvZGV3b3JkID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvZGV3b3JkLnNldFJvd051bWJlckFzUm93SW5kaWNhdG9yQ29sdW1uKCk7XG4gICAgICAgICAgICAgICAgbGV0IHJvd0luZGljYXRvclZhbHVlID0gY29kZXdvcmQuZ2V0VmFsdWUoKSAlIDMwO1xuICAgICAgICAgICAgICAgIGxldCBjb2Rld29yZFJvd051bWJlciA9IGNvZGV3b3JkLmdldFJvd051bWJlcigpO1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5faXNMZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvZGV3b3JkUm93TnVtYmVyICs9IDI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN3aXRjaCAoY29kZXdvcmRSb3dOdW1iZXIgJSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGJhcmNvZGVSb3dDb3VudFVwcGVyUGFydC5zZXRWYWx1ZShyb3dJbmRpY2F0b3JWYWx1ZSAqIDMgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBiYXJjb2RlRUNMZXZlbC5zZXRWYWx1ZShyb3dJbmRpY2F0b3JWYWx1ZSAvIDMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYmFyY29kZVJvd0NvdW50TG93ZXJQYXJ0LnNldFZhbHVlKHJvd0luZGljYXRvclZhbHVlICUgMyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgYmFyY29kZUNvbHVtbkNvdW50LnNldFZhbHVlKHJvd0luZGljYXRvclZhbHVlICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBNYXliZSB3ZSBzaG91bGQgY2hlY2sgaWYgd2UgaGF2ZSBhbWJpZ3VvdXMgdmFsdWVzP1xuICAgICAgICAgICAgaWYgKChiYXJjb2RlQ29sdW1uQ291bnQuZ2V0VmFsdWUoKS5sZW5ndGggPT09IDApIHx8XG4gICAgICAgICAgICAgICAgKGJhcmNvZGVSb3dDb3VudFVwcGVyUGFydC5nZXRWYWx1ZSgpLmxlbmd0aCA9PT0gMCkgfHxcbiAgICAgICAgICAgICAgICAoYmFyY29kZVJvd0NvdW50TG93ZXJQYXJ0LmdldFZhbHVlKCkubGVuZ3RoID09PSAwKSB8fFxuICAgICAgICAgICAgICAgIChiYXJjb2RlRUNMZXZlbC5nZXRWYWx1ZSgpLmxlbmd0aCA9PT0gMCkgfHxcbiAgICAgICAgICAgICAgICBiYXJjb2RlQ29sdW1uQ291bnQuZ2V0VmFsdWUoKVswXSA8IDEgfHxcbiAgICAgICAgICAgICAgICBiYXJjb2RlUm93Q291bnRVcHBlclBhcnQuZ2V0VmFsdWUoKVswXSArIGJhcmNvZGVSb3dDb3VudExvd2VyUGFydC5nZXRWYWx1ZSgpWzBdIDwgUERGNDE3Q29tbW9uLk1JTl9ST1dTX0lOX0JBUkNPREUgfHxcbiAgICAgICAgICAgICAgICBiYXJjb2RlUm93Q291bnRVcHBlclBhcnQuZ2V0VmFsdWUoKVswXSArIGJhcmNvZGVSb3dDb3VudExvd2VyUGFydC5nZXRWYWx1ZSgpWzBdID4gUERGNDE3Q29tbW9uLk1BWF9ST1dTX0lOX0JBUkNPREUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBiYXJjb2RlTWV0YWRhdGEgPSBuZXcgQmFyY29kZU1ldGFkYXRhKGJhcmNvZGVDb2x1bW5Db3VudC5nZXRWYWx1ZSgpWzBdLCBiYXJjb2RlUm93Q291bnRVcHBlclBhcnQuZ2V0VmFsdWUoKVswXSwgYmFyY29kZVJvd0NvdW50TG93ZXJQYXJ0LmdldFZhbHVlKClbMF0sIGJhcmNvZGVFQ0xldmVsLmdldFZhbHVlKClbMF0pO1xuICAgICAgICAgICAgdGhpcy5yZW1vdmVJbmNvcnJlY3RDb2Rld29yZHMoY29kZXdvcmRzLCBiYXJjb2RlTWV0YWRhdGEpO1xuICAgICAgICAgICAgcmV0dXJuIGJhcmNvZGVNZXRhZGF0YTtcbiAgICAgICAgfVxuICAgICAgICByZW1vdmVJbmNvcnJlY3RDb2Rld29yZHMoY29kZXdvcmRzLCBiYXJjb2RlTWV0YWRhdGEpIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBjb2Rld29yZHMgd2hpY2ggZG8gbm90IG1hdGNoIHRoZSBtZXRhZGF0YVxuICAgICAgICAgICAgLy8gVE9ETyBNYXliZSB3ZSBzaG91bGQga2VlcCB0aGUgaW5jb3JyZWN0IGNvZGV3b3JkcyBmb3IgdGhlIHN0YXJ0IGFuZCBlbmQgcG9zaXRpb25zP1xuICAgICAgICAgICAgZm9yIChsZXQgY29kZXdvcmRSb3cgLyppbnQqLyA9IDA7IGNvZGV3b3JkUm93IDwgY29kZXdvcmRzLmxlbmd0aDsgY29kZXdvcmRSb3crKykge1xuICAgICAgICAgICAgICAgIGxldCBjb2Rld29yZCA9IGNvZGV3b3Jkc1tjb2Rld29yZFJvd107XG4gICAgICAgICAgICAgICAgaWYgKGNvZGV3b3Jkc1tjb2Rld29yZFJvd10gPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IHJvd0luZGljYXRvclZhbHVlID0gY29kZXdvcmQuZ2V0VmFsdWUoKSAlIDMwO1xuICAgICAgICAgICAgICAgIGxldCBjb2Rld29yZFJvd051bWJlciA9IGNvZGV3b3JkLmdldFJvd051bWJlcigpO1xuICAgICAgICAgICAgICAgIGlmIChjb2Rld29yZFJvd051bWJlciA+IGJhcmNvZGVNZXRhZGF0YS5nZXRSb3dDb3VudCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvZGV3b3Jkc1tjb2Rld29yZFJvd10gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9pc0xlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29kZXdvcmRSb3dOdW1iZXIgKz0gMjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3dpdGNoIChjb2Rld29yZFJvd051bWJlciAlIDMpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJvd0luZGljYXRvclZhbHVlICogMyArIDEgIT09IGJhcmNvZGVNZXRhZGF0YS5nZXRSb3dDb3VudFVwcGVyUGFydCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZXdvcmRzW2NvZGV3b3JkUm93XSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKE1hdGgudHJ1bmMocm93SW5kaWNhdG9yVmFsdWUgLyAzKSAhPT0gYmFyY29kZU1ldGFkYXRhLmdldEVycm9yQ29ycmVjdGlvbkxldmVsKCkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3dJbmRpY2F0b3JWYWx1ZSAlIDMgIT09IGJhcmNvZGVNZXRhZGF0YS5nZXRSb3dDb3VudExvd2VyUGFydCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZXdvcmRzW2NvZGV3b3JkUm93XSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJvd0luZGljYXRvclZhbHVlICsgMSAhPT0gYmFyY29kZU1ldGFkYXRhLmdldENvbHVtbkNvdW50KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2Rld29yZHNbY29kZXdvcmRSb3ddID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpc0xlZnQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5faXNMZWZ0O1xuICAgICAgICB9XG4gICAgICAgIC8vIEBPdmVycmlkZVxuICAgICAgICB0b1N0cmluZygpIHtcbiAgICAgICAgICAgIHJldHVybiAnSXNMZWZ0OiAnICsgdGhpcy5faXNMZWZ0ICsgJ1xcbicgKyBzdXBlci50b1N0cmluZygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAxMyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKipcbiAgICAgKiBAYXV0aG9yIEd1ZW50aGVyIEdyYXVcbiAgICAgKi9cbiAgICAvKmZpbmFsKi8gY2xhc3MgRGV0ZWN0aW9uUmVzdWx0IHtcbiAgICAgICAgY29uc3RydWN0b3IoYmFyY29kZU1ldGFkYXRhLCBib3VuZGluZ0JveCkge1xuICAgICAgICAgICAgLypmaW5hbCovIHRoaXMuQURKVVNUX1JPV19OVU1CRVJfU0tJUCA9IDI7XG4gICAgICAgICAgICB0aGlzLmJhcmNvZGVNZXRhZGF0YSA9IGJhcmNvZGVNZXRhZGF0YTtcbiAgICAgICAgICAgIHRoaXMuYmFyY29kZUNvbHVtbkNvdW50ID0gYmFyY29kZU1ldGFkYXRhLmdldENvbHVtbkNvdW50KCk7XG4gICAgICAgICAgICB0aGlzLmJvdW5kaW5nQm94ID0gYm91bmRpbmdCb3g7XG4gICAgICAgICAgICAvLyB0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnMgPSBuZXcgRGV0ZWN0aW9uUmVzdWx0Q29sdW1uW3RoaXMuYmFyY29kZUNvbHVtbkNvdW50ICsgMl07XG4gICAgICAgICAgICB0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnMgPSBuZXcgQXJyYXkodGhpcy5iYXJjb2RlQ29sdW1uQ291bnQgKyAyKTtcbiAgICAgICAgfVxuICAgICAgICBnZXREZXRlY3Rpb25SZXN1bHRDb2x1bW5zKCkge1xuICAgICAgICAgICAgdGhpcy5hZGp1c3RJbmRpY2F0b3JDb2x1bW5Sb3dOdW1iZXJzKHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1swXSk7XG4gICAgICAgICAgICB0aGlzLmFkanVzdEluZGljYXRvckNvbHVtblJvd051bWJlcnModGhpcy5kZXRlY3Rpb25SZXN1bHRDb2x1bW5zW3RoaXMuYmFyY29kZUNvbHVtbkNvdW50ICsgMV0pO1xuICAgICAgICAgICAgbGV0IHVuYWRqdXN0ZWRDb2Rld29yZENvdW50ID0gUERGNDE3Q29tbW9uLk1BWF9DT0RFV09SRFNfSU5fQkFSQ09ERTtcbiAgICAgICAgICAgIGxldCBwcmV2aW91c1VuYWRqdXN0ZWRDb3VudDtcbiAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICBwcmV2aW91c1VuYWRqdXN0ZWRDb3VudCA9IHVuYWRqdXN0ZWRDb2Rld29yZENvdW50O1xuICAgICAgICAgICAgICAgIHVuYWRqdXN0ZWRDb2Rld29yZENvdW50ID0gdGhpcy5hZGp1c3RSb3dOdW1iZXJzQW5kR2V0Q291bnQoKTtcbiAgICAgICAgICAgIH0gd2hpbGUgKHVuYWRqdXN0ZWRDb2Rld29yZENvdW50ID4gMCAmJiB1bmFkanVzdGVkQ29kZXdvcmRDb3VudCA8IHByZXZpb3VzVW5hZGp1c3RlZENvdW50KTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnM7XG4gICAgICAgIH1cbiAgICAgICAgYWRqdXN0SW5kaWNhdG9yQ29sdW1uUm93TnVtYmVycyhkZXRlY3Rpb25SZXN1bHRDb2x1bW4pIHtcbiAgICAgICAgICAgIGlmIChkZXRlY3Rpb25SZXN1bHRDb2x1bW4gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGRldGVjdGlvblJlc3VsdENvbHVtblxuICAgICAgICAgICAgICAgICAgICAuYWRqdXN0Q29tcGxldGVJbmRpY2F0b3JDb2x1bW5Sb3dOdW1iZXJzKHRoaXMuYmFyY29kZU1ldGFkYXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBUT0RPIGVuc3VyZSB0aGF0IG5vIGRldGVjdGVkIGNvZGV3b3JkcyB3aXRoIHVua25vd24gcm93IG51bWJlciBhcmUgbGVmdFxuICAgICAgICAvLyB3ZSBzaG91bGQgYmUgYWJsZSB0byBlc3RpbWF0ZSB0aGUgcm93IGhlaWdodCBhbmQgdXNlIGl0IGFzIGEgaGludCBmb3IgdGhlIHJvdyBudW1iZXJcbiAgICAgICAgLy8gd2Ugc2hvdWxkIGFsc28gZmlsbCB0aGUgcm93cyB0b3AgdG8gYm90dG9tIGFuZCBib3R0b20gdG8gdG9wXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIG51bWJlciBvZiBjb2Rld29yZHMgd2hpY2ggZG9uJ3QgaGF2ZSBhIHZhbGlkIHJvdyBudW1iZXIuIE5vdGUgdGhhdCB0aGUgY291bnQgaXMgbm90IGFjY3VyYXRlIGFzIGNvZGV3b3Jkc1xuICAgICAgICAgKiB3aWxsIGJlIGNvdW50ZWQgc2V2ZXJhbCB0aW1lcy4gSXQganVzdCBzZXJ2ZXMgYXMgYW4gaW5kaWNhdG9yIHRvIHNlZSB3aGVuIHdlIGNhbiBzdG9wIGFkanVzdGluZyByb3cgbnVtYmVyc1xuICAgICAgICAgKi9cbiAgICAgICAgYWRqdXN0Um93TnVtYmVyc0FuZEdldENvdW50KCkge1xuICAgICAgICAgICAgbGV0IHVuYWRqdXN0ZWRDb3VudCA9IHRoaXMuYWRqdXN0Um93TnVtYmVyc0J5Um93KCk7XG4gICAgICAgICAgICBpZiAodW5hZGp1c3RlZENvdW50ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBiYXJjb2RlQ29sdW1uIC8qaW50Ki8gPSAxOyBiYXJjb2RlQ29sdW1uIDwgdGhpcy5iYXJjb2RlQ29sdW1uQ291bnQgKyAxOyBiYXJjb2RlQ29sdW1uKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgY29kZXdvcmRzID0gdGhpcy5kZXRlY3Rpb25SZXN1bHRDb2x1bW5zW2JhcmNvZGVDb2x1bW5dLmdldENvZGV3b3JkcygpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGNvZGV3b3Jkc1JvdyAvKmludCovID0gMDsgY29kZXdvcmRzUm93IDwgY29kZXdvcmRzLmxlbmd0aDsgY29kZXdvcmRzUm93KyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvZGV3b3Jkc1tjb2Rld29yZHNSb3ddID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICghY29kZXdvcmRzW2NvZGV3b3Jkc1Jvd10uaGFzVmFsaWRSb3dOdW1iZXIoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGp1c3RSb3dOdW1iZXJzKGJhcmNvZGVDb2x1bW4sIGNvZGV3b3Jkc1JvdywgY29kZXdvcmRzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB1bmFkanVzdGVkQ291bnQ7XG4gICAgICAgIH1cbiAgICAgICAgYWRqdXN0Um93TnVtYmVyc0J5Um93KCkge1xuICAgICAgICAgICAgdGhpcy5hZGp1c3RSb3dOdW1iZXJzRnJvbUJvdGhSSSgpO1xuICAgICAgICAgICAgLy8gVE9ETyB3ZSBzaG91bGQgb25seSBkbyBmdWxsIHJvdyBhZGp1c3RtZW50cyBpZiByb3cgbnVtYmVycyBvZiBsZWZ0IGFuZCByaWdodCByb3cgaW5kaWNhdG9yIGNvbHVtbiBtYXRjaC5cbiAgICAgICAgICAgIC8vIE1heWJlIGl0J3MgZXZlbiBiZXR0ZXIgdG8gY2FsY3VsYXRlZCB0aGUgaGVpZ2h0IChyb3dzOiBkKSBhbmQgZGl2aWRlIGl0IGJ5IHRoZSBudW1iZXIgb2YgYmFyY29kZVxuICAgICAgICAgICAgLy8gcm93cy4gVGhpcywgdG9nZXRoZXIgd2l0aCB0aGUgTFJJIGFuZCBSUkkgcm93IG51bWJlcnMgc2hvdWxkIGFsbG93IHVzIHRvIGdldCBhIGdvb2QgZXN0aW1hdGUgd2hlcmUgYSByb3dcbiAgICAgICAgICAgIC8vIG51bWJlciBzdGFydHMgYW5kIGVuZHMuXG4gICAgICAgICAgICBsZXQgdW5hZGp1c3RlZENvdW50ID0gdGhpcy5hZGp1c3RSb3dOdW1iZXJzRnJvbUxSSSgpO1xuICAgICAgICAgICAgcmV0dXJuIHVuYWRqdXN0ZWRDb3VudCArIHRoaXMuYWRqdXN0Um93TnVtYmVyc0Zyb21SUkkoKTtcbiAgICAgICAgfVxuICAgICAgICBhZGp1c3RSb3dOdW1iZXJzRnJvbUJvdGhSSSgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbMF0gPT0gbnVsbCB8fCB0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbdGhpcy5iYXJjb2RlQ29sdW1uQ291bnQgKyAxXSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IExSSWNvZGV3b3JkcyA9IHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1swXS5nZXRDb2Rld29yZHMoKTtcbiAgICAgICAgICAgIGxldCBSUkljb2Rld29yZHMgPSB0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbdGhpcy5iYXJjb2RlQ29sdW1uQ291bnQgKyAxXS5nZXRDb2Rld29yZHMoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGNvZGV3b3Jkc1JvdyAvKmludCovID0gMDsgY29kZXdvcmRzUm93IDwgTFJJY29kZXdvcmRzLmxlbmd0aDsgY29kZXdvcmRzUm93KyspIHtcbiAgICAgICAgICAgICAgICBpZiAoTFJJY29kZXdvcmRzW2NvZGV3b3Jkc1Jvd10gIT0gbnVsbCAmJlxuICAgICAgICAgICAgICAgICAgICBSUkljb2Rld29yZHNbY29kZXdvcmRzUm93XSAhPSBudWxsICYmXG4gICAgICAgICAgICAgICAgICAgIExSSWNvZGV3b3Jkc1tjb2Rld29yZHNSb3ddLmdldFJvd051bWJlcigpID09PSBSUkljb2Rld29yZHNbY29kZXdvcmRzUm93XS5nZXRSb3dOdW1iZXIoKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBiYXJjb2RlQ29sdW1uIC8qaW50Ki8gPSAxOyBiYXJjb2RlQ29sdW1uIDw9IHRoaXMuYmFyY29kZUNvbHVtbkNvdW50OyBiYXJjb2RlQ29sdW1uKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjb2Rld29yZCA9IHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1tiYXJjb2RlQ29sdW1uXS5nZXRDb2Rld29yZHMoKVtjb2Rld29yZHNSb3ddO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvZGV3b3JkID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGV3b3JkLnNldFJvd051bWJlcihMUkljb2Rld29yZHNbY29kZXdvcmRzUm93XS5nZXRSb3dOdW1iZXIoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvZGV3b3JkLmhhc1ZhbGlkUm93TnVtYmVyKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbYmFyY29kZUNvbHVtbl0uZ2V0Q29kZXdvcmRzKClbY29kZXdvcmRzUm93XSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYWRqdXN0Um93TnVtYmVyc0Zyb21SUkkoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5kZXRlY3Rpb25SZXN1bHRDb2x1bW5zW3RoaXMuYmFyY29kZUNvbHVtbkNvdW50ICsgMV0gPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHVuYWRqdXN0ZWRDb3VudCA9IDA7XG4gICAgICAgICAgICBsZXQgY29kZXdvcmRzID0gdGhpcy5kZXRlY3Rpb25SZXN1bHRDb2x1bW5zW3RoaXMuYmFyY29kZUNvbHVtbkNvdW50ICsgMV0uZ2V0Q29kZXdvcmRzKCk7XG4gICAgICAgICAgICBmb3IgKGxldCBjb2Rld29yZHNSb3cgLyppbnQqLyA9IDA7IGNvZGV3b3Jkc1JvdyA8IGNvZGV3b3Jkcy5sZW5ndGg7IGNvZGV3b3Jkc1JvdysrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvZGV3b3Jkc1tjb2Rld29yZHNSb3ddID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCByb3dJbmRpY2F0b3JSb3dOdW1iZXIgPSBjb2Rld29yZHNbY29kZXdvcmRzUm93XS5nZXRSb3dOdW1iZXIoKTtcbiAgICAgICAgICAgICAgICBsZXQgaW52YWxpZFJvd0NvdW50cyA9IDA7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgYmFyY29kZUNvbHVtbiAvKmludCovID0gdGhpcy5iYXJjb2RlQ29sdW1uQ291bnQgKyAxOyBiYXJjb2RlQ29sdW1uID4gMCAmJiBpbnZhbGlkUm93Q291bnRzIDwgdGhpcy5BREpVU1RfUk9XX05VTUJFUl9TS0lQOyBiYXJjb2RlQ29sdW1uLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNvZGV3b3JkID0gdGhpcy5kZXRlY3Rpb25SZXN1bHRDb2x1bW5zW2JhcmNvZGVDb2x1bW5dLmdldENvZGV3b3JkcygpW2NvZGV3b3Jkc1Jvd107XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb2Rld29yZCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnZhbGlkUm93Q291bnRzID0gRGV0ZWN0aW9uUmVzdWx0LmFkanVzdFJvd051bWJlcklmVmFsaWQocm93SW5kaWNhdG9yUm93TnVtYmVyLCBpbnZhbGlkUm93Q291bnRzLCBjb2Rld29yZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvZGV3b3JkLmhhc1ZhbGlkUm93TnVtYmVyKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmFkanVzdGVkQ291bnQrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB1bmFkanVzdGVkQ291bnQ7XG4gICAgICAgIH1cbiAgICAgICAgYWRqdXN0Um93TnVtYmVyc0Zyb21MUkkoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5kZXRlY3Rpb25SZXN1bHRDb2x1bW5zWzBdID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCB1bmFkanVzdGVkQ291bnQgPSAwO1xuICAgICAgICAgICAgbGV0IGNvZGV3b3JkcyA9IHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1swXS5nZXRDb2Rld29yZHMoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGNvZGV3b3Jkc1JvdyAvKmludCovID0gMDsgY29kZXdvcmRzUm93IDwgY29kZXdvcmRzLmxlbmd0aDsgY29kZXdvcmRzUm93KyspIHtcbiAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmRzW2NvZGV3b3Jkc1Jvd10gPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IHJvd0luZGljYXRvclJvd051bWJlciA9IGNvZGV3b3Jkc1tjb2Rld29yZHNSb3ddLmdldFJvd051bWJlcigpO1xuICAgICAgICAgICAgICAgIGxldCBpbnZhbGlkUm93Q291bnRzID0gMDtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBiYXJjb2RlQ29sdW1uIC8qaW50Ki8gPSAxOyBiYXJjb2RlQ29sdW1uIDwgdGhpcy5iYXJjb2RlQ29sdW1uQ291bnQgKyAxICYmIGludmFsaWRSb3dDb3VudHMgPCB0aGlzLkFESlVTVF9ST1dfTlVNQkVSX1NLSVA7IGJhcmNvZGVDb2x1bW4rKykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgY29kZXdvcmQgPSB0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbYmFyY29kZUNvbHVtbl0uZ2V0Q29kZXdvcmRzKClbY29kZXdvcmRzUm93XTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvZGV3b3JkICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGludmFsaWRSb3dDb3VudHMgPSBEZXRlY3Rpb25SZXN1bHQuYWRqdXN0Um93TnVtYmVySWZWYWxpZChyb3dJbmRpY2F0b3JSb3dOdW1iZXIsIGludmFsaWRSb3dDb3VudHMsIGNvZGV3b3JkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29kZXdvcmQuaGFzVmFsaWRSb3dOdW1iZXIoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuYWRqdXN0ZWRDb3VudCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHVuYWRqdXN0ZWRDb3VudDtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgYWRqdXN0Um93TnVtYmVySWZWYWxpZChyb3dJbmRpY2F0b3JSb3dOdW1iZXIsIGludmFsaWRSb3dDb3VudHMsIGNvZGV3b3JkKSB7XG4gICAgICAgICAgICBpZiAoY29kZXdvcmQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpbnZhbGlkUm93Q291bnRzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFjb2Rld29yZC5oYXNWYWxpZFJvd051bWJlcigpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvZGV3b3JkLmlzVmFsaWRSb3dOdW1iZXIocm93SW5kaWNhdG9yUm93TnVtYmVyKSkge1xuICAgICAgICAgICAgICAgICAgICBjb2Rld29yZC5zZXRSb3dOdW1iZXIocm93SW5kaWNhdG9yUm93TnVtYmVyKTtcbiAgICAgICAgICAgICAgICAgICAgaW52YWxpZFJvd0NvdW50cyA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICArK2ludmFsaWRSb3dDb3VudHM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGludmFsaWRSb3dDb3VudHM7XG4gICAgICAgIH1cbiAgICAgICAgYWRqdXN0Um93TnVtYmVycyhiYXJjb2RlQ29sdW1uLCBjb2Rld29yZHNSb3csIGNvZGV3b3Jkcykge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbYmFyY29kZUNvbHVtbiAtIDFdKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGNvZGV3b3JkID0gY29kZXdvcmRzW2NvZGV3b3Jkc1Jvd107XG4gICAgICAgICAgICBsZXQgcHJldmlvdXNDb2x1bW5Db2Rld29yZHMgPSB0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbYmFyY29kZUNvbHVtbiAtIDFdLmdldENvZGV3b3JkcygpO1xuICAgICAgICAgICAgbGV0IG5leHRDb2x1bW5Db2Rld29yZHMgPSBwcmV2aW91c0NvbHVtbkNvZGV3b3JkcztcbiAgICAgICAgICAgIGlmICh0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbYmFyY29kZUNvbHVtbiArIDFdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBuZXh0Q29sdW1uQ29kZXdvcmRzID0gdGhpcy5kZXRlY3Rpb25SZXN1bHRDb2x1bW5zW2JhcmNvZGVDb2x1bW4gKyAxXS5nZXRDb2Rld29yZHMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGxldCBvdGhlckNvZGV3b3JkczogQ29kZXdvcmRbXSA9IG5ldyBDb2Rld29yZFsxNF07XG4gICAgICAgICAgICBsZXQgb3RoZXJDb2Rld29yZHMgPSBuZXcgQXJyYXkoMTQpO1xuICAgICAgICAgICAgb3RoZXJDb2Rld29yZHNbMl0gPSBwcmV2aW91c0NvbHVtbkNvZGV3b3Jkc1tjb2Rld29yZHNSb3ddO1xuICAgICAgICAgICAgb3RoZXJDb2Rld29yZHNbM10gPSBuZXh0Q29sdW1uQ29kZXdvcmRzW2NvZGV3b3Jkc1Jvd107XG4gICAgICAgICAgICBpZiAoY29kZXdvcmRzUm93ID4gMCkge1xuICAgICAgICAgICAgICAgIG90aGVyQ29kZXdvcmRzWzBdID0gY29kZXdvcmRzW2NvZGV3b3Jkc1JvdyAtIDFdO1xuICAgICAgICAgICAgICAgIG90aGVyQ29kZXdvcmRzWzRdID0gcHJldmlvdXNDb2x1bW5Db2Rld29yZHNbY29kZXdvcmRzUm93IC0gMV07XG4gICAgICAgICAgICAgICAgb3RoZXJDb2Rld29yZHNbNV0gPSBuZXh0Q29sdW1uQ29kZXdvcmRzW2NvZGV3b3Jkc1JvdyAtIDFdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvZGV3b3Jkc1JvdyA+IDEpIHtcbiAgICAgICAgICAgICAgICBvdGhlckNvZGV3b3Jkc1s4XSA9IGNvZGV3b3Jkc1tjb2Rld29yZHNSb3cgLSAyXTtcbiAgICAgICAgICAgICAgICBvdGhlckNvZGV3b3Jkc1sxMF0gPSBwcmV2aW91c0NvbHVtbkNvZGV3b3Jkc1tjb2Rld29yZHNSb3cgLSAyXTtcbiAgICAgICAgICAgICAgICBvdGhlckNvZGV3b3Jkc1sxMV0gPSBuZXh0Q29sdW1uQ29kZXdvcmRzW2NvZGV3b3Jkc1JvdyAtIDJdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvZGV3b3Jkc1JvdyA8IGNvZGV3b3Jkcy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAgICAgb3RoZXJDb2Rld29yZHNbMV0gPSBjb2Rld29yZHNbY29kZXdvcmRzUm93ICsgMV07XG4gICAgICAgICAgICAgICAgb3RoZXJDb2Rld29yZHNbNl0gPSBwcmV2aW91c0NvbHVtbkNvZGV3b3Jkc1tjb2Rld29yZHNSb3cgKyAxXTtcbiAgICAgICAgICAgICAgICBvdGhlckNvZGV3b3Jkc1s3XSA9IG5leHRDb2x1bW5Db2Rld29yZHNbY29kZXdvcmRzUm93ICsgMV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29kZXdvcmRzUm93IDwgY29kZXdvcmRzLmxlbmd0aCAtIDIpIHtcbiAgICAgICAgICAgICAgICBvdGhlckNvZGV3b3Jkc1s5XSA9IGNvZGV3b3Jkc1tjb2Rld29yZHNSb3cgKyAyXTtcbiAgICAgICAgICAgICAgICBvdGhlckNvZGV3b3Jkc1sxMl0gPSBwcmV2aW91c0NvbHVtbkNvZGV3b3Jkc1tjb2Rld29yZHNSb3cgKyAyXTtcbiAgICAgICAgICAgICAgICBvdGhlckNvZGV3b3Jkc1sxM10gPSBuZXh0Q29sdW1uQ29kZXdvcmRzW2NvZGV3b3Jkc1JvdyArIDJdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgb3RoZXJDb2Rld29yZCBvZiBvdGhlckNvZGV3b3Jkcykge1xuICAgICAgICAgICAgICAgIGlmIChEZXRlY3Rpb25SZXN1bHQuYWRqdXN0Um93TnVtYmVyKGNvZGV3b3JkLCBvdGhlckNvZGV3b3JkKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHRydWUsIGlmIHJvdyBudW1iZXIgd2FzIGFkanVzdGVkLCBmYWxzZSBvdGhlcndpc2VcbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBhZGp1c3RSb3dOdW1iZXIoY29kZXdvcmQsIG90aGVyQ29kZXdvcmQpIHtcbiAgICAgICAgICAgIGlmIChvdGhlckNvZGV3b3JkID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob3RoZXJDb2Rld29yZC5oYXNWYWxpZFJvd051bWJlcigpICYmIG90aGVyQ29kZXdvcmQuZ2V0QnVja2V0KCkgPT09IGNvZGV3b3JkLmdldEJ1Y2tldCgpKSB7XG4gICAgICAgICAgICAgICAgY29kZXdvcmQuc2V0Um93TnVtYmVyKG90aGVyQ29kZXdvcmQuZ2V0Um93TnVtYmVyKCkpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGdldEJhcmNvZGVDb2x1bW5Db3VudCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJhcmNvZGVDb2x1bW5Db3VudDtcbiAgICAgICAgfVxuICAgICAgICBnZXRCYXJjb2RlUm93Q291bnQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5iYXJjb2RlTWV0YWRhdGEuZ2V0Um93Q291bnQoKTtcbiAgICAgICAgfVxuICAgICAgICBnZXRCYXJjb2RlRUNMZXZlbCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJhcmNvZGVNZXRhZGF0YS5nZXRFcnJvckNvcnJlY3Rpb25MZXZlbCgpO1xuICAgICAgICB9XG4gICAgICAgIHNldEJvdW5kaW5nQm94KGJvdW5kaW5nQm94KSB7XG4gICAgICAgICAgICB0aGlzLmJvdW5kaW5nQm94ID0gYm91bmRpbmdCb3g7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Qm91bmRpbmdCb3goKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ib3VuZGluZ0JveDtcbiAgICAgICAgfVxuICAgICAgICBzZXREZXRlY3Rpb25SZXN1bHRDb2x1bW4oYmFyY29kZUNvbHVtbiwgZGV0ZWN0aW9uUmVzdWx0Q29sdW1uKSB7XG4gICAgICAgICAgICB0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbYmFyY29kZUNvbHVtbl0gPSBkZXRlY3Rpb25SZXN1bHRDb2x1bW47XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RGV0ZWN0aW9uUmVzdWx0Q29sdW1uKGJhcmNvZGVDb2x1bW4pIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRldGVjdGlvblJlc3VsdENvbHVtbnNbYmFyY29kZUNvbHVtbl07XG4gICAgICAgIH1cbiAgICAgICAgLy8gQE92ZXJyaWRlXG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgbGV0IHJvd0luZGljYXRvckNvbHVtbiA9IHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1swXTtcbiAgICAgICAgICAgIGlmIChyb3dJbmRpY2F0b3JDb2x1bW4gPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJvd0luZGljYXRvckNvbHVtbiA9IHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1t0aGlzLmJhcmNvZGVDb2x1bW5Db3VudCArIDFdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gdHJ5IChcbiAgICAgICAgICAgIGxldCBmb3JtYXR0ZXIgPSBuZXcgRm9ybWF0dGVyKCk7XG4gICAgICAgICAgICAvLyApIHtcbiAgICAgICAgICAgIGZvciAobGV0IGNvZGV3b3Jkc1JvdyAvKmludCovID0gMDsgY29kZXdvcmRzUm93IDwgcm93SW5kaWNhdG9yQ29sdW1uLmdldENvZGV3b3JkcygpLmxlbmd0aDsgY29kZXdvcmRzUm93KyspIHtcbiAgICAgICAgICAgICAgICBmb3JtYXR0ZXIuZm9ybWF0KCdDVyAlM2Q6JywgY29kZXdvcmRzUm93KTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBiYXJjb2RlQ29sdW1uIC8qaW50Ki8gPSAwOyBiYXJjb2RlQ29sdW1uIDwgdGhpcy5iYXJjb2RlQ29sdW1uQ291bnQgKyAyOyBiYXJjb2RlQ29sdW1uKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGV0ZWN0aW9uUmVzdWx0Q29sdW1uc1tiYXJjb2RlQ29sdW1uXSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXR0ZXIuZm9ybWF0KCcgICAgfCAgICcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbGV0IGNvZGV3b3JkID0gdGhpcy5kZXRlY3Rpb25SZXN1bHRDb2x1bW5zW2JhcmNvZGVDb2x1bW5dLmdldENvZGV3b3JkcygpW2NvZGV3b3Jkc1Jvd107XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb2Rld29yZCA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXR0ZXIuZm9ybWF0KCcgICAgfCAgICcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZm9ybWF0dGVyLmZvcm1hdCgnICUzZHwlM2QnLCBjb2Rld29yZC5nZXRSb3dOdW1iZXIoKSwgY29kZXdvcmQuZ2V0VmFsdWUoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvcm1hdHRlci5mb3JtYXQoJyVuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZm9ybWF0dGVyLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAvLyB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDEzIFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8vIHBhY2thZ2UgY29tLmdvb2dsZS56eGluZy5wZGY0MTcuZGVjb2RlcjtcbiAgICAvKipcbiAgICAgKiBAYXV0aG9yIEd1ZW50aGVyIEdyYXVcbiAgICAgKi9cbiAgICAvKmZpbmFsKi8gY2xhc3MgQ29kZXdvcmQge1xuICAgICAgICBjb25zdHJ1Y3RvcihzdGFydFgsIGVuZFgsIGJ1Y2tldCwgdmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMucm93TnVtYmVyID0gQ29kZXdvcmQuQkFSQ09ERV9ST1dfVU5LTk9XTjtcbiAgICAgICAgICAgIHRoaXMuc3RhcnRYID0gTWF0aC50cnVuYyhzdGFydFgpO1xuICAgICAgICAgICAgdGhpcy5lbmRYID0gTWF0aC50cnVuYyhlbmRYKTtcbiAgICAgICAgICAgIHRoaXMuYnVja2V0ID0gTWF0aC50cnVuYyhidWNrZXQpO1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9IE1hdGgudHJ1bmModmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIGhhc1ZhbGlkUm93TnVtYmVyKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaXNWYWxpZFJvd051bWJlcih0aGlzLnJvd051bWJlcik7XG4gICAgICAgIH1cbiAgICAgICAgaXNWYWxpZFJvd051bWJlcihyb3dOdW1iZXIpIHtcbiAgICAgICAgICAgIHJldHVybiByb3dOdW1iZXIgIT09IENvZGV3b3JkLkJBUkNPREVfUk9XX1VOS05PV04gJiYgdGhpcy5idWNrZXQgPT09IChyb3dOdW1iZXIgJSAzKSAqIDM7XG4gICAgICAgIH1cbiAgICAgICAgc2V0Um93TnVtYmVyQXNSb3dJbmRpY2F0b3JDb2x1bW4oKSB7XG4gICAgICAgICAgICB0aGlzLnJvd051bWJlciA9IE1hdGgudHJ1bmMoKE1hdGgudHJ1bmModGhpcy52YWx1ZSAvIDMwKSkgKiAzICsgTWF0aC50cnVuYyh0aGlzLmJ1Y2tldCAvIDMpKTtcbiAgICAgICAgfVxuICAgICAgICBnZXRXaWR0aCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVuZFggLSB0aGlzLnN0YXJ0WDtcbiAgICAgICAgfVxuICAgICAgICBnZXRTdGFydFgoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zdGFydFg7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RW5kWCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVuZFg7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0QnVja2V0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYnVja2V0O1xuICAgICAgICB9XG4gICAgICAgIGdldFZhbHVlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0Um93TnVtYmVyKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucm93TnVtYmVyO1xuICAgICAgICB9XG4gICAgICAgIHNldFJvd051bWJlcihyb3dOdW1iZXIpIHtcbiAgICAgICAgICAgIHRoaXMucm93TnVtYmVyID0gcm93TnVtYmVyO1xuICAgICAgICB9XG4gICAgICAgIC8vICAgQE92ZXJyaWRlXG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucm93TnVtYmVyICsgJ3wnICsgdGhpcy52YWx1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBDb2Rld29yZC5CQVJDT0RFX1JPV19VTktOT1dOID0gLTE7XG5cbiAgICAvKlxuICAgICogQ29weXJpZ2h0IDIwMTMgWlhpbmcgYXV0aG9yc1xuICAgICpcbiAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAqXG4gICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICpcbiAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgKi9cbiAgICAvKipcbiAgICAgKiBAYXV0aG9yIEd1ZW50aGVyIEdyYXVcbiAgICAgKiBAYXV0aG9yIGNyZWF0YWxlIEdtYkggKGNocmlzdG9waC5zY2h1bHpAY3JlYXRhbGUuZGUpXG4gICAgICovXG4gICAgLypmaW5hbCovIGNsYXNzIFBERjQxN0NvZGV3b3JkRGVjb2RlciB7XG4gICAgICAgIC8qIEBub3RlXG4gICAgICAgICAqIHRoaXMgYWN0aW9uIGhhdmUgdG8gYmUgcGVyZm9ybWVkIGJlZm9yZSBmaXJzdCB1c2Ugb2YgY2xhc3NcbiAgICAgICAgICogLSBzdGF0aWMgY29uc3RydWN0b3JcbiAgICAgICAgICogd29ya2luZyB3aXRoIDMyYml0IGZsb2F0IChiYXNlZCBmcm9tIEphdmEgbG9naWMpXG4gICAgICAgICovXG4gICAgICAgIHN0YXRpYyBpbml0aWFsaXplKCkge1xuICAgICAgICAgICAgLy8gUHJlLWNvbXB1dGVzIHRoZSBzeW1ib2wgcmF0aW8gdGFibGUuXG4gICAgICAgICAgICBmb3IgKCAvKmludCovbGV0IGkgPSAwOyBpIDwgUERGNDE3Q29tbW9uLlNZTUJPTF9UQUJMRS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCBjdXJyZW50U3ltYm9sID0gUERGNDE3Q29tbW9uLlNZTUJPTF9UQUJMRVtpXTtcbiAgICAgICAgICAgICAgICBsZXQgY3VycmVudEJpdCA9IGN1cnJlbnRTeW1ib2wgJiAweDE7XG4gICAgICAgICAgICAgICAgZm9yICggLyppbnQqL2xldCBqID0gMDsgaiA8IFBERjQxN0NvbW1vbi5CQVJTX0lOX01PRFVMRTsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBzaXplID0gMC4wO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoKGN1cnJlbnRTeW1ib2wgJiAweDEpID09PSBjdXJyZW50Qml0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaXplICs9IDEuMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTeW1ib2wgPj49IDE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEJpdCA9IGN1cnJlbnRTeW1ib2wgJiAweDE7XG4gICAgICAgICAgICAgICAgICAgIGlmICghUERGNDE3Q29kZXdvcmREZWNvZGVyLlJBVElPU19UQUJMRVtpXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgUERGNDE3Q29kZXdvcmREZWNvZGVyLlJBVElPU19UQUJMRVtpXSA9IG5ldyBBcnJheShQREY0MTdDb21tb24uQkFSU19JTl9NT0RVTEUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIFBERjQxN0NvZGV3b3JkRGVjb2Rlci5SQVRJT1NfVEFCTEVbaV1bUERGNDE3Q29tbW9uLkJBUlNfSU5fTU9EVUxFIC0gaiAtIDFdID0gTWF0aC5mcm91bmQoc2l6ZSAvIFBERjQxN0NvbW1vbi5NT0RVTEVTX0lOX0NPREVXT1JEKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmJTeW1ib2xUYWJsZVJlYWR5ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZ2V0RGVjb2RlZFZhbHVlKG1vZHVsZUJpdENvdW50KSB7XG4gICAgICAgICAgICBsZXQgZGVjb2RlZFZhbHVlID0gUERGNDE3Q29kZXdvcmREZWNvZGVyLmdldERlY29kZWRDb2Rld29yZFZhbHVlKFBERjQxN0NvZGV3b3JkRGVjb2Rlci5zYW1wbGVCaXRDb3VudHMobW9kdWxlQml0Q291bnQpKTtcbiAgICAgICAgICAgIGlmIChkZWNvZGVkVmFsdWUgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRlY29kZWRWYWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBQREY0MTdDb2Rld29yZERlY29kZXIuZ2V0Q2xvc2VzdERlY29kZWRWYWx1ZShtb2R1bGVCaXRDb3VudCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHNhbXBsZUJpdENvdW50cyhtb2R1bGVCaXRDb3VudCkge1xuICAgICAgICAgICAgbGV0IGJpdENvdW50U3VtID0gTWF0aFV0aWxzLnN1bShtb2R1bGVCaXRDb3VudCk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gbmV3IEludDMyQXJyYXkoUERGNDE3Q29tbW9uLkJBUlNfSU5fTU9EVUxFKTtcbiAgICAgICAgICAgIGxldCBiaXRDb3VudEluZGV4ID0gMDtcbiAgICAgICAgICAgIGxldCBzdW1QcmV2aW91c0JpdHMgPSAwO1xuICAgICAgICAgICAgZm9yICggLyppbnQqL2xldCBpID0gMDsgaSA8IFBERjQxN0NvbW1vbi5NT0RVTEVTX0lOX0NPREVXT1JEOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgc2FtcGxlSW5kZXggPSBiaXRDb3VudFN1bSAvICgyICogUERGNDE3Q29tbW9uLk1PRFVMRVNfSU5fQ09ERVdPUkQpICtcbiAgICAgICAgICAgICAgICAgICAgKGkgKiBiaXRDb3VudFN1bSkgLyBQREY0MTdDb21tb24uTU9EVUxFU19JTl9DT0RFV09SRDtcbiAgICAgICAgICAgICAgICBpZiAoc3VtUHJldmlvdXNCaXRzICsgbW9kdWxlQml0Q291bnRbYml0Q291bnRJbmRleF0gPD0gc2FtcGxlSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgc3VtUHJldmlvdXNCaXRzICs9IG1vZHVsZUJpdENvdW50W2JpdENvdW50SW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICBiaXRDb3VudEluZGV4Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc3VsdFtiaXRDb3VudEluZGV4XSsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZ2V0RGVjb2RlZENvZGV3b3JkVmFsdWUobW9kdWxlQml0Q291bnQpIHtcbiAgICAgICAgICAgIGxldCBkZWNvZGVkVmFsdWUgPSBQREY0MTdDb2Rld29yZERlY29kZXIuZ2V0Qml0VmFsdWUobW9kdWxlQml0Q291bnQpO1xuICAgICAgICAgICAgcmV0dXJuIFBERjQxN0NvbW1vbi5nZXRDb2Rld29yZChkZWNvZGVkVmFsdWUpID09PSAtMSA/IC0xIDogZGVjb2RlZFZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXRCaXRWYWx1ZShtb2R1bGVCaXRDb3VudCkge1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IC8qbG9uZyovIDA7XG4gICAgICAgICAgICBmb3IgKGxldCAvKmludCovIGkgPSAwOyBpIDwgbW9kdWxlQml0Q291bnQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKCAvKmludCovbGV0IGJpdCA9IDA7IGJpdCA8IG1vZHVsZUJpdENvdW50W2ldOyBiaXQrKykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSAocmVzdWx0IDw8IDEpIHwgKGkgJSAyID09PSAwID8gMSA6IDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBNYXRoLnRydW5jKHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gd29ya2luZyB3aXRoIDMyYml0IGZsb2F0IChhcyBpbiBKYXZhKVxuICAgICAgICBzdGF0aWMgZ2V0Q2xvc2VzdERlY29kZWRWYWx1ZShtb2R1bGVCaXRDb3VudCkge1xuICAgICAgICAgICAgbGV0IGJpdENvdW50U3VtID0gTWF0aFV0aWxzLnN1bShtb2R1bGVCaXRDb3VudCk7XG4gICAgICAgICAgICBsZXQgYml0Q291bnRSYXRpb3MgPSBuZXcgQXJyYXkoUERGNDE3Q29tbW9uLkJBUlNfSU5fTU9EVUxFKTtcbiAgICAgICAgICAgIGlmIChiaXRDb3VudFN1bSA+IDEpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCAvKmludCovIGkgPSAwOyBpIDwgYml0Q291bnRSYXRpb3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgYml0Q291bnRSYXRpb3NbaV0gPSBNYXRoLmZyb3VuZChtb2R1bGVCaXRDb3VudFtpXSAvIGJpdENvdW50U3VtKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgYmVzdE1hdGNoRXJyb3IgPSBGbG9hdC5NQVhfVkFMVUU7XG4gICAgICAgICAgICBsZXQgYmVzdE1hdGNoID0gLTE7XG4gICAgICAgICAgICBpZiAoIXRoaXMuYlN5bWJvbFRhYmxlUmVhZHkpIHtcbiAgICAgICAgICAgICAgICBQREY0MTdDb2Rld29yZERlY29kZXIuaW5pdGlhbGl6ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yICggLyppbnQqL2xldCBqID0gMDsgaiA8IFBERjQxN0NvZGV3b3JkRGVjb2Rlci5SQVRJT1NfVEFCTEUubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgZXJyb3IgPSAwLjA7XG4gICAgICAgICAgICAgICAgbGV0IHJhdGlvVGFibGVSb3cgPSBQREY0MTdDb2Rld29yZERlY29kZXIuUkFUSU9TX1RBQkxFW2pdO1xuICAgICAgICAgICAgICAgIGZvciAoIC8qaW50Ki9sZXQgayA9IDA7IGsgPCBQREY0MTdDb21tb24uQkFSU19JTl9NT0RVTEU7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgZGlmZiA9IE1hdGguZnJvdW5kKHJhdGlvVGFibGVSb3dba10gLSBiaXRDb3VudFJhdGlvc1trXSk7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yICs9IE1hdGguZnJvdW5kKGRpZmYgKiBkaWZmKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yID49IGJlc3RNYXRjaEVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IgPCBiZXN0TWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBiZXN0TWF0Y2hFcnJvciA9IGVycm9yO1xuICAgICAgICAgICAgICAgICAgICBiZXN0TWF0Y2ggPSBQREY0MTdDb21tb24uU1lNQk9MX1RBQkxFW2pdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBiZXN0TWF0Y2g7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gZmxhZyB0aGF0IHRoZSB0YWJsZSBpcyByZWFkeSBmb3IgdXNlXG4gICAgUERGNDE3Q29kZXdvcmREZWNvZGVyLmJTeW1ib2xUYWJsZVJlYWR5ID0gZmFsc2U7XG4gICAgUERGNDE3Q29kZXdvcmREZWNvZGVyLlJBVElPU19UQUJMRSA9IG5ldyBBcnJheShQREY0MTdDb21tb24uU1lNQk9MX1RBQkxFLmxlbmd0aCkubWFwKHggPT4geCA9IG5ldyBBcnJheShQREY0MTdDb21tb24uQkFSU19JTl9NT0RVTEUpKTtcblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMTMgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLy8gcGFja2FnZSBjb20uZ29vZ2xlLnp4aW5nLnBkZjQxNztcbiAgICAvKipcbiAgICAgKiBAYXV0aG9yIEd1ZW50aGVyIEdyYXVcbiAgICAgKi9cbiAgICAvKnB1YmxpYyBmaW5hbCovIGNsYXNzIFBERjQxN1Jlc3VsdE1ldGFkYXRhIHtcbiAgICAgICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgICAgICB0aGlzLnNlZ21lbnRDb3VudCA9IC0xO1xuICAgICAgICAgICAgdGhpcy5maWxlU2l6ZSA9IC0xO1xuICAgICAgICAgICAgdGhpcy50aW1lc3RhbXAgPSAtMTtcbiAgICAgICAgICAgIHRoaXMuY2hlY2tzdW0gPSAtMTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogVGhlIFNlZ21lbnQgSUQgcmVwcmVzZW50cyB0aGUgc2VnbWVudCBvZiB0aGUgd2hvbGUgZmlsZSBkaXN0cmlidXRlZCBvdmVyIGRpZmZlcmVudCBzeW1ib2xzLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIEZpbGUgc2VnbWVudCBpbmRleFxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0U2VnbWVudEluZGV4KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2VnbWVudEluZGV4O1xuICAgICAgICB9XG4gICAgICAgIHNldFNlZ21lbnRJbmRleChzZWdtZW50SW5kZXgpIHtcbiAgICAgICAgICAgIHRoaXMuc2VnbWVudEluZGV4ID0gc2VnbWVudEluZGV4O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJcyB0aGUgc2FtZSBmb3IgZWFjaCByZWxhdGVkIFBERjQxNyBzeW1ib2xcbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiBGaWxlIElEXG4gICAgICAgICAqL1xuICAgICAgICBnZXRGaWxlSWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5maWxlSWQ7XG4gICAgICAgIH1cbiAgICAgICAgc2V0RmlsZUlkKGZpbGVJZCkge1xuICAgICAgICAgICAgdGhpcy5maWxlSWQgPSBmaWxlSWQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gYWx3YXlzIG51bGxcbiAgICAgICAgICogQGRlcHJlY2F0ZWQgdXNlIGRlZGljYXRlZCBhbHJlYWR5IHBhcnNlZCBmaWVsZHNcbiAgICAgICAgICovXG4gICAgICAgIC8vICAgQERlcHJlY2F0ZWRcbiAgICAgICAgZ2V0T3B0aW9uYWxEYXRhKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMub3B0aW9uYWxEYXRhO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gb3B0aW9uYWxEYXRhIG9sZCBvcHRpb25hbCBkYXRhIGZvcm1hdCBhcyBpbnQgYXJyYXlcbiAgICAgICAgICogQGRlcHJlY2F0ZWQgcGFyc2UgYW5kIHVzZSBuZXcgZmllbGRzXG4gICAgICAgICAqL1xuICAgICAgICAvLyAgIEBEZXByZWNhdGVkXG4gICAgICAgIHNldE9wdGlvbmFsRGF0YShvcHRpb25hbERhdGEpIHtcbiAgICAgICAgICAgIHRoaXMub3B0aW9uYWxEYXRhID0gb3B0aW9uYWxEYXRhO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHRydWUgaWYgaXQgaXMgdGhlIGxhc3Qgc2VnbWVudFxuICAgICAgICAgKi9cbiAgICAgICAgaXNMYXN0U2VnbWVudCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxhc3RTZWdtZW50O1xuICAgICAgICB9XG4gICAgICAgIHNldExhc3RTZWdtZW50KGxhc3RTZWdtZW50KSB7XG4gICAgICAgICAgICB0aGlzLmxhc3RTZWdtZW50ID0gbGFzdFNlZ21lbnQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gY291bnQgb2Ygc2VnbWVudHMsIC0xIGlmIG5vdCBzZXRcbiAgICAgICAgICovXG4gICAgICAgIGdldFNlZ21lbnRDb3VudCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNlZ21lbnRDb3VudDtcbiAgICAgICAgfVxuICAgICAgICBzZXRTZWdtZW50Q291bnQoc2VnbWVudENvdW50IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHRoaXMuc2VnbWVudENvdW50ID0gc2VnbWVudENvdW50O1xuICAgICAgICB9XG4gICAgICAgIGdldFNlbmRlcigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNlbmRlciB8fCBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHNldFNlbmRlcihzZW5kZXIpIHtcbiAgICAgICAgICAgIHRoaXMuc2VuZGVyID0gc2VuZGVyO1xuICAgICAgICB9XG4gICAgICAgIGdldEFkZHJlc3NlZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmFkZHJlc3NlZSB8fCBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHNldEFkZHJlc3NlZShhZGRyZXNzZWUpIHtcbiAgICAgICAgICAgIHRoaXMuYWRkcmVzc2VlID0gYWRkcmVzc2VlO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBGaWxlbmFtZSBvZiB0aGUgZW5jb2RlZCBmaWxlXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gZmlsZW5hbWVcbiAgICAgICAgICovXG4gICAgICAgIGdldEZpbGVOYW1lKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmlsZU5hbWU7XG4gICAgICAgIH1cbiAgICAgICAgc2V0RmlsZU5hbWUoZmlsZU5hbWUpIHtcbiAgICAgICAgICAgIHRoaXMuZmlsZU5hbWUgPSBmaWxlTmFtZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogZmlsZXNpemUgaW4gYnl0ZXMgb2YgdGhlIGVuY29kZWQgZmlsZVxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIGZpbGVzaXplIGluIGJ5dGVzLCAtMSBpZiBub3Qgc2V0XG4gICAgICAgICAqL1xuICAgICAgICBnZXRGaWxlU2l6ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbGVTaXplO1xuICAgICAgICB9XG4gICAgICAgIHNldEZpbGVTaXplKGZpbGVTaXplIC8qbG9uZyovKSB7XG4gICAgICAgICAgICB0aGlzLmZpbGVTaXplID0gZmlsZVNpemU7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDE2LWJpdCBDUkMgY2hlY2tzdW0gdXNpbmcgQ0NJVFQtMTZcbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiBjcmMgY2hlY2tzdW0sIC0xIGlmIG5vdCBzZXRcbiAgICAgICAgICovXG4gICAgICAgIGdldENoZWNrc3VtKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2hlY2tzdW07XG4gICAgICAgIH1cbiAgICAgICAgc2V0Q2hlY2tzdW0oY2hlY2tzdW0gLyppbnQqLykge1xuICAgICAgICAgICAgdGhpcy5jaGVja3N1bSA9IGNoZWNrc3VtO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiB1bml4IGVwb2NrIHRpbWVzdGFtcCwgZWxhcHNlZCBzZWNvbmRzIHNpbmNlIDE5NzAtMDEtMDFcbiAgICAgICAgICpcbiAgICAgICAgICogQHJldHVybiBlbGFwc2VkIHNlY29uZHMsIC0xIGlmIG5vdCBzZXRcbiAgICAgICAgICovXG4gICAgICAgIGdldFRpbWVzdGFtcCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRpbWVzdGFtcDtcbiAgICAgICAgfVxuICAgICAgICBzZXRUaW1lc3RhbXAodGltZXN0YW1wIC8qbG9uZyovKSB7XG4gICAgICAgICAgICB0aGlzLnRpbWVzdGFtcCA9IHRpbWVzdGFtcDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBvbnlmaWxsIGZvciBKYXZhJ3MgTG9uZyBjbGFzcy5cbiAgICAgKi9cbiAgICBjbGFzcyBMb25nIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFBhcnNlcyBhIHN0cmluZyB0byBhIG51bWJlciwgc2luY2UgSlMgaGFzIG5vIHJlYWxseSBJbnQ2NC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIG51bSBOdW1lcmljIHN0cmluZy5cbiAgICAgICAgICogQHBhcmFtIHJhZGl4IERlc3RpbmF0aW9uIHJhZGl4LlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIHBhcnNlTG9uZyhudW0sIHJhZGl4ID0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VJbnQobnVtLCByYWRpeCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDdXN0b20gRXJyb3IgY2xhc3Mgb2YgdHlwZSBFeGNlcHRpb24uXG4gICAgICovXG4gICAgY2xhc3MgTnVsbFBvaW50ZXJFeGNlcHRpb24gZXh0ZW5kcyBFeGNlcHRpb24ge1xuICAgIH1cbiAgICBOdWxsUG9pbnRlckV4Y2VwdGlvbi5raW5kID0gJ051bGxQb2ludGVyRXhjZXB0aW9uJztcblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IChjKSAxOTk0LCAyMDA0LCBPcmFjbGUgYW5kL29yIGl0cyBhZmZpbGlhdGVzLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICAgICAqIERPIE5PVCBBTFRFUiBPUiBSRU1PVkUgQ09QWVJJR0hUIE5PVElDRVMgT1IgVEhJUyBGSUxFIEhFQURFUi5cbiAgICAgKlxuICAgICAqIFRoaXMgY29kZSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgICogdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSB2ZXJzaW9uIDIgb25seSwgYXNcbiAgICAgKiBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4gIE9yYWNsZSBkZXNpZ25hdGVzIHRoaXNcbiAgICAgKiBwYXJ0aWN1bGFyIGZpbGUgYXMgc3ViamVjdCB0byB0aGUgXCJDbGFzc3BhdGhcIiBleGNlcHRpb24gYXMgcHJvdmlkZWRcbiAgICAgKiBieSBPcmFjbGUgaW4gdGhlIExJQ0VOU0UgZmlsZSB0aGF0IGFjY29tcGFuaWVkIHRoaXMgY29kZS5cbiAgICAgKlxuICAgICAqIFRoaXMgY29kZSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgICAqIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWSBvclxuICAgICAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgICAqIHZlcnNpb24gMiBmb3IgbW9yZSBkZXRhaWxzIChhIGNvcHkgaXMgaW5jbHVkZWQgaW4gdGhlIExJQ0VOU0UgZmlsZSB0aGF0XG4gICAgICogYWNjb21wYW5pZWQgdGhpcyBjb2RlKS5cbiAgICAgKlxuICAgICAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHZlcnNpb25cbiAgICAgKiAyIGFsb25nIHdpdGggdGhpcyB3b3JrOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sXG4gICAgICogSW5jLiwgNTEgRnJhbmtsaW4gU3QsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BIDAyMTEwLTEzMDEgVVNBLlxuICAgICAqXG4gICAgICogUGxlYXNlIGNvbnRhY3QgT3JhY2xlLCA1MDAgT3JhY2xlIFBhcmt3YXksIFJlZHdvb2QgU2hvcmVzLCBDQSA5NDA2NSBVU0FcbiAgICAgKiBvciB2aXNpdCB3d3cub3JhY2xlLmNvbSBpZiB5b3UgbmVlZCBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIG9yIGhhdmUgYW55XG4gICAgICogcXVlc3Rpb25zLlxuICAgICAqL1xuICAgIC8vIHBhY2thZ2UgamF2YS5pbztcbiAgICAvKipcbiAgICAgKiBUaGlzIGFic3RyYWN0IGNsYXNzIGlzIHRoZSBzdXBlcmNsYXNzIG9mIGFsbCBjbGFzc2VzIHJlcHJlc2VudGluZ1xuICAgICAqIGFuIG91dHB1dCBzdHJlYW0gb2YgYnl0ZXMuIEFuIG91dHB1dCBzdHJlYW0gYWNjZXB0cyBvdXRwdXQgYnl0ZXNcbiAgICAgKiBhbmQgc2VuZHMgdGhlbSB0byBzb21lIHNpbmsuXG4gICAgICogPHA+XG4gICAgICogQXBwbGljYXRpb25zIHRoYXQgbmVlZCB0byBkZWZpbmUgYSBzdWJjbGFzcyBvZlxuICAgICAqIDxjb2RlPk91dHB1dFN0cmVhbTwvY29kZT4gbXVzdCBhbHdheXMgcHJvdmlkZSBhdCBsZWFzdCBhIG1ldGhvZFxuICAgICAqIHRoYXQgd3JpdGVzIG9uZSBieXRlIG9mIG91dHB1dC5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgIEFydGh1ciB2YW4gSG9mZlxuICAgICAqIEBzZWUgICAgIGphdmEuaW8uQnVmZmVyZWRPdXRwdXRTdHJlYW1cbiAgICAgKiBAc2VlICAgICBqYXZhLmlvLkJ5dGVBcnJheU91dHB1dFN0cmVhbVxuICAgICAqIEBzZWUgICAgIGphdmEuaW8uRGF0YU91dHB1dFN0cmVhbVxuICAgICAqIEBzZWUgICAgIGphdmEuaW8uRmlsdGVyT3V0cHV0U3RyZWFtXG4gICAgICogQHNlZSAgICAgamF2YS5pby5JbnB1dFN0cmVhbVxuICAgICAqIEBzZWUgICAgIGphdmEuaW8uT3V0cHV0U3RyZWFtI3dyaXRlKGludClcbiAgICAgKiBAc2luY2UgICBKREsxLjBcbiAgICAgKi9cbiAgICAvKnB1YmxpYyovIGNsYXNzIE91dHB1dFN0cmVhbSAvKmltcGxlbWVudHMgQ2xvc2VhYmxlLCBGbHVzaGFibGUqLyB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXcml0ZXMgPGNvZGU+Yi5sZW5ndGg8L2NvZGU+IGJ5dGVzIGZyb20gdGhlIHNwZWNpZmllZCBieXRlIGFycmF5XG4gICAgICAgICAqIHRvIHRoaXMgb3V0cHV0IHN0cmVhbS4gVGhlIGdlbmVyYWwgY29udHJhY3QgZm9yIDxjb2RlPndyaXRlKGIpPC9jb2RlPlxuICAgICAgICAgKiBpcyB0aGF0IGl0IHNob3VsZCBoYXZlIGV4YWN0bHkgdGhlIHNhbWUgZWZmZWN0IGFzIHRoZSBjYWxsXG4gICAgICAgICAqIDxjb2RlPndyaXRlKGIsIDAsIGIubGVuZ3RoKTwvY29kZT4uXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSAgICAgIGIgICB0aGUgZGF0YS5cbiAgICAgICAgICogQGV4Y2VwdGlvbiAgSU9FeGNlcHRpb24gIGlmIGFuIEkvTyBlcnJvciBvY2N1cnMuXG4gICAgICAgICAqIEBzZWUgICAgICAgIGphdmEuaW8uT3V0cHV0U3RyZWFtI3dyaXRlKGJ5dGVbXSwgaW50LCBpbnQpXG4gICAgICAgICAqL1xuICAgICAgICB3cml0ZUJ5dGVzKGIpIHtcbiAgICAgICAgICAgIHRoaXMud3JpdGVCeXRlc09mZnNldChiLCAwLCBiLmxlbmd0aCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdyaXRlcyA8Y29kZT5sZW48L2NvZGU+IGJ5dGVzIGZyb20gdGhlIHNwZWNpZmllZCBieXRlIGFycmF5XG4gICAgICAgICAqIHN0YXJ0aW5nIGF0IG9mZnNldCA8Y29kZT5vZmY8L2NvZGU+IHRvIHRoaXMgb3V0cHV0IHN0cmVhbS5cbiAgICAgICAgICogVGhlIGdlbmVyYWwgY29udHJhY3QgZm9yIDxjb2RlPndyaXRlKGIsIG9mZiwgbGVuKTwvY29kZT4gaXMgdGhhdFxuICAgICAgICAgKiBzb21lIG9mIHRoZSBieXRlcyBpbiB0aGUgYXJyYXkgPGNvZGU+YjwvY29kZT4gYXJlIHdyaXR0ZW4gdG8gdGhlXG4gICAgICAgICAqIG91dHB1dCBzdHJlYW0gaW4gb3JkZXI7IGVsZW1lbnQgPGNvZGU+YltvZmZdPC9jb2RlPiBpcyB0aGUgZmlyc3RcbiAgICAgICAgICogYnl0ZSB3cml0dGVuIGFuZCA8Y29kZT5iW29mZitsZW4tMV08L2NvZGU+IGlzIHRoZSBsYXN0IGJ5dGUgd3JpdHRlblxuICAgICAgICAgKiBieSB0aGlzIG9wZXJhdGlvbi5cbiAgICAgICAgICogPHA+XG4gICAgICAgICAqIFRoZSA8Y29kZT53cml0ZTwvY29kZT4gbWV0aG9kIG9mIDxjb2RlPk91dHB1dFN0cmVhbTwvY29kZT4gY2FsbHNcbiAgICAgICAgICogdGhlIHdyaXRlIG1ldGhvZCBvZiBvbmUgYXJndW1lbnQgb24gZWFjaCBvZiB0aGUgYnl0ZXMgdG8gYmVcbiAgICAgICAgICogd3JpdHRlbiBvdXQuIFN1YmNsYXNzZXMgYXJlIGVuY291cmFnZWQgdG8gb3ZlcnJpZGUgdGhpcyBtZXRob2QgYW5kXG4gICAgICAgICAqIHByb3ZpZGUgYSBtb3JlIGVmZmljaWVudCBpbXBsZW1lbnRhdGlvbi5cbiAgICAgICAgICogPHA+XG4gICAgICAgICAqIElmIDxjb2RlPmI8L2NvZGU+IGlzIDxjb2RlPm51bGw8L2NvZGU+LCBhXG4gICAgICAgICAqIDxjb2RlPk51bGxQb2ludGVyRXhjZXB0aW9uPC9jb2RlPiBpcyB0aHJvd24uXG4gICAgICAgICAqIDxwPlxuICAgICAgICAgKiBJZiA8Y29kZT5vZmY8L2NvZGU+IGlzIG5lZ2F0aXZlLCBvciA8Y29kZT5sZW48L2NvZGU+IGlzIG5lZ2F0aXZlLCBvclxuICAgICAgICAgKiA8Y29kZT5vZmYrbGVuPC9jb2RlPiBpcyBncmVhdGVyIHRoYW4gdGhlIGxlbmd0aCBvZiB0aGUgYXJyYXlcbiAgICAgICAgICogPGNvZGU+YjwvY29kZT4sIHRoZW4gYW4gPHR0PkluZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb248L3R0PiBpcyB0aHJvd24uXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSAgICAgIGIgICAgIHRoZSBkYXRhLlxuICAgICAgICAgKiBAcGFyYW0gICAgICBvZmYgICB0aGUgc3RhcnQgb2Zmc2V0IGluIHRoZSBkYXRhLlxuICAgICAgICAgKiBAcGFyYW0gICAgICBsZW4gICB0aGUgbnVtYmVyIG9mIGJ5dGVzIHRvIHdyaXRlLlxuICAgICAgICAgKiBAZXhjZXB0aW9uICBJT0V4Y2VwdGlvbiAgaWYgYW4gSS9PIGVycm9yIG9jY3Vycy4gSW4gcGFydGljdWxhcixcbiAgICAgICAgICogICAgICAgICAgICAgYW4gPGNvZGU+SU9FeGNlcHRpb248L2NvZGU+IGlzIHRocm93biBpZiB0aGUgb3V0cHV0XG4gICAgICAgICAqICAgICAgICAgICAgIHN0cmVhbSBpcyBjbG9zZWQuXG4gICAgICAgICAqL1xuICAgICAgICB3cml0ZUJ5dGVzT2Zmc2V0KGIsIG9mZiwgbGVuKSB7XG4gICAgICAgICAgICBpZiAoYiA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE51bGxQb2ludGVyRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICgob2ZmIDwgMCkgfHwgKG9mZiA+IGIubGVuZ3RoKSB8fCAobGVuIDwgMCkgfHxcbiAgICAgICAgICAgICAgICAoKG9mZiArIGxlbikgPiBiLmxlbmd0aCkgfHwgKChvZmYgKyBsZW4pIDwgMCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAobGVuID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgIHRoaXMud3JpdGUoYltvZmYgKyBpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEZsdXNoZXMgdGhpcyBvdXRwdXQgc3RyZWFtIGFuZCBmb3JjZXMgYW55IGJ1ZmZlcmVkIG91dHB1dCBieXRlc1xuICAgICAgICAgKiB0byBiZSB3cml0dGVuIG91dC4gVGhlIGdlbmVyYWwgY29udHJhY3Qgb2YgPGNvZGU+Zmx1c2g8L2NvZGU+IGlzXG4gICAgICAgICAqIHRoYXQgY2FsbGluZyBpdCBpcyBhbiBpbmRpY2F0aW9uIHRoYXQsIGlmIGFueSBieXRlcyBwcmV2aW91c2x5XG4gICAgICAgICAqIHdyaXR0ZW4gaGF2ZSBiZWVuIGJ1ZmZlcmVkIGJ5IHRoZSBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgb3V0cHV0XG4gICAgICAgICAqIHN0cmVhbSwgc3VjaCBieXRlcyBzaG91bGQgaW1tZWRpYXRlbHkgYmUgd3JpdHRlbiB0byB0aGVpclxuICAgICAgICAgKiBpbnRlbmRlZCBkZXN0aW5hdGlvbi5cbiAgICAgICAgICogPHA+XG4gICAgICAgICAqIElmIHRoZSBpbnRlbmRlZCBkZXN0aW5hdGlvbiBvZiB0aGlzIHN0cmVhbSBpcyBhbiBhYnN0cmFjdGlvbiBwcm92aWRlZCBieVxuICAgICAgICAgKiB0aGUgdW5kZXJseWluZyBvcGVyYXRpbmcgc3lzdGVtLCBmb3IgZXhhbXBsZSBhIGZpbGUsIHRoZW4gZmx1c2hpbmcgdGhlXG4gICAgICAgICAqIHN0cmVhbSBndWFyYW50ZWVzIG9ubHkgdGhhdCBieXRlcyBwcmV2aW91c2x5IHdyaXR0ZW4gdG8gdGhlIHN0cmVhbSBhcmVcbiAgICAgICAgICogcGFzc2VkIHRvIHRoZSBvcGVyYXRpbmcgc3lzdGVtIGZvciB3cml0aW5nOyBpdCBkb2VzIG5vdCBndWFyYW50ZWUgdGhhdFxuICAgICAgICAgKiB0aGV5IGFyZSBhY3R1YWxseSB3cml0dGVuIHRvIGEgcGh5c2ljYWwgZGV2aWNlIHN1Y2ggYXMgYSBkaXNrIGRyaXZlLlxuICAgICAgICAgKiA8cD5cbiAgICAgICAgICogVGhlIDxjb2RlPmZsdXNoPC9jb2RlPiBtZXRob2Qgb2YgPGNvZGU+T3V0cHV0U3RyZWFtPC9jb2RlPiBkb2VzIG5vdGhpbmcuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBleGNlcHRpb24gIElPRXhjZXB0aW9uICBpZiBhbiBJL08gZXJyb3Igb2NjdXJzLlxuICAgICAgICAgKi9cbiAgICAgICAgZmx1c2goKSB7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENsb3NlcyB0aGlzIG91dHB1dCBzdHJlYW0gYW5kIHJlbGVhc2VzIGFueSBzeXN0ZW0gcmVzb3VyY2VzXG4gICAgICAgICAqIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHN0cmVhbS4gVGhlIGdlbmVyYWwgY29udHJhY3Qgb2YgPGNvZGU+Y2xvc2U8L2NvZGU+XG4gICAgICAgICAqIGlzIHRoYXQgaXQgY2xvc2VzIHRoZSBvdXRwdXQgc3RyZWFtLiBBIGNsb3NlZCBzdHJlYW0gY2Fubm90IHBlcmZvcm1cbiAgICAgICAgICogb3V0cHV0IG9wZXJhdGlvbnMgYW5kIGNhbm5vdCBiZSByZW9wZW5lZC5cbiAgICAgICAgICogPHA+XG4gICAgICAgICAqIFRoZSA8Y29kZT5jbG9zZTwvY29kZT4gbWV0aG9kIG9mIDxjb2RlPk91dHB1dFN0cmVhbTwvY29kZT4gZG9lcyBub3RoaW5nLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAZXhjZXB0aW9uICBJT0V4Y2VwdGlvbiAgaWYgYW4gSS9PIGVycm9yIG9jY3Vycy5cbiAgICAgICAgICovXG4gICAgICAgIGNsb3NlKCkge1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3VzdG9tIEVycm9yIGNsYXNzIG9mIHR5cGUgRXhjZXB0aW9uLlxuICAgICAqL1xuICAgIGNsYXNzIE91dE9mTWVtb3J5RXJyb3IgZXh0ZW5kcyBFeGNlcHRpb24ge1xuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IChjKSAxOTk0LCAyMDEwLCBPcmFjbGUgYW5kL29yIGl0cyBhZmZpbGlhdGVzLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICAgICAqIERPIE5PVCBBTFRFUiBPUiBSRU1PVkUgQ09QWVJJR0hUIE5PVElDRVMgT1IgVEhJUyBGSUxFIEhFQURFUi5cbiAgICAgKlxuICAgICAqIFRoaXMgY29kZSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgICogdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSB2ZXJzaW9uIDIgb25seSwgYXNcbiAgICAgKiBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4gIE9yYWNsZSBkZXNpZ25hdGVzIHRoaXNcbiAgICAgKiBwYXJ0aWN1bGFyIGZpbGUgYXMgc3ViamVjdCB0byB0aGUgXCJDbGFzc3BhdGhcIiBleGNlcHRpb24gYXMgcHJvdmlkZWRcbiAgICAgKiBieSBPcmFjbGUgaW4gdGhlIExJQ0VOU0UgZmlsZSB0aGF0IGFjY29tcGFuaWVkIHRoaXMgY29kZS5cbiAgICAgKlxuICAgICAqIFRoaXMgY29kZSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgICAqIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWSBvclxuICAgICAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgICAqIHZlcnNpb24gMiBmb3IgbW9yZSBkZXRhaWxzIChhIGNvcHkgaXMgaW5jbHVkZWQgaW4gdGhlIExJQ0VOU0UgZmlsZSB0aGF0XG4gICAgICogYWNjb21wYW5pZWQgdGhpcyBjb2RlKS5cbiAgICAgKlxuICAgICAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHZlcnNpb25cbiAgICAgKiAyIGFsb25nIHdpdGggdGhpcyB3b3JrOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sXG4gICAgICogSW5jLiwgNTEgRnJhbmtsaW4gU3QsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BIDAyMTEwLTEzMDEgVVNBLlxuICAgICAqXG4gICAgICogUGxlYXNlIGNvbnRhY3QgT3JhY2xlLCA1MDAgT3JhY2xlIFBhcmt3YXksIFJlZHdvb2QgU2hvcmVzLCBDQSA5NDA2NSBVU0FcbiAgICAgKiBvciB2aXNpdCB3d3cub3JhY2xlLmNvbSBpZiB5b3UgbmVlZCBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIG9yIGhhdmUgYW55XG4gICAgICogcXVlc3Rpb25zLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIFRoaXMgY2xhc3MgaW1wbGVtZW50cyBhbiBvdXRwdXQgc3RyZWFtIGluIHdoaWNoIHRoZSBkYXRhIGlzXG4gICAgICogd3JpdHRlbiBpbnRvIGEgYnl0ZSBhcnJheS4gVGhlIGJ1ZmZlciBhdXRvbWF0aWNhbGx5IGdyb3dzIGFzIGRhdGFcbiAgICAgKiBpcyB3cml0dGVuIHRvIGl0LlxuICAgICAqIFRoZSBkYXRhIGNhbiBiZSByZXRyaWV2ZWQgdXNpbmcgPGNvZGU+dG9CeXRlQXJyYXkoKTwvY29kZT4gYW5kXG4gICAgICogPGNvZGU+dG9TdHJpbmcoKTwvY29kZT4uXG4gICAgICogPHA+XG4gICAgICogQ2xvc2luZyBhIDx0dD5CeXRlQXJyYXlPdXRwdXRTdHJlYW08L3R0PiBoYXMgbm8gZWZmZWN0LiBUaGUgbWV0aG9kcyBpblxuICAgICAqIHRoaXMgY2xhc3MgY2FuIGJlIGNhbGxlZCBhZnRlciB0aGUgc3RyZWFtIGhhcyBiZWVuIGNsb3NlZCB3aXRob3V0XG4gICAgICogZ2VuZXJhdGluZyBhbiA8dHQ+SU9FeGNlcHRpb248L3R0Pi5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgIEFydGh1ciB2YW4gSG9mZlxuICAgICAqIEBzaW5jZSAgIEpESzEuMFxuICAgICAqL1xuICAgIC8qcHVibGljKi8gY2xhc3MgQnl0ZUFycmF5T3V0cHV0U3RyZWFtIGV4dGVuZHMgT3V0cHV0U3RyZWFtIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBuZXcgYnl0ZSBhcnJheSBvdXRwdXQgc3RyZWFtLiBUaGUgYnVmZmVyIGNhcGFjaXR5IGlzXG4gICAgICAgICAqIGluaXRpYWxseSAzMiBieXRlcywgdGhvdWdoIGl0cyBzaXplIGluY3JlYXNlcyBpZiBuZWNlc3NhcnkuXG4gICAgICAgICAqL1xuICAgICAgICAvLyBwdWJsaWMgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIC8vICAgICB0aGlzKDMyKTtcbiAgICAgICAgLy8gfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIG5ldyBieXRlIGFycmF5IG91dHB1dCBzdHJlYW0sIHdpdGggYSBidWZmZXIgY2FwYWNpdHkgb2ZcbiAgICAgICAgICogdGhlIHNwZWNpZmllZCBzaXplLCBpbiBieXRlcy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtICAgc2l6ZSAgIHRoZSBpbml0aWFsIHNpemUuXG4gICAgICAgICAqIEBleGNlcHRpb24gIElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbiBpZiBzaXplIGlzIG5lZ2F0aXZlLlxuICAgICAgICAgKi9cbiAgICAgICAgY29uc3RydWN0b3Ioc2l6ZSA9IDMyKSB7XG4gICAgICAgICAgICBzdXBlcigpO1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBUaGUgbnVtYmVyIG9mIHZhbGlkIGJ5dGVzIGluIHRoZSBidWZmZXIuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHRoaXMuY291bnQgPSAwO1xuICAgICAgICAgICAgaWYgKHNpemUgPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignTmVnYXRpdmUgaW5pdGlhbCBzaXplOiAnXG4gICAgICAgICAgICAgICAgICAgICsgc2l6ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmJ1ZiA9IG5ldyBVaW50OEFycmF5KHNpemUpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJbmNyZWFzZXMgdGhlIGNhcGFjaXR5IGlmIG5lY2Vzc2FyeSB0byBlbnN1cmUgdGhhdCBpdCBjYW4gaG9sZFxuICAgICAgICAgKiBhdCBsZWFzdCB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIHNwZWNpZmllZCBieSB0aGUgbWluaW11bVxuICAgICAgICAgKiBjYXBhY2l0eSBhcmd1bWVudC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIG1pbkNhcGFjaXR5IHRoZSBkZXNpcmVkIG1pbmltdW0gY2FwYWNpdHlcbiAgICAgICAgICogQHRocm93cyBPdXRPZk1lbW9yeUVycm9yIGlmIHtAY29kZSBtaW5DYXBhY2l0eSA8IDB9LiAgVGhpcyBpc1xuICAgICAgICAgKiBpbnRlcnByZXRlZCBhcyBhIHJlcXVlc3QgZm9yIHRoZSB1bnNhdGlzZmlhYmx5IGxhcmdlIGNhcGFjaXR5XG4gICAgICAgICAqIHtAY29kZSAobG9uZykgSW50ZWdlci5NQVhfVkFMVUUgKyAobWluQ2FwYWNpdHkgLSBJbnRlZ2VyLk1BWF9WQUxVRSl9LlxuICAgICAgICAgKi9cbiAgICAgICAgZW5zdXJlQ2FwYWNpdHkobWluQ2FwYWNpdHkpIHtcbiAgICAgICAgICAgIC8vIG92ZXJmbG93LWNvbnNjaW91cyBjb2RlXG4gICAgICAgICAgICBpZiAobWluQ2FwYWNpdHkgLSB0aGlzLmJ1Zi5sZW5ndGggPiAwKVxuICAgICAgICAgICAgICAgIHRoaXMuZ3JvdyhtaW5DYXBhY2l0eSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEluY3JlYXNlcyB0aGUgY2FwYWNpdHkgdG8gZW5zdXJlIHRoYXQgaXQgY2FuIGhvbGQgYXQgbGVhc3QgdGhlXG4gICAgICAgICAqIG51bWJlciBvZiBlbGVtZW50cyBzcGVjaWZpZWQgYnkgdGhlIG1pbmltdW0gY2FwYWNpdHkgYXJndW1lbnQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBtaW5DYXBhY2l0eSB0aGUgZGVzaXJlZCBtaW5pbXVtIGNhcGFjaXR5XG4gICAgICAgICAqL1xuICAgICAgICBncm93KG1pbkNhcGFjaXR5KSB7XG4gICAgICAgICAgICAvLyBvdmVyZmxvdy1jb25zY2lvdXMgY29kZVxuICAgICAgICAgICAgbGV0IG9sZENhcGFjaXR5ID0gdGhpcy5idWYubGVuZ3RoO1xuICAgICAgICAgICAgbGV0IG5ld0NhcGFjaXR5ID0gb2xkQ2FwYWNpdHkgPDwgMTtcbiAgICAgICAgICAgIGlmIChuZXdDYXBhY2l0eSAtIG1pbkNhcGFjaXR5IDwgMClcbiAgICAgICAgICAgICAgICBuZXdDYXBhY2l0eSA9IG1pbkNhcGFjaXR5O1xuICAgICAgICAgICAgaWYgKG5ld0NhcGFjaXR5IDwgMCkge1xuICAgICAgICAgICAgICAgIGlmIChtaW5DYXBhY2l0eSA8IDApIC8vIG92ZXJmbG93XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBPdXRPZk1lbW9yeUVycm9yKCk7XG4gICAgICAgICAgICAgICAgbmV3Q2FwYWNpdHkgPSBJbnRlZ2VyLk1BWF9WQUxVRTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuYnVmID0gQXJyYXlzLmNvcHlPZlVpbnQ4QXJyYXkodGhpcy5idWYsIG5ld0NhcGFjaXR5KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogV3JpdGVzIHRoZSBzcGVjaWZpZWQgYnl0ZSB0byB0aGlzIGJ5dGUgYXJyYXkgb3V0cHV0IHN0cmVhbS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtICAgYiAgIHRoZSBieXRlIHRvIGJlIHdyaXR0ZW4uXG4gICAgICAgICAqL1xuICAgICAgICB3cml0ZShiKSB7XG4gICAgICAgICAgICB0aGlzLmVuc3VyZUNhcGFjaXR5KHRoaXMuY291bnQgKyAxKTtcbiAgICAgICAgICAgIHRoaXMuYnVmW3RoaXMuY291bnRdID0gLyooYnl0ZSkqLyBiO1xuICAgICAgICAgICAgdGhpcy5jb3VudCArPSAxO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXcml0ZXMgPGNvZGU+bGVuPC9jb2RlPiBieXRlcyBmcm9tIHRoZSBzcGVjaWZpZWQgYnl0ZSBhcnJheVxuICAgICAgICAgKiBzdGFydGluZyBhdCBvZmZzZXQgPGNvZGU+b2ZmPC9jb2RlPiB0byB0aGlzIGJ5dGUgYXJyYXkgb3V0cHV0IHN0cmVhbS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtICAgYiAgICAgdGhlIGRhdGEuXG4gICAgICAgICAqIEBwYXJhbSAgIG9mZiAgIHRoZSBzdGFydCBvZmZzZXQgaW4gdGhlIGRhdGEuXG4gICAgICAgICAqIEBwYXJhbSAgIGxlbiAgIHRoZSBudW1iZXIgb2YgYnl0ZXMgdG8gd3JpdGUuXG4gICAgICAgICAqL1xuICAgICAgICB3cml0ZUJ5dGVzT2Zmc2V0KGIsIG9mZiwgbGVuKSB7XG4gICAgICAgICAgICBpZiAoKG9mZiA8IDApIHx8IChvZmYgPiBiLmxlbmd0aCkgfHwgKGxlbiA8IDApIHx8XG4gICAgICAgICAgICAgICAgKChvZmYgKyBsZW4pIC0gYi5sZW5ndGggPiAwKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVuc3VyZUNhcGFjaXR5KHRoaXMuY291bnQgKyBsZW4pO1xuICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weShiLCBvZmYsIHRoaXMuYnVmLCB0aGlzLmNvdW50LCBsZW4pO1xuICAgICAgICAgICAgdGhpcy5jb3VudCArPSBsZW47XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdyaXRlcyB0aGUgY29tcGxldGUgY29udGVudHMgb2YgdGhpcyBieXRlIGFycmF5IG91dHB1dCBzdHJlYW0gdG9cbiAgICAgICAgICogdGhlIHNwZWNpZmllZCBvdXRwdXQgc3RyZWFtIGFyZ3VtZW50LCBhcyBpZiBieSBjYWxsaW5nIHRoZSBvdXRwdXRcbiAgICAgICAgICogc3RyZWFtJ3Mgd3JpdGUgbWV0aG9kIHVzaW5nIDxjb2RlPm91dC53cml0ZShidWYsIDAsIGNvdW50KTwvY29kZT4uXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSAgICAgIG91dCAgIHRoZSBvdXRwdXQgc3RyZWFtIHRvIHdoaWNoIHRvIHdyaXRlIHRoZSBkYXRhLlxuICAgICAgICAgKiBAZXhjZXB0aW9uICBJT0V4Y2VwdGlvbiAgaWYgYW4gSS9PIGVycm9yIG9jY3Vycy5cbiAgICAgICAgICovXG4gICAgICAgIHdyaXRlVG8ob3V0KSB7XG4gICAgICAgICAgICBvdXQud3JpdGVCeXRlc09mZnNldCh0aGlzLmJ1ZiwgMCwgdGhpcy5jb3VudCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJlc2V0cyB0aGUgPGNvZGU+Y291bnQ8L2NvZGU+IGZpZWxkIG9mIHRoaXMgYnl0ZSBhcnJheSBvdXRwdXRcbiAgICAgICAgICogc3RyZWFtIHRvIHplcm8sIHNvIHRoYXQgYWxsIGN1cnJlbnRseSBhY2N1bXVsYXRlZCBvdXRwdXQgaW4gdGhlXG4gICAgICAgICAqIG91dHB1dCBzdHJlYW0gaXMgZGlzY2FyZGVkLiBUaGUgb3V0cHV0IHN0cmVhbSBjYW4gYmUgdXNlZCBhZ2FpbixcbiAgICAgICAgICogcmV1c2luZyB0aGUgYWxyZWFkeSBhbGxvY2F0ZWQgYnVmZmVyIHNwYWNlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAc2VlICAgICBqYXZhLmlvLkJ5dGVBcnJheUlucHV0U3RyZWFtI2NvdW50XG4gICAgICAgICAqL1xuICAgICAgICByZXNldCgpIHtcbiAgICAgICAgICAgIHRoaXMuY291bnQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgbmV3bHkgYWxsb2NhdGVkIGJ5dGUgYXJyYXkuIEl0cyBzaXplIGlzIHRoZSBjdXJyZW50XG4gICAgICAgICAqIHNpemUgb2YgdGhpcyBvdXRwdXQgc3RyZWFtIGFuZCB0aGUgdmFsaWQgY29udGVudHMgb2YgdGhlIGJ1ZmZlclxuICAgICAgICAgKiBoYXZlIGJlZW4gY29waWVkIGludG8gaXQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gIHRoZSBjdXJyZW50IGNvbnRlbnRzIG9mIHRoaXMgb3V0cHV0IHN0cmVhbSwgYXMgYSBieXRlIGFycmF5LlxuICAgICAgICAgKiBAc2VlICAgICBqYXZhLmlvLkJ5dGVBcnJheU91dHB1dFN0cmVhbSNzaXplKClcbiAgICAgICAgICovXG4gICAgICAgIHRvQnl0ZUFycmF5KCkge1xuICAgICAgICAgICAgcmV0dXJuIEFycmF5cy5jb3B5T2ZVaW50OEFycmF5KHRoaXMuYnVmLCB0aGlzLmNvdW50KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogUmV0dXJucyB0aGUgY3VycmVudCBzaXplIG9mIHRoZSBidWZmZXIuXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gIHRoZSB2YWx1ZSBvZiB0aGUgPGNvZGU+Y291bnQ8L2NvZGU+IGZpZWxkLCB3aGljaCBpcyB0aGUgbnVtYmVyXG4gICAgICAgICAqICAgICAgICAgIG9mIHZhbGlkIGJ5dGVzIGluIHRoaXMgb3V0cHV0IHN0cmVhbS5cbiAgICAgICAgICogQHNlZSAgICAgamF2YS5pby5CeXRlQXJyYXlPdXRwdXRTdHJlYW0jY291bnRcbiAgICAgICAgICovXG4gICAgICAgIHNpemUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb3VudDtcbiAgICAgICAgfVxuICAgICAgICB0b1N0cmluZyhwYXJhbSkge1xuICAgICAgICAgICAgaWYgKCFwYXJhbSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnRvU3RyaW5nX3ZvaWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgcGFyYW0gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9TdHJpbmdfc3RyaW5nKHBhcmFtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRvU3RyaW5nX251bWJlcihwYXJhbSk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnZlcnRzIHRoZSBidWZmZXIncyBjb250ZW50cyBpbnRvIGEgc3RyaW5nIGRlY29kaW5nIGJ5dGVzIHVzaW5nIHRoZVxuICAgICAgICAgKiBwbGF0Zm9ybSdzIGRlZmF1bHQgY2hhcmFjdGVyIHNldC4gVGhlIGxlbmd0aCBvZiB0aGUgbmV3IDx0dD5TdHJpbmc8L3R0PlxuICAgICAgICAgKiBpcyBhIGZ1bmN0aW9uIG9mIHRoZSBjaGFyYWN0ZXIgc2V0LCBhbmQgaGVuY2UgbWF5IG5vdCBiZSBlcXVhbCB0byB0aGVcbiAgICAgICAgICogc2l6ZSBvZiB0aGUgYnVmZmVyLlxuICAgICAgICAgKlxuICAgICAgICAgKiA8cD4gVGhpcyBtZXRob2QgYWx3YXlzIHJlcGxhY2VzIG1hbGZvcm1lZC1pbnB1dCBhbmQgdW5tYXBwYWJsZS1jaGFyYWN0ZXJcbiAgICAgICAgICogc2VxdWVuY2VzIHdpdGggdGhlIGRlZmF1bHQgcmVwbGFjZW1lbnQgc3RyaW5nIGZvciB0aGUgcGxhdGZvcm0nc1xuICAgICAgICAgKiBkZWZhdWx0IGNoYXJhY3RlciBzZXQuIFRoZSB7QGxpbmtwbGFpbiBqYXZhLm5pby5jaGFyc2V0LkNoYXJzZXREZWNvZGVyfVxuICAgICAgICAgKiBjbGFzcyBzaG91bGQgYmUgdXNlZCB3aGVuIG1vcmUgY29udHJvbCBvdmVyIHRoZSBkZWNvZGluZyBwcm9jZXNzIGlzXG4gICAgICAgICAqIHJlcXVpcmVkLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmV0dXJuIFN0cmluZyBkZWNvZGVkIGZyb20gdGhlIGJ1ZmZlcidzIGNvbnRlbnRzLlxuICAgICAgICAgKiBAc2luY2UgIEpESzEuMVxuICAgICAgICAgKi9cbiAgICAgICAgdG9TdHJpbmdfdm9pZCgpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU3RyaW5nKHRoaXMuYnVmIC8qLCAwLCB0aGlzLmNvdW50Ki8pLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnZlcnRzIHRoZSBidWZmZXIncyBjb250ZW50cyBpbnRvIGEgc3RyaW5nIGJ5IGRlY29kaW5nIHRoZSBieXRlcyB1c2luZ1xuICAgICAgICAgKiB0aGUgc3BlY2lmaWVkIHtAbGluayBqYXZhLm5pby5jaGFyc2V0LkNoYXJzZXQgY2hhcnNldE5hbWV9LiBUaGUgbGVuZ3RoIG9mXG4gICAgICAgICAqIHRoZSBuZXcgPHR0PlN0cmluZzwvdHQ+IGlzIGEgZnVuY3Rpb24gb2YgdGhlIGNoYXJzZXQsIGFuZCBoZW5jZSBtYXkgbm90IGJlXG4gICAgICAgICAqIGVxdWFsIHRvIHRoZSBsZW5ndGggb2YgdGhlIGJ5dGUgYXJyYXkuXG4gICAgICAgICAqXG4gICAgICAgICAqIDxwPiBUaGlzIG1ldGhvZCBhbHdheXMgcmVwbGFjZXMgbWFsZm9ybWVkLWlucHV0IGFuZCB1bm1hcHBhYmxlLWNoYXJhY3RlclxuICAgICAgICAgKiBzZXF1ZW5jZXMgd2l0aCB0aGlzIGNoYXJzZXQncyBkZWZhdWx0IHJlcGxhY2VtZW50IHN0cmluZy4gVGhlIHtAbGlua1xuICAgICAgICAgKiBqYXZhLm5pby5jaGFyc2V0LkNoYXJzZXREZWNvZGVyfSBjbGFzcyBzaG91bGQgYmUgdXNlZCB3aGVuIG1vcmUgY29udHJvbFxuICAgICAgICAgKiBvdmVyIHRoZSBkZWNvZGluZyBwcm9jZXNzIGlzIHJlcXVpcmVkLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gIGNoYXJzZXROYW1lICB0aGUgbmFtZSBvZiBhIHN1cHBvcnRlZFxuICAgICAgICAgKiAgICAgICAgICAgICAge0BsaW5rcGxhaW4gamF2YS5uaW8uY2hhcnNldC5DaGFyc2V0IDwvY29kZT5jaGFyc2V0PGNvZGU+fVxuICAgICAgICAgKiBAcmV0dXJuIFN0cmluZyBkZWNvZGVkIGZyb20gdGhlIGJ1ZmZlcidzIGNvbnRlbnRzLlxuICAgICAgICAgKiBAZXhjZXB0aW9uICBVbnN1cHBvcnRlZEVuY29kaW5nRXhjZXB0aW9uXG4gICAgICAgICAqICAgICAgICAgICAgIElmIHRoZSBuYW1lZCBjaGFyc2V0IGlzIG5vdCBzdXBwb3J0ZWRcbiAgICAgICAgICogQHNpbmNlICAgSkRLMS4xXG4gICAgICAgICAqL1xuICAgICAgICB0b1N0cmluZ19zdHJpbmcoY2hhcnNldE5hbWUpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU3RyaW5nKHRoaXMuYnVmIC8qLCAwLCB0aGlzLmNvdW50LCBjaGFyc2V0TmFtZSovKS50b1N0cmluZygpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgbmV3bHkgYWxsb2NhdGVkIHN0cmluZy4gSXRzIHNpemUgaXMgdGhlIGN1cnJlbnQgc2l6ZSBvZlxuICAgICAgICAgKiB0aGUgb3V0cHV0IHN0cmVhbSBhbmQgdGhlIHZhbGlkIGNvbnRlbnRzIG9mIHRoZSBidWZmZXIgaGF2ZSBiZWVuXG4gICAgICAgICAqIGNvcGllZCBpbnRvIGl0LiBFYWNoIGNoYXJhY3RlciA8aT5jPC9pPiBpbiB0aGUgcmVzdWx0aW5nIHN0cmluZyBpc1xuICAgICAgICAgKiBjb25zdHJ1Y3RlZCBmcm9tIHRoZSBjb3JyZXNwb25kaW5nIGVsZW1lbnQgPGk+YjwvaT4gaW4gdGhlIGJ5dGVcbiAgICAgICAgICogYXJyYXkgc3VjaCB0aGF0OlxuICAgICAgICAgKiA8YmxvY2txdW90ZT48cHJlPlxuICAgICAgICAgKiAgICAgYyA9PSAoY2hhcikoKChoaWJ5dGUgJmFtcDsgMHhmZikgJmx0OyZsdDsgOCkgfCAoYiAmYW1wOyAweGZmKSlcbiAgICAgICAgICogPC9wcmU+PC9ibG9ja3F1b3RlPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAZGVwcmVjYXRlZCBUaGlzIG1ldGhvZCBkb2VzIG5vdCBwcm9wZXJseSBjb252ZXJ0IGJ5dGVzIGludG8gY2hhcmFjdGVycy5cbiAgICAgICAgICogQXMgb2YgSkRLJm5ic3A7MS4xLCB0aGUgcHJlZmVycmVkIHdheSB0byBkbyB0aGlzIGlzIHZpYSB0aGVcbiAgICAgICAgICogPGNvZGU+dG9TdHJpbmcoU3RyaW5nIGVuYyk8L2NvZGU+IG1ldGhvZCwgd2hpY2ggdGFrZXMgYW4gZW5jb2RpbmctbmFtZVxuICAgICAgICAgKiBhcmd1bWVudCwgb3IgdGhlIDxjb2RlPnRvU3RyaW5nKCk8L2NvZGU+IG1ldGhvZCwgd2hpY2ggdXNlcyB0aGVcbiAgICAgICAgICogcGxhdGZvcm0ncyBkZWZhdWx0IGNoYXJhY3RlciBlbmNvZGluZy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtICAgICAgaGlieXRlICAgIHRoZSBoaWdoIGJ5dGUgb2YgZWFjaCByZXN1bHRpbmcgVW5pY29kZSBjaGFyYWN0ZXIuXG4gICAgICAgICAqIEByZXR1cm4gICAgIHRoZSBjdXJyZW50IGNvbnRlbnRzIG9mIHRoZSBvdXRwdXQgc3RyZWFtLCBhcyBhIHN0cmluZy5cbiAgICAgICAgICogQHNlZSAgICAgICAgamF2YS5pby5CeXRlQXJyYXlPdXRwdXRTdHJlYW0jc2l6ZSgpXG4gICAgICAgICAqIEBzZWUgICAgICAgIGphdmEuaW8uQnl0ZUFycmF5T3V0cHV0U3RyZWFtI3RvU3RyaW5nKFN0cmluZylcbiAgICAgICAgICogQHNlZSAgICAgICAgamF2YS5pby5CeXRlQXJyYXlPdXRwdXRTdHJlYW0jdG9TdHJpbmcoKVxuICAgICAgICAgKi9cbiAgICAgICAgLy8gQERlcHJlY2F0ZWRcbiAgICAgICAgdG9TdHJpbmdfbnVtYmVyKGhpYnl0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBTdHJpbmcodGhpcy5idWYgLyosIGhpYnl0ZSwgMCwgdGhpcy5jb3VudCovKS50b1N0cmluZygpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDbG9zaW5nIGEgPHR0PkJ5dGVBcnJheU91dHB1dFN0cmVhbTwvdHQ+IGhhcyBubyBlZmZlY3QuIFRoZSBtZXRob2RzIGluXG4gICAgICAgICAqIHRoaXMgY2xhc3MgY2FuIGJlIGNhbGxlZCBhZnRlciB0aGUgc3RyZWFtIGhhcyBiZWVuIGNsb3NlZCB3aXRob3V0XG4gICAgICAgICAqIGdlbmVyYXRpbmcgYW4gPHR0PklPRXhjZXB0aW9uPC90dD4uXG4gICAgICAgICAqIDxwPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAdGhyb3dzIElPRXhjZXB0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBjbG9zZSgpIHtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDkgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLypwcml2YXRlKi8gdmFyIE1vZGUkMjtcbiAgICAoZnVuY3Rpb24gKE1vZGUpIHtcbiAgICAgICAgTW9kZVtNb2RlW1wiQUxQSEFcIl0gPSAwXSA9IFwiQUxQSEFcIjtcbiAgICAgICAgTW9kZVtNb2RlW1wiTE9XRVJcIl0gPSAxXSA9IFwiTE9XRVJcIjtcbiAgICAgICAgTW9kZVtNb2RlW1wiTUlYRURcIl0gPSAyXSA9IFwiTUlYRURcIjtcbiAgICAgICAgTW9kZVtNb2RlW1wiUFVOQ1RcIl0gPSAzXSA9IFwiUFVOQ1RcIjtcbiAgICAgICAgTW9kZVtNb2RlW1wiQUxQSEFfU0hJRlRcIl0gPSA0XSA9IFwiQUxQSEFfU0hJRlRcIjtcbiAgICAgICAgTW9kZVtNb2RlW1wiUFVOQ1RfU0hJRlRcIl0gPSA1XSA9IFwiUFVOQ1RfU0hJRlRcIjtcbiAgICB9KShNb2RlJDIgfHwgKE1vZGUkMiA9IHt9KSk7XG4gICAgLyoqXG4gICAgICogSW5kaXJlY3RseSBhY2Nlc3MgdGhlIGdsb2JhbCBCaWdJbnQgY29uc3RydWN0b3IsIGl0XG4gICAgICogYWxsb3dzIGJyb3dzZXJzIHRoYXQgZG9lc24ndCBzdXBwb3J0IEJpZ0ludCB0byBydW5cbiAgICAgKiB0aGUgbGlicmFyeSB3aXRob3V0IGJyZWFraW5nIGR1ZSB0byBcInVuZGVmaW5lZCBCaWdJbnRcIlxuICAgICAqIGVycm9ycy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRCaWdJbnRDb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93WydCaWdJbnQnXSB8fCBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgcmV0dXJuIGdsb2JhbFsnQmlnSW50J10gfHwgbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICByZXR1cm4gc2VsZlsnQmlnSW50J10gfHwgbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcJ3Qgc2VhcmNoIGdsb2JhbHMgZm9yIEJpZ0ludCEnKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVXNlZCB0byBzdG9yZSB0aGUgQmlnSW50IGNvbnN0cnVjdG9yLlxuICAgICAqL1xuICAgIGxldCBCaWdJbnRlZ2VyO1xuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gY3JlYXRlcyBhIGJpZ2ludCB2YWx1ZS4gSXQgYWxsb3dzIGJyb3dzZXJzXG4gICAgICogdGhhdCBkb2Vzbid0IHN1cHBvcnQgQmlnSW50IHRvIHJ1biB0aGUgcmVzdCBvZiB0aGUgbGlicmFyeVxuICAgICAqIGJ5IG5vdCBkaXJlY3RseSBhY2Nlc3NpbmcgdGhlIEJpZ0ludCBjb25zdHJ1Y3Rvci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVCaWdJbnQobnVtKSB7XG4gICAgICAgIGlmICh0eXBlb2YgQmlnSW50ZWdlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIEJpZ0ludGVnZXIgPSBnZXRCaWdJbnRDb25zdHJ1Y3RvcigpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChCaWdJbnRlZ2VyID09PSBudWxsKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0JpZ0ludCBpcyBub3Qgc3VwcG9ydGVkIScpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBCaWdJbnRlZ2VyKG51bSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGdldEVYUDkwMCgpIHtcbiAgICAgICAgLy8gaW4gSmF2YSAtIGFycmF5IHdpdGggbGVuZ3RoID0gMTZcbiAgICAgICAgbGV0IEVYUDkwMCA9IFtdO1xuICAgICAgICBFWFA5MDBbMF0gPSBjcmVhdGVCaWdJbnQoMSk7XG4gICAgICAgIGxldCBuaW5lSHVuZHJlZCA9IGNyZWF0ZUJpZ0ludCg5MDApO1xuICAgICAgICBFWFA5MDBbMV0gPSBuaW5lSHVuZHJlZDtcbiAgICAgICAgLy8gaW4gSmF2YSAtIGFycmF5IHdpdGggbGVuZ3RoID0gMTZcbiAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMjsgaSA8IDE2OyBpKyspIHtcbiAgICAgICAgICAgIEVYUDkwMFtpXSA9IEVYUDkwMFtpIC0gMV0gKiBuaW5lSHVuZHJlZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gRVhQOTAwO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiA8cD5UaGlzIGNsYXNzIGNvbnRhaW5zIHRoZSBtZXRob2RzIGZvciBkZWNvZGluZyB0aGUgUERGNDE3IGNvZGV3b3Jkcy48L3A+XG4gICAgICpcbiAgICAgKiBAYXV0aG9yIFNJVEEgTGFiIChrZXZpbi5vc3VsbGl2YW5Ac2l0YS5hZXJvKVxuICAgICAqIEBhdXRob3IgR3VlbnRoZXIgR3JhdVxuICAgICAqL1xuICAgIC8qZmluYWwqLyBjbGFzcyBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIge1xuICAgICAgICAvLyAgIHByaXZhdGUgRGVjb2RlZEJpdFN0cmVhbVBhcnNlcigpIHtcbiAgICAgICAgLy8gfVxuICAgICAgICAvKipcbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGNvZGV3b3Jkc1xuICAgICAgICAgKiBAcGFyYW0gZWNMZXZlbFxuICAgICAgICAgKlxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGRlY29kZShjb2Rld29yZHMsIGVjTGV2ZWwpIHtcbiAgICAgICAgICAgIC8vIHBhc3MgZW5jb2RpbmcgdG8gcmVzdWx0ICh3aWxsIGJlIHVzZWQgZm9yIGRlY29kZSBzeW1ib2xzIGluIGJ5dGUgbW9kZSlcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSBuZXcgU3RyaW5nQnVpbGRlcignJyk7XG4gICAgICAgICAgICAvLyBsZXQgZW5jb2Rpbmc6IENoYXJzZXQgPSBTdGFuZGFyZENoYXJzZXRzLklTT184ODU5XzE7XG4gICAgICAgICAgICBsZXQgZW5jb2RpbmcgPSBDaGFyYWN0ZXJTZXRFQ0kuSVNPODg1OV8xO1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAbm90ZSB0aGUgbmV4dCBjb21tYW5kIGlzIHNwZWNpZmljIGZyb20gdGhpcyBUeXBlU2NyaXB0IGxpYnJhcnlcbiAgICAgICAgICAgICAqIGJlY2F1c2UgVFMgY2FuJ3QgcHJvcGVybHkgY2FzdCBzb21lIHZhbHVlcyB0byBjaGFyIGFuZFxuICAgICAgICAgICAgICogY29udmVydCBpdCB0byBzdHJpbmcgbGF0ZXIgY29ycmVjdGx5IGR1ZSB0byBlbmNvZGluZ1xuICAgICAgICAgICAgICogZGlmZmVyZW5jZXMgZnJvbSBKYXZhIHZlcnNpb24uIEFzIHJlcG9ydGVkIGhlcmU6XG4gICAgICAgICAgICAgKiBodHRwczovL2dpdGh1Yi5jb20venhpbmctanMvbGlicmFyeS9wdWxsLzI2NC9maWxlcyNyMzgyODMxNTkzXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHJlc3VsdC5lbmFibGVEZWNvZGluZyhlbmNvZGluZyk7XG4gICAgICAgICAgICAvLyBHZXQgY29tcGFjdGlvbiBtb2RlXG4gICAgICAgICAgICBsZXQgY29kZUluZGV4ID0gMTtcbiAgICAgICAgICAgIGxldCBjb2RlID0gY29kZXdvcmRzW2NvZGVJbmRleCsrXTtcbiAgICAgICAgICAgIGxldCByZXN1bHRNZXRhZGF0YSA9IG5ldyBQREY0MTdSZXN1bHRNZXRhZGF0YSgpO1xuICAgICAgICAgICAgd2hpbGUgKGNvZGVJbmRleCA8IGNvZGV3b3Jkc1swXSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoY29kZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5URVhUX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVJbmRleCA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi50ZXh0Q29tcGFjdGlvbihjb2Rld29yZHMsIGNvZGVJbmRleCwgcmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CWVRFX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQllURV9DT01QQUNUSU9OX01PREVfTEFUQ0hfNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVJbmRleCA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5ieXRlQ29tcGFjdGlvbihjb2RlLCBjb2Rld29yZHMsIGVuY29kaW5nLCBjb2RlSW5kZXgsIHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTU9ERV9TSElGVF9UT19CWVRFX0NPTVBBQ1RJT05fTU9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoLyooY2hhcikqLyBjb2Rld29yZHNbY29kZUluZGV4KytdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5OVU1FUklDX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVJbmRleCA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5udW1lcmljQ29tcGFjdGlvbihjb2Rld29yZHMsIGNvZGVJbmRleCwgcmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5FQ0lfQ0hBUlNFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjaGFyc2V0RUNJID0gQ2hhcmFjdGVyU2V0RUNJLmdldENoYXJhY3RlclNldEVDSUJ5VmFsdWUoY29kZXdvcmRzW2NvZGVJbmRleCsrXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBlbmNvZGluZyA9IENoYXJzZXQuZm9yTmFtZShjaGFyc2V0RUNJLmdldE5hbWUoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuRUNJX0dFTkVSQUxfUFVSUE9TRTpcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIENhbid0IGRvIGFueXRoaW5nIHdpdGggZ2VuZXJpYyBFQ0k7IHNraXAgaXRzIDIgY2hhcmFjdGVyc1xuICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4ICs9IDI7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuRUNJX1VTRVJfREVGSU5FRDpcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIENhbid0IGRvIGFueXRoaW5nIHdpdGggdXNlciBFQ0k7IHNraXAgaXRzIDEgY2hhcmFjdGVyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2RlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CRUdJTl9NQUNST19QREY0MTdfQ09OVFJPTF9CTE9DSzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVJbmRleCA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5kZWNvZGVNYWNyb0Jsb2NrKGNvZGV3b3JkcywgY29kZUluZGV4LCByZXN1bHRNZXRhZGF0YSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQkVHSU5fTUFDUk9fUERGNDE3X09QVElPTkFMX0ZJRUxEOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQUNST19QREY0MTdfVEVSTUlOQVRPUjpcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNob3VsZCBub3Qgc2VlIHRoZXNlIG91dHNpZGUgYSBtYWNybyBibG9ja1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRGVmYXVsdCB0byB0ZXh0IGNvbXBhY3Rpb24uIER1cmluZyB0ZXN0aW5nIG51bWVyb3VzIGJhcmNvZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhcHBlYXJlZCB0byBiZSBtaXNzaW5nIHRoZSBzdGFydGluZyBtb2RlLiBJbiB0aGVzZSBjYXNlcyBkZWZhdWx0aW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0byB0ZXh0IGNvbXBhY3Rpb24gc2VlbXMgdG8gd29yay5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVJbmRleC0tO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4ID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLnRleHRDb21wYWN0aW9uKGNvZGV3b3JkcywgY29kZUluZGV4LCByZXN1bHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjb2RlSW5kZXggPCBjb2Rld29yZHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvZGUgPSBjb2Rld29yZHNbY29kZUluZGV4KytdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgRm9ybWF0RXhjZXB0aW9uLmdldEZvcm1hdEluc3RhbmNlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJlc3VsdC5sZW5ndGgoKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IEZvcm1hdEV4Y2VwdGlvbi5nZXRGb3JtYXRJbnN0YW5jZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGRlY29kZXJSZXN1bHQgPSBuZXcgRGVjb2RlclJlc3VsdChudWxsLCByZXN1bHQudG9TdHJpbmcoKSwgbnVsbCwgZWNMZXZlbCk7XG4gICAgICAgICAgICBkZWNvZGVyUmVzdWx0LnNldE90aGVyKHJlc3VsdE1ldGFkYXRhKTtcbiAgICAgICAgICAgIHJldHVybiBkZWNvZGVyUmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gaW50XG4gICAgICAgICAqIEBwYXJhbSBwYXJhbTFcbiAgICAgICAgICogQHBhcmFtIGNvZGV3b3Jkc1xuICAgICAgICAgKiBAcGFyYW0gaW50XG4gICAgICAgICAqIEBwYXJhbSBjb2RlSW5kZXhcbiAgICAgICAgICogQHBhcmFtIFBERjQxN1Jlc3VsdE1ldGFkYXRhXG4gICAgICAgICAqIEBwYXJhbSByZXN1bHRNZXRhZGF0YVxuICAgICAgICAgKlxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgLy8gQFN1cHByZXNzV2FybmluZ3MoXCJkZXByZWNhdGlvblwiKVxuICAgICAgICBzdGF0aWMgZGVjb2RlTWFjcm9CbG9jayhjb2Rld29yZHMsIGNvZGVJbmRleCwgcmVzdWx0TWV0YWRhdGEpIHtcbiAgICAgICAgICAgIGlmIChjb2RlSW5kZXggKyBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTlVNQkVSX09GX1NFUVVFTkNFX0NPREVXT1JEUyA+IGNvZGV3b3Jkc1swXSkge1xuICAgICAgICAgICAgICAgIC8vIHdlIG11c3QgaGF2ZSBhdCBsZWFzdCB0d28gYnl0ZXMgbGVmdCBmb3IgdGhlIHNlZ21lbnQgaW5kZXhcbiAgICAgICAgICAgICAgICB0aHJvdyBGb3JtYXRFeGNlcHRpb24uZ2V0Rm9ybWF0SW5zdGFuY2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBzZWdtZW50SW5kZXhBcnJheSA9IG5ldyBJbnQzMkFycmF5KERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5OVU1CRVJfT0ZfU0VRVUVOQ0VfQ09ERVdPUkRTKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTlVNQkVSX09GX1NFUVVFTkNFX0NPREVXT1JEUzsgaSsrLCBjb2RlSW5kZXgrKykge1xuICAgICAgICAgICAgICAgIHNlZ21lbnRJbmRleEFycmF5W2ldID0gY29kZXdvcmRzW2NvZGVJbmRleF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXN1bHRNZXRhZGF0YS5zZXRTZWdtZW50SW5kZXgoSW50ZWdlci5wYXJzZUludChEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuZGVjb2RlQmFzZTkwMHRvQmFzZTEwKHNlZ21lbnRJbmRleEFycmF5LCBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTlVNQkVSX09GX1NFUVVFTkNFX0NPREVXT1JEUykpKTtcbiAgICAgICAgICAgIGxldCBmaWxlSWQgPSBuZXcgU3RyaW5nQnVpbGRlcigpO1xuICAgICAgICAgICAgY29kZUluZGV4ID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLnRleHRDb21wYWN0aW9uKGNvZGV3b3JkcywgY29kZUluZGV4LCBmaWxlSWQpO1xuICAgICAgICAgICAgcmVzdWx0TWV0YWRhdGEuc2V0RmlsZUlkKGZpbGVJZC50b1N0cmluZygpKTtcbiAgICAgICAgICAgIGxldCBvcHRpb25hbEZpZWxkc1N0YXJ0ID0gLTE7XG4gICAgICAgICAgICBpZiAoY29kZXdvcmRzW2NvZGVJbmRleF0gPT09IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CRUdJTl9NQUNST19QREY0MTdfT1BUSU9OQUxfRklFTEQpIHtcbiAgICAgICAgICAgICAgICBvcHRpb25hbEZpZWxkc1N0YXJ0ID0gY29kZUluZGV4ICsgMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdoaWxlIChjb2RlSW5kZXggPCBjb2Rld29yZHNbMF0pIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGNvZGV3b3Jkc1tjb2RlSW5kZXhdKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJFR0lOX01BQ1JPX1BERjQxN19PUFRJT05BTF9GSUVMRDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChjb2Rld29yZHNbY29kZUluZGV4XSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BQ1JPX1BERjQxN19PUFRJT05BTF9GSUVMRF9GSUxFX05BTUU6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmaWxlTmFtZSA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVJbmRleCA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi50ZXh0Q29tcGFjdGlvbihjb2Rld29yZHMsIGNvZGVJbmRleCArIDEsIGZpbGVOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0TWV0YWRhdGEuc2V0RmlsZU5hbWUoZmlsZU5hbWUudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BQ1JPX1BERjQxN19PUFRJT05BTF9GSUVMRF9TRU5ERVI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzZW5kZXIgPSBuZXcgU3RyaW5nQnVpbGRlcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2RlSW5kZXggPSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIudGV4dENvbXBhY3Rpb24oY29kZXdvcmRzLCBjb2RlSW5kZXggKyAxLCBzZW5kZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRNZXRhZGF0YS5zZXRTZW5kZXIoc2VuZGVyLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQUNST19QREY0MTdfT1BUSU9OQUxfRklFTERfQUREUkVTU0VFOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgYWRkcmVzc2VlID0gbmV3IFN0cmluZ0J1aWxkZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4ID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLnRleHRDb21wYWN0aW9uKGNvZGV3b3JkcywgY29kZUluZGV4ICsgMSwgYWRkcmVzc2VlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0TWV0YWRhdGEuc2V0QWRkcmVzc2VlKGFkZHJlc3NlZS50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUFDUk9fUERGNDE3X09QVElPTkFMX0ZJRUxEX1NFR01FTlRfQ09VTlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzZWdtZW50Q291bnQgPSBuZXcgU3RyaW5nQnVpbGRlcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2RlSW5kZXggPSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIubnVtZXJpY0NvbXBhY3Rpb24oY29kZXdvcmRzLCBjb2RlSW5kZXggKyAxLCBzZWdtZW50Q291bnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRNZXRhZGF0YS5zZXRTZWdtZW50Q291bnQoSW50ZWdlci5wYXJzZUludChzZWdtZW50Q291bnQudG9TdHJpbmcoKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQUNST19QREY0MTdfT1BUSU9OQUxfRklFTERfVElNRV9TVEFNUDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHRpbWVzdGFtcCA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVJbmRleCA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5udW1lcmljQ29tcGFjdGlvbihjb2Rld29yZHMsIGNvZGVJbmRleCArIDEsIHRpbWVzdGFtcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdE1ldGFkYXRhLnNldFRpbWVzdGFtcChMb25nLnBhcnNlTG9uZyh0aW1lc3RhbXAudG9TdHJpbmcoKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQUNST19QREY0MTdfT1BUSU9OQUxfRklFTERfQ0hFQ0tTVU06XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjaGVja3N1bSA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVJbmRleCA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5udW1lcmljQ29tcGFjdGlvbihjb2Rld29yZHMsIGNvZGVJbmRleCArIDEsIGNoZWNrc3VtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0TWV0YWRhdGEuc2V0Q2hlY2tzdW0oSW50ZWdlci5wYXJzZUludChjaGVja3N1bS50b1N0cmluZygpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BQ1JPX1BERjQxN19PUFRJT05BTF9GSUVMRF9GSUxFX1NJWkU6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmaWxlU2l6ZSA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVJbmRleCA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5udW1lcmljQ29tcGFjdGlvbihjb2Rld29yZHMsIGNvZGVJbmRleCArIDEsIGZpbGVTaXplKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0TWV0YWRhdGEuc2V0RmlsZVNpemUoTG9uZy5wYXJzZUxvbmcoZmlsZVNpemUudG9TdHJpbmcoKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBGb3JtYXRFeGNlcHRpb24uZ2V0Rm9ybWF0SW5zdGFuY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQUNST19QREY0MTdfVEVSTUlOQVRPUjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0TWV0YWRhdGEuc2V0TGFzdFNlZ21lbnQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IEZvcm1hdEV4Y2VwdGlvbi5nZXRGb3JtYXRJbnN0YW5jZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGNvcHkgb3B0aW9uYWwgZmllbGRzIHRvIGFkZGl0aW9uYWwgb3B0aW9uc1xuICAgICAgICAgICAgaWYgKG9wdGlvbmFsRmllbGRzU3RhcnQgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbGV0IG9wdGlvbmFsRmllbGRzTGVuZ3RoID0gY29kZUluZGV4IC0gb3B0aW9uYWxGaWVsZHNTdGFydDtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0TWV0YWRhdGEuaXNMYXN0U2VnbWVudCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGRvIG5vdCBpbmNsdWRlIHRlcm1pbmF0b3JcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWxGaWVsZHNMZW5ndGgtLTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzdWx0TWV0YWRhdGEuc2V0T3B0aW9uYWxEYXRhKEFycmF5cy5jb3B5T2ZSYW5nZShjb2Rld29yZHMsIG9wdGlvbmFsRmllbGRzU3RhcnQsIG9wdGlvbmFsRmllbGRzU3RhcnQgKyBvcHRpb25hbEZpZWxkc0xlbmd0aCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGNvZGVJbmRleDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogVGV4dCBDb21wYWN0aW9uIG1vZGUgKHNlZSA1LjQuMS41KSBwZXJtaXRzIGFsbCBwcmludGFibGUgQVNDSUkgY2hhcmFjdGVycyB0byBiZVxuICAgICAgICAgKiBlbmNvZGVkLCBpLmUuIHZhbHVlcyAzMiAtIDEyNiBpbmNsdXNpdmUgaW4gYWNjb3JkYW5jZSB3aXRoIElTTy9JRUMgNjQ2IChJUlYpLCBhc1xuICAgICAgICAgKiB3ZWxsIGFzIHNlbGVjdGVkIGNvbnRyb2wgY2hhcmFjdGVycy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGNvZGV3b3JkcyBUaGUgYXJyYXkgb2YgY29kZXdvcmRzIChkYXRhICsgZXJyb3IpXG4gICAgICAgICAqIEBwYXJhbSBjb2RlSW5kZXggVGhlIGN1cnJlbnQgaW5kZXggaW50byB0aGUgY29kZXdvcmQgYXJyYXkuXG4gICAgICAgICAqIEBwYXJhbSByZXN1bHQgICAgVGhlIGRlY29kZWQgZGF0YSBpcyBhcHBlbmRlZCB0byB0aGUgcmVzdWx0LlxuICAgICAgICAgKiBAcmV0dXJuIFRoZSBuZXh0IGluZGV4IGludG8gdGhlIGNvZGV3b3JkIGFycmF5LlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIHRleHRDb21wYWN0aW9uKGNvZGV3b3JkcywgY29kZUluZGV4LCByZXN1bHQpIHtcbiAgICAgICAgICAgIC8vIDIgY2hhcmFjdGVyIHBlciBjb2Rld29yZFxuICAgICAgICAgICAgbGV0IHRleHRDb21wYWN0aW9uRGF0YSA9IG5ldyBJbnQzMkFycmF5KChjb2Rld29yZHNbMF0gLSBjb2RlSW5kZXgpICogMik7XG4gICAgICAgICAgICAvLyBVc2VkIHRvIGhvbGQgdGhlIGJ5dGUgY29tcGFjdGlvbiB2YWx1ZSBpZiB0aGVyZSBpcyBhIG1vZGUgc2hpZnRcbiAgICAgICAgICAgIGxldCBieXRlQ29tcGFjdGlvbkRhdGEgPSBuZXcgSW50MzJBcnJheSgoY29kZXdvcmRzWzBdIC0gY29kZUluZGV4KSAqIDIpO1xuICAgICAgICAgICAgbGV0IGluZGV4ID0gMDtcbiAgICAgICAgICAgIGxldCBlbmQgPSBmYWxzZTtcbiAgICAgICAgICAgIHdoaWxlICgoY29kZUluZGV4IDwgY29kZXdvcmRzWzBdKSAmJiAhZW5kKSB7XG4gICAgICAgICAgICAgICAgbGV0IGNvZGUgPSBjb2Rld29yZHNbY29kZUluZGV4KytdO1xuICAgICAgICAgICAgICAgIGlmIChjb2RlIDwgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlRFWFRfQ09NUEFDVElPTl9NT0RFX0xBVENIKSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHRDb21wYWN0aW9uRGF0YVtpbmRleF0gPSBjb2RlIC8gMzA7XG4gICAgICAgICAgICAgICAgICAgIHRleHRDb21wYWN0aW9uRGF0YVtpbmRleCArIDFdID0gY29kZSAlIDMwO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChjb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5URVhUX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyByZWluaXRpYWxpemUgdGV4dCBjb21wYWN0aW9uIG1vZGUgdG8gYWxwaGEgc3ViIG1vZGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0Q29tcGFjdGlvbkRhdGFbaW5kZXgrK10gPSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuVEVYVF9DT01QQUNUSU9OX01PREVfTEFUQ0g7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CWVRFX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJZVEVfQ09NUEFDVElPTl9NT0RFX0xBVENIXzY6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5OVU1FUklDX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJFR0lOX01BQ1JPX1BERjQxN19DT05UUk9MX0JMT0NLOlxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQkVHSU5fTUFDUk9fUERGNDE3X09QVElPTkFMX0ZJRUxEOlxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUFDUk9fUERGNDE3X1RFUk1JTkFUT1I6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4LS07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1PREVfU0hJRlRfVE9fQllURV9DT01QQUNUSU9OX01PREU6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlIE1vZGUgU2hpZnQgY29kZXdvcmQgOTEzIHNoYWxsIGNhdXNlIGEgdGVtcG9yYXJ5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3dpdGNoIGZyb20gVGV4dCBDb21wYWN0aW9uIG1vZGUgdG8gQnl0ZSBDb21wYWN0aW9uIG1vZGUuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBzd2l0Y2ggc2hhbGwgYmUgaW4gZWZmZWN0IGZvciBvbmx5IHRoZSBuZXh0IGNvZGV3b3JkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFmdGVyIHdoaWNoIHRoZSBtb2RlIHNoYWxsIHJldmVydCB0byB0aGUgcHJldmFpbGluZyBzdWItbW9kZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9mIHRoZSBUZXh0IENvbXBhY3Rpb24gbW9kZS4gQ29kZXdvcmQgOTEzIGlzIG9ubHkgYXZhaWxhYmxlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gVGV4dCBDb21wYWN0aW9uIG1vZGU7IGl0cyB1c2UgaXMgZGVzY3JpYmVkIGluIDUuNC4yLjQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dENvbXBhY3Rpb25EYXRhW2luZGV4XSA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NT0RFX1NISUZUX1RPX0JZVEVfQ09NUEFDVElPTl9NT0RFO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGUgPSBjb2Rld29yZHNbY29kZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVDb21wYWN0aW9uRGF0YVtpbmRleF0gPSBjb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuZGVjb2RlVGV4dENvbXBhY3Rpb24odGV4dENvbXBhY3Rpb25EYXRhLCBieXRlQ29tcGFjdGlvbkRhdGEsIGluZGV4LCByZXN1bHQpO1xuICAgICAgICAgICAgcmV0dXJuIGNvZGVJbmRleDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogVGhlIFRleHQgQ29tcGFjdGlvbiBtb2RlIGluY2x1ZGVzIGFsbCB0aGUgcHJpbnRhYmxlIEFTQ0lJIGNoYXJhY3RlcnNcbiAgICAgICAgICogKGkuZS4gdmFsdWVzIGZyb20gMzIgdG8gMTI2KSBhbmQgdGhyZWUgQVNDSUkgY29udHJvbCBjaGFyYWN0ZXJzOiBIVCBvciB0YWJcbiAgICAgICAgICogKDk6IGUpLCBMRiBvciBsaW5lIGZlZWQgKDEwOiBlKSwgYW5kIENSIG9yIGNhcnJpYWdlXG4gICAgICAgICAqIHJldHVybiAoMTM6IGUpLiBUaGUgVGV4dCBDb21wYWN0aW9uIG1vZGUgYWxzbyBpbmNsdWRlcyB2YXJpb3VzIGxhdGNoXG4gICAgICAgICAqIGFuZCBzaGlmdCBjaGFyYWN0ZXJzIHdoaWNoIGFyZSB1c2VkIGV4Y2x1c2l2ZWx5IHdpdGhpbiB0aGUgbW9kZS4gVGhlIFRleHRcbiAgICAgICAgICogQ29tcGFjdGlvbiBtb2RlIGVuY29kZXMgdXAgdG8gMiBjaGFyYWN0ZXJzIHBlciBjb2Rld29yZC4gVGhlIGNvbXBhY3Rpb24gcnVsZXNcbiAgICAgICAgICogZm9yIGNvbnZlcnRpbmcgZGF0YSBpbnRvIFBERjQxNyBjb2Rld29yZHMgYXJlIGRlZmluZWQgaW4gNS40LjIuMi4gVGhlIHN1Yi1tb2RlXG4gICAgICAgICAqIHN3aXRjaGVzIGFyZSBkZWZpbmVkIGluIDUuNC4yLjMuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB0ZXh0Q29tcGFjdGlvbkRhdGEgVGhlIHRleHQgY29tcGFjdGlvbiBkYXRhLlxuICAgICAgICAgKiBAcGFyYW0gYnl0ZUNvbXBhY3Rpb25EYXRhIFRoZSBieXRlIGNvbXBhY3Rpb24gZGF0YSBpZiB0aGVyZVxuICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcyBhIG1vZGUgc2hpZnQuXG4gICAgICAgICAqIEBwYXJhbSBsZW5ndGggICAgICAgICAgICAgVGhlIHNpemUgb2YgdGhlIHRleHQgY29tcGFjdGlvbiBhbmQgYnl0ZSBjb21wYWN0aW9uIGRhdGEuXG4gICAgICAgICAqIEBwYXJhbSByZXN1bHQgICAgICAgICAgICAgVGhlIGRlY29kZWQgZGF0YSBpcyBhcHBlbmRlZCB0byB0aGUgcmVzdWx0LlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGRlY29kZVRleHRDb21wYWN0aW9uKHRleHRDb21wYWN0aW9uRGF0YSwgYnl0ZUNvbXBhY3Rpb25EYXRhLCBsZW5ndGgsIHJlc3VsdCkge1xuICAgICAgICAgICAgLy8gQmVnaW5uaW5nIGZyb20gYW4gaW5pdGlhbCBzdGF0ZSBvZiB0aGUgQWxwaGEgc3ViLW1vZGVcbiAgICAgICAgICAgIC8vIFRoZSBkZWZhdWx0IGNvbXBhY3Rpb24gbW9kZSBmb3IgUERGNDE3IGluIGVmZmVjdCBhdCB0aGUgc3RhcnQgb2YgZWFjaCBzeW1ib2wgc2hhbGwgYWx3YXlzIGJlIFRleHRcbiAgICAgICAgICAgIC8vIENvbXBhY3Rpb24gbW9kZSBBbHBoYSBzdWItbW9kZSAoYWxwaGFiZXRpYzogdXBwZXJjYXNlKS4gQSBsYXRjaCBjb2Rld29yZCBmcm9tIGFub3RoZXIgbW9kZSB0byB0aGUgVGV4dFxuICAgICAgICAgICAgLy8gQ29tcGFjdGlvbiBtb2RlIHNoYWxsIGFsd2F5cyBzd2l0Y2ggdG8gdGhlIFRleHQgQ29tcGFjdGlvbiBBbHBoYSBzdWItbW9kZS5cbiAgICAgICAgICAgIGxldCBzdWJNb2RlID0gTW9kZSQyLkFMUEhBO1xuICAgICAgICAgICAgbGV0IHByaW9yVG9TaGlmdE1vZGUgPSBNb2RlJDIuQUxQSEE7XG4gICAgICAgICAgICBsZXQgaSA9IDA7XG4gICAgICAgICAgICB3aGlsZSAoaSA8IGxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGxldCBzdWJNb2RlQ2ggPSB0ZXh0Q29tcGFjdGlvbkRhdGFbaV07XG4gICAgICAgICAgICAgICAgbGV0IGNoID0gLypjaGFyKi8gJyc7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChzdWJNb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgTW9kZSQyLkFMUEhBOlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWxwaGEgKGFscGhhYmV0aWM6IHVwcGVyY2FzZSlcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdWJNb2RlQ2ggPCAyNikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVwcGVyIGNhc2UgQWxwaGEgQ2hhcmFjdGVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm90ZTogNjUgPSAnQScgQVNDSUkgLT4gdGhlcmUgaXMgYnl0ZSBjb2RlIG9mIHN5bWJvbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoID0gLyooY2hhcikoJ0EnICsgc3ViTW9kZUNoKSAqLyBTdHJpbmcuZnJvbUNoYXJDb2RlKDY1ICsgc3ViTW9kZUNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoc3ViTW9kZUNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjY6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaCA9ICcgJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5MTDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Yk1vZGUgPSBNb2RlJDIuTE9XRVI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUw6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJNb2RlID0gTW9kZSQyLk1JWEVEO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlBTOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2hpZnQgdG8gcHVuY3R1YXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yVG9TaGlmdE1vZGUgPSBzdWJNb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ViTW9kZSA9IE1vZGUkMi5QVU5DVF9TSElGVDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NT0RFX1NISUZUX1RPX0JZVEVfQ09NUEFDVElPTl9NT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgvKihjaGFyKSovIGJ5dGVDb21wYWN0aW9uRGF0YVtpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuVEVYVF9DT01QQUNUSU9OX01PREVfTEFUQ0g6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJNb2RlID0gTW9kZSQyLkFMUEhBO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgTW9kZSQyLkxPV0VSOlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTG93ZXIgKGFscGhhYmV0aWM6IGxvd2VyY2FzZSlcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdWJNb2RlQ2ggPCAyNikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoID0gLyooY2hhcikoJ2EnICsgc3ViTW9kZUNoKSovIFN0cmluZy5mcm9tQ2hhckNvZGUoOTcgKyBzdWJNb2RlQ2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChzdWJNb2RlQ2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyNjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoID0gJyAnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkFTOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2hpZnQgdG8gYWxwaGFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yVG9TaGlmdE1vZGUgPSBzdWJNb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ViTW9kZSA9IE1vZGUkMi5BTFBIQV9TSElGVDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NTDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Yk1vZGUgPSBNb2RlJDIuTUlYRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuUFM6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaGlmdCB0byBwdW5jdHVhdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3JUb1NoaWZ0TW9kZSA9IHN1Yk1vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJNb2RlID0gTW9kZSQyLlBVTkNUX1NISUZUO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1PREVfU0hJRlRfVE9fQllURV9DT01QQUNUSU9OX01PREU6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUT0RPIERvZXMgdGhpcyBuZWVkIHRvIHVzZSB0aGUgY3VycmVudCBjaGFyYWN0ZXIgZW5jb2Rpbmc/IFNlZSBvdGhlciBvY2N1cnJlbmNlcyBiZWxvd1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgvKihjaGFyKSovIGJ5dGVDb21wYWN0aW9uRGF0YVtpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuVEVYVF9DT01QQUNUSU9OX01PREVfTEFUQ0g6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJNb2RlID0gTW9kZSQyLkFMUEhBO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgTW9kZSQyLk1JWEVEOlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWl4ZWQgKHB1bmN0dWF0aW9uOiBlKVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN1Yk1vZGVDaCA8IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5QTCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoID0gRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1JWEVEX0NIQVJTW3N1Yk1vZGVDaF07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHN1Yk1vZGVDaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5QTDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Yk1vZGUgPSBNb2RlJDIuUFVOQ1Q7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyNjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoID0gJyAnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkxMOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ViTW9kZSA9IE1vZGUkMi5MT1dFUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5BTDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Yk1vZGUgPSBNb2RlJDIuQUxQSEE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuUFM6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaGlmdCB0byBwdW5jdHVhdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3JUb1NoaWZ0TW9kZSA9IHN1Yk1vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJNb2RlID0gTW9kZSQyLlBVTkNUX1NISUZUO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1PREVfU0hJRlRfVE9fQllURV9DT01QQUNUSU9OX01PREU6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKC8qKGNoYXIpKi8gYnl0ZUNvbXBhY3Rpb25EYXRhW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5URVhUX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Yk1vZGUgPSBNb2RlJDIuQUxQSEE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBNb2RlJDIuUFVOQ1Q6XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBQdW5jdHVhdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN1Yk1vZGVDaCA8IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5QQUwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaCA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5QVU5DVF9DSEFSU1tzdWJNb2RlQ2hdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChzdWJNb2RlQ2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuUEFMOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ViTW9kZSA9IE1vZGUkMi5BTFBIQTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NT0RFX1NISUZUX1RPX0JZVEVfQ09NUEFDVElPTl9NT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgvKihjaGFyKSovIGJ5dGVDb21wYWN0aW9uRGF0YVtpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuVEVYVF9DT01QQUNUSU9OX01PREVfTEFUQ0g6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJNb2RlID0gTW9kZSQyLkFMUEhBO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgTW9kZSQyLkFMUEhBX1NISUZUOlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVzdG9yZSBzdWItbW9kZVxuICAgICAgICAgICAgICAgICAgICAgICAgc3ViTW9kZSA9IHByaW9yVG9TaGlmdE1vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3ViTW9kZUNoIDwgMjYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaCA9IC8qKGNoYXIpKCdBJyArIHN1Yk1vZGVDaCkqLyBTdHJpbmcuZnJvbUNoYXJDb2RlKDY1ICsgc3ViTW9kZUNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoc3ViTW9kZUNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjY6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaCA9ICcgJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5URVhUX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Yk1vZGUgPSBNb2RlJDIuQUxQSEE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBNb2RlJDIuUFVOQ1RfU0hJRlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBSZXN0b3JlIHN1Yi1tb2RlXG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJNb2RlID0gcHJpb3JUb1NoaWZ0TW9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdWJNb2RlQ2ggPCBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuUEFMKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2ggPSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuUFVOQ1RfQ0hBUlNbc3ViTW9kZUNoXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoc3ViTW9kZUNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlBBTDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Yk1vZGUgPSBNb2RlJDIuQUxQSEE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTU9ERV9TSElGVF9UT19CWVRFX0NPTVBBQ1RJT05fTU9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBTIGJlZm9yZSBTaGlmdC10by1CeXRlIGlzIHVzZWQgYXMgYSBwYWRkaW5nIGNoYXJhY3RlcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNlZSA1LjQuMi40IG9mIHRoZSBzcGVjaWZpY2F0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKC8qKGNoYXIpKi8gYnl0ZUNvbXBhY3Rpb25EYXRhW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5URVhUX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Yk1vZGUgPSBNb2RlJDIuQUxQSEE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gaWYgKGNoICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNoICE9PSAnJykge1xuICAgICAgICAgICAgICAgICAgICAvLyBBcHBlbmQgZGVjb2RlZCBjaGFyYWN0ZXIgdG8gcmVzdWx0XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoY2gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEJ5dGUgQ29tcGFjdGlvbiBtb2RlIChzZWUgNS40LjMpIHBlcm1pdHMgYWxsIDI1NiBwb3NzaWJsZSA4LWJpdCBieXRlIHZhbHVlcyB0byBiZSBlbmNvZGVkLlxuICAgICAgICAgKiBUaGlzIGluY2x1ZGVzIGFsbCBBU0NJSSBjaGFyYWN0ZXJzIHZhbHVlIDAgdG8gMTI3IGluY2x1c2l2ZSBhbmQgcHJvdmlkZXMgZm9yIGludGVybmF0aW9uYWxcbiAgICAgICAgICogY2hhcmFjdGVyIHNldCBzdXBwb3J0LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gbW9kZSAgICAgIFRoZSBieXRlIGNvbXBhY3Rpb24gbW9kZSBpLmUuIDkwMSBvciA5MjRcbiAgICAgICAgICogQHBhcmFtIGNvZGV3b3JkcyBUaGUgYXJyYXkgb2YgY29kZXdvcmRzIChkYXRhICsgZXJyb3IpXG4gICAgICAgICAqIEBwYXJhbSBlbmNvZGluZyAgQ3VycmVudGx5IGFjdGl2ZSBjaGFyYWN0ZXIgZW5jb2RpbmdcbiAgICAgICAgICogQHBhcmFtIGNvZGVJbmRleCBUaGUgY3VycmVudCBpbmRleCBpbnRvIHRoZSBjb2Rld29yZCBhcnJheS5cbiAgICAgICAgICogQHBhcmFtIHJlc3VsdCAgICBUaGUgZGVjb2RlZCBkYXRhIGlzIGFwcGVuZGVkIHRvIHRoZSByZXN1bHQuXG4gICAgICAgICAqIEByZXR1cm4gVGhlIG5leHQgaW5kZXggaW50byB0aGUgY29kZXdvcmQgYXJyYXkuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgLyppbnQqLyBieXRlQ29tcGFjdGlvbihtb2RlLCBjb2Rld29yZHMsIGVuY29kaW5nLCBjb2RlSW5kZXgsIHJlc3VsdCkge1xuICAgICAgICAgICAgbGV0IGRlY29kZWRCeXRlcyA9IG5ldyBCeXRlQXJyYXlPdXRwdXRTdHJlYW0oKTtcbiAgICAgICAgICAgIGxldCBjb3VudCA9IDA7XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSAvKmxvbmcqLyAwO1xuICAgICAgICAgICAgbGV0IGVuZCA9IGZhbHNlO1xuICAgICAgICAgICAgc3dpdGNoIChtb2RlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQllURV9DT01QQUNUSU9OX01PREVfTEFUQ0g6XG4gICAgICAgICAgICAgICAgICAgIC8vIFRvdGFsIG51bWJlciBvZiBCeXRlIENvbXBhY3Rpb24gY2hhcmFjdGVycyB0byBiZSBlbmNvZGVkXG4gICAgICAgICAgICAgICAgICAgIC8vIGlzIG5vdCBhIG11bHRpcGxlIG9mIDZcbiAgICAgICAgICAgICAgICAgICAgbGV0IGJ5dGVDb21wYWN0ZWRDb2Rld29yZHMgPSBuZXcgSW50MzJBcnJheSg2KTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG5leHRDb2RlID0gY29kZXdvcmRzW2NvZGVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKChjb2RlSW5kZXggPCBjb2Rld29yZHNbMF0pICYmICFlbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVDb21wYWN0ZWRDb2Rld29yZHNbY291bnQrK10gPSBuZXh0Q29kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJhc2UgOTAwXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IDkwMCAqIHZhbHVlICsgbmV4dENvZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXh0Q29kZSA9IGNvZGV3b3Jkc1tjb2RlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBwZXJoYXBzIGl0IHNob3VsZCBiZSBvayB0byBjaGVjayBvbmx5IG5leHRDb2RlID49IFRFWFRfQ09NUEFDVElPTl9NT0RFX0xBVENIXG4gICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKG5leHRDb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuVEVYVF9DT01QQUNUSU9OX01PREVfTEFUQ0g6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQllURV9DT01QQUNUSU9OX01PREVfTEFUQ0g6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTlVNRVJJQ19DT01QQUNUSU9OX01PREVfTEFUQ0g6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQllURV9DT01QQUNUSU9OX01PREVfTEFUQ0hfNjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CRUdJTl9NQUNST19QREY0MTdfQ09OVFJPTF9CTE9DSzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CRUdJTl9NQUNST19QREY0MTdfT1BUSU9OQUxfRklFTEQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUFDUk9fUERGNDE3X1RFUk1JTkFUT1I6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVJbmRleC0tO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKGNvdW50ICUgNSA9PT0gMCkgJiYgKGNvdW50ID4gMCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERlY29kZSBldmVyeSA1IGNvZGV3b3Jkc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ29udmVydCB0byBCYXNlIDI1NlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaiAvKmludCovID0gMDsgaiA8IDY7ICsraikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIEBub3RlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogSmF2YVNjcmlwdCBzdG9yZXMgbnVtYmVycyBhcyA2NCBiaXRzIGZsb2F0aW5nIHBvaW50IG51bWJlcnMsIGJ1dCBhbGwgYml0d2lzZSBvcGVyYXRpb25zIGFyZSBwZXJmb3JtZWQgb24gMzIgYml0cyBiaW5hcnkgbnVtYmVycy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBTbyB0aGUgbmV4dCBiaXR3aXNlIG9wZXJhdGlvbiBjb3VsZCBub3QgYmUgZG9uZSB3aXRoIHNpbXBsZSBudW1iZXJzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjb2RlZEJ5dGVzLndyaXRlKC8qKGJ5dGUpKi8gTnVtYmVyKGNyZWF0ZUJpZ0ludCh2YWx1ZSkgPj4gY3JlYXRlQmlnSW50KDggKiAoNSAtIGopKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnQgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSBlbmQgb2YgYWxsIGNvZGV3b3JkcyBpcyByZWFjaGVkIHRoZSBsYXN0IGNvZGV3b3JkIG5lZWRzIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICAgICAgICAgIGlmIChjb2RlSW5kZXggPT09IGNvZGV3b3Jkc1swXSAmJiBuZXh0Q29kZSA8IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5URVhUX0NPTVBBQ1RJT05fTU9ERV9MQVRDSCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZUNvbXBhY3RlZENvZGV3b3Jkc1tjb3VudCsrXSA9IG5leHRDb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIEJ5dGUgQ29tcGFjdGlvbiBtb2RlIGlzIGludm9rZWQgd2l0aCBjb2Rld29yZCA5MDEsXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoZSBsYXN0IGdyb3VwIG9mIGNvZGV3b3JkcyBpcyBpbnRlcnByZXRlZCBkaXJlY3RseVxuICAgICAgICAgICAgICAgICAgICAvLyBhcyBvbmUgYnl0ZSBwZXIgY29kZXdvcmQsIHdpdGhvdXQgY29tcGFjdGlvbi5cbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlY29kZWRCeXRlcy53cml0ZSgvKihieXRlKSovIGJ5dGVDb21wYWN0ZWRDb2Rld29yZHNbaV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJZVEVfQ09NUEFDVElPTl9NT0RFX0xBVENIXzY6XG4gICAgICAgICAgICAgICAgICAgIC8vIFRvdGFsIG51bWJlciBvZiBCeXRlIENvbXBhY3Rpb24gY2hhcmFjdGVycyB0byBiZSBlbmNvZGVkXG4gICAgICAgICAgICAgICAgICAgIC8vIGlzIGFuIGludGVnZXIgbXVsdGlwbGUgb2YgNlxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoY29kZUluZGV4IDwgY29kZXdvcmRzWzBdICYmICFlbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjb2RlID0gY29kZXdvcmRzW2NvZGVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb2RlIDwgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlRFWFRfQ09NUEFDVElPTl9NT0RFX0xBVENIKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnQrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBCYXNlIDkwMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gOTAwICogdmFsdWUgKyBjb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChjb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlRFWFRfQ09NUEFDVElPTl9NT0RFX0xBVENIOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CWVRFX0NPTVBBQ1RJT05fTU9ERV9MQVRDSDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTlVNRVJJQ19DT01QQUNUSU9OX01PREVfTEFUQ0g6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJZVEVfQ09NUEFDVElPTl9NT0RFX0xBVENIXzY6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJFR0lOX01BQ1JPX1BERjQxN19DT05UUk9MX0JMT0NLOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CRUdJTl9NQUNST19QREY0MTdfT1BUSU9OQUxfRklFTEQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BQ1JPX1BERjQxN19URVJNSU5BVE9SOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZUluZGV4LS07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChjb3VudCAlIDUgPT09IDApICYmIChjb3VudCA+IDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRGVjb2RlIGV2ZXJ5IDUgY29kZXdvcmRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ29udmVydCB0byBCYXNlIDI1NlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIEBub3RlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICogSmF2YVNjcmlwdCBzdG9yZXMgbnVtYmVycyBhcyA2NCBiaXRzIGZsb2F0aW5nIHBvaW50IG51bWJlcnMsIGJ1dCBhbGwgYml0d2lzZSBvcGVyYXRpb25zIGFyZSBwZXJmb3JtZWQgb24gMzIgYml0cyBiaW5hcnkgbnVtYmVycy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBTbyB0aGUgbmV4dCBiaXR3aXNlIG9wZXJhdGlvbiBjb3VsZCBub3QgYmUgZG9uZSB3aXRoIHNpbXBsZSBudW1iZXJzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBqIC8qaW50Ki8gPSAwOyBqIDwgNjsgKytqKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY29kZWRCeXRlcy53cml0ZSgvKihieXRlKSovIE51bWJlcihjcmVhdGVCaWdJbnQodmFsdWUpID4+IGNyZWF0ZUJpZ0ludCg4ICogKDUgLSBqKSkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoU3RyaW5nRW5jb2RpbmcuZGVjb2RlKGRlY29kZWRCeXRlcy50b0J5dGVBcnJheSgpLCBlbmNvZGluZykpO1xuICAgICAgICAgICAgcmV0dXJuIGNvZGVJbmRleDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogTnVtZXJpYyBDb21wYWN0aW9uIG1vZGUgKHNlZSA1LjQuNCkgcGVybWl0cyBlZmZpY2llbnQgZW5jb2Rpbmcgb2YgbnVtZXJpYyBkYXRhIHN0cmluZ3MuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBjb2Rld29yZHMgVGhlIGFycmF5IG9mIGNvZGV3b3JkcyAoZGF0YSArIGVycm9yKVxuICAgICAgICAgKiBAcGFyYW0gY29kZUluZGV4IFRoZSBjdXJyZW50IGluZGV4IGludG8gdGhlIGNvZGV3b3JkIGFycmF5LlxuICAgICAgICAgKiBAcGFyYW0gcmVzdWx0ICAgIFRoZSBkZWNvZGVkIGRhdGEgaXMgYXBwZW5kZWQgdG8gdGhlIHJlc3VsdC5cbiAgICAgICAgICogQHJldHVybiBUaGUgbmV4dCBpbmRleCBpbnRvIHRoZSBjb2Rld29yZCBhcnJheS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBudW1lcmljQ29tcGFjdGlvbihjb2Rld29yZHMsIGNvZGVJbmRleCAvKmludCovLCByZXN1bHQpIHtcbiAgICAgICAgICAgIGxldCBjb3VudCA9IDA7XG4gICAgICAgICAgICBsZXQgZW5kID0gZmFsc2U7XG4gICAgICAgICAgICBsZXQgbnVtZXJpY0NvZGV3b3JkcyA9IG5ldyBJbnQzMkFycmF5KERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQVhfTlVNRVJJQ19DT0RFV09SRFMpO1xuICAgICAgICAgICAgd2hpbGUgKGNvZGVJbmRleCA8IGNvZGV3b3Jkc1swXSAmJiAhZW5kKSB7XG4gICAgICAgICAgICAgICAgbGV0IGNvZGUgPSBjb2Rld29yZHNbY29kZUluZGV4KytdO1xuICAgICAgICAgICAgICAgIGlmIChjb2RlSW5kZXggPT09IGNvZGV3b3Jkc1swXSkge1xuICAgICAgICAgICAgICAgICAgICBlbmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY29kZSA8IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5URVhUX0NPTVBBQ1RJT05fTU9ERV9MQVRDSCkge1xuICAgICAgICAgICAgICAgICAgICBudW1lcmljQ29kZXdvcmRzW2NvdW50XSA9IGNvZGU7XG4gICAgICAgICAgICAgICAgICAgIGNvdW50Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGNvZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlRFWFRfQ09NUEFDVElPTl9NT0RFX0xBVENIOlxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQllURV9DT01QQUNUSU9OX01PREVfTEFUQ0g6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CWVRFX0NPTVBBQ1RJT05fTU9ERV9MQVRDSF82OlxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQkVHSU5fTUFDUk9fUERGNDE3X0NPTlRST0xfQkxPQ0s6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CRUdJTl9NQUNST19QREY0MTdfT1BUSU9OQUxfRklFTEQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQUNST19QREY0MTdfVEVSTUlOQVRPUjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2RlSW5kZXgtLTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICgoY291bnQgJSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUFYX05VTUVSSUNfQ09ERVdPUkRTID09PSAwIHx8IGNvZGUgPT09IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5OVU1FUklDX0NPTVBBQ1RJT05fTU9ERV9MQVRDSCB8fCBlbmQpICYmIGNvdW50ID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZS1pbnZva2luZyBOdW1lcmljIENvbXBhY3Rpb24gbW9kZSAoYnkgdXNpbmcgY29kZXdvcmQgOTAyXG4gICAgICAgICAgICAgICAgICAgIC8vIHdoaWxlIGluIE51bWVyaWMgQ29tcGFjdGlvbiBtb2RlKSBzZXJ2ZXMgIHRvIHRlcm1pbmF0ZSB0aGVcbiAgICAgICAgICAgICAgICAgICAgLy8gY3VycmVudCBOdW1lcmljIENvbXBhY3Rpb24gbW9kZSBncm91cGluZyBhcyBkZXNjcmliZWQgaW4gNS40LjQuMixcbiAgICAgICAgICAgICAgICAgICAgLy8gYW5kIHRoZW4gdG8gc3RhcnQgYSBuZXcgb25lIGdyb3VwaW5nLlxuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5kZWNvZGVCYXNlOTAwdG9CYXNlMTAobnVtZXJpY0NvZGV3b3JkcywgY291bnQpKTtcbiAgICAgICAgICAgICAgICAgICAgY291bnQgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBjb2RlSW5kZXg7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnZlcnQgYSBsaXN0IG9mIE51bWVyaWMgQ29tcGFjdGVkIGNvZGV3b3JkcyBmcm9tIEJhc2UgOTAwIHRvIEJhc2UgMTAuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBjb2Rld29yZHMgVGhlIGFycmF5IG9mIGNvZGV3b3Jkc1xuICAgICAgICAgKiBAcGFyYW0gY291bnQgICAgIFRoZSBudW1iZXIgb2YgY29kZXdvcmRzXG4gICAgICAgICAqIEByZXR1cm4gVGhlIGRlY29kZWQgc3RyaW5nIHJlcHJlc2VudGluZyB0aGUgTnVtZXJpYyBkYXRhLlxuICAgICAgICAgKlxuICAgICAgICAgKiBFWEFNUExFXG4gICAgICAgICAqIEVuY29kZSB0aGUgZmlmdGVlbiBkaWdpdCBudW1lcmljIHN0cmluZyAwMDAyMTMyOTgxNzQwMDBcbiAgICAgICAgICogUHJlZml4IHRoZSBudW1lcmljIHN0cmluZyB3aXRoIGEgMSBhbmQgc2V0IHRoZSBpbml0aWFsIHZhbHVlIG9mXG4gICAgICAgICAqIHQgPSAxIDAwMCAyMTMgMjk4IDE3NCAwMDBcbiAgICAgICAgICogQ2FsY3VsYXRlIGNvZGV3b3JkIDBcbiAgICAgICAgICogZDAgPSAxIDAwMCAyMTMgMjk4IDE3NCAwMDAgbW9kIDkwMCA9IDIwMFxuICAgICAgICAgKlxuICAgICAgICAgKiB0ID0gMSAwMDAgMjEzIDI5OCAxNzQgMDAwIGRpdiA5MDAgPSAxIDExMSAzNDggMTA5IDA4MlxuICAgICAgICAgKiBDYWxjdWxhdGUgY29kZXdvcmQgMVxuICAgICAgICAgKiBkMSA9IDEgMTExIDM0OCAxMDkgMDgyIG1vZCA5MDAgPSAyODJcbiAgICAgICAgICpcbiAgICAgICAgICogdCA9IDEgMTExIDM0OCAxMDkgMDgyIGRpdiA5MDAgPSAxIDIzNCA4MzEgMjMyXG4gICAgICAgICAqIENhbGN1bGF0ZSBjb2Rld29yZCAyXG4gICAgICAgICAqIGQyID0gMSAyMzQgODMxIDIzMiBtb2QgOTAwID0gNjMyXG4gICAgICAgICAqXG4gICAgICAgICAqIHQgPSAxIDIzNCA4MzEgMjMyIGRpdiA5MDAgPSAxIDM3MiAwMzRcbiAgICAgICAgICogQ2FsY3VsYXRlIGNvZGV3b3JkIDNcbiAgICAgICAgICogZDMgPSAxIDM3MiAwMzQgbW9kIDkwMCA9IDQzNFxuICAgICAgICAgKlxuICAgICAgICAgKiB0ID0gMSAzNzIgMDM0IGRpdiA5MDAgPSAxIDUyNFxuICAgICAgICAgKiBDYWxjdWxhdGUgY29kZXdvcmQgNFxuICAgICAgICAgKiBkNCA9IDEgNTI0IG1vZCA5MDAgPSA2MjRcbiAgICAgICAgICpcbiAgICAgICAgICogdCA9IDEgNTI0IGRpdiA5MDAgPSAxXG4gICAgICAgICAqIENhbGN1bGF0ZSBjb2Rld29yZCA1XG4gICAgICAgICAqIGQ1ID0gMSBtb2QgOTAwID0gMVxuICAgICAgICAgKiB0ID0gMSBkaXYgOTAwID0gMFxuICAgICAgICAgKiBDb2Rld29yZCBzZXF1ZW5jZSBpczogMSwgNjI0LCA0MzQsIDYzMiwgMjgyLCAyMDBcbiAgICAgICAgICpcbiAgICAgICAgICogRGVjb2RlIHRoZSBhYm92ZSBjb2Rld29yZHMgaW52b2x2ZXNcbiAgICAgICAgICogICAxIHggOTAwIHBvd2VyIG9mIDUgKyA2MjQgeCA5MDAgcG93ZXIgb2YgNCArIDQzNCB4IDkwMCBwb3dlciBvZiAzICtcbiAgICAgICAgICogNjMyIHggOTAwIHBvd2VyIG9mIDIgKyAyODIgeCA5MDAgcG93ZXIgb2YgMSArIDIwMCB4IDkwMCBwb3dlciBvZiAwID0gMTAwMDIxMzI5ODE3NDAwMFxuICAgICAgICAgKlxuICAgICAgICAgKiBSZW1vdmUgbGVhZGluZyAxID0+ICBSZXN1bHQgaXMgMDAwMjEzMjk4MTc0MDAwXG4gICAgICAgICAqXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGVjb2RlQmFzZTkwMHRvQmFzZTEwKGNvZGV3b3JkcywgY291bnQpIHtcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSBjcmVhdGVCaWdJbnQoMCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuRVhQOTAwW2NvdW50IC0gaSAtIDFdICogY3JlYXRlQmlnSW50KGNvZGV3b3Jkc1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcmVzdWx0U3RyaW5nID0gcmVzdWx0LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICBpZiAocmVzdWx0U3RyaW5nLmNoYXJBdCgwKSAhPT0gJzEnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdFN0cmluZy5zdWJzdHJpbmcoMSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlRFWFRfQ09NUEFDVElPTl9NT0RFX0xBVENIID0gOTAwO1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CWVRFX0NPTVBBQ1RJT05fTU9ERV9MQVRDSCA9IDkwMTtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTlVNRVJJQ19DT01QQUNUSU9OX01PREVfTEFUQ0ggPSA5MDI7XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkJZVEVfQ09NUEFDVElPTl9NT0RFX0xBVENIXzYgPSA5MjQ7XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkVDSV9VU0VSX0RFRklORUQgPSA5MjU7XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkVDSV9HRU5FUkFMX1BVUlBPU0UgPSA5MjY7XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkVDSV9DSEFSU0VUID0gOTI3O1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5CRUdJTl9NQUNST19QREY0MTdfQ09OVFJPTF9CTE9DSyA9IDkyODtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQkVHSU5fTUFDUk9fUERGNDE3X09QVElPTkFMX0ZJRUxEID0gOTIzO1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQUNST19QREY0MTdfVEVSTUlOQVRPUiA9IDkyMjtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTU9ERV9TSElGVF9UT19CWVRFX0NPTVBBQ1RJT05fTU9ERSA9IDkxMztcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUFYX05VTUVSSUNfQ09ERVdPUkRTID0gMTU7XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BQ1JPX1BERjQxN19PUFRJT05BTF9GSUVMRF9GSUxFX05BTUUgPSAwO1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQUNST19QREY0MTdfT1BUSU9OQUxfRklFTERfU0VHTUVOVF9DT1VOVCA9IDE7XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BQ1JPX1BERjQxN19PUFRJT05BTF9GSUVMRF9USU1FX1NUQU1QID0gMjtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUFDUk9fUERGNDE3X09QVElPTkFMX0ZJRUxEX1NFTkRFUiA9IDM7XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLk1BQ1JPX1BERjQxN19PUFRJT05BTF9GSUVMRF9BRERSRVNTRUUgPSA0O1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5NQUNST19QREY0MTdfT1BUSU9OQUxfRklFTERfRklMRV9TSVpFID0gNTtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUFDUk9fUERGNDE3X09QVElPTkFMX0ZJRUxEX0NIRUNLU1VNID0gNjtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuUEwgPSAyNTtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTEwgPSAyNztcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQVMgPSAyNztcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUwgPSAyODtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuQUwgPSAyODtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuUFMgPSAyOTtcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuUEFMID0gMjk7XG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLlBVTkNUX0NIQVJTID0gJzs8PkBbXFxcXF1fYH4hXFxyXFx0LDpcXG4tLiQvXCJ8KigpP3t9XFwnJztcbiAgICBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDIuTUlYRURfQ0hBUlMgPSAnMDEyMzQ1Njc4OSZcXHJcXHQsOiMtLiQvKyUqPV4nO1xuICAgIC8qKlxuICAgICAqIFRhYmxlIGNvbnRhaW5pbmcgdmFsdWVzIGZvciB0aGUgZXhwb25lbnQgb2YgOTAwLlxuICAgICAqIFRoaXMgaXMgdXNlZCBpbiB0aGUgbnVtZXJpYyBjb21wYWN0aW9uIGRlY29kZSBhbGdvcml0aG0uXG4gICAgICovXG4gICAgRGVjb2RlZEJpdFN0cmVhbVBhcnNlciQyLkVYUDkwMCA9IGdldEJpZ0ludENvbnN0cnVjdG9yKCkgPyBnZXRFWFA5MDAoKSA6IFtdO1xuICAgIERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5OVU1CRVJfT0ZfU0VRVUVOQ0VfQ09ERVdPUkRTID0gMjtcblxuICAgIC8qXG4gICAgKiBDb3B5cmlnaHQgMjAxMyBaWGluZyBhdXRob3JzXG4gICAgKlxuICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICpcbiAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgKlxuICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAqL1xuICAgIC8vIGltcG9ydCBqYXZhLnV0aWwuQXJyYXlMaXN0O1xuICAgIC8vIGltcG9ydCBqYXZhLnV0aWwuQ29sbGVjdGlvbjtcbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLkZvcm1hdHRlcjtcbiAgICAvLyBpbXBvcnQgamF2YS51dGlsLkxpc3Q7XG4gICAgLyoqXG4gICAgICogQGF1dGhvciBHdWVudGhlciBHcmF1XG4gICAgICovXG4gICAgLypwdWJsaWMgZmluYWwqLyBjbGFzcyBQREY0MTdTY2FubmluZ0RlY29kZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHsgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQFRPRE8gZG9uJ3QgcGFzcyBpbiBtaW5Db2Rld29yZFdpZHRoIGFuZCBtYXhDb2Rld29yZFdpZHRoLCBwYXNzIGluIGJhcmNvZGUgY29sdW1ucyBmb3Igc3RhcnQgYW5kIHN0b3AgcGF0dGVyblxuICAgICAgICAgKlxuICAgICAgICAgKiBjb2x1bW5zLiBUaGF0IHdheSB3aWR0aCBjYW4gYmUgZGVkdWN0ZWQgZnJvbSB0aGUgcGF0dGVybiBjb2x1bW4uXG4gICAgICAgICAqIFRoaXMgYXBwcm9hY2ggYWxzbyBhbGxvd3MgdG8gZGV0ZWN0IG1vcmUgZGV0YWlscyBhYm91dCB0aGUgYmFyY29kZSwgZS5nLiBpZiBhIGJhciB0eXBlICh3aGl0ZSBvciBibGFjaykgaXMgd2lkZXJcbiAgICAgICAgICogdGhhbiBpdCBzaG91bGQgYmUuIFRoaXMgY2FuIGhhcHBlbiBpZiB0aGUgc2Nhbm5lciB1c2VkIGEgYmFkIGJsYWNrcG9pbnQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBCaXRNYXRyaXhcbiAgICAgICAgICogQHBhcmFtIGltYWdlXG4gICAgICAgICAqIEBwYXJhbSBSZXN1bHRQb2ludFxuICAgICAgICAgKiBAcGFyYW0gaW1hZ2VUb3BMZWZ0XG4gICAgICAgICAqIEBwYXJhbSBSZXN1bHRQb2ludFxuICAgICAgICAgKiBAcGFyYW0gaW1hZ2VCb3R0b21MZWZ0XG4gICAgICAgICAqIEBwYXJhbSBSZXN1bHRQb2ludFxuICAgICAgICAgKiBAcGFyYW0gaW1hZ2VUb3BSaWdodFxuICAgICAgICAgKiBAcGFyYW0gUmVzdWx0UG9pbnRcbiAgICAgICAgICogQHBhcmFtIGltYWdlQm90dG9tUmlnaHRcbiAgICAgICAgICogQHBhcmFtIGludFxuICAgICAgICAgKiBAcGFyYW0gbWluQ29kZXdvcmRXaWR0aFxuICAgICAgICAgKiBAcGFyYW0gaW50XG4gICAgICAgICAqIEBwYXJhbSBtYXhDb2Rld29yZFdpZHRoXG4gICAgICAgICAqXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb25cbiAgICAgICAgICogQHRocm93cyBGb3JtYXRFeGNlcHRpb25cbiAgICAgICAgICogQHRocm93cyBDaGVja3N1bUV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGRlY29kZShpbWFnZSwgaW1hZ2VUb3BMZWZ0LCBpbWFnZUJvdHRvbUxlZnQsIGltYWdlVG9wUmlnaHQsIGltYWdlQm90dG9tUmlnaHQsIG1pbkNvZGV3b3JkV2lkdGgsIG1heENvZGV3b3JkV2lkdGgpIHtcbiAgICAgICAgICAgIGxldCBib3VuZGluZ0JveCA9IG5ldyBCb3VuZGluZ0JveChpbWFnZSwgaW1hZ2VUb3BMZWZ0LCBpbWFnZUJvdHRvbUxlZnQsIGltYWdlVG9wUmlnaHQsIGltYWdlQm90dG9tUmlnaHQpO1xuICAgICAgICAgICAgbGV0IGxlZnRSb3dJbmRpY2F0b3JDb2x1bW4gPSBudWxsO1xuICAgICAgICAgICAgbGV0IHJpZ2h0Um93SW5kaWNhdG9yQ29sdW1uID0gbnVsbDtcbiAgICAgICAgICAgIGxldCBkZXRlY3Rpb25SZXN1bHQ7XG4gICAgICAgICAgICBmb3IgKGxldCBmaXJzdFBhc3MgLypib29sZWFuKi8gPSB0cnVlOzsgZmlyc3RQYXNzID0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW1hZ2VUb3BMZWZ0ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgbGVmdFJvd0luZGljYXRvckNvbHVtbiA9IFBERjQxN1NjYW5uaW5nRGVjb2Rlci5nZXRSb3dJbmRpY2F0b3JDb2x1bW4oaW1hZ2UsIGJvdW5kaW5nQm94LCBpbWFnZVRvcExlZnQsIHRydWUsIG1pbkNvZGV3b3JkV2lkdGgsIG1heENvZGV3b3JkV2lkdGgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoaW1hZ2VUb3BSaWdodCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0Um93SW5kaWNhdG9yQ29sdW1uID0gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmdldFJvd0luZGljYXRvckNvbHVtbihpbWFnZSwgYm91bmRpbmdCb3gsIGltYWdlVG9wUmlnaHQsIGZhbHNlLCBtaW5Db2Rld29yZFdpZHRoLCBtYXhDb2Rld29yZFdpZHRoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGV0ZWN0aW9uUmVzdWx0ID0gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLm1lcmdlKGxlZnRSb3dJbmRpY2F0b3JDb2x1bW4sIHJpZ2h0Um93SW5kaWNhdG9yQ29sdW1uKTtcbiAgICAgICAgICAgICAgICBpZiAoZGV0ZWN0aW9uUmVzdWx0ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgTm90Rm91bmRFeGNlcHRpb24uZ2V0Tm90Rm91bmRJbnN0YW5jZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgcmVzdWx0Qm94ID0gZGV0ZWN0aW9uUmVzdWx0LmdldEJvdW5kaW5nQm94KCk7XG4gICAgICAgICAgICAgICAgaWYgKGZpcnN0UGFzcyAmJiByZXN1bHRCb3ggIT0gbnVsbCAmJlxuICAgICAgICAgICAgICAgICAgICAocmVzdWx0Qm94LmdldE1pblkoKSA8IGJvdW5kaW5nQm94LmdldE1pblkoKSB8fCByZXN1bHRCb3guZ2V0TWF4WSgpID4gYm91bmRpbmdCb3guZ2V0TWF4WSgpKSkge1xuICAgICAgICAgICAgICAgICAgICBib3VuZGluZ0JveCA9IHJlc3VsdEJveDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRldGVjdGlvblJlc3VsdC5zZXRCb3VuZGluZ0JveChib3VuZGluZ0JveCk7XG4gICAgICAgICAgICBsZXQgbWF4QmFyY29kZUNvbHVtbiA9IGRldGVjdGlvblJlc3VsdC5nZXRCYXJjb2RlQ29sdW1uQ291bnQoKSArIDE7XG4gICAgICAgICAgICBkZXRlY3Rpb25SZXN1bHQuc2V0RGV0ZWN0aW9uUmVzdWx0Q29sdW1uKDAsIGxlZnRSb3dJbmRpY2F0b3JDb2x1bW4pO1xuICAgICAgICAgICAgZGV0ZWN0aW9uUmVzdWx0LnNldERldGVjdGlvblJlc3VsdENvbHVtbihtYXhCYXJjb2RlQ29sdW1uLCByaWdodFJvd0luZGljYXRvckNvbHVtbik7XG4gICAgICAgICAgICBsZXQgbGVmdFRvUmlnaHQgPSBsZWZ0Um93SW5kaWNhdG9yQ29sdW1uICE9IG51bGw7XG4gICAgICAgICAgICBmb3IgKGxldCBiYXJjb2RlQ29sdW1uQ291bnQgLyppbnQqLyA9IDE7IGJhcmNvZGVDb2x1bW5Db3VudCA8PSBtYXhCYXJjb2RlQ29sdW1uOyBiYXJjb2RlQ29sdW1uQ291bnQrKykge1xuICAgICAgICAgICAgICAgIGxldCBiYXJjb2RlQ29sdW1uID0gbGVmdFRvUmlnaHQgPyBiYXJjb2RlQ29sdW1uQ291bnQgOiBtYXhCYXJjb2RlQ29sdW1uIC0gYmFyY29kZUNvbHVtbkNvdW50O1xuICAgICAgICAgICAgICAgIGlmIChkZXRlY3Rpb25SZXN1bHQuZ2V0RGV0ZWN0aW9uUmVzdWx0Q29sdW1uKGJhcmNvZGVDb2x1bW4pICE9PSAvKiBudWxsICovIHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHdpbGwgYmUgdGhlIGNhc2UgZm9yIHRoZSBvcHBvc2l0ZSByb3cgaW5kaWNhdG9yIGNvbHVtbiwgd2hpY2ggZG9lc24ndCBuZWVkIHRvIGJlIGRlY29kZWQgYWdhaW4uXG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgZGV0ZWN0aW9uUmVzdWx0Q29sdW1uO1xuICAgICAgICAgICAgICAgIGlmIChiYXJjb2RlQ29sdW1uID09PSAwIHx8IGJhcmNvZGVDb2x1bW4gPT09IG1heEJhcmNvZGVDb2x1bW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZGV0ZWN0aW9uUmVzdWx0Q29sdW1uID0gbmV3IERldGVjdGlvblJlc3VsdFJvd0luZGljYXRvckNvbHVtbihib3VuZGluZ0JveCwgYmFyY29kZUNvbHVtbiA9PT0gMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBkZXRlY3Rpb25SZXN1bHRDb2x1bW4gPSBuZXcgRGV0ZWN0aW9uUmVzdWx0Q29sdW1uKGJvdW5kaW5nQm94KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGV0ZWN0aW9uUmVzdWx0LnNldERldGVjdGlvblJlc3VsdENvbHVtbihiYXJjb2RlQ29sdW1uLCBkZXRlY3Rpb25SZXN1bHRDb2x1bW4pO1xuICAgICAgICAgICAgICAgIGxldCBzdGFydENvbHVtbiA9IC0xO1xuICAgICAgICAgICAgICAgIGxldCBwcmV2aW91c1N0YXJ0Q29sdW1uID0gc3RhcnRDb2x1bW47XG4gICAgICAgICAgICAgICAgLy8gVE9ETyBzdGFydCBhdCBhIHJvdyBmb3Igd2hpY2ggd2Uga25vdyB0aGUgc3RhcnQgcG9zaXRpb24sIHRoZW4gZGV0ZWN0IHVwd2FyZHMgYW5kIGRvd253YXJkcyBmcm9tIHRoZXJlLlxuICAgICAgICAgICAgICAgIGZvciAobGV0IGltYWdlUm93IC8qaW50Ki8gPSBib3VuZGluZ0JveC5nZXRNaW5ZKCk7IGltYWdlUm93IDw9IGJvdW5kaW5nQm94LmdldE1heFkoKTsgaW1hZ2VSb3crKykge1xuICAgICAgICAgICAgICAgICAgICBzdGFydENvbHVtbiA9IFBERjQxN1NjYW5uaW5nRGVjb2Rlci5nZXRTdGFydENvbHVtbihkZXRlY3Rpb25SZXN1bHQsIGJhcmNvZGVDb2x1bW4sIGltYWdlUm93LCBsZWZ0VG9SaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGFydENvbHVtbiA8IDAgfHwgc3RhcnRDb2x1bW4gPiBib3VuZGluZ0JveC5nZXRNYXhYKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1N0YXJ0Q29sdW1uID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRDb2x1bW4gPSBwcmV2aW91c1N0YXJ0Q29sdW1uO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGxldCBjb2Rld29yZCA9IFBERjQxN1NjYW5uaW5nRGVjb2Rlci5kZXRlY3RDb2Rld29yZChpbWFnZSwgYm91bmRpbmdCb3guZ2V0TWluWCgpLCBib3VuZGluZ0JveC5nZXRNYXhYKCksIGxlZnRUb1JpZ2h0LCBzdGFydENvbHVtbiwgaW1hZ2VSb3csIG1pbkNvZGV3b3JkV2lkdGgsIG1heENvZGV3b3JkV2lkdGgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGV0ZWN0aW9uUmVzdWx0Q29sdW1uLnNldENvZGV3b3JkKGltYWdlUm93LCBjb2Rld29yZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1N0YXJ0Q29sdW1uID0gc3RhcnRDb2x1bW47XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5Db2Rld29yZFdpZHRoID0gTWF0aC5taW4obWluQ29kZXdvcmRXaWR0aCwgY29kZXdvcmQuZ2V0V2lkdGgoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhDb2Rld29yZFdpZHRoID0gTWF0aC5tYXgobWF4Q29kZXdvcmRXaWR0aCwgY29kZXdvcmQuZ2V0V2lkdGgoKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmNyZWF0ZURlY29kZXJSZXN1bHQoZGV0ZWN0aW9uUmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGxlZnRSb3dJbmRpY2F0b3JDb2x1bW5cbiAgICAgICAgICogQHBhcmFtIHJpZ2h0Um93SW5kaWNhdG9yQ29sdW1uXG4gICAgICAgICAqXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBtZXJnZShsZWZ0Um93SW5kaWNhdG9yQ29sdW1uLCByaWdodFJvd0luZGljYXRvckNvbHVtbikge1xuICAgICAgICAgICAgaWYgKGxlZnRSb3dJbmRpY2F0b3JDb2x1bW4gPT0gbnVsbCAmJiByaWdodFJvd0luZGljYXRvckNvbHVtbiA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgYmFyY29kZU1ldGFkYXRhID0gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmdldEJhcmNvZGVNZXRhZGF0YShsZWZ0Um93SW5kaWNhdG9yQ29sdW1uLCByaWdodFJvd0luZGljYXRvckNvbHVtbik7XG4gICAgICAgICAgICBpZiAoYmFyY29kZU1ldGFkYXRhID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBib3VuZGluZ0JveCA9IEJvdW5kaW5nQm94Lm1lcmdlKFBERjQxN1NjYW5uaW5nRGVjb2Rlci5hZGp1c3RCb3VuZGluZ0JveChsZWZ0Um93SW5kaWNhdG9yQ29sdW1uKSwgUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmFkanVzdEJvdW5kaW5nQm94KHJpZ2h0Um93SW5kaWNhdG9yQ29sdW1uKSk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IERldGVjdGlvblJlc3VsdChiYXJjb2RlTWV0YWRhdGEsIGJvdW5kaW5nQm94KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHJvd0luZGljYXRvckNvbHVtblxuICAgICAgICAgKlxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgYWRqdXN0Qm91bmRpbmdCb3gocm93SW5kaWNhdG9yQ29sdW1uKSB7XG4gICAgICAgICAgICBpZiAocm93SW5kaWNhdG9yQ29sdW1uID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCByb3dIZWlnaHRzID0gcm93SW5kaWNhdG9yQ29sdW1uLmdldFJvd0hlaWdodHMoKTtcbiAgICAgICAgICAgIGlmIChyb3dIZWlnaHRzID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBtYXhSb3dIZWlnaHQgPSBQREY0MTdTY2FubmluZ0RlY29kZXIuZ2V0TWF4KHJvd0hlaWdodHMpO1xuICAgICAgICAgICAgbGV0IG1pc3NpbmdTdGFydFJvd3MgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgcm93SGVpZ2h0IC8qaW50Ki8gb2Ygcm93SGVpZ2h0cykge1xuICAgICAgICAgICAgICAgIG1pc3NpbmdTdGFydFJvd3MgKz0gbWF4Um93SGVpZ2h0IC0gcm93SGVpZ2h0O1xuICAgICAgICAgICAgICAgIGlmIChyb3dIZWlnaHQgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBjb2Rld29yZHMgPSByb3dJbmRpY2F0b3JDb2x1bW4uZ2V0Q29kZXdvcmRzKCk7XG4gICAgICAgICAgICBmb3IgKGxldCByb3cgLyppbnQqLyA9IDA7IG1pc3NpbmdTdGFydFJvd3MgPiAwICYmIGNvZGV3b3Jkc1tyb3ddID09IG51bGw7IHJvdysrKSB7XG4gICAgICAgICAgICAgICAgbWlzc2luZ1N0YXJ0Um93cy0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IG1pc3NpbmdFbmRSb3dzID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IHJvdyAvKmludCovID0gcm93SGVpZ2h0cy5sZW5ndGggLSAxOyByb3cgPj0gMDsgcm93LS0pIHtcbiAgICAgICAgICAgICAgICBtaXNzaW5nRW5kUm93cyArPSBtYXhSb3dIZWlnaHQgLSByb3dIZWlnaHRzW3Jvd107XG4gICAgICAgICAgICAgICAgaWYgKHJvd0hlaWdodHNbcm93XSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgcm93IC8qaW50Ki8gPSBjb2Rld29yZHMubGVuZ3RoIC0gMTsgbWlzc2luZ0VuZFJvd3MgPiAwICYmIGNvZGV3b3Jkc1tyb3ddID09IG51bGw7IHJvdy0tKSB7XG4gICAgICAgICAgICAgICAgbWlzc2luZ0VuZFJvd3MtLTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByb3dJbmRpY2F0b3JDb2x1bW4uZ2V0Qm91bmRpbmdCb3goKS5hZGRNaXNzaW5nUm93cyhtaXNzaW5nU3RhcnRSb3dzLCBtaXNzaW5nRW5kUm93cywgcm93SW5kaWNhdG9yQ29sdW1uLmlzTGVmdCgpKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZ2V0TWF4KHZhbHVlcykge1xuICAgICAgICAgICAgbGV0IG1heFZhbHVlID0gLTE7XG4gICAgICAgICAgICBmb3IgKGxldCB2YWx1ZSAvKmludCovIG9mIHZhbHVlcykge1xuICAgICAgICAgICAgICAgIG1heFZhbHVlID0gTWF0aC5tYXgobWF4VmFsdWUsIHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtYXhWYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZ2V0QmFyY29kZU1ldGFkYXRhKGxlZnRSb3dJbmRpY2F0b3JDb2x1bW4sIHJpZ2h0Um93SW5kaWNhdG9yQ29sdW1uKSB7XG4gICAgICAgICAgICBsZXQgbGVmdEJhcmNvZGVNZXRhZGF0YTtcbiAgICAgICAgICAgIGlmIChsZWZ0Um93SW5kaWNhdG9yQ29sdW1uID09IG51bGwgfHxcbiAgICAgICAgICAgICAgICAobGVmdEJhcmNvZGVNZXRhZGF0YSA9IGxlZnRSb3dJbmRpY2F0b3JDb2x1bW4uZ2V0QmFyY29kZU1ldGFkYXRhKCkpID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmlnaHRSb3dJbmRpY2F0b3JDb2x1bW4gPT0gbnVsbCA/IG51bGwgOiByaWdodFJvd0luZGljYXRvckNvbHVtbi5nZXRCYXJjb2RlTWV0YWRhdGEoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCByaWdodEJhcmNvZGVNZXRhZGF0YTtcbiAgICAgICAgICAgIGlmIChyaWdodFJvd0luZGljYXRvckNvbHVtbiA9PSBudWxsIHx8XG4gICAgICAgICAgICAgICAgKHJpZ2h0QmFyY29kZU1ldGFkYXRhID0gcmlnaHRSb3dJbmRpY2F0b3JDb2x1bW4uZ2V0QmFyY29kZU1ldGFkYXRhKCkpID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVmdEJhcmNvZGVNZXRhZGF0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChsZWZ0QmFyY29kZU1ldGFkYXRhLmdldENvbHVtbkNvdW50KCkgIT09IHJpZ2h0QmFyY29kZU1ldGFkYXRhLmdldENvbHVtbkNvdW50KCkgJiZcbiAgICAgICAgICAgICAgICBsZWZ0QmFyY29kZU1ldGFkYXRhLmdldEVycm9yQ29ycmVjdGlvbkxldmVsKCkgIT09IHJpZ2h0QmFyY29kZU1ldGFkYXRhLmdldEVycm9yQ29ycmVjdGlvbkxldmVsKCkgJiZcbiAgICAgICAgICAgICAgICBsZWZ0QmFyY29kZU1ldGFkYXRhLmdldFJvd0NvdW50KCkgIT09IHJpZ2h0QmFyY29kZU1ldGFkYXRhLmdldFJvd0NvdW50KCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBsZWZ0QmFyY29kZU1ldGFkYXRhO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXRSb3dJbmRpY2F0b3JDb2x1bW4oaW1hZ2UsIGJvdW5kaW5nQm94LCBzdGFydFBvaW50LCBsZWZ0VG9SaWdodCwgbWluQ29kZXdvcmRXaWR0aCwgbWF4Q29kZXdvcmRXaWR0aCkge1xuICAgICAgICAgICAgbGV0IHJvd0luZGljYXRvckNvbHVtbiA9IG5ldyBEZXRlY3Rpb25SZXN1bHRSb3dJbmRpY2F0b3JDb2x1bW4oYm91bmRpbmdCb3gsIGxlZnRUb1JpZ2h0KTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgaW5jcmVtZW50ID0gaSA9PT0gMCA/IDEgOiAtMTtcbiAgICAgICAgICAgICAgICBsZXQgc3RhcnRDb2x1bW4gPSBNYXRoLnRydW5jKE1hdGgudHJ1bmMoc3RhcnRQb2ludC5nZXRYKCkpKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpbWFnZVJvdyAvKmludCovID0gTWF0aC50cnVuYyhNYXRoLnRydW5jKHN0YXJ0UG9pbnQuZ2V0WSgpKSk7IGltYWdlUm93IDw9IGJvdW5kaW5nQm94LmdldE1heFkoKSAmJlxuICAgICAgICAgICAgICAgICAgICBpbWFnZVJvdyA+PSBib3VuZGluZ0JveC5nZXRNaW5ZKCk7IGltYWdlUm93ICs9IGluY3JlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgY29kZXdvcmQgPSBQREY0MTdTY2FubmluZ0RlY29kZXIuZGV0ZWN0Q29kZXdvcmQoaW1hZ2UsIDAsIGltYWdlLmdldFdpZHRoKCksIGxlZnRUb1JpZ2h0LCBzdGFydENvbHVtbiwgaW1hZ2VSb3csIG1pbkNvZGV3b3JkV2lkdGgsIG1heENvZGV3b3JkV2lkdGgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29kZXdvcmQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm93SW5kaWNhdG9yQ29sdW1uLnNldENvZGV3b3JkKGltYWdlUm93LCBjb2Rld29yZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGVmdFRvUmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydENvbHVtbiA9IGNvZGV3b3JkLmdldFN0YXJ0WCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRDb2x1bW4gPSBjb2Rld29yZC5nZXRFbmRYKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcm93SW5kaWNhdG9yQ29sdW1uO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gZGV0ZWN0aW9uUmVzdWx0XG4gICAgICAgICAqIEBwYXJhbSBCYXJjb2RlVmFsdWVcbiAgICAgICAgICogQHBhcmFtIHBhcmFtMlxuICAgICAgICAgKiBAcGFyYW0gcGFyYW0zXG4gICAgICAgICAqIEBwYXJhbSBiYXJjb2RlTWF0cml4XG4gICAgICAgICAqXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBhZGp1c3RDb2Rld29yZENvdW50KGRldGVjdGlvblJlc3VsdCwgYmFyY29kZU1hdHJpeCkge1xuICAgICAgICAgICAgbGV0IGJhcmNvZGVNYXRyaXgwMSA9IGJhcmNvZGVNYXRyaXhbMF1bMV07XG4gICAgICAgICAgICBsZXQgbnVtYmVyT2ZDb2Rld29yZHMgPSBiYXJjb2RlTWF0cml4MDEuZ2V0VmFsdWUoKTtcbiAgICAgICAgICAgIGxldCBjYWxjdWxhdGVkTnVtYmVyT2ZDb2Rld29yZHMgPSBkZXRlY3Rpb25SZXN1bHQuZ2V0QmFyY29kZUNvbHVtbkNvdW50KCkgKlxuICAgICAgICAgICAgICAgIGRldGVjdGlvblJlc3VsdC5nZXRCYXJjb2RlUm93Q291bnQoKSAtXG4gICAgICAgICAgICAgICAgUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmdldE51bWJlck9mRUNDb2RlV29yZHMoZGV0ZWN0aW9uUmVzdWx0LmdldEJhcmNvZGVFQ0xldmVsKCkpO1xuICAgICAgICAgICAgaWYgKG51bWJlck9mQ29kZXdvcmRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGlmIChjYWxjdWxhdGVkTnVtYmVyT2ZDb2Rld29yZHMgPCAxIHx8IGNhbGN1bGF0ZWROdW1iZXJPZkNvZGV3b3JkcyA+IFBERjQxN0NvbW1vbi5NQVhfQ09ERVdPUkRTX0lOX0JBUkNPREUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgTm90Rm91bmRFeGNlcHRpb24uZ2V0Tm90Rm91bmRJbnN0YW5jZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBiYXJjb2RlTWF0cml4MDEuc2V0VmFsdWUoY2FsY3VsYXRlZE51bWJlck9mQ29kZXdvcmRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKG51bWJlck9mQ29kZXdvcmRzWzBdICE9PSBjYWxjdWxhdGVkTnVtYmVyT2ZDb2Rld29yZHMpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGUgY2FsY3VsYXRlZCBvbmUgaXMgbW9yZSByZWxpYWJsZSBhcyBpdCBpcyBkZXJpdmVkIGZyb20gdGhlIHJvdyBpbmRpY2F0b3IgY29sdW1uc1xuICAgICAgICAgICAgICAgIGJhcmNvZGVNYXRyaXgwMS5zZXRWYWx1ZShjYWxjdWxhdGVkTnVtYmVyT2ZDb2Rld29yZHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gZGV0ZWN0aW9uUmVzdWx0XG4gICAgICAgICAqXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uXG4gICAgICAgICAqIEB0aHJvd3MgQ2hlY2tzdW1FeGNlcHRpb25cbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGNyZWF0ZURlY29kZXJSZXN1bHQoZGV0ZWN0aW9uUmVzdWx0KSB7XG4gICAgICAgICAgICBsZXQgYmFyY29kZU1hdHJpeCA9IFBERjQxN1NjYW5uaW5nRGVjb2Rlci5jcmVhdGVCYXJjb2RlTWF0cml4KGRldGVjdGlvblJlc3VsdCk7XG4gICAgICAgICAgICBQREY0MTdTY2FubmluZ0RlY29kZXIuYWRqdXN0Q29kZXdvcmRDb3VudChkZXRlY3Rpb25SZXN1bHQsIGJhcmNvZGVNYXRyaXgpO1xuICAgICAgICAgICAgbGV0IGVyYXN1cmVzIC8qQ29sbGVjdGlvbjxJbnRlZ2VyPiovID0gbmV3IEFycmF5KCk7XG4gICAgICAgICAgICBsZXQgY29kZXdvcmRzID0gbmV3IEludDMyQXJyYXkoZGV0ZWN0aW9uUmVzdWx0LmdldEJhcmNvZGVSb3dDb3VudCgpICogZGV0ZWN0aW9uUmVzdWx0LmdldEJhcmNvZGVDb2x1bW5Db3VudCgpKTtcbiAgICAgICAgICAgIGxldCBhbWJpZ3VvdXNJbmRleFZhbHVlc0xpc3QgPSAvKkxpc3Q8aW50W10+Ki8gW107XG4gICAgICAgICAgICBsZXQgYW1iaWd1b3VzSW5kZXhlc0xpc3QgPSAvKkNvbGxlY3Rpb248SW50ZWdlcj4qLyBuZXcgQXJyYXkoKTtcbiAgICAgICAgICAgIGZvciAobGV0IHJvdyAvKmludCovID0gMDsgcm93IDwgZGV0ZWN0aW9uUmVzdWx0LmdldEJhcmNvZGVSb3dDb3VudCgpOyByb3crKykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGNvbHVtbiAvKmludCovID0gMDsgY29sdW1uIDwgZGV0ZWN0aW9uUmVzdWx0LmdldEJhcmNvZGVDb2x1bW5Db3VudCgpOyBjb2x1bW4rKykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgdmFsdWVzID0gYmFyY29kZU1hdHJpeFtyb3ddW2NvbHVtbiArIDFdLmdldFZhbHVlKCk7XG4gICAgICAgICAgICAgICAgICAgIGxldCBjb2Rld29yZEluZGV4ID0gcm93ICogZGV0ZWN0aW9uUmVzdWx0LmdldEJhcmNvZGVDb2x1bW5Db3VudCgpICsgY29sdW1uO1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJhc3VyZXMucHVzaChjb2Rld29yZEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh2YWx1ZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb2Rld29yZHNbY29kZXdvcmRJbmRleF0gPSB2YWx1ZXNbMF07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbWJpZ3VvdXNJbmRleGVzTGlzdC5wdXNoKGNvZGV3b3JkSW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYW1iaWd1b3VzSW5kZXhWYWx1ZXNMaXN0LnB1c2godmFsdWVzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBhbWJpZ3VvdXNJbmRleFZhbHVlcyA9IG5ldyBBcnJheShhbWJpZ3VvdXNJbmRleFZhbHVlc0xpc3QubGVuZ3RoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCBhbWJpZ3VvdXNJbmRleFZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGFtYmlndW91c0luZGV4VmFsdWVzW2ldID0gYW1iaWd1b3VzSW5kZXhWYWx1ZXNMaXN0W2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIFBERjQxN1NjYW5uaW5nRGVjb2Rlci5jcmVhdGVEZWNvZGVyUmVzdWx0RnJvbUFtYmlndW91c1ZhbHVlcyhkZXRlY3Rpb25SZXN1bHQuZ2V0QmFyY29kZUVDTGV2ZWwoKSwgY29kZXdvcmRzLCBQREY0MTdDb21tb24udG9JbnRBcnJheShlcmFzdXJlcyksIFBERjQxN0NvbW1vbi50b0ludEFycmF5KGFtYmlndW91c0luZGV4ZXNMaXN0KSwgYW1iaWd1b3VzSW5kZXhWYWx1ZXMpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGlzIG1ldGhvZCBkZWFscyB3aXRoIHRoZSBmYWN0LCB0aGF0IHRoZSBkZWNvZGluZyBwcm9jZXNzIGRvZXNuJ3QgYWx3YXlzIHlpZWxkIGEgc2luZ2xlIG1vc3QgbGlrZWx5IHZhbHVlLiBUaGVcbiAgICAgICAgICogY3VycmVudCBlcnJvciBjb3JyZWN0aW9uIGltcGxlbWVudGF0aW9uIGRvZXNuJ3QgZGVhbCB3aXRoIGVyYXN1cmVzIHZlcnkgd2VsbCwgc28gaXQncyBiZXR0ZXIgdG8gcHJvdmlkZSBhIHZhbHVlXG4gICAgICAgICAqIGZvciB0aGVzZSBhbWJpZ3VvdXMgY29kZXdvcmRzIGluc3RlYWQgb2YgdHJlYXRpbmcgaXQgYXMgYW4gZXJhc3VyZS4gVGhlIHByb2JsZW0gaXMgdGhhdCB3ZSBkb24ndCBrbm93IHdoaWNoIG9mXG4gICAgICAgICAqIHRoZSBhbWJpZ3VvdXMgdmFsdWVzIHRvIGNob29zZS4gV2UgdHJ5IGRlY29kZSB1c2luZyB0aGUgZmlyc3QgdmFsdWUsIGFuZCBpZiB0aGF0IGZhaWxzLCB3ZSB1c2UgYW5vdGhlciBvZiB0aGVcbiAgICAgICAgICogYW1iaWd1b3VzIHZhbHVlcyBhbmQgdHJ5IHRvIGRlY29kZSBhZ2Fpbi4gVGhpcyB1c3VhbGx5IG9ubHkgaGFwcGVucyBvbiB2ZXJ5IGhhcmQgdG8gcmVhZCBhbmQgZGVjb2RlIGJhcmNvZGVzLFxuICAgICAgICAgKiBzbyBkZWNvZGluZyB0aGUgbm9ybWFsIGJhcmNvZGVzIGlzIG5vdCBhZmZlY3RlZCBieSB0aGlzLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gZXJhc3VyZUFycmF5IGNvbnRhaW5zIHRoZSBpbmRleGVzIG9mIGVyYXN1cmVzXG4gICAgICAgICAqIEBwYXJhbSBhbWJpZ3VvdXNJbmRleGVzIGFycmF5IHdpdGggdGhlIGluZGV4ZXMgdGhhdCBoYXZlIG1vcmUgdGhhbiBvbmUgbW9zdCBsaWtlbHkgdmFsdWVcbiAgICAgICAgICogQHBhcmFtIGFtYmlndW91c0luZGV4VmFsdWVzIHR3byBkaW1lbnNpb25hbCBhcnJheSB0aGF0IGNvbnRhaW5zIHRoZSBhbWJpZ3VvdXMgdmFsdWVzLiBUaGUgZmlyc3QgZGltZW5zaW9uIG11c3RcbiAgICAgICAgICogYmUgdGhlIHNhbWUgbGVuZ3RoIGFzIHRoZSBhbWJpZ3VvdXNJbmRleGVzIGFycmF5XG4gICAgICAgICAqXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uXG4gICAgICAgICAqIEB0aHJvd3MgQ2hlY2tzdW1FeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBjcmVhdGVEZWNvZGVyUmVzdWx0RnJvbUFtYmlndW91c1ZhbHVlcyhlY0xldmVsLCBjb2Rld29yZHMsIGVyYXN1cmVBcnJheSwgYW1iaWd1b3VzSW5kZXhlcywgYW1iaWd1b3VzSW5kZXhWYWx1ZXMpIHtcbiAgICAgICAgICAgIGxldCBhbWJpZ3VvdXNJbmRleENvdW50ID0gbmV3IEludDMyQXJyYXkoYW1iaWd1b3VzSW5kZXhlcy5sZW5ndGgpO1xuICAgICAgICAgICAgbGV0IHRyaWVzID0gMTAwO1xuICAgICAgICAgICAgd2hpbGUgKHRyaWVzLS0gPiAwKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMDsgaSA8IGFtYmlndW91c0luZGV4Q291bnQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29kZXdvcmRzW2FtYmlndW91c0luZGV4ZXNbaV1dID0gYW1iaWd1b3VzSW5kZXhWYWx1ZXNbaV1bYW1iaWd1b3VzSW5kZXhDb3VudFtpXV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBQREY0MTdTY2FubmluZ0RlY29kZXIuZGVjb2RlQ29kZXdvcmRzKGNvZGV3b3JkcywgZWNMZXZlbCwgZXJhc3VyZUFycmF5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICBsZXQgaWdub3JlZCA9IGVyciBpbnN0YW5jZW9mIENoZWNrc3VtRXhjZXB0aW9uO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlnbm9yZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYW1iaWd1b3VzSW5kZXhDb3VudC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgQ2hlY2tzdW1FeGNlcHRpb24uZ2V0Q2hlY2tzdW1JbnN0YW5jZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAwOyBpIDwgYW1iaWd1b3VzSW5kZXhDb3VudC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoYW1iaWd1b3VzSW5kZXhDb3VudFtpXSA8IGFtYmlndW91c0luZGV4VmFsdWVzW2ldLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFtYmlndW91c0luZGV4Q291bnRbaV0rKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYW1iaWd1b3VzSW5kZXhDb3VudFtpXSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaSA9PT0gYW1iaWd1b3VzSW5kZXhDb3VudC5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgQ2hlY2tzdW1FeGNlcHRpb24uZ2V0Q2hlY2tzdW1JbnN0YW5jZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgQ2hlY2tzdW1FeGNlcHRpb24uZ2V0Q2hlY2tzdW1JbnN0YW5jZSgpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBjcmVhdGVCYXJjb2RlTWF0cml4KGRldGVjdGlvblJlc3VsdCkge1xuICAgICAgICAgICAgLy8gbGV0IGJhcmNvZGVNYXRyaXg6IEJhcmNvZGVWYWx1ZVtdW10gPVxuICAgICAgICAgICAgLy8gbmV3IEJhcmNvZGVWYWx1ZVtkZXRlY3Rpb25SZXN1bHQuZ2V0QmFyY29kZVJvd0NvdW50KCldW2RldGVjdGlvblJlc3VsdC5nZXRCYXJjb2RlQ29sdW1uQ291bnQoKSArIDJdO1xuICAgICAgICAgICAgbGV0IGJhcmNvZGVNYXRyaXggPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiBkZXRlY3Rpb25SZXN1bHQuZ2V0QmFyY29kZVJvd0NvdW50KCkgfSwgKCkgPT4gbmV3IEFycmF5KGRldGVjdGlvblJlc3VsdC5nZXRCYXJjb2RlQ29sdW1uQ291bnQoKSArIDIpKTtcbiAgICAgICAgICAgIGZvciAobGV0IHJvdyAvKmludCovID0gMDsgcm93IDwgYmFyY29kZU1hdHJpeC5sZW5ndGg7IHJvdysrKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgY29sdW1uIC8qaW50Ki8gPSAwOyBjb2x1bW4gPCBiYXJjb2RlTWF0cml4W3Jvd10ubGVuZ3RoOyBjb2x1bW4rKykge1xuICAgICAgICAgICAgICAgICAgICBiYXJjb2RlTWF0cml4W3Jvd11bY29sdW1uXSA9IG5ldyBCYXJjb2RlVmFsdWUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgY29sdW1uID0gMDtcbiAgICAgICAgICAgIGZvciAobGV0IGRldGVjdGlvblJlc3VsdENvbHVtbiAvKkRldGVjdGlvblJlc3VsdENvbHVtbiovIG9mIGRldGVjdGlvblJlc3VsdC5nZXREZXRlY3Rpb25SZXN1bHRDb2x1bW5zKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGV0ZWN0aW9uUmVzdWx0Q29sdW1uICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgY29kZXdvcmQgLypDb2Rld29yZCovIG9mIGRldGVjdGlvblJlc3VsdENvbHVtbi5nZXRDb2Rld29yZHMoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvZGV3b3JkICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgcm93TnVtYmVyID0gY29kZXdvcmQuZ2V0Um93TnVtYmVyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJvd051bWJlciA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyb3dOdW1iZXIgPj0gYmFyY29kZU1hdHJpeC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGhhdmUgbW9yZSByb3dzIHRoYW4gdGhlIGJhcmNvZGUgbWV0YWRhdGEgYWxsb3dzIGZvciwgaWdub3JlIHRoZW0uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYXJjb2RlTWF0cml4W3Jvd051bWJlcl1bY29sdW1uXS5zZXRWYWx1ZShjb2Rld29yZC5nZXRWYWx1ZSgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29sdW1uKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYmFyY29kZU1hdHJpeDtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgaXNWYWxpZEJhcmNvZGVDb2x1bW4oZGV0ZWN0aW9uUmVzdWx0LCBiYXJjb2RlQ29sdW1uKSB7XG4gICAgICAgICAgICByZXR1cm4gYmFyY29kZUNvbHVtbiA+PSAwICYmIGJhcmNvZGVDb2x1bW4gPD0gZGV0ZWN0aW9uUmVzdWx0LmdldEJhcmNvZGVDb2x1bW5Db3VudCgpICsgMTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZ2V0U3RhcnRDb2x1bW4oZGV0ZWN0aW9uUmVzdWx0LCBiYXJjb2RlQ29sdW1uLCBpbWFnZVJvdywgbGVmdFRvUmlnaHQpIHtcbiAgICAgICAgICAgIGxldCBvZmZzZXQgPSBsZWZ0VG9SaWdodCA/IDEgOiAtMTtcbiAgICAgICAgICAgIGxldCBjb2Rld29yZCA9IG51bGw7XG4gICAgICAgICAgICBpZiAoUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmlzVmFsaWRCYXJjb2RlQ29sdW1uKGRldGVjdGlvblJlc3VsdCwgYmFyY29kZUNvbHVtbiAtIG9mZnNldCkpIHtcbiAgICAgICAgICAgICAgICBjb2Rld29yZCA9IGRldGVjdGlvblJlc3VsdC5nZXREZXRlY3Rpb25SZXN1bHRDb2x1bW4oYmFyY29kZUNvbHVtbiAtIG9mZnNldCkuZ2V0Q29kZXdvcmQoaW1hZ2VSb3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvZGV3b3JkICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVmdFRvUmlnaHQgPyBjb2Rld29yZC5nZXRFbmRYKCkgOiBjb2Rld29yZC5nZXRTdGFydFgoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvZGV3b3JkID0gZGV0ZWN0aW9uUmVzdWx0LmdldERldGVjdGlvblJlc3VsdENvbHVtbihiYXJjb2RlQ29sdW1uKS5nZXRDb2Rld29yZE5lYXJieShpbWFnZVJvdyk7XG4gICAgICAgICAgICBpZiAoY29kZXdvcmQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBsZWZ0VG9SaWdodCA/IGNvZGV3b3JkLmdldFN0YXJ0WCgpIDogY29kZXdvcmQuZ2V0RW5kWCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKFBERjQxN1NjYW5uaW5nRGVjb2Rlci5pc1ZhbGlkQmFyY29kZUNvbHVtbihkZXRlY3Rpb25SZXN1bHQsIGJhcmNvZGVDb2x1bW4gLSBvZmZzZXQpKSB7XG4gICAgICAgICAgICAgICAgY29kZXdvcmQgPSBkZXRlY3Rpb25SZXN1bHQuZ2V0RGV0ZWN0aW9uUmVzdWx0Q29sdW1uKGJhcmNvZGVDb2x1bW4gLSBvZmZzZXQpLmdldENvZGV3b3JkTmVhcmJ5KGltYWdlUm93KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjb2Rld29yZCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxlZnRUb1JpZ2h0ID8gY29kZXdvcmQuZ2V0RW5kWCgpIDogY29kZXdvcmQuZ2V0U3RhcnRYKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc2tpcHBlZENvbHVtbnMgPSAwO1xuICAgICAgICAgICAgd2hpbGUgKFBERjQxN1NjYW5uaW5nRGVjb2Rlci5pc1ZhbGlkQmFyY29kZUNvbHVtbihkZXRlY3Rpb25SZXN1bHQsIGJhcmNvZGVDb2x1bW4gLSBvZmZzZXQpKSB7XG4gICAgICAgICAgICAgICAgYmFyY29kZUNvbHVtbiAtPSBvZmZzZXQ7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgcHJldmlvdXNSb3dDb2Rld29yZCAvKkNvZGV3b3JkKi8gb2YgZGV0ZWN0aW9uUmVzdWx0LmdldERldGVjdGlvblJlc3VsdENvbHVtbihiYXJjb2RlQ29sdW1uKS5nZXRDb2Rld29yZHMoKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNSb3dDb2Rld29yZCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKGxlZnRUb1JpZ2h0ID8gcHJldmlvdXNSb3dDb2Rld29yZC5nZXRFbmRYKCkgOiBwcmV2aW91c1Jvd0NvZGV3b3JkLmdldFN0YXJ0WCgpKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0ICpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2tpcHBlZENvbHVtbnMgKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocHJldmlvdXNSb3dDb2Rld29yZC5nZXRFbmRYKCkgLSBwcmV2aW91c1Jvd0NvZGV3b3JkLmdldFN0YXJ0WCgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBza2lwcGVkQ29sdW1ucysrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGxlZnRUb1JpZ2h0ID8gZGV0ZWN0aW9uUmVzdWx0LmdldEJvdW5kaW5nQm94KCkuZ2V0TWluWCgpIDogZGV0ZWN0aW9uUmVzdWx0LmdldEJvdW5kaW5nQm94KCkuZ2V0TWF4WCgpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBkZXRlY3RDb2Rld29yZChpbWFnZSwgbWluQ29sdW1uLCBtYXhDb2x1bW4sIGxlZnRUb1JpZ2h0LCBzdGFydENvbHVtbiwgaW1hZ2VSb3csIG1pbkNvZGV3b3JkV2lkdGgsIG1heENvZGV3b3JkV2lkdGgpIHtcbiAgICAgICAgICAgIHN0YXJ0Q29sdW1uID0gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmFkanVzdENvZGV3b3JkU3RhcnRDb2x1bW4oaW1hZ2UsIG1pbkNvbHVtbiwgbWF4Q29sdW1uLCBsZWZ0VG9SaWdodCwgc3RhcnRDb2x1bW4sIGltYWdlUm93KTtcbiAgICAgICAgICAgIC8vIHdlIHVzdWFsbHkga25vdyBmYWlybHkgZXhhY3Qgbm93IGhvdyBsb25nIGEgY29kZXdvcmQgaXMuIFdlIHNob3VsZCBwcm92aWRlIG1pbmltdW0gYW5kIG1heGltdW0gZXhwZWN0ZWQgbGVuZ3RoXG4gICAgICAgICAgICAvLyBhbmQgdHJ5IHRvIGFkanVzdCB0aGUgcmVhZCBwaXhlbHMsIGUuZy4gcmVtb3ZlIHNpbmdsZSBwaXhlbCBlcnJvcnMgb3IgdHJ5IHRvIGN1dCBvZmYgZXhjZWVkaW5nIHBpeGVscy5cbiAgICAgICAgICAgIC8vIG1pbiBhbmQgbWF4Q29kZXdvcmRXaWR0aCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhleSBhcmUgY2FsY3VsYXRlZCBmb3IgdGhlIHdob2xlIGJhcmNvZGUgYW4gY2FuIGJlIGluYWNjdXJhdGVcbiAgICAgICAgICAgIC8vIGZvciB0aGUgY3VycmVudCBwb3NpdGlvblxuICAgICAgICAgICAgbGV0IG1vZHVsZUJpdENvdW50ID0gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmdldE1vZHVsZUJpdENvdW50KGltYWdlLCBtaW5Db2x1bW4sIG1heENvbHVtbiwgbGVmdFRvUmlnaHQsIHN0YXJ0Q29sdW1uLCBpbWFnZVJvdyk7XG4gICAgICAgICAgICBpZiAobW9kdWxlQml0Q291bnQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGVuZENvbHVtbjtcbiAgICAgICAgICAgIGxldCBjb2Rld29yZEJpdENvdW50ID0gTWF0aFV0aWxzLnN1bShtb2R1bGVCaXRDb3VudCk7XG4gICAgICAgICAgICBpZiAobGVmdFRvUmlnaHQpIHtcbiAgICAgICAgICAgICAgICBlbmRDb2x1bW4gPSBzdGFydENvbHVtbiArIGNvZGV3b3JkQml0Q291bnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAwOyBpIDwgbW9kdWxlQml0Q291bnQubGVuZ3RoIC8gMjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCB0bXBDb3VudCA9IG1vZHVsZUJpdENvdW50W2ldO1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGVCaXRDb3VudFtpXSA9IG1vZHVsZUJpdENvdW50W21vZHVsZUJpdENvdW50Lmxlbmd0aCAtIDEgLSBpXTtcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlQml0Q291bnRbbW9kdWxlQml0Q291bnQubGVuZ3RoIC0gMSAtIGldID0gdG1wQ291bnQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVuZENvbHVtbiA9IHN0YXJ0Q29sdW1uO1xuICAgICAgICAgICAgICAgIHN0YXJ0Q29sdW1uID0gZW5kQ29sdW1uIC0gY29kZXdvcmRCaXRDb3VudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFRPRE8gaW1wbGVtZW50IGNoZWNrIGZvciB3aWR0aCBhbmQgY29ycmVjdGlvbiBvZiBibGFjayBhbmQgd2hpdGUgYmFyc1xuICAgICAgICAgICAgLy8gdXNlIHN0YXJ0IChhbmQgbWF5YmUgc3RvcCBwYXR0ZXJuKSB0byBkZXRlcm1pbmUgaWYgYmxhY2sgYmFycyBhcmUgd2lkZXIgdGhhbiB3aGl0ZSBiYXJzLiBJZiBzbywgYWRqdXN0LlxuICAgICAgICAgICAgLy8gc2hvdWxkIHByb2JhYmx5IGRvbmUgb25seSBmb3IgY29kZXdvcmRzIHdpdGggYSBsb3QgbW9yZSB0aGFuIDE3IGJpdHMuXG4gICAgICAgICAgICAvLyBUaGUgZm9sbG93aW5nIGZpeGVzIDEwLTEucG5nLCB3aGljaCBoYXMgd2lkZSBibGFjayBiYXJzIGFuZCBzbWFsbCB3aGl0ZSBiYXJzXG4gICAgICAgICAgICAvLyAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAwOyBpIDwgbW9kdWxlQml0Q291bnQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIC8vICAgICAgaWYgKGkgJSAyID09PSAwKSB7XG4gICAgICAgICAgICAvLyAgICAgICAgbW9kdWxlQml0Q291bnRbaV0tLTtcbiAgICAgICAgICAgIC8vICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vICAgICAgICBtb2R1bGVCaXRDb3VudFtpXSsrO1xuICAgICAgICAgICAgLy8gICAgICB9XG4gICAgICAgICAgICAvLyAgICB9XG4gICAgICAgICAgICAvLyBXZSBjb3VsZCBhbHNvIHVzZSB0aGUgd2lkdGggb2Ygc3Vycm91bmRpbmcgY29kZXdvcmRzIGZvciBtb3JlIGFjY3VyYXRlIHJlc3VsdHMsIGJ1dCB0aGlzIHNlZW1zXG4gICAgICAgICAgICAvLyBzdWZmaWNpZW50IGZvciBub3dcbiAgICAgICAgICAgIGlmICghUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmNoZWNrQ29kZXdvcmRTa2V3KGNvZGV3b3JkQml0Q291bnQsIG1pbkNvZGV3b3JkV2lkdGgsIG1heENvZGV3b3JkV2lkdGgpKSB7XG4gICAgICAgICAgICAgICAgLy8gV2UgY291bGQgdHJ5IHRvIHVzZSB0aGUgc3RhcnRYIGFuZCBlbmRYIHBvc2l0aW9uIG9mIHRoZSBjb2Rld29yZCBpbiB0aGUgc2FtZSBjb2x1bW4gaW4gdGhlIHByZXZpb3VzIHJvdyxcbiAgICAgICAgICAgICAgICAvLyBjcmVhdGUgdGhlIGJpdCBjb3VudCBmcm9tIGl0IGFuZCBub3JtYWxpemUgaXQgdG8gOC4gVGhpcyB3b3VsZCBoZWxwIHdpdGggc2luZ2xlIHBpeGVsIGVycm9ycy5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBkZWNvZGVkVmFsdWUgPSBQREY0MTdDb2Rld29yZERlY29kZXIuZ2V0RGVjb2RlZFZhbHVlKG1vZHVsZUJpdENvdW50KTtcbiAgICAgICAgICAgIGxldCBjb2Rld29yZCA9IFBERjQxN0NvbW1vbi5nZXRDb2Rld29yZChkZWNvZGVkVmFsdWUpO1xuICAgICAgICAgICAgaWYgKGNvZGV3b3JkID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBDb2Rld29yZChzdGFydENvbHVtbiwgZW5kQ29sdW1uLCBQREY0MTdTY2FubmluZ0RlY29kZXIuZ2V0Q29kZXdvcmRCdWNrZXROdW1iZXIoZGVjb2RlZFZhbHVlKSwgY29kZXdvcmQpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXRNb2R1bGVCaXRDb3VudChpbWFnZSwgbWluQ29sdW1uLCBtYXhDb2x1bW4sIGxlZnRUb1JpZ2h0LCBzdGFydENvbHVtbiwgaW1hZ2VSb3cpIHtcbiAgICAgICAgICAgIGxldCBpbWFnZUNvbHVtbiA9IHN0YXJ0Q29sdW1uO1xuICAgICAgICAgICAgbGV0IG1vZHVsZUJpdENvdW50ID0gbmV3IEludDMyQXJyYXkoOCk7XG4gICAgICAgICAgICBsZXQgbW9kdWxlTnVtYmVyID0gMDtcbiAgICAgICAgICAgIGxldCBpbmNyZW1lbnQgPSBsZWZ0VG9SaWdodCA/IDEgOiAtMTtcbiAgICAgICAgICAgIGxldCBwcmV2aW91c1BpeGVsVmFsdWUgPSBsZWZ0VG9SaWdodDtcbiAgICAgICAgICAgIHdoaWxlICgobGVmdFRvUmlnaHQgPyBpbWFnZUNvbHVtbiA8IG1heENvbHVtbiA6IGltYWdlQ29sdW1uID49IG1pbkNvbHVtbikgJiZcbiAgICAgICAgICAgICAgICBtb2R1bGVOdW1iZXIgPCBtb2R1bGVCaXRDb3VudC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW1hZ2UuZ2V0KGltYWdlQ29sdW1uLCBpbWFnZVJvdykgPT09IHByZXZpb3VzUGl4ZWxWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGVCaXRDb3VudFttb2R1bGVOdW1iZXJdKys7XG4gICAgICAgICAgICAgICAgICAgIGltYWdlQ29sdW1uICs9IGluY3JlbWVudDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZU51bWJlcisrO1xuICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1BpeGVsVmFsdWUgPSAhcHJldmlvdXNQaXhlbFZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtb2R1bGVOdW1iZXIgPT09IG1vZHVsZUJpdENvdW50Lmxlbmd0aCB8fFxuICAgICAgICAgICAgICAgICgoaW1hZ2VDb2x1bW4gPT09IChsZWZ0VG9SaWdodCA/IG1heENvbHVtbiA6IG1pbkNvbHVtbikpICYmXG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZU51bWJlciA9PT0gbW9kdWxlQml0Q291bnQubGVuZ3RoIC0gMSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9kdWxlQml0Q291bnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZ2V0TnVtYmVyT2ZFQ0NvZGVXb3JkcyhiYXJjb2RlRUNMZXZlbCkge1xuICAgICAgICAgICAgcmV0dXJuIDIgPDwgYmFyY29kZUVDTGV2ZWw7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGFkanVzdENvZGV3b3JkU3RhcnRDb2x1bW4oaW1hZ2UsIG1pbkNvbHVtbiwgbWF4Q29sdW1uLCBsZWZ0VG9SaWdodCwgY29kZXdvcmRTdGFydENvbHVtbiwgaW1hZ2VSb3cpIHtcbiAgICAgICAgICAgIGxldCBjb3JyZWN0ZWRTdGFydENvbHVtbiA9IGNvZGV3b3JkU3RhcnRDb2x1bW47XG4gICAgICAgICAgICBsZXQgaW5jcmVtZW50ID0gbGVmdFRvUmlnaHQgPyAtMSA6IDE7XG4gICAgICAgICAgICAvLyB0aGVyZSBzaG91bGQgYmUgbm8gYmxhY2sgcGl4ZWxzIGJlZm9yZSB0aGUgc3RhcnQgY29sdW1uLiBJZiB0aGVyZSBhcmUsIHRoZW4gd2UgbmVlZCB0byBzdGFydCBlYXJsaWVyLlxuICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMDsgaSA8IDI7IGkrKykge1xuICAgICAgICAgICAgICAgIHdoaWxlICgobGVmdFRvUmlnaHQgPyBjb3JyZWN0ZWRTdGFydENvbHVtbiA+PSBtaW5Db2x1bW4gOiBjb3JyZWN0ZWRTdGFydENvbHVtbiA8IG1heENvbHVtbikgJiZcbiAgICAgICAgICAgICAgICAgICAgbGVmdFRvUmlnaHQgPT09IGltYWdlLmdldChjb3JyZWN0ZWRTdGFydENvbHVtbiwgaW1hZ2VSb3cpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChNYXRoLmFicyhjb2Rld29yZFN0YXJ0Q29sdW1uIC0gY29ycmVjdGVkU3RhcnRDb2x1bW4pID4gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLkNPREVXT1JEX1NLRVdfU0laRSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvZGV3b3JkU3RhcnRDb2x1bW47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY29ycmVjdGVkU3RhcnRDb2x1bW4gKz0gaW5jcmVtZW50O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpbmNyZW1lbnQgPSAtaW5jcmVtZW50O1xuICAgICAgICAgICAgICAgIGxlZnRUb1JpZ2h0ID0gIWxlZnRUb1JpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGNvcnJlY3RlZFN0YXJ0Q29sdW1uO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBjaGVja0NvZGV3b3JkU2tldyhjb2Rld29yZFNpemUsIG1pbkNvZGV3b3JkV2lkdGgsIG1heENvZGV3b3JkV2lkdGgpIHtcbiAgICAgICAgICAgIHJldHVybiBtaW5Db2Rld29yZFdpZHRoIC0gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLkNPREVXT1JEX1NLRVdfU0laRSA8PSBjb2Rld29yZFNpemUgJiZcbiAgICAgICAgICAgICAgICBjb2Rld29yZFNpemUgPD0gbWF4Q29kZXdvcmRXaWR0aCArIFBERjQxN1NjYW5uaW5nRGVjb2Rlci5DT0RFV09SRF9TS0VXX1NJWkU7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uLFxuICAgICAgICAgKiBAdGhyb3dzIENoZWNrc3VtRXhjZXB0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZGVjb2RlQ29kZXdvcmRzKGNvZGV3b3JkcywgZWNMZXZlbCwgZXJhc3VyZXMpIHtcbiAgICAgICAgICAgIGlmIChjb2Rld29yZHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgRm9ybWF0RXhjZXB0aW9uLmdldEZvcm1hdEluc3RhbmNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgbnVtRUNDb2Rld29yZHMgPSAxIDw8IChlY0xldmVsICsgMSk7XG4gICAgICAgICAgICBsZXQgY29ycmVjdGVkRXJyb3JzQ291bnQgPSBQREY0MTdTY2FubmluZ0RlY29kZXIuY29ycmVjdEVycm9ycyhjb2Rld29yZHMsIGVyYXN1cmVzLCBudW1FQ0NvZGV3b3Jkcyk7XG4gICAgICAgICAgICBQREY0MTdTY2FubmluZ0RlY29kZXIudmVyaWZ5Q29kZXdvcmRDb3VudChjb2Rld29yZHMsIG51bUVDQ29kZXdvcmRzKTtcbiAgICAgICAgICAgIC8vIERlY29kZSB0aGUgY29kZXdvcmRzXG4gICAgICAgICAgICBsZXQgZGVjb2RlclJlc3VsdCA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMi5kZWNvZGUoY29kZXdvcmRzLCAnJyArIGVjTGV2ZWwpO1xuICAgICAgICAgICAgZGVjb2RlclJlc3VsdC5zZXRFcnJvcnNDb3JyZWN0ZWQoY29ycmVjdGVkRXJyb3JzQ291bnQpO1xuICAgICAgICAgICAgZGVjb2RlclJlc3VsdC5zZXRFcmFzdXJlcyhlcmFzdXJlcy5sZW5ndGgpO1xuICAgICAgICAgICAgcmV0dXJuIGRlY29kZXJSZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxwPkdpdmVuIGRhdGEgYW5kIGVycm9yLWNvcnJlY3Rpb24gY29kZXdvcmRzIHJlY2VpdmVkLCBwb3NzaWJseSBjb3JydXB0ZWQgYnkgZXJyb3JzLCBhdHRlbXB0cyB0b1xuICAgICAgICAgKiBjb3JyZWN0IHRoZSBlcnJvcnMgaW4tcGxhY2UuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gY29kZXdvcmRzICAgZGF0YSBhbmQgZXJyb3IgY29ycmVjdGlvbiBjb2Rld29yZHNcbiAgICAgICAgICogQHBhcmFtIGVyYXN1cmVzIHBvc2l0aW9ucyBvZiBhbnkga25vd24gZXJhc3VyZXNcbiAgICAgICAgICogQHBhcmFtIG51bUVDQ29kZXdvcmRzIG51bWJlciBvZiBlcnJvciBjb3JyZWN0aW9uIGNvZGV3b3JkcyB0aGF0IGFyZSBhdmFpbGFibGUgaW4gY29kZXdvcmRzXG4gICAgICAgICAqIEB0aHJvd3MgQ2hlY2tzdW1FeGNlcHRpb24gaWYgZXJyb3IgY29ycmVjdGlvbiBmYWlsc1xuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGNvcnJlY3RFcnJvcnMoY29kZXdvcmRzLCBlcmFzdXJlcywgbnVtRUNDb2Rld29yZHMpIHtcbiAgICAgICAgICAgIGlmIChlcmFzdXJlcyAhPSBudWxsICYmXG4gICAgICAgICAgICAgICAgZXJhc3VyZXMubGVuZ3RoID4gbnVtRUNDb2Rld29yZHMgLyAyICsgUERGNDE3U2Nhbm5pbmdEZWNvZGVyLk1BWF9FUlJPUlMgfHxcbiAgICAgICAgICAgICAgICBudW1FQ0NvZGV3b3JkcyA8IDAgfHxcbiAgICAgICAgICAgICAgICBudW1FQ0NvZGV3b3JkcyA+IFBERjQxN1NjYW5uaW5nRGVjb2Rlci5NQVhfRUNfQ09ERVdPUkRTKSB7XG4gICAgICAgICAgICAgICAgLy8gVG9vIG1hbnkgZXJyb3JzIG9yIEVDIENvZGV3b3JkcyBpcyBjb3JydXB0ZWRcbiAgICAgICAgICAgICAgICB0aHJvdyBDaGVja3N1bUV4Y2VwdGlvbi5nZXRDaGVja3N1bUluc3RhbmNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmVycm9yQ29ycmVjdGlvbi5kZWNvZGUoY29kZXdvcmRzLCBudW1FQ0NvZGV3b3JkcywgZXJhc3VyZXMpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBWZXJpZnkgdGhhdCBhbGwgaXMgT0sgd2l0aCB0aGUgY29kZXdvcmQgYXJyYXkuXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgdmVyaWZ5Q29kZXdvcmRDb3VudChjb2Rld29yZHMsIG51bUVDQ29kZXdvcmRzKSB7XG4gICAgICAgICAgICBpZiAoY29kZXdvcmRzLmxlbmd0aCA8IDQpIHtcbiAgICAgICAgICAgICAgICAvLyBDb2Rld29yZCBhcnJheSBzaXplIHNob3VsZCBiZSBhdCBsZWFzdCA0IGFsbG93aW5nIGZvclxuICAgICAgICAgICAgICAgIC8vIENvdW50IENXLCBBdCBsZWFzdCBvbmUgRGF0YSBDVywgRXJyb3IgQ29ycmVjdGlvbiBDVywgRXJyb3IgQ29ycmVjdGlvbiBDV1xuICAgICAgICAgICAgICAgIHRocm93IEZvcm1hdEV4Y2VwdGlvbi5nZXRGb3JtYXRJbnN0YW5jZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gVGhlIGZpcnN0IGNvZGV3b3JkLCB0aGUgU3ltYm9sIExlbmd0aCBEZXNjcmlwdG9yLCBzaGFsbCBhbHdheXMgZW5jb2RlIHRoZSB0b3RhbCBudW1iZXIgb2YgZGF0YVxuICAgICAgICAgICAgLy8gY29kZXdvcmRzIGluIHRoZSBzeW1ib2wsIGluY2x1ZGluZyB0aGUgU3ltYm9sIExlbmd0aCBEZXNjcmlwdG9yIGl0c2VsZiwgZGF0YSBjb2Rld29yZHMgYW5kIHBhZFxuICAgICAgICAgICAgLy8gY29kZXdvcmRzLCBidXQgZXhjbHVkaW5nIHRoZSBudW1iZXIgb2YgZXJyb3IgY29ycmVjdGlvbiBjb2Rld29yZHMuXG4gICAgICAgICAgICBsZXQgbnVtYmVyT2ZDb2Rld29yZHMgPSBjb2Rld29yZHNbMF07XG4gICAgICAgICAgICBpZiAobnVtYmVyT2ZDb2Rld29yZHMgPiBjb2Rld29yZHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgRm9ybWF0RXhjZXB0aW9uLmdldEZvcm1hdEluc3RhbmNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobnVtYmVyT2ZDb2Rld29yZHMgPT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNldCB0byB0aGUgbGVuZ3RoIG9mIHRoZSBhcnJheSAtIDggKEFsbG93IGZvciBhdCBsZWFzdCBsZXZlbCAzIEVycm9yIENvcnJlY3Rpb24gKDggRXJyb3IgQ29kZXdvcmRzKVxuICAgICAgICAgICAgICAgIGlmIChudW1FQ0NvZGV3b3JkcyA8IGNvZGV3b3Jkcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgY29kZXdvcmRzWzBdID0gY29kZXdvcmRzLmxlbmd0aCAtIG51bUVDQ29kZXdvcmRzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgRm9ybWF0RXhjZXB0aW9uLmdldEZvcm1hdEluc3RhbmNlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXRCaXRDb3VudEZvckNvZGV3b3JkKGNvZGV3b3JkKSB7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gbmV3IEludDMyQXJyYXkoOCk7XG4gICAgICAgICAgICBsZXQgcHJldmlvdXNWYWx1ZSA9IDA7XG4gICAgICAgICAgICBsZXQgaSA9IHJlc3VsdC5sZW5ndGggLSAxO1xuICAgICAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoKGNvZGV3b3JkICYgMHgxKSAhPT0gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlID0gY29kZXdvcmQgJiAweDE7XG4gICAgICAgICAgICAgICAgICAgIGktLTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXN1bHRbaV0rKztcbiAgICAgICAgICAgICAgICBjb2Rld29yZCA+Pj0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdldENvZGV3b3JkQnVja2V0TnVtYmVyKGNvZGV3b3JkKSB7XG4gICAgICAgICAgICBpZiAoY29kZXdvcmQgaW5zdGFuY2VvZiBJbnQzMkFycmF5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29kZXdvcmRCdWNrZXROdW1iZXJfSW50MzJBcnJheShjb2Rld29yZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRDb2Rld29yZEJ1Y2tldE51bWJlcl9udW1iZXIoY29kZXdvcmQpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXRDb2Rld29yZEJ1Y2tldE51bWJlcl9udW1iZXIoY29kZXdvcmQpIHtcbiAgICAgICAgICAgIHJldHVybiBQREY0MTdTY2FubmluZ0RlY29kZXIuZ2V0Q29kZXdvcmRCdWNrZXROdW1iZXIoUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmdldEJpdENvdW50Rm9yQ29kZXdvcmQoY29kZXdvcmQpKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZ2V0Q29kZXdvcmRCdWNrZXROdW1iZXJfSW50MzJBcnJheShtb2R1bGVCaXRDb3VudCkge1xuICAgICAgICAgICAgcmV0dXJuIChtb2R1bGVCaXRDb3VudFswXSAtIG1vZHVsZUJpdENvdW50WzJdICsgbW9kdWxlQml0Q291bnRbNF0gLSBtb2R1bGVCaXRDb3VudFs2XSArIDkpICUgOTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgdG9TdHJpbmcoYmFyY29kZU1hdHJpeCkge1xuICAgICAgICAgICAgbGV0IGZvcm1hdHRlciA9IG5ldyBGb3JtYXR0ZXIoKTtcbiAgICAgICAgICAgIC8vIHRyeSAobGV0IGZvcm1hdHRlciA9IG5ldyBGb3JtYXR0ZXIoKSkge1xuICAgICAgICAgICAgZm9yIChsZXQgcm93IC8qaW50Ki8gPSAwOyByb3cgPCBiYXJjb2RlTWF0cml4Lmxlbmd0aDsgcm93KyspIHtcbiAgICAgICAgICAgICAgICBmb3JtYXR0ZXIuZm9ybWF0KCdSb3cgJTJkOiAnLCByb3cpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGNvbHVtbiAvKmludCovID0gMDsgY29sdW1uIDwgYmFyY29kZU1hdHJpeFtyb3ddLmxlbmd0aDsgY29sdW1uKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGJhcmNvZGVWYWx1ZSA9IGJhcmNvZGVNYXRyaXhbcm93XVtjb2x1bW5dO1xuICAgICAgICAgICAgICAgICAgICBpZiAoYmFyY29kZVZhbHVlLmdldFZhbHVlKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXR0ZXIuZm9ybWF0KCcgICAgICAgICcsIG51bGwpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0dGVyLmZvcm1hdCgnJTRkKCUyZCknLCBiYXJjb2RlVmFsdWUuZ2V0VmFsdWUoKVswXSwgYmFyY29kZVZhbHVlLmdldENvbmZpZGVuY2UoYmFyY29kZVZhbHVlLmdldFZhbHVlKClbMF0pKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3JtYXR0ZXIuZm9ybWF0KCclbicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZvcm1hdHRlci50b1N0cmluZygpO1xuICAgICAgICAgICAgLy8gfVxuICAgICAgICB9XG4gICAgfVxuICAgIC8qZmluYWwqLyBQREY0MTdTY2FubmluZ0RlY29kZXIuQ09ERVdPUkRfU0tFV19TSVpFID0gMjtcbiAgICAvKmZpbmFsKi8gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLk1BWF9FUlJPUlMgPSAzO1xuICAgIC8qZmluYWwqLyBQREY0MTdTY2FubmluZ0RlY29kZXIuTUFYX0VDX0NPREVXT1JEUyA9IDUxMjtcbiAgICAvKmZpbmFsKi8gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmVycm9yQ29ycmVjdGlvbiA9IG5ldyBFcnJvckNvcnJlY3Rpb24oKTtcblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDkgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7XG4gICAgLy8gaW1wb3J0IGphdmEudXRpbC5MaXN0O1xuICAgIC8vIGltcG9ydCBqYXZhLnV0aWwuTWFwO1xuICAgIC8qKlxuICAgICAqIFRoaXMgaW1wbGVtZW50YXRpb24gY2FuIGRldGVjdCBhbmQgZGVjb2RlIFBERjQxNyBjb2RlcyBpbiBhbiBpbWFnZS5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgR3VlbnRoZXIgR3JhdVxuICAgICAqL1xuICAgIC8qcHVibGljIGZpbmFsKi8gY2xhc3MgUERGNDE3UmVhZGVyIHtcbiAgICAgICAgLy8gcHJpdmF0ZSBzdGF0aWMgLypmaW5hbCBSZXN1bHRbXSovIEVNUFRZX1JFU1VMVF9BUlJBWTogUmVzdWx0W10gPSBuZXcgUmVzdWx0KFswXSk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBMb2NhdGVzIGFuZCBkZWNvZGVzIGEgUERGNDE3IGNvZGUgaW4gYW4gaW1hZ2UuXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm4gYSBTdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBjb250ZW50IGVuY29kZWQgYnkgdGhlIFBERjQxNyBjb2RlXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gaWYgYSBQREY0MTcgY29kZSBjYW5ub3QgYmUgZm91bmQsXG4gICAgICAgICAqIEB0aHJvd3MgRm9ybWF0RXhjZXB0aW9uIGlmIGEgUERGNDE3IGNhbm5vdCBiZSBkZWNvZGVkXG4gICAgICAgICAqIEB0aHJvd3MgQ2hlY2tzdW1FeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIC8vIEBPdmVycmlkZVxuICAgICAgICBkZWNvZGUoaW1hZ2UsIGhpbnRzID0gbnVsbCkge1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IFBERjQxN1JlYWRlci5kZWNvZGUoaW1hZ2UsIGhpbnRzLCBmYWxzZSk7XG4gICAgICAgICAgICBpZiAocmVzdWx0ID09IG51bGwgfHwgcmVzdWx0Lmxlbmd0aCA9PT0gMCB8fCByZXN1bHRbMF0gPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRocm93IE5vdEZvdW5kRXhjZXB0aW9uLmdldE5vdEZvdW5kSW5zdGFuY2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHRbMF07XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBCaW5hcnlCaXRtYXBcbiAgICAgICAgICogQHBhcmFtIGltYWdlXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIC8vICAgQE92ZXJyaWRlXG4gICAgICAgIGRlY29kZU11bHRpcGxlKGltYWdlLCBoaW50cyA9IG51bGwpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFBERjQxN1JlYWRlci5kZWNvZGUoaW1hZ2UsIGhpbnRzLCB0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChpZ25vcmVkKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlnbm9yZWQgaW5zdGFuY2VvZiBGb3JtYXRFeGNlcHRpb24gfHwgaWdub3JlZCBpbnN0YW5jZW9mIENoZWNrc3VtRXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IE5vdEZvdW5kRXhjZXB0aW9uLmdldE5vdEZvdW5kSW5zdGFuY2UoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhyb3cgaWdub3JlZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGltYWdlXG4gICAgICAgICAqIEBwYXJhbSBoaW50c1xuICAgICAgICAgKiBAcGFyYW0gbXVsdGlwbGVcbiAgICAgICAgICpcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvblxuICAgICAgICAgKiBAdGhyb3dzIEZvcm1hdEV4Y2VwdGlvbsOfXG4gICAgICAgICAqIEB0aHJvd3MgQ2hlY2tzdW1FeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBkZWNvZGUoaW1hZ2UsIGhpbnRzLCBtdWx0aXBsZSkge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0cyA9IG5ldyBBcnJheSgpO1xuICAgICAgICAgICAgY29uc3QgZGV0ZWN0b3JSZXN1bHQgPSBEZXRlY3RvciQzLmRldGVjdE11bHRpcGxlKGltYWdlLCBoaW50cywgbXVsdGlwbGUpO1xuICAgICAgICAgICAgZm9yIChjb25zdCBwb2ludHMgb2YgZGV0ZWN0b3JSZXN1bHQuZ2V0UG9pbnRzKCkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkZWNvZGVyUmVzdWx0ID0gUERGNDE3U2Nhbm5pbmdEZWNvZGVyLmRlY29kZShkZXRlY3RvclJlc3VsdC5nZXRCaXRzKCksIHBvaW50c1s0XSwgcG9pbnRzWzVdLCBwb2ludHNbNl0sIHBvaW50c1s3XSwgUERGNDE3UmVhZGVyLmdldE1pbkNvZGV3b3JkV2lkdGgocG9pbnRzKSwgUERGNDE3UmVhZGVyLmdldE1heENvZGV3b3JkV2lkdGgocG9pbnRzKSk7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IFJlc3VsdChkZWNvZGVyUmVzdWx0LmdldFRleHQoKSwgZGVjb2RlclJlc3VsdC5nZXRSYXdCeXRlcygpLCB1bmRlZmluZWQsIHBvaW50cywgQmFyY29kZUZvcm1hdCQxLlBERl80MTcpO1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXRNZXRhZGF0YShSZXN1bHRNZXRhZGF0YVR5cGUkMS5FUlJPUl9DT1JSRUNUSU9OX0xFVkVMLCBkZWNvZGVyUmVzdWx0LmdldEVDTGV2ZWwoKSk7XG4gICAgICAgICAgICAgICAgY29uc3QgcGRmNDE3UmVzdWx0TWV0YWRhdGEgPSBkZWNvZGVyUmVzdWx0LmdldE90aGVyKCk7XG4gICAgICAgICAgICAgICAgaWYgKHBkZjQxN1Jlc3VsdE1ldGFkYXRhICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1dE1ldGFkYXRhKFJlc3VsdE1ldGFkYXRhVHlwZSQxLlBERjQxN19FWFRSQV9NRVRBREFUQSwgcGRmNDE3UmVzdWx0TWV0YWRhdGEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXN1bHRzLnB1c2gocmVzdWx0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHRzLm1hcCh4ID0+IHgpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXRNYXhXaWR0aChwMSwgcDIpIHtcbiAgICAgICAgICAgIGlmIChwMSA9PSBudWxsIHx8IHAyID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBNYXRoLnRydW5jKE1hdGguYWJzKHAxLmdldFgoKSAtIHAyLmdldFgoKSkpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXRNaW5XaWR0aChwMSwgcDIpIHtcbiAgICAgICAgICAgIGlmIChwMSA9PSBudWxsIHx8IHAyID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gSW50ZWdlci5NQVhfVkFMVUU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gTWF0aC50cnVuYyhNYXRoLmFicyhwMS5nZXRYKCkgLSBwMi5nZXRYKCkpKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZ2V0TWF4Q29kZXdvcmRXaWR0aChwKSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLm1heChNYXRoLm1heChQREY0MTdSZWFkZXIuZ2V0TWF4V2lkdGgocFswXSwgcFs0XSksIFBERjQxN1JlYWRlci5nZXRNYXhXaWR0aChwWzZdLCBwWzJdKSAqIFBERjQxN0NvbW1vbi5NT0RVTEVTX0lOX0NPREVXT1JEIC9cbiAgICAgICAgICAgICAgICBQREY0MTdDb21tb24uTU9EVUxFU19JTl9TVE9QX1BBVFRFUk4pLCBNYXRoLm1heChQREY0MTdSZWFkZXIuZ2V0TWF4V2lkdGgocFsxXSwgcFs1XSksIFBERjQxN1JlYWRlci5nZXRNYXhXaWR0aChwWzddLCBwWzNdKSAqIFBERjQxN0NvbW1vbi5NT0RVTEVTX0lOX0NPREVXT1JEIC9cbiAgICAgICAgICAgICAgICBQREY0MTdDb21tb24uTU9EVUxFU19JTl9TVE9QX1BBVFRFUk4pKSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdldE1pbkNvZGV3b3JkV2lkdGgocCkge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoTWF0aC5taW4oTWF0aC5taW4oUERGNDE3UmVhZGVyLmdldE1pbldpZHRoKHBbMF0sIHBbNF0pLCBQREY0MTdSZWFkZXIuZ2V0TWluV2lkdGgocFs2XSwgcFsyXSkgKiBQREY0MTdDb21tb24uTU9EVUxFU19JTl9DT0RFV09SRCAvXG4gICAgICAgICAgICAgICAgUERGNDE3Q29tbW9uLk1PRFVMRVNfSU5fU1RPUF9QQVRURVJOKSwgTWF0aC5taW4oUERGNDE3UmVhZGVyLmdldE1pbldpZHRoKHBbMV0sIHBbNV0pLCBQREY0MTdSZWFkZXIuZ2V0TWluV2lkdGgocFs3XSwgcFszXSkgKiBQREY0MTdDb21tb24uTU9EVUxFU19JTl9DT0RFV09SRCAvXG4gICAgICAgICAgICAgICAgUERGNDE3Q29tbW9uLk1PRFVMRVNfSU5fU1RPUF9QQVRURVJOKSkpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEBPdmVycmlkZVxuICAgICAgICByZXNldCgpIHtcbiAgICAgICAgICAgIC8vIG5vdGhpbmcgbmVlZHMgdG8gYmUgcmVzZXRcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEN1c3RvbSBFcnJvciBjbGFzcyBvZiB0eXBlIEV4Y2VwdGlvbi5cbiAgICAgKi9cbiAgICBjbGFzcyBSZWFkZXJFeGNlcHRpb24gZXh0ZW5kcyBFeGNlcHRpb24ge1xuICAgIH1cbiAgICBSZWFkZXJFeGNlcHRpb24ua2luZCA9ICdSZWFkZXJFeGNlcHRpb24nO1xuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAwOSBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvKm5hbWVzcGFjZSBjb20uZ29vZ2xlLnp4aW5nIHsqL1xuICAgIC8qKlxuICAgICAqIE11bHRpRm9ybWF0UmVhZGVyIGlzIGEgY29udmVuaWVuY2UgY2xhc3MgYW5kIHRoZSBtYWluIGVudHJ5IHBvaW50IGludG8gdGhlIGxpYnJhcnkgZm9yIG1vc3QgdXNlcy5cbiAgICAgKiBCeSBkZWZhdWx0IGl0IGF0dGVtcHRzIHRvIGRlY29kZSBhbGwgYmFyY29kZSBmb3JtYXRzIHRoYXQgdGhlIGxpYnJhcnkgc3VwcG9ydHMuIE9wdGlvbmFsbHksIHlvdVxuICAgICAqIGNhbiBwcm92aWRlIGEgaGludHMgb2JqZWN0IHRvIHJlcXVlc3QgZGlmZmVyZW50IGJlaGF2aW9yLCBmb3IgZXhhbXBsZSBvbmx5IGRlY29kaW5nIFFSIGNvZGVzLlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKiBAYXV0aG9yIGRzd2l0a2luQGdvb2dsZS5jb20gKERhbmllbCBTd2l0a2luKVxuICAgICAqL1xuICAgIGNsYXNzIE11bHRpRm9ybWF0UmVhZGVyIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgdGhpcyBjbGFzc1xuICAgICAgICAgKiBcbiAgICAgICAgICogQHBhcmFtIHtCb29sZWFufSB2ZXJib3NlIGlmICd0cnVlJyBsb2dzIHdpbGwgYmUgZHVtcGVkIHRvIGNvbnNvbGUsIG90aGVyd2lzZSBoaWRkZW4uXG4gICAgICAgICAqIEBwYXJhbSBoaW50cyBUaGUgaGludHMgdG8gdXNlLCBjbGVhcmluZyB0aGUgcHJldmlvdXMgc3RhdGUuXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdHJ1Y3Rvcih2ZXJib3NlLCBoaW50cykge1xuICAgICAgICAgICAgdGhpcy52ZXJib3NlID0gKHZlcmJvc2UgPT09IHRydWUpO1xuICAgICAgICAgICAgaWYgKGhpbnRzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRIaW50cyhoaW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoaXMgdmVyc2lvbiBvZiBkZWNvZGUgaG9ub3JzIHRoZSBpbnRlbnQgb2YgUmVhZGVyLmRlY29kZShCaW5hcnlCaXRtYXApIGluIHRoYXQgaXRcbiAgICAgICAgICogcGFzc2VzIG51bGwgYXMgYSBoaW50IHRvIHRoZSBkZWNvZGVycy4gSG93ZXZlciwgdGhhdCBtYWtlcyBpdCBpbmVmZmljaWVudCB0byBjYWxsIHJlcGVhdGVkbHkuXG4gICAgICAgICAqIFVzZSBzZXRIaW50cygpIGZvbGxvd2VkIGJ5IGRlY29kZVdpdGhTdGF0ZSgpIGZvciBjb250aW51b3VzIHNjYW4gYXBwbGljYXRpb25zLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gaW1hZ2UgVGhlIHBpeGVsIGRhdGEgdG8gZGVjb2RlXG4gICAgICAgICAqIEByZXR1cm4gVGhlIGNvbnRlbnRzIG9mIHRoZSBpbWFnZVxuICAgICAgICAgKlxuICAgICAgICAgKiBAdGhyb3dzIE5vdEZvdW5kRXhjZXB0aW9uIEFueSBlcnJvcnMgd2hpY2ggb2NjdXJyZWRcbiAgICAgICAgICovXG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgLy8gcHVibGljIGRlY29kZShpbWFnZTogQmluYXJ5Qml0bWFwKTogUmVzdWx0IHtcbiAgICAgICAgLy8gICBzZXRIaW50cyhudWxsKVxuICAgICAgICAvLyAgIHJldHVybiBkZWNvZGVJbnRlcm5hbChpbWFnZSlcbiAgICAgICAgLy8gfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlIGFuIGltYWdlIHVzaW5nIHRoZSBoaW50cyBwcm92aWRlZC4gRG9lcyBub3QgaG9ub3IgZXhpc3Rpbmcgc3RhdGUuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBpbWFnZSBUaGUgcGl4ZWwgZGF0YSB0byBkZWNvZGVcbiAgICAgICAgICogQHBhcmFtIGhpbnRzIFRoZSBoaW50cyB0byB1c2UsIGNsZWFyaW5nIHRoZSBwcmV2aW91cyBzdGF0ZS5cbiAgICAgICAgICogQHJldHVybiBUaGUgY29udGVudHMgb2YgdGhlIGltYWdlXG4gICAgICAgICAqXG4gICAgICAgICAqIEB0aHJvd3MgTm90Rm91bmRFeGNlcHRpb24gQW55IGVycm9ycyB3aGljaCBvY2N1cnJlZFxuICAgICAgICAgKi9cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBkZWNvZGUoaW1hZ2UsIGhpbnRzKSB7XG4gICAgICAgICAgICBpZiAoaGludHMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldEhpbnRzKGhpbnRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZUludGVybmFsKGltYWdlKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlIGFuIGltYWdlIHVzaW5nIHRoZSBzdGF0ZSBzZXQgdXAgYnkgY2FsbGluZyBzZXRIaW50cygpIHByZXZpb3VzbHkuIENvbnRpbnVvdXMgc2NhblxuICAgICAgICAgKiBjbGllbnRzIHdpbGwgZ2V0IGEgPGI+bGFyZ2U8L2I+IHNwZWVkIGluY3JlYXNlIGJ5IHVzaW5nIHRoaXMgaW5zdGVhZCBvZiBkZWNvZGUoKS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGltYWdlIFRoZSBwaXhlbCBkYXRhIHRvIGRlY29kZVxuICAgICAgICAgKiBAcmV0dXJuIFRoZSBjb250ZW50cyBvZiB0aGUgaW1hZ2VcbiAgICAgICAgICpcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvbiBBbnkgZXJyb3JzIHdoaWNoIG9jY3VycmVkXG4gICAgICAgICAqL1xuICAgICAgICBkZWNvZGVXaXRoU3RhdGUoaW1hZ2UpIHtcbiAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSB0byBzZXQgdXAgdGhlIGRlZmF1bHQgc3RhdGUgc28gd2UgZG9uJ3QgY3Jhc2hcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRlcnMgPT09IG51bGwgfHwgdGhpcy5yZWFkZXJzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldEhpbnRzKG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlSW50ZXJuYWwoaW1hZ2UpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGlzIG1ldGhvZCBhZGRzIHN0YXRlIHRvIHRoZSBNdWx0aUZvcm1hdFJlYWRlci4gQnkgc2V0dGluZyB0aGUgaGludHMgb25jZSwgc3Vic2VxdWVudCBjYWxsc1xuICAgICAgICAgKiB0byBkZWNvZGVXaXRoU3RhdGUoaW1hZ2UpIGNhbiByZXVzZSB0aGUgc2FtZSBzZXQgb2YgcmVhZGVycyB3aXRob3V0IHJlYWxsb2NhdGluZyBtZW1vcnkuIFRoaXNcbiAgICAgICAgICogaXMgaW1wb3J0YW50IGZvciBwZXJmb3JtYW5jZSBpbiBjb250aW51b3VzIHNjYW4gY2xpZW50cy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGhpbnRzIFRoZSBzZXQgb2YgaGludHMgdG8gdXNlIGZvciBzdWJzZXF1ZW50IGNhbGxzIHRvIGRlY29kZShpbWFnZSlcbiAgICAgICAgICovXG4gICAgICAgIHNldEhpbnRzKGhpbnRzKSB7XG4gICAgICAgICAgICB0aGlzLmhpbnRzID0gaGludHM7XG4gICAgICAgICAgICBjb25zdCB0cnlIYXJkZXIgPSAhaXNOdWxsT3JVbmRlZmluZWQoaGludHMpXG4gICAgICAgICAgICAgICAgJiYgaGludHMuZ2V0KERlY29kZUhpbnRUeXBlJDEuVFJZX0hBUkRFUikgPT09IHRydWU7XG4gICAgICAgICAgICBjb25zdCBmb3JtYXRzID0gaXNOdWxsT3JVbmRlZmluZWQoaGludHMpID8gbnVsbCA6IGhpbnRzLmdldChEZWNvZGVIaW50VHlwZSQxLlBPU1NJQkxFX0ZPUk1BVFMpO1xuICAgICAgICAgICAgY29uc3QgcmVhZGVycyA9IG5ldyBBcnJheSgpO1xuICAgICAgICAgICAgaWYgKCFpc051bGxPclVuZGVmaW5lZChmb3JtYXRzKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFkZE9uZURSZWFkZXIgPSBmb3JtYXRzLnNvbWUoZiA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBmID09PSBCYXJjb2RlRm9ybWF0JDEuVVBDX0EgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIGYgPT09IEJhcmNvZGVGb3JtYXQkMS5VUENfRSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgZiA9PT0gQmFyY29kZUZvcm1hdCQxLkVBTl8xMyB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgZiA9PT0gQmFyY29kZUZvcm1hdCQxLkVBTl84IHx8XG4gICAgICAgICAgICAgICAgICAgICAgICBmID09PSBCYXJjb2RlRm9ybWF0JDEuQ09EQUJBUiB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgZiA9PT0gQmFyY29kZUZvcm1hdCQxLkNPREVfMzkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIGYgPT09IEJhcmNvZGVGb3JtYXQkMS5DT0RFXzkzIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICBmID09PSBCYXJjb2RlRm9ybWF0JDEuQ09ERV8xMjggfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIGYgPT09IEJhcmNvZGVGb3JtYXQkMS5JVEYgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIGYgPT09IEJhcmNvZGVGb3JtYXQkMS5SU1NfMTQgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIGYgPT09IEJhcmNvZGVGb3JtYXQkMS5SU1NfRVhQQU5ERUQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIC8vIFB1dCAxRCByZWFkZXJzIHVwZnJvbnQgaW4gXCJub3JtYWxcIiBtb2RlXG4gICAgICAgICAgICAgICAgaWYgKGFkZE9uZURSZWFkZXIgJiYgIXRyeUhhcmRlcikge1xuICAgICAgICAgICAgICAgICAgICByZWFkZXJzLnB1c2gobmV3IE11bHRpRm9ybWF0T25lRFJlYWRlcihoaW50cywgdGhpcy52ZXJib3NlKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChmb3JtYXRzLmluY2x1ZGVzKEJhcmNvZGVGb3JtYXQkMS5RUl9DT0RFKSkge1xuICAgICAgICAgICAgICAgICAgICByZWFkZXJzLnB1c2gobmV3IFFSQ29kZVJlYWRlcigpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGZvcm1hdHMuaW5jbHVkZXMoQmFyY29kZUZvcm1hdCQxLkRBVEFfTUFUUklYKSkge1xuICAgICAgICAgICAgICAgICAgICByZWFkZXJzLnB1c2gobmV3IERhdGFNYXRyaXhSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChmb3JtYXRzLmluY2x1ZGVzKEJhcmNvZGVGb3JtYXQkMS5BWlRFQykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVycy5wdXNoKG5ldyBBenRlY1JlYWRlcigpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGZvcm1hdHMuaW5jbHVkZXMoQmFyY29kZUZvcm1hdCQxLlBERl80MTcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlcnMucHVzaChuZXcgUERGNDE3UmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBpZiAoZm9ybWF0cy5pbmNsdWRlcyhCYXJjb2RlRm9ybWF0Lk1BWElDT0RFKSkge1xuICAgICAgICAgICAgICAgIC8vICAgIHJlYWRlcnMucHVzaChuZXcgTWF4aUNvZGVSZWFkZXIoKSlcbiAgICAgICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICAgICAgLy8gQXQgZW5kIGluIFwidHJ5IGhhcmRlclwiIG1vZGVcbiAgICAgICAgICAgICAgICBpZiAoYWRkT25lRFJlYWRlciAmJiB0cnlIYXJkZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVycy5wdXNoKG5ldyBNdWx0aUZvcm1hdE9uZURSZWFkZXIoaGludHMsIHRoaXMudmVyYm9zZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyZWFkZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGlmICghdHJ5SGFyZGVyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlcnMucHVzaChuZXcgTXVsdGlGb3JtYXRPbmVEUmVhZGVyKGhpbnRzLCB0aGlzLnZlcmJvc2UpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVhZGVycy5wdXNoKG5ldyBRUkNvZGVSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgcmVhZGVycy5wdXNoKG5ldyBEYXRhTWF0cml4UmVhZGVyKCkpO1xuICAgICAgICAgICAgICAgIHJlYWRlcnMucHVzaChuZXcgQXp0ZWNSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgcmVhZGVycy5wdXNoKG5ldyBQREY0MTdSZWFkZXIoKSk7XG4gICAgICAgICAgICAgICAgLy8gcmVhZGVycy5wdXNoKG5ldyBNYXhpQ29kZVJlYWRlcigpKVxuICAgICAgICAgICAgICAgIGlmICh0cnlIYXJkZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVycy5wdXNoKG5ldyBNdWx0aUZvcm1hdE9uZURSZWFkZXIoaGludHMsIHRoaXMudmVyYm9zZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucmVhZGVycyA9IHJlYWRlcnM7IC8vIC50b0FycmF5KG5ldyBSZWFkZXJbcmVhZGVycy5zaXplKCldKVxuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgcmVzZXQoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkZXJzICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCByZWFkZXIgb2YgdGhpcy5yZWFkZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlci5yZXNldCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHRocm93cyBOb3RGb3VuZEV4Y2VwdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlSW50ZXJuYWwoaW1hZ2UpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRlcnMgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUmVhZGVyRXhjZXB0aW9uKCdObyByZWFkZXJzIHdoZXJlIHNlbGVjdGVkLCBub3RoaW5nIGNhbiBiZSByZWFkLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChjb25zdCByZWFkZXIgb2YgdGhpcy5yZWFkZXJzKSB7XG4gICAgICAgICAgICAgICAgLy8gVHJ5aW5nIHRvIGRlY29kZSB3aXRoICR7cmVhZGVyfSByZWFkZXIuXG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlYWRlci5kZWNvZGUoaW1hZ2UsIHRoaXMuaGludHMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUmVhZGVyRXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBCYWQgRXhjZXB0aW9uLlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbignTm8gTXVsdGlGb3JtYXQgUmVhZGVycyB3ZXJlIGFibGUgdG8gZGV0ZWN0IHRoZSBjb2RlLicpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xhc3MgQnJvd3Nlck11bHRpRm9ybWF0UmVhZGVyIGV4dGVuZHMgQnJvd3NlckNvZGVSZWFkZXIge1xuICAgICAgICBjb25zdHJ1Y3RvcihoaW50cyA9IG51bGwsIHRpbWVCZXR3ZWVuU2NhbnNNaWxsaXMgPSA1MDApIHtcbiAgICAgICAgICAgIGNvbnN0IHJlYWRlciA9IG5ldyBNdWx0aUZvcm1hdFJlYWRlcigpO1xuICAgICAgICAgICAgcmVhZGVyLnNldEhpbnRzKGhpbnRzKTtcbiAgICAgICAgICAgIHN1cGVyKHJlYWRlciwgdGltZUJldHdlZW5TY2Fuc01pbGxpcyk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE92ZXJ3cml0ZSBkZWNvZGVCaXRtYXAgdG8gY2FsbCBkZWNvZGVXaXRoU3RhdGUsIHdoaWNoIHdpbGwgcGF5XG4gICAgICAgICAqIGF0dGVudGlvbiB0byB0aGUgaGludHMgc2V0IGluIHRoZSBjb25zdHJ1Y3RvciBmdW5jdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgZGVjb2RlQml0bWFwKGJpbmFyeUJpdG1hcCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVhZGVyLmRlY29kZVdpdGhTdGF0ZShiaW5hcnlCaXRtYXApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGRlcHJlY2F0ZWQgTW92aW5nIHRvIEB6eGluZy9icm93c2VyXG4gICAgICpcbiAgICAgKiBRUiBDb2RlIHJlYWRlciB0byB1c2UgZnJvbSBicm93c2VyLlxuICAgICAqL1xuICAgIGNsYXNzIEJyb3dzZXJQREY0MTdSZWFkZXIgZXh0ZW5kcyBCcm93c2VyQ29kZVJlYWRlciB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIEJyb3dzZXJQREY0MTdSZWFkZXIuXG4gICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbdGltZUJldHdlZW5TY2Fuc01pbGxpcz01MDBdIHRoZSB0aW1lIGRlbGF5IGJldHdlZW4gc3Vic2VxdWVudCBkZWNvZGUgdHJpZXNcbiAgICAgICAgICovXG4gICAgICAgIGNvbnN0cnVjdG9yKHRpbWVCZXR3ZWVuU2NhbnNNaWxsaXMgPSA1MDApIHtcbiAgICAgICAgICAgIHN1cGVyKG5ldyBQREY0MTdSZWFkZXIoKSwgdGltZUJldHdlZW5TY2Fuc01pbGxpcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAZGVwcmVjYXRlZCBNb3ZpbmcgdG8gQHp4aW5nL2Jyb3dzZXJcbiAgICAgKlxuICAgICAqIFFSIENvZGUgcmVhZGVyIHRvIHVzZSBmcm9tIGJyb3dzZXIuXG4gICAgICovXG4gICAgY2xhc3MgQnJvd3NlclFSQ29kZVJlYWRlciBleHRlbmRzIEJyb3dzZXJDb2RlUmVhZGVyIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgQnJvd3NlclFSQ29kZVJlYWRlci5cbiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IFt0aW1lQmV0d2VlblNjYW5zTWlsbGlzPTUwMF0gdGhlIHRpbWUgZGVsYXkgYmV0d2VlbiBzdWJzZXF1ZW50IGRlY29kZSB0cmllc1xuICAgICAgICAgKi9cbiAgICAgICAgY29uc3RydWN0b3IodGltZUJldHdlZW5TY2Fuc01pbGxpcyA9IDUwMCkge1xuICAgICAgICAgICAgc3VwZXIobmV3IFFSQ29kZVJlYWRlcigpLCB0aW1lQmV0d2VlblNjYW5zTWlsbGlzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDkgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLypuYW1lc3BhY2UgY29tLmdvb2dsZS56eGluZyB7Ki9cbiAgICAvKipcbiAgICAgKiBUaGVzZSBhcmUgYSBzZXQgb2YgaGludHMgdGhhdCB5b3UgbWF5IHBhc3MgdG8gV3JpdGVycyB0byBzcGVjaWZ5IHRoZWlyIGJlaGF2aW9yLlxuICAgICAqXG4gICAgICogQGF1dGhvciBkc3dpdGtpbkBnb29nbGUuY29tIChEYW5pZWwgU3dpdGtpbilcbiAgICAgKi9cbiAgICB2YXIgRW5jb2RlSGludFR5cGU7XG4gICAgKGZ1bmN0aW9uIChFbmNvZGVIaW50VHlwZSkge1xuICAgICAgICAvKipcbiAgICAgICAgICogU3BlY2lmaWVzIHdoYXQgZGVncmVlIG9mIGVycm9yIGNvcnJlY3Rpb24gdG8gdXNlLCBmb3IgZXhhbXBsZSBpbiBRUiBDb2Rlcy5cbiAgICAgICAgICogVHlwZSBkZXBlbmRzIG9uIHRoZSBlbmNvZGVyLiBGb3IgZXhhbXBsZSBmb3IgUVIgY29kZXMgaXQncyB0eXBlXG4gICAgICAgICAqIHtAbGluayBjb20uZ29vZ2xlLnp4aW5nLnFyY29kZS5kZWNvZGVyLkVycm9yQ29ycmVjdGlvbkxldmVsIEVycm9yQ29ycmVjdGlvbkxldmVsfS5cbiAgICAgICAgICogRm9yIEF6dGVjIGl0IGlzIG9mIHR5cGUge0BsaW5rIEludGVnZXJ9LCByZXByZXNlbnRpbmcgdGhlIG1pbmltYWwgcGVyY2VudGFnZSBvZiBlcnJvciBjb3JyZWN0aW9uIHdvcmRzLlxuICAgICAgICAgKiBGb3IgUERGNDE3IGl0IGlzIG9mIHR5cGUge0BsaW5rIEludGVnZXJ9LCB2YWxpZCB2YWx1ZXMgYmVpbmcgMCB0byA4LlxuICAgICAgICAgKiBJbiBhbGwgY2FzZXMsIGl0IGNhbiBhbHNvIGJlIGEge0BsaW5rIFN0cmluZ30gcmVwcmVzZW50YXRpb24gb2YgdGhlIGRlc2lyZWQgdmFsdWUgYXMgd2VsbC5cbiAgICAgICAgICogTm90ZTogYW4gQXp0ZWMgc3ltYm9sIHNob3VsZCBoYXZlIGEgbWluaW11bSBvZiAyNSUgRUMgd29yZHMuXG4gICAgICAgICAqL1xuICAgICAgICBFbmNvZGVIaW50VHlwZVtFbmNvZGVIaW50VHlwZVtcIkVSUk9SX0NPUlJFQ1RJT05cIl0gPSAwXSA9IFwiRVJST1JfQ09SUkVDVElPTlwiO1xuICAgICAgICAvKipcbiAgICAgICAgICogU3BlY2lmaWVzIHdoYXQgY2hhcmFjdGVyIGVuY29kaW5nIHRvIHVzZSB3aGVyZSBhcHBsaWNhYmxlICh0eXBlIHtAbGluayBTdHJpbmd9KVxuICAgICAgICAgKi9cbiAgICAgICAgRW5jb2RlSGludFR5cGVbRW5jb2RlSGludFR5cGVbXCJDSEFSQUNURVJfU0VUXCJdID0gMV0gPSBcIkNIQVJBQ1RFUl9TRVRcIjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNwZWNpZmllcyB0aGUgbWF0cml4IHNoYXBlIGZvciBEYXRhIE1hdHJpeCAodHlwZSB7QGxpbmsgY29tLmdvb2dsZS56eGluZy5kYXRhbWF0cml4LmVuY29kZXIuU3ltYm9sU2hhcGVIaW50fSlcbiAgICAgICAgICovXG4gICAgICAgIEVuY29kZUhpbnRUeXBlW0VuY29kZUhpbnRUeXBlW1wiREFUQV9NQVRSSVhfU0hBUEVcIl0gPSAyXSA9IFwiREFUQV9NQVRSSVhfU0hBUEVcIjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNwZWNpZmllcyBhIG1pbmltdW0gYmFyY29kZSBzaXplICh0eXBlIHtAbGluayBEaW1lbnNpb259KS4gT25seSBhcHBsaWNhYmxlIHRvIERhdGEgTWF0cml4IG5vdy5cbiAgICAgICAgICpcbiAgICAgICAgICogQGRlcHJlY2F0ZWQgdXNlIHdpZHRoL2hlaWdodCBwYXJhbXMgaW5cbiAgICAgICAgICoge0BsaW5rIGNvbS5nb29nbGUuenhpbmcuZGF0YW1hdHJpeC5EYXRhTWF0cml4V3JpdGVyI2VuY29kZShTdHJpbmcsIEJhcmNvZGVGb3JtYXQsIGludCwgaW50KX1cbiAgICAgICAgICovXG4gICAgICAgIC8qQERlcHJlY2F0ZWQqL1xuICAgICAgICBFbmNvZGVIaW50VHlwZVtFbmNvZGVIaW50VHlwZVtcIk1JTl9TSVpFXCJdID0gM10gPSBcIk1JTl9TSVpFXCI7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTcGVjaWZpZXMgYSBtYXhpbXVtIGJhcmNvZGUgc2l6ZSAodHlwZSB7QGxpbmsgRGltZW5zaW9ufSkuIE9ubHkgYXBwbGljYWJsZSB0byBEYXRhIE1hdHJpeCBub3cuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBkZXByZWNhdGVkIHdpdGhvdXQgcmVwbGFjZW1lbnRcbiAgICAgICAgICovXG4gICAgICAgIC8qQERlcHJlY2F0ZWQqL1xuICAgICAgICBFbmNvZGVIaW50VHlwZVtFbmNvZGVIaW50VHlwZVtcIk1BWF9TSVpFXCJdID0gNF0gPSBcIk1BWF9TSVpFXCI7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTcGVjaWZpZXMgbWFyZ2luLCBpbiBwaXhlbHMsIHRvIHVzZSB3aGVuIGdlbmVyYXRpbmcgdGhlIGJhcmNvZGUuIFRoZSBtZWFuaW5nIGNhbiB2YXJ5XG4gICAgICAgICAqIGJ5IGZvcm1hdDsgZm9yIGV4YW1wbGUgaXQgY29udHJvbHMgbWFyZ2luIGJlZm9yZSBhbmQgYWZ0ZXIgdGhlIGJhcmNvZGUgaG9yaXpvbnRhbGx5IGZvclxuICAgICAgICAgKiBtb3N0IDFEIGZvcm1hdHMuIChUeXBlIHtAbGluayBJbnRlZ2VyfSwgb3Ige0BsaW5rIFN0cmluZ30gcmVwcmVzZW50YXRpb24gb2YgdGhlIGludGVnZXIgdmFsdWUpLlxuICAgICAgICAgKi9cbiAgICAgICAgRW5jb2RlSGludFR5cGVbRW5jb2RlSGludFR5cGVbXCJNQVJHSU5cIl0gPSA1XSA9IFwiTUFSR0lOXCI7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTcGVjaWZpZXMgd2hldGhlciB0byB1c2UgY29tcGFjdCBtb2RlIGZvciBQREY0MTcgKHR5cGUge0BsaW5rIEJvb2xlYW59LCBvciBcInRydWVcIiBvciBcImZhbHNlXCJcbiAgICAgICAgICoge0BsaW5rIFN0cmluZ30gdmFsdWUpLlxuICAgICAgICAgKi9cbiAgICAgICAgRW5jb2RlSGludFR5cGVbRW5jb2RlSGludFR5cGVbXCJQREY0MTdfQ09NUEFDVFwiXSA9IDZdID0gXCJQREY0MTdfQ09NUEFDVFwiO1xuICAgICAgICAvKipcbiAgICAgICAgICogU3BlY2lmaWVzIHdoYXQgY29tcGFjdGlvbiBtb2RlIHRvIHVzZSBmb3IgUERGNDE3ICh0eXBlXG4gICAgICAgICAqIHtAbGluayBjb20uZ29vZ2xlLnp4aW5nLnBkZjQxNy5lbmNvZGVyLkNvbXBhY3Rpb24gQ29tcGFjdGlvbn0gb3Ige0BsaW5rIFN0cmluZ30gdmFsdWUgb2Ygb25lIG9mIGl0c1xuICAgICAgICAgKiBlbnVtIHZhbHVlcykuXG4gICAgICAgICAqL1xuICAgICAgICBFbmNvZGVIaW50VHlwZVtFbmNvZGVIaW50VHlwZVtcIlBERjQxN19DT01QQUNUSU9OXCJdID0gN10gPSBcIlBERjQxN19DT01QQUNUSU9OXCI7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTcGVjaWZpZXMgdGhlIG1pbmltdW0gYW5kIG1heGltdW0gbnVtYmVyIG9mIHJvd3MgYW5kIGNvbHVtbnMgZm9yIFBERjQxNyAodHlwZVxuICAgICAgICAgKiB7QGxpbmsgY29tLmdvb2dsZS56eGluZy5wZGY0MTcuZW5jb2Rlci5EaW1lbnNpb25zIERpbWVuc2lvbnN9KS5cbiAgICAgICAgICovXG4gICAgICAgIEVuY29kZUhpbnRUeXBlW0VuY29kZUhpbnRUeXBlW1wiUERGNDE3X0RJTUVOU0lPTlNcIl0gPSA4XSA9IFwiUERGNDE3X0RJTUVOU0lPTlNcIjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNwZWNpZmllcyB0aGUgcmVxdWlyZWQgbnVtYmVyIG9mIGxheWVycyBmb3IgYW4gQXp0ZWMgY29kZS5cbiAgICAgICAgICogQSBuZWdhdGl2ZSBudW1iZXIgKC0xLCAtMiwgLTMsIC00KSBzcGVjaWZpZXMgYSBjb21wYWN0IEF6dGVjIGNvZGUuXG4gICAgICAgICAqIDAgaW5kaWNhdGVzIHRvIHVzZSB0aGUgbWluaW11bSBudW1iZXIgb2YgbGF5ZXJzICh0aGUgZGVmYXVsdCkuXG4gICAgICAgICAqIEEgcG9zaXRpdmUgbnVtYmVyICgxLCAyLCAuLiAzMikgc3BlY2lmaWVzIGEgbm9ybWFsIChub24tY29tcGFjdCkgQXp0ZWMgY29kZS5cbiAgICAgICAgICogKFR5cGUge0BsaW5rIEludGVnZXJ9LCBvciB7QGxpbmsgU3RyaW5nfSByZXByZXNlbnRhdGlvbiBvZiB0aGUgaW50ZWdlciB2YWx1ZSkuXG4gICAgICAgICAqL1xuICAgICAgICBFbmNvZGVIaW50VHlwZVtFbmNvZGVIaW50VHlwZVtcIkFaVEVDX0xBWUVSU1wiXSA9IDldID0gXCJBWlRFQ19MQVlFUlNcIjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNwZWNpZmllcyB0aGUgZXhhY3QgdmVyc2lvbiBvZiBRUiBjb2RlIHRvIGJlIGVuY29kZWQuXG4gICAgICAgICAqIChUeXBlIHtAbGluayBJbnRlZ2VyfSwgb3Ige0BsaW5rIFN0cmluZ30gcmVwcmVzZW50YXRpb24gb2YgdGhlIGludGVnZXIgdmFsdWUpLlxuICAgICAgICAgKi9cbiAgICAgICAgRW5jb2RlSGludFR5cGVbRW5jb2RlSGludFR5cGVbXCJRUl9WRVJTSU9OXCJdID0gMTBdID0gXCJRUl9WRVJTSU9OXCI7XG4gICAgfSkoRW5jb2RlSGludFR5cGUgfHwgKEVuY29kZUhpbnRUeXBlID0ge30pKTtcbiAgICB2YXIgRW5jb2RlSGludFR5cGUkMSA9IEVuY29kZUhpbnRUeXBlO1xuXG4gICAgLyoqXG4gICAgICogPHA+SW1wbGVtZW50cyBSZWVkLVNvbG9tb24gZW5jb2RpbmcsIGFzIHRoZSBuYW1lIGltcGxpZXMuPC9wPlxuICAgICAqXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKiBAYXV0aG9yIFdpbGxpYW0gUnVja2xpZGdlXG4gICAgICovXG4gICAgY2xhc3MgUmVlZFNvbG9tb25FbmNvZGVyIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEEgcmVlZCBzb2xvbW9uIGVycm9yLWNvcnJlY3RpbmcgZW5jb2RpbmcgY29uc3RydWN0b3IgaXMgY3JlYXRlZCBieVxuICAgICAgICAgKiBwYXNzaW5nIGFzIEdhbG9pcyBGaWVsZCB3aXRoIG9mIHNpemUgZXF1YWwgdG8gdGhlIG51bWJlciBvZiBjb2RlXG4gICAgICAgICAqIHdvcmRzIChzeW1ib2xzKSBpbiB0aGUgYWxwaGFiZXQgKHRoZSBudW1iZXIgb2YgdmFsdWVzIGluIGVhY2hcbiAgICAgICAgICogZWxlbWVudCBvZiBhcnJheXMgdGhhdCBhcmUgZW5jb2RlZC9kZWNvZGVkKS5cbiAgICAgICAgICogQHBhcmFtIGZpZWxkIEEgZ2Fsb2lzIGZpZWxkIHdpdGggYSBudW1iZXIgb2YgZWxlbWVudHMgZXF1YWwgdG8gdGhlIHNpemVcbiAgICAgICAgICogb2YgdGhlIGFscGhhYmV0IG9mIHN5bWJvbHMgdG8gZW5jb2RlLlxuICAgICAgICAgKi9cbiAgICAgICAgY29uc3RydWN0b3IoZmllbGQpIHtcbiAgICAgICAgICAgIHRoaXMuZmllbGQgPSBmaWVsZDtcbiAgICAgICAgICAgIHRoaXMuY2FjaGVkR2VuZXJhdG9ycyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5jYWNoZWRHZW5lcmF0b3JzLnB1c2gobmV3IEdlbmVyaWNHRlBvbHkoZmllbGQsIEludDMyQXJyYXkuZnJvbShbMV0pKSk7XG4gICAgICAgIH1cbiAgICAgICAgYnVpbGRHZW5lcmF0b3IoZGVncmVlIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IGNhY2hlZEdlbmVyYXRvcnMgPSB0aGlzLmNhY2hlZEdlbmVyYXRvcnM7XG4gICAgICAgICAgICBpZiAoZGVncmVlID49IGNhY2hlZEdlbmVyYXRvcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgbGV0IGxhc3RHZW5lcmF0b3IgPSBjYWNoZWRHZW5lcmF0b3JzW2NhY2hlZEdlbmVyYXRvcnMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpZWxkO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGQgPSBjYWNoZWRHZW5lcmF0b3JzLmxlbmd0aDsgZCA8PSBkZWdyZWU7IGQrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXh0R2VuZXJhdG9yID0gbGFzdEdlbmVyYXRvci5tdWx0aXBseShuZXcgR2VuZXJpY0dGUG9seShmaWVsZCwgSW50MzJBcnJheS5mcm9tKFsxLCBmaWVsZC5leHAoZCAtIDEgKyBmaWVsZC5nZXRHZW5lcmF0b3JCYXNlKCkpXSkpKTtcbiAgICAgICAgICAgICAgICAgICAgY2FjaGVkR2VuZXJhdG9ycy5wdXNoKG5leHRHZW5lcmF0b3IpO1xuICAgICAgICAgICAgICAgICAgICBsYXN0R2VuZXJhdG9yID0gbmV4dEdlbmVyYXRvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkR2VuZXJhdG9yc1tkZWdyZWVdO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8cD5FbmNvZGUgYSBzZXF1ZW5jZSBvZiBjb2RlIHdvcmRzIChzeW1ib2xzKSB1c2luZyBSZWVkLVNvbG9tb24gdG8gYWxsb3cgZGVjb2RlcnNcbiAgICAgICAgICogdG8gZGV0ZWN0IGFuZCBjb3JyZWN0IGVycm9ycyB0aGF0IG1heSBoYXZlIGJlZW4gaW50cm9kdWNlZCB3aGVuIHRoZSByZXN1bHRpbmdcbiAgICAgICAgICogZGF0YSBpcyBzdG9yZWQgb3IgdHJhbnNtaXR0ZWQuPC9wPlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gdG9FbmNvZGUgYXJyYXkgdXNlZCBmb3IgYm90aCBhbmQgb3V0cHV0LiBDYWxsZXIgaW5pdGlhbGl6ZXMgdGhlIGFycmF5IHdpdGhcbiAgICAgICAgICogdGhlIGNvZGUgd29yZHMgKHN5bWJvbHMpIHRvIGJlIGVuY29kZWQgZm9sbG93ZWQgYnkgZW1wdHkgZWxlbWVudHMgYWxsb2NhdGVkIHRvIG1ha2VcbiAgICAgICAgICogc3BhY2UgZm9yIGVycm9yLWNvcnJlY3Rpb24gY29kZSB3b3JkcyBpbiB0aGUgZW5jb2RlZCBvdXRwdXQuIFRoZSBhcnJheSBjb250YWluc1xuICAgICAgICAgKiB0aGUgZW5jZG9kZWQgb3V0cHV0IHdoZW4gZW5jb2RlIHJldHVybnMuIENvZGUgd29yZHMgYXJlIGVuY29kZWQgYXMgbnVtYmVycyBmcm9tXG4gICAgICAgICAqIDAgdG8gbi0xLCB3aGVyZSBuIGlzIHRoZSBudW1iZXIgb2YgcG9zc2libGUgY29kZSB3b3JkcyAoc3ltYm9scyksIGFzIGRldGVybWluZWRcbiAgICAgICAgICogYnkgdGhlIHNpemUgb2YgdGhlIEdhbG9pcyBGaWVsZCBwYXNzZWQgaW4gdGhlIGNvbnN0cnVjdG9yIG9mIHRoaXMgb2JqZWN0LlxuICAgICAgICAgKiBAcGFyYW0gZWNCeXRlcyB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIHJlc2VydmVkIGluIHRoZSBhcnJheSAoZmlyc3QgcGFyYW1ldGVyKVxuICAgICAgICAgKiB0byBzdG9yZSBlcnJvci1jb3JyZWN0aW9uIGNvZGUgd29yZHMuIFRodXMsIHRoZSBudW1iZXIgb2YgY29kZSB3b3JkcyAoc3ltYm9scylcbiAgICAgICAgICogdG8gZW5jb2RlIGluIHRoZSBmaXJzdCBwYXJhbWV0ZXIgaXMgdGh1cyB0b0VuY29kZS5sZW5ndGggLSBlY0J5dGVzLlxuICAgICAgICAgKiBOb3RlLCB0aGUgdXNlIG9mIFwiYnl0ZXNcIiBpbiB0aGUgbmFtZSBvZiB0aGlzIHBhcmFtZXRlciBpcyBtaXNsZWFkaW5nLCBhcyB0aGVyZSBtYXlcbiAgICAgICAgICogYmUgbW9yZSBvciBmZXdlciB0aGFuIDI1NiBzeW1ib2xzIGJlaW5nIGVuY29kZWQsIGFzIGRldGVybWluZWQgYnkgdGhlIG51bWJlciBvZlxuICAgICAgICAgKiBlbGVtZW50cyBpbiB0aGUgR2Fsb2lzIEZpZWxkIHBhc3NlZCBhcyBhIGNvbnN0cnVjdG9yIHRvIHRoaXMgb2JqZWN0LlxuICAgICAgICAgKiBAdGhyb3dzIElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbiB0aHJvd24gaW4gcmVzcG9uc2UgdG8gdmFsaWRhdGlvbiBlcnJyb3MuXG4gICAgICAgICAqL1xuICAgICAgICBlbmNvZGUodG9FbmNvZGUsIGVjQnl0ZXMgLyppbnQqLykge1xuICAgICAgICAgICAgaWYgKGVjQnl0ZXMgPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdObyBlcnJvciBjb3JyZWN0aW9uIGJ5dGVzJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBkYXRhQnl0ZXMgPSB0b0VuY29kZS5sZW5ndGggLSBlY0J5dGVzO1xuICAgICAgICAgICAgaWYgKGRhdGFCeXRlcyA8PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignTm8gZGF0YSBieXRlcyBwcm92aWRlZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZ2VuZXJhdG9yID0gdGhpcy5idWlsZEdlbmVyYXRvcihlY0J5dGVzKTtcbiAgICAgICAgICAgIGNvbnN0IGluZm9Db2VmZmljaWVudHMgPSBuZXcgSW50MzJBcnJheShkYXRhQnl0ZXMpO1xuICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weSh0b0VuY29kZSwgMCwgaW5mb0NvZWZmaWNpZW50cywgMCwgZGF0YUJ5dGVzKTtcbiAgICAgICAgICAgIGxldCBpbmZvID0gbmV3IEdlbmVyaWNHRlBvbHkodGhpcy5maWVsZCwgaW5mb0NvZWZmaWNpZW50cyk7XG4gICAgICAgICAgICBpbmZvID0gaW5mby5tdWx0aXBseUJ5TW9ub21pYWwoZWNCeXRlcywgMSk7XG4gICAgICAgICAgICBjb25zdCByZW1haW5kZXIgPSBpbmZvLmRpdmlkZShnZW5lcmF0b3IpWzFdO1xuICAgICAgICAgICAgY29uc3QgY29lZmZpY2llbnRzID0gcmVtYWluZGVyLmdldENvZWZmaWNpZW50cygpO1xuICAgICAgICAgICAgY29uc3QgbnVtWmVyb0NvZWZmaWNpZW50cyA9IGVjQnl0ZXMgLSBjb2VmZmljaWVudHMubGVuZ3RoO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1aZXJvQ29lZmZpY2llbnRzOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0b0VuY29kZVtkYXRhQnl0ZXMgKyBpXSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KGNvZWZmaWNpZW50cywgMCwgdG9FbmNvZGUsIGRhdGFCeXRlcyArIG51bVplcm9Db2VmZmljaWVudHMsIGNvZWZmaWNpZW50cy5sZW5ndGgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGF1dGhvciBTYXRvcnUgVGFrYWJheWFzaGlcbiAgICAgKiBAYXV0aG9yIERhbmllbCBTd2l0a2luXG4gICAgICogQGF1dGhvciBTZWFuIE93ZW5cbiAgICAgKi9cbiAgICBjbGFzcyBNYXNrVXRpbCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgLy8gZG8gbm90aGluZ1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBcHBseSBtYXNrIHBlbmFsdHkgcnVsZSAxIGFuZCByZXR1cm4gdGhlIHBlbmFsdHkuIEZpbmQgcmVwZXRpdGl2ZSBjZWxscyB3aXRoIHRoZSBzYW1lIGNvbG9yIGFuZFxuICAgICAgICAgKiBnaXZlIHBlbmFsdHkgdG8gdGhlbS4gRXhhbXBsZTogMDAwMDAgb3IgMTExMTEuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgYXBwbHlNYXNrUGVuYWx0eVJ1bGUxKG1hdHJpeCkge1xuICAgICAgICAgICAgcmV0dXJuIE1hc2tVdGlsLmFwcGx5TWFza1BlbmFsdHlSdWxlMUludGVybmFsKG1hdHJpeCwgdHJ1ZSkgKyBNYXNrVXRpbC5hcHBseU1hc2tQZW5hbHR5UnVsZTFJbnRlcm5hbChtYXRyaXgsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQXBwbHkgbWFzayBwZW5hbHR5IHJ1bGUgMiBhbmQgcmV0dXJuIHRoZSBwZW5hbHR5LiBGaW5kIDJ4MiBibG9ja3Mgd2l0aCB0aGUgc2FtZSBjb2xvciBhbmQgZ2l2ZVxuICAgICAgICAgKiBwZW5hbHR5IHRvIHRoZW0uIFRoaXMgaXMgYWN0dWFsbHkgZXF1aXZhbGVudCB0byB0aGUgc3BlYydzIHJ1bGUsIHdoaWNoIGlzIHRvIGZpbmQgTXhOIGJsb2NrcyBhbmQgZ2l2ZSBhXG4gICAgICAgICAqIHBlbmFsdHkgcHJvcG9ydGlvbmFsIHRvIChNLTEpeChOLTEpLCBiZWNhdXNlIHRoaXMgaXMgdGhlIG51bWJlciBvZiAyeDIgYmxvY2tzIGluc2lkZSBzdWNoIGEgYmxvY2suXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgYXBwbHlNYXNrUGVuYWx0eVJ1bGUyKG1hdHJpeCkge1xuICAgICAgICAgICAgbGV0IHBlbmFsdHkgPSAwO1xuICAgICAgICAgICAgY29uc3QgYXJyYXkgPSBtYXRyaXguZ2V0QXJyYXkoKTtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gbWF0cml4LmdldFdpZHRoKCk7XG4gICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBtYXRyaXguZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IGhlaWdodCAtIDE7IHkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFycmF5WSA9IGFycmF5W3ldO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgd2lkdGggLSAxOyB4KyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBhcnJheVlbeF07XG4gICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gYXJyYXlZW3ggKyAxXSAmJiB2YWx1ZSA9PT0gYXJyYXlbeSArIDFdW3hdICYmIHZhbHVlID09PSBhcnJheVt5ICsgMV1beCArIDFdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwZW5hbHR5Kys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gTWFza1V0aWwuTjIgKiBwZW5hbHR5O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBcHBseSBtYXNrIHBlbmFsdHkgcnVsZSAzIGFuZCByZXR1cm4gdGhlIHBlbmFsdHkuIEZpbmQgY29uc2VjdXRpdmUgcnVucyBvZiAxOjE6MzoxOjE6NFxuICAgICAgICAgKiBzdGFydGluZyB3aXRoIGJsYWNrLCBvciA0OjE6MTozOjE6MSBzdGFydGluZyB3aXRoIHdoaXRlLCBhbmQgZ2l2ZSBwZW5hbHR5IHRvIHRoZW0uICBJZiB3ZVxuICAgICAgICAgKiBmaW5kIHBhdHRlcm5zIGxpa2UgMDAwMDEwMTExMDEwMDAwLCB3ZSBnaXZlIHBlbmFsdHkgb25jZS5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBhcHBseU1hc2tQZW5hbHR5UnVsZTMobWF0cml4KSB7XG4gICAgICAgICAgICBsZXQgbnVtUGVuYWx0aWVzID0gMDtcbiAgICAgICAgICAgIGNvbnN0IGFycmF5ID0gbWF0cml4LmdldEFycmF5KCk7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IG1hdHJpeC5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gbWF0cml4LmdldEhlaWdodCgpO1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgd2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBhcnJheVkgPSBhcnJheVt5XTsgLy8gV2UgY2FuIGF0IGxlYXN0IG9wdGltaXplIHRoaXMgYWNjZXNzXG4gICAgICAgICAgICAgICAgICAgIGlmICh4ICsgNiA8IHdpZHRoICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBhcnJheVlbeF0gPT09IDEgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5WVt4ICsgMV0gPT09IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5WVt4ICsgMl0gPT09IDEgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5WVt4ICsgM10gPT09IDEgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5WVt4ICsgNF0gPT09IDEgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5WVt4ICsgNV0gPT09IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5WVt4ICsgNl0gPT09IDEgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIChNYXNrVXRpbC5pc1doaXRlSG9yaXpvbnRhbChhcnJheVksIHggLSA0LCB4KSB8fCBNYXNrVXRpbC5pc1doaXRlSG9yaXpvbnRhbChhcnJheVksIHggKyA3LCB4ICsgMTEpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbnVtUGVuYWx0aWVzKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHkgKyA2IDwgaGVpZ2h0ICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBhcnJheVt5XVt4XSA9PT0gMSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXlbeSArIDFdW3hdID09PSAwICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBhcnJheVt5ICsgMl1beF0gPT09IDEgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5W3kgKyAzXVt4XSA9PT0gMSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXlbeSArIDRdW3hdID09PSAxICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBhcnJheVt5ICsgNV1beF0gPT09IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5W3kgKyA2XVt4XSA9PT0gMSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKE1hc2tVdGlsLmlzV2hpdGVWZXJ0aWNhbChhcnJheSwgeCwgeSAtIDQsIHkpIHx8IE1hc2tVdGlsLmlzV2hpdGVWZXJ0aWNhbChhcnJheSwgeCwgeSArIDcsIHkgKyAxMSkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBudW1QZW5hbHRpZXMrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBudW1QZW5hbHRpZXMgKiBNYXNrVXRpbC5OMztcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgaXNXaGl0ZUhvcml6b250YWwocm93QXJyYXksIGZyb20gLyppbnQqLywgdG8gLyppbnQqLykge1xuICAgICAgICAgICAgZnJvbSA9IE1hdGgubWF4KGZyb20sIDApO1xuICAgICAgICAgICAgdG8gPSBNYXRoLm1pbih0bywgcm93QXJyYXkubGVuZ3RoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBmcm9tOyBpIDwgdG87IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChyb3dBcnJheVtpXSA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGlzV2hpdGVWZXJ0aWNhbChhcnJheSwgY29sIC8qaW50Ki8sIGZyb20gLyppbnQqLywgdG8gLyppbnQqLykge1xuICAgICAgICAgICAgZnJvbSA9IE1hdGgubWF4KGZyb20sIDApO1xuICAgICAgICAgICAgdG8gPSBNYXRoLm1pbih0bywgYXJyYXkubGVuZ3RoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBmcm9tOyBpIDwgdG87IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChhcnJheVtpXVtjb2xdID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQXBwbHkgbWFzayBwZW5hbHR5IHJ1bGUgNCBhbmQgcmV0dXJuIHRoZSBwZW5hbHR5LiBDYWxjdWxhdGUgdGhlIHJhdGlvIG9mIGRhcmsgY2VsbHMgYW5kIGdpdmVcbiAgICAgICAgICogcGVuYWx0eSBpZiB0aGUgcmF0aW8gaXMgZmFyIGZyb20gNTAlLiBJdCBnaXZlcyAxMCBwZW5hbHR5IGZvciA1JSBkaXN0YW5jZS5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBhcHBseU1hc2tQZW5hbHR5UnVsZTQobWF0cml4KSB7XG4gICAgICAgICAgICBsZXQgbnVtRGFya0NlbGxzID0gMDtcbiAgICAgICAgICAgIGNvbnN0IGFycmF5ID0gbWF0cml4LmdldEFycmF5KCk7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IG1hdHJpeC5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gbWF0cml4LmdldEhlaWdodCgpO1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFycmF5WSA9IGFycmF5W3ldO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgd2lkdGg7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoYXJyYXlZW3hdID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBudW1EYXJrQ2VsbHMrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG51bVRvdGFsQ2VsbHMgPSBtYXRyaXguZ2V0SGVpZ2h0KCkgKiBtYXRyaXguZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGNvbnN0IGZpdmVQZXJjZW50VmFyaWFuY2VzID0gTWF0aC5mbG9vcihNYXRoLmFicyhudW1EYXJrQ2VsbHMgKiAyIC0gbnVtVG90YWxDZWxscykgKiAxMCAvIG51bVRvdGFsQ2VsbHMpO1xuICAgICAgICAgICAgcmV0dXJuIGZpdmVQZXJjZW50VmFyaWFuY2VzICogTWFza1V0aWwuTjQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldHVybiB0aGUgbWFzayBiaXQgZm9yIFwiZ2V0TWFza1BhdHRlcm5cIiBhdCBcInhcIiBhbmQgXCJ5XCIuIFNlZSA4Ljggb2YgSklTWDA1MTA6MjAwNCBmb3IgbWFza1xuICAgICAgICAgKiBwYXR0ZXJuIGNvbmRpdGlvbnMuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZ2V0RGF0YU1hc2tCaXQobWFza1BhdHRlcm4gLyppbnQqLywgeCAvKmludCovLCB5IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGxldCBpbnRlcm1lZGlhdGU7IC8qaW50Ki9cbiAgICAgICAgICAgIGxldCB0ZW1wOyAvKmludCovXG4gICAgICAgICAgICBzd2l0Y2ggKG1hc2tQYXR0ZXJuKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICBpbnRlcm1lZGlhdGUgPSAoeSArIHgpICYgMHgxO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGludGVybWVkaWF0ZSA9IHkgJiAweDE7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJtZWRpYXRlID0geCAlIDM7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJtZWRpYXRlID0gKHkgKyB4KSAlIDM7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJtZWRpYXRlID0gKE1hdGguZmxvb3IoeSAvIDIpICsgTWF0aC5mbG9vcih4IC8gMykpICYgMHgxO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIHRlbXAgPSB5ICogeDtcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJtZWRpYXRlID0gKHRlbXAgJiAweDEpICsgKHRlbXAgJSAzKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICB0ZW1wID0geSAqIHg7XG4gICAgICAgICAgICAgICAgICAgIGludGVybWVkaWF0ZSA9ICgodGVtcCAmIDB4MSkgKyAodGVtcCAlIDMpKSAmIDB4MTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA3OlxuICAgICAgICAgICAgICAgICAgICB0ZW1wID0geSAqIHg7XG4gICAgICAgICAgICAgICAgICAgIGludGVybWVkaWF0ZSA9ICgodGVtcCAlIDMpICsgKCh5ICsgeCkgJiAweDEpKSAmIDB4MTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignSW52YWxpZCBtYXNrIHBhdHRlcm46ICcgKyBtYXNrUGF0dGVybik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaW50ZXJtZWRpYXRlID09PSAwO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBIZWxwZXIgZnVuY3Rpb24gZm9yIGFwcGx5TWFza1BlbmFsdHlSdWxlMS4gV2UgbmVlZCB0aGlzIGZvciBkb2luZyB0aGlzIGNhbGN1bGF0aW9uIGluIGJvdGhcbiAgICAgICAgICogdmVydGljYWwgYW5kIGhvcml6b250YWwgb3JkZXJzIHJlc3BlY3RpdmVseS5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBhcHBseU1hc2tQZW5hbHR5UnVsZTFJbnRlcm5hbChtYXRyaXgsIGlzSG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgbGV0IHBlbmFsdHkgPSAwO1xuICAgICAgICAgICAgY29uc3QgaUxpbWl0ID0gaXNIb3Jpem9udGFsID8gbWF0cml4LmdldEhlaWdodCgpIDogbWF0cml4LmdldFdpZHRoKCk7XG4gICAgICAgICAgICBjb25zdCBqTGltaXQgPSBpc0hvcml6b250YWwgPyBtYXRyaXguZ2V0V2lkdGgoKSA6IG1hdHJpeC5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IGFycmF5ID0gbWF0cml4LmdldEFycmF5KCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlMaW1pdDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IG51bVNhbWVCaXRDZWxscyA9IDA7XG4gICAgICAgICAgICAgICAgbGV0IHByZXZCaXQgPSAtMTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGpMaW1pdDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGJpdCA9IGlzSG9yaXpvbnRhbCA/IGFycmF5W2ldW2pdIDogYXJyYXlbal1baV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChiaXQgPT09IHByZXZCaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG51bVNhbWVCaXRDZWxscysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG51bVNhbWVCaXRDZWxscyA+PSA1KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVuYWx0eSArPSBNYXNrVXRpbC5OMSArIChudW1TYW1lQml0Q2VsbHMgLSA1KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIG51bVNhbWVCaXRDZWxscyA9IDE7IC8vIEluY2x1ZGUgdGhlIGNlbGwgaXRzZWxmLlxuICAgICAgICAgICAgICAgICAgICAgICAgcHJldkJpdCA9IGJpdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobnVtU2FtZUJpdENlbGxzID49IDUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGVuYWx0eSArPSBNYXNrVXRpbC5OMSArIChudW1TYW1lQml0Q2VsbHMgLSA1KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcGVuYWx0eTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBQZW5hbHR5IHdlaWdodHMgZnJvbSBzZWN0aW9uIDYuOC4yLjFcbiAgICBNYXNrVXRpbC5OMSA9IDM7XG4gICAgTWFza1V0aWwuTjIgPSAzO1xuICAgIE1hc2tVdGlsLk4zID0gNDA7XG4gICAgTWFza1V0aWwuTjQgPSAxMDtcblxuICAgIC8qKlxuICAgICAqIEpBVkFQT1JUOiBUaGUgb3JpZ2luYWwgY29kZSB3YXMgYSAyRCBhcnJheSBvZiBpbnRzLCBidXQgc2luY2UgaXQgb25seSBldmVyIGdldHMgYXNzaWduZWRcbiAgICAgKiAtMSwgMCwgYW5kIDEsIEknbSBnb2luZyB0byB1c2UgbGVzcyBtZW1vcnkgYW5kIGdvIHdpdGggYnl0ZXMuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIGRzd2l0a2luQGdvb2dsZS5jb20gKERhbmllbCBTd2l0a2luKVxuICAgICAqL1xuICAgIGNsYXNzIEJ5dGVNYXRyaXgge1xuICAgICAgICBjb25zdHJ1Y3Rvcih3aWR0aCAvKmludCovLCBoZWlnaHQgLyppbnQqLykge1xuICAgICAgICAgICAgdGhpcy53aWR0aCA9IHdpZHRoO1xuICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgICAgICBjb25zdCBieXRlcyA9IG5ldyBBcnJheShoZWlnaHQpOyAvLyBbaGVpZ2h0XVt3aWR0aF1cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpICE9PSBoZWlnaHQ7IGkrKykge1xuICAgICAgICAgICAgICAgIGJ5dGVzW2ldID0gbmV3IFVpbnQ4QXJyYXkod2lkdGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5ieXRlcyA9IGJ5dGVzO1xuICAgICAgICB9XG4gICAgICAgIGdldEhlaWdodCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmhlaWdodDtcbiAgICAgICAgfVxuICAgICAgICBnZXRXaWR0aCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndpZHRoO1xuICAgICAgICB9XG4gICAgICAgIGdldCh4IC8qaW50Ki8sIHkgLyppbnQqLykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYnl0ZXNbeV1beF07XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gYW4gaW50ZXJuYWwgcmVwcmVzZW50YXRpb24gYXMgYnl0ZXMsIGluIHJvdy1tYWpvciBvcmRlci4gYXJyYXlbeV1beF0gcmVwcmVzZW50cyBwb2ludCAoeCx5KVxuICAgICAgICAgKi9cbiAgICAgICAgZ2V0QXJyYXkoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ieXRlcztcbiAgICAgICAgfVxuICAgICAgICAvLyBUWVBFU0NSSVBUUE9SVDogcHJlZmZlciB0byBsZXQgdHdvIG1ldGhvZHMgaW5zdGVhZCBvZiBvdmVycmlkZSB0byBhdm9pZCB0eXBlIGNvbXBhcmlzb24gaW5zaWRlXG4gICAgICAgIHNldE51bWJlcih4IC8qaW50Ki8sIHkgLyppbnQqLywgdmFsdWUgLypieXRlfGludCovKSB7XG4gICAgICAgICAgICB0aGlzLmJ5dGVzW3ldW3hdID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gcHVibGljIHNldCh4OiBudW1iZXIgLyppbnQqLywgeTogbnVtYmVyIC8qaW50Ki8sIHZhbHVlOiBudW1iZXIgLyppbnQqLyk6IHZvaWQge1xuICAgICAgICAvLyAgIGJ5dGVzW3ldW3hdID0gKGJ5dGUpIHZhbHVlXG4gICAgICAgIC8vIH1cbiAgICAgICAgc2V0Qm9vbGVhbih4IC8qaW50Ki8sIHkgLyppbnQqLywgdmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMuYnl0ZXNbeV1beF0gPSAvKihieXRlKSAqLyAodmFsdWUgPyAxIDogMCk7XG4gICAgICAgIH1cbiAgICAgICAgY2xlYXIodmFsdWUgLypieXRlKi8pIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgYUJ5dGUgb2YgdGhpcy5ieXRlcykge1xuICAgICAgICAgICAgICAgIEFycmF5cy5maWxsKGFCeXRlLCB2YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZXF1YWxzKG8pIHtcbiAgICAgICAgICAgIGlmICghKG8gaW5zdGFuY2VvZiBCeXRlTWF0cml4KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG90aGVyID0gbztcbiAgICAgICAgICAgIGlmICh0aGlzLndpZHRoICE9PSBvdGhlci53aWR0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmhlaWdodCAhPT0gb3RoZXIuaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDAsIGhlaWdodCA9IHRoaXMuaGVpZ2h0OyB5IDwgaGVpZ2h0OyArK3kpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBieXRlc1kgPSB0aGlzLmJ5dGVzW3ldO1xuICAgICAgICAgICAgICAgIGNvbnN0IG90aGVyQnl0ZXNZID0gb3RoZXIuYnl0ZXNbeV07XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeCA9IDAsIHdpZHRoID0gdGhpcy53aWR0aDsgeCA8IHdpZHRoOyArK3gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGJ5dGVzWVt4XSAhPT0gb3RoZXJCeXRlc1lbeF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgU3RyaW5nQnVpbGRlcigpOyAvLyAoMiAqIHdpZHRoICogaGVpZ2h0ICsgMilcbiAgICAgICAgICAgIGZvciAobGV0IHkgPSAwLCBoZWlnaHQgPSB0aGlzLmhlaWdodDsgeSA8IGhlaWdodDsgKyt5KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYnl0ZXNZID0gdGhpcy5ieXRlc1t5XTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB4ID0gMCwgd2lkdGggPSB0aGlzLndpZHRoOyB4IDwgd2lkdGg7ICsreCkge1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGJ5dGVzWVt4XSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoJyAwJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnIDEnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnICAnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXN1bHQuYXBwZW5kKCdcXG4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBhdXRob3Igc2F0b3J1eEBnb29nbGUuY29tIChTYXRvcnUgVGFrYWJheWFzaGkpIC0gY3JlYXRvclxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pIC0gcG9ydGVkIGZyb20gQysrXG4gICAgICovXG4gICAgY2xhc3MgUVJDb2RlIHtcbiAgICAgICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgICAgICB0aGlzLm1hc2tQYXR0ZXJuID0gLTE7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0TW9kZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1vZGU7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RUNMZXZlbCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVjTGV2ZWw7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0VmVyc2lvbigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZlcnNpb247XG4gICAgICAgIH1cbiAgICAgICAgZ2V0TWFza1BhdHRlcm4oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXNrUGF0dGVybjtcbiAgICAgICAgfVxuICAgICAgICBnZXRNYXRyaXgoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXRyaXg7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICB0b1N0cmluZygpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7IC8vICgyMDApXG4gICAgICAgICAgICByZXN1bHQuYXBwZW5kKCc8PFxcbicpO1xuICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnIG1vZGU6ICcpO1xuICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCh0aGlzLm1vZGUgPyB0aGlzLm1vZGUudG9TdHJpbmcoKSA6ICdudWxsJyk7XG4gICAgICAgICAgICByZXN1bHQuYXBwZW5kKCdcXG4gZWNMZXZlbDogJyk7XG4gICAgICAgICAgICByZXN1bHQuYXBwZW5kKHRoaXMuZWNMZXZlbCA/IHRoaXMuZWNMZXZlbC50b1N0cmluZygpIDogJ251bGwnKTtcbiAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoJ1xcbiB2ZXJzaW9uOiAnKTtcbiAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQodGhpcy52ZXJzaW9uID8gdGhpcy52ZXJzaW9uLnRvU3RyaW5nKCkgOiAnbnVsbCcpO1xuICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCgnXFxuIG1hc2tQYXR0ZXJuOiAnKTtcbiAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQodGhpcy5tYXNrUGF0dGVybi50b1N0cmluZygpKTtcbiAgICAgICAgICAgIGlmICh0aGlzLm1hdHJpeCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoJ1xcbiBtYXRyaXg6XFxuJyk7XG4gICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZCh0aGlzLm1hdHJpeC50b1N0cmluZygpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoJ1xcbiBtYXRyaXg6IG51bGxcXG4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoJz4+XFxuJyk7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0LnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICAgICAgc2V0TW9kZSh2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5tb2RlID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgc2V0RUNMZXZlbCh2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5lY0xldmVsID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgc2V0VmVyc2lvbih2ZXJzaW9uKSB7XG4gICAgICAgICAgICB0aGlzLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICB9XG4gICAgICAgIHNldE1hc2tQYXR0ZXJuKHZhbHVlIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHRoaXMubWFza1BhdHRlcm4gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBzZXRNYXRyaXgodmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMubWF0cml4ID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ2hlY2sgaWYgXCJtYXNrX3BhdHRlcm5cIiBpcyB2YWxpZC5cbiAgICAgICAgc3RhdGljIGlzVmFsaWRNYXNrUGF0dGVybihtYXNrUGF0dGVybiAvKmludCovKSB7XG4gICAgICAgICAgICByZXR1cm4gbWFza1BhdHRlcm4gPj0gMCAmJiBtYXNrUGF0dGVybiA8IFFSQ29kZS5OVU1fTUFTS19QQVRURVJOUztcbiAgICAgICAgfVxuICAgIH1cbiAgICBRUkNvZGUuTlVNX01BU0tfUEFUVEVSTlMgPSA4O1xuXG4gICAgLyoqXG4gICAgICogQ3VzdG9tIEVycm9yIGNsYXNzIG9mIHR5cGUgRXhjZXB0aW9uLlxuICAgICAqL1xuICAgIGNsYXNzIFdyaXRlckV4Y2VwdGlvbiBleHRlbmRzIEV4Y2VwdGlvbiB7XG4gICAgfVxuICAgIFdyaXRlckV4Y2VwdGlvbi5raW5kID0gJ1dyaXRlckV4Y2VwdGlvbic7XG5cbiAgICAvKipcbiAgICAgKiBAYXV0aG9yIHNhdG9ydXhAZ29vZ2xlLmNvbSAoU2F0b3J1IFRha2FiYXlhc2hpKSAtIGNyZWF0b3JcbiAgICAgKiBAYXV0aG9yIGRzd2l0a2luQGdvb2dsZS5jb20gKERhbmllbCBTd2l0a2luKSAtIHBvcnRlZCBmcm9tIEMrK1xuICAgICAqL1xuICAgIGNsYXNzIE1hdHJpeFV0aWwge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICAgICAgfVxuICAgICAgICAvLyBTZXQgYWxsIGNlbGxzIHRvIC0xIChUWVBFU0NSSVBUUE9SVDogMjU1KS4gIC0xIChUWVBFU0NSSVBUUE9SVDogMjU1KSBtZWFucyB0aGF0IHRoZSBjZWxsIGlzIGVtcHR5IChub3Qgc2V0IHlldCkuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIEpBVkFQT1JUOiBXZSBzaG91bGRuJ3QgbmVlZCB0byBkbyB0aGlzIGF0IGFsbC4gVGhlIGNvZGUgc2hvdWxkIGJlIHJld3JpdHRlbiB0byBiZWdpbiBlbmNvZGluZ1xuICAgICAgICAvLyB3aXRoIHRoZSBCeXRlTWF0cml4IGluaXRpYWxpemVkIGFsbCB0byB6ZXJvLlxuICAgICAgICBzdGF0aWMgY2xlYXJNYXRyaXgobWF0cml4KSB7XG4gICAgICAgICAgICAvLyBUWVBFU0NSSVBUUE9SVDogd2UgdXNlIFVpbnRBcnJheSBzZSBjaGFuZ2VkIGhlcmUgZnJvbSAtMSB0byAyNTVcbiAgICAgICAgICAgIG1hdHJpeC5jbGVhcigvKihieXRlKSAqLyAvKi0xKi8gMjU1KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBCdWlsZCAyRCBtYXRyaXggb2YgUVIgQ29kZSBmcm9tIFwiZGF0YUJpdHNcIiB3aXRoIFwiZWNMZXZlbFwiLCBcInZlcnNpb25cIiBhbmQgXCJnZXRNYXNrUGF0dGVyblwiLiBPblxuICAgICAgICAvLyBzdWNjZXNzLCBzdG9yZSB0aGUgcmVzdWx0IGluIFwibWF0cml4XCIgYW5kIHJldHVybiB0cnVlLlxuICAgICAgICBzdGF0aWMgYnVpbGRNYXRyaXgoZGF0YUJpdHMsIGVjTGV2ZWwsIHZlcnNpb24sIG1hc2tQYXR0ZXJuIC8qaW50Ki8sIG1hdHJpeCkge1xuICAgICAgICAgICAgTWF0cml4VXRpbC5jbGVhck1hdHJpeChtYXRyaXgpO1xuICAgICAgICAgICAgTWF0cml4VXRpbC5lbWJlZEJhc2ljUGF0dGVybnModmVyc2lvbiwgbWF0cml4KTtcbiAgICAgICAgICAgIC8vIFR5cGUgaW5mb3JtYXRpb24gYXBwZWFyIHdpdGggYW55IHZlcnNpb24uXG4gICAgICAgICAgICBNYXRyaXhVdGlsLmVtYmVkVHlwZUluZm8oZWNMZXZlbCwgbWFza1BhdHRlcm4sIG1hdHJpeCk7XG4gICAgICAgICAgICAvLyBWZXJzaW9uIGluZm8gYXBwZWFyIGlmIHZlcnNpb24gPj0gNy5cbiAgICAgICAgICAgIE1hdHJpeFV0aWwubWF5YmVFbWJlZFZlcnNpb25JbmZvKHZlcnNpb24sIG1hdHJpeCk7XG4gICAgICAgICAgICAvLyBEYXRhIHNob3VsZCBiZSBlbWJlZGRlZCBhdCBlbmQuXG4gICAgICAgICAgICBNYXRyaXhVdGlsLmVtYmVkRGF0YUJpdHMoZGF0YUJpdHMsIG1hc2tQYXR0ZXJuLCBtYXRyaXgpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEVtYmVkIGJhc2ljIHBhdHRlcm5zLiBPbiBzdWNjZXNzLCBtb2RpZnkgdGhlIG1hdHJpeCBhbmQgcmV0dXJuIHRydWUuXG4gICAgICAgIC8vIFRoZSBiYXNpYyBwYXR0ZXJucyBhcmU6XG4gICAgICAgIC8vIC0gUG9zaXRpb24gZGV0ZWN0aW9uIHBhdHRlcm5zXG4gICAgICAgIC8vIC0gVGltaW5nIHBhdHRlcm5zXG4gICAgICAgIC8vIC0gRGFyayBkb3QgYXQgdGhlIGxlZnQgYm90dG9tIGNvcm5lclxuICAgICAgICAvLyAtIFBvc2l0aW9uIGFkanVzdG1lbnQgcGF0dGVybnMsIGlmIG5lZWQgYmVcbiAgICAgICAgc3RhdGljIGVtYmVkQmFzaWNQYXR0ZXJucyh2ZXJzaW9uLCBtYXRyaXgpIHtcbiAgICAgICAgICAgIC8vIExldCdzIGdldCBzdGFydGVkIHdpdGggZW1iZWRkaW5nIGJpZyBzcXVhcmVzIGF0IGNvcm5lcnMuXG4gICAgICAgICAgICBNYXRyaXhVdGlsLmVtYmVkUG9zaXRpb25EZXRlY3Rpb25QYXR0ZXJuc0FuZFNlcGFyYXRvcnMobWF0cml4KTtcbiAgICAgICAgICAgIC8vIFRoZW4sIGVtYmVkIHRoZSBkYXJrIGRvdCBhdCB0aGUgbGVmdCBib3R0b20gY29ybmVyLlxuICAgICAgICAgICAgTWF0cml4VXRpbC5lbWJlZERhcmtEb3RBdExlZnRCb3R0b21Db3JuZXIobWF0cml4KTtcbiAgICAgICAgICAgIC8vIFBvc2l0aW9uIGFkanVzdG1lbnQgcGF0dGVybnMgYXBwZWFyIGlmIHZlcnNpb24gPj0gMi5cbiAgICAgICAgICAgIE1hdHJpeFV0aWwubWF5YmVFbWJlZFBvc2l0aW9uQWRqdXN0bWVudFBhdHRlcm5zKHZlcnNpb24sIG1hdHJpeCk7XG4gICAgICAgICAgICAvLyBUaW1pbmcgcGF0dGVybnMgc2hvdWxkIGJlIGVtYmVkZGVkIGFmdGVyIHBvc2l0aW9uIGFkai4gcGF0dGVybnMuXG4gICAgICAgICAgICBNYXRyaXhVdGlsLmVtYmVkVGltaW5nUGF0dGVybnMobWF0cml4KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBFbWJlZCB0eXBlIGluZm9ybWF0aW9uLiBPbiBzdWNjZXNzLCBtb2RpZnkgdGhlIG1hdHJpeC5cbiAgICAgICAgc3RhdGljIGVtYmVkVHlwZUluZm8oZWNMZXZlbCwgbWFza1BhdHRlcm4gLyppbnQqLywgbWF0cml4KSB7XG4gICAgICAgICAgICBjb25zdCB0eXBlSW5mb0JpdHMgPSBuZXcgQml0QXJyYXkoKTtcbiAgICAgICAgICAgIE1hdHJpeFV0aWwubWFrZVR5cGVJbmZvQml0cyhlY0xldmVsLCBtYXNrUGF0dGVybiwgdHlwZUluZm9CaXRzKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBzaXplID0gdHlwZUluZm9CaXRzLmdldFNpemUoKTsgaSA8IHNpemU7ICsraSkge1xuICAgICAgICAgICAgICAgIC8vIFBsYWNlIGJpdHMgaW4gTFNCIHRvIE1TQiBvcmRlci4gIExTQiAobGVhc3Qgc2lnbmlmaWNhbnQgYml0KSBpcyB0aGUgbGFzdCB2YWx1ZSBpblxuICAgICAgICAgICAgICAgIC8vIFwidHlwZUluZm9CaXRzXCIuXG4gICAgICAgICAgICAgICAgY29uc3QgYml0ID0gdHlwZUluZm9CaXRzLmdldCh0eXBlSW5mb0JpdHMuZ2V0U2l6ZSgpIC0gMSAtIGkpO1xuICAgICAgICAgICAgICAgIC8vIFR5cGUgaW5mbyBiaXRzIGF0IHRoZSBsZWZ0IHRvcCBjb3JuZXIuIFNlZSA4Ljkgb2YgSklTWDA1MTA6MjAwNCAocC40NikuXG4gICAgICAgICAgICAgICAgY29uc3QgY29vcmRpbmF0ZXMgPSBNYXRyaXhVdGlsLlRZUEVfSU5GT19DT09SRElOQVRFU1tpXTtcbiAgICAgICAgICAgICAgICBjb25zdCB4MSA9IGNvb3JkaW5hdGVzWzBdO1xuICAgICAgICAgICAgICAgIGNvbnN0IHkxID0gY29vcmRpbmF0ZXNbMV07XG4gICAgICAgICAgICAgICAgbWF0cml4LnNldEJvb2xlYW4oeDEsIHkxLCBiaXQpO1xuICAgICAgICAgICAgICAgIGlmIChpIDwgOCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBSaWdodCB0b3AgY29ybmVyLlxuICAgICAgICAgICAgICAgICAgICBjb25zdCB4MiA9IG1hdHJpeC5nZXRXaWR0aCgpIC0gaSAtIDE7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHkyID0gODtcbiAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldEJvb2xlYW4oeDIsIHkyLCBiaXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gTGVmdCBib3R0b20gY29ybmVyLlxuICAgICAgICAgICAgICAgICAgICBjb25zdCB4MiA9IDg7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHkyID0gbWF0cml4LmdldEhlaWdodCgpIC0gNyArIChpIC0gOCk7XG4gICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXRCb29sZWFuKHgyLCB5MiwgYml0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gRW1iZWQgdmVyc2lvbiBpbmZvcm1hdGlvbiBpZiBuZWVkIGJlLiBPbiBzdWNjZXNzLCBtb2RpZnkgdGhlIG1hdHJpeCBhbmQgcmV0dXJuIHRydWUuXG4gICAgICAgIC8vIFNlZSA4LjEwIG9mIEpJU1gwNTEwOjIwMDQgKHAuNDcpIGZvciBob3cgdG8gZW1iZWQgdmVyc2lvbiBpbmZvcm1hdGlvbi5cbiAgICAgICAgc3RhdGljIG1heWJlRW1iZWRWZXJzaW9uSW5mbyh2ZXJzaW9uLCBtYXRyaXgpIHtcbiAgICAgICAgICAgIGlmICh2ZXJzaW9uLmdldFZlcnNpb25OdW1iZXIoKSA8IDcpIHsgLy8gVmVyc2lvbiBpbmZvIGlzIG5lY2Vzc2FyeSBpZiB2ZXJzaW9uID49IDcuXG4gICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBEb24ndCBuZWVkIHZlcnNpb24gaW5mby5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHZlcnNpb25JbmZvQml0cyA9IG5ldyBCaXRBcnJheSgpO1xuICAgICAgICAgICAgTWF0cml4VXRpbC5tYWtlVmVyc2lvbkluZm9CaXRzKHZlcnNpb24sIHZlcnNpb25JbmZvQml0cyk7XG4gICAgICAgICAgICBsZXQgYml0SW5kZXggPSA2ICogMyAtIDE7IC8vIEl0IHdpbGwgZGVjcmVhc2UgZnJvbSAxNyB0byAwLlxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCA2OyArK2kpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IDM7ICsraikge1xuICAgICAgICAgICAgICAgICAgICAvLyBQbGFjZSBiaXRzIGluIExTQiAobGVhc3Qgc2lnbmlmaWNhbnQgYml0KSB0byBNU0Igb3JkZXIuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGJpdCA9IHZlcnNpb25JbmZvQml0cy5nZXQoYml0SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICBiaXRJbmRleC0tO1xuICAgICAgICAgICAgICAgICAgICAvLyBMZWZ0IGJvdHRvbSBjb3JuZXIuXG4gICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXRCb29sZWFuKGksIG1hdHJpeC5nZXRIZWlnaHQoKSAtIDExICsgaiwgYml0KTtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmlnaHQgYm90dG9tIGNvcm5lci5cbiAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldEJvb2xlYW4obWF0cml4LmdldEhlaWdodCgpIC0gMTEgKyBqLCBpLCBiaXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBFbWJlZCBcImRhdGFCaXRzXCIgdXNpbmcgXCJnZXRNYXNrUGF0dGVyblwiLiBPbiBzdWNjZXNzLCBtb2RpZnkgdGhlIG1hdHJpeCBhbmQgcmV0dXJuIHRydWUuXG4gICAgICAgIC8vIEZvciBkZWJ1Z2dpbmcgcHVycG9zZXMsIGl0IHNraXBzIG1hc2tpbmcgcHJvY2VzcyBpZiBcImdldE1hc2tQYXR0ZXJuXCIgaXMgLTEoVFlQRVNDUklQVFBPUlQ6IDI1NSkuXG4gICAgICAgIC8vIFNlZSA4Ljcgb2YgSklTWDA1MTA6MjAwNCAocC4zOCkgZm9yIGhvdyB0byBlbWJlZCBkYXRhIGJpdHMuXG4gICAgICAgIHN0YXRpYyBlbWJlZERhdGFCaXRzKGRhdGFCaXRzLCBtYXNrUGF0dGVybiAvKmludCovLCBtYXRyaXgpIHtcbiAgICAgICAgICAgIGxldCBiaXRJbmRleCA9IDA7XG4gICAgICAgICAgICBsZXQgZGlyZWN0aW9uID0gLTE7XG4gICAgICAgICAgICAvLyBTdGFydCBmcm9tIHRoZSByaWdodCBib3R0b20gY2VsbC5cbiAgICAgICAgICAgIGxldCB4ID0gbWF0cml4LmdldFdpZHRoKCkgLSAxO1xuICAgICAgICAgICAgbGV0IHkgPSBtYXRyaXguZ2V0SGVpZ2h0KCkgLSAxO1xuICAgICAgICAgICAgd2hpbGUgKHggPiAwKSB7XG4gICAgICAgICAgICAgICAgLy8gU2tpcCB0aGUgdmVydGljYWwgdGltaW5nIHBhdHRlcm4uXG4gICAgICAgICAgICAgICAgaWYgKHggPT09IDYpIHtcbiAgICAgICAgICAgICAgICAgICAgeCAtPSAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3aGlsZSAoeSA+PSAwICYmIHkgPCBtYXRyaXguZ2V0SGVpZ2h0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAyOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHh4ID0geCAtIGk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTa2lwIHRoZSBjZWxsIGlmIGl0J3Mgbm90IGVtcHR5LlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFNYXRyaXhVdGlsLmlzRW1wdHkobWF0cml4LmdldCh4eCwgeSkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgYml0O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJpdEluZGV4IDwgZGF0YUJpdHMuZ2V0U2l6ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYml0ID0gZGF0YUJpdHMuZ2V0KGJpdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICArK2JpdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUGFkZGluZyBiaXQuIElmIHRoZXJlIGlzIG5vIGJpdCBsZWZ0LCB3ZSdsbCBmaWxsIHRoZSBsZWZ0IGNlbGxzIHdpdGggMCwgYXMgZGVzY3JpYmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gOC40Ljkgb2YgSklTWDA1MTA6MjAwNCAocC4gMjQpLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpdCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2tpcCBtYXNraW5nIGlmIG1hc2tfcGF0dGVybiBpcyAtMSAoVFlQRVNDUklQVFBPUlQ6IDI1NSkuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobWFza1BhdHRlcm4gIT09IDI1NSAmJiBNYXNrVXRpbC5nZXREYXRhTWFza0JpdChtYXNrUGF0dGVybiwgeHgsIHkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYml0ID0gIWJpdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXRCb29sZWFuKHh4LCB5LCBiaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHkgKz0gZGlyZWN0aW9uO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSAtZGlyZWN0aW9uOyAvLyBSZXZlcnNlIHRoZSBkaXJlY3Rpb24uXG4gICAgICAgICAgICAgICAgeSArPSBkaXJlY3Rpb247XG4gICAgICAgICAgICAgICAgeCAtPSAyOyAvLyBNb3ZlIHRvIHRoZSBsZWZ0LlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQWxsIGJpdHMgc2hvdWxkIGJlIGNvbnN1bWVkLlxuICAgICAgICAgICAgaWYgKGJpdEluZGV4ICE9PSBkYXRhQml0cy5nZXRTaXplKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKCdOb3QgYWxsIGJpdHMgY29uc3VtZWQ6ICcgKyBiaXRJbmRleCArICcvJyArIGRhdGFCaXRzLmdldFNpemUoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmV0dXJuIHRoZSBwb3NpdGlvbiBvZiB0aGUgbW9zdCBzaWduaWZpY2FudCBiaXQgc2V0IChvbmU6IHRvKSBpbiB0aGUgXCJ2YWx1ZVwiLiBUaGUgbW9zdFxuICAgICAgICAvLyBzaWduaWZpY2FudCBiaXQgaXMgcG9zaXRpb24gMzIuIElmIHRoZXJlIGlzIG5vIGJpdCBzZXQsIHJldHVybiAwLiBFeGFtcGxlczpcbiAgICAgICAgLy8gLSBmaW5kTVNCU2V0KDApID0+IDBcbiAgICAgICAgLy8gLSBmaW5kTVNCU2V0KDEpID0+IDFcbiAgICAgICAgLy8gLSBmaW5kTVNCU2V0KDI1NSkgPT4gOFxuICAgICAgICBzdGF0aWMgZmluZE1TQlNldCh2YWx1ZSAvKmludCovKSB7XG4gICAgICAgICAgICByZXR1cm4gMzIgLSBJbnRlZ2VyLm51bWJlck9mTGVhZGluZ1plcm9zKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBDYWxjdWxhdGUgQkNIIChCb3NlLUNoYXVkaHVyaS1Ib2NxdWVuZ2hlbSkgY29kZSBmb3IgXCJ2YWx1ZVwiIHVzaW5nIHBvbHlub21pYWwgXCJwb2x5XCIuIFRoZSBCQ0hcbiAgICAgICAgLy8gY29kZSBpcyB1c2VkIGZvciBlbmNvZGluZyB0eXBlIGluZm9ybWF0aW9uIGFuZCB2ZXJzaW9uIGluZm9ybWF0aW9uLlxuICAgICAgICAvLyBFeGFtcGxlOiBDYWxjdWxhdGlvbiBvZiB2ZXJzaW9uIGluZm9ybWF0aW9uIG9mIDcuXG4gICAgICAgIC8vIGYoeCkgaXMgY3JlYXRlZCBmcm9tIDcuXG4gICAgICAgIC8vICAgLSA3ID0gMDAwMTExIGluIDYgYml0c1xuICAgICAgICAvLyAgIC0gZih4KSA9IHheMiArIHheMSArIHheMFxuICAgICAgICAvLyBnKHgpIGlzIGdpdmVuIGJ5IHRoZSBzdGFuZGFyZCAocC4gNjcpXG4gICAgICAgIC8vICAgLSBnKHgpID0geF4xMiArIHheMTEgKyB4XjEwICsgeF45ICsgeF44ICsgeF41ICsgeF4yICsgMVxuICAgICAgICAvLyBNdWx0aXBseSBmKHgpIGJ5IHheKDE4IC0gNilcbiAgICAgICAgLy8gICAtIGYnKHgpID0gZih4KSAqIHheKDE4IC0gNilcbiAgICAgICAgLy8gICAtIGYnKHgpID0geF4xNCArIHheMTMgKyB4XjEyXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgcmVtYWluZGVyIG9mIGYnKHgpIC8gZyh4KVxuICAgICAgICAvLyAgICAgICAgIHheMlxuICAgICAgICAvLyAgICAgICAgIF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXG4gICAgICAgIC8vICAgZyh4KSApeF4xNCArIHheMTMgKyB4XjEyXG4gICAgICAgIC8vICAgICAgICAgeF4xNCArIHheMTMgKyB4XjEyICsgeF4xMSArIHheMTAgKyB4XjcgKyB4XjQgKyB4XjJcbiAgICAgICAgLy8gICAgICAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHheMTEgKyB4XjEwICsgeF43ICsgeF40ICsgeF4yXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFRoZSByZW1haW5kZXIgaXMgeF4xMSArIHheMTAgKyB4XjcgKyB4XjQgKyB4XjJcbiAgICAgICAgLy8gRW5jb2RlIGl0IGluIGJpbmFyeTogMTEwMDEwMDEwMTAwXG4gICAgICAgIC8vIFRoZSByZXR1cm4gdmFsdWUgaXMgMHhjOTQgKDExMDAgMTAwMSAwMTAwKVxuICAgICAgICAvL1xuICAgICAgICAvLyBTaW5jZSBhbGwgY29lZmZpY2llbnRzIGluIHRoZSBwb2x5bm9taWFscyBhcmUgMSBvciAwLCB3ZSBjYW4gZG8gdGhlIGNhbGN1bGF0aW9uIGJ5IGJpdFxuICAgICAgICAvLyBvcGVyYXRpb25zLiBXZSBkb24ndCBjYXJlIGlmIGNvZWZmaWNpZW50cyBhcmUgcG9zaXRpdmUgb3IgbmVnYXRpdmUuXG4gICAgICAgIHN0YXRpYyBjYWxjdWxhdGVCQ0hDb2RlKHZhbHVlIC8qaW50Ki8sIHBvbHkgLyppbnQqLykge1xuICAgICAgICAgICAgaWYgKHBvbHkgPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCcwIHBvbHlub21pYWwnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIElmIHBvbHkgaXMgXCIxIDExMTEgMDAxMCAwMTAxXCIgKHZlcnNpb24gaW5mbyBwb2x5KSwgbXNiU2V0SW5Qb2x5IGlzIDEzLiBXZSdsbCBzdWJ0cmFjdCAxXG4gICAgICAgICAgICAvLyBmcm9tIDEzIHRvIG1ha2UgaXQgMTIuXG4gICAgICAgICAgICBjb25zdCBtc2JTZXRJblBvbHkgPSBNYXRyaXhVdGlsLmZpbmRNU0JTZXQocG9seSk7XG4gICAgICAgICAgICB2YWx1ZSA8PD0gbXNiU2V0SW5Qb2x5IC0gMTtcbiAgICAgICAgICAgIC8vIERvIHRoZSBkaXZpc2lvbiBidXNpbmVzcyB1c2luZyBleGNsdXNpdmUtb3Igb3BlcmF0aW9ucy5cbiAgICAgICAgICAgIHdoaWxlIChNYXRyaXhVdGlsLmZpbmRNU0JTZXQodmFsdWUpID49IG1zYlNldEluUG9seSkge1xuICAgICAgICAgICAgICAgIHZhbHVlIF49IHBvbHkgPDwgKE1hdHJpeFV0aWwuZmluZE1TQlNldCh2YWx1ZSkgLSBtc2JTZXRJblBvbHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gTm93IHRoZSBcInZhbHVlXCIgaXMgdGhlIHJlbWFpbmRlciAoaS5lLiB0aGUgQkNIIGNvZGUpXG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTWFrZSBiaXQgdmVjdG9yIG9mIHR5cGUgaW5mb3JtYXRpb24uIE9uIHN1Y2Nlc3MsIHN0b3JlIHRoZSByZXN1bHQgaW4gXCJiaXRzXCIgYW5kIHJldHVybiB0cnVlLlxuICAgICAgICAvLyBFbmNvZGUgZXJyb3IgY29ycmVjdGlvbiBsZXZlbCBhbmQgbWFzayBwYXR0ZXJuLiBTZWUgOC45IG9mXG4gICAgICAgIC8vIEpJU1gwNTEwOjIwMDQgKHAuNDUpIGZvciBkZXRhaWxzLlxuICAgICAgICBzdGF0aWMgbWFrZVR5cGVJbmZvQml0cyhlY0xldmVsLCBtYXNrUGF0dGVybiAvKmludCovLCBiaXRzKSB7XG4gICAgICAgICAgICBpZiAoIVFSQ29kZS5pc1ZhbGlkTWFza1BhdHRlcm4obWFza1BhdHRlcm4pKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdyaXRlckV4Y2VwdGlvbignSW52YWxpZCBtYXNrIHBhdHRlcm4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHR5cGVJbmZvID0gKGVjTGV2ZWwuZ2V0Qml0cygpIDw8IDMpIHwgbWFza1BhdHRlcm47XG4gICAgICAgICAgICBiaXRzLmFwcGVuZEJpdHModHlwZUluZm8sIDUpO1xuICAgICAgICAgICAgY29uc3QgYmNoQ29kZSA9IE1hdHJpeFV0aWwuY2FsY3VsYXRlQkNIQ29kZSh0eXBlSW5mbywgTWF0cml4VXRpbC5UWVBFX0lORk9fUE9MWSk7XG4gICAgICAgICAgICBiaXRzLmFwcGVuZEJpdHMoYmNoQ29kZSwgMTApO1xuICAgICAgICAgICAgY29uc3QgbWFza0JpdHMgPSBuZXcgQml0QXJyYXkoKTtcbiAgICAgICAgICAgIG1hc2tCaXRzLmFwcGVuZEJpdHMoTWF0cml4VXRpbC5UWVBFX0lORk9fTUFTS19QQVRURVJOLCAxNSk7XG4gICAgICAgICAgICBiaXRzLnhvcihtYXNrQml0cyk7XG4gICAgICAgICAgICBpZiAoYml0cy5nZXRTaXplKCkgIT09IDE1KSB7IC8vIEp1c3QgaW4gY2FzZS5cbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKCdzaG91bGQgbm90IGhhcHBlbiBidXQgd2UgZ290OiAnICsgYml0cy5nZXRTaXplKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIE1ha2UgYml0IHZlY3RvciBvZiB2ZXJzaW9uIGluZm9ybWF0aW9uLiBPbiBzdWNjZXNzLCBzdG9yZSB0aGUgcmVzdWx0IGluIFwiYml0c1wiIGFuZCByZXR1cm4gdHJ1ZS5cbiAgICAgICAgLy8gU2VlIDguMTAgb2YgSklTWDA1MTA6MjAwNCAocC40NSkgZm9yIGRldGFpbHMuXG4gICAgICAgIHN0YXRpYyBtYWtlVmVyc2lvbkluZm9CaXRzKHZlcnNpb24sIGJpdHMpIHtcbiAgICAgICAgICAgIGJpdHMuYXBwZW5kQml0cyh2ZXJzaW9uLmdldFZlcnNpb25OdW1iZXIoKSwgNik7XG4gICAgICAgICAgICBjb25zdCBiY2hDb2RlID0gTWF0cml4VXRpbC5jYWxjdWxhdGVCQ0hDb2RlKHZlcnNpb24uZ2V0VmVyc2lvbk51bWJlcigpLCBNYXRyaXhVdGlsLlZFUlNJT05fSU5GT19QT0xZKTtcbiAgICAgICAgICAgIGJpdHMuYXBwZW5kQml0cyhiY2hDb2RlLCAxMik7XG4gICAgICAgICAgICBpZiAoYml0cy5nZXRTaXplKCkgIT09IDE4KSB7IC8vIEp1c3QgaW4gY2FzZS5cbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKCdzaG91bGQgbm90IGhhcHBlbiBidXQgd2UgZ290OiAnICsgYml0cy5nZXRTaXplKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIENoZWNrIGlmIFwidmFsdWVcIiBpcyBlbXB0eS5cbiAgICAgICAgc3RhdGljIGlzRW1wdHkodmFsdWUgLyppbnQqLykge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlID09PSAyNTU7IC8vIC0xXG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGVtYmVkVGltaW5nUGF0dGVybnMobWF0cml4KSB7XG4gICAgICAgICAgICAvLyAtOCBpcyBmb3Igc2tpcHBpbmcgcG9zaXRpb24gZGV0ZWN0aW9uIHBhdHRlcm5zICg3OiBzaXplKSwgYW5kIHR3byBob3Jpem9udGFsL3ZlcnRpY2FsXG4gICAgICAgICAgICAvLyBzZXBhcmF0aW9uIHBhdHRlcm5zICgxOiBzaXplKS4gVGh1cywgOCA9IDcgKyAxLlxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDg7IGkgPCBtYXRyaXguZ2V0V2lkdGgoKSAtIDg7ICsraSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGJpdCA9IChpICsgMSkgJSAyO1xuICAgICAgICAgICAgICAgIC8vIEhvcml6b250YWwgbGluZS5cbiAgICAgICAgICAgICAgICBpZiAoTWF0cml4VXRpbC5pc0VtcHR5KG1hdHJpeC5nZXQoaSwgNikpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXROdW1iZXIoaSwgNiwgYml0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gVmVydGljYWwgbGluZS5cbiAgICAgICAgICAgICAgICBpZiAoTWF0cml4VXRpbC5pc0VtcHR5KG1hdHJpeC5nZXQoNiwgaSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXROdW1iZXIoNiwgaSwgYml0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gRW1iZWQgdGhlIGxvbmVseSBkYXJrIGRvdCBhdCBsZWZ0IGJvdHRvbSBjb3JuZXIuIEpJU1gwNTEwOjIwMDQgKHAuNDYpXG4gICAgICAgIHN0YXRpYyBlbWJlZERhcmtEb3RBdExlZnRCb3R0b21Db3JuZXIobWF0cml4KSB7XG4gICAgICAgICAgICBpZiAobWF0cml4LmdldCg4LCBtYXRyaXguZ2V0SGVpZ2h0KCkgLSA4KSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1hdHJpeC5zZXROdW1iZXIoOCwgbWF0cml4LmdldEhlaWdodCgpIC0gOCwgMSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGVtYmVkSG9yaXpvbnRhbFNlcGFyYXRpb25QYXR0ZXJuKHhTdGFydCAvKmludCovLCB5U3RhcnQgLyppbnQqLywgbWF0cml4KSB7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IDg7ICsreCkge1xuICAgICAgICAgICAgICAgIGlmICghTWF0cml4VXRpbC5pc0VtcHR5KG1hdHJpeC5nZXQoeFN0YXJ0ICsgeCwgeVN0YXJ0KSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdyaXRlckV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBtYXRyaXguc2V0TnVtYmVyKHhTdGFydCArIHgsIHlTdGFydCwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGVtYmVkVmVydGljYWxTZXBhcmF0aW9uUGF0dGVybih4U3RhcnQgLyppbnQqLywgeVN0YXJ0IC8qaW50Ki8sIG1hdHJpeCkge1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCA3OyArK3kpIHtcbiAgICAgICAgICAgICAgICBpZiAoIU1hdHJpeFV0aWwuaXNFbXB0eShtYXRyaXguZ2V0KHhTdGFydCwgeVN0YXJ0ICsgeSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbWF0cml4LnNldE51bWJlcih4U3RhcnQsIHlTdGFydCArIHksIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBlbWJlZFBvc2l0aW9uQWRqdXN0bWVudFBhdHRlcm4oeFN0YXJ0IC8qaW50Ki8sIHlTdGFydCAvKmludCovLCBtYXRyaXgpIHtcbiAgICAgICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgNTsgKyt5KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGF0dGVyblkgPSBNYXRyaXhVdGlsLlBPU0lUSU9OX0FESlVTVE1FTlRfUEFUVEVSTlt5XTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IDU7ICsreCkge1xuICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0TnVtYmVyKHhTdGFydCArIHgsIHlTdGFydCArIHksIHBhdHRlcm5ZW3hdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGVtYmVkUG9zaXRpb25EZXRlY3Rpb25QYXR0ZXJuKHhTdGFydCAvKmludCovLCB5U3RhcnQgLyppbnQqLywgbWF0cml4KSB7XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IDc7ICsreSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhdHRlcm5ZID0gTWF0cml4VXRpbC5QT1NJVElPTl9ERVRFQ1RJT05fUEFUVEVSTlt5XTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IDc7ICsreCkge1xuICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0TnVtYmVyKHhTdGFydCArIHgsIHlTdGFydCArIHksIHBhdHRlcm5ZW3hdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gRW1iZWQgcG9zaXRpb24gZGV0ZWN0aW9uIHBhdHRlcm5zIGFuZCBzdXJyb3VuZGluZyB2ZXJ0aWNhbC9ob3Jpem9udGFsIHNlcGFyYXRvcnMuXG4gICAgICAgIHN0YXRpYyBlbWJlZFBvc2l0aW9uRGV0ZWN0aW9uUGF0dGVybnNBbmRTZXBhcmF0b3JzKG1hdHJpeCkge1xuICAgICAgICAgICAgLy8gRW1iZWQgdGhyZWUgYmlnIHNxdWFyZXMgYXQgY29ybmVycy5cbiAgICAgICAgICAgIGNvbnN0IHBkcFdpZHRoID0gTWF0cml4VXRpbC5QT1NJVElPTl9ERVRFQ1RJT05fUEFUVEVSTlswXS5sZW5ndGg7XG4gICAgICAgICAgICAvLyBMZWZ0IHRvcCBjb3JuZXIuXG4gICAgICAgICAgICBNYXRyaXhVdGlsLmVtYmVkUG9zaXRpb25EZXRlY3Rpb25QYXR0ZXJuKDAsIDAsIG1hdHJpeCk7XG4gICAgICAgICAgICAvLyBSaWdodCB0b3AgY29ybmVyLlxuICAgICAgICAgICAgTWF0cml4VXRpbC5lbWJlZFBvc2l0aW9uRGV0ZWN0aW9uUGF0dGVybihtYXRyaXguZ2V0V2lkdGgoKSAtIHBkcFdpZHRoLCAwLCBtYXRyaXgpO1xuICAgICAgICAgICAgLy8gTGVmdCBib3R0b20gY29ybmVyLlxuICAgICAgICAgICAgTWF0cml4VXRpbC5lbWJlZFBvc2l0aW9uRGV0ZWN0aW9uUGF0dGVybigwLCBtYXRyaXguZ2V0V2lkdGgoKSAtIHBkcFdpZHRoLCBtYXRyaXgpO1xuICAgICAgICAgICAgLy8gRW1iZWQgaG9yaXpvbnRhbCBzZXBhcmF0aW9uIHBhdHRlcm5zIGFyb3VuZCB0aGUgc3F1YXJlcy5cbiAgICAgICAgICAgIGNvbnN0IGhzcFdpZHRoID0gODtcbiAgICAgICAgICAgIC8vIExlZnQgdG9wIGNvcm5lci5cbiAgICAgICAgICAgIE1hdHJpeFV0aWwuZW1iZWRIb3Jpem9udGFsU2VwYXJhdGlvblBhdHRlcm4oMCwgaHNwV2lkdGggLSAxLCBtYXRyaXgpO1xuICAgICAgICAgICAgLy8gUmlnaHQgdG9wIGNvcm5lci5cbiAgICAgICAgICAgIE1hdHJpeFV0aWwuZW1iZWRIb3Jpem9udGFsU2VwYXJhdGlvblBhdHRlcm4obWF0cml4LmdldFdpZHRoKCkgLSBoc3BXaWR0aCwgaHNwV2lkdGggLSAxLCBtYXRyaXgpO1xuICAgICAgICAgICAgLy8gTGVmdCBib3R0b20gY29ybmVyLlxuICAgICAgICAgICAgTWF0cml4VXRpbC5lbWJlZEhvcml6b250YWxTZXBhcmF0aW9uUGF0dGVybigwLCBtYXRyaXguZ2V0V2lkdGgoKSAtIGhzcFdpZHRoLCBtYXRyaXgpO1xuICAgICAgICAgICAgLy8gRW1iZWQgdmVydGljYWwgc2VwYXJhdGlvbiBwYXR0ZXJucyBhcm91bmQgdGhlIHNxdWFyZXMuXG4gICAgICAgICAgICBjb25zdCB2c3BTaXplID0gNztcbiAgICAgICAgICAgIC8vIExlZnQgdG9wIGNvcm5lci5cbiAgICAgICAgICAgIE1hdHJpeFV0aWwuZW1iZWRWZXJ0aWNhbFNlcGFyYXRpb25QYXR0ZXJuKHZzcFNpemUsIDAsIG1hdHJpeCk7XG4gICAgICAgICAgICAvLyBSaWdodCB0b3AgY29ybmVyLlxuICAgICAgICAgICAgTWF0cml4VXRpbC5lbWJlZFZlcnRpY2FsU2VwYXJhdGlvblBhdHRlcm4obWF0cml4LmdldEhlaWdodCgpIC0gdnNwU2l6ZSAtIDEsIDAsIG1hdHJpeCk7XG4gICAgICAgICAgICAvLyBMZWZ0IGJvdHRvbSBjb3JuZXIuXG4gICAgICAgICAgICBNYXRyaXhVdGlsLmVtYmVkVmVydGljYWxTZXBhcmF0aW9uUGF0dGVybih2c3BTaXplLCBtYXRyaXguZ2V0SGVpZ2h0KCkgLSB2c3BTaXplLCBtYXRyaXgpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEVtYmVkIHBvc2l0aW9uIGFkanVzdG1lbnQgcGF0dGVybnMgaWYgbmVlZCBiZS5cbiAgICAgICAgc3RhdGljIG1heWJlRW1iZWRQb3NpdGlvbkFkanVzdG1lbnRQYXR0ZXJucyh2ZXJzaW9uLCBtYXRyaXgpIHtcbiAgICAgICAgICAgIGlmICh2ZXJzaW9uLmdldFZlcnNpb25OdW1iZXIoKSA8IDIpIHsgLy8gVGhlIHBhdHRlcm5zIGFwcGVhciBpZiB2ZXJzaW9uID49IDJcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IHZlcnNpb24uZ2V0VmVyc2lvbk51bWJlcigpIC0gMTtcbiAgICAgICAgICAgIGNvbnN0IGNvb3JkaW5hdGVzID0gTWF0cml4VXRpbC5QT1NJVElPTl9BREpVU1RNRU5UX1BBVFRFUk5fQ09PUkRJTkFURV9UQUJMRVtpbmRleF07XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgbGVuZ3RoID0gY29vcmRpbmF0ZXMubGVuZ3RoOyBpICE9PSBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHkgPSBjb29yZGluYXRlc1tpXTtcbiAgICAgICAgICAgICAgICBpZiAoeSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqICE9PSBsZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeCA9IGNvb3JkaW5hdGVzW2pdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHggPj0gMCAmJiBNYXRyaXhVdGlsLmlzRW1wdHkobWF0cml4LmdldCh4LCB5KSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgY2VsbCBpcyB1bnNldCwgd2UgZW1iZWQgdGhlIHBvc2l0aW9uIGFkanVzdG1lbnQgcGF0dGVybiBoZXJlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0yIGlzIG5lY2Vzc2FyeSBzaW5jZSB0aGUgeC95IGNvb3JkaW5hdGVzIHBvaW50IHRvIHRoZSBjZW50ZXIgb2YgdGhlIHBhdHRlcm4sIG5vdCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBsZWZ0IHRvcCBjb3JuZXIuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTWF0cml4VXRpbC5lbWJlZFBvc2l0aW9uQWRqdXN0bWVudFBhdHRlcm4oeCAtIDIsIHkgLSAyLCBtYXRyaXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIE1hdHJpeFV0aWwuUE9TSVRJT05fREVURUNUSU9OX1BBVFRFUk4gPSBBcnJheS5mcm9tKFtcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAxLCAxLCAxLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMCwgMCwgMCwgMCwgMCwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDAsIDEsIDEsIDEsIDAsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAwLCAxLCAxLCAxLCAwLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMCwgMSwgMSwgMSwgMCwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDAsIDAsIDAsIDAsIDAsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAxLCAxLCAxLCAxLCAxXSksXG4gICAgXSk7XG4gICAgTWF0cml4VXRpbC5QT1NJVElPTl9BREpVU1RNRU5UX1BBVFRFUk4gPSBBcnJheS5mcm9tKFtcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAxLCAxLCAxLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMCwgMCwgMCwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzEsIDAsIDEsIDAsIDFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsxLCAwLCAwLCAwLCAxXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgMSwgMSwgMSwgMV0pLFxuICAgIF0pO1xuICAgIC8vIEZyb20gQXBwZW5kaXggRS4gVGFibGUgMSwgSklTMDUxMFg6MjAwNCAoNzE6IHApLiBUaGUgdGFibGUgd2FzIGRvdWJsZS1jaGVja2VkIGJ5IGtvbWF0c3UuXG4gICAgTWF0cml4VXRpbC5QT1NJVElPTl9BREpVU1RNRU5UX1BBVFRFUk5fQ09PUkRJTkFURV9UQUJMRSA9IEFycmF5LmZyb20oW1xuICAgICAgICBJbnQzMkFycmF5LmZyb20oWy0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMTgsIC0xLCAtMSwgLTEsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDIyLCAtMSwgLTEsIC0xLCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAyNiwgLTEsIC0xLCAtMSwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIC0xLCAtMSwgLTEsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDM0LCAtMSwgLTEsIC0xLCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAyMiwgMzgsIC0xLCAtMSwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMjQsIDQyLCAtMSwgLTEsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDI2LCA0NiwgLTEsIC0xLCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAyOCwgNTAsIC0xLCAtMSwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIDU0LCAtMSwgLTEsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDMyLCA1OCwgLTEsIC0xLCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzNCwgNjIsIC0xLCAtMSwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMjYsIDQ2LCA2NiwgLTEsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDI2LCA0OCwgNzAsIC0xLCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAyNiwgNTAsIDc0LCAtMSwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIDU0LCA3OCwgLTEsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDMwLCA1NiwgODIsIC0xLCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTgsIDg2LCAtMSwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzQsIDYyLCA5MCwgLTEsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDI4LCA1MCwgNzIsIDk0LCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAyNiwgNTAsIDc0LCA5OCwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIDU0LCA3OCwgMTAyLCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAyOCwgNTQsIDgwLCAxMDYsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDMyLCA1OCwgODQsIDExMCwgLTEsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIDU4LCA4NiwgMTE0LCAtMSwgLTFdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzNCwgNjIsIDkwLCAxMTgsIC0xLCAtMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDI2LCA1MCwgNzQsIDk4LCAxMjIsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIDU0LCA3OCwgMTAyLCAxMjYsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMjYsIDUyLCA3OCwgMTA0LCAxMzAsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIDU2LCA4MiwgMTA4LCAxMzQsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzQsIDYwLCA4NiwgMTEyLCAxMzgsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIDU4LCA4NiwgMTE0LCAxNDIsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzQsIDYyLCA5MCwgMTE4LCAxNDYsIC0xXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzAsIDU0LCA3OCwgMTAyLCAxMjYsIDE1MF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDI0LCA1MCwgNzYsIDEwMiwgMTI4LCAxNTRdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAyOCwgNTQsIDgwLCAxMDYsIDEzMiwgMTU4XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNiwgMzIsIDU4LCA4NCwgMTEwLCAxMzYsIDE2Ml0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzYsIDI2LCA1NCwgODIsIDExMCwgMTM4LCAxNjZdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs2LCAzMCwgNTgsIDg2LCAxMTQsIDE0MiwgMTcwXSksXG4gICAgXSk7XG4gICAgLy8gVHlwZSBpbmZvIGNlbGxzIGF0IHRoZSBsZWZ0IHRvcCBjb3JuZXIuXG4gICAgTWF0cml4VXRpbC5UWVBFX0lORk9fQ09PUkRJTkFURVMgPSBBcnJheS5mcm9tKFtcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs4LCAwXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbOCwgMV0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzgsIDJdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs4LCAzXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbOCwgNF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzgsIDVdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs4LCA3XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbOCwgOF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzcsIDhdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFs1LCA4XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbNCwgOF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzMsIDhdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFsyLCA4XSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbMSwgOF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oWzAsIDhdKSxcbiAgICBdKTtcbiAgICAvLyBGcm9tIEFwcGVuZGl4IEQgaW4gSklTWDA1MTA6MjAwNCAocC4gNjcpXG4gICAgTWF0cml4VXRpbC5WRVJTSU9OX0lORk9fUE9MWSA9IDB4MWYyNTsgLy8gMSAxMTExIDAwMTAgMDEwMVxuICAgIC8vIEZyb20gQXBwZW5kaXggQyBpbiBKSVNYMDUxMDoyMDA0IChwLjY1KS5cbiAgICBNYXRyaXhVdGlsLlRZUEVfSU5GT19QT0xZID0gMHg1Mzc7XG4gICAgTWF0cml4VXRpbC5UWVBFX0lORk9fTUFTS19QQVRURVJOID0gMHg1NDEyO1xuXG4gICAgLypuYW1lc3BhY2UgY29tLmdvb2dsZS56eGluZy5xcmNvZGUuZW5jb2RlciB7Ki9cbiAgICBjbGFzcyBCbG9ja1BhaXIge1xuICAgICAgICBjb25zdHJ1Y3RvcihkYXRhQnl0ZXMsIGVycm9yQ29ycmVjdGlvbkJ5dGVzKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGFCeXRlcyA9IGRhdGFCeXRlcztcbiAgICAgICAgICAgIHRoaXMuZXJyb3JDb3JyZWN0aW9uQnl0ZXMgPSBlcnJvckNvcnJlY3Rpb25CeXRlcztcbiAgICAgICAgfVxuICAgICAgICBnZXREYXRhQnl0ZXMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRhQnl0ZXM7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0RXJyb3JDb3JyZWN0aW9uQnl0ZXMoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lcnJvckNvcnJlY3Rpb25CeXRlcztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qaW1wb3J0IGphdmEuaW8uVW5zdXBwb3J0ZWRFbmNvZGluZ0V4Y2VwdGlvbjsqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7Ki9cbiAgICAvKmltcG9ydCBqYXZhLnV0aWwuQ29sbGVjdGlvbjsqL1xuICAgIC8qaW1wb3J0IGphdmEudXRpbC5NYXA7Ki9cbiAgICAvKipcbiAgICAgKiBAYXV0aG9yIHNhdG9ydXhAZ29vZ2xlLmNvbSAoU2F0b3J1IFRha2FiYXlhc2hpKSAtIGNyZWF0b3JcbiAgICAgKiBAYXV0aG9yIGRzd2l0a2luQGdvb2dsZS5jb20gKERhbmllbCBTd2l0a2luKSAtIHBvcnRlZCBmcm9tIEMrK1xuICAgICAqL1xuICAgIGNsYXNzIEVuY29kZXIge1xuICAgICAgICAvLyBUWVBFU0NSSVBUUE9SVDogY2hhbmdlZCB0byBVVEY4LCB0aGUgZGVmYXVsdCBmb3IganNcbiAgICAgICAgY29uc3RydWN0b3IoKSB7IH1cbiAgICAgICAgLy8gVGhlIG1hc2sgcGVuYWx0eSBjYWxjdWxhdGlvbiBpcyBjb21wbGljYXRlZC4gIFNlZSBUYWJsZSAyMSBvZiBKSVNYMDUxMDoyMDA0IChwLjQ1KSBmb3IgZGV0YWlscy5cbiAgICAgICAgLy8gQmFzaWNhbGx5IGl0IGFwcGxpZXMgZm91ciBydWxlcyBhbmQgc3VtbWF0ZSBhbGwgcGVuYWx0aWVzLlxuICAgICAgICBzdGF0aWMgY2FsY3VsYXRlTWFza1BlbmFsdHkobWF0cml4KSB7XG4gICAgICAgICAgICByZXR1cm4gTWFza1V0aWwuYXBwbHlNYXNrUGVuYWx0eVJ1bGUxKG1hdHJpeClcbiAgICAgICAgICAgICAgICArIE1hc2tVdGlsLmFwcGx5TWFza1BlbmFsdHlSdWxlMihtYXRyaXgpXG4gICAgICAgICAgICAgICAgKyBNYXNrVXRpbC5hcHBseU1hc2tQZW5hbHR5UnVsZTMobWF0cml4KVxuICAgICAgICAgICAgICAgICsgTWFza1V0aWwuYXBwbHlNYXNrUGVuYWx0eVJ1bGU0KG1hdHJpeCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSBjb250ZW50IHRleHQgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSBlY0xldmVsIGVycm9yIGNvcnJlY3Rpb24gbGV2ZWwgdG8gdXNlXG4gICAgICAgICAqIEByZXR1cm4ge0BsaW5rIFFSQ29kZX0gcmVwcmVzZW50aW5nIHRoZSBlbmNvZGVkIFFSIGNvZGVcbiAgICAgICAgICogQHRocm93cyBXcml0ZXJFeGNlcHRpb24gaWYgZW5jb2RpbmcgY2FuJ3Qgc3VjY2VlZCwgYmVjYXVzZSBvZiBmb3IgZXhhbXBsZSBpbnZhbGlkIGNvbnRlbnRcbiAgICAgICAgICogICBvciBjb25maWd1cmF0aW9uXG4gICAgICAgICAqL1xuICAgICAgICAvLyBwdWJsaWMgc3RhdGljIGVuY29kZShjb250ZW50OiBzdHJpbmcsIGVjTGV2ZWw6IEVycm9yQ29ycmVjdGlvbkxldmVsKTogUVJDb2RlIC8qdGhyb3dzIFdyaXRlckV4Y2VwdGlvbiovIHtcbiAgICAgICAgLy8gICByZXR1cm4gZW5jb2RlKGNvbnRlbnQsIGVjTGV2ZWwsIG51bGwpXG4gICAgICAgIC8vIH1cbiAgICAgICAgc3RhdGljIGVuY29kZShjb250ZW50LCBlY0xldmVsLCBoaW50cyA9IG51bGwpIHtcbiAgICAgICAgICAgIC8vIERldGVybWluZSB3aGF0IGNoYXJhY3RlciBlbmNvZGluZyBoYXMgYmVlbiBzcGVjaWZpZWQgYnkgdGhlIGNhbGxlciwgaWYgYW55XG4gICAgICAgICAgICBsZXQgZW5jb2RpbmcgPSBFbmNvZGVyLkRFRkFVTFRfQllURV9NT0RFX0VOQ09ESU5HO1xuICAgICAgICAgICAgY29uc3QgaGFzRW5jb2RpbmdIaW50ID0gaGludHMgIT09IG51bGwgJiYgdW5kZWZpbmVkICE9PSBoaW50cy5nZXQoRW5jb2RlSGludFR5cGUkMS5DSEFSQUNURVJfU0VUKTtcbiAgICAgICAgICAgIGlmIChoYXNFbmNvZGluZ0hpbnQpIHtcbiAgICAgICAgICAgICAgICBlbmNvZGluZyA9IGhpbnRzLmdldChFbmNvZGVIaW50VHlwZSQxLkNIQVJBQ1RFUl9TRVQpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBQaWNrIGFuIGVuY29kaW5nIG1vZGUgYXBwcm9wcmlhdGUgZm9yIHRoZSBjb250ZW50LiBOb3RlIHRoYXQgdGhpcyB3aWxsIG5vdCBhdHRlbXB0IHRvIHVzZVxuICAgICAgICAgICAgLy8gbXVsdGlwbGUgbW9kZXMgLyBzZWdtZW50cyBldmVuIGlmIHRoYXQgd2VyZSBtb3JlIGVmZmljaWVudC4gVHdvdWxkIGJlIG5pY2UuXG4gICAgICAgICAgICBjb25zdCBtb2RlID0gdGhpcy5jaG9vc2VNb2RlKGNvbnRlbnQsIGVuY29kaW5nKTtcbiAgICAgICAgICAgIC8vIFRoaXMgd2lsbCBzdG9yZSB0aGUgaGVhZGVyIGluZm9ybWF0aW9uLCBsaWtlIG1vZGUgYW5kXG4gICAgICAgICAgICAvLyBsZW5ndGgsIGFzIHdlbGwgYXMgXCJoZWFkZXJcIiBzZWdtZW50cyBsaWtlIGFuIEVDSSBzZWdtZW50LlxuICAgICAgICAgICAgY29uc3QgaGVhZGVyQml0cyA9IG5ldyBCaXRBcnJheSgpO1xuICAgICAgICAgICAgLy8gQXBwZW5kIEVDSSBzZWdtZW50IGlmIGFwcGxpY2FibGVcbiAgICAgICAgICAgIGlmIChtb2RlID09PSBNb2RlJDEuQllURSAmJiAoaGFzRW5jb2RpbmdIaW50IHx8IEVuY29kZXIuREVGQVVMVF9CWVRFX01PREVfRU5DT0RJTkcgIT09IGVuY29kaW5nKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGVjaSA9IENoYXJhY3RlclNldEVDSS5nZXRDaGFyYWN0ZXJTZXRFQ0lCeU5hbWUoZW5jb2RpbmcpO1xuICAgICAgICAgICAgICAgIGlmIChlY2kgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFwcGVuZEVDSShlY2ksIGhlYWRlckJpdHMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIChXaXRoIEVDSSBpbiBwbGFjZSwpIFdyaXRlIHRoZSBtb2RlIG1hcmtlclxuICAgICAgICAgICAgdGhpcy5hcHBlbmRNb2RlSW5mbyhtb2RlLCBoZWFkZXJCaXRzKTtcbiAgICAgICAgICAgIC8vIENvbGxlY3QgZGF0YSB3aXRoaW4gdGhlIG1haW4gc2VnbWVudCwgc2VwYXJhdGVseSwgdG8gY291bnQgaXRzIHNpemUgaWYgbmVlZGVkLiBEb24ndCBhZGQgaXQgdG9cbiAgICAgICAgICAgIC8vIG1haW4gcGF5bG9hZCB5ZXQuXG4gICAgICAgICAgICBjb25zdCBkYXRhQml0cyA9IG5ldyBCaXRBcnJheSgpO1xuICAgICAgICAgICAgdGhpcy5hcHBlbmRCeXRlcyhjb250ZW50LCBtb2RlLCBkYXRhQml0cywgZW5jb2RpbmcpO1xuICAgICAgICAgICAgbGV0IHZlcnNpb247XG4gICAgICAgICAgICBpZiAoaGludHMgIT09IG51bGwgJiYgdW5kZWZpbmVkICE9PSBoaW50cy5nZXQoRW5jb2RlSGludFR5cGUkMS5RUl9WRVJTSU9OKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZlcnNpb25OdW1iZXIgPSBOdW1iZXIucGFyc2VJbnQoaGludHMuZ2V0KEVuY29kZUhpbnRUeXBlJDEuUVJfVkVSU0lPTikudG9TdHJpbmcoKSwgMTApO1xuICAgICAgICAgICAgICAgIHZlcnNpb24gPSBWZXJzaW9uJDEuZ2V0VmVyc2lvbkZvck51bWJlcih2ZXJzaW9uTnVtYmVyKTtcbiAgICAgICAgICAgICAgICBjb25zdCBiaXRzTmVlZGVkID0gdGhpcy5jYWxjdWxhdGVCaXRzTmVlZGVkKG1vZGUsIGhlYWRlckJpdHMsIGRhdGFCaXRzLCB2ZXJzaW9uKTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMud2lsbEZpdChiaXRzTmVlZGVkLCB2ZXJzaW9uLCBlY0xldmVsKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKCdEYXRhIHRvbyBiaWcgZm9yIHJlcXVlc3RlZCB2ZXJzaW9uJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmVyc2lvbiA9IHRoaXMucmVjb21tZW5kVmVyc2lvbihlY0xldmVsLCBtb2RlLCBoZWFkZXJCaXRzLCBkYXRhQml0cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBoZWFkZXJBbmREYXRhQml0cyA9IG5ldyBCaXRBcnJheSgpO1xuICAgICAgICAgICAgaGVhZGVyQW5kRGF0YUJpdHMuYXBwZW5kQml0QXJyYXkoaGVhZGVyQml0cyk7XG4gICAgICAgICAgICAvLyBGaW5kIFwibGVuZ3RoXCIgb2YgbWFpbiBzZWdtZW50IGFuZCB3cml0ZSBpdFxuICAgICAgICAgICAgY29uc3QgbnVtTGV0dGVycyA9IG1vZGUgPT09IE1vZGUkMS5CWVRFID8gZGF0YUJpdHMuZ2V0U2l6ZUluQnl0ZXMoKSA6IGNvbnRlbnQubGVuZ3RoO1xuICAgICAgICAgICAgdGhpcy5hcHBlbmRMZW5ndGhJbmZvKG51bUxldHRlcnMsIHZlcnNpb24sIG1vZGUsIGhlYWRlckFuZERhdGFCaXRzKTtcbiAgICAgICAgICAgIC8vIFB1dCBkYXRhIHRvZ2V0aGVyIGludG8gdGhlIG92ZXJhbGwgcGF5bG9hZFxuICAgICAgICAgICAgaGVhZGVyQW5kRGF0YUJpdHMuYXBwZW5kQml0QXJyYXkoZGF0YUJpdHMpO1xuICAgICAgICAgICAgY29uc3QgZWNCbG9ja3MgPSB2ZXJzaW9uLmdldEVDQmxvY2tzRm9yTGV2ZWwoZWNMZXZlbCk7XG4gICAgICAgICAgICBjb25zdCBudW1EYXRhQnl0ZXMgPSB2ZXJzaW9uLmdldFRvdGFsQ29kZXdvcmRzKCkgLSBlY0Jsb2Nrcy5nZXRUb3RhbEVDQ29kZXdvcmRzKCk7XG4gICAgICAgICAgICAvLyBUZXJtaW5hdGUgdGhlIGJpdHMgcHJvcGVybHkuXG4gICAgICAgICAgICB0aGlzLnRlcm1pbmF0ZUJpdHMobnVtRGF0YUJ5dGVzLCBoZWFkZXJBbmREYXRhQml0cyk7XG4gICAgICAgICAgICAvLyBJbnRlcmxlYXZlIGRhdGEgYml0cyB3aXRoIGVycm9yIGNvcnJlY3Rpb24gY29kZS5cbiAgICAgICAgICAgIGNvbnN0IGZpbmFsQml0cyA9IHRoaXMuaW50ZXJsZWF2ZVdpdGhFQ0J5dGVzKGhlYWRlckFuZERhdGFCaXRzLCB2ZXJzaW9uLmdldFRvdGFsQ29kZXdvcmRzKCksIG51bURhdGFCeXRlcywgZWNCbG9ja3MuZ2V0TnVtQmxvY2tzKCkpO1xuICAgICAgICAgICAgY29uc3QgcXJDb2RlID0gbmV3IFFSQ29kZSgpO1xuICAgICAgICAgICAgcXJDb2RlLnNldEVDTGV2ZWwoZWNMZXZlbCk7XG4gICAgICAgICAgICBxckNvZGUuc2V0TW9kZShtb2RlKTtcbiAgICAgICAgICAgIHFyQ29kZS5zZXRWZXJzaW9uKHZlcnNpb24pO1xuICAgICAgICAgICAgLy8gIENob29zZSB0aGUgbWFzayBwYXR0ZXJuIGFuZCBzZXQgdG8gXCJxckNvZGVcIi5cbiAgICAgICAgICAgIGNvbnN0IGRpbWVuc2lvbiA9IHZlcnNpb24uZ2V0RGltZW5zaW9uRm9yVmVyc2lvbigpO1xuICAgICAgICAgICAgY29uc3QgbWF0cml4ID0gbmV3IEJ5dGVNYXRyaXgoZGltZW5zaW9uLCBkaW1lbnNpb24pO1xuICAgICAgICAgICAgY29uc3QgbWFza1BhdHRlcm4gPSB0aGlzLmNob29zZU1hc2tQYXR0ZXJuKGZpbmFsQml0cywgZWNMZXZlbCwgdmVyc2lvbiwgbWF0cml4KTtcbiAgICAgICAgICAgIHFyQ29kZS5zZXRNYXNrUGF0dGVybihtYXNrUGF0dGVybik7XG4gICAgICAgICAgICAvLyBCdWlsZCB0aGUgbWF0cml4IGFuZCBzZXQgaXQgdG8gXCJxckNvZGVcIi5cbiAgICAgICAgICAgIE1hdHJpeFV0aWwuYnVpbGRNYXRyaXgoZmluYWxCaXRzLCBlY0xldmVsLCB2ZXJzaW9uLCBtYXNrUGF0dGVybiwgbWF0cml4KTtcbiAgICAgICAgICAgIHFyQ29kZS5zZXRNYXRyaXgobWF0cml4KTtcbiAgICAgICAgICAgIHJldHVybiBxckNvZGU7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY2lkZXMgdGhlIHNtYWxsZXN0IHZlcnNpb24gb2YgUVIgY29kZSB0aGF0IHdpbGwgY29udGFpbiBhbGwgb2YgdGhlIHByb3ZpZGVkIGRhdGEuXG4gICAgICAgICAqXG4gICAgICAgICAqIEB0aHJvd3MgV3JpdGVyRXhjZXB0aW9uIGlmIHRoZSBkYXRhIGNhbm5vdCBmaXQgaW4gYW55IHZlcnNpb25cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyByZWNvbW1lbmRWZXJzaW9uKGVjTGV2ZWwsIG1vZGUsIGhlYWRlckJpdHMsIGRhdGFCaXRzKSB7XG4gICAgICAgICAgICAvLyBIYXJkIHBhcnQ6IG5lZWQgdG8ga25vdyB2ZXJzaW9uIHRvIGtub3cgaG93IG1hbnkgYml0cyBsZW5ndGggdGFrZXMuIEJ1dCBuZWVkIHRvIGtub3cgaG93IG1hbnlcbiAgICAgICAgICAgIC8vIGJpdHMgaXQgdGFrZXMgdG8ga25vdyB2ZXJzaW9uLiBGaXJzdCB3ZSB0YWtlIGEgZ3Vlc3MgYXQgdmVyc2lvbiBieSBhc3N1bWluZyB2ZXJzaW9uIHdpbGwgYmVcbiAgICAgICAgICAgIC8vIHRoZSBtaW5pbXVtLCAxOlxuICAgICAgICAgICAgY29uc3QgcHJvdmlzaW9uYWxCaXRzTmVlZGVkID0gdGhpcy5jYWxjdWxhdGVCaXRzTmVlZGVkKG1vZGUsIGhlYWRlckJpdHMsIGRhdGFCaXRzLCBWZXJzaW9uJDEuZ2V0VmVyc2lvbkZvck51bWJlcigxKSk7XG4gICAgICAgICAgICBjb25zdCBwcm92aXNpb25hbFZlcnNpb24gPSB0aGlzLmNob29zZVZlcnNpb24ocHJvdmlzaW9uYWxCaXRzTmVlZGVkLCBlY0xldmVsKTtcbiAgICAgICAgICAgIC8vIFVzZSB0aGF0IGd1ZXNzIHRvIGNhbGN1bGF0ZSB0aGUgcmlnaHQgdmVyc2lvbi4gSSBhbSBzdGlsbCBub3Qgc3VyZSB0aGlzIHdvcmtzIGluIDEwMCUgb2YgY2FzZXMuXG4gICAgICAgICAgICBjb25zdCBiaXRzTmVlZGVkID0gdGhpcy5jYWxjdWxhdGVCaXRzTmVlZGVkKG1vZGUsIGhlYWRlckJpdHMsIGRhdGFCaXRzLCBwcm92aXNpb25hbFZlcnNpb24pO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2hvb3NlVmVyc2lvbihiaXRzTmVlZGVkLCBlY0xldmVsKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgY2FsY3VsYXRlQml0c05lZWRlZChtb2RlLCBoZWFkZXJCaXRzLCBkYXRhQml0cywgdmVyc2lvbikge1xuICAgICAgICAgICAgcmV0dXJuIGhlYWRlckJpdHMuZ2V0U2l6ZSgpICsgbW9kZS5nZXRDaGFyYWN0ZXJDb3VudEJpdHModmVyc2lvbikgKyBkYXRhQml0cy5nZXRTaXplKCk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gdGhlIGNvZGUgcG9pbnQgb2YgdGhlIHRhYmxlIHVzZWQgaW4gYWxwaGFudW1lcmljIG1vZGUgb3JcbiAgICAgICAgICogIC0xIGlmIHRoZXJlIGlzIG5vIGNvcnJlc3BvbmRpbmcgY29kZSBpbiB0aGUgdGFibGUuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZ2V0QWxwaGFudW1lcmljQ29kZShjb2RlIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGlmIChjb2RlIDwgRW5jb2Rlci5BTFBIQU5VTUVSSUNfVEFCTEUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEVuY29kZXIuQUxQSEFOVU1FUklDX1RBQkxFW2NvZGVdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICB9XG4gICAgICAgIC8vIHB1YmxpYyBzdGF0aWMgY2hvb3NlTW9kZShjb250ZW50OiBzdHJpbmcpOiBNb2RlIHtcbiAgICAgICAgLy8gICByZXR1cm4gY2hvb3NlTW9kZShjb250ZW50LCBudWxsKTtcbiAgICAgICAgLy8gfVxuICAgICAgICAvKipcbiAgICAgICAgICogQ2hvb3NlIHRoZSBiZXN0IG1vZGUgYnkgZXhhbWluaW5nIHRoZSBjb250ZW50LiBOb3RlIHRoYXQgJ2VuY29kaW5nJyBpcyB1c2VkIGFzIGEgaGludDtcbiAgICAgICAgICogaWYgaXQgaXMgU2hpZnRfSklTLCBhbmQgdGhlIGlucHV0IGlzIG9ubHkgZG91YmxlLWJ5dGUgS2FuamksIHRoZW4gd2UgcmV0dXJuIHtAbGluayBNb2RlI0tBTkpJfS5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBjaG9vc2VNb2RlKGNvbnRlbnQsIGVuY29kaW5nID0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKENoYXJhY3RlclNldEVDSS5TSklTLmdldE5hbWUoKSA9PT0gZW5jb2RpbmcgJiYgdGhpcy5pc09ubHlEb3VibGVCeXRlS2FuamkoY29udGVudCkpIHtcbiAgICAgICAgICAgICAgICAvLyBDaG9vc2UgS2FuamkgbW9kZSBpZiBhbGwgaW5wdXQgYXJlIGRvdWJsZS1ieXRlIGNoYXJhY3RlcnNcbiAgICAgICAgICAgICAgICByZXR1cm4gTW9kZSQxLktBTkpJO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGhhc051bWVyaWMgPSBmYWxzZTtcbiAgICAgICAgICAgIGxldCBoYXNBbHBoYW51bWVyaWMgPSBmYWxzZTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBsZW5ndGggPSBjb250ZW50Lmxlbmd0aDsgaSA8IGxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYyA9IGNvbnRlbnQuY2hhckF0KGkpO1xuICAgICAgICAgICAgICAgIGlmIChFbmNvZGVyLmlzRGlnaXQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzTnVtZXJpYyA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuZ2V0QWxwaGFudW1lcmljQ29kZShjLmNoYXJDb2RlQXQoMCkpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBoYXNBbHBoYW51bWVyaWMgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE1vZGUkMS5CWVRFO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChoYXNBbHBoYW51bWVyaWMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTW9kZSQxLkFMUEhBTlVNRVJJQztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChoYXNOdW1lcmljKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE1vZGUkMS5OVU1FUklDO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIE1vZGUkMS5CWVRFO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBpc09ubHlEb3VibGVCeXRlS2FuamkoY29udGVudCkge1xuICAgICAgICAgICAgbGV0IGJ5dGVzO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBieXRlcyA9IFN0cmluZ0VuY29kaW5nLmVuY29kZShjb250ZW50LCBDaGFyYWN0ZXJTZXRFQ0kuU0pJUyk7IC8vIGNvbnRlbnQuZ2V0Qnl0ZXMoXCJTaGlmdF9KSVNcIikpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoaWdub3JlZCAvKjogVW5zdXBwb3J0ZWRFbmNvZGluZ0V4Y2VwdGlvbiovKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbGVuZ3RoID0gYnl0ZXMubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKGxlbmd0aCAlIDIgIT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAyKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYnl0ZTEgPSBieXRlc1tpXSAmIDB4RkY7XG4gICAgICAgICAgICAgICAgaWYgKChieXRlMSA8IDB4ODEgfHwgYnl0ZTEgPiAweDlGKSAmJiAoYnl0ZTEgPCAweEUwIHx8IGJ5dGUxID4gMHhFQikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBjaG9vc2VNYXNrUGF0dGVybihiaXRzLCBlY0xldmVsLCB2ZXJzaW9uLCBtYXRyaXgpIHtcbiAgICAgICAgICAgIGxldCBtaW5QZW5hbHR5ID0gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVI7IC8vIExvd2VyIHBlbmFsdHkgaXMgYmV0dGVyLlxuICAgICAgICAgICAgbGV0IGJlc3RNYXNrUGF0dGVybiA9IC0xO1xuICAgICAgICAgICAgLy8gV2UgdHJ5IGFsbCBtYXNrIHBhdHRlcm5zIHRvIGNob29zZSB0aGUgYmVzdCBvbmUuXG4gICAgICAgICAgICBmb3IgKGxldCBtYXNrUGF0dGVybiA9IDA7IG1hc2tQYXR0ZXJuIDwgUVJDb2RlLk5VTV9NQVNLX1BBVFRFUk5TOyBtYXNrUGF0dGVybisrKSB7XG4gICAgICAgICAgICAgICAgTWF0cml4VXRpbC5idWlsZE1hdHJpeChiaXRzLCBlY0xldmVsLCB2ZXJzaW9uLCBtYXNrUGF0dGVybiwgbWF0cml4KTtcbiAgICAgICAgICAgICAgICBsZXQgcGVuYWx0eSA9IHRoaXMuY2FsY3VsYXRlTWFza1BlbmFsdHkobWF0cml4KTtcbiAgICAgICAgICAgICAgICBpZiAocGVuYWx0eSA8IG1pblBlbmFsdHkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWluUGVuYWx0eSA9IHBlbmFsdHk7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RNYXNrUGF0dGVybiA9IG1hc2tQYXR0ZXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBiZXN0TWFza1BhdHRlcm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGNob29zZVZlcnNpb24obnVtSW5wdXRCaXRzIC8qaW50Ki8sIGVjTGV2ZWwpIHtcbiAgICAgICAgICAgIGZvciAobGV0IHZlcnNpb25OdW0gPSAxOyB2ZXJzaW9uTnVtIDw9IDQwOyB2ZXJzaW9uTnVtKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCB2ZXJzaW9uID0gVmVyc2lvbiQxLmdldFZlcnNpb25Gb3JOdW1iZXIodmVyc2lvbk51bSk7XG4gICAgICAgICAgICAgICAgaWYgKEVuY29kZXIud2lsbEZpdChudW1JbnB1dEJpdHMsIHZlcnNpb24sIGVjTGV2ZWwpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2ZXJzaW9uO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oJ0RhdGEgdG9vIGJpZycpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHRydWUgaWYgdGhlIG51bWJlciBvZiBpbnB1dCBiaXRzIHdpbGwgZml0IGluIGEgY29kZSB3aXRoIHRoZSBzcGVjaWZpZWQgdmVyc2lvbiBhbmRcbiAgICAgICAgICogZXJyb3IgY29ycmVjdGlvbiBsZXZlbC5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyB3aWxsRml0KG51bUlucHV0Qml0cyAvKmludCovLCB2ZXJzaW9uLCBlY0xldmVsKSB7XG4gICAgICAgICAgICAvLyBJbiB0aGUgZm9sbG93aW5nIGNvbW1lbnRzLCB3ZSB1c2UgbnVtYmVycyBvZiBWZXJzaW9uIDctSC5cbiAgICAgICAgICAgIC8vIG51bUJ5dGVzID0gMTk2XG4gICAgICAgICAgICBjb25zdCBudW1CeXRlcyA9IHZlcnNpb24uZ2V0VG90YWxDb2Rld29yZHMoKTtcbiAgICAgICAgICAgIC8vIGdldE51bUVDQnl0ZXMgPSAxMzBcbiAgICAgICAgICAgIGNvbnN0IGVjQmxvY2tzID0gdmVyc2lvbi5nZXRFQ0Jsb2Nrc0ZvckxldmVsKGVjTGV2ZWwpO1xuICAgICAgICAgICAgY29uc3QgbnVtRWNCeXRlcyA9IGVjQmxvY2tzLmdldFRvdGFsRUNDb2Rld29yZHMoKTtcbiAgICAgICAgICAgIC8vIGdldE51bURhdGFCeXRlcyA9IDE5NiAtIDEzMCA9IDY2XG4gICAgICAgICAgICBjb25zdCBudW1EYXRhQnl0ZXMgPSBudW1CeXRlcyAtIG51bUVjQnl0ZXM7XG4gICAgICAgICAgICBjb25zdCB0b3RhbElucHV0Qnl0ZXMgPSAobnVtSW5wdXRCaXRzICsgNykgLyA4O1xuICAgICAgICAgICAgcmV0dXJuIG51bURhdGFCeXRlcyA+PSB0b3RhbElucHV0Qnl0ZXM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRlcm1pbmF0ZSBiaXRzIGFzIGRlc2NyaWJlZCBpbiA4LjQuOCBhbmQgOC40Ljkgb2YgSklTWDA1MTA6MjAwNCAocC4yNCkuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgdGVybWluYXRlQml0cyhudW1EYXRhQnl0ZXMgLyppbnQqLywgYml0cykge1xuICAgICAgICAgICAgY29uc3QgY2FwYWNpdHkgPSBudW1EYXRhQnl0ZXMgKiA4O1xuICAgICAgICAgICAgaWYgKGJpdHMuZ2V0U2l6ZSgpID4gY2FwYWNpdHkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKCdkYXRhIGJpdHMgY2Fubm90IGZpdCBpbiB0aGUgUVIgQ29kZScgKyBiaXRzLmdldFNpemUoKSArICcgPiAnICtcbiAgICAgICAgICAgICAgICAgICAgY2FwYWNpdHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCA0ICYmIGJpdHMuZ2V0U2l6ZSgpIDwgY2FwYWNpdHk7ICsraSkge1xuICAgICAgICAgICAgICAgIGJpdHMuYXBwZW5kQml0KGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEFwcGVuZCB0ZXJtaW5hdGlvbiBiaXRzLiBTZWUgOC40Ljggb2YgSklTWDA1MTA6MjAwNCAocC4yNCkgZm9yIGRldGFpbHMuXG4gICAgICAgICAgICAvLyBJZiB0aGUgbGFzdCBieXRlIGlzbid0IDgtYml0IGFsaWduZWQsIHdlJ2xsIGFkZCBwYWRkaW5nIGJpdHMuXG4gICAgICAgICAgICBjb25zdCBudW1CaXRzSW5MYXN0Qnl0ZSA9IGJpdHMuZ2V0U2l6ZSgpICYgMHgwNztcbiAgICAgICAgICAgIGlmIChudW1CaXRzSW5MYXN0Qnl0ZSA+IDApIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gbnVtQml0c0luTGFzdEJ5dGU7IGkgPCA4OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgYml0cy5hcHBlbmRCaXQoZmFsc2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIElmIHdlIGhhdmUgbW9yZSBzcGFjZSwgd2UnbGwgZmlsbCB0aGUgc3BhY2Ugd2l0aCBwYWRkaW5nIHBhdHRlcm5zIGRlZmluZWQgaW4gOC40LjkgKHAuMjQpLlxuICAgICAgICAgICAgY29uc3QgbnVtUGFkZGluZ0J5dGVzID0gbnVtRGF0YUJ5dGVzIC0gYml0cy5nZXRTaXplSW5CeXRlcygpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1QYWRkaW5nQnl0ZXM7ICsraSkge1xuICAgICAgICAgICAgICAgIGJpdHMuYXBwZW5kQml0cygoaSAmIDB4MDEpID09PSAwID8gMHhFQyA6IDB4MTEsIDgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGJpdHMuZ2V0U2l6ZSgpICE9PSBjYXBhY2l0eSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oJ0JpdHMgc2l6ZSBkb2VzIG5vdCBlcXVhbCBjYXBhY2l0eScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHZXQgbnVtYmVyIG9mIGRhdGEgYnl0ZXMgYW5kIG51bWJlciBvZiBlcnJvciBjb3JyZWN0aW9uIGJ5dGVzIGZvciBibG9jayBpZCBcImJsb2NrSURcIi4gU3RvcmVcbiAgICAgICAgICogdGhlIHJlc3VsdCBpbiBcIm51bURhdGFCeXRlc0luQmxvY2tcIiwgYW5kIFwibnVtRUNCeXRlc0luQmxvY2tcIi4gU2VlIHRhYmxlIDEyIGluIDguNS4xIG9mXG4gICAgICAgICAqIEpJU1gwNTEwOjIwMDQgKHAuMzApXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZ2V0TnVtRGF0YUJ5dGVzQW5kTnVtRUNCeXRlc0ZvckJsb2NrSUQobnVtVG90YWxCeXRlcyAvKmludCovLCBudW1EYXRhQnl0ZXMgLyppbnQqLywgbnVtUlNCbG9ja3MgLyppbnQqLywgYmxvY2tJRCAvKmludCovLCBudW1EYXRhQnl0ZXNJbkJsb2NrLCBudW1FQ0J5dGVzSW5CbG9jaykge1xuICAgICAgICAgICAgaWYgKGJsb2NrSUQgPj0gbnVtUlNCbG9ja3MpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKCdCbG9jayBJRCB0b28gbGFyZ2UnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIG51bVJzQmxvY2tzSW5Hcm91cDIgPSAxOTYgJSA1ID0gMVxuICAgICAgICAgICAgY29uc3QgbnVtUnNCbG9ja3NJbkdyb3VwMiA9IG51bVRvdGFsQnl0ZXMgJSBudW1SU0Jsb2NrcztcbiAgICAgICAgICAgIC8vIG51bVJzQmxvY2tzSW5Hcm91cDEgPSA1IC0gMSA9IDRcbiAgICAgICAgICAgIGNvbnN0IG51bVJzQmxvY2tzSW5Hcm91cDEgPSBudW1SU0Jsb2NrcyAtIG51bVJzQmxvY2tzSW5Hcm91cDI7XG4gICAgICAgICAgICAvLyBudW1Ub3RhbEJ5dGVzSW5Hcm91cDEgPSAxOTYgLyA1ID0gMzlcbiAgICAgICAgICAgIGNvbnN0IG51bVRvdGFsQnl0ZXNJbkdyb3VwMSA9IE1hdGguZmxvb3IobnVtVG90YWxCeXRlcyAvIG51bVJTQmxvY2tzKTtcbiAgICAgICAgICAgIC8vIG51bVRvdGFsQnl0ZXNJbkdyb3VwMiA9IDM5ICsgMSA9IDQwXG4gICAgICAgICAgICBjb25zdCBudW1Ub3RhbEJ5dGVzSW5Hcm91cDIgPSBudW1Ub3RhbEJ5dGVzSW5Hcm91cDEgKyAxO1xuICAgICAgICAgICAgLy8gbnVtRGF0YUJ5dGVzSW5Hcm91cDEgPSA2NiAvIDUgPSAxM1xuICAgICAgICAgICAgY29uc3QgbnVtRGF0YUJ5dGVzSW5Hcm91cDEgPSBNYXRoLmZsb29yKG51bURhdGFCeXRlcyAvIG51bVJTQmxvY2tzKTtcbiAgICAgICAgICAgIC8vIG51bURhdGFCeXRlc0luR3JvdXAyID0gMTMgKyAxID0gMTRcbiAgICAgICAgICAgIGNvbnN0IG51bURhdGFCeXRlc0luR3JvdXAyID0gbnVtRGF0YUJ5dGVzSW5Hcm91cDEgKyAxO1xuICAgICAgICAgICAgLy8gbnVtRWNCeXRlc0luR3JvdXAxID0gMzkgLSAxMyA9IDI2XG4gICAgICAgICAgICBjb25zdCBudW1FY0J5dGVzSW5Hcm91cDEgPSBudW1Ub3RhbEJ5dGVzSW5Hcm91cDEgLSBudW1EYXRhQnl0ZXNJbkdyb3VwMTtcbiAgICAgICAgICAgIC8vIG51bUVjQnl0ZXNJbkdyb3VwMiA9IDQwIC0gMTQgPSAyNlxuICAgICAgICAgICAgY29uc3QgbnVtRWNCeXRlc0luR3JvdXAyID0gbnVtVG90YWxCeXRlc0luR3JvdXAyIC0gbnVtRGF0YUJ5dGVzSW5Hcm91cDI7XG4gICAgICAgICAgICAvLyBTYW5pdHkgY2hlY2tzLlxuICAgICAgICAgICAgLy8gMjYgPSAyNlxuICAgICAgICAgICAgaWYgKG51bUVjQnl0ZXNJbkdyb3VwMSAhPT0gbnVtRWNCeXRlc0luR3JvdXAyKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdyaXRlckV4Y2VwdGlvbignRUMgYnl0ZXMgbWlzbWF0Y2gnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIDUgPSA0ICsgMS5cbiAgICAgICAgICAgIGlmIChudW1SU0Jsb2NrcyAhPT0gbnVtUnNCbG9ja3NJbkdyb3VwMSArIG51bVJzQmxvY2tzSW5Hcm91cDIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKCdSUyBibG9ja3MgbWlzbWF0Y2gnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIDE5NiA9ICgxMyArIDI2KSAqIDQgKyAoMTQgKyAyNikgKiAxXG4gICAgICAgICAgICBpZiAobnVtVG90YWxCeXRlcyAhPT1cbiAgICAgICAgICAgICAgICAoKG51bURhdGFCeXRlc0luR3JvdXAxICsgbnVtRWNCeXRlc0luR3JvdXAxKSAqXG4gICAgICAgICAgICAgICAgICAgIG51bVJzQmxvY2tzSW5Hcm91cDEpICtcbiAgICAgICAgICAgICAgICAgICAgKChudW1EYXRhQnl0ZXNJbkdyb3VwMiArIG51bUVjQnl0ZXNJbkdyb3VwMikgKlxuICAgICAgICAgICAgICAgICAgICAgICAgbnVtUnNCbG9ja3NJbkdyb3VwMikpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKCdUb3RhbCBieXRlcyBtaXNtYXRjaCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGJsb2NrSUQgPCBudW1Sc0Jsb2Nrc0luR3JvdXAxKSB7XG4gICAgICAgICAgICAgICAgbnVtRGF0YUJ5dGVzSW5CbG9ja1swXSA9IG51bURhdGFCeXRlc0luR3JvdXAxO1xuICAgICAgICAgICAgICAgIG51bUVDQnl0ZXNJbkJsb2NrWzBdID0gbnVtRWNCeXRlc0luR3JvdXAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbnVtRGF0YUJ5dGVzSW5CbG9ja1swXSA9IG51bURhdGFCeXRlc0luR3JvdXAyO1xuICAgICAgICAgICAgICAgIG51bUVDQnl0ZXNJbkJsb2NrWzBdID0gbnVtRWNCeXRlc0luR3JvdXAyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJbnRlcmxlYXZlIFwiYml0c1wiIHdpdGggY29ycmVzcG9uZGluZyBlcnJvciBjb3JyZWN0aW9uIGJ5dGVzLiBPbiBzdWNjZXNzLCBzdG9yZSB0aGUgcmVzdWx0IGluXG4gICAgICAgICAqIFwicmVzdWx0XCIuIFRoZSBpbnRlcmxlYXZlIHJ1bGUgaXMgY29tcGxpY2F0ZWQuIFNlZSA4LjYgb2YgSklTWDA1MTA6MjAwNCAocC4zNykgZm9yIGRldGFpbHMuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgaW50ZXJsZWF2ZVdpdGhFQ0J5dGVzKGJpdHMsIG51bVRvdGFsQnl0ZXMgLyppbnQqLywgbnVtRGF0YUJ5dGVzIC8qaW50Ki8sIG51bVJTQmxvY2tzIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIC8vIFwiYml0c1wiIG11c3QgaGF2ZSBcImdldE51bURhdGFCeXRlc1wiIGJ5dGVzIG9mIGRhdGEuXG4gICAgICAgICAgICBpZiAoYml0cy5nZXRTaXplSW5CeXRlcygpICE9PSBudW1EYXRhQnl0ZXMpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKCdOdW1iZXIgb2YgYml0cyBhbmQgZGF0YSBieXRlcyBkb2VzIG5vdCBtYXRjaCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gU3RlcCAxLiAgRGl2aWRlIGRhdGEgYnl0ZXMgaW50byBibG9ja3MgYW5kIGdlbmVyYXRlIGVycm9yIGNvcnJlY3Rpb24gYnl0ZXMgZm9yIHRoZW0uIFdlJ2xsXG4gICAgICAgICAgICAvLyBzdG9yZSB0aGUgZGl2aWRlZCBkYXRhIGJ5dGVzIGJsb2NrcyBhbmQgZXJyb3IgY29ycmVjdGlvbiBieXRlcyBibG9ja3MgaW50byBcImJsb2Nrc1wiLlxuICAgICAgICAgICAgbGV0IGRhdGFCeXRlc09mZnNldCA9IDA7XG4gICAgICAgICAgICBsZXQgbWF4TnVtRGF0YUJ5dGVzID0gMDtcbiAgICAgICAgICAgIGxldCBtYXhOdW1FY0J5dGVzID0gMDtcbiAgICAgICAgICAgIC8vIFNpbmNlLCB3ZSBrbm93IHRoZSBudW1iZXIgb2YgcmVlZHNvbG1vbiBibG9ja3MsIHdlIGNhbiBpbml0aWFsaXplIHRoZSB2ZWN0b3Igd2l0aCB0aGUgbnVtYmVyLlxuICAgICAgICAgICAgY29uc3QgYmxvY2tzID0gbmV3IEFycmF5KCk7IC8vIG5ldyBBcnJheTxCbG9ja1BhaXI+KG51bVJTQmxvY2tzKVxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1SU0Jsb2NrczsgKytpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbnVtRGF0YUJ5dGVzSW5CbG9jayA9IG5ldyBJbnQzMkFycmF5KDEpO1xuICAgICAgICAgICAgICAgIGNvbnN0IG51bUVjQnl0ZXNJbkJsb2NrID0gbmV3IEludDMyQXJyYXkoMSk7XG4gICAgICAgICAgICAgICAgRW5jb2Rlci5nZXROdW1EYXRhQnl0ZXNBbmROdW1FQ0J5dGVzRm9yQmxvY2tJRChudW1Ub3RhbEJ5dGVzLCBudW1EYXRhQnl0ZXMsIG51bVJTQmxvY2tzLCBpLCBudW1EYXRhQnl0ZXNJbkJsb2NrLCBudW1FY0J5dGVzSW5CbG9jayk7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IG51bURhdGFCeXRlc0luQmxvY2tbMF07XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0YUJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoc2l6ZSk7XG4gICAgICAgICAgICAgICAgYml0cy50b0J5dGVzKDggKiBkYXRhQnl0ZXNPZmZzZXQsIGRhdGFCeXRlcywgMCwgc2l6ZSk7XG4gICAgICAgICAgICAgICAgY29uc3QgZWNCeXRlcyA9IEVuY29kZXIuZ2VuZXJhdGVFQ0J5dGVzKGRhdGFCeXRlcywgbnVtRWNCeXRlc0luQmxvY2tbMF0pO1xuICAgICAgICAgICAgICAgIGJsb2Nrcy5wdXNoKG5ldyBCbG9ja1BhaXIoZGF0YUJ5dGVzLCBlY0J5dGVzKSk7XG4gICAgICAgICAgICAgICAgbWF4TnVtRGF0YUJ5dGVzID0gTWF0aC5tYXgobWF4TnVtRGF0YUJ5dGVzLCBzaXplKTtcbiAgICAgICAgICAgICAgICBtYXhOdW1FY0J5dGVzID0gTWF0aC5tYXgobWF4TnVtRWNCeXRlcywgZWNCeXRlcy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIGRhdGFCeXRlc09mZnNldCArPSBudW1EYXRhQnl0ZXNJbkJsb2NrWzBdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG51bURhdGFCeXRlcyAhPT0gZGF0YUJ5dGVzT2Zmc2V0KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdyaXRlckV4Y2VwdGlvbignRGF0YSBieXRlcyBkb2VzIG5vdCBtYXRjaCBvZmZzZXQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBCaXRBcnJheSgpO1xuICAgICAgICAgICAgLy8gRmlyc3QsIHBsYWNlIGRhdGEgYmxvY2tzLlxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXhOdW1EYXRhQnl0ZXM7ICsraSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgYmxvY2sgb2YgYmxvY2tzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGFCeXRlcyA9IGJsb2NrLmdldERhdGFCeXRlcygpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSA8IGRhdGFCeXRlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmRCaXRzKGRhdGFCeXRlc1tpXSwgOCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBUaGVuLCBwbGFjZSBlcnJvciBjb3JyZWN0aW9uIGJsb2Nrcy5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbWF4TnVtRWNCeXRlczsgKytpKSB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBibG9jayBvZiBibG9ja3MpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZWNCeXRlcyA9IGJsb2NrLmdldEVycm9yQ29ycmVjdGlvbkJ5dGVzKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpIDwgZWNCeXRlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcHBlbmRCaXRzKGVjQnl0ZXNbaV0sIDgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG51bVRvdGFsQnl0ZXMgIT09IHJlc3VsdC5nZXRTaXplSW5CeXRlcygpKSB7IC8vIFNob3VsZCBiZSBzYW1lLlxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oJ0ludGVybGVhdmluZyBlcnJvcjogJyArIG51bVRvdGFsQnl0ZXMgKyAnIGFuZCAnICtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmdldFNpemVJbkJ5dGVzKCkgKyAnIGRpZmZlci4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGdlbmVyYXRlRUNCeXRlcyhkYXRhQnl0ZXMsIG51bUVjQnl0ZXNJbkJsb2NrIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IG51bURhdGFCeXRlcyA9IGRhdGFCeXRlcy5sZW5ndGg7XG4gICAgICAgICAgICBjb25zdCB0b0VuY29kZSA9IG5ldyBJbnQzMkFycmF5KG51bURhdGFCeXRlcyArIG51bUVjQnl0ZXNJbkJsb2NrKTsgLy8gaW50W251bURhdGFCeXRlcyArIG51bUVjQnl0ZXNJbkJsb2NrXVxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1EYXRhQnl0ZXM7IGkrKykge1xuICAgICAgICAgICAgICAgIHRvRW5jb2RlW2ldID0gZGF0YUJ5dGVzW2ldICYgMHhGRjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5ldyBSZWVkU29sb21vbkVuY29kZXIoR2VuZXJpY0dGLlFSX0NPREVfRklFTERfMjU2KS5lbmNvZGUodG9FbmNvZGUsIG51bUVjQnl0ZXNJbkJsb2NrKTtcbiAgICAgICAgICAgIGNvbnN0IGVjQnl0ZXMgPSBuZXcgVWludDhBcnJheShudW1FY0J5dGVzSW5CbG9jayk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUVjQnl0ZXNJbkJsb2NrOyBpKyspIHtcbiAgICAgICAgICAgICAgICBlY0J5dGVzW2ldID0gLyooYnl0ZSkgKi8gdG9FbmNvZGVbbnVtRGF0YUJ5dGVzICsgaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZWNCeXRlcztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQXBwZW5kIG1vZGUgaW5mby4gT24gc3VjY2Vzcywgc3RvcmUgdGhlIHJlc3VsdCBpbiBcImJpdHNcIi5cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBhcHBlbmRNb2RlSW5mbyhtb2RlLCBiaXRzKSB7XG4gICAgICAgICAgICBiaXRzLmFwcGVuZEJpdHMobW9kZS5nZXRCaXRzKCksIDQpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBcHBlbmQgbGVuZ3RoIGluZm8uIE9uIHN1Y2Nlc3MsIHN0b3JlIHRoZSByZXN1bHQgaW4gXCJiaXRzXCIuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgYXBwZW5kTGVuZ3RoSW5mbyhudW1MZXR0ZXJzIC8qaW50Ki8sIHZlcnNpb24sIG1vZGUsIGJpdHMpIHtcbiAgICAgICAgICAgIGNvbnN0IG51bUJpdHMgPSBtb2RlLmdldENoYXJhY3RlckNvdW50Qml0cyh2ZXJzaW9uKTtcbiAgICAgICAgICAgIGlmIChudW1MZXR0ZXJzID49ICgxIDw8IG51bUJpdHMpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdyaXRlckV4Y2VwdGlvbihudW1MZXR0ZXJzICsgJyBpcyBiaWdnZXIgdGhhbiAnICsgKCgxIDw8IG51bUJpdHMpIC0gMSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYml0cy5hcHBlbmRCaXRzKG51bUxldHRlcnMsIG51bUJpdHMpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBcHBlbmQgXCJieXRlc1wiIGluIFwibW9kZVwiIG1vZGUgKGVuY29kaW5nKSBpbnRvIFwiYml0c1wiLiBPbiBzdWNjZXNzLCBzdG9yZSB0aGUgcmVzdWx0IGluIFwiYml0c1wiLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGFwcGVuZEJ5dGVzKGNvbnRlbnQsIG1vZGUsIGJpdHMsIGVuY29kaW5nKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKG1vZGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIE1vZGUkMS5OVU1FUklDOlxuICAgICAgICAgICAgICAgICAgICBFbmNvZGVyLmFwcGVuZE51bWVyaWNCeXRlcyhjb250ZW50LCBiaXRzKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBNb2RlJDEuQUxQSEFOVU1FUklDOlxuICAgICAgICAgICAgICAgICAgICBFbmNvZGVyLmFwcGVuZEFscGhhbnVtZXJpY0J5dGVzKGNvbnRlbnQsIGJpdHMpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIE1vZGUkMS5CWVRFOlxuICAgICAgICAgICAgICAgICAgICBFbmNvZGVyLmFwcGVuZDhCaXRCeXRlcyhjb250ZW50LCBiaXRzLCBlbmNvZGluZyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgTW9kZSQxLktBTkpJOlxuICAgICAgICAgICAgICAgICAgICBFbmNvZGVyLmFwcGVuZEthbmppQnl0ZXMoY29udGVudCwgYml0cyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oJ0ludmFsaWQgbW9kZTogJyArIG1vZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZXREaWdpdChzaW5nbGVDaGFyYWN0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBzaW5nbGVDaGFyYWN0ZXIuY2hhckNvZGVBdCgwKSAtIDQ4O1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBpc0RpZ2l0KHNpbmdsZUNoYXJhY3Rlcikge1xuICAgICAgICAgICAgY29uc3QgY24gPSBFbmNvZGVyLmdldERpZ2l0KHNpbmdsZUNoYXJhY3Rlcik7XG4gICAgICAgICAgICByZXR1cm4gY24gPj0gMCAmJiBjbiA8PSA5O1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBhcHBlbmROdW1lcmljQnl0ZXMoY29udGVudCwgYml0cykge1xuICAgICAgICAgICAgY29uc3QgbGVuZ3RoID0gY29udGVudC5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgaSA9IDA7XG4gICAgICAgICAgICB3aGlsZSAoaSA8IGxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG51bTEgPSBFbmNvZGVyLmdldERpZ2l0KGNvbnRlbnQuY2hhckF0KGkpKTtcbiAgICAgICAgICAgICAgICBpZiAoaSArIDIgPCBsZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRW5jb2RlIHRocmVlIG51bWVyaWMgbGV0dGVycyBpbiB0ZW4gYml0cy5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbnVtMiA9IEVuY29kZXIuZ2V0RGlnaXQoY29udGVudC5jaGFyQXQoaSArIDEpKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbnVtMyA9IEVuY29kZXIuZ2V0RGlnaXQoY29udGVudC5jaGFyQXQoaSArIDIpKTtcbiAgICAgICAgICAgICAgICAgICAgYml0cy5hcHBlbmRCaXRzKG51bTEgKiAxMDAgKyBudW0yICogMTAgKyBudW0zLCAxMCk7XG4gICAgICAgICAgICAgICAgICAgIGkgKz0gMztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoaSArIDEgPCBsZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRW5jb2RlIHR3byBudW1lcmljIGxldHRlcnMgaW4gc2V2ZW4gYml0cy5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbnVtMiA9IEVuY29kZXIuZ2V0RGlnaXQoY29udGVudC5jaGFyQXQoaSArIDEpKTtcbiAgICAgICAgICAgICAgICAgICAgYml0cy5hcHBlbmRCaXRzKG51bTEgKiAxMCArIG51bTIsIDcpO1xuICAgICAgICAgICAgICAgICAgICBpICs9IDI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBFbmNvZGUgb25lIG51bWVyaWMgbGV0dGVyIGluIGZvdXIgYml0cy5cbiAgICAgICAgICAgICAgICAgICAgYml0cy5hcHBlbmRCaXRzKG51bTEsIDQpO1xuICAgICAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBhcHBlbmRBbHBoYW51bWVyaWNCeXRlcyhjb250ZW50LCBiaXRzKSB7XG4gICAgICAgICAgICBjb25zdCBsZW5ndGggPSBjb250ZW50Lmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBpID0gMDtcbiAgICAgICAgICAgIHdoaWxlIChpIDwgbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29kZTEgPSBFbmNvZGVyLmdldEFscGhhbnVtZXJpY0NvZGUoY29udGVudC5jaGFyQ29kZUF0KGkpKTtcbiAgICAgICAgICAgICAgICBpZiAoY29kZTEgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGkgKyAxIDwgbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvZGUyID0gRW5jb2Rlci5nZXRBbHBoYW51bWVyaWNDb2RlKGNvbnRlbnQuY2hhckNvZGVBdChpICsgMSkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29kZTIgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV3JpdGVyRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gRW5jb2RlIHR3byBhbHBoYW51bWVyaWMgbGV0dGVycyBpbiAxMSBiaXRzLlxuICAgICAgICAgICAgICAgICAgICBiaXRzLmFwcGVuZEJpdHMoY29kZTEgKiA0NSArIGNvZGUyLCAxMSk7XG4gICAgICAgICAgICAgICAgICAgIGkgKz0gMjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEVuY29kZSBvbmUgYWxwaGFudW1lcmljIGxldHRlciBpbiBzaXggYml0cy5cbiAgICAgICAgICAgICAgICAgICAgYml0cy5hcHBlbmRCaXRzKGNvZGUxLCA2KTtcbiAgICAgICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgYXBwZW5kOEJpdEJ5dGVzKGNvbnRlbnQsIGJpdHMsIGVuY29kaW5nKSB7XG4gICAgICAgICAgICBsZXQgYnl0ZXM7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGJ5dGVzID0gU3RyaW5nRW5jb2RpbmcuZW5jb2RlKGNvbnRlbnQsIGVuY29kaW5nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoICh1ZWUgLyo6IFVuc3VwcG9ydGVkRW5jb2RpbmdFeGNlcHRpb24qLykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBXcml0ZXJFeGNlcHRpb24odWVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBsZW5ndGggPSBieXRlcy5sZW5ndGg7IGkgIT09IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYiA9IGJ5dGVzW2ldO1xuICAgICAgICAgICAgICAgIGJpdHMuYXBwZW5kQml0cyhiLCA4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHRocm93cyBXcml0ZXJFeGNlcHRpb25cbiAgICAgICAgICovXG4gICAgICAgIHN0YXRpYyBhcHBlbmRLYW5qaUJ5dGVzKGNvbnRlbnQsIGJpdHMpIHtcbiAgICAgICAgICAgIGxldCBieXRlcztcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYnl0ZXMgPSBTdHJpbmdFbmNvZGluZy5lbmNvZGUoY29udGVudCwgQ2hhcmFjdGVyU2V0RUNJLlNKSVMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKHVlZSAvKjogVW5zdXBwb3J0ZWRFbmNvZGluZ0V4Y2VwdGlvbiovKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdyaXRlckV4Y2VwdGlvbih1ZWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbGVuZ3RoID0gYnl0ZXMubGVuZ3RoO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMikge1xuICAgICAgICAgICAgICAgIGNvbnN0IGJ5dGUxID0gYnl0ZXNbaV0gJiAweEZGO1xuICAgICAgICAgICAgICAgIGNvbnN0IGJ5dGUyID0gYnl0ZXNbaSArIDFdICYgMHhGRjtcbiAgICAgICAgICAgICAgICBjb25zdCBjb2RlID0gKChieXRlMSA8PCA4KSAmIDB4RkZGRkZGRkYpIHwgYnl0ZTI7XG4gICAgICAgICAgICAgICAgbGV0IHN1YnRyYWN0ZWQgPSAtMTtcbiAgICAgICAgICAgICAgICBpZiAoY29kZSA+PSAweDgxNDAgJiYgY29kZSA8PSAweDlmZmMpIHtcbiAgICAgICAgICAgICAgICAgICAgc3VidHJhY3RlZCA9IGNvZGUgLSAweDgxNDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGNvZGUgPj0gMHhlMDQwICYmIGNvZGUgPD0gMHhlYmJmKSB7XG4gICAgICAgICAgICAgICAgICAgIHN1YnRyYWN0ZWQgPSBjb2RlIC0gMHhjMTQwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoc3VidHJhY3RlZCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdyaXRlckV4Y2VwdGlvbignSW52YWxpZCBieXRlIHNlcXVlbmNlJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGVuY29kZWQgPSAoKHN1YnRyYWN0ZWQgPj4gOCkgKiAweGMwKSArIChzdWJ0cmFjdGVkICYgMHhmZik7XG4gICAgICAgICAgICAgICAgYml0cy5hcHBlbmRCaXRzKGVuY29kZWQsIDEzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgYXBwZW5kRUNJKGVjaSwgYml0cykge1xuICAgICAgICAgICAgYml0cy5hcHBlbmRCaXRzKE1vZGUkMS5FQ0kuZ2V0Qml0cygpLCA0KTtcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgY29ycmVjdCBmb3IgdmFsdWVzIHVwIHRvIDEyNywgd2hpY2ggaXMgYWxsIHdlIG5lZWQgbm93LlxuICAgICAgICAgICAgYml0cy5hcHBlbmRCaXRzKGVjaS5nZXRWYWx1ZSgpLCA4KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBUaGUgb3JpZ2luYWwgdGFibGUgaXMgZGVmaW5lZCBpbiB0aGUgdGFibGUgNSBvZiBKSVNYMDUxMDoyMDA0IChwLjE5KS5cbiAgICBFbmNvZGVyLkFMUEhBTlVNRVJJQ19UQUJMRSA9IEludDMyQXJyYXkuZnJvbShbXG4gICAgICAgIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLFxuICAgICAgICAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSxcbiAgICAgICAgMzYsIC0xLCAtMSwgLTEsIDM3LCAzOCwgLTEsIC0xLCAtMSwgLTEsIDM5LCA0MCwgLTEsIDQxLCA0MiwgNDMsXG4gICAgICAgIDAsIDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsIDksIDQ0LCAtMSwgLTEsIC0xLCAtMSwgLTEsXG4gICAgICAgIC0xLCAxMCwgMTEsIDEyLCAxMywgMTQsIDE1LCAxNiwgMTcsIDE4LCAxOSwgMjAsIDIxLCAyMiwgMjMsIDI0LFxuICAgICAgICAyNSwgMjYsIDI3LCAyOCwgMjksIDMwLCAzMSwgMzIsIDMzLCAzNCwgMzUsIC0xLCAtMSwgLTEsIC0xLCAtMSxcbiAgICBdKTtcbiAgICBFbmNvZGVyLkRFRkFVTFRfQllURV9NT0RFX0VOQ09ESU5HID0gQ2hhcmFjdGVyU2V0RUNJLlVURjguZ2V0TmFtZSgpOyAvLyBcIklTTy04ODU5LTFcIlxuXG4gICAgLyoqXG4gICAgICogQGRlcHJlY2F0ZWQgTW92aW5nIHRvIEB6eGluZy9icm93c2VyXG4gICAgICovXG4gICAgY2xhc3MgQnJvd3NlclFSQ29kZVN2Z1dyaXRlciB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXcml0ZXMgYW5kIHJlbmRlcnMgYSBRUkNvZGUgU1ZHIGVsZW1lbnQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBjb250ZW50c1xuICAgICAgICAgKiBAcGFyYW0gd2lkdGhcbiAgICAgICAgICogQHBhcmFtIGhlaWdodFxuICAgICAgICAgKiBAcGFyYW0gaGludHNcbiAgICAgICAgICovXG4gICAgICAgIHdyaXRlKGNvbnRlbnRzLCB3aWR0aCwgaGVpZ2h0LCBoaW50cyA9IG51bGwpIHtcbiAgICAgICAgICAgIGlmIChjb250ZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdGb3VuZCBlbXB0eSBjb250ZW50cycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gaWYgKGZvcm1hdCAhPSBCYXJjb2RlRm9ybWF0LlFSX0NPREUpIHtcbiAgICAgICAgICAgIC8vICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbihcIkNhbiBvbmx5IGVuY29kZSBRUl9DT0RFLCBidXQgZ290IFwiICsgZm9ybWF0KVxuICAgICAgICAgICAgLy8gfVxuICAgICAgICAgICAgaWYgKHdpZHRoIDwgMCB8fCBoZWlnaHQgPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignUmVxdWVzdGVkIGRpbWVuc2lvbnMgYXJlIHRvbyBzbWFsbDogJyArIHdpZHRoICsgJ3gnICsgaGVpZ2h0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBlcnJvckNvcnJlY3Rpb25MZXZlbCA9IEVycm9yQ29ycmVjdGlvbkxldmVsLkw7XG4gICAgICAgICAgICBsZXQgcXVpZXRab25lID0gQnJvd3NlclFSQ29kZVN2Z1dyaXRlci5RVUlFVF9aT05FX1NJWkU7XG4gICAgICAgICAgICBpZiAoaGludHMgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAodW5kZWZpbmVkICE9PSBoaW50cy5nZXQoRW5jb2RlSGludFR5cGUkMS5FUlJPUl9DT1JSRUNUSU9OKSkge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNvcnJlY3Rpb25MZXZlbCA9IEVycm9yQ29ycmVjdGlvbkxldmVsLmZyb21TdHJpbmcoaGludHMuZ2V0KEVuY29kZUhpbnRUeXBlJDEuRVJST1JfQ09SUkVDVElPTikudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh1bmRlZmluZWQgIT09IGhpbnRzLmdldChFbmNvZGVIaW50VHlwZSQxLk1BUkdJTikpIHtcbiAgICAgICAgICAgICAgICAgICAgcXVpZXRab25lID0gTnVtYmVyLnBhcnNlSW50KGhpbnRzLmdldChFbmNvZGVIaW50VHlwZSQxLk1BUkdJTikudG9TdHJpbmcoKSwgMTApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGNvZGUgPSBFbmNvZGVyLmVuY29kZShjb250ZW50cywgZXJyb3JDb3JyZWN0aW9uTGV2ZWwsIGhpbnRzKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlbmRlclJlc3VsdChjb2RlLCB3aWR0aCwgaGVpZ2h0LCBxdWlldFpvbmUpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZW5kZXJzIHRoZSByZXN1bHQgYW5kIHRoZW4gYXBwZW5kcyBpdCB0byB0aGUgRE9NLlxuICAgICAgICAgKi9cbiAgICAgICAgd3JpdGVUb0RvbShjb250YWluZXJFbGVtZW50LCBjb250ZW50cywgd2lkdGgsIGhlaWdodCwgaGludHMgPSBudWxsKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGNvbnRhaW5lckVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyRWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoY29udGFpbmVyRWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBzdmdFbGVtZW50ID0gdGhpcy53cml0ZShjb250ZW50cywgd2lkdGgsIGhlaWdodCwgaGludHMpO1xuICAgICAgICAgICAgaWYgKGNvbnRhaW5lckVsZW1lbnQpXG4gICAgICAgICAgICAgICAgY29udGFpbmVyRWxlbWVudC5hcHBlbmRDaGlsZChzdmdFbGVtZW50KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogTm90ZSB0aGF0IHRoZSBpbnB1dCBtYXRyaXggdXNlcyAwID09IHdoaXRlLCAxID09IGJsYWNrLlxuICAgICAgICAgKiBUaGUgb3V0cHV0IG1hdHJpeCB1c2VzIDAgPT0gYmxhY2ssIDI1NSA9PSB3aGl0ZSAoaS5lLiBhbiA4IGJpdCBncmV5c2NhbGUgYml0bWFwKS5cbiAgICAgICAgICovXG4gICAgICAgIHJlbmRlclJlc3VsdChjb2RlLCB3aWR0aCAvKmludCovLCBoZWlnaHQgLyppbnQqLywgcXVpZXRab25lIC8qaW50Ki8pIHtcbiAgICAgICAgICAgIGNvbnN0IGlucHV0ID0gY29kZS5nZXRNYXRyaXgoKTtcbiAgICAgICAgICAgIGlmIChpbnB1dCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGlucHV0V2lkdGggPSBpbnB1dC5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgY29uc3QgaW5wdXRIZWlnaHQgPSBpbnB1dC5nZXRIZWlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IHFyV2lkdGggPSBpbnB1dFdpZHRoICsgKHF1aWV0Wm9uZSAqIDIpO1xuICAgICAgICAgICAgY29uc3QgcXJIZWlnaHQgPSBpbnB1dEhlaWdodCArIChxdWlldFpvbmUgKiAyKTtcbiAgICAgICAgICAgIGNvbnN0IG91dHB1dFdpZHRoID0gTWF0aC5tYXgod2lkdGgsIHFyV2lkdGgpO1xuICAgICAgICAgICAgY29uc3Qgb3V0cHV0SGVpZ2h0ID0gTWF0aC5tYXgoaGVpZ2h0LCBxckhlaWdodCk7XG4gICAgICAgICAgICBjb25zdCBtdWx0aXBsZSA9IE1hdGgubWluKE1hdGguZmxvb3Iob3V0cHV0V2lkdGggLyBxcldpZHRoKSwgTWF0aC5mbG9vcihvdXRwdXRIZWlnaHQgLyBxckhlaWdodCkpO1xuICAgICAgICAgICAgLy8gUGFkZGluZyBpbmNsdWRlcyBib3RoIHRoZSBxdWlldCB6b25lIGFuZCB0aGUgZXh0cmEgd2hpdGUgcGl4ZWxzIHRvIGFjY29tbW9kYXRlIHRoZSByZXF1ZXN0ZWRcbiAgICAgICAgICAgIC8vIGRpbWVuc2lvbnMuIEZvciBleGFtcGxlLCBpZiBpbnB1dCBpcyAyNXgyNSB0aGUgUVIgd2lsbCBiZSAzM3gzMyBpbmNsdWRpbmcgdGhlIHF1aWV0IHpvbmUuXG4gICAgICAgICAgICAvLyBJZiB0aGUgcmVxdWVzdGVkIHNpemUgaXMgMjAweDE2MCwgdGhlIG11bHRpcGxlIHdpbGwgYmUgNCwgZm9yIGEgUVIgb2YgMTMyeDEzMi4gVGhlc2Ugd2lsbFxuICAgICAgICAgICAgLy8gaGFuZGxlIGFsbCB0aGUgcGFkZGluZyBmcm9tIDEwMHgxMDAgKHRoZSBhY3R1YWwgUVIpIHVwIHRvIDIwMHgxNjAuXG4gICAgICAgICAgICBjb25zdCBsZWZ0UGFkZGluZyA9IE1hdGguZmxvb3IoKG91dHB1dFdpZHRoIC0gKGlucHV0V2lkdGggKiBtdWx0aXBsZSkpIC8gMik7XG4gICAgICAgICAgICBjb25zdCB0b3BQYWRkaW5nID0gTWF0aC5mbG9vcigob3V0cHV0SGVpZ2h0IC0gKGlucHV0SGVpZ2h0ICogbXVsdGlwbGUpKSAvIDIpO1xuICAgICAgICAgICAgY29uc3Qgc3ZnRWxlbWVudCA9IHRoaXMuY3JlYXRlU1ZHRWxlbWVudChvdXRwdXRXaWR0aCwgb3V0cHV0SGVpZ2h0KTtcbiAgICAgICAgICAgIGZvciAobGV0IGlucHV0WSA9IDAsIG91dHB1dFkgPSB0b3BQYWRkaW5nOyBpbnB1dFkgPCBpbnB1dEhlaWdodDsgaW5wdXRZKyssIG91dHB1dFkgKz0gbXVsdGlwbGUpIHtcbiAgICAgICAgICAgICAgICAvLyBXcml0ZSB0aGUgY29udGVudHMgb2YgdGhpcyByb3cgb2YgdGhlIGJhcmNvZGVcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpbnB1dFggPSAwLCBvdXRwdXRYID0gbGVmdFBhZGRpbmc7IGlucHV0WCA8IGlucHV0V2lkdGg7IGlucHV0WCsrLCBvdXRwdXRYICs9IG11bHRpcGxlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dC5nZXQoaW5wdXRYLCBpbnB1dFkpID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdmdSZWN0RWxlbWVudCA9IHRoaXMuY3JlYXRlU3ZnUmVjdEVsZW1lbnQob3V0cHV0WCwgb3V0cHV0WSwgbXVsdGlwbGUsIG11bHRpcGxlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN2Z0VsZW1lbnQuYXBwZW5kQ2hpbGQoc3ZnUmVjdEVsZW1lbnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN2Z0VsZW1lbnQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBTVkcgZWxlbWVudC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHcgU1ZHJ3Mgd2lkdGggYXR0cmlidXRlXG4gICAgICAgICAqIEBwYXJhbSBoIFNWRydzIGhlaWdodCBhdHRyaWJ1dGVcbiAgICAgICAgICovXG4gICAgICAgIGNyZWF0ZVNWR0VsZW1lbnQodywgaCkge1xuICAgICAgICAgICAgY29uc3Qgc3ZnRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhCcm93c2VyUVJDb2RlU3ZnV3JpdGVyLlNWR19OUywgJ3N2ZycpO1xuICAgICAgICAgICAgc3ZnRWxlbWVudC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAnaGVpZ2h0Jywgdy50b1N0cmluZygpKTtcbiAgICAgICAgICAgIHN2Z0VsZW1lbnQuc2V0QXR0cmlidXRlTlMobnVsbCwgJ3dpZHRoJywgaC50b1N0cmluZygpKTtcbiAgICAgICAgICAgIHJldHVybiBzdmdFbGVtZW50O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgU1ZHIHJlY3QgZWxlbWVudC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHggRWxlbWVudCdzIHggY29vcmRpbmF0ZVxuICAgICAgICAgKiBAcGFyYW0geSBFbGVtZW50J3MgeSBjb29yZGluYXRlXG4gICAgICAgICAqIEBwYXJhbSB3IEVsZW1lbnQncyB3aWR0aCBhdHRyaWJ1dGVcbiAgICAgICAgICogQHBhcmFtIGggRWxlbWVudCdzIGhlaWdodCBhdHRyaWJ1dGVcbiAgICAgICAgICovXG4gICAgICAgIGNyZWF0ZVN2Z1JlY3RFbGVtZW50KHgsIHksIHcsIGgpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlY3QgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoQnJvd3NlclFSQ29kZVN2Z1dyaXRlci5TVkdfTlMsICdyZWN0Jyk7XG4gICAgICAgICAgICByZWN0LnNldEF0dHJpYnV0ZU5TKG51bGwsICd4JywgeC50b1N0cmluZygpKTtcbiAgICAgICAgICAgIHJlY3Quc2V0QXR0cmlidXRlTlMobnVsbCwgJ3knLCB5LnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgcmVjdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAnaGVpZ2h0Jywgdy50b1N0cmluZygpKTtcbiAgICAgICAgICAgIHJlY3Quc2V0QXR0cmlidXRlTlMobnVsbCwgJ3dpZHRoJywgaC50b1N0cmluZygpKTtcbiAgICAgICAgICAgIHJlY3Quc2V0QXR0cmlidXRlTlMobnVsbCwgJ2ZpbGwnLCAnIzAwMDAwMCcpO1xuICAgICAgICAgICAgcmV0dXJuIHJlY3Q7XG4gICAgICAgIH1cbiAgICB9XG4gICAgQnJvd3NlclFSQ29kZVN2Z1dyaXRlci5RVUlFVF9aT05FX1NJWkUgPSA0O1xuICAgIC8qKlxuICAgICAqIFNWRyBtYXJrdXAgTmFtZVNwYWNlXG4gICAgICovXG4gICAgQnJvd3NlclFSQ29kZVN2Z1dyaXRlci5TVkdfTlMgPSAnaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnO1xuXG4gICAgLyppbXBvcnQgamF2YS51dGlsLk1hcDsqL1xuICAgIC8qKlxuICAgICAqIFRoaXMgb2JqZWN0IHJlbmRlcnMgYSBRUiBDb2RlIGFzIGEgQml0TWF0cml4IDJEIGFycmF5IG9mIGdyZXlzY2FsZSB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIGRzd2l0a2luQGdvb2dsZS5jb20gKERhbmllbCBTd2l0a2luKVxuICAgICAqL1xuICAgIGNsYXNzIFFSQ29kZVdyaXRlciB7XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgLy8gcHVibGljIGVuY29kZShjb250ZW50czogc3RyaW5nLCBmb3JtYXQ6IEJhcmNvZGVGb3JtYXQsIHdpZHRoOiBudW1iZXIgLyppbnQqLywgaGVpZ2h0OiBudW1iZXIgLyppbnQqLyk6IEJpdE1hdHJpeFxuICAgICAgICAvLyAgICAgLyp0aHJvd3MgV3JpdGVyRXhjZXB0aW9uICovIHtcbiAgICAgICAgLy8gICByZXR1cm4gZW5jb2RlKGNvbnRlbnRzLCBmb3JtYXQsIHdpZHRoLCBoZWlnaHQsIG51bGwpXG4gICAgICAgIC8vIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBlbmNvZGUoY29udGVudHMsIGZvcm1hdCwgd2lkdGggLyppbnQqLywgaGVpZ2h0IC8qaW50Ki8sIGhpbnRzKSB7XG4gICAgICAgICAgICBpZiAoY29udGVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignRm91bmQgZW1wdHkgY29udGVudHMnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmb3JtYXQgIT09IEJhcmNvZGVGb3JtYXQkMS5RUl9DT0RFKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignQ2FuIG9ubHkgZW5jb2RlIFFSX0NPREUsIGJ1dCBnb3QgJyArIGZvcm1hdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAod2lkdGggPCAwIHx8IGhlaWdodCA8IDApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKGBSZXF1ZXN0ZWQgZGltZW5zaW9ucyBhcmUgdG9vIHNtYWxsOiAke3dpZHRofXgke2hlaWdodH1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBlcnJvckNvcnJlY3Rpb25MZXZlbCA9IEVycm9yQ29ycmVjdGlvbkxldmVsLkw7XG4gICAgICAgICAgICBsZXQgcXVpZXRab25lID0gUVJDb2RlV3JpdGVyLlFVSUVUX1pPTkVfU0laRTtcbiAgICAgICAgICAgIGlmIChoaW50cyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGlmICh1bmRlZmluZWQgIT09IGhpbnRzLmdldChFbmNvZGVIaW50VHlwZSQxLkVSUk9SX0NPUlJFQ1RJT04pKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yQ29ycmVjdGlvbkxldmVsID0gRXJyb3JDb3JyZWN0aW9uTGV2ZWwuZnJvbVN0cmluZyhoaW50cy5nZXQoRW5jb2RlSGludFR5cGUkMS5FUlJPUl9DT1JSRUNUSU9OKS50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCAhPT0gaGludHMuZ2V0KEVuY29kZUhpbnRUeXBlJDEuTUFSR0lOKSkge1xuICAgICAgICAgICAgICAgICAgICBxdWlldFpvbmUgPSBOdW1iZXIucGFyc2VJbnQoaGludHMuZ2V0KEVuY29kZUhpbnRUeXBlJDEuTUFSR0lOKS50b1N0cmluZygpLCAxMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgY29kZSA9IEVuY29kZXIuZW5jb2RlKGNvbnRlbnRzLCBlcnJvckNvcnJlY3Rpb25MZXZlbCwgaGludHMpO1xuICAgICAgICAgICAgcmV0dXJuIFFSQ29kZVdyaXRlci5yZW5kZXJSZXN1bHQoY29kZSwgd2lkdGgsIGhlaWdodCwgcXVpZXRab25lKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBOb3RlIHRoYXQgdGhlIGlucHV0IG1hdHJpeCB1c2VzIDAgPT0gd2hpdGUsIDEgPT0gYmxhY2ssIHdoaWxlIHRoZSBvdXRwdXQgbWF0cml4IHVzZXNcbiAgICAgICAgLy8gMCA9PSBibGFjaywgMjU1ID09IHdoaXRlIChpLmUuIGFuIDggYml0IGdyZXlzY2FsZSBiaXRtYXApLlxuICAgICAgICBzdGF0aWMgcmVuZGVyUmVzdWx0KGNvZGUsIHdpZHRoIC8qaW50Ki8sIGhlaWdodCAvKmludCovLCBxdWlldFpvbmUgLyppbnQqLykge1xuICAgICAgICAgICAgY29uc3QgaW5wdXQgPSBjb2RlLmdldE1hdHJpeCgpO1xuICAgICAgICAgICAgaWYgKGlucHV0ID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgaW5wdXRXaWR0aCA9IGlucHV0LmdldFdpZHRoKCk7XG4gICAgICAgICAgICBjb25zdCBpbnB1dEhlaWdodCA9IGlucHV0LmdldEhlaWdodCgpO1xuICAgICAgICAgICAgY29uc3QgcXJXaWR0aCA9IGlucHV0V2lkdGggKyAocXVpZXRab25lICogMik7XG4gICAgICAgICAgICBjb25zdCBxckhlaWdodCA9IGlucHV0SGVpZ2h0ICsgKHF1aWV0Wm9uZSAqIDIpO1xuICAgICAgICAgICAgY29uc3Qgb3V0cHV0V2lkdGggPSBNYXRoLm1heCh3aWR0aCwgcXJXaWR0aCk7XG4gICAgICAgICAgICBjb25zdCBvdXRwdXRIZWlnaHQgPSBNYXRoLm1heChoZWlnaHQsIHFySGVpZ2h0KTtcbiAgICAgICAgICAgIGNvbnN0IG11bHRpcGxlID0gTWF0aC5taW4oTWF0aC5mbG9vcihvdXRwdXRXaWR0aCAvIHFyV2lkdGgpLCBNYXRoLmZsb29yKG91dHB1dEhlaWdodCAvIHFySGVpZ2h0KSk7XG4gICAgICAgICAgICAvLyBQYWRkaW5nIGluY2x1ZGVzIGJvdGggdGhlIHF1aWV0IHpvbmUgYW5kIHRoZSBleHRyYSB3aGl0ZSBwaXhlbHMgdG8gYWNjb21tb2RhdGUgdGhlIHJlcXVlc3RlZFxuICAgICAgICAgICAgLy8gZGltZW5zaW9ucy4gRm9yIGV4YW1wbGUsIGlmIGlucHV0IGlzIDI1eDI1IHRoZSBRUiB3aWxsIGJlIDMzeDMzIGluY2x1ZGluZyB0aGUgcXVpZXQgem9uZS5cbiAgICAgICAgICAgIC8vIElmIHRoZSByZXF1ZXN0ZWQgc2l6ZSBpcyAyMDB4MTYwLCB0aGUgbXVsdGlwbGUgd2lsbCBiZSA0LCBmb3IgYSBRUiBvZiAxMzJ4MTMyLiBUaGVzZSB3aWxsXG4gICAgICAgICAgICAvLyBoYW5kbGUgYWxsIHRoZSBwYWRkaW5nIGZyb20gMTAweDEwMCAodGhlIGFjdHVhbCBRUikgdXAgdG8gMjAweDE2MC5cbiAgICAgICAgICAgIGNvbnN0IGxlZnRQYWRkaW5nID0gTWF0aC5mbG9vcigob3V0cHV0V2lkdGggLSAoaW5wdXRXaWR0aCAqIG11bHRpcGxlKSkgLyAyKTtcbiAgICAgICAgICAgIGNvbnN0IHRvcFBhZGRpbmcgPSBNYXRoLmZsb29yKChvdXRwdXRIZWlnaHQgLSAoaW5wdXRIZWlnaHQgKiBtdWx0aXBsZSkpIC8gMik7XG4gICAgICAgICAgICBjb25zdCBvdXRwdXQgPSBuZXcgQml0TWF0cml4KG91dHB1dFdpZHRoLCBvdXRwdXRIZWlnaHQpO1xuICAgICAgICAgICAgZm9yIChsZXQgaW5wdXRZID0gMCwgb3V0cHV0WSA9IHRvcFBhZGRpbmc7IGlucHV0WSA8IGlucHV0SGVpZ2h0OyBpbnB1dFkrKywgb3V0cHV0WSArPSBtdWx0aXBsZSkge1xuICAgICAgICAgICAgICAgIC8vIFdyaXRlIHRoZSBjb250ZW50cyBvZiB0aGlzIHJvdyBvZiB0aGUgYmFyY29kZVxuICAgICAgICAgICAgICAgIGZvciAobGV0IGlucHV0WCA9IDAsIG91dHB1dFggPSBsZWZ0UGFkZGluZzsgaW5wdXRYIDwgaW5wdXRXaWR0aDsgaW5wdXRYKyssIG91dHB1dFggKz0gbXVsdGlwbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0LmdldChpbnB1dFgsIGlucHV0WSkgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5zZXRSZWdpb24ob3V0cHV0WCwgb3V0cHV0WSwgbXVsdGlwbGUsIG11bHRpcGxlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBvdXRwdXQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgUVJDb2RlV3JpdGVyLlFVSUVUX1pPTkVfU0laRSA9IDQ7XG5cbiAgICAvKmltcG9ydCBqYXZhLnV0aWwuTWFwOyovXG4gICAgLyoqXG4gICAgICogVGhpcyBpcyBhIGZhY3RvcnkgY2xhc3Mgd2hpY2ggZmluZHMgdGhlIGFwcHJvcHJpYXRlIFdyaXRlciBzdWJjbGFzcyBmb3IgdGhlIEJhcmNvZGVGb3JtYXRcbiAgICAgKiByZXF1ZXN0ZWQgYW5kIGVuY29kZXMgdGhlIGJhcmNvZGUgd2l0aCB0aGUgc3VwcGxpZWQgY29udGVudHMuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIGRzd2l0a2luQGdvb2dsZS5jb20gKERhbmllbCBTd2l0a2luKVxuICAgICAqL1xuICAgIGNsYXNzIE11bHRpRm9ybWF0V3JpdGVyIHtcbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICAvLyBwdWJsaWMgZW5jb2RlKGNvbnRlbnRzOiBzdHJpbmcsXG4gICAgICAgIC8vICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1hdDogQmFyY29kZUZvcm1hdCxcbiAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg6IG51bWJlciAvKmludCovLFxuICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IG51bWJlciAvKmludCovKTogQml0TWF0cml4IC8qdGhyb3dzIFdyaXRlckV4Y2VwdGlvbiAqLyB7XG4gICAgICAgIC8vICAgcmV0dXJuIGVuY29kZShjb250ZW50cywgZm9ybWF0LCB3aWR0aCwgaGVpZ2h0LCBudWxsKVxuICAgICAgICAvLyB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgZW5jb2RlKGNvbnRlbnRzLCBmb3JtYXQsIHdpZHRoIC8qaW50Ki8sIGhlaWdodCAvKmludCovLCBoaW50cykge1xuICAgICAgICAgICAgbGV0IHdyaXRlcjtcbiAgICAgICAgICAgIHN3aXRjaCAoZm9ybWF0KSB7XG4gICAgICAgICAgICAgICAgLy8gY2FzZSBCYXJjb2RlRm9ybWF0LkVBTl84OlxuICAgICAgICAgICAgICAgIC8vICAgd3JpdGVyID0gbmV3IEVBTjhXcml0ZXIoKVxuICAgICAgICAgICAgICAgIC8vICAgYnJlYWtcbiAgICAgICAgICAgICAgICAvLyBjYXNlIEJhcmNvZGVGb3JtYXQuVVBDX0U6XG4gICAgICAgICAgICAgICAgLy8gICB3cml0ZXIgPSBuZXcgVVBDRVdyaXRlcigpXG4gICAgICAgICAgICAgICAgLy8gICBicmVha1xuICAgICAgICAgICAgICAgIC8vIGNhc2UgQmFyY29kZUZvcm1hdC5FQU5fMTM6XG4gICAgICAgICAgICAgICAgLy8gICB3cml0ZXIgPSBuZXcgRUFOMTNXcml0ZXIoKVxuICAgICAgICAgICAgICAgIC8vICAgYnJlYWtcbiAgICAgICAgICAgICAgICAvLyBjYXNlIEJhcmNvZGVGb3JtYXQuVVBDX0E6XG4gICAgICAgICAgICAgICAgLy8gICB3cml0ZXIgPSBuZXcgVVBDQVdyaXRlcigpXG4gICAgICAgICAgICAgICAgLy8gICBicmVha1xuICAgICAgICAgICAgICAgIGNhc2UgQmFyY29kZUZvcm1hdCQxLlFSX0NPREU6XG4gICAgICAgICAgICAgICAgICAgIHdyaXRlciA9IG5ldyBRUkNvZGVXcml0ZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgLy8gY2FzZSBCYXJjb2RlRm9ybWF0LkNPREVfMzk6XG4gICAgICAgICAgICAgICAgLy8gICB3cml0ZXIgPSBuZXcgQ29kZTM5V3JpdGVyKClcbiAgICAgICAgICAgICAgICAvLyAgIGJyZWFrXG4gICAgICAgICAgICAgICAgLy8gY2FzZSBCYXJjb2RlRm9ybWF0LkNPREVfOTM6XG4gICAgICAgICAgICAgICAgLy8gICB3cml0ZXIgPSBuZXcgQ29kZTkzV3JpdGVyKClcbiAgICAgICAgICAgICAgICAvLyAgIGJyZWFrXG4gICAgICAgICAgICAgICAgLy8gY2FzZSBCYXJjb2RlRm9ybWF0LkNPREVfMTI4OlxuICAgICAgICAgICAgICAgIC8vICAgd3JpdGVyID0gbmV3IENvZGUxMjhXcml0ZXIoKVxuICAgICAgICAgICAgICAgIC8vICAgYnJlYWtcbiAgICAgICAgICAgICAgICAvLyBjYXNlIEJhcmNvZGVGb3JtYXQuSVRGOlxuICAgICAgICAgICAgICAgIC8vICAgd3JpdGVyID0gbmV3IElURldyaXRlcigpXG4gICAgICAgICAgICAgICAgLy8gICBicmVha1xuICAgICAgICAgICAgICAgIC8vIGNhc2UgQmFyY29kZUZvcm1hdC5QREZfNDE3OlxuICAgICAgICAgICAgICAgIC8vICAgd3JpdGVyID0gbmV3IFBERjQxN1dyaXRlcigpXG4gICAgICAgICAgICAgICAgLy8gICBicmVha1xuICAgICAgICAgICAgICAgIC8vIGNhc2UgQmFyY29kZUZvcm1hdC5DT0RBQkFSOlxuICAgICAgICAgICAgICAgIC8vICAgd3JpdGVyID0gbmV3IENvZGFCYXJXcml0ZXIoKVxuICAgICAgICAgICAgICAgIC8vICAgYnJlYWtcbiAgICAgICAgICAgICAgICAvLyBjYXNlIEJhcmNvZGVGb3JtYXQuREFUQV9NQVRSSVg6XG4gICAgICAgICAgICAgICAgLy8gICB3cml0ZXIgPSBuZXcgRGF0YU1hdHJpeFdyaXRlcigpXG4gICAgICAgICAgICAgICAgLy8gICBicmVha1xuICAgICAgICAgICAgICAgIC8vIGNhc2UgQmFyY29kZUZvcm1hdC5BWlRFQzpcbiAgICAgICAgICAgICAgICAvLyAgIHdyaXRlciA9IG5ldyBBenRlY1dyaXRlcigpXG4gICAgICAgICAgICAgICAgLy8gICBicmVha1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ05vIGVuY29kZXIgYXZhaWxhYmxlIGZvciBmb3JtYXQgJyArIGZvcm1hdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gd3JpdGVyLmVuY29kZShjb250ZW50cywgZm9ybWF0LCB3aWR0aCwgaGVpZ2h0LCBoaW50cyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDA5IFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIFRoaXMgb2JqZWN0IGV4dGVuZHMgTHVtaW5hbmNlU291cmNlIGFyb3VuZCBhbiBhcnJheSBvZiBZVVYgZGF0YSByZXR1cm5lZCBmcm9tIHRoZSBjYW1lcmEgZHJpdmVyLFxuICAgICAqIHdpdGggdGhlIG9wdGlvbiB0byBjcm9wIHRvIGEgcmVjdGFuZ2xlIHdpdGhpbiB0aGUgZnVsbCBkYXRhLiBUaGlzIGNhbiBiZSB1c2VkIHRvIGV4Y2x1ZGVcbiAgICAgKiBzdXBlcmZsdW91cyBwaXhlbHMgYXJvdW5kIHRoZSBwZXJpbWV0ZXIgYW5kIHNwZWVkIHVwIGRlY29kaW5nLlxuICAgICAqXG4gICAgICogSXQgd29ya3MgZm9yIGFueSBwaXhlbCBmb3JtYXQgd2hlcmUgdGhlIFkgY2hhbm5lbCBpcyBwbGFuYXIgYW5kIGFwcGVhcnMgZmlyc3QsIGluY2x1ZGluZ1xuICAgICAqIFlDYkNyXzQyMF9TUCBhbmQgWUNiQ3JfNDIyX1NQLlxuICAgICAqXG4gICAgICogQGF1dGhvciBkc3dpdGtpbkBnb29nbGUuY29tIChEYW5pZWwgU3dpdGtpbilcbiAgICAgKi9cbiAgICBjbGFzcyBQbGFuYXJZVVZMdW1pbmFuY2VTb3VyY2UgZXh0ZW5kcyBMdW1pbmFuY2VTb3VyY2Uge1xuICAgICAgICBjb25zdHJ1Y3Rvcih5dXZEYXRhLCBkYXRhV2lkdGggLyppbnQqLywgZGF0YUhlaWdodCAvKmludCovLCBsZWZ0IC8qaW50Ki8sIHRvcCAvKmludCovLCB3aWR0aCAvKmludCovLCBoZWlnaHQgLyppbnQqLywgcmV2ZXJzZUhvcml6b250YWwpIHtcbiAgICAgICAgICAgIHN1cGVyKHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgdGhpcy55dXZEYXRhID0geXV2RGF0YTtcbiAgICAgICAgICAgIHRoaXMuZGF0YVdpZHRoID0gZGF0YVdpZHRoO1xuICAgICAgICAgICAgdGhpcy5kYXRhSGVpZ2h0ID0gZGF0YUhlaWdodDtcbiAgICAgICAgICAgIHRoaXMubGVmdCA9IGxlZnQ7XG4gICAgICAgICAgICB0aGlzLnRvcCA9IHRvcDtcbiAgICAgICAgICAgIGlmIChsZWZ0ICsgd2lkdGggPiBkYXRhV2lkdGggfHwgdG9wICsgaGVpZ2h0ID4gZGF0YUhlaWdodCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oJ0Nyb3AgcmVjdGFuZ2xlIGRvZXMgbm90IGZpdCB3aXRoaW4gaW1hZ2UgZGF0YS4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyZXZlcnNlSG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgICAgIHRoaXMucmV2ZXJzZUhvcml6b250YWwod2lkdGgsIGhlaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBnZXRSb3coeSAvKmludCovLCByb3cpIHtcbiAgICAgICAgICAgIGlmICh5IDwgMCB8fCB5ID49IHRoaXMuZ2V0SGVpZ2h0KCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdSZXF1ZXN0ZWQgcm93IGlzIG91dHNpZGUgdGhlIGltYWdlOiAnICsgeSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMuZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGlmIChyb3cgPT09IG51bGwgfHwgcm93ID09PSB1bmRlZmluZWQgfHwgcm93Lmxlbmd0aCA8IHdpZHRoKSB7XG4gICAgICAgICAgICAgICAgcm93ID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHdpZHRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9ICh5ICsgdGhpcy50b3ApICogdGhpcy5kYXRhV2lkdGggKyB0aGlzLmxlZnQ7XG4gICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KHRoaXMueXV2RGF0YSwgb2Zmc2V0LCByb3csIDAsIHdpZHRoKTtcbiAgICAgICAgICAgIHJldHVybiByb3c7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBnZXRNYXRyaXgoKSB7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMuZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuZ2V0SGVpZ2h0KCk7XG4gICAgICAgICAgICAvLyBJZiB0aGUgY2FsbGVyIGFza3MgZm9yIHRoZSBlbnRpcmUgdW5kZXJseWluZyBpbWFnZSwgc2F2ZSB0aGUgY29weSBhbmQgZ2l2ZSB0aGVtIHRoZVxuICAgICAgICAgICAgLy8gb3JpZ2luYWwgZGF0YS4gVGhlIGRvY3Mgc3BlY2lmaWNhbGx5IHdhcm4gdGhhdCByZXN1bHQubGVuZ3RoIG11c3QgYmUgaWdub3JlZC5cbiAgICAgICAgICAgIGlmICh3aWR0aCA9PT0gdGhpcy5kYXRhV2lkdGggJiYgaGVpZ2h0ID09PSB0aGlzLmRhdGFIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy55dXZEYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYXJlYSA9IHdpZHRoICogaGVpZ2h0O1xuICAgICAgICAgICAgY29uc3QgbWF0cml4ID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KGFyZWEpO1xuICAgICAgICAgICAgbGV0IGlucHV0T2Zmc2V0ID0gdGhpcy50b3AgKiB0aGlzLmRhdGFXaWR0aCArIHRoaXMubGVmdDtcbiAgICAgICAgICAgIC8vIElmIHRoZSB3aWR0aCBtYXRjaGVzIHRoZSBmdWxsIHdpZHRoIG9mIHRoZSB1bmRlcmx5aW5nIGRhdGEsIHBlcmZvcm0gYSBzaW5nbGUgY29weS5cbiAgICAgICAgICAgIGlmICh3aWR0aCA9PT0gdGhpcy5kYXRhV2lkdGgpIHtcbiAgICAgICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KHRoaXMueXV2RGF0YSwgaW5wdXRPZmZzZXQsIG1hdHJpeCwgMCwgYXJlYSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hdHJpeDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE90aGVyd2lzZSBjb3B5IG9uZSBjcm9wcGVkIHJvdyBhdCBhIHRpbWUuXG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgb3V0cHV0T2Zmc2V0ID0geSAqIHdpZHRoO1xuICAgICAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkodGhpcy55dXZEYXRhLCBpbnB1dE9mZnNldCwgbWF0cml4LCBvdXRwdXRPZmZzZXQsIHdpZHRoKTtcbiAgICAgICAgICAgICAgICBpbnB1dE9mZnNldCArPSB0aGlzLmRhdGFXaWR0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtYXRyaXg7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBpc0Nyb3BTdXBwb3J0ZWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICAvKkBPdmVycmlkZSovXG4gICAgICAgIGNyb3AobGVmdCAvKmludCovLCB0b3AgLyppbnQqLywgd2lkdGggLyppbnQqLywgaGVpZ2h0IC8qaW50Ki8pIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUGxhbmFyWVVWTHVtaW5hbmNlU291cmNlKHRoaXMueXV2RGF0YSwgdGhpcy5kYXRhV2lkdGgsIHRoaXMuZGF0YUhlaWdodCwgdGhpcy5sZWZ0ICsgbGVmdCwgdGhpcy50b3AgKyB0b3AsIHdpZHRoLCBoZWlnaHQsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICByZW5kZXJUaHVtYm5haWwoKSB7XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMuZ2V0V2lkdGgoKSAvIFBsYW5hcllVVkx1bWluYW5jZVNvdXJjZS5USFVNQk5BSUxfU0NBTEVfRkFDVE9SO1xuICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5nZXRIZWlnaHQoKSAvIFBsYW5hcllVVkx1bWluYW5jZVNvdXJjZS5USFVNQk5BSUxfU0NBTEVfRkFDVE9SO1xuICAgICAgICAgICAgY29uc3QgcGl4ZWxzID0gbmV3IEludDMyQXJyYXkod2lkdGggKiBoZWlnaHQpO1xuICAgICAgICAgICAgY29uc3QgeXV2ID0gdGhpcy55dXZEYXRhO1xuICAgICAgICAgICAgbGV0IGlucHV0T2Zmc2V0ID0gdGhpcy50b3AgKiB0aGlzLmRhdGFXaWR0aCArIHRoaXMubGVmdDtcbiAgICAgICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgaGVpZ2h0OyB5KyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBvdXRwdXRPZmZzZXQgPSB5ICogd2lkdGg7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGdyZXkgPSB5dXZbaW5wdXRPZmZzZXQgKyB4ICogUGxhbmFyWVVWTHVtaW5hbmNlU291cmNlLlRIVU1CTkFJTF9TQ0FMRV9GQUNUT1JdICYgMHhmZjtcbiAgICAgICAgICAgICAgICAgICAgcGl4ZWxzW291dHB1dE9mZnNldCArIHhdID0gMHhGRjAwMDAwMCB8IChncmV5ICogMHgwMDAxMDEwMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlucHV0T2Zmc2V0ICs9IHRoaXMuZGF0YVdpZHRoICogUGxhbmFyWVVWTHVtaW5hbmNlU291cmNlLlRIVU1CTkFJTF9TQ0FMRV9GQUNUT1I7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcGl4ZWxzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHdpZHRoIG9mIGltYWdlIGZyb20ge0BsaW5rICNyZW5kZXJUaHVtYm5haWwoKX1cbiAgICAgICAgICovXG4gICAgICAgIGdldFRodW1ibmFpbFdpZHRoKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0V2lkdGgoKSAvIFBsYW5hcllVVkx1bWluYW5jZVNvdXJjZS5USFVNQk5BSUxfU0NBTEVfRkFDVE9SO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIGhlaWdodCBvZiBpbWFnZSBmcm9tIHtAbGluayAjcmVuZGVyVGh1bWJuYWlsKCl9XG4gICAgICAgICAqL1xuICAgICAgICBnZXRUaHVtYm5haWxIZWlnaHQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRIZWlnaHQoKSAvIFBsYW5hcllVVkx1bWluYW5jZVNvdXJjZS5USFVNQk5BSUxfU0NBTEVfRkFDVE9SO1xuICAgICAgICB9XG4gICAgICAgIHJldmVyc2VIb3Jpem9udGFsKHdpZHRoIC8qaW50Ki8sIGhlaWdodCAvKmludCovKSB7XG4gICAgICAgICAgICBjb25zdCB5dXZEYXRhID0gdGhpcy55dXZEYXRhO1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDAsIHJvd1N0YXJ0ID0gdGhpcy50b3AgKiB0aGlzLmRhdGFXaWR0aCArIHRoaXMubGVmdDsgeSA8IGhlaWdodDsgeSsrLCByb3dTdGFydCArPSB0aGlzLmRhdGFXaWR0aCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG1pZGRsZSA9IHJvd1N0YXJ0ICsgd2lkdGggLyAyO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHgxID0gcm93U3RhcnQsIHgyID0gcm93U3RhcnQgKyB3aWR0aCAtIDE7IHgxIDwgbWlkZGxlOyB4MSsrLCB4Mi0tKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRlbXAgPSB5dXZEYXRhW3gxXTtcbiAgICAgICAgICAgICAgICAgICAgeXV2RGF0YVt4MV0gPSB5dXZEYXRhW3gyXTtcbiAgICAgICAgICAgICAgICAgICAgeXV2RGF0YVt4Ml0gPSB0ZW1wO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpbnZlcnQoKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEludmVydGVkTHVtaW5hbmNlU291cmNlKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIFBsYW5hcllVVkx1bWluYW5jZVNvdXJjZS5USFVNQk5BSUxfU0NBTEVfRkFDVE9SID0gMjtcblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMDkgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogVGhpcyBjbGFzcyBpcyB1c2VkIHRvIGhlbHAgZGVjb2RlIGltYWdlcyBmcm9tIGZpbGVzIHdoaWNoIGFycml2ZSBhcyBSR0IgZGF0YSBmcm9tXG4gICAgICogYW4gQVJHQiBwaXhlbCBhcnJheS4gSXQgZG9lcyBub3Qgc3VwcG9ydCByb3RhdGlvbi5cbiAgICAgKlxuICAgICAqIEBhdXRob3IgZHN3aXRraW5AZ29vZ2xlLmNvbSAoRGFuaWVsIFN3aXRraW4pXG4gICAgICogQGF1dGhvciBCZXRhbWlub3NcbiAgICAgKi9cbiAgICBjbGFzcyBSR0JMdW1pbmFuY2VTb3VyY2UgZXh0ZW5kcyBMdW1pbmFuY2VTb3VyY2Uge1xuICAgICAgICBjb25zdHJ1Y3RvcihsdW1pbmFuY2VzLCB3aWR0aCAvKmludCovLCBoZWlnaHQgLyppbnQqLywgZGF0YVdpZHRoIC8qaW50Ki8sIGRhdGFIZWlnaHQgLyppbnQqLywgbGVmdCAvKmludCovLCB0b3AgLyppbnQqLykge1xuICAgICAgICAgICAgc3VwZXIod2lkdGgsIGhlaWdodCk7XG4gICAgICAgICAgICB0aGlzLmRhdGFXaWR0aCA9IGRhdGFXaWR0aDtcbiAgICAgICAgICAgIHRoaXMuZGF0YUhlaWdodCA9IGRhdGFIZWlnaHQ7XG4gICAgICAgICAgICB0aGlzLmxlZnQgPSBsZWZ0O1xuICAgICAgICAgICAgdGhpcy50b3AgPSB0b3A7XG4gICAgICAgICAgICBpZiAobHVtaW5hbmNlcy5CWVRFU19QRVJfRUxFTUVOVCA9PT0gNCkgeyAvLyBJbnQzMkFycmF5XG4gICAgICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IHdpZHRoICogaGVpZ2h0O1xuICAgICAgICAgICAgICAgIGNvbnN0IGx1bWluYW5jZXNVaW50OEFycmF5ID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHNpemUpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IG9mZnNldCA9IDA7IG9mZnNldCA8IHNpemU7IG9mZnNldCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBpeGVsID0gbHVtaW5hbmNlc1tvZmZzZXRdO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByID0gKHBpeGVsID4+IDE2KSAmIDB4ZmY7IC8vIHJlZFxuICAgICAgICAgICAgICAgICAgICBjb25zdCBnMiA9IChwaXhlbCA+PiA3KSAmIDB4MWZlOyAvLyAyICogZ3JlZW5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYiA9IHBpeGVsICYgMHhmZjsgLy8gYmx1ZVxuICAgICAgICAgICAgICAgICAgICAvLyBDYWxjdWxhdGUgZ3JlZW4tZmF2b3VyaW5nIGF2ZXJhZ2UgY2hlYXBseVxuICAgICAgICAgICAgICAgICAgICBsdW1pbmFuY2VzVWludDhBcnJheVtvZmZzZXRdID0gLyooYnl0ZSkgKi8gKChyICsgZzIgKyBiKSAvIDQpICYgMHhGRjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5sdW1pbmFuY2VzID0gbHVtaW5hbmNlc1VpbnQ4QXJyYXk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmx1bWluYW5jZXMgPSBsdW1pbmFuY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHVuZGVmaW5lZCA9PT0gZGF0YVdpZHRoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhV2lkdGggPSB3aWR0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IGRhdGFIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGFIZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodW5kZWZpbmVkID09PSBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sZWZ0ID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh1bmRlZmluZWQgPT09IHRvcCkge1xuICAgICAgICAgICAgICAgIHRoaXMudG9wID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmxlZnQgKyB3aWR0aCA+IHRoaXMuZGF0YVdpZHRoIHx8IHRoaXMudG9wICsgaGVpZ2h0ID4gdGhpcy5kYXRhSGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignQ3JvcCByZWN0YW5nbGUgZG9lcyBub3QgZml0IHdpdGhpbiBpbWFnZSBkYXRhLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgZ2V0Um93KHkgLyppbnQqLywgcm93KSB7XG4gICAgICAgICAgICBpZiAoeSA8IDAgfHwgeSA+PSB0aGlzLmdldEhlaWdodCgpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignUmVxdWVzdGVkIHJvdyBpcyBvdXRzaWRlIHRoZSBpbWFnZTogJyArIHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSB0aGlzLmdldFdpZHRoKCk7XG4gICAgICAgICAgICBpZiAocm93ID09PSBudWxsIHx8IHJvdyA9PT0gdW5kZWZpbmVkIHx8IHJvdy5sZW5ndGggPCB3aWR0aCkge1xuICAgICAgICAgICAgICAgIHJvdyA9IG5ldyBVaW50OENsYW1wZWRBcnJheSh3aWR0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBvZmZzZXQgPSAoeSArIHRoaXMudG9wKSAqIHRoaXMuZGF0YVdpZHRoICsgdGhpcy5sZWZ0O1xuICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weSh0aGlzLmx1bWluYW5jZXMsIG9mZnNldCwgcm93LCAwLCB3aWR0aCk7XG4gICAgICAgICAgICByZXR1cm4gcm93O1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgZ2V0TWF0cml4KCkge1xuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSB0aGlzLmdldFdpZHRoKCk7XG4gICAgICAgICAgICBjb25zdCBoZWlnaHQgPSB0aGlzLmdldEhlaWdodCgpO1xuICAgICAgICAgICAgLy8gSWYgdGhlIGNhbGxlciBhc2tzIGZvciB0aGUgZW50aXJlIHVuZGVybHlpbmcgaW1hZ2UsIHNhdmUgdGhlIGNvcHkgYW5kIGdpdmUgdGhlbSB0aGVcbiAgICAgICAgICAgIC8vIG9yaWdpbmFsIGRhdGEuIFRoZSBkb2NzIHNwZWNpZmljYWxseSB3YXJuIHRoYXQgcmVzdWx0Lmxlbmd0aCBtdXN0IGJlIGlnbm9yZWQuXG4gICAgICAgICAgICBpZiAod2lkdGggPT09IHRoaXMuZGF0YVdpZHRoICYmIGhlaWdodCA9PT0gdGhpcy5kYXRhSGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubHVtaW5hbmNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGFyZWEgPSB3aWR0aCAqIGhlaWdodDtcbiAgICAgICAgICAgIGNvbnN0IG1hdHJpeCA9IG5ldyBVaW50OENsYW1wZWRBcnJheShhcmVhKTtcbiAgICAgICAgICAgIGxldCBpbnB1dE9mZnNldCA9IHRoaXMudG9wICogdGhpcy5kYXRhV2lkdGggKyB0aGlzLmxlZnQ7XG4gICAgICAgICAgICAvLyBJZiB0aGUgd2lkdGggbWF0Y2hlcyB0aGUgZnVsbCB3aWR0aCBvZiB0aGUgdW5kZXJseWluZyBkYXRhLCBwZXJmb3JtIGEgc2luZ2xlIGNvcHkuXG4gICAgICAgICAgICBpZiAod2lkdGggPT09IHRoaXMuZGF0YVdpZHRoKSB7XG4gICAgICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weSh0aGlzLmx1bWluYW5jZXMsIGlucHV0T2Zmc2V0LCBtYXRyaXgsIDAsIGFyZWEpO1xuICAgICAgICAgICAgICAgIHJldHVybiBtYXRyaXg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBPdGhlcndpc2UgY29weSBvbmUgY3JvcHBlZCByb3cgYXQgYSB0aW1lLlxuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IG91dHB1dE9mZnNldCA9IHkgKiB3aWR0aDtcbiAgICAgICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KHRoaXMubHVtaW5hbmNlcywgaW5wdXRPZmZzZXQsIG1hdHJpeCwgb3V0cHV0T2Zmc2V0LCB3aWR0aCk7XG4gICAgICAgICAgICAgICAgaW5wdXRPZmZzZXQgKz0gdGhpcy5kYXRhV2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWF0cml4O1xuICAgICAgICB9XG4gICAgICAgIC8qQE92ZXJyaWRlKi9cbiAgICAgICAgaXNDcm9wU3VwcG9ydGVkKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgLypAT3ZlcnJpZGUqL1xuICAgICAgICBjcm9wKGxlZnQgLyppbnQqLywgdG9wIC8qaW50Ki8sIHdpZHRoIC8qaW50Ki8sIGhlaWdodCAvKmludCovKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFJHQkx1bWluYW5jZVNvdXJjZSh0aGlzLmx1bWluYW5jZXMsIHdpZHRoLCBoZWlnaHQsIHRoaXMuZGF0YVdpZHRoLCB0aGlzLmRhdGFIZWlnaHQsIHRoaXMubGVmdCArIGxlZnQsIHRoaXMudG9wICsgdG9wKTtcbiAgICAgICAgfVxuICAgICAgICBpbnZlcnQoKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEludmVydGVkTHVtaW5hbmNlU291cmNlKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSnVzdCB0byBtYWtlIGEgc2hvcnRjdXQgYmV0d2VlbiBKYXZhIGNvZGUgYW5kIFRTIGNvZGUuXG4gICAgICovXG4gICAgY2xhc3MgQ2hhcnNldCBleHRlbmRzIENoYXJhY3RlclNldEVDSSB7XG4gICAgICAgIHN0YXRpYyBmb3JOYW1lKG5hbWUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldENoYXJhY3RlclNldEVDSUJ5TmFtZShuYW1lKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEp1c3QgdG8gbWFrZSBhIHNob3J0Y3V0IGJldHdlZW4gSmF2YSBjb2RlIGFuZCBUUyBjb2RlLlxuICAgICAqL1xuICAgIGNsYXNzIFN0YW5kYXJkQ2hhcnNldHMge1xuICAgIH1cbiAgICBTdGFuZGFyZENoYXJzZXRzLklTT184ODU5XzEgPSBDaGFyYWN0ZXJTZXRFQ0kuSVNPODg1OV8xO1xuXG4gICAgLypcbiAgICAqIENvcHlyaWdodCAyMDEzIFpYaW5nIGF1dGhvcnNcbiAgICAqXG4gICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgKlxuICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAqXG4gICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICovXG4gICAgLyoqXG4gICAgICogQXp0ZWMgMkQgY29kZSByZXByZXNlbnRhdGlvblxuICAgICAqXG4gICAgICogQGF1dGhvciBSdXN0YW0gQWJkdWxsYWV2XG4gICAgICovXG4gICAgLypwdWJsaWMgZmluYWwqLyBjbGFzcyBBenRlY0NvZGUge1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7QGNvZGUgdHJ1ZX0gaWYgY29tcGFjdCBpbnN0ZWFkIG9mIGZ1bGwgbW9kZVxuICAgICAgICAgKi9cbiAgICAgICAgaXNDb21wYWN0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29tcGFjdDtcbiAgICAgICAgfVxuICAgICAgICBzZXRDb21wYWN0KGNvbXBhY3QpIHtcbiAgICAgICAgICAgIHRoaXMuY29tcGFjdCA9IGNvbXBhY3Q7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gc2l6ZSBpbiBwaXhlbHMgKHdpZHRoIGFuZCBoZWlnaHQpXG4gICAgICAgICAqL1xuICAgICAgICBnZXRTaXplKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2l6ZTtcbiAgICAgICAgfVxuICAgICAgICBzZXRTaXplKHNpemUpIHtcbiAgICAgICAgICAgIHRoaXMuc2l6ZSA9IHNpemU7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gbnVtYmVyIG9mIGxldmVsc1xuICAgICAgICAgKi9cbiAgICAgICAgZ2V0TGF5ZXJzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubGF5ZXJzO1xuICAgICAgICB9XG4gICAgICAgIHNldExheWVycyhsYXllcnMpIHtcbiAgICAgICAgICAgIHRoaXMubGF5ZXJzID0gbGF5ZXJzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIG51bWJlciBvZiBkYXRhIGNvZGV3b3Jkc1xuICAgICAgICAgKi9cbiAgICAgICAgZ2V0Q29kZVdvcmRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29kZVdvcmRzO1xuICAgICAgICB9XG4gICAgICAgIHNldENvZGVXb3Jkcyhjb2RlV29yZHMpIHtcbiAgICAgICAgICAgIHRoaXMuY29kZVdvcmRzID0gY29kZVdvcmRzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHRoZSBzeW1ib2wgaW1hZ2VcbiAgICAgICAgICovXG4gICAgICAgIGdldE1hdHJpeCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1hdHJpeDtcbiAgICAgICAgfVxuICAgICAgICBzZXRNYXRyaXgobWF0cml4KSB7XG4gICAgICAgICAgICB0aGlzLm1hdHJpeCA9IG1hdHJpeDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNsYXNzIENvbGxlY3Rpb25zIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoZSBzaW5nbGV0b25MaXN0KFQpIG1ldGhvZCBpcyB1c2VkIHRvIHJldHVybiBhbiBpbW11dGFibGUgbGlzdCBjb250YWluaW5nIG9ubHkgdGhlIHNwZWNpZmllZCBvYmplY3QuXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgc2luZ2xldG9uTGlzdChpdGVtKSB7XG4gICAgICAgICAgICByZXR1cm4gW2l0ZW1dO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgbWluKENvbGxlY3Rpb248PyBleHRlbmRzIFQ+LCBDb21wYXJhdG9yPD8gc3VwZXIgVD4pIG1ldGhvZCBpcyB1c2VkIHRvIHJldHVybiB0aGUgbWluaW11bSBlbGVtZW50IG9mIHRoZSBnaXZlbiBjb2xsZWN0aW9uLCBhY2NvcmRpbmcgdG8gdGhlIG9yZGVyIGluZHVjZWQgYnkgdGhlIHNwZWNpZmllZCBjb21wYXJhdG9yLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIG1pbihjb2xsZWN0aW9uLCBjb21wYXJhdG9yKSB7XG4gICAgICAgICAgICByZXR1cm4gY29sbGVjdGlvbi5zb3J0KGNvbXBhcmF0b3IpWzBdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAqIENvcHlyaWdodCAyMDEzIFpYaW5nIGF1dGhvcnNcbiAgICAqXG4gICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgKlxuICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAqXG4gICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICovXG4gICAgY2xhc3MgVG9rZW4ge1xuICAgICAgICBjb25zdHJ1Y3RvcihwcmV2aW91cykge1xuICAgICAgICAgICAgdGhpcy5wcmV2aW91cyA9IHByZXZpb3VzO1xuICAgICAgICB9XG4gICAgICAgIGdldFByZXZpb3VzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJldmlvdXM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICogQ29weXJpZ2h0IDIwMTMgWlhpbmcgYXV0aG9yc1xuICAgICpcbiAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAqXG4gICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICpcbiAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgKi9cbiAgICAvKmZpbmFsKi8gY2xhc3MgU2ltcGxlVG9rZW4gZXh0ZW5kcyBUb2tlbiB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHByZXZpb3VzLCB2YWx1ZSwgYml0Q291bnQpIHtcbiAgICAgICAgICAgIHN1cGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIHRoaXMuYml0Q291bnQgPSBiaXRDb3VudDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQE92ZXJyaWRlXG4gICAgICAgICAqL1xuICAgICAgICBhcHBlbmRUbyhiaXRBcnJheSwgdGV4dCkge1xuICAgICAgICAgICAgYml0QXJyYXkuYXBwZW5kQml0cyh0aGlzLnZhbHVlLCB0aGlzLmJpdENvdW50KTtcbiAgICAgICAgfVxuICAgICAgICBhZGQodmFsdWUsIGJpdENvdW50KSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFNpbXBsZVRva2VuKHRoaXMsIHZhbHVlLCBiaXRDb3VudCk7XG4gICAgICAgIH1cbiAgICAgICAgYWRkQmluYXJ5U2hpZnQoc3RhcnQsIGJ5dGVDb3VudCkge1xuICAgICAgICAgICAgLy8gbm8tb3AgY2FuJ3QgYmluYXJ5IHNoaWZ0IGEgc2ltcGxlIHRva2VuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ2FkZEJpbmFyeVNoaWZ0IG9uIFNpbXBsZVRva2VuLCB0aGlzIHNpbXBseSByZXR1cm5zIGEgY29weSBvZiB0aGlzIHRva2VuJyk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFNpbXBsZVRva2VuKHRoaXMsIHN0YXJ0LCBieXRlQ291bnQpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAT3ZlcnJpZGVcbiAgICAgICAgICovXG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgbGV0IHZhbHVlID0gdGhpcy52YWx1ZSAmICgoMSA8PCB0aGlzLmJpdENvdW50KSAtIDEpO1xuICAgICAgICAgICAgdmFsdWUgfD0gMSA8PCB0aGlzLmJpdENvdW50O1xuICAgICAgICAgICAgcmV0dXJuICc8JyArIEludGVnZXIudG9CaW5hcnlTdHJpbmcodmFsdWUgfCAoMSA8PCB0aGlzLmJpdENvdW50KSkuc3Vic3RyaW5nKDEpICsgJz4nO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAqIENvcHlyaWdodCAyMDEzIFpYaW5nIGF1dGhvcnNcbiAgICAqXG4gICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgKlxuICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAqXG4gICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICovXG4gICAgLypmaW5hbCovIGNsYXNzIEJpbmFyeVNoaWZ0VG9rZW4gZXh0ZW5kcyBTaW1wbGVUb2tlbiB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHByZXZpb3VzLCBiaW5hcnlTaGlmdFN0YXJ0LCBiaW5hcnlTaGlmdEJ5dGVDb3VudCkge1xuICAgICAgICAgICAgc3VwZXIocHJldmlvdXMsIDAsIDApO1xuICAgICAgICAgICAgdGhpcy5iaW5hcnlTaGlmdFN0YXJ0ID0gYmluYXJ5U2hpZnRTdGFydDtcbiAgICAgICAgICAgIHRoaXMuYmluYXJ5U2hpZnRCeXRlQ291bnQgPSBiaW5hcnlTaGlmdEJ5dGVDb3VudDtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQE92ZXJyaWRlXG4gICAgICAgICAqL1xuICAgICAgICBhcHBlbmRUbyhiaXRBcnJheSwgdGV4dCkge1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmJpbmFyeVNoaWZ0Qnl0ZUNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoaSA9PT0gMCB8fCAoaSA9PT0gMzEgJiYgdGhpcy5iaW5hcnlTaGlmdEJ5dGVDb3VudCA8PSA2MikpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gV2UgbmVlZCBhIGhlYWRlciBiZWZvcmUgdGhlIGZpcnN0IGNoYXJhY3RlciwgYW5kIGJlZm9yZVxuICAgICAgICAgICAgICAgICAgICAvLyBjaGFyYWN0ZXIgMzEgd2hlbiB0aGUgdG90YWwgYnl0ZSBjb2RlIGlzIDw9IDYyXG4gICAgICAgICAgICAgICAgICAgIGJpdEFycmF5LmFwcGVuZEJpdHMoMzEsIDUpOyAvLyBCSU5BUllfU0hJRlRcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuYmluYXJ5U2hpZnRCeXRlQ291bnQgPiA2Mikge1xuICAgICAgICAgICAgICAgICAgICAgICAgYml0QXJyYXkuYXBwZW5kQml0cyh0aGlzLmJpbmFyeVNoaWZ0Qnl0ZUNvdW50IC0gMzEsIDE2KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAxIDw9IGJpbmFyeVNoaWZ0Qnl0ZUNvZGUgPD0gNjJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJpdEFycmF5LmFwcGVuZEJpdHMoTWF0aC5taW4odGhpcy5iaW5hcnlTaGlmdEJ5dGVDb3VudCwgMzEpLCA1KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIDMyIDw9IGJpbmFyeVNoaWZ0Q291bnQgPD0gNjIgYW5kIGkgPT0gMzFcbiAgICAgICAgICAgICAgICAgICAgICAgIGJpdEFycmF5LmFwcGVuZEJpdHModGhpcy5iaW5hcnlTaGlmdEJ5dGVDb3VudCAtIDMxLCA1KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBiaXRBcnJheS5hcHBlbmRCaXRzKHRleHRbdGhpcy5iaW5hcnlTaGlmdFN0YXJ0ICsgaV0sIDgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGFkZEJpbmFyeVNoaWZ0KHN0YXJ0LCBieXRlQ291bnQpIHtcbiAgICAgICAgICAgIC8vIGludCBiaXRDb3VudCA9IChieXRlQ291bnQgKiA4KSArIChieXRlQ291bnQgPD0gMzEgPyAxMCA6IGJ5dGVDb3VudCA8PSA2MiA/IDIwIDogMjEpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBCaW5hcnlTaGlmdFRva2VuKHRoaXMsIHN0YXJ0LCBieXRlQ291bnQpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAT3ZlcnJpZGVcbiAgICAgICAgICovXG4gICAgICAgIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgcmV0dXJuICc8JyArIHRoaXMuYmluYXJ5U2hpZnRTdGFydCArICc6OicgKyAodGhpcy5iaW5hcnlTaGlmdFN0YXJ0ICsgdGhpcy5iaW5hcnlTaGlmdEJ5dGVDb3VudCAtIDEpICsgJz4nO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWRkQmluYXJ5U2hpZnQodG9rZW4sIHN0YXJ0LCBieXRlQ291bnQpIHtcbiAgICAgICAgLy8gaW50IGJpdENvdW50ID0gKGJ5dGVDb3VudCAqIDgpICsgKGJ5dGVDb3VudCA8PSAzMSA/IDEwIDogYnl0ZUNvdW50IDw9IDYyID8gMjAgOiAyMSk7XG4gICAgICAgIHJldHVybiBuZXcgQmluYXJ5U2hpZnRUb2tlbih0b2tlbiwgc3RhcnQsIGJ5dGVDb3VudCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGFkZCh0b2tlbiwgdmFsdWUsIGJpdENvdW50KSB7XG4gICAgICAgIHJldHVybiBuZXcgU2ltcGxlVG9rZW4odG9rZW4sIHZhbHVlLCBiaXRDb3VudCk7XG4gICAgfVxuXG4gICAgY29uc3QgLypmaW5hbCovIE1PREVfTkFNRVMgPSBbXG4gICAgICAgICdVUFBFUicsXG4gICAgICAgICdMT1dFUicsXG4gICAgICAgICdESUdJVCcsXG4gICAgICAgICdNSVhFRCcsXG4gICAgICAgICdQVU5DVCdcbiAgICBdO1xuICAgIGNvbnN0IC8qZmluYWwqLyBNT0RFX1VQUEVSID0gMDsgLy8gNSBiaXRzXG4gICAgY29uc3QgLypmaW5hbCovIE1PREVfTE9XRVIgPSAxOyAvLyA1IGJpdHNcbiAgICBjb25zdCAvKmZpbmFsKi8gTU9ERV9ESUdJVCA9IDI7IC8vIDQgYml0c1xuICAgIGNvbnN0IC8qZmluYWwqLyBNT0RFX01JWEVEID0gMzsgLy8gNSBiaXRzXG4gICAgY29uc3QgLypmaW5hbCovIE1PREVfUFVOQ1QgPSA0OyAvLyA1IGJpdHNcbiAgICBjb25zdCBFTVBUWV9UT0tFTiA9IG5ldyBTaW1wbGVUb2tlbihudWxsLCAwLCAwKTtcblxuICAgIC8vIFRoZSBMYXRjaCBUYWJsZSBzaG93cywgZm9yIGVhY2ggcGFpciBvZiBNb2RlcywgdGhlIG9wdGltYWwgbWV0aG9kIGZvclxuICAgIC8vIGdldHRpbmcgZnJvbSBvbmUgbW9kZSB0byBhbm90aGVyLiAgSW4gdGhlIHdvcnN0IHBvc3NpYmxlIGNhc2UsIHRoaXMgY2FuXG4gICAgLy8gYmUgdXAgdG8gMTQgYml0cy4gIEluIHRoZSBiZXN0IHBvc3NpYmxlIGNhc2UsIHdlIGFyZSBhbHJlYWR5IHRoZXJlIVxuICAgIC8vIFRoZSBoaWdoIGhhbGYtd29yZCBvZiBlYWNoIGVudHJ5IGdpdmVzIHRoZSBudW1iZXIgb2YgYml0cy5cbiAgICAvLyBUaGUgbG93IGhhbGYtd29yZCBvZiBlYWNoIGVudHJ5IGFyZSB0aGUgYWN0dWFsIGJpdHMgbmVjZXNzYXJ5IHRvIGNoYW5nZVxuICAgIGNvbnN0IExBVENIX1RBQkxFID0gW1xuICAgICAgICBJbnQzMkFycmF5LmZyb20oW1xuICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICg1IDw8IDE2KSArIDI4LFxuICAgICAgICAgICAgKDUgPDwgMTYpICsgMzAsXG4gICAgICAgICAgICAoNSA8PCAxNikgKyAyOSxcbiAgICAgICAgICAgICgxMCA8PCAxNikgKyAoMjkgPDwgNSkgKyAzMCAvLyBVUFBFUiAtPiBNSVhFRCAtPiBQVU5DVFxuICAgICAgICBdKSxcbiAgICAgICAgSW50MzJBcnJheS5mcm9tKFtcbiAgICAgICAgICAgICg5IDw8IDE2KSArICgzMCA8PCA0KSArIDE0LFxuICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICg1IDw8IDE2KSArIDMwLFxuICAgICAgICAgICAgKDUgPDwgMTYpICsgMjksXG4gICAgICAgICAgICAoMTAgPDwgMTYpICsgKDI5IDw8IDUpICsgMzAgLy8gTE9XRVIgLT4gTUlYRUQgLT4gUFVOQ1RcbiAgICAgICAgXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbXG4gICAgICAgICAgICAoNCA8PCAxNikgKyAxNCxcbiAgICAgICAgICAgICg5IDw8IDE2KSArICgxNCA8PCA1KSArIDI4LFxuICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICg5IDw8IDE2KSArICgxNCA8PCA1KSArIDI5LFxuICAgICAgICAgICAgKDE0IDw8IDE2KSArICgxNCA8PCAxMCkgKyAoMjkgPDwgNSkgKyAzMFxuICAgICAgICAgICAgLy8gRElHSVQgLT4gVVBQRVIgLT4gTUlYRUQgLT4gUFVOQ1RcbiAgICAgICAgXSksXG4gICAgICAgIEludDMyQXJyYXkuZnJvbShbXG4gICAgICAgICAgICAoNSA8PCAxNikgKyAyOSxcbiAgICAgICAgICAgICg1IDw8IDE2KSArIDI4LFxuICAgICAgICAgICAgKDEwIDw8IDE2KSArICgyOSA8PCA1KSArIDMwLFxuICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICg1IDw8IDE2KSArIDMwIC8vIE1JWEVEIC0+IFBVTkNUXG4gICAgICAgIF0pLFxuICAgICAgICBJbnQzMkFycmF5LmZyb20oW1xuICAgICAgICAgICAgKDUgPDwgMTYpICsgMzEsXG4gICAgICAgICAgICAoMTAgPDwgMTYpICsgKDMxIDw8IDUpICsgMjgsXG4gICAgICAgICAgICAoMTAgPDwgMTYpICsgKDMxIDw8IDUpICsgMzAsXG4gICAgICAgICAgICAoMTAgPDwgMTYpICsgKDMxIDw8IDUpICsgMjksXG4gICAgICAgICAgICAwXG4gICAgICAgIF0pXG4gICAgXTtcblxuICAgIGZ1bmN0aW9uIHN0YXRpY19TSElGVF9UQUJMRShTSElGVF9UQUJMRSkge1xuICAgICAgICBmb3IgKGxldCB0YWJsZSAvKkludDMyQXJyYXkqLyBvZiBTSElGVF9UQUJMRSkge1xuICAgICAgICAgICAgQXJyYXlzLmZpbGwodGFibGUsIC0xKTtcbiAgICAgICAgfVxuICAgICAgICBTSElGVF9UQUJMRVtNT0RFX1VQUEVSXVtNT0RFX1BVTkNUXSA9IDA7XG4gICAgICAgIFNISUZUX1RBQkxFW01PREVfTE9XRVJdW01PREVfUFVOQ1RdID0gMDtcbiAgICAgICAgU0hJRlRfVEFCTEVbTU9ERV9MT1dFUl1bTU9ERV9VUFBFUl0gPSAyODtcbiAgICAgICAgU0hJRlRfVEFCTEVbTU9ERV9NSVhFRF1bTU9ERV9QVU5DVF0gPSAwO1xuICAgICAgICBTSElGVF9UQUJMRVtNT0RFX0RJR0lUXVtNT0RFX1BVTkNUXSA9IDA7XG4gICAgICAgIFNISUZUX1RBQkxFW01PREVfRElHSVRdW01PREVfVVBQRVJdID0gMTU7XG4gICAgICAgIHJldHVybiBTSElGVF9UQUJMRTtcbiAgICB9XG4gICAgY29uc3QgLypmaW5hbCovIFNISUZUX1RBQkxFID0gc3RhdGljX1NISUZUX1RBQkxFKEFycmF5cy5jcmVhdGVJbnQzMkFycmF5KDYsIDYpKTsgLy8gbW9kZSBzaGlmdCBjb2RlcywgcGVyIHRhYmxlXG5cbiAgICAvKlxuICAgICAqIENvcHlyaWdodCAyMDEzIFpYaW5nIGF1dGhvcnNcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgICAqXG4gICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAgKlxuICAgICAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gICAgICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIFN0YXRlIHJlcHJlc2VudHMgYWxsIGluZm9ybWF0aW9uIGFib3V0IGEgc2VxdWVuY2UgbmVjZXNzYXJ5IHRvIGdlbmVyYXRlIHRoZSBjdXJyZW50IG91dHB1dC5cbiAgICAgKiBOb3RlIHRoYXQgYSBzdGF0ZSBpcyBpbW11dGFibGUuXG4gICAgICovXG4gICAgLypmaW5hbCovIGNsYXNzIFN0YXRlIHtcbiAgICAgICAgY29uc3RydWN0b3IodG9rZW4sIG1vZGUsIGJpbmFyeUJ5dGVzLCBiaXRDb3VudCkge1xuICAgICAgICAgICAgdGhpcy50b2tlbiA9IHRva2VuO1xuICAgICAgICAgICAgdGhpcy5tb2RlID0gbW9kZTtcbiAgICAgICAgICAgIHRoaXMuYmluYXJ5U2hpZnRCeXRlQ291bnQgPSBiaW5hcnlCeXRlcztcbiAgICAgICAgICAgIHRoaXMuYml0Q291bnQgPSBiaXRDb3VudDtcbiAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSB3ZSBtYXRjaCB0aGUgdG9rZW5cbiAgICAgICAgICAgIC8vIGludCBiaW5hcnlTaGlmdEJpdENvdW50ID0gKGJpbmFyeVNoaWZ0Qnl0ZUNvdW50ICogOCkgK1xuICAgICAgICAgICAgLy8gICAgKGJpbmFyeVNoaWZ0Qnl0ZUNvdW50ID09PSAwID8gMCA6XG4gICAgICAgICAgICAvLyAgICAgYmluYXJ5U2hpZnRCeXRlQ291bnQgPD0gMzEgPyAxMCA6XG4gICAgICAgICAgICAvLyAgICAgYmluYXJ5U2hpZnRCeXRlQ291bnQgPD0gNjIgPyAyMCA6IDIxKTtcbiAgICAgICAgICAgIC8vIGFzc2VydCB0aGlzLmJpdENvdW50ID09PSB0b2tlbi5nZXRUb3RhbEJpdENvdW50KCkgKyBiaW5hcnlTaGlmdEJpdENvdW50O1xuICAgICAgICB9XG4gICAgICAgIGdldE1vZGUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tb2RlO1xuICAgICAgICB9XG4gICAgICAgIGdldFRva2VuKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9rZW47XG4gICAgICAgIH1cbiAgICAgICAgZ2V0QmluYXJ5U2hpZnRCeXRlQ291bnQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5iaW5hcnlTaGlmdEJ5dGVDb3VudDtcbiAgICAgICAgfVxuICAgICAgICBnZXRCaXRDb3VudCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJpdENvdW50O1xuICAgICAgICB9XG4gICAgICAgIC8vIENyZWF0ZSBhIG5ldyBzdGF0ZSByZXByZXNlbnRpbmcgdGhpcyBzdGF0ZSB3aXRoIGEgbGF0Y2ggdG8gYSAobm90XG4gICAgICAgIC8vIG5lY2Vzc2FyeSBkaWZmZXJlbnQpIG1vZGUsIGFuZCB0aGVuIGEgY29kZS5cbiAgICAgICAgbGF0Y2hBbmRBcHBlbmQobW9kZSwgdmFsdWUpIHtcbiAgICAgICAgICAgIC8vIGFzc2VydCBiaW5hcnlTaGlmdEJ5dGVDb3VudCA9PT0gMDtcbiAgICAgICAgICAgIGxldCBiaXRDb3VudCA9IHRoaXMuYml0Q291bnQ7XG4gICAgICAgICAgICBsZXQgdG9rZW4gPSB0aGlzLnRva2VuO1xuICAgICAgICAgICAgaWYgKG1vZGUgIT09IHRoaXMubW9kZSkge1xuICAgICAgICAgICAgICAgIGxldCBsYXRjaCA9IExBVENIX1RBQkxFW3RoaXMubW9kZV1bbW9kZV07XG4gICAgICAgICAgICAgICAgdG9rZW4gPSBhZGQodG9rZW4sIGxhdGNoICYgMHhmZmZmLCBsYXRjaCA+PiAxNik7XG4gICAgICAgICAgICAgICAgYml0Q291bnQgKz0gbGF0Y2ggPj4gMTY7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgbGF0Y2hNb2RlQml0Q291bnQgPSBtb2RlID09PSBNT0RFX0RJR0lUID8gNCA6IDU7XG4gICAgICAgICAgICB0b2tlbiA9IGFkZCh0b2tlbiwgdmFsdWUsIGxhdGNoTW9kZUJpdENvdW50KTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU3RhdGUodG9rZW4sIG1vZGUsIDAsIGJpdENvdW50ICsgbGF0Y2hNb2RlQml0Q291bnQpO1xuICAgICAgICB9XG4gICAgICAgIC8vIENyZWF0ZSBhIG5ldyBzdGF0ZSByZXByZXNlbnRpbmcgdGhpcyBzdGF0ZSwgd2l0aCBhIHRlbXBvcmFyeSBzaGlmdFxuICAgICAgICAvLyB0byBhIGRpZmZlcmVudCBtb2RlIHRvIG91dHB1dCBhIHNpbmdsZSB2YWx1ZS5cbiAgICAgICAgc2hpZnRBbmRBcHBlbmQobW9kZSwgdmFsdWUpIHtcbiAgICAgICAgICAgIC8vIGFzc2VydCBiaW5hcnlTaGlmdEJ5dGVDb3VudCA9PT0gMCAmJiB0aGlzLm1vZGUgIT09IG1vZGU7XG4gICAgICAgICAgICBsZXQgdG9rZW4gPSB0aGlzLnRva2VuO1xuICAgICAgICAgICAgbGV0IHRoaXNNb2RlQml0Q291bnQgPSB0aGlzLm1vZGUgPT09IE1PREVfRElHSVQgPyA0IDogNTtcbiAgICAgICAgICAgIC8vIFNoaWZ0cyBleGlzdCBvbmx5IHRvIFVQUEVSIGFuZCBQVU5DVCwgYm90aCB3aXRoIHRva2VucyBzaXplIDUuXG4gICAgICAgICAgICB0b2tlbiA9IGFkZCh0b2tlbiwgU0hJRlRfVEFCTEVbdGhpcy5tb2RlXVttb2RlXSwgdGhpc01vZGVCaXRDb3VudCk7XG4gICAgICAgICAgICB0b2tlbiA9IGFkZCh0b2tlbiwgdmFsdWUsIDUpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBTdGF0ZSh0b2tlbiwgdGhpcy5tb2RlLCAwLCB0aGlzLmJpdENvdW50ICsgdGhpc01vZGVCaXRDb3VudCArIDUpO1xuICAgICAgICB9XG4gICAgICAgIC8vIENyZWF0ZSBhIG5ldyBzdGF0ZSByZXByZXNlbnRpbmcgdGhpcyBzdGF0ZSwgYnV0IGFuIGFkZGl0aW9uYWwgY2hhcmFjdGVyXG4gICAgICAgIC8vIG91dHB1dCBpbiBCaW5hcnkgU2hpZnQgbW9kZS5cbiAgICAgICAgYWRkQmluYXJ5U2hpZnRDaGFyKGluZGV4KSB7XG4gICAgICAgICAgICBsZXQgdG9rZW4gPSB0aGlzLnRva2VuO1xuICAgICAgICAgICAgbGV0IG1vZGUgPSB0aGlzLm1vZGU7XG4gICAgICAgICAgICBsZXQgYml0Q291bnQgPSB0aGlzLmJpdENvdW50O1xuICAgICAgICAgICAgaWYgKHRoaXMubW9kZSA9PT0gTU9ERV9QVU5DVCB8fCB0aGlzLm1vZGUgPT09IE1PREVfRElHSVQpIHtcbiAgICAgICAgICAgICAgICAvLyBhc3NlcnQgYmluYXJ5U2hpZnRCeXRlQ291bnQgPT09IDA7XG4gICAgICAgICAgICAgICAgbGV0IGxhdGNoID0gTEFUQ0hfVEFCTEVbbW9kZV1bTU9ERV9VUFBFUl07XG4gICAgICAgICAgICAgICAgdG9rZW4gPSBhZGQodG9rZW4sIGxhdGNoICYgMHhmZmZmLCBsYXRjaCA+PiAxNik7XG4gICAgICAgICAgICAgICAgYml0Q291bnQgKz0gbGF0Y2ggPj4gMTY7XG4gICAgICAgICAgICAgICAgbW9kZSA9IE1PREVfVVBQRVI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgZGVsdGFCaXRDb3VudCA9IHRoaXMuYmluYXJ5U2hpZnRCeXRlQ291bnQgPT09IDAgfHwgdGhpcy5iaW5hcnlTaGlmdEJ5dGVDb3VudCA9PT0gMzFcbiAgICAgICAgICAgICAgICA/IDE4XG4gICAgICAgICAgICAgICAgOiB0aGlzLmJpbmFyeVNoaWZ0Qnl0ZUNvdW50ID09PSA2MlxuICAgICAgICAgICAgICAgICAgICA/IDlcbiAgICAgICAgICAgICAgICAgICAgOiA4O1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IG5ldyBTdGF0ZSh0b2tlbiwgbW9kZSwgdGhpcy5iaW5hcnlTaGlmdEJ5dGVDb3VudCArIDEsIGJpdENvdW50ICsgZGVsdGFCaXRDb3VudCk7XG4gICAgICAgICAgICBpZiAocmVzdWx0LmJpbmFyeVNoaWZ0Qnl0ZUNvdW50ID09PSAyMDQ3ICsgMzEpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGUgc3RyaW5nIGlzIGFzIGxvbmcgYXMgaXQncyBhbGxvd2VkIHRvIGJlLiAgV2Ugc2hvdWxkIGVuZCBpdC5cbiAgICAgICAgICAgICAgICByZXN1bHQgPSByZXN1bHQuZW5kQmluYXJ5U2hpZnQoaW5kZXggKyAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ3JlYXRlIHRoZSBzdGF0ZSBpZGVudGljYWwgdG8gdGhpcyBvbmUsIGJ1dCB3ZSBhcmUgbm8gbG9uZ2VyIGluXG4gICAgICAgIC8vIEJpbmFyeSBTaGlmdCBtb2RlLlxuICAgICAgICBlbmRCaW5hcnlTaGlmdChpbmRleCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuYmluYXJ5U2hpZnRCeXRlQ291bnQgPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCB0b2tlbiA9IHRoaXMudG9rZW47XG4gICAgICAgICAgICB0b2tlbiA9IGFkZEJpbmFyeVNoaWZ0KHRva2VuLCBpbmRleCAtIHRoaXMuYmluYXJ5U2hpZnRCeXRlQ291bnQsIHRoaXMuYmluYXJ5U2hpZnRCeXRlQ291bnQpO1xuICAgICAgICAgICAgLy8gYXNzZXJ0IHRva2VuLmdldFRvdGFsQml0Q291bnQoKSA9PT0gdGhpcy5iaXRDb3VudDtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU3RhdGUodG9rZW4sIHRoaXMubW9kZSwgMCwgdGhpcy5iaXRDb3VudCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmV0dXJucyB0cnVlIGlmIFwidGhpc1wiIHN0YXRlIGlzIGJldHRlciAoZXF1YWw6IG9yKSB0byBiZSBpbiB0aGFuIFwidGhhdFwiXG4gICAgICAgIC8vIHN0YXRlIHVuZGVyIGFsbCBwb3NzaWJsZSBjaXJjdW1zdGFuY2VzLlxuICAgICAgICBpc0JldHRlclRoYW5PckVxdWFsVG8ob3RoZXIpIHtcbiAgICAgICAgICAgIGxldCBuZXdNb2RlQml0Q291bnQgPSB0aGlzLmJpdENvdW50ICsgKExBVENIX1RBQkxFW3RoaXMubW9kZV1bb3RoZXIubW9kZV0gPj4gMTYpO1xuICAgICAgICAgICAgaWYgKHRoaXMuYmluYXJ5U2hpZnRCeXRlQ291bnQgPCBvdGhlci5iaW5hcnlTaGlmdEJ5dGVDb3VudCkge1xuICAgICAgICAgICAgICAgIC8vIGFkZCBhZGRpdGlvbmFsIEIvUyBlbmNvZGluZyBjb3N0IG9mIG90aGVyLCBpZiBhbnlcbiAgICAgICAgICAgICAgICBuZXdNb2RlQml0Q291bnQgKz1cbiAgICAgICAgICAgICAgICAgICAgU3RhdGUuY2FsY3VsYXRlQmluYXJ5U2hpZnRDb3N0KG90aGVyKSAtXG4gICAgICAgICAgICAgICAgICAgICAgICBTdGF0ZS5jYWxjdWxhdGVCaW5hcnlTaGlmdENvc3QodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLmJpbmFyeVNoaWZ0Qnl0ZUNvdW50ID4gb3RoZXIuYmluYXJ5U2hpZnRCeXRlQ291bnQgJiZcbiAgICAgICAgICAgICAgICBvdGhlci5iaW5hcnlTaGlmdEJ5dGVDb3VudCA+IDApIHtcbiAgICAgICAgICAgICAgICAvLyBtYXhpbXVtIHBvc3NpYmxlIGFkZGl0aW9uYWwgY29zdCAoaXQ6IGgpXG4gICAgICAgICAgICAgICAgbmV3TW9kZUJpdENvdW50ICs9IDEwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ld01vZGVCaXRDb3VudCA8PSBvdGhlci5iaXRDb3VudDtcbiAgICAgICAgfVxuICAgICAgICB0b0JpdEFycmF5KHRleHQpIHtcbiAgICAgICAgICAgIC8vIFJldmVyc2UgdGhlIHRva2Vucywgc28gdGhhdCB0aGV5IGFyZSBpbiB0aGUgb3JkZXIgdGhhdCB0aGV5IHNob3VsZFxuICAgICAgICAgICAgLy8gYmUgb3V0cHV0XG4gICAgICAgICAgICBsZXQgc3ltYm9scyA9IFtdO1xuICAgICAgICAgICAgZm9yIChsZXQgdG9rZW4gPSB0aGlzLmVuZEJpbmFyeVNoaWZ0KHRleHQubGVuZ3RoKS50b2tlbjsgdG9rZW4gIT09IG51bGw7IHRva2VuID0gdG9rZW4uZ2V0UHJldmlvdXMoKSkge1xuICAgICAgICAgICAgICAgIHN5bWJvbHMudW5zaGlmdCh0b2tlbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgYml0QXJyYXkgPSBuZXcgQml0QXJyYXkoKTtcbiAgICAgICAgICAgIC8vIEFkZCBlYWNoIHRva2VuIHRvIHRoZSByZXN1bHQuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IHN5bWJvbCBvZiBzeW1ib2xzKSB7XG4gICAgICAgICAgICAgICAgc3ltYm9sLmFwcGVuZFRvKGJpdEFycmF5LCB0ZXh0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGFzc2VydCBiaXRBcnJheS5nZXRTaXplKCkgPT09IHRoaXMuYml0Q291bnQ7XG4gICAgICAgICAgICByZXR1cm4gYml0QXJyYXk7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBPdmVycmlkZVxuICAgICAgICAgKi9cbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICByZXR1cm4gU3RyaW5nVXRpbHMuZm9ybWF0KCclcyBiaXRzPSVkIGJ5dGVzPSVkJywgTU9ERV9OQU1FU1t0aGlzLm1vZGVdLCB0aGlzLmJpdENvdW50LCB0aGlzLmJpbmFyeVNoaWZ0Qnl0ZUNvdW50KTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgY2FsY3VsYXRlQmluYXJ5U2hpZnRDb3N0KHN0YXRlKSB7XG4gICAgICAgICAgICBpZiAoc3RhdGUuYmluYXJ5U2hpZnRCeXRlQ291bnQgPiA2Mikge1xuICAgICAgICAgICAgICAgIHJldHVybiAyMTsgLy8gQi9TIHdpdGggZXh0ZW5kZWQgbGVuZ3RoXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RhdGUuYmluYXJ5U2hpZnRCeXRlQ291bnQgPiAzMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAyMDsgLy8gdHdvIEIvU1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0YXRlLmJpbmFyeVNoaWZ0Qnl0ZUNvdW50ID4gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAxMDsgLy8gb25lIEIvU1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cbiAgICB9XG4gICAgU3RhdGUuSU5JVElBTF9TVEFURSA9IG5ldyBTdGF0ZShFTVBUWV9UT0tFTiwgTU9ERV9VUFBFUiwgMCwgMCk7XG5cbiAgICBmdW5jdGlvbiBzdGF0aWNfQ0hBUl9NQVAoQ0hBUl9NQVApIHtcbiAgICAgICAgY29uc3Qgc3BhY2VDaGFyQ29kZSA9IFN0cmluZ1V0aWxzLmdldENoYXJDb2RlKCcgJyk7XG4gICAgICAgIGNvbnN0IHBvaW50Q2hhckNvZGUgPSBTdHJpbmdVdGlscy5nZXRDaGFyQ29kZSgnLicpO1xuICAgICAgICBjb25zdCBjb21tYUNoYXJDb2RlID0gU3RyaW5nVXRpbHMuZ2V0Q2hhckNvZGUoJywnKTtcbiAgICAgICAgQ0hBUl9NQVBbTU9ERV9VUFBFUl1bc3BhY2VDaGFyQ29kZV0gPSAxO1xuICAgICAgICBjb25zdCB6VXBwZXJDaGFyQ29kZSA9IFN0cmluZ1V0aWxzLmdldENoYXJDb2RlKCdaJyk7XG4gICAgICAgIGNvbnN0IGFVcHBlckNoYXJDb2RlID0gU3RyaW5nVXRpbHMuZ2V0Q2hhckNvZGUoJ0EnKTtcbiAgICAgICAgZm9yIChsZXQgYyA9IGFVcHBlckNoYXJDb2RlOyBjIDw9IHpVcHBlckNoYXJDb2RlOyBjKyspIHtcbiAgICAgICAgICAgIENIQVJfTUFQW01PREVfVVBQRVJdW2NdID0gYyAtIGFVcHBlckNoYXJDb2RlICsgMjtcbiAgICAgICAgfVxuICAgICAgICBDSEFSX01BUFtNT0RFX0xPV0VSXVtzcGFjZUNoYXJDb2RlXSA9IDE7XG4gICAgICAgIGNvbnN0IHpMb3dlckNoYXJDb2RlID0gU3RyaW5nVXRpbHMuZ2V0Q2hhckNvZGUoJ3onKTtcbiAgICAgICAgY29uc3QgYUxvd2VyQ2hhckNvZGUgPSBTdHJpbmdVdGlscy5nZXRDaGFyQ29kZSgnYScpO1xuICAgICAgICBmb3IgKGxldCBjID0gYUxvd2VyQ2hhckNvZGU7IGMgPD0gekxvd2VyQ2hhckNvZGU7IGMrKykge1xuICAgICAgICAgICAgQ0hBUl9NQVBbTU9ERV9MT1dFUl1bY10gPSBjIC0gYUxvd2VyQ2hhckNvZGUgKyAyO1xuICAgICAgICB9XG4gICAgICAgIENIQVJfTUFQW01PREVfRElHSVRdW3NwYWNlQ2hhckNvZGVdID0gMTtcbiAgICAgICAgY29uc3QgbmluZUNoYXJDb2RlID0gU3RyaW5nVXRpbHMuZ2V0Q2hhckNvZGUoJzknKTtcbiAgICAgICAgY29uc3QgemVyb0NoYXJDb2RlID0gU3RyaW5nVXRpbHMuZ2V0Q2hhckNvZGUoJzAnKTtcbiAgICAgICAgZm9yIChsZXQgYyA9IHplcm9DaGFyQ29kZTsgYyA8PSBuaW5lQ2hhckNvZGU7IGMrKykge1xuICAgICAgICAgICAgQ0hBUl9NQVBbTU9ERV9ESUdJVF1bY10gPSBjIC0gemVyb0NoYXJDb2RlICsgMjtcbiAgICAgICAgfVxuICAgICAgICBDSEFSX01BUFtNT0RFX0RJR0lUXVtjb21tYUNoYXJDb2RlXSA9IDEyO1xuICAgICAgICBDSEFSX01BUFtNT0RFX0RJR0lUXVtwb2ludENoYXJDb2RlXSA9IDEzO1xuICAgICAgICBjb25zdCBtaXhlZFRhYmxlID0gW1xuICAgICAgICAgICAgJ1xceDAwJyxcbiAgICAgICAgICAgICcgJyxcbiAgICAgICAgICAgICdcXHgwMScsXG4gICAgICAgICAgICAnXFx4MDInLFxuICAgICAgICAgICAgJ1xceDAzJyxcbiAgICAgICAgICAgICdcXHgwNCcsXG4gICAgICAgICAgICAnXFx4MDUnLFxuICAgICAgICAgICAgJ1xceDA2JyxcbiAgICAgICAgICAgICdcXHgwNycsXG4gICAgICAgICAgICAnXFxiJyxcbiAgICAgICAgICAgICdcXHQnLFxuICAgICAgICAgICAgJ1xcbicsXG4gICAgICAgICAgICAnXFx4MGInLFxuICAgICAgICAgICAgJ1xcZicsXG4gICAgICAgICAgICAnXFxyJyxcbiAgICAgICAgICAgICdcXHgxYicsXG4gICAgICAgICAgICAnXFx4MWMnLFxuICAgICAgICAgICAgJ1xceDFkJyxcbiAgICAgICAgICAgICdcXHgxZScsXG4gICAgICAgICAgICAnXFx4MWYnLFxuICAgICAgICAgICAgJ0AnLFxuICAgICAgICAgICAgJ1xcXFwnLFxuICAgICAgICAgICAgJ14nLFxuICAgICAgICAgICAgJ18nLFxuICAgICAgICAgICAgJ2AnLFxuICAgICAgICAgICAgJ3wnLFxuICAgICAgICAgICAgJ34nLFxuICAgICAgICAgICAgJ1xceDdmJ1xuICAgICAgICBdO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1peGVkVGFibGUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIENIQVJfTUFQW01PREVfTUlYRURdW1N0cmluZ1V0aWxzLmdldENoYXJDb2RlKG1peGVkVGFibGVbaV0pXSA9IGk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcHVuY3RUYWJsZSA9IFtcbiAgICAgICAgICAgICdcXHgwMCcsXG4gICAgICAgICAgICAnXFxyJyxcbiAgICAgICAgICAgICdcXHgwMCcsXG4gICAgICAgICAgICAnXFx4MDAnLFxuICAgICAgICAgICAgJ1xceDAwJyxcbiAgICAgICAgICAgICdcXHgwMCcsXG4gICAgICAgICAgICAnIScsXG4gICAgICAgICAgICAnXFwnJyxcbiAgICAgICAgICAgICcjJyxcbiAgICAgICAgICAgICckJyxcbiAgICAgICAgICAgICclJyxcbiAgICAgICAgICAgICcmJyxcbiAgICAgICAgICAgICdcXCcnLFxuICAgICAgICAgICAgJygnLFxuICAgICAgICAgICAgJyknLFxuICAgICAgICAgICAgJyonLFxuICAgICAgICAgICAgJysnLFxuICAgICAgICAgICAgJywnLFxuICAgICAgICAgICAgJy0nLFxuICAgICAgICAgICAgJy4nLFxuICAgICAgICAgICAgJy8nLFxuICAgICAgICAgICAgJzonLFxuICAgICAgICAgICAgJzsnLFxuICAgICAgICAgICAgJzwnLFxuICAgICAgICAgICAgJz0nLFxuICAgICAgICAgICAgJz4nLFxuICAgICAgICAgICAgJz8nLFxuICAgICAgICAgICAgJ1snLFxuICAgICAgICAgICAgJ10nLFxuICAgICAgICAgICAgJ3snLFxuICAgICAgICAgICAgJ30nXG4gICAgICAgIF07XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcHVuY3RUYWJsZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKFN0cmluZ1V0aWxzLmdldENoYXJDb2RlKHB1bmN0VGFibGVbaV0pID4gMCkge1xuICAgICAgICAgICAgICAgIENIQVJfTUFQW01PREVfUFVOQ1RdW1N0cmluZ1V0aWxzLmdldENoYXJDb2RlKHB1bmN0VGFibGVbaV0pXSA9IGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIENIQVJfTUFQO1xuICAgIH1cbiAgICBjb25zdCBDSEFSX01BUCA9IHN0YXRpY19DSEFSX01BUChBcnJheXMuY3JlYXRlSW50MzJBcnJheSg1LCAyNTYpKTtcblxuICAgIC8qXG4gICAgICogQ29weXJpZ2h0IDIwMTMgWlhpbmcgYXV0aG9yc1xuICAgICAqXG4gICAgICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAgICAgKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgICpcbiAgICAgKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICAgICAqXG4gICAgICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICAgICAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAgICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAgKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gICAgICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gICAgICovXG4gICAgLyoqXG4gICAgICogVGhpcyBwcm9kdWNlcyBuZWFybHkgb3B0aW1hbCBlbmNvZGluZ3Mgb2YgdGV4dCBpbnRvIHRoZSBmaXJzdC1sZXZlbCBvZlxuICAgICAqIGVuY29kaW5nIHVzZWQgYnkgQXp0ZWMgY29kZS5cbiAgICAgKlxuICAgICAqIEl0IHVzZXMgYSBkeW5hbWljIGFsZ29yaXRobS4gIEZvciBlYWNoIHByZWZpeCBvZiB0aGUgc3RyaW5nLCBpdCBkZXRlcm1pbmVzXG4gICAgICogYSBzZXQgb2YgZW5jb2RpbmdzIHRoYXQgY291bGQgbGVhZCB0byB0aGlzIHByZWZpeC4gIFdlIHJlcGVhdGVkbHkgYWRkIGFcbiAgICAgKiBjaGFyYWN0ZXIgYW5kIGdlbmVyYXRlIGEgbmV3IHNldCBvZiBvcHRpbWFsIGVuY29kaW5ncyB1bnRpbCB3ZSBoYXZlIHJlYWRcbiAgICAgKiB0aHJvdWdoIHRoZSBlbnRpcmUgaW5wdXQuXG4gICAgICpcbiAgICAgKiBAYXV0aG9yIEZyYW5rIFllbGxpblxuICAgICAqIEBhdXRob3IgUnVzdGFtIEFiZHVsbGFldlxuICAgICAqL1xuICAgIC8qcHVibGljIGZpbmFsKi8gY2xhc3MgSGlnaExldmVsRW5jb2RlciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKHRleHQpIHtcbiAgICAgICAgICAgIHRoaXMudGV4dCA9IHRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gdGV4dCByZXByZXNlbnRlZCBieSB0aGlzIGVuY29kZXIgZW5jb2RlZCBhcyBhIHtAbGluayBCaXRBcnJheX1cbiAgICAgICAgICovXG4gICAgICAgIGVuY29kZSgpIHtcbiAgICAgICAgICAgIGNvbnN0IHNwYWNlQ2hhckNvZGUgPSBTdHJpbmdVdGlscy5nZXRDaGFyQ29kZSgnICcpO1xuICAgICAgICAgICAgY29uc3QgbGluZUJyZWFrQ2hhckNvZGUgPSBTdHJpbmdVdGlscy5nZXRDaGFyQ29kZSgnXFxuJyk7XG4gICAgICAgICAgICBsZXQgc3RhdGVzID0gQ29sbGVjdGlvbnMuc2luZ2xldG9uTGlzdChTdGF0ZS5JTklUSUFMX1NUQVRFKTtcbiAgICAgICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCB0aGlzLnRleHQubGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IHBhaXJDb2RlO1xuICAgICAgICAgICAgICAgIGxldCBuZXh0Q2hhciA9IGluZGV4ICsgMSA8IHRoaXMudGV4dC5sZW5ndGggPyB0aGlzLnRleHRbaW5kZXggKyAxXSA6IDA7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnRleHRbaW5kZXhdKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgU3RyaW5nVXRpbHMuZ2V0Q2hhckNvZGUoJ1xccicpOlxuICAgICAgICAgICAgICAgICAgICAgICAgcGFpckNvZGUgPSBuZXh0Q2hhciA9PT0gbGluZUJyZWFrQ2hhckNvZGUgPyAyIDogMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFN0cmluZ1V0aWxzLmdldENoYXJDb2RlKCcuJyk6XG4gICAgICAgICAgICAgICAgICAgICAgICBwYWlyQ29kZSA9IG5leHRDaGFyID09PSBzcGFjZUNoYXJDb2RlID8gMyA6IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBTdHJpbmdVdGlscy5nZXRDaGFyQ29kZSgnLCcpOlxuICAgICAgICAgICAgICAgICAgICAgICAgcGFpckNvZGUgPSBuZXh0Q2hhciA9PT0gc3BhY2VDaGFyQ29kZSA/IDQgOiAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgU3RyaW5nVXRpbHMuZ2V0Q2hhckNvZGUoJzonKTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhaXJDb2RlID0gbmV4dENoYXIgPT09IHNwYWNlQ2hhckNvZGUgPyA1IDogMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcGFpckNvZGUgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocGFpckNvZGUgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIGhhdmUgb25lIG9mIHRoZSBmb3VyIHNwZWNpYWwgUFVOQ1QgcGFpcnMuICBUcmVhdCB0aGVtIHNwZWNpYWxseS5cbiAgICAgICAgICAgICAgICAgICAgLy8gR2V0IGEgbmV3IHNldCBvZiBzdGF0ZXMgZm9yIHRoZSB0d28gbmV3IGNoYXJhY3RlcnMuXG4gICAgICAgICAgICAgICAgICAgIHN0YXRlcyA9IEhpZ2hMZXZlbEVuY29kZXIudXBkYXRlU3RhdGVMaXN0Rm9yUGFpcihzdGF0ZXMsIGluZGV4LCBwYWlyQ29kZSk7XG4gICAgICAgICAgICAgICAgICAgIGluZGV4Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBHZXQgYSBuZXcgc2V0IG9mIHN0YXRlcyBmb3IgdGhlIG5ldyBjaGFyYWN0ZXIuXG4gICAgICAgICAgICAgICAgICAgIHN0YXRlcyA9IHRoaXMudXBkYXRlU3RhdGVMaXN0Rm9yQ2hhcihzdGF0ZXMsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBXZSBhcmUgbGVmdCB3aXRoIGEgc2V0IG9mIHN0YXRlcy4gIEZpbmQgdGhlIHNob3J0ZXN0IG9uZS5cbiAgICAgICAgICAgIGNvbnN0IG1pblN0YXRlID0gQ29sbGVjdGlvbnMubWluKHN0YXRlcywgKGEsIGIpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYS5nZXRCaXRDb3VudCgpIC0gYi5nZXRCaXRDb3VudCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAvLyBDb252ZXJ0IGl0IHRvIGEgYml0IGFycmF5LCBhbmQgcmV0dXJuLlxuICAgICAgICAgICAgcmV0dXJuIG1pblN0YXRlLnRvQml0QXJyYXkodGhpcy50ZXh0KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBXZSB1cGRhdGUgYSBzZXQgb2Ygc3RhdGVzIGZvciBhIG5ldyBjaGFyYWN0ZXIgYnkgdXBkYXRpbmcgZWFjaCBzdGF0ZVxuICAgICAgICAvLyBmb3IgdGhlIG5ldyBjaGFyYWN0ZXIsIG1lcmdpbmcgdGhlIHJlc3VsdHMsIGFuZCB0aGVuIHJlbW92aW5nIHRoZVxuICAgICAgICAvLyBub24tb3B0aW1hbCBzdGF0ZXMuXG4gICAgICAgIHVwZGF0ZVN0YXRlTGlzdEZvckNoYXIoc3RhdGVzLCBpbmRleCkge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgICAgICAgICBmb3IgKGxldCBzdGF0ZSAvKlN0YXRlKi8gb2Ygc3RhdGVzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVTdGF0ZUZvckNoYXIoc3RhdGUsIGluZGV4LCByZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIEhpZ2hMZXZlbEVuY29kZXIuc2ltcGxpZnlTdGF0ZXMocmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBSZXR1cm4gYSBzZXQgb2Ygc3RhdGVzIHRoYXQgcmVwcmVzZW50IHRoZSBwb3NzaWJsZSB3YXlzIG9mIHVwZGF0aW5nIHRoaXNcbiAgICAgICAgLy8gc3RhdGUgZm9yIHRoZSBuZXh0IGNoYXJhY3Rlci4gIFRoZSByZXN1bHRpbmcgc2V0IG9mIHN0YXRlcyBhcmUgYWRkZWQgdG9cbiAgICAgICAgLy8gdGhlIFwicmVzdWx0XCIgbGlzdC5cbiAgICAgICAgdXBkYXRlU3RhdGVGb3JDaGFyKHN0YXRlLCBpbmRleCwgcmVzdWx0KSB7XG4gICAgICAgICAgICBsZXQgY2ggPSAodGhpcy50ZXh0W2luZGV4XSAmIDB4ZmYpO1xuICAgICAgICAgICAgbGV0IGNoYXJJbkN1cnJlbnRUYWJsZSA9IENIQVJfTUFQW3N0YXRlLmdldE1vZGUoKV1bY2hdID4gMDtcbiAgICAgICAgICAgIGxldCBzdGF0ZU5vQmluYXJ5ID0gbnVsbDtcbiAgICAgICAgICAgIGZvciAobGV0IG1vZGUgLyppbnQqLyA9IDA7IG1vZGUgPD0gTU9ERV9QVU5DVDsgbW9kZSsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IGNoYXJJbk1vZGUgPSBDSEFSX01BUFttb2RlXVtjaF07XG4gICAgICAgICAgICAgICAgaWYgKGNoYXJJbk1vZGUgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0ZU5vQmluYXJ5ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9ubHkgY3JlYXRlIHN0YXRlTm9CaW5hcnkgdGhlIGZpcnN0IHRpbWUgaXQncyByZXF1aXJlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlTm9CaW5hcnkgPSBzdGF0ZS5lbmRCaW5hcnlTaGlmdChpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gVHJ5IGdlbmVyYXRpbmcgdGhlIGNoYXJhY3RlciBieSBsYXRjaGluZyB0byBpdHMgbW9kZVxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNoYXJJbkN1cnJlbnRUYWJsZSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgbW9kZSA9PT0gc3RhdGUuZ2V0TW9kZSgpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICBtb2RlID09PSBNT0RFX0RJR0lUKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgY2hhcmFjdGVyIGlzIGluIHRoZSBjdXJyZW50IHRhYmxlLCB3ZSBkb24ndCB3YW50IHRvIGxhdGNoIHRvXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhbnkgb3RoZXIgbW9kZSBleGNlcHQgcG9zc2libHkgZGlnaXQgKHdoaWNoIHVzZXMgb25seSA0IGJpdHMpLiAgQW55XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBvdGhlciBsYXRjaCB3b3VsZCBiZSBlcXVhbGx5IHN1Y2Nlc3NmdWwgKmFmdGVyKiB0aGlzIGNoYXJhY3RlciwgYW5kXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzbyB3b3VsZG4ndCBzYXZlIGFueSBiaXRzLlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbGF0Y2hTdGF0ZSA9IHN0YXRlTm9CaW5hcnkubGF0Y2hBbmRBcHBlbmQobW9kZSwgY2hhckluTW9kZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChsYXRjaFN0YXRlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBUcnkgZ2VuZXJhdGluZyB0aGUgY2hhcmFjdGVyIGJ5IHN3aXRjaGluZyB0byBpdHMgbW9kZS5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjaGFySW5DdXJyZW50VGFibGUgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIFNISUZUX1RBQkxFW3N0YXRlLmdldE1vZGUoKV1bbW9kZV0gPj0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSXQgbmV2ZXIgbWFrZXMgc2Vuc2UgdG8gdGVtcG9yYXJpbHkgc2hpZnQgdG8gYW5vdGhlciBtb2RlIGlmIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2hhcmFjdGVyIGV4aXN0cyBpbiB0aGUgY3VycmVudCBtb2RlLiAgVGhhdCBjYW4gbmV2ZXIgc2F2ZSBiaXRzLlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2hpZnRTdGF0ZSA9IHN0YXRlTm9CaW5hcnkuc2hpZnRBbmRBcHBlbmQobW9kZSwgY2hhckluTW9kZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChzaGlmdFN0YXRlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzdGF0ZS5nZXRCaW5hcnlTaGlmdEJ5dGVDb3VudCgpID4gMCB8fFxuICAgICAgICAgICAgICAgIENIQVJfTUFQW3N0YXRlLmdldE1vZGUoKV1bY2hdID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gSXQncyBuZXZlciB3b3J0aHdoaWxlIHRvIGdvIGludG8gYmluYXJ5IHNoaWZ0IG1vZGUgaWYgeW91J3JlIG5vdCBhbHJlYWR5XG4gICAgICAgICAgICAgICAgLy8gaW4gYmluYXJ5IHNoaWZ0IG1vZGUsIGFuZCB0aGUgY2hhcmFjdGVyIGV4aXN0cyBpbiB5b3VyIGN1cnJlbnQgbW9kZS5cbiAgICAgICAgICAgICAgICAvLyBUaGF0IGNhbiBuZXZlciBzYXZlIGJpdHMgb3ZlciBqdXN0IG91dHB1dHRpbmcgdGhlIGNoYXIgaW4gdGhlIGN1cnJlbnQgbW9kZS5cbiAgICAgICAgICAgICAgICBsZXQgYmluYXJ5U3RhdGUgPSBzdGF0ZS5hZGRCaW5hcnlTaGlmdENoYXIoaW5kZXgpO1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKGJpbmFyeVN0YXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgdXBkYXRlU3RhdGVMaXN0Rm9yUGFpcihzdGF0ZXMsIGluZGV4LCBwYWlyQ29kZSkge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgICAgICAgICBmb3IgKGxldCBzdGF0ZSAvKlN0YXRlKi8gb2Ygc3RhdGVzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVTdGF0ZUZvclBhaXIoc3RhdGUsIGluZGV4LCBwYWlyQ29kZSwgcmVzdWx0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNpbXBsaWZ5U3RhdGVzKHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHVwZGF0ZVN0YXRlRm9yUGFpcihzdGF0ZSwgaW5kZXgsIHBhaXJDb2RlLCByZXN1bHQpIHtcbiAgICAgICAgICAgIGxldCBzdGF0ZU5vQmluYXJ5ID0gc3RhdGUuZW5kQmluYXJ5U2hpZnQoaW5kZXgpO1xuICAgICAgICAgICAgLy8gUG9zc2liaWxpdHkgMS4gIExhdGNoIHRvIEMuTU9ERV9QVU5DVCwgYW5kIHRoZW4gYXBwZW5kIHRoaXMgY29kZVxuICAgICAgICAgICAgcmVzdWx0LnB1c2goc3RhdGVOb0JpbmFyeS5sYXRjaEFuZEFwcGVuZChNT0RFX1BVTkNULCBwYWlyQ29kZSkpO1xuICAgICAgICAgICAgaWYgKHN0YXRlLmdldE1vZGUoKSAhPT0gTU9ERV9QVU5DVCkge1xuICAgICAgICAgICAgICAgIC8vIFBvc3NpYmlsaXR5IDIuICBTaGlmdCB0byBDLk1PREVfUFVOQ1QsIGFuZCB0aGVuIGFwcGVuZCB0aGlzIGNvZGUuXG4gICAgICAgICAgICAgICAgLy8gRXZlcnkgc3RhdGUgZXhjZXB0IEMuTU9ERV9QVU5DVCAoaGFuZGxlZCBhYm92ZSkgY2FuIHNoaWZ0XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goc3RhdGVOb0JpbmFyeS5zaGlmdEFuZEFwcGVuZChNT0RFX1BVTkNULCBwYWlyQ29kZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBhaXJDb2RlID09PSAzIHx8IHBhaXJDb2RlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgLy8gYm90aCBjaGFyYWN0ZXJzIGFyZSBpbiBESUdJVFMuICBTb21ldGltZXMgYmV0dGVyIHRvIGp1c3QgYWRkIHR3byBkaWdpdHNcbiAgICAgICAgICAgICAgICBsZXQgZGlnaXRTdGF0ZSA9IHN0YXRlTm9CaW5hcnlcbiAgICAgICAgICAgICAgICAgICAgLmxhdGNoQW5kQXBwZW5kKE1PREVfRElHSVQsIDE2IC0gcGFpckNvZGUpIC8vIHBlcmlvZCBvciBjb21tYSBpbiBESUdJVFxuICAgICAgICAgICAgICAgICAgICAubGF0Y2hBbmRBcHBlbmQoTU9ERV9ESUdJVCwgMSk7IC8vIHNwYWNlIGluIERJR0lUXG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goZGlnaXRTdGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RhdGUuZ2V0QmluYXJ5U2hpZnRCeXRlQ291bnQoKSA+IDApIHtcbiAgICAgICAgICAgICAgICAvLyBJdCBvbmx5IG1ha2VzIHNlbnNlIHRvIGRvIHRoZSBjaGFyYWN0ZXJzIGFzIGJpbmFyeSBpZiB3ZSdyZSBhbHJlYWR5XG4gICAgICAgICAgICAgICAgLy8gaW4gYmluYXJ5IG1vZGUuXG4gICAgICAgICAgICAgICAgbGV0IGJpbmFyeVN0YXRlID0gc3RhdGVcbiAgICAgICAgICAgICAgICAgICAgLmFkZEJpbmFyeVNoaWZ0Q2hhcihpbmRleClcbiAgICAgICAgICAgICAgICAgICAgLmFkZEJpbmFyeVNoaWZ0Q2hhcihpbmRleCArIDEpO1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKGJpbmFyeVN0YXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgc2ltcGxpZnlTdGF0ZXMoc3RhdGVzKSB7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICAgICAgICBmb3IgKGNvbnN0IG5ld1N0YXRlIG9mIHN0YXRlcykge1xuICAgICAgICAgICAgICAgIGxldCBhZGQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgb2xkU3RhdGUgb2YgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvbGRTdGF0ZS5pc0JldHRlclRoYW5PckVxdWFsVG8obmV3U3RhdGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdTdGF0ZS5pc0JldHRlclRoYW5PckVxdWFsVG8ob2xkU3RhdGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVyYXRvci5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5maWx0ZXIoeCA9PiB4ICE9PSBvbGRTdGF0ZSk7IC8vIHJlbW92ZSBvbGQgc3RhdGVcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYWRkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKG5ld1N0YXRlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb3B5cmlnaHQgMjAxMyBaWGluZyBhdXRob3JzXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgICAgKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgICAgKlxuICAgICAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gICAgICpcbiAgICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICAgICAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAgKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAgICAgKi9cbiAgICAvLyBwYWNrYWdlIGNvbS5nb29nbGUuenhpbmcuYXp0ZWMuZW5jb2RlcjtcbiAgICAvLyBpbXBvcnQgY29tLmdvb2dsZS56eGluZy5jb21tb24uQml0QXJyYXk7XG4gICAgLy8gaW1wb3J0IGNvbS5nb29nbGUuenhpbmcuY29tbW9uLkJpdE1hdHJpeDtcbiAgICAvLyBpbXBvcnQgY29tLmdvb2dsZS56eGluZy5jb21tb24ucmVlZHNvbG9tb24uR2VuZXJpY0dGO1xuICAgIC8vIGltcG9ydCBjb20uZ29vZ2xlLnp4aW5nLmNvbW1vbi5yZWVkc29sb21vbi5SZWVkU29sb21vbkVuY29kZXI7XG4gICAgLyoqXG4gICAgICogR2VuZXJhdGVzIEF6dGVjIDJEIGJhcmNvZGVzLlxuICAgICAqXG4gICAgICogQGF1dGhvciBSdXN0YW0gQWJkdWxsYWV2XG4gICAgICovXG4gICAgLypwdWJsaWMgZmluYWwqLyBjbGFzcyBFbmNvZGVyJDEge1xuICAgICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgZ2l2ZW4gYmluYXJ5IGNvbnRlbnQgYXMgYW4gQXp0ZWMgc3ltYm9sXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBkYXRhIGlucHV0IGRhdGEgc3RyaW5nXG4gICAgICAgICAqIEByZXR1cm4gQXp0ZWMgc3ltYm9sIG1hdHJpeCB3aXRoIG1ldGFkYXRhXG4gICAgICAgICAqL1xuICAgICAgICBzdGF0aWMgZW5jb2RlQnl0ZXMoZGF0YSkge1xuICAgICAgICAgICAgcmV0dXJuIEVuY29kZXIkMS5lbmNvZGUoZGF0YSwgRW5jb2RlciQxLkRFRkFVTFRfRUNfUEVSQ0VOVCwgRW5jb2RlciQxLkRFRkFVTFRfQVpURUNfTEFZRVJTKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgZ2l2ZW4gYmluYXJ5IGNvbnRlbnQgYXMgYW4gQXp0ZWMgc3ltYm9sXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBkYXRhIGlucHV0IGRhdGEgc3RyaW5nXG4gICAgICAgICAqIEBwYXJhbSBtaW5FQ0NQZXJjZW50IG1pbmltYWwgcGVyY2VudGFnZSBvZiBlcnJvciBjaGVjayB3b3JkcyAoQWNjb3JkaW5nIHRvIElTTy9JRUMgMjQ3Nzg6MjAwOCxcbiAgICAgICAgICogICAgICAgICAgICAgICAgICAgICAgYSBtaW5pbXVtIG9mIDIzJSArIDMgd29yZHMgaXMgcmVjb21tZW5kZWQpXG4gICAgICAgICAqIEBwYXJhbSB1c2VyU3BlY2lmaWVkTGF5ZXJzIGlmIG5vbi16ZXJvLCBhIHVzZXItc3BlY2lmaWVkIHZhbHVlIGZvciB0aGUgbnVtYmVyIG9mIGxheWVyc1xuICAgICAgICAgKiBAcmV0dXJuIEF6dGVjIHN5bWJvbCBtYXRyaXggd2l0aCBtZXRhZGF0YVxuICAgICAgICAgKi9cbiAgICAgICAgc3RhdGljIGVuY29kZShkYXRhLCBtaW5FQ0NQZXJjZW50LCB1c2VyU3BlY2lmaWVkTGF5ZXJzKSB7XG4gICAgICAgICAgICAvLyBIaWdoLWxldmVsIGVuY29kZVxuICAgICAgICAgICAgbGV0IGJpdHMgPSBuZXcgSGlnaExldmVsRW5jb2RlcihkYXRhKS5lbmNvZGUoKTtcbiAgICAgICAgICAgIC8vIHN0dWZmIGJpdHMgYW5kIGNob29zZSBzeW1ib2wgc2l6ZVxuICAgICAgICAgICAgbGV0IGVjY0JpdHMgPSBJbnRlZ2VyLnRydW5jRGl2aXNpb24oKGJpdHMuZ2V0U2l6ZSgpICogbWluRUNDUGVyY2VudCksIDEwMCkgKyAxMTtcbiAgICAgICAgICAgIGxldCB0b3RhbFNpemVCaXRzID0gYml0cy5nZXRTaXplKCkgKyBlY2NCaXRzO1xuICAgICAgICAgICAgbGV0IGNvbXBhY3Q7XG4gICAgICAgICAgICBsZXQgbGF5ZXJzO1xuICAgICAgICAgICAgbGV0IHRvdGFsQml0c0luTGF5ZXI7XG4gICAgICAgICAgICBsZXQgd29yZFNpemU7XG4gICAgICAgICAgICBsZXQgc3R1ZmZlZEJpdHM7XG4gICAgICAgICAgICBpZiAodXNlclNwZWNpZmllZExheWVycyAhPT0gRW5jb2RlciQxLkRFRkFVTFRfQVpURUNfTEFZRVJTKSB7XG4gICAgICAgICAgICAgICAgY29tcGFjdCA9IHVzZXJTcGVjaWZpZWRMYXllcnMgPCAwO1xuICAgICAgICAgICAgICAgIGxheWVycyA9IE1hdGguYWJzKHVzZXJTcGVjaWZpZWRMYXllcnMpO1xuICAgICAgICAgICAgICAgIGlmIChsYXllcnMgPiAoY29tcGFjdCA/IEVuY29kZXIkMS5NQVhfTkJfQklUU19DT01QQUNUIDogRW5jb2RlciQxLk1BWF9OQl9CSVRTKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKFN0cmluZ1V0aWxzLmZvcm1hdCgnSWxsZWdhbCB2YWx1ZSAlcyBmb3IgbGF5ZXJzJywgdXNlclNwZWNpZmllZExheWVycykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0b3RhbEJpdHNJbkxheWVyID0gRW5jb2RlciQxLnRvdGFsQml0c0luTGF5ZXIobGF5ZXJzLCBjb21wYWN0KTtcbiAgICAgICAgICAgICAgICB3b3JkU2l6ZSA9IEVuY29kZXIkMS5XT1JEX1NJWkVbbGF5ZXJzXTtcbiAgICAgICAgICAgICAgICBsZXQgdXNhYmxlQml0c0luTGF5ZXJzID0gdG90YWxCaXRzSW5MYXllciAtICh0b3RhbEJpdHNJbkxheWVyICUgd29yZFNpemUpO1xuICAgICAgICAgICAgICAgIHN0dWZmZWRCaXRzID0gRW5jb2RlciQxLnN0dWZmQml0cyhiaXRzLCB3b3JkU2l6ZSk7XG4gICAgICAgICAgICAgICAgaWYgKHN0dWZmZWRCaXRzLmdldFNpemUoKSArIGVjY0JpdHMgPiB1c2FibGVCaXRzSW5MYXllcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignRGF0YSB0byBsYXJnZSBmb3IgdXNlciBzcGVjaWZpZWQgbGF5ZXInKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBhY3QgJiYgc3R1ZmZlZEJpdHMuZ2V0U2l6ZSgpID4gd29yZFNpemUgKiA2NCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBDb21wYWN0IGZvcm1hdCBvbmx5IGFsbG93cyA2NCBkYXRhIHdvcmRzLCB0aG91Z2ggQzQgY2FuIGhvbGQgbW9yZSB3b3JkcyB0aGFuIHRoYXRcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignRGF0YSB0byBsYXJnZSBmb3IgdXNlciBzcGVjaWZpZWQgbGF5ZXInKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB3b3JkU2l6ZSA9IDA7XG4gICAgICAgICAgICAgICAgc3R1ZmZlZEJpdHMgPSBudWxsO1xuICAgICAgICAgICAgICAgIC8vIFdlIGxvb2sgYXQgdGhlIHBvc3NpYmxlIHRhYmxlIHNpemVzIGluIHRoZSBvcmRlciBDb21wYWN0MSwgQ29tcGFjdDIsIENvbXBhY3QzLFxuICAgICAgICAgICAgICAgIC8vIENvbXBhY3Q0LCBOb3JtYWw0LC4uLiAgTm9ybWFsKGkpIGZvciBpIDwgNCBpc24ndCB0eXBpY2FsbHkgdXNlZCBzaW5jZSBDb21wYWN0KGkrMSlcbiAgICAgICAgICAgICAgICAvLyBpcyB0aGUgc2FtZSBzaXplLCBidXQgaGFzIG1vcmUgZGF0YS5cbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAwOzsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpID4gRW5jb2RlciQxLk1BWF9OQl9CSVRTKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCdEYXRhIHRvbyBsYXJnZSBmb3IgYW4gQXp0ZWMgY29kZScpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbXBhY3QgPSBpIDw9IDM7XG4gICAgICAgICAgICAgICAgICAgIGxheWVycyA9IGNvbXBhY3QgPyBpICsgMSA6IGk7XG4gICAgICAgICAgICAgICAgICAgIHRvdGFsQml0c0luTGF5ZXIgPSBFbmNvZGVyJDEudG90YWxCaXRzSW5MYXllcihsYXllcnMsIGNvbXBhY3QpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodG90YWxTaXplQml0cyA+IHRvdGFsQml0c0luTGF5ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIFtSZV1zdHVmZiB0aGUgYml0cyBpZiB0aGlzIGlzIHRoZSBmaXJzdCBvcHBvcnR1bml0eSwgb3IgaWYgdGhlXG4gICAgICAgICAgICAgICAgICAgIC8vIHdvcmRTaXplIGhhcyBjaGFuZ2VkXG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHVmZmVkQml0cyA9PSBudWxsIHx8IHdvcmRTaXplICE9PSBFbmNvZGVyJDEuV09SRF9TSVpFW2xheWVyc10pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmRTaXplID0gRW5jb2RlciQxLldPUkRfU0laRVtsYXllcnNdO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3R1ZmZlZEJpdHMgPSBFbmNvZGVyJDEuc3R1ZmZCaXRzKGJpdHMsIHdvcmRTaXplKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBsZXQgdXNhYmxlQml0c0luTGF5ZXJzID0gdG90YWxCaXRzSW5MYXllciAtICh0b3RhbEJpdHNJbkxheWVyICUgd29yZFNpemUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29tcGFjdCAmJiBzdHVmZmVkQml0cy5nZXRTaXplKCkgPiB3b3JkU2l6ZSAqIDY0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBDb21wYWN0IGZvcm1hdCBvbmx5IGFsbG93cyA2NCBkYXRhIHdvcmRzLCB0aG91Z2ggQzQgY2FuIGhvbGQgbW9yZSB3b3JkcyB0aGFuIHRoYXRcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHVmZmVkQml0cy5nZXRTaXplKCkgKyBlY2NCaXRzIDw9IHVzYWJsZUJpdHNJbkxheWVycykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgbWVzc2FnZUJpdHMgPSBFbmNvZGVyJDEuZ2VuZXJhdGVDaGVja1dvcmRzKHN0dWZmZWRCaXRzLCB0b3RhbEJpdHNJbkxheWVyLCB3b3JkU2l6ZSk7XG4gICAgICAgICAgICAvLyBnZW5lcmF0ZSBtb2RlIG1lc3NhZ2VcbiAgICAgICAgICAgIGxldCBtZXNzYWdlU2l6ZUluV29yZHMgPSBzdHVmZmVkQml0cy5nZXRTaXplKCkgLyB3b3JkU2l6ZTtcbiAgICAgICAgICAgIGxldCBtb2RlTWVzc2FnZSA9IEVuY29kZXIkMS5nZW5lcmF0ZU1vZGVNZXNzYWdlKGNvbXBhY3QsIGxheWVycywgbWVzc2FnZVNpemVJbldvcmRzKTtcbiAgICAgICAgICAgIC8vIGFsbG9jYXRlIHN5bWJvbFxuICAgICAgICAgICAgbGV0IGJhc2VNYXRyaXhTaXplID0gKGNvbXBhY3QgPyAxMSA6IDE0KSArIGxheWVycyAqIDQ7IC8vIG5vdCBpbmNsdWRpbmcgYWxpZ25tZW50IGxpbmVzXG4gICAgICAgICAgICBsZXQgYWxpZ25tZW50TWFwID0gbmV3IEludDMyQXJyYXkoYmFzZU1hdHJpeFNpemUpO1xuICAgICAgICAgICAgbGV0IG1hdHJpeFNpemU7XG4gICAgICAgICAgICBpZiAoY29tcGFjdCkge1xuICAgICAgICAgICAgICAgIC8vIG5vIGFsaWdubWVudCBtYXJrcyBpbiBjb21wYWN0IG1vZGUsIGFsaWdubWVudE1hcCBpcyBhIG5vLW9wXG4gICAgICAgICAgICAgICAgbWF0cml4U2l6ZSA9IGJhc2VNYXRyaXhTaXplO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCBhbGlnbm1lbnRNYXAubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgYWxpZ25tZW50TWFwW2ldID0gaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBtYXRyaXhTaXplID0gYmFzZU1hdHJpeFNpemUgKyAxICsgMiAqIEludGVnZXIudHJ1bmNEaXZpc2lvbigoSW50ZWdlci50cnVuY0RpdmlzaW9uKGJhc2VNYXRyaXhTaXplLCAyKSAtIDEpLCAxNSk7XG4gICAgICAgICAgICAgICAgbGV0IG9yaWdDZW50ZXIgPSBJbnRlZ2VyLnRydW5jRGl2aXNpb24oYmFzZU1hdHJpeFNpemUsIDIpO1xuICAgICAgICAgICAgICAgIGxldCBjZW50ZXIgPSBJbnRlZ2VyLnRydW5jRGl2aXNpb24obWF0cml4U2l6ZSwgMik7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMDsgaSA8IG9yaWdDZW50ZXI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgbmV3T2Zmc2V0ID0gaSArIEludGVnZXIudHJ1bmNEaXZpc2lvbihpLCAxNSk7XG4gICAgICAgICAgICAgICAgICAgIGFsaWdubWVudE1hcFtvcmlnQ2VudGVyIC0gaSAtIDFdID0gY2VudGVyIC0gbmV3T2Zmc2V0IC0gMTtcbiAgICAgICAgICAgICAgICAgICAgYWxpZ25tZW50TWFwW29yaWdDZW50ZXIgKyBpXSA9IGNlbnRlciArIG5ld09mZnNldCArIDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IG1hdHJpeCA9IG5ldyBCaXRNYXRyaXgobWF0cml4U2l6ZSk7XG4gICAgICAgICAgICAvLyBkcmF3IGRhdGEgYml0c1xuICAgICAgICAgICAgZm9yIChsZXQgaSAvKmludCovID0gMCwgcm93T2Zmc2V0ID0gMDsgaSA8IGxheWVyczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbGV0IHJvd1NpemUgPSAobGF5ZXJzIC0gaSkgKiA0ICsgKGNvbXBhY3QgPyA5IDogMTIpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogLyppbnQqLyA9IDA7IGogPCByb3dTaXplOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNvbHVtbk9mZnNldCA9IGogKiAyO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBrIC8qaW50Ki8gPSAwOyBrIDwgMjsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobWVzc2FnZUJpdHMuZ2V0KHJvd09mZnNldCArIGNvbHVtbk9mZnNldCArIGspKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChhbGlnbm1lbnRNYXBbaSAqIDIgKyBrXSwgYWxpZ25tZW50TWFwW2kgKiAyICsgal0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2VCaXRzLmdldChyb3dPZmZzZXQgKyByb3dTaXplICogMiArIGNvbHVtbk9mZnNldCArIGspKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChhbGlnbm1lbnRNYXBbaSAqIDIgKyBqXSwgYWxpZ25tZW50TWFwW2Jhc2VNYXRyaXhTaXplIC0gMSAtIGkgKiAyIC0ga10pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2VCaXRzLmdldChyb3dPZmZzZXQgKyByb3dTaXplICogNCArIGNvbHVtbk9mZnNldCArIGspKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChhbGlnbm1lbnRNYXBbYmFzZU1hdHJpeFNpemUgLSAxIC0gaSAqIDIgLSBrXSwgYWxpZ25tZW50TWFwW2Jhc2VNYXRyaXhTaXplIC0gMSAtIGkgKiAyIC0gal0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2VCaXRzLmdldChyb3dPZmZzZXQgKyByb3dTaXplICogNiArIGNvbHVtbk9mZnNldCArIGspKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChhbGlnbm1lbnRNYXBbYmFzZU1hdHJpeFNpemUgLSAxIC0gaSAqIDIgLSBqXSwgYWxpZ25tZW50TWFwW2kgKiAyICsga10pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJvd09mZnNldCArPSByb3dTaXplICogODtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGRyYXcgbW9kZSBtZXNzYWdlXG4gICAgICAgICAgICBFbmNvZGVyJDEuZHJhd01vZGVNZXNzYWdlKG1hdHJpeCwgY29tcGFjdCwgbWF0cml4U2l6ZSwgbW9kZU1lc3NhZ2UpO1xuICAgICAgICAgICAgLy8gZHJhdyBhbGlnbm1lbnQgbWFya3NcbiAgICAgICAgICAgIGlmIChjb21wYWN0KSB7XG4gICAgICAgICAgICAgICAgRW5jb2RlciQxLmRyYXdCdWxsc0V5ZShtYXRyaXgsIEludGVnZXIudHJ1bmNEaXZpc2lvbihtYXRyaXhTaXplLCAyKSwgNSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBFbmNvZGVyJDEuZHJhd0J1bGxzRXllKG1hdHJpeCwgSW50ZWdlci50cnVuY0RpdmlzaW9uKG1hdHJpeFNpemUsIDIpLCA3KTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAwLCBqID0gMDsgaSA8IEludGVnZXIudHJ1bmNEaXZpc2lvbihiYXNlTWF0cml4U2l6ZSwgMikgLSAxOyBpICs9IDE1LCBqICs9IDE2KSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGsgLyppbnQqLyA9IEludGVnZXIudHJ1bmNEaXZpc2lvbihtYXRyaXhTaXplLCAyKSAmIDE7IGsgPCBtYXRyaXhTaXplOyBrICs9IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXQoSW50ZWdlci50cnVuY0RpdmlzaW9uKG1hdHJpeFNpemUsIDIpIC0gaiwgayk7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KEludGVnZXIudHJ1bmNEaXZpc2lvbihtYXRyaXhTaXplLCAyKSArIGosIGspO1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChrLCBJbnRlZ2VyLnRydW5jRGl2aXNpb24obWF0cml4U2l6ZSwgMikgLSBqKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXQoaywgSW50ZWdlci50cnVuY0RpdmlzaW9uKG1hdHJpeFNpemUsIDIpICsgaik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgYXp0ZWMgPSBuZXcgQXp0ZWNDb2RlKCk7XG4gICAgICAgICAgICBhenRlYy5zZXRDb21wYWN0KGNvbXBhY3QpO1xuICAgICAgICAgICAgYXp0ZWMuc2V0U2l6ZShtYXRyaXhTaXplKTtcbiAgICAgICAgICAgIGF6dGVjLnNldExheWVycyhsYXllcnMpO1xuICAgICAgICAgICAgYXp0ZWMuc2V0Q29kZVdvcmRzKG1lc3NhZ2VTaXplSW5Xb3Jkcyk7XG4gICAgICAgICAgICBhenRlYy5zZXRNYXRyaXgobWF0cml4KTtcbiAgICAgICAgICAgIHJldHVybiBhenRlYztcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZHJhd0J1bGxzRXllKG1hdHJpeCwgY2VudGVyLCBzaXplKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpIC8qaW50Ki8gPSAwOyBpIDwgc2l6ZTsgaSArPSAyKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiAvKmludCovID0gY2VudGVyIC0gaTsgaiA8PSBjZW50ZXIgKyBpOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChqLCBjZW50ZXIgLSBpKTtcbiAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChqLCBjZW50ZXIgKyBpKTtcbiAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChjZW50ZXIgLSBpLCBqKTtcbiAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChjZW50ZXIgKyBpLCBqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBtYXRyaXguc2V0KGNlbnRlciAtIHNpemUsIGNlbnRlciAtIHNpemUpO1xuICAgICAgICAgICAgbWF0cml4LnNldChjZW50ZXIgLSBzaXplICsgMSwgY2VudGVyIC0gc2l6ZSk7XG4gICAgICAgICAgICBtYXRyaXguc2V0KGNlbnRlciAtIHNpemUsIGNlbnRlciAtIHNpemUgKyAxKTtcbiAgICAgICAgICAgIG1hdHJpeC5zZXQoY2VudGVyICsgc2l6ZSwgY2VudGVyIC0gc2l6ZSk7XG4gICAgICAgICAgICBtYXRyaXguc2V0KGNlbnRlciArIHNpemUsIGNlbnRlciAtIHNpemUgKyAxKTtcbiAgICAgICAgICAgIG1hdHJpeC5zZXQoY2VudGVyICsgc2l6ZSwgY2VudGVyICsgc2l6ZSAtIDEpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZW5lcmF0ZU1vZGVNZXNzYWdlKGNvbXBhY3QsIGxheWVycywgbWVzc2FnZVNpemVJbldvcmRzKSB7XG4gICAgICAgICAgICBsZXQgbW9kZU1lc3NhZ2UgPSBuZXcgQml0QXJyYXkoKTtcbiAgICAgICAgICAgIGlmIChjb21wYWN0KSB7XG4gICAgICAgICAgICAgICAgbW9kZU1lc3NhZ2UuYXBwZW5kQml0cyhsYXllcnMgLSAxLCAyKTtcbiAgICAgICAgICAgICAgICBtb2RlTWVzc2FnZS5hcHBlbmRCaXRzKG1lc3NhZ2VTaXplSW5Xb3JkcyAtIDEsIDYpO1xuICAgICAgICAgICAgICAgIG1vZGVNZXNzYWdlID0gRW5jb2RlciQxLmdlbmVyYXRlQ2hlY2tXb3Jkcyhtb2RlTWVzc2FnZSwgMjgsIDQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbW9kZU1lc3NhZ2UuYXBwZW5kQml0cyhsYXllcnMgLSAxLCA1KTtcbiAgICAgICAgICAgICAgICBtb2RlTWVzc2FnZS5hcHBlbmRCaXRzKG1lc3NhZ2VTaXplSW5Xb3JkcyAtIDEsIDExKTtcbiAgICAgICAgICAgICAgICBtb2RlTWVzc2FnZSA9IEVuY29kZXIkMS5nZW5lcmF0ZUNoZWNrV29yZHMobW9kZU1lc3NhZ2UsIDQwLCA0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtb2RlTWVzc2FnZTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZHJhd01vZGVNZXNzYWdlKG1hdHJpeCwgY29tcGFjdCwgbWF0cml4U2l6ZSwgbW9kZU1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGxldCBjZW50ZXIgPSBJbnRlZ2VyLnRydW5jRGl2aXNpb24obWF0cml4U2l6ZSwgMik7XG4gICAgICAgICAgICBpZiAoY29tcGFjdCkge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCA3OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG9mZnNldCA9IGNlbnRlciAtIDMgKyBpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobW9kZU1lc3NhZ2UuZ2V0KGkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXguc2V0KG9mZnNldCwgY2VudGVyIC0gNSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1vZGVNZXNzYWdlLmdldChpICsgNykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXQoY2VudGVyICsgNSwgb2Zmc2V0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobW9kZU1lc3NhZ2UuZ2V0KDIwIC0gaSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXQob2Zmc2V0LCBjZW50ZXIgKyA1KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobW9kZU1lc3NhZ2UuZ2V0KDI3IC0gaSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdHJpeC5zZXQoY2VudGVyIC0gNSwgb2Zmc2V0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCAxMDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvZmZzZXQgPSBjZW50ZXIgLSA1ICsgaSArIEludGVnZXIudHJ1bmNEaXZpc2lvbihpLCA1KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1vZGVNZXNzYWdlLmdldChpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChvZmZzZXQsIGNlbnRlciAtIDcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChtb2RlTWVzc2FnZS5nZXQoaSArIDEwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChjZW50ZXIgKyA3LCBvZmZzZXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChtb2RlTWVzc2FnZS5nZXQoMjkgLSBpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChvZmZzZXQsIGNlbnRlciArIDcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChtb2RlTWVzc2FnZS5nZXQoMzkgLSBpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0cml4LnNldChjZW50ZXIgLSA3LCBvZmZzZXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBnZW5lcmF0ZUNoZWNrV29yZHMoYml0QXJyYXksIHRvdGFsQml0cywgd29yZFNpemUpIHtcbiAgICAgICAgICAgIC8vIGJpdEFycmF5IGlzIGd1YXJhbnRlZWQgdG8gYmUgYSBtdWx0aXBsZSBvZiB0aGUgd29yZFNpemUsIHNvIG5vIHBhZGRpbmcgbmVlZGVkXG4gICAgICAgICAgICBsZXQgbWVzc2FnZVNpemVJbldvcmRzID0gYml0QXJyYXkuZ2V0U2l6ZSgpIC8gd29yZFNpemU7XG4gICAgICAgICAgICBsZXQgcnMgPSBuZXcgUmVlZFNvbG9tb25FbmNvZGVyKEVuY29kZXIkMS5nZXRHRih3b3JkU2l6ZSkpO1xuICAgICAgICAgICAgbGV0IHRvdGFsV29yZHMgPSBJbnRlZ2VyLnRydW5jRGl2aXNpb24odG90YWxCaXRzLCB3b3JkU2l6ZSk7XG4gICAgICAgICAgICBsZXQgbWVzc2FnZVdvcmRzID0gRW5jb2RlciQxLmJpdHNUb1dvcmRzKGJpdEFycmF5LCB3b3JkU2l6ZSwgdG90YWxXb3Jkcyk7XG4gICAgICAgICAgICBycy5lbmNvZGUobWVzc2FnZVdvcmRzLCB0b3RhbFdvcmRzIC0gbWVzc2FnZVNpemVJbldvcmRzKTtcbiAgICAgICAgICAgIGxldCBzdGFydFBhZCA9IHRvdGFsQml0cyAlIHdvcmRTaXplO1xuICAgICAgICAgICAgbGV0IG1lc3NhZ2VCaXRzID0gbmV3IEJpdEFycmF5KCk7XG4gICAgICAgICAgICBtZXNzYWdlQml0cy5hcHBlbmRCaXRzKDAsIHN0YXJ0UGFkKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgbWVzc2FnZVdvcmQgLyo6IGludCovIG9mIEFycmF5LmZyb20obWVzc2FnZVdvcmRzKSkge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2VCaXRzLmFwcGVuZEJpdHMobWVzc2FnZVdvcmQsIHdvcmRTaXplKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlQml0cztcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgYml0c1RvV29yZHMoc3R1ZmZlZEJpdHMsIHdvcmRTaXplLCB0b3RhbFdvcmRzKSB7XG4gICAgICAgICAgICBsZXQgbWVzc2FnZSA9IG5ldyBJbnQzMkFycmF5KHRvdGFsV29yZHMpO1xuICAgICAgICAgICAgbGV0IGk7XG4gICAgICAgICAgICBsZXQgbjtcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIG4gPSBzdHVmZmVkQml0cy5nZXRTaXplKCkgLyB3b3JkU2l6ZTsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCB2YWx1ZSA9IDA7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiAvKmludCovID0gMDsgaiA8IHdvcmRTaXplOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgfD0gc3R1ZmZlZEJpdHMuZ2V0KGkgKiB3b3JkU2l6ZSArIGopID8gKDEgPDwgd29yZFNpemUgLSBqIC0gMSkgOiAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBtZXNzYWdlW2ldID0gdmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZ2V0R0Yod29yZFNpemUpIHtcbiAgICAgICAgICAgIHN3aXRjaCAod29yZFNpemUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBHZW5lcmljR0YuQVpURUNfUEFSQU07XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gR2VuZXJpY0dGLkFaVEVDX0RBVEFfNjtcbiAgICAgICAgICAgICAgICBjYXNlIDg6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBHZW5lcmljR0YuQVpURUNfREFUQV84O1xuICAgICAgICAgICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBHZW5lcmljR0YuQVpURUNfREFUQV8xMDtcbiAgICAgICAgICAgICAgICBjYXNlIDEyOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gR2VuZXJpY0dGLkFaVEVDX0RBVEFfMTI7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignVW5zdXBwb3J0ZWQgd29yZCBzaXplICcgKyB3b3JkU2l6ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHN0dWZmQml0cyhiaXRzLCB3b3JkU2l6ZSkge1xuICAgICAgICAgICAgbGV0IG91dCA9IG5ldyBCaXRBcnJheSgpO1xuICAgICAgICAgICAgbGV0IG4gPSBiaXRzLmdldFNpemUoKTtcbiAgICAgICAgICAgIGxldCBtYXNrID0gKDEgPDwgd29yZFNpemUpIC0gMjtcbiAgICAgICAgICAgIGZvciAobGV0IGkgLyppbnQqLyA9IDA7IGkgPCBuOyBpICs9IHdvcmRTaXplKSB7XG4gICAgICAgICAgICAgICAgbGV0IHdvcmQgPSAwO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogLyppbnQqLyA9IDA7IGogPCB3b3JkU2l6ZTsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpICsgaiA+PSBuIHx8IGJpdHMuZ2V0KGkgKyBqKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgd29yZCB8PSAxIDw8ICh3b3JkU2l6ZSAtIDEgLSBqKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoKHdvcmQgJiBtYXNrKSA9PT0gbWFzaykge1xuICAgICAgICAgICAgICAgICAgICBvdXQuYXBwZW5kQml0cyh3b3JkICYgbWFzaywgd29yZFNpemUpO1xuICAgICAgICAgICAgICAgICAgICBpLS07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKCh3b3JkICYgbWFzaykgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0LmFwcGVuZEJpdHMod29yZCB8IDEsIHdvcmRTaXplKTtcbiAgICAgICAgICAgICAgICAgICAgaS0tO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0LmFwcGVuZEJpdHMod29yZCwgd29yZFNpemUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIHRvdGFsQml0c0luTGF5ZXIobGF5ZXJzLCBjb21wYWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gKChjb21wYWN0ID8gODggOiAxMTIpICsgMTYgKiBsYXllcnMpICogbGF5ZXJzO1xuICAgICAgICB9XG4gICAgfVxuICAgIEVuY29kZXIkMS5ERUZBVUxUX0VDX1BFUkNFTlQgPSAzMzsgLy8gZGVmYXVsdCBtaW5pbWFsIHBlcmNlbnRhZ2Ugb2YgZXJyb3IgY2hlY2sgd29yZHNcbiAgICBFbmNvZGVyJDEuREVGQVVMVF9BWlRFQ19MQVlFUlMgPSAwO1xuICAgIEVuY29kZXIkMS5NQVhfTkJfQklUUyA9IDMyO1xuICAgIEVuY29kZXIkMS5NQVhfTkJfQklUU19DT01QQUNUID0gNDtcbiAgICBFbmNvZGVyJDEuV09SRF9TSVpFID0gSW50MzJBcnJheS5mcm9tKFtcbiAgICAgICAgNCwgNiwgNiwgOCwgOCwgOCwgOCwgOCwgOCwgMTAsIDEwLCAxMCwgMTAsIDEwLCAxMCwgMTAsIDEwLCAxMCwgMTAsIDEwLCAxMCwgMTAsIDEwLFxuICAgICAgICAxMiwgMTIsIDEyLCAxMiwgMTIsIDEyLCAxMiwgMTIsIDEyLCAxMlxuICAgIF0pO1xuXG4gICAgLypcbiAgICAqIENvcHlyaWdodCAyMDEzIFpYaW5nIGF1dGhvcnNcbiAgICAqXG4gICAgKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICAgICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICAgICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICAgKlxuICAgICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAgICAqXG4gICAgKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gICAgKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gICAgKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgICAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAgICAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAgICovXG4gICAgLyoqXG4gICAgICogUmVuZGVycyBhbiBBenRlYyBjb2RlIGFzIGEge0BsaW5rIEJpdE1hdHJpeH0uXG4gICAgICovXG4gICAgLypwdWJsaWMgZmluYWwqLyBjbGFzcyBBenRlY1dyaXRlciB7XG4gICAgICAgIC8vIEBPdmVycmlkZVxuICAgICAgICBlbmNvZGUoY29udGVudHMsIGZvcm1hdCwgd2lkdGgsIGhlaWdodCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2RlV2l0aEhpbnRzKGNvbnRlbnRzLCBmb3JtYXQsIHdpZHRoLCBoZWlnaHQsIG51bGwpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEBPdmVycmlkZVxuICAgICAgICBlbmNvZGVXaXRoSGludHMoY29udGVudHMsIGZvcm1hdCwgd2lkdGgsIGhlaWdodCwgaGludHMpIHtcbiAgICAgICAgICAgIGxldCBjaGFyc2V0ID0gU3RhbmRhcmRDaGFyc2V0cy5JU09fODg1OV8xO1xuICAgICAgICAgICAgbGV0IGVjY1BlcmNlbnQgPSBFbmNvZGVyJDEuREVGQVVMVF9FQ19QRVJDRU5UO1xuICAgICAgICAgICAgbGV0IGxheWVycyA9IEVuY29kZXIkMS5ERUZBVUxUX0FaVEVDX0xBWUVSUztcbiAgICAgICAgICAgIGlmIChoaW50cyAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKGhpbnRzLmhhcyhFbmNvZGVIaW50VHlwZSQxLkNIQVJBQ1RFUl9TRVQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoYXJzZXQgPSBDaGFyc2V0LmZvck5hbWUoaGludHMuZ2V0KEVuY29kZUhpbnRUeXBlJDEuQ0hBUkFDVEVSX1NFVCkudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChoaW50cy5oYXMoRW5jb2RlSGludFR5cGUkMS5FUlJPUl9DT1JSRUNUSU9OKSkge1xuICAgICAgICAgICAgICAgICAgICBlY2NQZXJjZW50ID0gSW50ZWdlci5wYXJzZUludChoaW50cy5nZXQoRW5jb2RlSGludFR5cGUkMS5FUlJPUl9DT1JSRUNUSU9OKS50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGhpbnRzLmhhcyhFbmNvZGVIaW50VHlwZSQxLkFaVEVDX0xBWUVSUykpIHtcbiAgICAgICAgICAgICAgICAgICAgbGF5ZXJzID0gSW50ZWdlci5wYXJzZUludChoaW50cy5nZXQoRW5jb2RlSGludFR5cGUkMS5BWlRFQ19MQVlFUlMpLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBBenRlY1dyaXRlci5lbmNvZGVMYXllcnMoY29udGVudHMsIGZvcm1hdCwgd2lkdGgsIGhlaWdodCwgY2hhcnNldCwgZWNjUGVyY2VudCwgbGF5ZXJzKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZW5jb2RlTGF5ZXJzKGNvbnRlbnRzLCBmb3JtYXQsIHdpZHRoLCBoZWlnaHQsIGNoYXJzZXQsIGVjY1BlcmNlbnQsIGxheWVycykge1xuICAgICAgICAgICAgaWYgKGZvcm1hdCAhPT0gQmFyY29kZUZvcm1hdCQxLkFaVEVDKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbignQ2FuIG9ubHkgZW5jb2RlIEFaVEVDLCBidXQgZ290ICcgKyBmb3JtYXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGF6dGVjID0gRW5jb2RlciQxLmVuY29kZShTdHJpbmdVdGlscy5nZXRCeXRlcyhjb250ZW50cywgY2hhcnNldCksIGVjY1BlcmNlbnQsIGxheWVycyk7XG4gICAgICAgICAgICByZXR1cm4gQXp0ZWNXcml0ZXIucmVuZGVyUmVzdWx0KGF6dGVjLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgcmVuZGVyUmVzdWx0KGNvZGUsIHdpZHRoLCBoZWlnaHQpIHtcbiAgICAgICAgICAgIGxldCBpbnB1dCA9IGNvZGUuZ2V0TWF0cml4KCk7XG4gICAgICAgICAgICBpZiAoaW5wdXQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBpbnB1dFdpZHRoID0gaW5wdXQuZ2V0V2lkdGgoKTtcbiAgICAgICAgICAgIGxldCBpbnB1dEhlaWdodCA9IGlucHV0LmdldEhlaWdodCgpO1xuICAgICAgICAgICAgbGV0IG91dHB1dFdpZHRoID0gTWF0aC5tYXgod2lkdGgsIGlucHV0V2lkdGgpO1xuICAgICAgICAgICAgbGV0IG91dHB1dEhlaWdodCA9IE1hdGgubWF4KGhlaWdodCwgaW5wdXRIZWlnaHQpO1xuICAgICAgICAgICAgbGV0IG11bHRpcGxlID0gTWF0aC5taW4ob3V0cHV0V2lkdGggLyBpbnB1dFdpZHRoLCBvdXRwdXRIZWlnaHQgLyBpbnB1dEhlaWdodCk7XG4gICAgICAgICAgICBsZXQgbGVmdFBhZGRpbmcgPSAob3V0cHV0V2lkdGggLSAoaW5wdXRXaWR0aCAqIG11bHRpcGxlKSkgLyAyO1xuICAgICAgICAgICAgbGV0IHRvcFBhZGRpbmcgPSAob3V0cHV0SGVpZ2h0IC0gKGlucHV0SGVpZ2h0ICogbXVsdGlwbGUpKSAvIDI7XG4gICAgICAgICAgICBsZXQgb3V0cHV0ID0gbmV3IEJpdE1hdHJpeChvdXRwdXRXaWR0aCwgb3V0cHV0SGVpZ2h0KTtcbiAgICAgICAgICAgIGZvciAobGV0IGlucHV0WSAvKmludCovID0gMCwgb3V0cHV0WSA9IHRvcFBhZGRpbmc7IGlucHV0WSA8IGlucHV0SGVpZ2h0OyBpbnB1dFkrKywgb3V0cHV0WSArPSBtdWx0aXBsZSkge1xuICAgICAgICAgICAgICAgIC8vIFdyaXRlIHRoZSBjb250ZW50cyBvZiB0aGlzIHJvdyBvZiB0aGUgYmFyY29kZVxuICAgICAgICAgICAgICAgIGZvciAobGV0IGlucHV0WCAvKmludCovID0gMCwgb3V0cHV0WCA9IGxlZnRQYWRkaW5nOyBpbnB1dFggPCBpbnB1dFdpZHRoOyBpbnB1dFgrKywgb3V0cHV0WCArPSBtdWx0aXBsZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXQuZ2V0KGlucHV0WCwgaW5wdXRZKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnNldFJlZ2lvbihvdXRwdXRYLCBvdXRwdXRZLCBtdWx0aXBsZSwgbXVsdGlwbGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dHB1dDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGV4cG9ydHMuQWJzdHJhY3RFeHBhbmRlZERlY29kZXIgPSBBYnN0cmFjdEV4cGFuZGVkRGVjb2RlcjtcbiAgICBleHBvcnRzLkFyZ3VtZW50RXhjZXB0aW9uID0gQXJndW1lbnRFeGNlcHRpb247XG4gICAgZXhwb3J0cy5Bcml0aG1ldGljRXhjZXB0aW9uID0gQXJpdGhtZXRpY0V4Y2VwdGlvbjtcbiAgICBleHBvcnRzLkF6dGVjQ29kZSA9IEF6dGVjQ29kZTtcbiAgICBleHBvcnRzLkF6dGVjQ29kZVJlYWRlciA9IEF6dGVjUmVhZGVyO1xuICAgIGV4cG9ydHMuQXp0ZWNDb2RlV3JpdGVyID0gQXp0ZWNXcml0ZXI7XG4gICAgZXhwb3J0cy5BenRlY0RlY29kZXIgPSBEZWNvZGVyO1xuICAgIGV4cG9ydHMuQXp0ZWNEZXRlY3RvciA9IERldGVjdG9yO1xuICAgIGV4cG9ydHMuQXp0ZWNEZXRlY3RvclJlc3VsdCA9IEF6dGVjRGV0ZWN0b3JSZXN1bHQ7XG4gICAgZXhwb3J0cy5BenRlY0VuY29kZXIgPSBFbmNvZGVyJDE7XG4gICAgZXhwb3J0cy5BenRlY0hpZ2hMZXZlbEVuY29kZXIgPSBIaWdoTGV2ZWxFbmNvZGVyO1xuICAgIGV4cG9ydHMuQXp0ZWNQb2ludCA9IFBvaW50O1xuICAgIGV4cG9ydHMuQmFyY29kZUZvcm1hdCA9IEJhcmNvZGVGb3JtYXQkMTtcbiAgICBleHBvcnRzLkJpbmFyaXplciA9IEJpbmFyaXplcjtcbiAgICBleHBvcnRzLkJpbmFyeUJpdG1hcCA9IEJpbmFyeUJpdG1hcDtcbiAgICBleHBvcnRzLkJpdEFycmF5ID0gQml0QXJyYXk7XG4gICAgZXhwb3J0cy5CaXRNYXRyaXggPSBCaXRNYXRyaXg7XG4gICAgZXhwb3J0cy5CaXRTb3VyY2UgPSBCaXRTb3VyY2U7XG4gICAgZXhwb3J0cy5Ccm93c2VyQXp0ZWNDb2RlUmVhZGVyID0gQnJvd3NlckF6dGVjQ29kZVJlYWRlcjtcbiAgICBleHBvcnRzLkJyb3dzZXJCYXJjb2RlUmVhZGVyID0gQnJvd3NlckJhcmNvZGVSZWFkZXI7XG4gICAgZXhwb3J0cy5Ccm93c2VyQ29kZVJlYWRlciA9IEJyb3dzZXJDb2RlUmVhZGVyO1xuICAgIGV4cG9ydHMuQnJvd3NlckRhdGFtYXRyaXhDb2RlUmVhZGVyID0gQnJvd3NlckRhdGFtYXRyaXhDb2RlUmVhZGVyO1xuICAgIGV4cG9ydHMuQnJvd3Nlck11bHRpRm9ybWF0UmVhZGVyID0gQnJvd3Nlck11bHRpRm9ybWF0UmVhZGVyO1xuICAgIGV4cG9ydHMuQnJvd3NlclBERjQxN1JlYWRlciA9IEJyb3dzZXJQREY0MTdSZWFkZXI7XG4gICAgZXhwb3J0cy5Ccm93c2VyUVJDb2RlUmVhZGVyID0gQnJvd3NlclFSQ29kZVJlYWRlcjtcbiAgICBleHBvcnRzLkJyb3dzZXJRUkNvZGVTdmdXcml0ZXIgPSBCcm93c2VyUVJDb2RlU3ZnV3JpdGVyO1xuICAgIGV4cG9ydHMuQ2hhcmFjdGVyU2V0RUNJID0gQ2hhcmFjdGVyU2V0RUNJO1xuICAgIGV4cG9ydHMuQ2hlY2tzdW1FeGNlcHRpb24gPSBDaGVja3N1bUV4Y2VwdGlvbjtcbiAgICBleHBvcnRzLkNvZGUxMjhSZWFkZXIgPSBDb2RlMTI4UmVhZGVyO1xuICAgIGV4cG9ydHMuQ29kZTM5UmVhZGVyID0gQ29kZTM5UmVhZGVyO1xuICAgIGV4cG9ydHMuRGF0YU1hdHJpeERlY29kZWRCaXRTdHJlYW1QYXJzZXIgPSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyO1xuICAgIGV4cG9ydHMuRGF0YU1hdHJpeFJlYWRlciA9IERhdGFNYXRyaXhSZWFkZXI7XG4gICAgZXhwb3J0cy5EZWNvZGVIaW50VHlwZSA9IERlY29kZUhpbnRUeXBlJDE7XG4gICAgZXhwb3J0cy5EZWNvZGVyUmVzdWx0ID0gRGVjb2RlclJlc3VsdDtcbiAgICBleHBvcnRzLkRlZmF1bHRHcmlkU2FtcGxlciA9IERlZmF1bHRHcmlkU2FtcGxlcjtcbiAgICBleHBvcnRzLkRldGVjdG9yUmVzdWx0ID0gRGV0ZWN0b3JSZXN1bHQ7XG4gICAgZXhwb3J0cy5FQU4xM1JlYWRlciA9IEVBTjEzUmVhZGVyO1xuICAgIGV4cG9ydHMuRW5jb2RlSGludFR5cGUgPSBFbmNvZGVIaW50VHlwZSQxO1xuICAgIGV4cG9ydHMuRXhjZXB0aW9uID0gRXhjZXB0aW9uO1xuICAgIGV4cG9ydHMuRm9ybWF0RXhjZXB0aW9uID0gRm9ybWF0RXhjZXB0aW9uO1xuICAgIGV4cG9ydHMuR2VuZXJpY0dGID0gR2VuZXJpY0dGO1xuICAgIGV4cG9ydHMuR2VuZXJpY0dGUG9seSA9IEdlbmVyaWNHRlBvbHk7XG4gICAgZXhwb3J0cy5HbG9iYWxIaXN0b2dyYW1CaW5hcml6ZXIgPSBHbG9iYWxIaXN0b2dyYW1CaW5hcml6ZXI7XG4gICAgZXhwb3J0cy5HcmlkU2FtcGxlciA9IEdyaWRTYW1wbGVyO1xuICAgIGV4cG9ydHMuR3JpZFNhbXBsZXJJbnN0YW5jZSA9IEdyaWRTYW1wbGVySW5zdGFuY2U7XG4gICAgZXhwb3J0cy5IVE1MQ2FudmFzRWxlbWVudEx1bWluYW5jZVNvdXJjZSA9IEhUTUxDYW52YXNFbGVtZW50THVtaW5hbmNlU291cmNlO1xuICAgIGV4cG9ydHMuSHlicmlkQmluYXJpemVyID0gSHlicmlkQmluYXJpemVyO1xuICAgIGV4cG9ydHMuSVRGUmVhZGVyID0gSVRGUmVhZGVyO1xuICAgIGV4cG9ydHMuSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uID0gSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uO1xuICAgIGV4cG9ydHMuSWxsZWdhbFN0YXRlRXhjZXB0aW9uID0gSWxsZWdhbFN0YXRlRXhjZXB0aW9uO1xuICAgIGV4cG9ydHMuSW52ZXJ0ZWRMdW1pbmFuY2VTb3VyY2UgPSBJbnZlcnRlZEx1bWluYW5jZVNvdXJjZTtcbiAgICBleHBvcnRzLkx1bWluYW5jZVNvdXJjZSA9IEx1bWluYW5jZVNvdXJjZTtcbiAgICBleHBvcnRzLk1hdGhVdGlscyA9IE1hdGhVdGlscztcbiAgICBleHBvcnRzLk11bHRpRm9ybWF0T25lRFJlYWRlciA9IE11bHRpRm9ybWF0T25lRFJlYWRlcjtcbiAgICBleHBvcnRzLk11bHRpRm9ybWF0UmVhZGVyID0gTXVsdGlGb3JtYXRSZWFkZXI7XG4gICAgZXhwb3J0cy5NdWx0aUZvcm1hdFdyaXRlciA9IE11bHRpRm9ybWF0V3JpdGVyO1xuICAgIGV4cG9ydHMuTm90Rm91bmRFeGNlcHRpb24gPSBOb3RGb3VuZEV4Y2VwdGlvbjtcbiAgICBleHBvcnRzLk9uZURSZWFkZXIgPSBPbmVEUmVhZGVyO1xuICAgIGV4cG9ydHMuUERGNDE3RGVjb2RlZEJpdFN0cmVhbVBhcnNlciA9IERlY29kZWRCaXRTdHJlYW1QYXJzZXIkMjtcbiAgICBleHBvcnRzLlBERjQxN0RlY29kZXJFcnJvckNvcnJlY3Rpb24gPSBFcnJvckNvcnJlY3Rpb247XG4gICAgZXhwb3J0cy5QREY0MTdSZWFkZXIgPSBQREY0MTdSZWFkZXI7XG4gICAgZXhwb3J0cy5QREY0MTdSZXN1bHRNZXRhZGF0YSA9IFBERjQxN1Jlc3VsdE1ldGFkYXRhO1xuICAgIGV4cG9ydHMuUGVyc3BlY3RpdmVUcmFuc2Zvcm0gPSBQZXJzcGVjdGl2ZVRyYW5zZm9ybTtcbiAgICBleHBvcnRzLlBsYW5hcllVVkx1bWluYW5jZVNvdXJjZSA9IFBsYW5hcllVVkx1bWluYW5jZVNvdXJjZTtcbiAgICBleHBvcnRzLlFSQ29kZUJ5dGVNYXRyaXggPSBCeXRlTWF0cml4O1xuICAgIGV4cG9ydHMuUVJDb2RlRGF0YU1hc2sgPSBEYXRhTWFzaztcbiAgICBleHBvcnRzLlFSQ29kZURlY29kZWRCaXRTdHJlYW1QYXJzZXIgPSBEZWNvZGVkQml0U3RyZWFtUGFyc2VyJDE7XG4gICAgZXhwb3J0cy5RUkNvZGVEZWNvZGVyRXJyb3JDb3JyZWN0aW9uTGV2ZWwgPSBFcnJvckNvcnJlY3Rpb25MZXZlbDtcbiAgICBleHBvcnRzLlFSQ29kZURlY29kZXJGb3JtYXRJbmZvcm1hdGlvbiA9IEZvcm1hdEluZm9ybWF0aW9uO1xuICAgIGV4cG9ydHMuUVJDb2RlRW5jb2RlciA9IEVuY29kZXI7XG4gICAgZXhwb3J0cy5RUkNvZGVFbmNvZGVyUVJDb2RlID0gUVJDb2RlO1xuICAgIGV4cG9ydHMuUVJDb2RlTWFza1V0aWwgPSBNYXNrVXRpbDtcbiAgICBleHBvcnRzLlFSQ29kZU1hdHJpeFV0aWwgPSBNYXRyaXhVdGlsO1xuICAgIGV4cG9ydHMuUVJDb2RlTW9kZSA9IE1vZGUkMTtcbiAgICBleHBvcnRzLlFSQ29kZVJlYWRlciA9IFFSQ29kZVJlYWRlcjtcbiAgICBleHBvcnRzLlFSQ29kZVZlcnNpb24gPSBWZXJzaW9uJDE7XG4gICAgZXhwb3J0cy5RUkNvZGVXcml0ZXIgPSBRUkNvZGVXcml0ZXI7XG4gICAgZXhwb3J0cy5SR0JMdW1pbmFuY2VTb3VyY2UgPSBSR0JMdW1pbmFuY2VTb3VyY2U7XG4gICAgZXhwb3J0cy5SU1MxNFJlYWRlciA9IFJTUzE0UmVhZGVyO1xuICAgIGV4cG9ydHMuUlNTRXhwYW5kZWRSZWFkZXIgPSBSU1NFeHBhbmRlZFJlYWRlcjtcbiAgICBleHBvcnRzLlJlYWRlckV4Y2VwdGlvbiA9IFJlYWRlckV4Y2VwdGlvbjtcbiAgICBleHBvcnRzLlJlZWRTb2xvbW9uRGVjb2RlciA9IFJlZWRTb2xvbW9uRGVjb2RlcjtcbiAgICBleHBvcnRzLlJlZWRTb2xvbW9uRW5jb2RlciA9IFJlZWRTb2xvbW9uRW5jb2RlcjtcbiAgICBleHBvcnRzLlJlZWRTb2xvbW9uRXhjZXB0aW9uID0gUmVlZFNvbG9tb25FeGNlcHRpb247XG4gICAgZXhwb3J0cy5SZXN1bHQgPSBSZXN1bHQ7XG4gICAgZXhwb3J0cy5SZXN1bHRNZXRhZGF0YVR5cGUgPSBSZXN1bHRNZXRhZGF0YVR5cGUkMTtcbiAgICBleHBvcnRzLlJlc3VsdFBvaW50ID0gUmVzdWx0UG9pbnQ7XG4gICAgZXhwb3J0cy5TdHJpbmdVdGlscyA9IFN0cmluZ1V0aWxzO1xuICAgIGV4cG9ydHMuVW5zdXBwb3J0ZWRPcGVyYXRpb25FeGNlcHRpb24gPSBVbnN1cHBvcnRlZE9wZXJhdGlvbkV4Y2VwdGlvbjtcbiAgICBleHBvcnRzLlZpZGVvSW5wdXREZXZpY2UgPSBWaWRlb0lucHV0RGV2aWNlO1xuICAgIGV4cG9ydHMuV2hpdGVSZWN0YW5nbGVEZXRlY3RvciA9IFdoaXRlUmVjdGFuZ2xlRGV0ZWN0b3I7XG4gICAgZXhwb3J0cy5Xcml0ZXJFeGNlcHRpb24gPSBXcml0ZXJFeGNlcHRpb247XG4gICAgZXhwb3J0cy5aWGluZ0FycmF5cyA9IEFycmF5cztcbiAgICBleHBvcnRzLlpYaW5nQ2hhcnNldCA9IENoYXJzZXQ7XG4gICAgZXhwb3J0cy5aWGluZ0ludGVnZXIgPSBJbnRlZ2VyO1xuICAgIGV4cG9ydHMuWlhpbmdTdGFuZGFyZENoYXJzZXRzID0gU3RhbmRhcmRDaGFyc2V0cztcbiAgICBleHBvcnRzLlpYaW5nU3RyaW5nQnVpbGRlciA9IFN0cmluZ0J1aWxkZXI7XG4gICAgZXhwb3J0cy5aWGluZ1N0cmluZ0VuY29kaW5nID0gU3RyaW5nRW5jb2Rpbmc7XG4gICAgZXhwb3J0cy5aWGluZ1N5c3RlbSA9IFN5c3RlbTtcbiAgICBleHBvcnRzLmNyZWF0ZUFic3RyYWN0RXhwYW5kZWREZWNvZGVyID0gY3JlYXRlRGVjb2RlcjtcblxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/html5-qrcode/third_party/zxing-js.umd.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/ieee754/index.js":
+/*!***************************************!*\
+  !*** ./node_modules/ieee754/index.js ***!
+  \***************************************/
+/***/ ((__unused_webpack_module, exports) => {
+
+eval("/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */\nexports.read = function (buffer, offset, isLE, mLen, nBytes) {\n  var e, m\n  var eLen = (nBytes * 8) - mLen - 1\n  var eMax = (1 << eLen) - 1\n  var eBias = eMax >> 1\n  var nBits = -7\n  var i = isLE ? (nBytes - 1) : 0\n  var d = isLE ? -1 : 1\n  var s = buffer[offset + i]\n\n  i += d\n\n  e = s & ((1 << (-nBits)) - 1)\n  s >>= (-nBits)\n  nBits += eLen\n  for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {}\n\n  m = e & ((1 << (-nBits)) - 1)\n  e >>= (-nBits)\n  nBits += mLen\n  for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {}\n\n  if (e === 0) {\n    e = 1 - eBias\n  } else if (e === eMax) {\n    return m ? NaN : ((s ? -1 : 1) * Infinity)\n  } else {\n    m = m + Math.pow(2, mLen)\n    e = e - eBias\n  }\n  return (s ? -1 : 1) * m * Math.pow(2, e - mLen)\n}\n\nexports.write = function (buffer, value, offset, isLE, mLen, nBytes) {\n  var e, m, c\n  var eLen = (nBytes * 8) - mLen - 1\n  var eMax = (1 << eLen) - 1\n  var eBias = eMax >> 1\n  var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)\n  var i = isLE ? 0 : (nBytes - 1)\n  var d = isLE ? 1 : -1\n  var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0\n\n  value = Math.abs(value)\n\n  if (isNaN(value) || value === Infinity) {\n    m = isNaN(value) ? 1 : 0\n    e = eMax\n  } else {\n    e = Math.floor(Math.log(value) / Math.LN2)\n    if (value * (c = Math.pow(2, -e)) < 1) {\n      e--\n      c *= 2\n    }\n    if (e + eBias >= 1) {\n      value += rt / c\n    } else {\n      value += rt * Math.pow(2, 1 - eBias)\n    }\n    if (value * c >= 2) {\n      e++\n      c /= 2\n    }\n\n    if (e + eBias >= eMax) {\n      m = 0\n      e = eMax\n    } else if (e + eBias >= 1) {\n      m = ((value * c) - 1) * Math.pow(2, mLen)\n      e = e + eBias\n    } else {\n      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)\n      e = 0\n    }\n  }\n\n  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}\n\n  e = (e << mLen) | m\n  eLen += mLen\n  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}\n\n  buffer[offset + i - d] |= s * 128\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvaWVlZTc1NC9pbmRleC5qcy5qcyIsIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9pZWVlNzU0L2luZGV4LmpzPzkxNTIiXSwic291cmNlc0NvbnRlbnQiOlsiLyohIGllZWU3NTQuIEJTRC0zLUNsYXVzZSBMaWNlbnNlLiBGZXJvc3MgQWJvdWtoYWRpamVoIDxodHRwczovL2Zlcm9zcy5vcmcvb3BlbnNvdXJjZT4gKi9cbmV4cG9ydHMucmVhZCA9IGZ1bmN0aW9uIChidWZmZXIsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtXG4gIHZhciBlTGVuID0gKG5CeXRlcyAqIDgpIC0gbUxlbiAtIDFcbiAgdmFyIGVNYXggPSAoMSA8PCBlTGVuKSAtIDFcbiAgdmFyIGVCaWFzID0gZU1heCA+PiAxXG4gIHZhciBuQml0cyA9IC03XG4gIHZhciBpID0gaXNMRSA/IChuQnl0ZXMgLSAxKSA6IDBcbiAgdmFyIGQgPSBpc0xFID8gLTEgOiAxXG4gIHZhciBzID0gYnVmZmVyW29mZnNldCArIGldXG5cbiAgaSArPSBkXG5cbiAgZSA9IHMgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgcyA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gZUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBlID0gKGUgKiAyNTYpICsgYnVmZmVyW29mZnNldCArIGldLCBpICs9IGQsIG5CaXRzIC09IDgpIHt9XG5cbiAgbSA9IGUgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgZSA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gbUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBtID0gKG0gKiAyNTYpICsgYnVmZmVyW29mZnNldCArIGldLCBpICs9IGQsIG5CaXRzIC09IDgpIHt9XG5cbiAgaWYgKGUgPT09IDApIHtcbiAgICBlID0gMSAtIGVCaWFzXG4gIH0gZWxzZSBpZiAoZSA9PT0gZU1heCkge1xuICAgIHJldHVybiBtID8gTmFOIDogKChzID8gLTEgOiAxKSAqIEluZmluaXR5KVxuICB9IGVsc2Uge1xuICAgIG0gPSBtICsgTWF0aC5wb3coMiwgbUxlbilcbiAgICBlID0gZSAtIGVCaWFzXG4gIH1cbiAgcmV0dXJuIChzID8gLTEgOiAxKSAqIG0gKiBNYXRoLnBvdygyLCBlIC0gbUxlbilcbn1cblxuZXhwb3J0cy53cml0ZSA9IGZ1bmN0aW9uIChidWZmZXIsIHZhbHVlLCBvZmZzZXQsIGlzTEUsIG1MZW4sIG5CeXRlcykge1xuICB2YXIgZSwgbSwgY1xuICB2YXIgZUxlbiA9IChuQnl0ZXMgKiA4KSAtIG1MZW4gLSAxXG4gIHZhciBlTWF4ID0gKDEgPDwgZUxlbikgLSAxXG4gIHZhciBlQmlhcyA9IGVNYXggPj4gMVxuICB2YXIgcnQgPSAobUxlbiA9PT0gMjMgPyBNYXRoLnBvdygyLCAtMjQpIC0gTWF0aC5wb3coMiwgLTc3KSA6IDApXG4gIHZhciBpID0gaXNMRSA/IDAgOiAobkJ5dGVzIC0gMSlcbiAgdmFyIGQgPSBpc0xFID8gMSA6IC0xXG4gIHZhciBzID0gdmFsdWUgPCAwIHx8ICh2YWx1ZSA9PT0gMCAmJiAxIC8gdmFsdWUgPCAwKSA/IDEgOiAwXG5cbiAgdmFsdWUgPSBNYXRoLmFicyh2YWx1ZSlcblxuICBpZiAoaXNOYU4odmFsdWUpIHx8IHZhbHVlID09PSBJbmZpbml0eSkge1xuICAgIG0gPSBpc05hTih2YWx1ZSkgPyAxIDogMFxuICAgIGUgPSBlTWF4XG4gIH0gZWxzZSB7XG4gICAgZSA9IE1hdGguZmxvb3IoTWF0aC5sb2codmFsdWUpIC8gTWF0aC5MTjIpXG4gICAgaWYgKHZhbHVlICogKGMgPSBNYXRoLnBvdygyLCAtZSkpIDwgMSkge1xuICAgICAgZS0tXG4gICAgICBjICo9IDJcbiAgICB9XG4gICAgaWYgKGUgKyBlQmlhcyA+PSAxKSB7XG4gICAgICB2YWx1ZSArPSBydCAvIGNcbiAgICB9IGVsc2Uge1xuICAgICAgdmFsdWUgKz0gcnQgKiBNYXRoLnBvdygyLCAxIC0gZUJpYXMpXG4gICAgfVxuICAgIGlmICh2YWx1ZSAqIGMgPj0gMikge1xuICAgICAgZSsrXG4gICAgICBjIC89IDJcbiAgICB9XG5cbiAgICBpZiAoZSArIGVCaWFzID49IGVNYXgpIHtcbiAgICAgIG0gPSAwXG4gICAgICBlID0gZU1heFxuICAgIH0gZWxzZSBpZiAoZSArIGVCaWFzID49IDEpIHtcbiAgICAgIG0gPSAoKHZhbHVlICogYykgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pXG4gICAgICBlID0gZSArIGVCaWFzXG4gICAgfSBlbHNlIHtcbiAgICAgIG0gPSB2YWx1ZSAqIE1hdGgucG93KDIsIGVCaWFzIC0gMSkgKiBNYXRoLnBvdygyLCBtTGVuKVxuICAgICAgZSA9IDBcbiAgICB9XG4gIH1cblxuICBmb3IgKDsgbUxlbiA+PSA4OyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBtICYgMHhmZiwgaSArPSBkLCBtIC89IDI1NiwgbUxlbiAtPSA4KSB7fVxuXG4gIGUgPSAoZSA8PCBtTGVuKSB8IG1cbiAgZUxlbiArPSBtTGVuXG4gIGZvciAoOyBlTGVuID4gMDsgYnVmZmVyW29mZnNldCArIGldID0gZSAmIDB4ZmYsIGkgKz0gZCwgZSAvPSAyNTYsIGVMZW4gLT0gOCkge31cblxuICBidWZmZXJbb2Zmc2V0ICsgaSAtIGRdIHw9IHMgKiAxMjhcbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/ieee754/index.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/@noble/curves/esm/abstract/curve.js":
+/*!**********************************************************!*\
+  !*** ./node_modules/@noble/curves/esm/abstract/curve.js ***!
+  \**********************************************************/
+/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   validateBasic: () => (/* binding */ validateBasic),\n/* harmony export */   wNAF: () => (/* binding */ wNAF)\n/* harmony export */ });\n/* harmony import */ var _modular_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./modular.js */ \"./node_modules/@noble/curves/esm/abstract/modular.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils.js */ \"./node_modules/@noble/curves/esm/abstract/utils.js\");\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// Abelian group utilities\n\n\nconst _0n = BigInt(0);\nconst _1n = BigInt(1);\n// Elliptic curve multiplication of Point by scalar. Fragile.\n// Scalars should always be less than curve order: this should be checked inside of a curve itself.\n// Creates precomputation tables for fast multiplication:\n// - private scalar is split by fixed size windows of W bits\n// - every window point is collected from window's table & added to accumulator\n// - since windows are different, same point inside tables won't be accessed more than once per calc\n// - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar)\n// - +1 window is neccessary for wNAF\n// - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication\n// TODO: Research returning 2d JS array of windows, instead of a single window. This would allow\n// windows to be in different memory locations\nfunction wNAF(c, bits) {\n    const constTimeNegate = (condition, item) => {\n        const neg = item.negate();\n        return condition ? neg : item;\n    };\n    const opts = (W) => {\n        const windows = Math.ceil(bits / W) + 1; // +1, because\n        const windowSize = 2 ** (W - 1); // -1 because we skip zero\n        return { windows, windowSize };\n    };\n    return {\n        constTimeNegate,\n        // non-const time multiplication ladder\n        unsafeLadder(elm, n) {\n            let p = c.ZERO;\n            let d = elm;\n            while (n > _0n) {\n                if (n & _1n)\n                    p = p.add(d);\n                d = d.double();\n                n >>= _1n;\n            }\n            return p;\n        },\n        /**\n         * Creates a wNAF precomputation window. Used for caching.\n         * Default window size is set by `utils.precompute()` and is equal to 8.\n         * Number of precomputed points depends on the curve size:\n         * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:\n         * - 𝑊 is the window size\n         * - 𝑛 is the bitlength of the curve order.\n         * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.\n         * @returns precomputed point tables flattened to a single array\n         */\n        precomputeWindow(elm, W) {\n            const { windows, windowSize } = opts(W);\n            const points = [];\n            let p = elm;\n            let base = p;\n            for (let window = 0; window < windows; window++) {\n                base = p;\n                points.push(base);\n                // =1, because we skip zero\n                for (let i = 1; i < windowSize; i++) {\n                    base = base.add(p);\n                    points.push(base);\n                }\n                p = base.double();\n            }\n            return points;\n        },\n        /**\n         * Implements ec multiplication using precomputed tables and w-ary non-adjacent form.\n         * @param W window size\n         * @param precomputes precomputed tables\n         * @param n scalar (we don't check here, but should be less than curve order)\n         * @returns real and fake (for const-time) points\n         */\n        wNAF(W, precomputes, n) {\n            // TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise\n            // But need to carefully remove other checks before wNAF. ORDER == bits here\n            const { windows, windowSize } = opts(W);\n            let p = c.ZERO;\n            let f = c.BASE;\n            const mask = BigInt(2 ** W - 1); // Create mask with W ones: 0b1111 for W=4 etc.\n            const maxNumber = 2 ** W;\n            const shiftBy = BigInt(W);\n            for (let window = 0; window < windows; window++) {\n                const offset = window * windowSize;\n                // Extract W bits.\n                let wbits = Number(n & mask);\n                // Shift number by W bits.\n                n >>= shiftBy;\n                // If the bits are bigger than max size, we'll split those.\n                // +224 => 256 - 32\n                if (wbits > windowSize) {\n                    wbits -= maxNumber;\n                    n += _1n;\n                }\n                // This code was first written with assumption that 'f' and 'p' will never be infinity point:\n                // since each addition is multiplied by 2 ** W, it cannot cancel each other. However,\n                // there is negate now: it is possible that negated element from low value\n                // would be the same as high element, which will create carry into next window.\n                // It's not obvious how this can fail, but still worth investigating later.\n                // Check if we're onto Zero point.\n                // Add random point inside current window to f.\n                const offset1 = offset;\n                const offset2 = offset + Math.abs(wbits) - 1; // -1 because we skip zero\n                const cond1 = window % 2 !== 0;\n                const cond2 = wbits < 0;\n                if (wbits === 0) {\n                    // The most important part for const-time getPublicKey\n                    f = f.add(constTimeNegate(cond1, precomputes[offset1]));\n                }\n                else {\n                    p = p.add(constTimeNegate(cond2, precomputes[offset2]));\n                }\n            }\n            // JIT-compiler should not eliminate f here, since it will later be used in normalizeZ()\n            // Even if the variable is still unused, there are some checks which will\n            // throw an exception, so compiler needs to prove they won't happen, which is hard.\n            // At this point there is a way to F be infinity-point even if p is not,\n            // which makes it less const-time: around 1 bigint multiply.\n            return { p, f };\n        },\n        wNAFCached(P, precomputesMap, n, transform) {\n            // @ts-ignore\n            const W = P._WINDOW_SIZE || 1;\n            // Calculate precomputes on a first run, reuse them after\n            let comp = precomputesMap.get(P);\n            if (!comp) {\n                comp = this.precomputeWindow(P, W);\n                if (W !== 1) {\n                    precomputesMap.set(P, transform(comp));\n                }\n            }\n            return this.wNAF(W, comp, n);\n        },\n    };\n}\nfunction validateBasic(curve) {\n    (0,_modular_js__WEBPACK_IMPORTED_MODULE_0__.validateField)(curve.Fp);\n    (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.validateObject)(curve, {\n        n: 'bigint',\n        h: 'bigint',\n        Gx: 'field',\n        Gy: 'field',\n    }, {\n        nBitLength: 'isSafeInteger',\n        nByteLength: 'isSafeInteger',\n    });\n    // Set defaults\n    return Object.freeze({\n        ...(0,_modular_js__WEBPACK_IMPORTED_MODULE_0__.nLength)(curve.n, curve.nBitLength),\n        ...curve,\n        ...{ p: curve.Fp.ORDER },\n    });\n}\n//# sourceMappingURL=curve.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQG5vYmxlL2N1cnZlcy9lc20vYWJzdHJhY3QvY3VydmUuanMuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9Abm9ibGUvY3VydmVzL2VzbS9hYnN0cmFjdC9jdXJ2ZS5qcz8zOTk4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qISBub2JsZS1jdXJ2ZXMgLSBNSVQgTGljZW5zZSAoYykgMjAyMiBQYXVsIE1pbGxlciAocGF1bG1pbGxyLmNvbSkgKi9cbi8vIEFiZWxpYW4gZ3JvdXAgdXRpbGl0aWVzXG5pbXBvcnQgeyB2YWxpZGF0ZUZpZWxkLCBuTGVuZ3RoIH0gZnJvbSAnLi9tb2R1bGFyLmpzJztcbmltcG9ydCB7IHZhbGlkYXRlT2JqZWN0IH0gZnJvbSAnLi91dGlscy5qcyc7XG5jb25zdCBfMG4gPSBCaWdJbnQoMCk7XG5jb25zdCBfMW4gPSBCaWdJbnQoMSk7XG4vLyBFbGxpcHRpYyBjdXJ2ZSBtdWx0aXBsaWNhdGlvbiBvZiBQb2ludCBieSBzY2FsYXIuIEZyYWdpbGUuXG4vLyBTY2FsYXJzIHNob3VsZCBhbHdheXMgYmUgbGVzcyB0aGFuIGN1cnZlIG9yZGVyOiB0aGlzIHNob3VsZCBiZSBjaGVja2VkIGluc2lkZSBvZiBhIGN1cnZlIGl0c2VsZi5cbi8vIENyZWF0ZXMgcHJlY29tcHV0YXRpb24gdGFibGVzIGZvciBmYXN0IG11bHRpcGxpY2F0aW9uOlxuLy8gLSBwcml2YXRlIHNjYWxhciBpcyBzcGxpdCBieSBmaXhlZCBzaXplIHdpbmRvd3Mgb2YgVyBiaXRzXG4vLyAtIGV2ZXJ5IHdpbmRvdyBwb2ludCBpcyBjb2xsZWN0ZWQgZnJvbSB3aW5kb3cncyB0YWJsZSAmIGFkZGVkIHRvIGFjY3VtdWxhdG9yXG4vLyAtIHNpbmNlIHdpbmRvd3MgYXJlIGRpZmZlcmVudCwgc2FtZSBwb2ludCBpbnNpZGUgdGFibGVzIHdvbid0IGJlIGFjY2Vzc2VkIG1vcmUgdGhhbiBvbmNlIHBlciBjYWxjXG4vLyAtIGVhY2ggbXVsdGlwbGljYXRpb24gaXMgJ01hdGguY2VpbChDVVJWRV9PUkRFUiAvIPCdkYopICsgMScgcG9pbnQgYWRkaXRpb25zIChmaXhlZCBmb3IgYW55IHNjYWxhcilcbi8vIC0gKzEgd2luZG93IGlzIG5lY2Nlc3NhcnkgZm9yIHdOQUZcbi8vIC0gd05BRiByZWR1Y2VzIHRhYmxlIHNpemU6IDJ4IGxlc3MgbWVtb3J5ICsgMnggZmFzdGVyIGdlbmVyYXRpb24sIGJ1dCAxMCUgc2xvd2VyIG11bHRpcGxpY2F0aW9uXG4vLyBUT0RPOiBSZXNlYXJjaCByZXR1cm5pbmcgMmQgSlMgYXJyYXkgb2Ygd2luZG93cywgaW5zdGVhZCBvZiBhIHNpbmdsZSB3aW5kb3cuIFRoaXMgd291bGQgYWxsb3dcbi8vIHdpbmRvd3MgdG8gYmUgaW4gZGlmZmVyZW50IG1lbW9yeSBsb2NhdGlvbnNcbmV4cG9ydCBmdW5jdGlvbiB3TkFGKGMsIGJpdHMpIHtcbiAgICBjb25zdCBjb25zdFRpbWVOZWdhdGUgPSAoY29uZGl0aW9uLCBpdGVtKSA9PiB7XG4gICAgICAgIGNvbnN0IG5lZyA9IGl0ZW0ubmVnYXRlKCk7XG4gICAgICAgIHJldHVybiBjb25kaXRpb24gPyBuZWcgOiBpdGVtO1xuICAgIH07XG4gICAgY29uc3Qgb3B0cyA9IChXKSA9PiB7XG4gICAgICAgIGNvbnN0IHdpbmRvd3MgPSBNYXRoLmNlaWwoYml0cyAvIFcpICsgMTsgLy8gKzEsIGJlY2F1c2VcbiAgICAgICAgY29uc3Qgd2luZG93U2l6ZSA9IDIgKiogKFcgLSAxKTsgLy8gLTEgYmVjYXVzZSB3ZSBza2lwIHplcm9cbiAgICAgICAgcmV0dXJuIHsgd2luZG93cywgd2luZG93U2l6ZSB9O1xuICAgIH07XG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29uc3RUaW1lTmVnYXRlLFxuICAgICAgICAvLyBub24tY29uc3QgdGltZSBtdWx0aXBsaWNhdGlvbiBsYWRkZXJcbiAgICAgICAgdW5zYWZlTGFkZGVyKGVsbSwgbikge1xuICAgICAgICAgICAgbGV0IHAgPSBjLlpFUk87XG4gICAgICAgICAgICBsZXQgZCA9IGVsbTtcbiAgICAgICAgICAgIHdoaWxlIChuID4gXzBuKSB7XG4gICAgICAgICAgICAgICAgaWYgKG4gJiBfMW4pXG4gICAgICAgICAgICAgICAgICAgIHAgPSBwLmFkZChkKTtcbiAgICAgICAgICAgICAgICBkID0gZC5kb3VibGUoKTtcbiAgICAgICAgICAgICAgICBuID4+PSBfMW47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcDtcbiAgICAgICAgfSxcbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSB3TkFGIHByZWNvbXB1dGF0aW9uIHdpbmRvdy4gVXNlZCBmb3IgY2FjaGluZy5cbiAgICAgICAgICogRGVmYXVsdCB3aW5kb3cgc2l6ZSBpcyBzZXQgYnkgYHV0aWxzLnByZWNvbXB1dGUoKWAgYW5kIGlzIGVxdWFsIHRvIDguXG4gICAgICAgICAqIE51bWJlciBvZiBwcmVjb21wdXRlZCBwb2ludHMgZGVwZW5kcyBvbiB0aGUgY3VydmUgc2l6ZTpcbiAgICAgICAgICogMl4o8J2RiuKIkjEpICogKE1hdGguY2VpbCjwnZGbIC8g8J2RiikgKyAxKSwgd2hlcmU6XG4gICAgICAgICAqIC0g8J2RiiBpcyB0aGUgd2luZG93IHNpemVcbiAgICAgICAgICogLSDwnZGbIGlzIHRoZSBiaXRsZW5ndGggb2YgdGhlIGN1cnZlIG9yZGVyLlxuICAgICAgICAgKiBGb3IgYSAyNTYtYml0IGN1cnZlIGFuZCB3aW5kb3cgc2l6ZSA4LCB0aGUgbnVtYmVyIG9mIHByZWNvbXB1dGVkIHBvaW50cyBpcyAxMjggKiAzMyA9IDQyMjQuXG4gICAgICAgICAqIEByZXR1cm5zIHByZWNvbXB1dGVkIHBvaW50IHRhYmxlcyBmbGF0dGVuZWQgdG8gYSBzaW5nbGUgYXJyYXlcbiAgICAgICAgICovXG4gICAgICAgIHByZWNvbXB1dGVXaW5kb3coZWxtLCBXKSB7XG4gICAgICAgICAgICBjb25zdCB7IHdpbmRvd3MsIHdpbmRvd1NpemUgfSA9IG9wdHMoVyk7XG4gICAgICAgICAgICBjb25zdCBwb2ludHMgPSBbXTtcbiAgICAgICAgICAgIGxldCBwID0gZWxtO1xuICAgICAgICAgICAgbGV0IGJhc2UgPSBwO1xuICAgICAgICAgICAgZm9yIChsZXQgd2luZG93ID0gMDsgd2luZG93IDwgd2luZG93czsgd2luZG93KyspIHtcbiAgICAgICAgICAgICAgICBiYXNlID0gcDtcbiAgICAgICAgICAgICAgICBwb2ludHMucHVzaChiYXNlKTtcbiAgICAgICAgICAgICAgICAvLyA9MSwgYmVjYXVzZSB3ZSBza2lwIHplcm9cbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHdpbmRvd1NpemU7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBiYXNlID0gYmFzZS5hZGQocCk7XG4gICAgICAgICAgICAgICAgICAgIHBvaW50cy5wdXNoKGJhc2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwID0gYmFzZS5kb3VibGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBwb2ludHM7XG4gICAgICAgIH0sXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJbXBsZW1lbnRzIGVjIG11bHRpcGxpY2F0aW9uIHVzaW5nIHByZWNvbXB1dGVkIHRhYmxlcyBhbmQgdy1hcnkgbm9uLWFkamFjZW50IGZvcm0uXG4gICAgICAgICAqIEBwYXJhbSBXIHdpbmRvdyBzaXplXG4gICAgICAgICAqIEBwYXJhbSBwcmVjb21wdXRlcyBwcmVjb21wdXRlZCB0YWJsZXNcbiAgICAgICAgICogQHBhcmFtIG4gc2NhbGFyICh3ZSBkb24ndCBjaGVjayBoZXJlLCBidXQgc2hvdWxkIGJlIGxlc3MgdGhhbiBjdXJ2ZSBvcmRlcilcbiAgICAgICAgICogQHJldHVybnMgcmVhbCBhbmQgZmFrZSAoZm9yIGNvbnN0LXRpbWUpIHBvaW50c1xuICAgICAgICAgKi9cbiAgICAgICAgd05BRihXLCBwcmVjb21wdXRlcywgbikge1xuICAgICAgICAgICAgLy8gVE9ETzogbWF5YmUgY2hlY2sgdGhhdCBzY2FsYXIgaXMgbGVzcyB0aGFuIGdyb3VwIG9yZGVyPyB3TkFGIGJlaGF2aW91cyBpcyB1bmRlZmluZWQgb3RoZXJ3aXNlXG4gICAgICAgICAgICAvLyBCdXQgbmVlZCB0byBjYXJlZnVsbHkgcmVtb3ZlIG90aGVyIGNoZWNrcyBiZWZvcmUgd05BRi4gT1JERVIgPT0gYml0cyBoZXJlXG4gICAgICAgICAgICBjb25zdCB7IHdpbmRvd3MsIHdpbmRvd1NpemUgfSA9IG9wdHMoVyk7XG4gICAgICAgICAgICBsZXQgcCA9IGMuWkVSTztcbiAgICAgICAgICAgIGxldCBmID0gYy5CQVNFO1xuICAgICAgICAgICAgY29uc3QgbWFzayA9IEJpZ0ludCgyICoqIFcgLSAxKTsgLy8gQ3JlYXRlIG1hc2sgd2l0aCBXIG9uZXM6IDBiMTExMSBmb3IgVz00IGV0Yy5cbiAgICAgICAgICAgIGNvbnN0IG1heE51bWJlciA9IDIgKiogVztcbiAgICAgICAgICAgIGNvbnN0IHNoaWZ0QnkgPSBCaWdJbnQoVyk7XG4gICAgICAgICAgICBmb3IgKGxldCB3aW5kb3cgPSAwOyB3aW5kb3cgPCB3aW5kb3dzOyB3aW5kb3crKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHdpbmRvdyAqIHdpbmRvd1NpemU7XG4gICAgICAgICAgICAgICAgLy8gRXh0cmFjdCBXIGJpdHMuXG4gICAgICAgICAgICAgICAgbGV0IHdiaXRzID0gTnVtYmVyKG4gJiBtYXNrKTtcbiAgICAgICAgICAgICAgICAvLyBTaGlmdCBudW1iZXIgYnkgVyBiaXRzLlxuICAgICAgICAgICAgICAgIG4gPj49IHNoaWZ0Qnk7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIGJpdHMgYXJlIGJpZ2dlciB0aGFuIG1heCBzaXplLCB3ZSdsbCBzcGxpdCB0aG9zZS5cbiAgICAgICAgICAgICAgICAvLyArMjI0ID0+IDI1NiAtIDMyXG4gICAgICAgICAgICAgICAgaWYgKHdiaXRzID4gd2luZG93U2l6ZSkge1xuICAgICAgICAgICAgICAgICAgICB3Yml0cyAtPSBtYXhOdW1iZXI7XG4gICAgICAgICAgICAgICAgICAgIG4gKz0gXzFuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBUaGlzIGNvZGUgd2FzIGZpcnN0IHdyaXR0ZW4gd2l0aCBhc3N1bXB0aW9uIHRoYXQgJ2YnIGFuZCAncCcgd2lsbCBuZXZlciBiZSBpbmZpbml0eSBwb2ludDpcbiAgICAgICAgICAgICAgICAvLyBzaW5jZSBlYWNoIGFkZGl0aW9uIGlzIG11bHRpcGxpZWQgYnkgMiAqKiBXLCBpdCBjYW5ub3QgY2FuY2VsIGVhY2ggb3RoZXIuIEhvd2V2ZXIsXG4gICAgICAgICAgICAgICAgLy8gdGhlcmUgaXMgbmVnYXRlIG5vdzogaXQgaXMgcG9zc2libGUgdGhhdCBuZWdhdGVkIGVsZW1lbnQgZnJvbSBsb3cgdmFsdWVcbiAgICAgICAgICAgICAgICAvLyB3b3VsZCBiZSB0aGUgc2FtZSBhcyBoaWdoIGVsZW1lbnQsIHdoaWNoIHdpbGwgY3JlYXRlIGNhcnJ5IGludG8gbmV4dCB3aW5kb3cuXG4gICAgICAgICAgICAgICAgLy8gSXQncyBub3Qgb2J2aW91cyBob3cgdGhpcyBjYW4gZmFpbCwgYnV0IHN0aWxsIHdvcnRoIGludmVzdGlnYXRpbmcgbGF0ZXIuXG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgd2UncmUgb250byBaZXJvIHBvaW50LlxuICAgICAgICAgICAgICAgIC8vIEFkZCByYW5kb20gcG9pbnQgaW5zaWRlIGN1cnJlbnQgd2luZG93IHRvIGYuXG4gICAgICAgICAgICAgICAgY29uc3Qgb2Zmc2V0MSA9IG9mZnNldDtcbiAgICAgICAgICAgICAgICBjb25zdCBvZmZzZXQyID0gb2Zmc2V0ICsgTWF0aC5hYnMod2JpdHMpIC0gMTsgLy8gLTEgYmVjYXVzZSB3ZSBza2lwIHplcm9cbiAgICAgICAgICAgICAgICBjb25zdCBjb25kMSA9IHdpbmRvdyAlIDIgIT09IDA7XG4gICAgICAgICAgICAgICAgY29uc3QgY29uZDIgPSB3Yml0cyA8IDA7XG4gICAgICAgICAgICAgICAgaWYgKHdiaXRzID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSBtb3N0IGltcG9ydGFudCBwYXJ0IGZvciBjb25zdC10aW1lIGdldFB1YmxpY0tleVxuICAgICAgICAgICAgICAgICAgICBmID0gZi5hZGQoY29uc3RUaW1lTmVnYXRlKGNvbmQxLCBwcmVjb21wdXRlc1tvZmZzZXQxXSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcCA9IHAuYWRkKGNvbnN0VGltZU5lZ2F0ZShjb25kMiwgcHJlY29tcHV0ZXNbb2Zmc2V0Ml0pKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBKSVQtY29tcGlsZXIgc2hvdWxkIG5vdCBlbGltaW5hdGUgZiBoZXJlLCBzaW5jZSBpdCB3aWxsIGxhdGVyIGJlIHVzZWQgaW4gbm9ybWFsaXplWigpXG4gICAgICAgICAgICAvLyBFdmVuIGlmIHRoZSB2YXJpYWJsZSBpcyBzdGlsbCB1bnVzZWQsIHRoZXJlIGFyZSBzb21lIGNoZWNrcyB3aGljaCB3aWxsXG4gICAgICAgICAgICAvLyB0aHJvdyBhbiBleGNlcHRpb24sIHNvIGNvbXBpbGVyIG5lZWRzIHRvIHByb3ZlIHRoZXkgd29uJ3QgaGFwcGVuLCB3aGljaCBpcyBoYXJkLlxuICAgICAgICAgICAgLy8gQXQgdGhpcyBwb2ludCB0aGVyZSBpcyBhIHdheSB0byBGIGJlIGluZmluaXR5LXBvaW50IGV2ZW4gaWYgcCBpcyBub3QsXG4gICAgICAgICAgICAvLyB3aGljaCBtYWtlcyBpdCBsZXNzIGNvbnN0LXRpbWU6IGFyb3VuZCAxIGJpZ2ludCBtdWx0aXBseS5cbiAgICAgICAgICAgIHJldHVybiB7IHAsIGYgfTtcbiAgICAgICAgfSxcbiAgICAgICAgd05BRkNhY2hlZChQLCBwcmVjb21wdXRlc01hcCwgbiwgdHJhbnNmb3JtKSB7XG4gICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICBjb25zdCBXID0gUC5fV0lORE9XX1NJWkUgfHwgMTtcbiAgICAgICAgICAgIC8vIENhbGN1bGF0ZSBwcmVjb21wdXRlcyBvbiBhIGZpcnN0IHJ1biwgcmV1c2UgdGhlbSBhZnRlclxuICAgICAgICAgICAgbGV0IGNvbXAgPSBwcmVjb21wdXRlc01hcC5nZXQoUCk7XG4gICAgICAgICAgICBpZiAoIWNvbXApIHtcbiAgICAgICAgICAgICAgICBjb21wID0gdGhpcy5wcmVjb21wdXRlV2luZG93KFAsIFcpO1xuICAgICAgICAgICAgICAgIGlmIChXICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHByZWNvbXB1dGVzTWFwLnNldChQLCB0cmFuc2Zvcm0oY29tcCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLndOQUYoVywgY29tcCwgbik7XG4gICAgICAgIH0sXG4gICAgfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUJhc2ljKGN1cnZlKSB7XG4gICAgdmFsaWRhdGVGaWVsZChjdXJ2ZS5GcCk7XG4gICAgdmFsaWRhdGVPYmplY3QoY3VydmUsIHtcbiAgICAgICAgbjogJ2JpZ2ludCcsXG4gICAgICAgIGg6ICdiaWdpbnQnLFxuICAgICAgICBHeDogJ2ZpZWxkJyxcbiAgICAgICAgR3k6ICdmaWVsZCcsXG4gICAgfSwge1xuICAgICAgICBuQml0TGVuZ3RoOiAnaXNTYWZlSW50ZWdlcicsXG4gICAgICAgIG5CeXRlTGVuZ3RoOiAnaXNTYWZlSW50ZWdlcicsXG4gICAgfSk7XG4gICAgLy8gU2V0IGRlZmF1bHRzXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoe1xuICAgICAgICAuLi5uTGVuZ3RoKGN1cnZlLm4sIGN1cnZlLm5CaXRMZW5ndGgpLFxuICAgICAgICAuLi5jdXJ2ZSxcbiAgICAgICAgLi4ueyBwOiBjdXJ2ZS5GcC5PUkRFUiB9LFxuICAgIH0pO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y3VydmUuanMubWFwIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/@noble/curves/esm/abstract/curve.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/@noble/curves/esm/abstract/edwards.js":
+/*!************************************************************!*\
+  !*** ./node_modules/@noble/curves/esm/abstract/edwards.js ***!
+  \************************************************************/
+/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   twistedEdwards: () => (/* binding */ twistedEdwards)\n/* harmony export */ });\n/* harmony import */ var _modular_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./modular.js */ \"./node_modules/@noble/curves/esm/abstract/modular.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils.js */ \"./node_modules/@noble/curves/esm/abstract/utils.js\");\n/* harmony import */ var _curve_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./curve.js */ \"./node_modules/@noble/curves/esm/abstract/curve.js\");\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y²\n\n\n\n\n// Be friendly to bad ECMAScript parsers by not using bigint literals\n// prettier-ignore\nconst _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _8n = BigInt(8);\n// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex:\nconst VERIFY_DEFAULT = { zip215: true };\nfunction validateOpts(curve) {\n    const opts = (0,_curve_js__WEBPACK_IMPORTED_MODULE_2__.validateBasic)(curve);\n    _utils_js__WEBPACK_IMPORTED_MODULE_1__.validateObject(curve, {\n        hash: 'function',\n        a: 'bigint',\n        d: 'bigint',\n        randomBytes: 'function',\n    }, {\n        adjustScalarBytes: 'function',\n        domain: 'function',\n        uvRatio: 'function',\n        mapToCurve: 'function',\n    });\n    // Set defaults\n    return Object.freeze({ ...opts });\n}\n// It is not generic twisted curve for now, but ed25519/ed448 generic implementation\nfunction twistedEdwards(curveDef) {\n    const CURVE = validateOpts(curveDef);\n    const { Fp, n: CURVE_ORDER, prehash: prehash, hash: cHash, randomBytes, nByteLength, h: cofactor, } = CURVE;\n    const MASK = _2n ** BigInt(nByteLength * 8);\n    const modP = Fp.create; // Function overrides\n    // sqrt(u/v)\n    const uvRatio = CURVE.uvRatio ||\n        ((u, v) => {\n            try {\n                return { isValid: true, value: Fp.sqrt(u * Fp.inv(v)) };\n            }\n            catch (e) {\n                return { isValid: false, value: _0n };\n            }\n        });\n    const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes) => bytes); // NOOP\n    const domain = CURVE.domain ||\n        ((data, ctx, phflag) => {\n            if (ctx.length || phflag)\n                throw new Error('Contexts/pre-hash are not supported');\n            return data;\n        }); // NOOP\n    const inBig = (n) => typeof n === 'bigint' && _0n < n; // n in [1..]\n    const inRange = (n, max) => inBig(n) && inBig(max) && n < max; // n in [1..max-1]\n    const in0MaskRange = (n) => n === _0n || inRange(n, MASK); // n in [0..MASK-1]\n    function assertInRange(n, max) {\n        // n in [1..max-1]\n        if (inRange(n, max))\n            return n;\n        throw new Error(`Expected valid scalar < ${max}, got ${typeof n} ${n}`);\n    }\n    function assertGE0(n) {\n        // n in [0..CURVE_ORDER-1]\n        return n === _0n ? n : assertInRange(n, CURVE_ORDER); // GE = prime subgroup, not full group\n    }\n    const pointPrecomputes = new Map();\n    function isPoint(other) {\n        if (!(other instanceof Point))\n            throw new Error('ExtendedPoint expected');\n    }\n    // Extended Point works in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z, t=xy).\n    // https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Extended_coordinates\n    class Point {\n        constructor(ex, ey, ez, et) {\n            this.ex = ex;\n            this.ey = ey;\n            this.ez = ez;\n            this.et = et;\n            if (!in0MaskRange(ex))\n                throw new Error('x required');\n            if (!in0MaskRange(ey))\n                throw new Error('y required');\n            if (!in0MaskRange(ez))\n                throw new Error('z required');\n            if (!in0MaskRange(et))\n                throw new Error('t required');\n        }\n        get x() {\n            return this.toAffine().x;\n        }\n        get y() {\n            return this.toAffine().y;\n        }\n        static fromAffine(p) {\n            if (p instanceof Point)\n                throw new Error('extended point not allowed');\n            const { x, y } = p || {};\n            if (!in0MaskRange(x) || !in0MaskRange(y))\n                throw new Error('invalid affine point');\n            return new Point(x, y, _1n, modP(x * y));\n        }\n        static normalizeZ(points) {\n            const toInv = Fp.invertBatch(points.map((p) => p.ez));\n            return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);\n        }\n        // \"Private method\", don't use it directly\n        _setWindowSize(windowSize) {\n            this._WINDOW_SIZE = windowSize;\n            pointPrecomputes.delete(this);\n        }\n        // Not required for fromHex(), which always creates valid points.\n        // Could be useful for fromAffine().\n        assertValidity() {\n            const { a, d } = CURVE;\n            if (this.is0())\n                throw new Error('bad point: ZERO'); // TODO: optimize, with vars below?\n            // Equation in affine coordinates: ax² + y² = 1 + dx²y²\n            // Equation in projective coordinates (X/Z, Y/Z, Z):  (aX² + Y²)Z² = Z⁴ + dX²Y²\n            const { ex: X, ey: Y, ez: Z, et: T } = this;\n            const X2 = modP(X * X); // X²\n            const Y2 = modP(Y * Y); // Y²\n            const Z2 = modP(Z * Z); // Z²\n            const Z4 = modP(Z2 * Z2); // Z⁴\n            const aX2 = modP(X2 * a); // aX²\n            const left = modP(Z2 * modP(aX2 + Y2)); // (aX² + Y²)Z²\n            const right = modP(Z4 + modP(d * modP(X2 * Y2))); // Z⁴ + dX²Y²\n            if (left !== right)\n                throw new Error('bad point: equation left != right (1)');\n            // In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T\n            const XY = modP(X * Y);\n            const ZT = modP(Z * T);\n            if (XY !== ZT)\n                throw new Error('bad point: equation left != right (2)');\n        }\n        // Compare one point to another.\n        equals(other) {\n            isPoint(other);\n            const { ex: X1, ey: Y1, ez: Z1 } = this;\n            const { ex: X2, ey: Y2, ez: Z2 } = other;\n            const X1Z2 = modP(X1 * Z2);\n            const X2Z1 = modP(X2 * Z1);\n            const Y1Z2 = modP(Y1 * Z2);\n            const Y2Z1 = modP(Y2 * Z1);\n            return X1Z2 === X2Z1 && Y1Z2 === Y2Z1;\n        }\n        is0() {\n            return this.equals(Point.ZERO);\n        }\n        negate() {\n            // Flips point sign to a negative one (-x, y in affine coords)\n            return new Point(modP(-this.ex), this.ey, this.ez, modP(-this.et));\n        }\n        // Fast algo for doubling Extended Point.\n        // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd\n        // Cost: 4M + 4S + 1*a + 6add + 1*2.\n        double() {\n            const { a } = CURVE;\n            const { ex: X1, ey: Y1, ez: Z1 } = this;\n            const A = modP(X1 * X1); // A = X12\n            const B = modP(Y1 * Y1); // B = Y12\n            const C = modP(_2n * modP(Z1 * Z1)); // C = 2*Z12\n            const D = modP(a * A); // D = a*A\n            const x1y1 = X1 + Y1;\n            const E = modP(modP(x1y1 * x1y1) - A - B); // E = (X1+Y1)2-A-B\n            const G = D + B; // G = D+B\n            const F = G - C; // F = G-C\n            const H = D - B; // H = D-B\n            const X3 = modP(E * F); // X3 = E*F\n            const Y3 = modP(G * H); // Y3 = G*H\n            const T3 = modP(E * H); // T3 = E*H\n            const Z3 = modP(F * G); // Z3 = F*G\n            return new Point(X3, Y3, Z3, T3);\n        }\n        // Fast algo for adding 2 Extended Points.\n        // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd\n        // Cost: 9M + 1*a + 1*d + 7add.\n        add(other) {\n            isPoint(other);\n            const { a, d } = CURVE;\n            const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this;\n            const { ex: X2, ey: Y2, ez: Z2, et: T2 } = other;\n            // Faster algo for adding 2 Extended Points when curve's a=-1.\n            // http://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-4\n            // Cost: 8M + 8add + 2*2.\n            // Note: It does not check whether the `other` point is valid.\n            if (a === BigInt(-1)) {\n                const A = modP((Y1 - X1) * (Y2 + X2));\n                const B = modP((Y1 + X1) * (Y2 - X2));\n                const F = modP(B - A);\n                if (F === _0n)\n                    return this.double(); // Same point. Tests say it doesn't affect timing\n                const C = modP(Z1 * _2n * T2);\n                const D = modP(T1 * _2n * Z2);\n                const E = D + C;\n                const G = B + A;\n                const H = D - C;\n                const X3 = modP(E * F);\n                const Y3 = modP(G * H);\n                const T3 = modP(E * H);\n                const Z3 = modP(F * G);\n                return new Point(X3, Y3, Z3, T3);\n            }\n            const A = modP(X1 * X2); // A = X1*X2\n            const B = modP(Y1 * Y2); // B = Y1*Y2\n            const C = modP(T1 * d * T2); // C = T1*d*T2\n            const D = modP(Z1 * Z2); // D = Z1*Z2\n            const E = modP((X1 + Y1) * (X2 + Y2) - A - B); // E = (X1+Y1)*(X2+Y2)-A-B\n            const F = D - C; // F = D-C\n            const G = D + C; // G = D+C\n            const H = modP(B - a * A); // H = B-a*A\n            const X3 = modP(E * F); // X3 = E*F\n            const Y3 = modP(G * H); // Y3 = G*H\n            const T3 = modP(E * H); // T3 = E*H\n            const Z3 = modP(F * G); // Z3 = F*G\n            return new Point(X3, Y3, Z3, T3);\n        }\n        subtract(other) {\n            return this.add(other.negate());\n        }\n        wNAF(n) {\n            return wnaf.wNAFCached(this, pointPrecomputes, n, Point.normalizeZ);\n        }\n        // Constant-time multiplication.\n        multiply(scalar) {\n            const { p, f } = this.wNAF(assertInRange(scalar, CURVE_ORDER));\n            return Point.normalizeZ([p, f])[0];\n        }\n        // Non-constant-time multiplication. Uses double-and-add algorithm.\n        // It's faster, but should only be used when you don't care about\n        // an exposed private key e.g. sig verification.\n        // Does NOT allow scalars higher than CURVE.n.\n        multiplyUnsafe(scalar) {\n            let n = assertGE0(scalar); // 0 <= scalar < CURVE.n\n            if (n === _0n)\n                return I;\n            if (this.equals(I) || n === _1n)\n                return this;\n            if (this.equals(G))\n                return this.wNAF(n).p;\n            return wnaf.unsafeLadder(this, n);\n        }\n        // Checks if point is of small order.\n        // If you add something to small order point, you will have \"dirty\"\n        // point with torsion component.\n        // Multiplies point by cofactor and checks if the result is 0.\n        isSmallOrder() {\n            return this.multiplyUnsafe(cofactor).is0();\n        }\n        // Multiplies point by curve order and checks if the result is 0.\n        // Returns `false` is the point is dirty.\n        isTorsionFree() {\n            return wnaf.unsafeLadder(this, CURVE_ORDER).is0();\n        }\n        // Converts Extended point to default (x, y) coordinates.\n        // Can accept precomputed Z^-1 - for example, from invertBatch.\n        toAffine(iz) {\n            const { ex: x, ey: y, ez: z } = this;\n            const is0 = this.is0();\n            if (iz == null)\n                iz = is0 ? _8n : Fp.inv(z); // 8 was chosen arbitrarily\n            const ax = modP(x * iz);\n            const ay = modP(y * iz);\n            const zz = modP(z * iz);\n            if (is0)\n                return { x: _0n, y: _1n };\n            if (zz !== _1n)\n                throw new Error('invZ was invalid');\n            return { x: ax, y: ay };\n        }\n        clearCofactor() {\n            const { h: cofactor } = CURVE;\n            if (cofactor === _1n)\n                return this;\n            return this.multiplyUnsafe(cofactor);\n        }\n        // Converts hash string or Uint8Array to Point.\n        // Uses algo from RFC8032 5.1.3.\n        static fromHex(hex, zip215 = false) {\n            const { d, a } = CURVE;\n            const len = Fp.BYTES;\n            hex = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.ensureBytes)('pointHex', hex, len); // copy hex to a new array\n            const normed = hex.slice(); // copy again, we'll manipulate it\n            const lastByte = hex[len - 1]; // select last byte\n            normed[len - 1] = lastByte & ~0x80; // clear last bit\n            const y = _utils_js__WEBPACK_IMPORTED_MODULE_1__.bytesToNumberLE(normed);\n            if (y === _0n) {\n                // y=0 is allowed\n            }\n            else {\n                // RFC8032 prohibits >= p, but ZIP215 doesn't\n                if (zip215)\n                    assertInRange(y, MASK); // zip215=true [1..P-1] (2^255-19-1 for ed25519)\n                else\n                    assertInRange(y, Fp.ORDER); // zip215=false [1..MASK-1] (2^256-1 for ed25519)\n            }\n            // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case:\n            // ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a)\n            const y2 = modP(y * y); // denominator is always non-0 mod p.\n            const u = modP(y2 - _1n); // u = y² - 1\n            const v = modP(d * y2 - a); // v = d y² + 1.\n            let { isValid, value: x } = uvRatio(u, v); // √(u/v)\n            if (!isValid)\n                throw new Error('Point.fromHex: invalid y coordinate');\n            const isXOdd = (x & _1n) === _1n; // There are 2 square roots. Use x_0 bit to select proper\n            const isLastByteOdd = (lastByte & 0x80) !== 0; // if x=0 and x_0 = 1, fail\n            if (isLastByteOdd !== isXOdd)\n                x = modP(-x); // if x_0 != x mod 2, set x = p-x\n            return Point.fromAffine({ x, y });\n        }\n        static fromPrivateKey(privKey) {\n            return getExtendedPublicKey(privKey).point;\n        }\n        toRawBytes() {\n            const { x, y } = this.toAffine();\n            const bytes = _utils_js__WEBPACK_IMPORTED_MODULE_1__.numberToBytesLE(y, Fp.BYTES); // each y has 2 x values (x, -y)\n            bytes[bytes.length - 1] |= x & _1n ? 0x80 : 0; // when compressing, it's enough to store y\n            return bytes; // and use the last byte to encode sign of x\n        }\n        toHex() {\n            return _utils_js__WEBPACK_IMPORTED_MODULE_1__.bytesToHex(this.toRawBytes()); // Same as toRawBytes, but returns string.\n        }\n    }\n    Point.BASE = new Point(CURVE.Gx, CURVE.Gy, _1n, modP(CURVE.Gx * CURVE.Gy));\n    Point.ZERO = new Point(_0n, _1n, _1n, _0n); // 0, 1, 1, 0\n    const { BASE: G, ZERO: I } = Point;\n    const wnaf = (0,_curve_js__WEBPACK_IMPORTED_MODULE_2__.wNAF)(Point, nByteLength * 8);\n    function modN(a) {\n        return (0,_modular_js__WEBPACK_IMPORTED_MODULE_0__.mod)(a, CURVE_ORDER);\n    }\n    // Little-endian SHA512 with modulo n\n    function modN_LE(hash) {\n        return modN(_utils_js__WEBPACK_IMPORTED_MODULE_1__.bytesToNumberLE(hash));\n    }\n    /** Convenience method that creates public key and other stuff. RFC8032 5.1.5 */\n    function getExtendedPublicKey(key) {\n        const len = nByteLength;\n        key = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.ensureBytes)('private key', key, len);\n        // Hash private key with curve's hash function to produce uniformingly random input\n        // Check byte lengths: ensure(64, h(ensure(32, key)))\n        const hashed = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.ensureBytes)('hashed private key', cHash(key), 2 * len);\n        const head = adjustScalarBytes(hashed.slice(0, len)); // clear first half bits, produce FE\n        const prefix = hashed.slice(len, 2 * len); // second half is called key prefix (5.1.6)\n        const scalar = modN_LE(head); // The actual private scalar\n        const point = G.multiply(scalar); // Point on Edwards curve aka public key\n        const pointBytes = point.toRawBytes(); // Uint8Array representation\n        return { head, prefix, scalar, point, pointBytes };\n    }\n    // Calculates EdDSA pub key. RFC8032 5.1.5. Privkey is hashed. Use first half with 3 bits cleared\n    function getPublicKey(privKey) {\n        return getExtendedPublicKey(privKey).pointBytes;\n    }\n    // int('LE', SHA512(dom2(F, C) || msgs)) mod N\n    function hashDomainToScalar(context = new Uint8Array(), ...msgs) {\n        const msg = _utils_js__WEBPACK_IMPORTED_MODULE_1__.concatBytes(...msgs);\n        return modN_LE(cHash(domain(msg, (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.ensureBytes)('context', context), !!prehash)));\n    }\n    /** Signs message with privateKey. RFC8032 5.1.6 */\n    function sign(msg, privKey, options = {}) {\n        msg = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.ensureBytes)('message', msg);\n        if (prehash)\n            msg = prehash(msg); // for ed25519ph etc.\n        const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey);\n        const r = hashDomainToScalar(options.context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)\n        const R = G.multiply(r).toRawBytes(); // R = rG\n        const k = hashDomainToScalar(options.context, R, pointBytes, msg); // R || A || PH(M)\n        const s = modN(r + k * scalar); // S = (r + k * s) mod L\n        assertGE0(s); // 0 <= s < l\n        const res = _utils_js__WEBPACK_IMPORTED_MODULE_1__.concatBytes(R, _utils_js__WEBPACK_IMPORTED_MODULE_1__.numberToBytesLE(s, Fp.BYTES));\n        return (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.ensureBytes)('result', res, nByteLength * 2); // 64-byte signature\n    }\n    const verifyOpts = VERIFY_DEFAULT;\n    function verify(sig, msg, publicKey, options = verifyOpts) {\n        const { context, zip215 } = options;\n        const len = Fp.BYTES; // Verifies EdDSA signature against message and public key. RFC8032 5.1.7.\n        sig = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.ensureBytes)('signature', sig, 2 * len); // An extended group equation is checked.\n        msg = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.ensureBytes)('message', msg);\n        if (prehash)\n            msg = prehash(msg); // for ed25519ph, etc\n        const s = _utils_js__WEBPACK_IMPORTED_MODULE_1__.bytesToNumberLE(sig.slice(len, 2 * len));\n        // zip215: true is good for consensus-critical apps and allows points < 2^256\n        // zip215: false follows RFC8032 / NIST186-5 and restricts points to CURVE.p\n        let A, R, SB;\n        try {\n            A = Point.fromHex(publicKey, zip215);\n            R = Point.fromHex(sig.slice(0, len), zip215);\n            SB = G.multiplyUnsafe(s); // 0 <= s < l is done inside\n        }\n        catch (error) {\n            return false;\n        }\n        const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg);\n        const RkA = R.add(A.multiplyUnsafe(k));\n        // [8][S]B = [8]R + [8][k]A'\n        return RkA.subtract(SB).clearCofactor().equals(Point.ZERO);\n    }\n    G._setWindowSize(8); // Enable precomputes. Slows down first publicKey computation by 20ms.\n    const utils = {\n        getExtendedPublicKey,\n        // ed25519 private keys are uniform 32b. No need to check for modulo bias, like in secp256k1.\n        randomPrivateKey: () => randomBytes(Fp.BYTES),\n        /**\n         * We're doing scalar multiplication (used in getPublicKey etc) with precomputed BASE_POINT\n         * values. This slows down first getPublicKey() by milliseconds (see Speed section),\n         * but allows to speed-up subsequent getPublicKey() calls up to 20x.\n         * @param windowSize 2, 4, 8, 16\n         */\n        precompute(windowSize = 8, point = Point.BASE) {\n            point._setWindowSize(windowSize);\n            point.multiply(BigInt(3));\n            return point;\n        },\n    };\n    return {\n        CURVE,\n        getPublicKey,\n        sign,\n        verify,\n        ExtendedPoint: Point,\n        utils,\n    };\n}\n//# sourceMappingURL=edwards.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQG5vYmxlL2N1cnZlcy9lc20vYWJzdHJhY3QvZWR3YXJkcy5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9jdXJ2ZXMvZXNtL2Fic3RyYWN0L2Vkd2FyZHMuanM/YjFhZSJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiEgbm9ibGUtY3VydmVzIC0gTUlUIExpY2Vuc2UgKGMpIDIwMjIgUGF1bCBNaWxsZXIgKHBhdWxtaWxsci5jb20pICovXG4vLyBUd2lzdGVkIEVkd2FyZHMgY3VydmUuIFRoZSBmb3JtdWxhIGlzOiBheMKyICsgecKyID0gMSArIGR4wrJ5wrJcbmltcG9ydCB7IG1vZCB9IGZyb20gJy4vbW9kdWxhci5qcyc7XG5pbXBvcnQgKiBhcyB1dCBmcm9tICcuL3V0aWxzLmpzJztcbmltcG9ydCB7IGVuc3VyZUJ5dGVzIH0gZnJvbSAnLi91dGlscy5qcyc7XG5pbXBvcnQgeyB3TkFGLCB2YWxpZGF0ZUJhc2ljIH0gZnJvbSAnLi9jdXJ2ZS5qcyc7XG4vLyBCZSBmcmllbmRseSB0byBiYWQgRUNNQVNjcmlwdCBwYXJzZXJzIGJ5IG5vdCB1c2luZyBiaWdpbnQgbGl0ZXJhbHNcbi8vIHByZXR0aWVyLWlnbm9yZVxuY29uc3QgXzBuID0gQmlnSW50KDApLCBfMW4gPSBCaWdJbnQoMSksIF8ybiA9IEJpZ0ludCgyKSwgXzhuID0gQmlnSW50KDgpO1xuLy8gdmVyaWZpY2F0aW9uIHJ1bGUgaXMgZWl0aGVyIHppcDIxNSBvciByZmM4MDMyIC8gbmlzdDE4Ni01LiBDb25zdWx0IGZyb21IZXg6XG5jb25zdCBWRVJJRllfREVGQVVMVCA9IHsgemlwMjE1OiB0cnVlIH07XG5mdW5jdGlvbiB2YWxpZGF0ZU9wdHMoY3VydmUpIHtcbiAgICBjb25zdCBvcHRzID0gdmFsaWRhdGVCYXNpYyhjdXJ2ZSk7XG4gICAgdXQudmFsaWRhdGVPYmplY3QoY3VydmUsIHtcbiAgICAgICAgaGFzaDogJ2Z1bmN0aW9uJyxcbiAgICAgICAgYTogJ2JpZ2ludCcsXG4gICAgICAgIGQ6ICdiaWdpbnQnLFxuICAgICAgICByYW5kb21CeXRlczogJ2Z1bmN0aW9uJyxcbiAgICB9LCB7XG4gICAgICAgIGFkanVzdFNjYWxhckJ5dGVzOiAnZnVuY3Rpb24nLFxuICAgICAgICBkb21haW46ICdmdW5jdGlvbicsXG4gICAgICAgIHV2UmF0aW86ICdmdW5jdGlvbicsXG4gICAgICAgIG1hcFRvQ3VydmU6ICdmdW5jdGlvbicsXG4gICAgfSk7XG4gICAgLy8gU2V0IGRlZmF1bHRzXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeyAuLi5vcHRzIH0pO1xufVxuLy8gSXQgaXMgbm90IGdlbmVyaWMgdHdpc3RlZCBjdXJ2ZSBmb3Igbm93LCBidXQgZWQyNTUxOS9lZDQ0OCBnZW5lcmljIGltcGxlbWVudGF0aW9uXG5leHBvcnQgZnVuY3Rpb24gdHdpc3RlZEVkd2FyZHMoY3VydmVEZWYpIHtcbiAgICBjb25zdCBDVVJWRSA9IHZhbGlkYXRlT3B0cyhjdXJ2ZURlZik7XG4gICAgY29uc3QgeyBGcCwgbjogQ1VSVkVfT1JERVIsIHByZWhhc2g6IHByZWhhc2gsIGhhc2g6IGNIYXNoLCByYW5kb21CeXRlcywgbkJ5dGVMZW5ndGgsIGg6IGNvZmFjdG9yLCB9ID0gQ1VSVkU7XG4gICAgY29uc3QgTUFTSyA9IF8ybiAqKiBCaWdJbnQobkJ5dGVMZW5ndGggKiA4KTtcbiAgICBjb25zdCBtb2RQID0gRnAuY3JlYXRlOyAvLyBGdW5jdGlvbiBvdmVycmlkZXNcbiAgICAvLyBzcXJ0KHUvdilcbiAgICBjb25zdCB1dlJhdGlvID0gQ1VSVkUudXZSYXRpbyB8fFxuICAgICAgICAoKHUsIHYpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgaXNWYWxpZDogdHJ1ZSwgdmFsdWU6IEZwLnNxcnQodSAqIEZwLmludih2KSkgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgaXNWYWxpZDogZmFsc2UsIHZhbHVlOiBfMG4gfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgY29uc3QgYWRqdXN0U2NhbGFyQnl0ZXMgPSBDVVJWRS5hZGp1c3RTY2FsYXJCeXRlcyB8fCAoKGJ5dGVzKSA9PiBieXRlcyk7IC8vIE5PT1BcbiAgICBjb25zdCBkb21haW4gPSBDVVJWRS5kb21haW4gfHxcbiAgICAgICAgKChkYXRhLCBjdHgsIHBoZmxhZykgPT4ge1xuICAgICAgICAgICAgaWYgKGN0eC5sZW5ndGggfHwgcGhmbGFnKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ29udGV4dHMvcHJlLWhhc2ggYXJlIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICAgICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgICB9KTsgLy8gTk9PUFxuICAgIGNvbnN0IGluQmlnID0gKG4pID0+IHR5cGVvZiBuID09PSAnYmlnaW50JyAmJiBfMG4gPCBuOyAvLyBuIGluIFsxLi5dXG4gICAgY29uc3QgaW5SYW5nZSA9IChuLCBtYXgpID0+IGluQmlnKG4pICYmIGluQmlnKG1heCkgJiYgbiA8IG1heDsgLy8gbiBpbiBbMS4ubWF4LTFdXG4gICAgY29uc3QgaW4wTWFza1JhbmdlID0gKG4pID0+IG4gPT09IF8wbiB8fCBpblJhbmdlKG4sIE1BU0spOyAvLyBuIGluIFswLi5NQVNLLTFdXG4gICAgZnVuY3Rpb24gYXNzZXJ0SW5SYW5nZShuLCBtYXgpIHtcbiAgICAgICAgLy8gbiBpbiBbMS4ubWF4LTFdXG4gICAgICAgIGlmIChpblJhbmdlKG4sIG1heCkpXG4gICAgICAgICAgICByZXR1cm4gbjtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCB2YWxpZCBzY2FsYXIgPCAke21heH0sIGdvdCAke3R5cGVvZiBufSAke259YCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGFzc2VydEdFMChuKSB7XG4gICAgICAgIC8vIG4gaW4gWzAuLkNVUlZFX09SREVSLTFdXG4gICAgICAgIHJldHVybiBuID09PSBfMG4gPyBuIDogYXNzZXJ0SW5SYW5nZShuLCBDVVJWRV9PUkRFUik7IC8vIEdFID0gcHJpbWUgc3ViZ3JvdXAsIG5vdCBmdWxsIGdyb3VwXG4gICAgfVxuICAgIGNvbnN0IHBvaW50UHJlY29tcHV0ZXMgPSBuZXcgTWFwKCk7XG4gICAgZnVuY3Rpb24gaXNQb2ludChvdGhlcikge1xuICAgICAgICBpZiAoIShvdGhlciBpbnN0YW5jZW9mIFBvaW50KSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRXh0ZW5kZWRQb2ludCBleHBlY3RlZCcpO1xuICAgIH1cbiAgICAvLyBFeHRlbmRlZCBQb2ludCB3b3JrcyBpbiBleHRlbmRlZCBjb29yZGluYXRlczogKHgsIHksIHosIHQpIOKIiyAoeD14L3osIHk9eS96LCB0PXh5KS5cbiAgICAvLyBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Ud2lzdGVkX0Vkd2FyZHNfY3VydmUjRXh0ZW5kZWRfY29vcmRpbmF0ZXNcbiAgICBjbGFzcyBQb2ludCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGV4LCBleSwgZXosIGV0KSB7XG4gICAgICAgICAgICB0aGlzLmV4ID0gZXg7XG4gICAgICAgICAgICB0aGlzLmV5ID0gZXk7XG4gICAgICAgICAgICB0aGlzLmV6ID0gZXo7XG4gICAgICAgICAgICB0aGlzLmV0ID0gZXQ7XG4gICAgICAgICAgICBpZiAoIWluME1hc2tSYW5nZShleCkpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd4IHJlcXVpcmVkJyk7XG4gICAgICAgICAgICBpZiAoIWluME1hc2tSYW5nZShleSkpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd5IHJlcXVpcmVkJyk7XG4gICAgICAgICAgICBpZiAoIWluME1hc2tSYW5nZShleikpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd6IHJlcXVpcmVkJyk7XG4gICAgICAgICAgICBpZiAoIWluME1hc2tSYW5nZShldCkpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd0IHJlcXVpcmVkJyk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0IHgoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50b0FmZmluZSgpLng7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0IHkoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50b0FmZmluZSgpLnk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGZyb21BZmZpbmUocCkge1xuICAgICAgICAgICAgaWYgKHAgaW5zdGFuY2VvZiBQb2ludClcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2V4dGVuZGVkIHBvaW50IG5vdCBhbGxvd2VkJyk7XG4gICAgICAgICAgICBjb25zdCB7IHgsIHkgfSA9IHAgfHwge307XG4gICAgICAgICAgICBpZiAoIWluME1hc2tSYW5nZSh4KSB8fCAhaW4wTWFza1JhbmdlKHkpKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBhZmZpbmUgcG9pbnQnKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUG9pbnQoeCwgeSwgXzFuLCBtb2RQKHggKiB5KSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIG5vcm1hbGl6ZVoocG9pbnRzKSB7XG4gICAgICAgICAgICBjb25zdCB0b0ludiA9IEZwLmludmVydEJhdGNoKHBvaW50cy5tYXAoKHApID0+IHAuZXopKTtcbiAgICAgICAgICAgIHJldHVybiBwb2ludHMubWFwKChwLCBpKSA9PiBwLnRvQWZmaW5lKHRvSW52W2ldKSkubWFwKFBvaW50LmZyb21BZmZpbmUpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFwiUHJpdmF0ZSBtZXRob2RcIiwgZG9uJ3QgdXNlIGl0IGRpcmVjdGx5XG4gICAgICAgIF9zZXRXaW5kb3dTaXplKHdpbmRvd1NpemUpIHtcbiAgICAgICAgICAgIHRoaXMuX1dJTkRPV19TSVpFID0gd2luZG93U2l6ZTtcbiAgICAgICAgICAgIHBvaW50UHJlY29tcHV0ZXMuZGVsZXRlKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIC8vIE5vdCByZXF1aXJlZCBmb3IgZnJvbUhleCgpLCB3aGljaCBhbHdheXMgY3JlYXRlcyB2YWxpZCBwb2ludHMuXG4gICAgICAgIC8vIENvdWxkIGJlIHVzZWZ1bCBmb3IgZnJvbUFmZmluZSgpLlxuICAgICAgICBhc3NlcnRWYWxpZGl0eSgpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgYSwgZCB9ID0gQ1VSVkU7XG4gICAgICAgICAgICBpZiAodGhpcy5pczAoKSlcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2JhZCBwb2ludDogWkVSTycpOyAvLyBUT0RPOiBvcHRpbWl6ZSwgd2l0aCB2YXJzIGJlbG93P1xuICAgICAgICAgICAgLy8gRXF1YXRpb24gaW4gYWZmaW5lIGNvb3JkaW5hdGVzOiBheMKyICsgecKyID0gMSArIGR4wrJ5wrJcbiAgICAgICAgICAgIC8vIEVxdWF0aW9uIGluIHByb2plY3RpdmUgY29vcmRpbmF0ZXMgKFgvWiwgWS9aLCBaKTogIChhWMKyICsgWcKyKVrCsiA9IFrigbQgKyBkWMKyWcKyXG4gICAgICAgICAgICBjb25zdCB7IGV4OiBYLCBleTogWSwgZXo6IFosIGV0OiBUIH0gPSB0aGlzO1xuICAgICAgICAgICAgY29uc3QgWDIgPSBtb2RQKFggKiBYKTsgLy8gWMKyXG4gICAgICAgICAgICBjb25zdCBZMiA9IG1vZFAoWSAqIFkpOyAvLyBZwrJcbiAgICAgICAgICAgIGNvbnN0IFoyID0gbW9kUChaICogWik7IC8vIFrCslxuICAgICAgICAgICAgY29uc3QgWjQgPSBtb2RQKFoyICogWjIpOyAvLyBa4oG0XG4gICAgICAgICAgICBjb25zdCBhWDIgPSBtb2RQKFgyICogYSk7IC8vIGFYwrJcbiAgICAgICAgICAgIGNvbnN0IGxlZnQgPSBtb2RQKFoyICogbW9kUChhWDIgKyBZMikpOyAvLyAoYVjCsiArIFnCsilawrJcbiAgICAgICAgICAgIGNvbnN0IHJpZ2h0ID0gbW9kUChaNCArIG1vZFAoZCAqIG1vZFAoWDIgKiBZMikpKTsgLy8gWuKBtCArIGRYwrJZwrJcbiAgICAgICAgICAgIGlmIChsZWZ0ICE9PSByaWdodClcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2JhZCBwb2ludDogZXF1YXRpb24gbGVmdCAhPSByaWdodCAoMSknKTtcbiAgICAgICAgICAgIC8vIEluIEV4dGVuZGVkIGNvb3JkaW5hdGVzIHdlIGFsc28gaGF2ZSBULCB3aGljaCBpcyB4Knk9VC9aOiBjaGVjayBYKlkgPT0gWipUXG4gICAgICAgICAgICBjb25zdCBYWSA9IG1vZFAoWCAqIFkpO1xuICAgICAgICAgICAgY29uc3QgWlQgPSBtb2RQKFogKiBUKTtcbiAgICAgICAgICAgIGlmIChYWSAhPT0gWlQpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdiYWQgcG9pbnQ6IGVxdWF0aW9uIGxlZnQgIT0gcmlnaHQgKDIpJyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ29tcGFyZSBvbmUgcG9pbnQgdG8gYW5vdGhlci5cbiAgICAgICAgZXF1YWxzKG90aGVyKSB7XG4gICAgICAgICAgICBpc1BvaW50KG90aGVyKTtcbiAgICAgICAgICAgIGNvbnN0IHsgZXg6IFgxLCBleTogWTEsIGV6OiBaMSB9ID0gdGhpcztcbiAgICAgICAgICAgIGNvbnN0IHsgZXg6IFgyLCBleTogWTIsIGV6OiBaMiB9ID0gb3RoZXI7XG4gICAgICAgICAgICBjb25zdCBYMVoyID0gbW9kUChYMSAqIFoyKTtcbiAgICAgICAgICAgIGNvbnN0IFgyWjEgPSBtb2RQKFgyICogWjEpO1xuICAgICAgICAgICAgY29uc3QgWTFaMiA9IG1vZFAoWTEgKiBaMik7XG4gICAgICAgICAgICBjb25zdCBZMloxID0gbW9kUChZMiAqIFoxKTtcbiAgICAgICAgICAgIHJldHVybiBYMVoyID09PSBYMloxICYmIFkxWjIgPT09IFkyWjE7XG4gICAgICAgIH1cbiAgICAgICAgaXMwKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXF1YWxzKFBvaW50LlpFUk8pO1xuICAgICAgICB9XG4gICAgICAgIG5lZ2F0ZSgpIHtcbiAgICAgICAgICAgIC8vIEZsaXBzIHBvaW50IHNpZ24gdG8gYSBuZWdhdGl2ZSBvbmUgKC14LCB5IGluIGFmZmluZSBjb29yZHMpXG4gICAgICAgICAgICByZXR1cm4gbmV3IFBvaW50KG1vZFAoLXRoaXMuZXgpLCB0aGlzLmV5LCB0aGlzLmV6LCBtb2RQKC10aGlzLmV0KSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRmFzdCBhbGdvIGZvciBkb3VibGluZyBFeHRlbmRlZCBQb2ludC5cbiAgICAgICAgLy8gaHR0cHM6Ly9oeXBlcmVsbGlwdGljLm9yZy9FRkQvZzFwL2F1dG8tdHdpc3RlZC1leHRlbmRlZC5odG1sI2RvdWJsaW5nLWRibC0yMDA4LWh3Y2RcbiAgICAgICAgLy8gQ29zdDogNE0gKyA0UyArIDEqYSArIDZhZGQgKyAxKjIuXG4gICAgICAgIGRvdWJsZSgpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgYSB9ID0gQ1VSVkU7XG4gICAgICAgICAgICBjb25zdCB7IGV4OiBYMSwgZXk6IFkxLCBlejogWjEgfSA9IHRoaXM7XG4gICAgICAgICAgICBjb25zdCBBID0gbW9kUChYMSAqIFgxKTsgLy8gQSA9IFgxMlxuICAgICAgICAgICAgY29uc3QgQiA9IG1vZFAoWTEgKiBZMSk7IC8vIEIgPSBZMTJcbiAgICAgICAgICAgIGNvbnN0IEMgPSBtb2RQKF8ybiAqIG1vZFAoWjEgKiBaMSkpOyAvLyBDID0gMipaMTJcbiAgICAgICAgICAgIGNvbnN0IEQgPSBtb2RQKGEgKiBBKTsgLy8gRCA9IGEqQVxuICAgICAgICAgICAgY29uc3QgeDF5MSA9IFgxICsgWTE7XG4gICAgICAgICAgICBjb25zdCBFID0gbW9kUChtb2RQKHgxeTEgKiB4MXkxKSAtIEEgLSBCKTsgLy8gRSA9IChYMStZMSkyLUEtQlxuICAgICAgICAgICAgY29uc3QgRyA9IEQgKyBCOyAvLyBHID0gRCtCXG4gICAgICAgICAgICBjb25zdCBGID0gRyAtIEM7IC8vIEYgPSBHLUNcbiAgICAgICAgICAgIGNvbnN0IEggPSBEIC0gQjsgLy8gSCA9IEQtQlxuICAgICAgICAgICAgY29uc3QgWDMgPSBtb2RQKEUgKiBGKTsgLy8gWDMgPSBFKkZcbiAgICAgICAgICAgIGNvbnN0IFkzID0gbW9kUChHICogSCk7IC8vIFkzID0gRypIXG4gICAgICAgICAgICBjb25zdCBUMyA9IG1vZFAoRSAqIEgpOyAvLyBUMyA9IEUqSFxuICAgICAgICAgICAgY29uc3QgWjMgPSBtb2RQKEYgKiBHKTsgLy8gWjMgPSBGKkdcbiAgICAgICAgICAgIHJldHVybiBuZXcgUG9pbnQoWDMsIFkzLCBaMywgVDMpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEZhc3QgYWxnbyBmb3IgYWRkaW5nIDIgRXh0ZW5kZWQgUG9pbnRzLlxuICAgICAgICAvLyBodHRwczovL2h5cGVyZWxsaXB0aWMub3JnL0VGRC9nMXAvYXV0by10d2lzdGVkLWV4dGVuZGVkLmh0bWwjYWRkaXRpb24tYWRkLTIwMDgtaHdjZFxuICAgICAgICAvLyBDb3N0OiA5TSArIDEqYSArIDEqZCArIDdhZGQuXG4gICAgICAgIGFkZChvdGhlcikge1xuICAgICAgICAgICAgaXNQb2ludChvdGhlcik7XG4gICAgICAgICAgICBjb25zdCB7IGEsIGQgfSA9IENVUlZFO1xuICAgICAgICAgICAgY29uc3QgeyBleDogWDEsIGV5OiBZMSwgZXo6IFoxLCBldDogVDEgfSA9IHRoaXM7XG4gICAgICAgICAgICBjb25zdCB7IGV4OiBYMiwgZXk6IFkyLCBlejogWjIsIGV0OiBUMiB9ID0gb3RoZXI7XG4gICAgICAgICAgICAvLyBGYXN0ZXIgYWxnbyBmb3IgYWRkaW5nIDIgRXh0ZW5kZWQgUG9pbnRzIHdoZW4gY3VydmUncyBhPS0xLlxuICAgICAgICAgICAgLy8gaHR0cDovL2h5cGVyZWxsaXB0aWMub3JnL0VGRC9nMXAvYXV0by10d2lzdGVkLWV4dGVuZGVkLTEuaHRtbCNhZGRpdGlvbi1hZGQtMjAwOC1od2NkLTRcbiAgICAgICAgICAgIC8vIENvc3Q6IDhNICsgOGFkZCArIDIqMi5cbiAgICAgICAgICAgIC8vIE5vdGU6IEl0IGRvZXMgbm90IGNoZWNrIHdoZXRoZXIgdGhlIGBvdGhlcmAgcG9pbnQgaXMgdmFsaWQuXG4gICAgICAgICAgICBpZiAoYSA9PT0gQmlnSW50KC0xKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IEEgPSBtb2RQKChZMSAtIFgxKSAqIChZMiArIFgyKSk7XG4gICAgICAgICAgICAgICAgY29uc3QgQiA9IG1vZFAoKFkxICsgWDEpICogKFkyIC0gWDIpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBGID0gbW9kUChCIC0gQSk7XG4gICAgICAgICAgICAgICAgaWYgKEYgPT09IF8wbilcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZG91YmxlKCk7IC8vIFNhbWUgcG9pbnQuIFRlc3RzIHNheSBpdCBkb2Vzbid0IGFmZmVjdCB0aW1pbmdcbiAgICAgICAgICAgICAgICBjb25zdCBDID0gbW9kUChaMSAqIF8ybiAqIFQyKTtcbiAgICAgICAgICAgICAgICBjb25zdCBEID0gbW9kUChUMSAqIF8ybiAqIFoyKTtcbiAgICAgICAgICAgICAgICBjb25zdCBFID0gRCArIEM7XG4gICAgICAgICAgICAgICAgY29uc3QgRyA9IEIgKyBBO1xuICAgICAgICAgICAgICAgIGNvbnN0IEggPSBEIC0gQztcbiAgICAgICAgICAgICAgICBjb25zdCBYMyA9IG1vZFAoRSAqIEYpO1xuICAgICAgICAgICAgICAgIGNvbnN0IFkzID0gbW9kUChHICogSCk7XG4gICAgICAgICAgICAgICAgY29uc3QgVDMgPSBtb2RQKEUgKiBIKTtcbiAgICAgICAgICAgICAgICBjb25zdCBaMyA9IG1vZFAoRiAqIEcpO1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUG9pbnQoWDMsIFkzLCBaMywgVDMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgQSA9IG1vZFAoWDEgKiBYMik7IC8vIEEgPSBYMSpYMlxuICAgICAgICAgICAgY29uc3QgQiA9IG1vZFAoWTEgKiBZMik7IC8vIEIgPSBZMSpZMlxuICAgICAgICAgICAgY29uc3QgQyA9IG1vZFAoVDEgKiBkICogVDIpOyAvLyBDID0gVDEqZCpUMlxuICAgICAgICAgICAgY29uc3QgRCA9IG1vZFAoWjEgKiBaMik7IC8vIEQgPSBaMSpaMlxuICAgICAgICAgICAgY29uc3QgRSA9IG1vZFAoKFgxICsgWTEpICogKFgyICsgWTIpIC0gQSAtIEIpOyAvLyBFID0gKFgxK1kxKSooWDIrWTIpLUEtQlxuICAgICAgICAgICAgY29uc3QgRiA9IEQgLSBDOyAvLyBGID0gRC1DXG4gICAgICAgICAgICBjb25zdCBHID0gRCArIEM7IC8vIEcgPSBEK0NcbiAgICAgICAgICAgIGNvbnN0IEggPSBtb2RQKEIgLSBhICogQSk7IC8vIEggPSBCLWEqQVxuICAgICAgICAgICAgY29uc3QgWDMgPSBtb2RQKEUgKiBGKTsgLy8gWDMgPSBFKkZcbiAgICAgICAgICAgIGNvbnN0IFkzID0gbW9kUChHICogSCk7IC8vIFkzID0gRypIXG4gICAgICAgICAgICBjb25zdCBUMyA9IG1vZFAoRSAqIEgpOyAvLyBUMyA9IEUqSFxuICAgICAgICAgICAgY29uc3QgWjMgPSBtb2RQKEYgKiBHKTsgLy8gWjMgPSBGKkdcbiAgICAgICAgICAgIHJldHVybiBuZXcgUG9pbnQoWDMsIFkzLCBaMywgVDMpO1xuICAgICAgICB9XG4gICAgICAgIHN1YnRyYWN0KG90aGVyKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hZGQob3RoZXIubmVnYXRlKCkpO1xuICAgICAgICB9XG4gICAgICAgIHdOQUYobikge1xuICAgICAgICAgICAgcmV0dXJuIHduYWYud05BRkNhY2hlZCh0aGlzLCBwb2ludFByZWNvbXB1dGVzLCBuLCBQb2ludC5ub3JtYWxpemVaKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBDb25zdGFudC10aW1lIG11bHRpcGxpY2F0aW9uLlxuICAgICAgICBtdWx0aXBseShzY2FsYXIpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgcCwgZiB9ID0gdGhpcy53TkFGKGFzc2VydEluUmFuZ2Uoc2NhbGFyLCBDVVJWRV9PUkRFUikpO1xuICAgICAgICAgICAgcmV0dXJuIFBvaW50Lm5vcm1hbGl6ZVooW3AsIGZdKVswXTtcbiAgICAgICAgfVxuICAgICAgICAvLyBOb24tY29uc3RhbnQtdGltZSBtdWx0aXBsaWNhdGlvbi4gVXNlcyBkb3VibGUtYW5kLWFkZCBhbGdvcml0aG0uXG4gICAgICAgIC8vIEl0J3MgZmFzdGVyLCBidXQgc2hvdWxkIG9ubHkgYmUgdXNlZCB3aGVuIHlvdSBkb24ndCBjYXJlIGFib3V0XG4gICAgICAgIC8vIGFuIGV4cG9zZWQgcHJpdmF0ZSBrZXkgZS5nLiBzaWcgdmVyaWZpY2F0aW9uLlxuICAgICAgICAvLyBEb2VzIE5PVCBhbGxvdyBzY2FsYXJzIGhpZ2hlciB0aGFuIENVUlZFLm4uXG4gICAgICAgIG11bHRpcGx5VW5zYWZlKHNjYWxhcikge1xuICAgICAgICAgICAgbGV0IG4gPSBhc3NlcnRHRTAoc2NhbGFyKTsgLy8gMCA8PSBzY2FsYXIgPCBDVVJWRS5uXG4gICAgICAgICAgICBpZiAobiA9PT0gXzBuKVxuICAgICAgICAgICAgICAgIHJldHVybiBJO1xuICAgICAgICAgICAgaWYgKHRoaXMuZXF1YWxzKEkpIHx8IG4gPT09IF8xbilcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIGlmICh0aGlzLmVxdWFscyhHKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy53TkFGKG4pLnA7XG4gICAgICAgICAgICByZXR1cm4gd25hZi51bnNhZmVMYWRkZXIodGhpcywgbik7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ2hlY2tzIGlmIHBvaW50IGlzIG9mIHNtYWxsIG9yZGVyLlxuICAgICAgICAvLyBJZiB5b3UgYWRkIHNvbWV0aGluZyB0byBzbWFsbCBvcmRlciBwb2ludCwgeW91IHdpbGwgaGF2ZSBcImRpcnR5XCJcbiAgICAgICAgLy8gcG9pbnQgd2l0aCB0b3JzaW9uIGNvbXBvbmVudC5cbiAgICAgICAgLy8gTXVsdGlwbGllcyBwb2ludCBieSBjb2ZhY3RvciBhbmQgY2hlY2tzIGlmIHRoZSByZXN1bHQgaXMgMC5cbiAgICAgICAgaXNTbWFsbE9yZGVyKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubXVsdGlwbHlVbnNhZmUoY29mYWN0b3IpLmlzMCgpO1xuICAgICAgICB9XG4gICAgICAgIC8vIE11bHRpcGxpZXMgcG9pbnQgYnkgY3VydmUgb3JkZXIgYW5kIGNoZWNrcyBpZiB0aGUgcmVzdWx0IGlzIDAuXG4gICAgICAgIC8vIFJldHVybnMgYGZhbHNlYCBpcyB0aGUgcG9pbnQgaXMgZGlydHkuXG4gICAgICAgIGlzVG9yc2lvbkZyZWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gd25hZi51bnNhZmVMYWRkZXIodGhpcywgQ1VSVkVfT1JERVIpLmlzMCgpO1xuICAgICAgICB9XG4gICAgICAgIC8vIENvbnZlcnRzIEV4dGVuZGVkIHBvaW50IHRvIGRlZmF1bHQgKHgsIHkpIGNvb3JkaW5hdGVzLlxuICAgICAgICAvLyBDYW4gYWNjZXB0IHByZWNvbXB1dGVkIFpeLTEgLSBmb3IgZXhhbXBsZSwgZnJvbSBpbnZlcnRCYXRjaC5cbiAgICAgICAgdG9BZmZpbmUoaXopIHtcbiAgICAgICAgICAgIGNvbnN0IHsgZXg6IHgsIGV5OiB5LCBlejogeiB9ID0gdGhpcztcbiAgICAgICAgICAgIGNvbnN0IGlzMCA9IHRoaXMuaXMwKCk7XG4gICAgICAgICAgICBpZiAoaXogPT0gbnVsbClcbiAgICAgICAgICAgICAgICBpeiA9IGlzMCA/IF84biA6IEZwLmludih6KTsgLy8gOCB3YXMgY2hvc2VuIGFyYml0cmFyaWx5XG4gICAgICAgICAgICBjb25zdCBheCA9IG1vZFAoeCAqIGl6KTtcbiAgICAgICAgICAgIGNvbnN0IGF5ID0gbW9kUCh5ICogaXopO1xuICAgICAgICAgICAgY29uc3QgenogPSBtb2RQKHogKiBpeik7XG4gICAgICAgICAgICBpZiAoaXMwKVxuICAgICAgICAgICAgICAgIHJldHVybiB7IHg6IF8wbiwgeTogXzFuIH07XG4gICAgICAgICAgICBpZiAoenogIT09IF8xbilcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludlogd2FzIGludmFsaWQnKTtcbiAgICAgICAgICAgIHJldHVybiB7IHg6IGF4LCB5OiBheSB9O1xuICAgICAgICB9XG4gICAgICAgIGNsZWFyQ29mYWN0b3IoKSB7XG4gICAgICAgICAgICBjb25zdCB7IGg6IGNvZmFjdG9yIH0gPSBDVVJWRTtcbiAgICAgICAgICAgIGlmIChjb2ZhY3RvciA9PT0gXzFuKVxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubXVsdGlwbHlVbnNhZmUoY29mYWN0b3IpO1xuICAgICAgICB9XG4gICAgICAgIC8vIENvbnZlcnRzIGhhc2ggc3RyaW5nIG9yIFVpbnQ4QXJyYXkgdG8gUG9pbnQuXG4gICAgICAgIC8vIFVzZXMgYWxnbyBmcm9tIFJGQzgwMzIgNS4xLjMuXG4gICAgICAgIHN0YXRpYyBmcm9tSGV4KGhleCwgemlwMjE1ID0gZmFsc2UpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgZCwgYSB9ID0gQ1VSVkU7XG4gICAgICAgICAgICBjb25zdCBsZW4gPSBGcC5CWVRFUztcbiAgICAgICAgICAgIGhleCA9IGVuc3VyZUJ5dGVzKCdwb2ludEhleCcsIGhleCwgbGVuKTsgLy8gY29weSBoZXggdG8gYSBuZXcgYXJyYXlcbiAgICAgICAgICAgIGNvbnN0IG5vcm1lZCA9IGhleC5zbGljZSgpOyAvLyBjb3B5IGFnYWluLCB3ZSdsbCBtYW5pcHVsYXRlIGl0XG4gICAgICAgICAgICBjb25zdCBsYXN0Qnl0ZSA9IGhleFtsZW4gLSAxXTsgLy8gc2VsZWN0IGxhc3QgYnl0ZVxuICAgICAgICAgICAgbm9ybWVkW2xlbiAtIDFdID0gbGFzdEJ5dGUgJiB+MHg4MDsgLy8gY2xlYXIgbGFzdCBiaXRcbiAgICAgICAgICAgIGNvbnN0IHkgPSB1dC5ieXRlc1RvTnVtYmVyTEUobm9ybWVkKTtcbiAgICAgICAgICAgIGlmICh5ID09PSBfMG4pIHtcbiAgICAgICAgICAgICAgICAvLyB5PTAgaXMgYWxsb3dlZFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUkZDODAzMiBwcm9oaWJpdHMgPj0gcCwgYnV0IFpJUDIxNSBkb2Vzbid0XG4gICAgICAgICAgICAgICAgaWYgKHppcDIxNSlcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0SW5SYW5nZSh5LCBNQVNLKTsgLy8gemlwMjE1PXRydWUgWzEuLlAtMV0gKDJeMjU1LTE5LTEgZm9yIGVkMjU1MTkpXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICBhc3NlcnRJblJhbmdlKHksIEZwLk9SREVSKTsgLy8gemlwMjE1PWZhbHNlIFsxLi5NQVNLLTFdICgyXjI1Ni0xIGZvciBlZDI1NTE5KVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRWQyNTUxOTogeMKyID0gKHnCsi0xKS8oZHnCsisxKSBtb2QgcC4gRWQ0NDg6IHjCsiA9ICh5wrItMSkvKGR5wrItMSkgbW9kIHAuIEdlbmVyaWMgY2FzZTpcbiAgICAgICAgICAgIC8vIGF4wrIrecKyPTErZHjCsnnCsiA9PiB5wrItMT1keMKyecKyLWF4wrIgPT4gecKyLTE9eMKyKGR5wrItYSkgPT4geMKyPSh5wrItMSkvKGR5wrItYSlcbiAgICAgICAgICAgIGNvbnN0IHkyID0gbW9kUCh5ICogeSk7IC8vIGRlbm9taW5hdG9yIGlzIGFsd2F5cyBub24tMCBtb2QgcC5cbiAgICAgICAgICAgIGNvbnN0IHUgPSBtb2RQKHkyIC0gXzFuKTsgLy8gdSA9IHnCsiAtIDFcbiAgICAgICAgICAgIGNvbnN0IHYgPSBtb2RQKGQgKiB5MiAtIGEpOyAvLyB2ID0gZCB5wrIgKyAxLlxuICAgICAgICAgICAgbGV0IHsgaXNWYWxpZCwgdmFsdWU6IHggfSA9IHV2UmF0aW8odSwgdik7IC8vIOKImih1L3YpXG4gICAgICAgICAgICBpZiAoIWlzVmFsaWQpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQb2ludC5mcm9tSGV4OiBpbnZhbGlkIHkgY29vcmRpbmF0ZScpO1xuICAgICAgICAgICAgY29uc3QgaXNYT2RkID0gKHggJiBfMW4pID09PSBfMW47IC8vIFRoZXJlIGFyZSAyIHNxdWFyZSByb290cy4gVXNlIHhfMCBiaXQgdG8gc2VsZWN0IHByb3BlclxuICAgICAgICAgICAgY29uc3QgaXNMYXN0Qnl0ZU9kZCA9IChsYXN0Qnl0ZSAmIDB4ODApICE9PSAwOyAvLyBpZiB4PTAgYW5kIHhfMCA9IDEsIGZhaWxcbiAgICAgICAgICAgIGlmIChpc0xhc3RCeXRlT2RkICE9PSBpc1hPZGQpXG4gICAgICAgICAgICAgICAgeCA9IG1vZFAoLXgpOyAvLyBpZiB4XzAgIT0geCBtb2QgMiwgc2V0IHggPSBwLXhcbiAgICAgICAgICAgIHJldHVybiBQb2ludC5mcm9tQWZmaW5lKHsgeCwgeSB9KTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZnJvbVByaXZhdGVLZXkocHJpdktleSkge1xuICAgICAgICAgICAgcmV0dXJuIGdldEV4dGVuZGVkUHVibGljS2V5KHByaXZLZXkpLnBvaW50O1xuICAgICAgICB9XG4gICAgICAgIHRvUmF3Qnl0ZXMoKSB7XG4gICAgICAgICAgICBjb25zdCB7IHgsIHkgfSA9IHRoaXMudG9BZmZpbmUoKTtcbiAgICAgICAgICAgIGNvbnN0IGJ5dGVzID0gdXQubnVtYmVyVG9CeXRlc0xFKHksIEZwLkJZVEVTKTsgLy8gZWFjaCB5IGhhcyAyIHggdmFsdWVzICh4LCAteSlcbiAgICAgICAgICAgIGJ5dGVzW2J5dGVzLmxlbmd0aCAtIDFdIHw9IHggJiBfMW4gPyAweDgwIDogMDsgLy8gd2hlbiBjb21wcmVzc2luZywgaXQncyBlbm91Z2ggdG8gc3RvcmUgeVxuICAgICAgICAgICAgcmV0dXJuIGJ5dGVzOyAvLyBhbmQgdXNlIHRoZSBsYXN0IGJ5dGUgdG8gZW5jb2RlIHNpZ24gb2YgeFxuICAgICAgICB9XG4gICAgICAgIHRvSGV4KCkge1xuICAgICAgICAgICAgcmV0dXJuIHV0LmJ5dGVzVG9IZXgodGhpcy50b1Jhd0J5dGVzKCkpOyAvLyBTYW1lIGFzIHRvUmF3Qnl0ZXMsIGJ1dCByZXR1cm5zIHN0cmluZy5cbiAgICAgICAgfVxuICAgIH1cbiAgICBQb2ludC5CQVNFID0gbmV3IFBvaW50KENVUlZFLkd4LCBDVVJWRS5HeSwgXzFuLCBtb2RQKENVUlZFLkd4ICogQ1VSVkUuR3kpKTtcbiAgICBQb2ludC5aRVJPID0gbmV3IFBvaW50KF8wbiwgXzFuLCBfMW4sIF8wbik7IC8vIDAsIDEsIDEsIDBcbiAgICBjb25zdCB7IEJBU0U6IEcsIFpFUk86IEkgfSA9IFBvaW50O1xuICAgIGNvbnN0IHduYWYgPSB3TkFGKFBvaW50LCBuQnl0ZUxlbmd0aCAqIDgpO1xuICAgIGZ1bmN0aW9uIG1vZE4oYSkge1xuICAgICAgICByZXR1cm4gbW9kKGEsIENVUlZFX09SREVSKTtcbiAgICB9XG4gICAgLy8gTGl0dGxlLWVuZGlhbiBTSEE1MTIgd2l0aCBtb2R1bG8gblxuICAgIGZ1bmN0aW9uIG1vZE5fTEUoaGFzaCkge1xuICAgICAgICByZXR1cm4gbW9kTih1dC5ieXRlc1RvTnVtYmVyTEUoaGFzaCkpO1xuICAgIH1cbiAgICAvKiogQ29udmVuaWVuY2UgbWV0aG9kIHRoYXQgY3JlYXRlcyBwdWJsaWMga2V5IGFuZCBvdGhlciBzdHVmZi4gUkZDODAzMiA1LjEuNSAqL1xuICAgIGZ1bmN0aW9uIGdldEV4dGVuZGVkUHVibGljS2V5KGtleSkge1xuICAgICAgICBjb25zdCBsZW4gPSBuQnl0ZUxlbmd0aDtcbiAgICAgICAga2V5ID0gZW5zdXJlQnl0ZXMoJ3ByaXZhdGUga2V5Jywga2V5LCBsZW4pO1xuICAgICAgICAvLyBIYXNoIHByaXZhdGUga2V5IHdpdGggY3VydmUncyBoYXNoIGZ1bmN0aW9uIHRvIHByb2R1Y2UgdW5pZm9ybWluZ2x5IHJhbmRvbSBpbnB1dFxuICAgICAgICAvLyBDaGVjayBieXRlIGxlbmd0aHM6IGVuc3VyZSg2NCwgaChlbnN1cmUoMzIsIGtleSkpKVxuICAgICAgICBjb25zdCBoYXNoZWQgPSBlbnN1cmVCeXRlcygnaGFzaGVkIHByaXZhdGUga2V5JywgY0hhc2goa2V5KSwgMiAqIGxlbik7XG4gICAgICAgIGNvbnN0IGhlYWQgPSBhZGp1c3RTY2FsYXJCeXRlcyhoYXNoZWQuc2xpY2UoMCwgbGVuKSk7IC8vIGNsZWFyIGZpcnN0IGhhbGYgYml0cywgcHJvZHVjZSBGRVxuICAgICAgICBjb25zdCBwcmVmaXggPSBoYXNoZWQuc2xpY2UobGVuLCAyICogbGVuKTsgLy8gc2Vjb25kIGhhbGYgaXMgY2FsbGVkIGtleSBwcmVmaXggKDUuMS42KVxuICAgICAgICBjb25zdCBzY2FsYXIgPSBtb2ROX0xFKGhlYWQpOyAvLyBUaGUgYWN0dWFsIHByaXZhdGUgc2NhbGFyXG4gICAgICAgIGNvbnN0IHBvaW50ID0gRy5tdWx0aXBseShzY2FsYXIpOyAvLyBQb2ludCBvbiBFZHdhcmRzIGN1cnZlIGFrYSBwdWJsaWMga2V5XG4gICAgICAgIGNvbnN0IHBvaW50Qnl0ZXMgPSBwb2ludC50b1Jhd0J5dGVzKCk7IC8vIFVpbnQ4QXJyYXkgcmVwcmVzZW50YXRpb25cbiAgICAgICAgcmV0dXJuIHsgaGVhZCwgcHJlZml4LCBzY2FsYXIsIHBvaW50LCBwb2ludEJ5dGVzIH07XG4gICAgfVxuICAgIC8vIENhbGN1bGF0ZXMgRWREU0EgcHViIGtleS4gUkZDODAzMiA1LjEuNS4gUHJpdmtleSBpcyBoYXNoZWQuIFVzZSBmaXJzdCBoYWxmIHdpdGggMyBiaXRzIGNsZWFyZWRcbiAgICBmdW5jdGlvbiBnZXRQdWJsaWNLZXkocHJpdktleSkge1xuICAgICAgICByZXR1cm4gZ2V0RXh0ZW5kZWRQdWJsaWNLZXkocHJpdktleSkucG9pbnRCeXRlcztcbiAgICB9XG4gICAgLy8gaW50KCdMRScsIFNIQTUxMihkb20yKEYsIEMpIHx8IG1zZ3MpKSBtb2QgTlxuICAgIGZ1bmN0aW9uIGhhc2hEb21haW5Ub1NjYWxhcihjb250ZXh0ID0gbmV3IFVpbnQ4QXJyYXkoKSwgLi4ubXNncykge1xuICAgICAgICBjb25zdCBtc2cgPSB1dC5jb25jYXRCeXRlcyguLi5tc2dzKTtcbiAgICAgICAgcmV0dXJuIG1vZE5fTEUoY0hhc2goZG9tYWluKG1zZywgZW5zdXJlQnl0ZXMoJ2NvbnRleHQnLCBjb250ZXh0KSwgISFwcmVoYXNoKSkpO1xuICAgIH1cbiAgICAvKiogU2lnbnMgbWVzc2FnZSB3aXRoIHByaXZhdGVLZXkuIFJGQzgwMzIgNS4xLjYgKi9cbiAgICBmdW5jdGlvbiBzaWduKG1zZywgcHJpdktleSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIG1zZyA9IGVuc3VyZUJ5dGVzKCdtZXNzYWdlJywgbXNnKTtcbiAgICAgICAgaWYgKHByZWhhc2gpXG4gICAgICAgICAgICBtc2cgPSBwcmVoYXNoKG1zZyk7IC8vIGZvciBlZDI1NTE5cGggZXRjLlxuICAgICAgICBjb25zdCB7IHByZWZpeCwgc2NhbGFyLCBwb2ludEJ5dGVzIH0gPSBnZXRFeHRlbmRlZFB1YmxpY0tleShwcml2S2V5KTtcbiAgICAgICAgY29uc3QgciA9IGhhc2hEb21haW5Ub1NjYWxhcihvcHRpb25zLmNvbnRleHQsIHByZWZpeCwgbXNnKTsgLy8gciA9IGRvbTIoRiwgQykgfHwgcHJlZml4IHx8IFBIKE0pXG4gICAgICAgIGNvbnN0IFIgPSBHLm11bHRpcGx5KHIpLnRvUmF3Qnl0ZXMoKTsgLy8gUiA9IHJHXG4gICAgICAgIGNvbnN0IGsgPSBoYXNoRG9tYWluVG9TY2FsYXIob3B0aW9ucy5jb250ZXh0LCBSLCBwb2ludEJ5dGVzLCBtc2cpOyAvLyBSIHx8IEEgfHwgUEgoTSlcbiAgICAgICAgY29uc3QgcyA9IG1vZE4ociArIGsgKiBzY2FsYXIpOyAvLyBTID0gKHIgKyBrICogcykgbW9kIExcbiAgICAgICAgYXNzZXJ0R0UwKHMpOyAvLyAwIDw9IHMgPCBsXG4gICAgICAgIGNvbnN0IHJlcyA9IHV0LmNvbmNhdEJ5dGVzKFIsIHV0Lm51bWJlclRvQnl0ZXNMRShzLCBGcC5CWVRFUykpO1xuICAgICAgICByZXR1cm4gZW5zdXJlQnl0ZXMoJ3Jlc3VsdCcsIHJlcywgbkJ5dGVMZW5ndGggKiAyKTsgLy8gNjQtYnl0ZSBzaWduYXR1cmVcbiAgICB9XG4gICAgY29uc3QgdmVyaWZ5T3B0cyA9IFZFUklGWV9ERUZBVUxUO1xuICAgIGZ1bmN0aW9uIHZlcmlmeShzaWcsIG1zZywgcHVibGljS2V5LCBvcHRpb25zID0gdmVyaWZ5T3B0cykge1xuICAgICAgICBjb25zdCB7IGNvbnRleHQsIHppcDIxNSB9ID0gb3B0aW9ucztcbiAgICAgICAgY29uc3QgbGVuID0gRnAuQllURVM7IC8vIFZlcmlmaWVzIEVkRFNBIHNpZ25hdHVyZSBhZ2FpbnN0IG1lc3NhZ2UgYW5kIHB1YmxpYyBrZXkuIFJGQzgwMzIgNS4xLjcuXG4gICAgICAgIHNpZyA9IGVuc3VyZUJ5dGVzKCdzaWduYXR1cmUnLCBzaWcsIDIgKiBsZW4pOyAvLyBBbiBleHRlbmRlZCBncm91cCBlcXVhdGlvbiBpcyBjaGVja2VkLlxuICAgICAgICBtc2cgPSBlbnN1cmVCeXRlcygnbWVzc2FnZScsIG1zZyk7XG4gICAgICAgIGlmIChwcmVoYXNoKVxuICAgICAgICAgICAgbXNnID0gcHJlaGFzaChtc2cpOyAvLyBmb3IgZWQyNTUxOXBoLCBldGNcbiAgICAgICAgY29uc3QgcyA9IHV0LmJ5dGVzVG9OdW1iZXJMRShzaWcuc2xpY2UobGVuLCAyICogbGVuKSk7XG4gICAgICAgIC8vIHppcDIxNTogdHJ1ZSBpcyBnb29kIGZvciBjb25zZW5zdXMtY3JpdGljYWwgYXBwcyBhbmQgYWxsb3dzIHBvaW50cyA8IDJeMjU2XG4gICAgICAgIC8vIHppcDIxNTogZmFsc2UgZm9sbG93cyBSRkM4MDMyIC8gTklTVDE4Ni01IGFuZCByZXN0cmljdHMgcG9pbnRzIHRvIENVUlZFLnBcbiAgICAgICAgbGV0IEEsIFIsIFNCO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgQSA9IFBvaW50LmZyb21IZXgocHVibGljS2V5LCB6aXAyMTUpO1xuICAgICAgICAgICAgUiA9IFBvaW50LmZyb21IZXgoc2lnLnNsaWNlKDAsIGxlbiksIHppcDIxNSk7XG4gICAgICAgICAgICBTQiA9IEcubXVsdGlwbHlVbnNhZmUocyk7IC8vIDAgPD0gcyA8IGwgaXMgZG9uZSBpbnNpZGVcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBrID0gaGFzaERvbWFpblRvU2NhbGFyKGNvbnRleHQsIFIudG9SYXdCeXRlcygpLCBBLnRvUmF3Qnl0ZXMoKSwgbXNnKTtcbiAgICAgICAgY29uc3QgUmtBID0gUi5hZGQoQS5tdWx0aXBseVVuc2FmZShrKSk7XG4gICAgICAgIC8vIFs4XVtTXUIgPSBbOF1SICsgWzhdW2tdQSdcbiAgICAgICAgcmV0dXJuIFJrQS5zdWJ0cmFjdChTQikuY2xlYXJDb2ZhY3RvcigpLmVxdWFscyhQb2ludC5aRVJPKTtcbiAgICB9XG4gICAgRy5fc2V0V2luZG93U2l6ZSg4KTsgLy8gRW5hYmxlIHByZWNvbXB1dGVzLiBTbG93cyBkb3duIGZpcnN0IHB1YmxpY0tleSBjb21wdXRhdGlvbiBieSAyMG1zLlxuICAgIGNvbnN0IHV0aWxzID0ge1xuICAgICAgICBnZXRFeHRlbmRlZFB1YmxpY0tleSxcbiAgICAgICAgLy8gZWQyNTUxOSBwcml2YXRlIGtleXMgYXJlIHVuaWZvcm0gMzJiLiBObyBuZWVkIHRvIGNoZWNrIGZvciBtb2R1bG8gYmlhcywgbGlrZSBpbiBzZWNwMjU2azEuXG4gICAgICAgIHJhbmRvbVByaXZhdGVLZXk6ICgpID0+IHJhbmRvbUJ5dGVzKEZwLkJZVEVTKSxcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdlJ3JlIGRvaW5nIHNjYWxhciBtdWx0aXBsaWNhdGlvbiAodXNlZCBpbiBnZXRQdWJsaWNLZXkgZXRjKSB3aXRoIHByZWNvbXB1dGVkIEJBU0VfUE9JTlRcbiAgICAgICAgICogdmFsdWVzLiBUaGlzIHNsb3dzIGRvd24gZmlyc3QgZ2V0UHVibGljS2V5KCkgYnkgbWlsbGlzZWNvbmRzIChzZWUgU3BlZWQgc2VjdGlvbiksXG4gICAgICAgICAqIGJ1dCBhbGxvd3MgdG8gc3BlZWQtdXAgc3Vic2VxdWVudCBnZXRQdWJsaWNLZXkoKSBjYWxscyB1cCB0byAyMHguXG4gICAgICAgICAqIEBwYXJhbSB3aW5kb3dTaXplIDIsIDQsIDgsIDE2XG4gICAgICAgICAqL1xuICAgICAgICBwcmVjb21wdXRlKHdpbmRvd1NpemUgPSA4LCBwb2ludCA9IFBvaW50LkJBU0UpIHtcbiAgICAgICAgICAgIHBvaW50Ll9zZXRXaW5kb3dTaXplKHdpbmRvd1NpemUpO1xuICAgICAgICAgICAgcG9pbnQubXVsdGlwbHkoQmlnSW50KDMpKTtcbiAgICAgICAgICAgIHJldHVybiBwb2ludDtcbiAgICAgICAgfSxcbiAgICB9O1xuICAgIHJldHVybiB7XG4gICAgICAgIENVUlZFLFxuICAgICAgICBnZXRQdWJsaWNLZXksXG4gICAgICAgIHNpZ24sXG4gICAgICAgIHZlcmlmeSxcbiAgICAgICAgRXh0ZW5kZWRQb2ludDogUG9pbnQsXG4gICAgICAgIHV0aWxzLFxuICAgIH07XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1lZHdhcmRzLmpzLm1hcCJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/@noble/curves/esm/abstract/edwards.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/@noble/curves/esm/abstract/hash-to-curve.js":
+/*!******************************************************************!*\
+  !*** ./node_modules/@noble/curves/esm/abstract/hash-to-curve.js ***!
+  \******************************************************************/
+/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   createHasher: () => (/* binding */ createHasher),\n/* harmony export */   expand_message_xmd: () => (/* binding */ expand_message_xmd),\n/* harmony export */   expand_message_xof: () => (/* binding */ expand_message_xof),\n/* harmony export */   hash_to_field: () => (/* binding */ hash_to_field),\n/* harmony export */   isogenyMap: () => (/* binding */ isogenyMap)\n/* harmony export */ });\n/* harmony import */ var _modular_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./modular.js */ \"./node_modules/@noble/curves/esm/abstract/modular.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils.js */ \"./node_modules/@noble/curves/esm/abstract/utils.js\");\n\n\nfunction validateDST(dst) {\n    if (dst instanceof Uint8Array)\n        return dst;\n    if (typeof dst === 'string')\n        return (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.utf8ToBytes)(dst);\n    throw new Error('DST must be Uint8Array or string');\n}\n// Octet Stream to Integer. \"spec\" implementation of os2ip is 2.5x slower vs bytesToNumberBE.\nconst os2ip = _utils_js__WEBPACK_IMPORTED_MODULE_1__.bytesToNumberBE;\n// Integer to Octet Stream (numberToBytesBE)\nfunction i2osp(value, length) {\n    if (value < 0 || value >= 1 << (8 * length)) {\n        throw new Error(`bad I2OSP call: value=${value} length=${length}`);\n    }\n    const res = Array.from({ length }).fill(0);\n    for (let i = length - 1; i >= 0; i--) {\n        res[i] = value & 0xff;\n        value >>>= 8;\n    }\n    return new Uint8Array(res);\n}\nfunction strxor(a, b) {\n    const arr = new Uint8Array(a.length);\n    for (let i = 0; i < a.length; i++) {\n        arr[i] = a[i] ^ b[i];\n    }\n    return arr;\n}\nfunction isBytes(item) {\n    if (!(item instanceof Uint8Array))\n        throw new Error('Uint8Array expected');\n}\nfunction isNum(item) {\n    if (!Number.isSafeInteger(item))\n        throw new Error('number expected');\n}\n// Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits\n// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.4.1\nfunction expand_message_xmd(msg, DST, lenInBytes, H) {\n    isBytes(msg);\n    isBytes(DST);\n    isNum(lenInBytes);\n    // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3\n    if (DST.length > 255)\n        DST = H((0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.concatBytes)((0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.utf8ToBytes)('H2C-OVERSIZE-DST-'), DST));\n    const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H;\n    const ell = Math.ceil(lenInBytes / b_in_bytes);\n    if (ell > 255)\n        throw new Error('Invalid xmd length');\n    const DST_prime = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.concatBytes)(DST, i2osp(DST.length, 1));\n    const Z_pad = i2osp(0, r_in_bytes);\n    const l_i_b_str = i2osp(lenInBytes, 2); // len_in_bytes_str\n    const b = new Array(ell);\n    const b_0 = H((0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.concatBytes)(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime));\n    b[0] = H((0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.concatBytes)(b_0, i2osp(1, 1), DST_prime));\n    for (let i = 1; i <= ell; i++) {\n        const args = [strxor(b_0, b[i - 1]), i2osp(i + 1, 1), DST_prime];\n        b[i] = H((0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.concatBytes)(...args));\n    }\n    const pseudo_random_bytes = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.concatBytes)(...b);\n    return pseudo_random_bytes.slice(0, lenInBytes);\n}\nfunction expand_message_xof(msg, DST, lenInBytes, k, H) {\n    isBytes(msg);\n    isBytes(DST);\n    isNum(lenInBytes);\n    // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3\n    // DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));\n    if (DST.length > 255) {\n        const dkLen = Math.ceil((2 * k) / 8);\n        DST = H.create({ dkLen }).update((0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.utf8ToBytes)('H2C-OVERSIZE-DST-')).update(DST).digest();\n    }\n    if (lenInBytes > 65535 || DST.length > 255)\n        throw new Error('expand_message_xof: invalid lenInBytes');\n    return (H.create({ dkLen: lenInBytes })\n        .update(msg)\n        .update(i2osp(lenInBytes, 2))\n        // 2. DST_prime = DST || I2OSP(len(DST), 1)\n        .update(DST)\n        .update(i2osp(DST.length, 1))\n        .digest());\n}\n/**\n * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F\n * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3\n * @param msg a byte string containing the message to hash\n * @param count the number of elements of F to output\n * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above\n * @returns [u_0, ..., u_(count - 1)], a list of field elements.\n */\nfunction hash_to_field(msg, count, options) {\n    (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.validateObject)(options, {\n        DST: 'string',\n        p: 'bigint',\n        m: 'isSafeInteger',\n        k: 'isSafeInteger',\n        hash: 'hash',\n    });\n    const { p, k, m, hash, expand, DST: _DST } = options;\n    isBytes(msg);\n    isNum(count);\n    const DST = validateDST(_DST);\n    const log2p = p.toString(2).length;\n    const L = Math.ceil((log2p + k) / 8); // section 5.1 of ietf draft link above\n    const len_in_bytes = count * m * L;\n    let prb; // pseudo_random_bytes\n    if (expand === 'xmd') {\n        prb = expand_message_xmd(msg, DST, len_in_bytes, hash);\n    }\n    else if (expand === 'xof') {\n        prb = expand_message_xof(msg, DST, len_in_bytes, k, hash);\n    }\n    else if (expand === '_internal_pass') {\n        // for internal tests only\n        prb = msg;\n    }\n    else {\n        throw new Error('expand must be \"xmd\" or \"xof\"');\n    }\n    const u = new Array(count);\n    for (let i = 0; i < count; i++) {\n        const e = new Array(m);\n        for (let j = 0; j < m; j++) {\n            const elm_offset = L * (j + i * m);\n            const tv = prb.subarray(elm_offset, elm_offset + L);\n            e[j] = (0,_modular_js__WEBPACK_IMPORTED_MODULE_0__.mod)(os2ip(tv), p);\n        }\n        u[i] = e;\n    }\n    return u;\n}\nfunction isogenyMap(field, map) {\n    // Make same order as in spec\n    const COEFF = map.map((i) => Array.from(i).reverse());\n    return (x, y) => {\n        const [xNum, xDen, yNum, yDen] = COEFF.map((val) => val.reduce((acc, i) => field.add(field.mul(acc, x), i)));\n        x = field.div(xNum, xDen); // xNum / xDen\n        y = field.mul(y, field.div(yNum, yDen)); // y * (yNum / yDev)\n        return { x, y };\n    };\n}\nfunction createHasher(Point, mapToCurve, def) {\n    if (typeof mapToCurve !== 'function')\n        throw new Error('mapToCurve() must be defined');\n    return {\n        // Encodes byte string to elliptic curve\n        // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3\n        hashToCurve(msg, options) {\n            const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options });\n            const u0 = Point.fromAffine(mapToCurve(u[0]));\n            const u1 = Point.fromAffine(mapToCurve(u[1]));\n            const P = u0.add(u1).clearCofactor();\n            P.assertValidity();\n            return P;\n        },\n        // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-3\n        encodeToCurve(msg, options) {\n            const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options });\n            const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor();\n            P.assertValidity();\n            return P;\n        },\n    };\n}\n//# sourceMappingURL=hash-to-curve.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQG5vYmxlL2N1cnZlcy9lc20vYWJzdHJhY3QvaGFzaC10by1jdXJ2ZS5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9Abm9ibGUvY3VydmVzL2VzbS9hYnN0cmFjdC9oYXNoLXRvLWN1cnZlLmpzPzQ2ZDAiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgbW9kIH0gZnJvbSAnLi9tb2R1bGFyLmpzJztcbmltcG9ydCB7IGJ5dGVzVG9OdW1iZXJCRSwgY29uY2F0Qnl0ZXMsIHV0ZjhUb0J5dGVzLCB2YWxpZGF0ZU9iamVjdCB9IGZyb20gJy4vdXRpbHMuanMnO1xuZnVuY3Rpb24gdmFsaWRhdGVEU1QoZHN0KSB7XG4gICAgaWYgKGRzdCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpXG4gICAgICAgIHJldHVybiBkc3Q7XG4gICAgaWYgKHR5cGVvZiBkc3QgPT09ICdzdHJpbmcnKVxuICAgICAgICByZXR1cm4gdXRmOFRvQnl0ZXMoZHN0KTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0RTVCBtdXN0IGJlIFVpbnQ4QXJyYXkgb3Igc3RyaW5nJyk7XG59XG4vLyBPY3RldCBTdHJlYW0gdG8gSW50ZWdlci4gXCJzcGVjXCIgaW1wbGVtZW50YXRpb24gb2Ygb3MyaXAgaXMgMi41eCBzbG93ZXIgdnMgYnl0ZXNUb051bWJlckJFLlxuY29uc3Qgb3MyaXAgPSBieXRlc1RvTnVtYmVyQkU7XG4vLyBJbnRlZ2VyIHRvIE9jdGV0IFN0cmVhbSAobnVtYmVyVG9CeXRlc0JFKVxuZnVuY3Rpb24gaTJvc3AodmFsdWUsIGxlbmd0aCkge1xuICAgIGlmICh2YWx1ZSA8IDAgfHwgdmFsdWUgPj0gMSA8PCAoOCAqIGxlbmd0aCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBiYWQgSTJPU1AgY2FsbDogdmFsdWU9JHt2YWx1ZX0gbGVuZ3RoPSR7bGVuZ3RofWApO1xuICAgIH1cbiAgICBjb25zdCByZXMgPSBBcnJheS5mcm9tKHsgbGVuZ3RoIH0pLmZpbGwoMCk7XG4gICAgZm9yIChsZXQgaSA9IGxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIHJlc1tpXSA9IHZhbHVlICYgMHhmZjtcbiAgICAgICAgdmFsdWUgPj4+PSA4O1xuICAgIH1cbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkocmVzKTtcbn1cbmZ1bmN0aW9uIHN0cnhvcihhLCBiKSB7XG4gICAgY29uc3QgYXJyID0gbmV3IFVpbnQ4QXJyYXkoYS5sZW5ndGgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgICBhcnJbaV0gPSBhW2ldIF4gYltpXTtcbiAgICB9XG4gICAgcmV0dXJuIGFycjtcbn1cbmZ1bmN0aW9uIGlzQnl0ZXMoaXRlbSkge1xuICAgIGlmICghKGl0ZW0gaW5zdGFuY2VvZiBVaW50OEFycmF5KSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVaW50OEFycmF5IGV4cGVjdGVkJyk7XG59XG5mdW5jdGlvbiBpc051bShpdGVtKSB7XG4gICAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcihpdGVtKSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdudW1iZXIgZXhwZWN0ZWQnKTtcbn1cbi8vIFByb2R1Y2VzIGEgdW5pZm9ybWx5IHJhbmRvbSBieXRlIHN0cmluZyB1c2luZyBhIGNyeXB0b2dyYXBoaWMgaGFzaCBmdW5jdGlvbiBIIHRoYXQgb3V0cHV0cyBiIGJpdHNcbi8vIGh0dHBzOi8vZGF0YXRyYWNrZXIuaWV0Zi5vcmcvZG9jL2h0bWwvZHJhZnQtaXJ0Zi1jZnJnLWhhc2gtdG8tY3VydmUtMTEjc2VjdGlvbi01LjQuMVxuZXhwb3J0IGZ1bmN0aW9uIGV4cGFuZF9tZXNzYWdlX3htZChtc2csIERTVCwgbGVuSW5CeXRlcywgSCkge1xuICAgIGlzQnl0ZXMobXNnKTtcbiAgICBpc0J5dGVzKERTVCk7XG4gICAgaXNOdW0obGVuSW5CeXRlcyk7XG4gICAgLy8gaHR0cHM6Ly9kYXRhdHJhY2tlci5pZXRmLm9yZy9kb2MvaHRtbC9kcmFmdC1pcnRmLWNmcmctaGFzaC10by1jdXJ2ZS0xNiNzZWN0aW9uLTUuMy4zXG4gICAgaWYgKERTVC5sZW5ndGggPiAyNTUpXG4gICAgICAgIERTVCA9IEgoY29uY2F0Qnl0ZXModXRmOFRvQnl0ZXMoJ0gyQy1PVkVSU0laRS1EU1QtJyksIERTVCkpO1xuICAgIGNvbnN0IHsgb3V0cHV0TGVuOiBiX2luX2J5dGVzLCBibG9ja0xlbjogcl9pbl9ieXRlcyB9ID0gSDtcbiAgICBjb25zdCBlbGwgPSBNYXRoLmNlaWwobGVuSW5CeXRlcyAvIGJfaW5fYnl0ZXMpO1xuICAgIGlmIChlbGwgPiAyNTUpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB4bWQgbGVuZ3RoJyk7XG4gICAgY29uc3QgRFNUX3ByaW1lID0gY29uY2F0Qnl0ZXMoRFNULCBpMm9zcChEU1QubGVuZ3RoLCAxKSk7XG4gICAgY29uc3QgWl9wYWQgPSBpMm9zcCgwLCByX2luX2J5dGVzKTtcbiAgICBjb25zdCBsX2lfYl9zdHIgPSBpMm9zcChsZW5JbkJ5dGVzLCAyKTsgLy8gbGVuX2luX2J5dGVzX3N0clxuICAgIGNvbnN0IGIgPSBuZXcgQXJyYXkoZWxsKTtcbiAgICBjb25zdCBiXzAgPSBIKGNvbmNhdEJ5dGVzKFpfcGFkLCBtc2csIGxfaV9iX3N0ciwgaTJvc3AoMCwgMSksIERTVF9wcmltZSkpO1xuICAgIGJbMF0gPSBIKGNvbmNhdEJ5dGVzKGJfMCwgaTJvc3AoMSwgMSksIERTVF9wcmltZSkpO1xuICAgIGZvciAobGV0IGkgPSAxOyBpIDw9IGVsbDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGFyZ3MgPSBbc3RyeG9yKGJfMCwgYltpIC0gMV0pLCBpMm9zcChpICsgMSwgMSksIERTVF9wcmltZV07XG4gICAgICAgIGJbaV0gPSBIKGNvbmNhdEJ5dGVzKC4uLmFyZ3MpKTtcbiAgICB9XG4gICAgY29uc3QgcHNldWRvX3JhbmRvbV9ieXRlcyA9IGNvbmNhdEJ5dGVzKC4uLmIpO1xuICAgIHJldHVybiBwc2V1ZG9fcmFuZG9tX2J5dGVzLnNsaWNlKDAsIGxlbkluQnl0ZXMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGV4cGFuZF9tZXNzYWdlX3hvZihtc2csIERTVCwgbGVuSW5CeXRlcywgaywgSCkge1xuICAgIGlzQnl0ZXMobXNnKTtcbiAgICBpc0J5dGVzKERTVCk7XG4gICAgaXNOdW0obGVuSW5CeXRlcyk7XG4gICAgLy8gaHR0cHM6Ly9kYXRhdHJhY2tlci5pZXRmLm9yZy9kb2MvaHRtbC9kcmFmdC1pcnRmLWNmcmctaGFzaC10by1jdXJ2ZS0xNiNzZWN0aW9uLTUuMy4zXG4gICAgLy8gRFNUID0gSCgnSDJDLU9WRVJTSVpFLURTVC0nIHx8IGFfdmVyeV9sb25nX0RTVCwgTWF0aC5jZWlsKChsZW5JbkJ5dGVzICogaykgLyA4KSk7XG4gICAgaWYgKERTVC5sZW5ndGggPiAyNTUpIHtcbiAgICAgICAgY29uc3QgZGtMZW4gPSBNYXRoLmNlaWwoKDIgKiBrKSAvIDgpO1xuICAgICAgICBEU1QgPSBILmNyZWF0ZSh7IGRrTGVuIH0pLnVwZGF0ZSh1dGY4VG9CeXRlcygnSDJDLU9WRVJTSVpFLURTVC0nKSkudXBkYXRlKERTVCkuZGlnZXN0KCk7XG4gICAgfVxuICAgIGlmIChsZW5JbkJ5dGVzID4gNjU1MzUgfHwgRFNULmxlbmd0aCA+IDI1NSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdleHBhbmRfbWVzc2FnZV94b2Y6IGludmFsaWQgbGVuSW5CeXRlcycpO1xuICAgIHJldHVybiAoSC5jcmVhdGUoeyBka0xlbjogbGVuSW5CeXRlcyB9KVxuICAgICAgICAudXBkYXRlKG1zZylcbiAgICAgICAgLnVwZGF0ZShpMm9zcChsZW5JbkJ5dGVzLCAyKSlcbiAgICAgICAgLy8gMi4gRFNUX3ByaW1lID0gRFNUIHx8IEkyT1NQKGxlbihEU1QpLCAxKVxuICAgICAgICAudXBkYXRlKERTVClcbiAgICAgICAgLnVwZGF0ZShpMm9zcChEU1QubGVuZ3RoLCAxKSlcbiAgICAgICAgLmRpZ2VzdCgpKTtcbn1cbi8qKlxuICogSGFzaGVzIGFyYml0cmFyeS1sZW5ndGggYnl0ZSBzdHJpbmdzIHRvIGEgbGlzdCBvZiBvbmUgb3IgbW9yZSBlbGVtZW50cyBvZiBhIGZpbml0ZSBmaWVsZCBGXG4gKiBodHRwczovL2RhdGF0cmFja2VyLmlldGYub3JnL2RvYy9odG1sL2RyYWZ0LWlydGYtY2ZyZy1oYXNoLXRvLWN1cnZlLTExI3NlY3Rpb24tNS4zXG4gKiBAcGFyYW0gbXNnIGEgYnl0ZSBzdHJpbmcgY29udGFpbmluZyB0aGUgbWVzc2FnZSB0byBoYXNoXG4gKiBAcGFyYW0gY291bnQgdGhlIG51bWJlciBvZiBlbGVtZW50cyBvZiBGIHRvIG91dHB1dFxuICogQHBhcmFtIG9wdGlvbnMgYHtEU1Q6IHN0cmluZywgcDogYmlnaW50LCBtOiBudW1iZXIsIGs6IG51bWJlciwgZXhwYW5kOiAneG1kJyB8ICd4b2YnLCBoYXNoOiBIfWAsIHNlZSBhYm92ZVxuICogQHJldHVybnMgW3VfMCwgLi4uLCB1Xyhjb3VudCAtIDEpXSwgYSBsaXN0IG9mIGZpZWxkIGVsZW1lbnRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzaF90b19maWVsZChtc2csIGNvdW50LCBvcHRpb25zKSB7XG4gICAgdmFsaWRhdGVPYmplY3Qob3B0aW9ucywge1xuICAgICAgICBEU1Q6ICdzdHJpbmcnLFxuICAgICAgICBwOiAnYmlnaW50JyxcbiAgICAgICAgbTogJ2lzU2FmZUludGVnZXInLFxuICAgICAgICBrOiAnaXNTYWZlSW50ZWdlcicsXG4gICAgICAgIGhhc2g6ICdoYXNoJyxcbiAgICB9KTtcbiAgICBjb25zdCB7IHAsIGssIG0sIGhhc2gsIGV4cGFuZCwgRFNUOiBfRFNUIH0gPSBvcHRpb25zO1xuICAgIGlzQnl0ZXMobXNnKTtcbiAgICBpc051bShjb3VudCk7XG4gICAgY29uc3QgRFNUID0gdmFsaWRhdGVEU1QoX0RTVCk7XG4gICAgY29uc3QgbG9nMnAgPSBwLnRvU3RyaW5nKDIpLmxlbmd0aDtcbiAgICBjb25zdCBMID0gTWF0aC5jZWlsKChsb2cycCArIGspIC8gOCk7IC8vIHNlY3Rpb24gNS4xIG9mIGlldGYgZHJhZnQgbGluayBhYm92ZVxuICAgIGNvbnN0IGxlbl9pbl9ieXRlcyA9IGNvdW50ICogbSAqIEw7XG4gICAgbGV0IHByYjsgLy8gcHNldWRvX3JhbmRvbV9ieXRlc1xuICAgIGlmIChleHBhbmQgPT09ICd4bWQnKSB7XG4gICAgICAgIHByYiA9IGV4cGFuZF9tZXNzYWdlX3htZChtc2csIERTVCwgbGVuX2luX2J5dGVzLCBoYXNoKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoZXhwYW5kID09PSAneG9mJykge1xuICAgICAgICBwcmIgPSBleHBhbmRfbWVzc2FnZV94b2YobXNnLCBEU1QsIGxlbl9pbl9ieXRlcywgaywgaGFzaCk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGV4cGFuZCA9PT0gJ19pbnRlcm5hbF9wYXNzJykge1xuICAgICAgICAvLyBmb3IgaW50ZXJuYWwgdGVzdHMgb25seVxuICAgICAgICBwcmIgPSBtc2c7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2V4cGFuZCBtdXN0IGJlIFwieG1kXCIgb3IgXCJ4b2ZcIicpO1xuICAgIH1cbiAgICBjb25zdCB1ID0gbmV3IEFycmF5KGNvdW50KTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgY29uc3QgZSA9IG5ldyBBcnJheShtKTtcbiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBtOyBqKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGVsbV9vZmZzZXQgPSBMICogKGogKyBpICogbSk7XG4gICAgICAgICAgICBjb25zdCB0diA9IHByYi5zdWJhcnJheShlbG1fb2Zmc2V0LCBlbG1fb2Zmc2V0ICsgTCk7XG4gICAgICAgICAgICBlW2pdID0gbW9kKG9zMmlwKHR2KSwgcCk7XG4gICAgICAgIH1cbiAgICAgICAgdVtpXSA9IGU7XG4gICAgfVxuICAgIHJldHVybiB1O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGlzb2dlbnlNYXAoZmllbGQsIG1hcCkge1xuICAgIC8vIE1ha2Ugc2FtZSBvcmRlciBhcyBpbiBzcGVjXG4gICAgY29uc3QgQ09FRkYgPSBtYXAubWFwKChpKSA9PiBBcnJheS5mcm9tKGkpLnJldmVyc2UoKSk7XG4gICAgcmV0dXJuICh4LCB5KSA9PiB7XG4gICAgICAgIGNvbnN0IFt4TnVtLCB4RGVuLCB5TnVtLCB5RGVuXSA9IENPRUZGLm1hcCgodmFsKSA9PiB2YWwucmVkdWNlKChhY2MsIGkpID0+IGZpZWxkLmFkZChmaWVsZC5tdWwoYWNjLCB4KSwgaSkpKTtcbiAgICAgICAgeCA9IGZpZWxkLmRpdih4TnVtLCB4RGVuKTsgLy8geE51bSAvIHhEZW5cbiAgICAgICAgeSA9IGZpZWxkLm11bCh5LCBmaWVsZC5kaXYoeU51bSwgeURlbikpOyAvLyB5ICogKHlOdW0gLyB5RGV2KVxuICAgICAgICByZXR1cm4geyB4LCB5IH07XG4gICAgfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVIYXNoZXIoUG9pbnQsIG1hcFRvQ3VydmUsIGRlZikge1xuICAgIGlmICh0eXBlb2YgbWFwVG9DdXJ2ZSAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtYXBUb0N1cnZlKCkgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgLy8gRW5jb2RlcyBieXRlIHN0cmluZyB0byBlbGxpcHRpYyBjdXJ2ZVxuICAgICAgICAvLyBodHRwczovL2RhdGF0cmFja2VyLmlldGYub3JnL2RvYy9odG1sL2RyYWZ0LWlydGYtY2ZyZy1oYXNoLXRvLWN1cnZlLTE2I3NlY3Rpb24tM1xuICAgICAgICBoYXNoVG9DdXJ2ZShtc2csIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGNvbnN0IHUgPSBoYXNoX3RvX2ZpZWxkKG1zZywgMiwgeyAuLi5kZWYsIERTVDogZGVmLkRTVCwgLi4ub3B0aW9ucyB9KTtcbiAgICAgICAgICAgIGNvbnN0IHUwID0gUG9pbnQuZnJvbUFmZmluZShtYXBUb0N1cnZlKHVbMF0pKTtcbiAgICAgICAgICAgIGNvbnN0IHUxID0gUG9pbnQuZnJvbUFmZmluZShtYXBUb0N1cnZlKHVbMV0pKTtcbiAgICAgICAgICAgIGNvbnN0IFAgPSB1MC5hZGQodTEpLmNsZWFyQ29mYWN0b3IoKTtcbiAgICAgICAgICAgIFAuYXNzZXJ0VmFsaWRpdHkoKTtcbiAgICAgICAgICAgIHJldHVybiBQO1xuICAgICAgICB9LFxuICAgICAgICAvLyBodHRwczovL2RhdGF0cmFja2VyLmlldGYub3JnL2RvYy9odG1sL2RyYWZ0LWlydGYtY2ZyZy1oYXNoLXRvLWN1cnZlLTE2I3NlY3Rpb24tM1xuICAgICAgICBlbmNvZGVUb0N1cnZlKG1zZywgb3B0aW9ucykge1xuICAgICAgICAgICAgY29uc3QgdSA9IGhhc2hfdG9fZmllbGQobXNnLCAxLCB7IC4uLmRlZiwgRFNUOiBkZWYuZW5jb2RlRFNULCAuLi5vcHRpb25zIH0pO1xuICAgICAgICAgICAgY29uc3QgUCA9IFBvaW50LmZyb21BZmZpbmUobWFwVG9DdXJ2ZSh1WzBdKSkuY2xlYXJDb2ZhY3RvcigpO1xuICAgICAgICAgICAgUC5hc3NlcnRWYWxpZGl0eSgpO1xuICAgICAgICAgICAgcmV0dXJuIFA7XG4gICAgICAgIH0sXG4gICAgfTtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWhhc2gtdG8tY3VydmUuanMubWFwIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/@noble/curves/esm/abstract/hash-to-curve.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/@noble/curves/esm/abstract/modular.js":
+/*!************************************************************!*\
+  !*** ./node_modules/@noble/curves/esm/abstract/modular.js ***!
+  \************************************************************/
+/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   Field: () => (/* binding */ Field),\n/* harmony export */   FpDiv: () => (/* binding */ FpDiv),\n/* harmony export */   FpInvertBatch: () => (/* binding */ FpInvertBatch),\n/* harmony export */   FpIsSquare: () => (/* binding */ FpIsSquare),\n/* harmony export */   FpPow: () => (/* binding */ FpPow),\n/* harmony export */   FpSqrt: () => (/* binding */ FpSqrt),\n/* harmony export */   FpSqrtEven: () => (/* binding */ FpSqrtEven),\n/* harmony export */   FpSqrtOdd: () => (/* binding */ FpSqrtOdd),\n/* harmony export */   hashToPrivateScalar: () => (/* binding */ hashToPrivateScalar),\n/* harmony export */   invert: () => (/* binding */ invert),\n/* harmony export */   isNegativeLE: () => (/* binding */ isNegativeLE),\n/* harmony export */   mod: () => (/* binding */ mod),\n/* harmony export */   nLength: () => (/* binding */ nLength),\n/* harmony export */   pow: () => (/* binding */ pow),\n/* harmony export */   pow2: () => (/* binding */ pow2),\n/* harmony export */   tonelliShanks: () => (/* binding */ tonelliShanks),\n/* harmony export */   validateField: () => (/* binding */ validateField)\n/* harmony export */ });\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils.js */ \"./node_modules/@noble/curves/esm/abstract/utils.js\");\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// Utilities for modular arithmetics and finite fields\n\n// prettier-ignore\nconst _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);\n// prettier-ignore\nconst _4n = BigInt(4), _5n = BigInt(5), _8n = BigInt(8);\n// prettier-ignore\nconst _9n = BigInt(9), _16n = BigInt(16);\n// Calculates a modulo b\nfunction mod(a, b) {\n    const result = a % b;\n    return result >= _0n ? result : b + result;\n}\n/**\n * Efficiently exponentiate num to power and do modular division.\n * Unsafe in some contexts: uses ladder, so can expose bigint bits.\n * @example\n * powMod(2n, 6n, 11n) // 64n % 11n == 9n\n */\n// TODO: use field version && remove\nfunction pow(num, power, modulo) {\n    if (modulo <= _0n || power < _0n)\n        throw new Error('Expected power/modulo > 0');\n    if (modulo === _1n)\n        return _0n;\n    let res = _1n;\n    while (power > _0n) {\n        if (power & _1n)\n            res = (res * num) % modulo;\n        num = (num * num) % modulo;\n        power >>= _1n;\n    }\n    return res;\n}\n// Does x ^ (2 ^ power) mod p. pow2(30, 4) == 30 ^ (2 ^ 4)\nfunction pow2(x, power, modulo) {\n    let res = x;\n    while (power-- > _0n) {\n        res *= res;\n        res %= modulo;\n    }\n    return res;\n}\n// Inverses number over modulo\nfunction invert(number, modulo) {\n    if (number === _0n || modulo <= _0n) {\n        throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`);\n    }\n    // Eucledian GCD https://brilliant.org/wiki/extended-euclidean-algorithm/\n    // Fermat's little theorem \"CT-like\" version inv(n) = n^(m-2) mod m is 30x slower.\n    let a = mod(number, modulo);\n    let b = modulo;\n    // prettier-ignore\n    let x = _0n, y = _1n, u = _1n, v = _0n;\n    while (a !== _0n) {\n        // JIT applies optimization if those two lines follow each other\n        const q = b / a;\n        const r = b % a;\n        const m = x - u * q;\n        const n = y - v * q;\n        // prettier-ignore\n        b = a, a = r, x = u, y = v, u = m, v = n;\n    }\n    const gcd = b;\n    if (gcd !== _1n)\n        throw new Error('invert: does not exist');\n    return mod(x, modulo);\n}\n// Tonelli-Shanks algorithm\n// Paper 1: https://eprint.iacr.org/2012/685.pdf (page 12)\n// Paper 2: Square Roots from 1; 24, 51, 10 to Dan Shanks\nfunction tonelliShanks(P) {\n    // Legendre constant: used to calculate Legendre symbol (a | p),\n    // which denotes the value of a^((p-1)/2) (mod p).\n    // (a | p) ≡ 1    if a is a square (mod p)\n    // (a | p) ≡ -1   if a is not a square (mod p)\n    // (a | p) ≡ 0    if a ≡ 0 (mod p)\n    const legendreC = (P - _1n) / _2n;\n    let Q, S, Z;\n    // Step 1: By factoring out powers of 2 from p - 1,\n    // find q and s such that p - 1 = q*(2^s) with q odd\n    for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++)\n        ;\n    // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq\n    for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++)\n        ;\n    // Fast-path\n    if (S === 1) {\n        const p1div4 = (P + _1n) / _4n;\n        return function tonelliFast(Fp, n) {\n            const root = Fp.pow(n, p1div4);\n            if (!Fp.eql(Fp.sqr(root), n))\n                throw new Error('Cannot find square root');\n            return root;\n        };\n    }\n    // Slow-path\n    const Q1div2 = (Q + _1n) / _2n;\n    return function tonelliSlow(Fp, n) {\n        // Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1\n        if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE))\n            throw new Error('Cannot find square root');\n        let r = S;\n        // TODO: will fail at Fp2/etc\n        let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q); // will update both x and b\n        let x = Fp.pow(n, Q1div2); // first guess at the square root\n        let b = Fp.pow(n, Q); // first guess at the fudge factor\n        while (!Fp.eql(b, Fp.ONE)) {\n            if (Fp.eql(b, Fp.ZERO))\n                return Fp.ZERO; // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0)\n            // Find m such b^(2^m)==1\n            let m = 1;\n            for (let t2 = Fp.sqr(b); m < r; m++) {\n                if (Fp.eql(t2, Fp.ONE))\n                    break;\n                t2 = Fp.sqr(t2); // t2 *= t2\n            }\n            // NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow\n            const ge = Fp.pow(g, _1n << BigInt(r - m - 1)); // ge = 2^(r-m-1)\n            g = Fp.sqr(ge); // g = ge * ge\n            x = Fp.mul(x, ge); // x *= ge\n            b = Fp.mul(b, g); // b *= g\n            r = m;\n        }\n        return x;\n    };\n}\nfunction FpSqrt(P) {\n    // NOTE: different algorithms can give different roots, it is up to user to decide which one they want.\n    // For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).\n    // P ≡ 3 (mod 4)\n    // √n = n^((P+1)/4)\n    if (P % _4n === _3n) {\n        // Not all roots possible!\n        // const ORDER =\n        //   0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn;\n        // const NUM = 72057594037927816n;\n        const p1div4 = (P + _1n) / _4n;\n        return function sqrt3mod4(Fp, n) {\n            const root = Fp.pow(n, p1div4);\n            // Throw if root**2 != n\n            if (!Fp.eql(Fp.sqr(root), n))\n                throw new Error('Cannot find square root');\n            return root;\n        };\n    }\n    // Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10)\n    if (P % _8n === _5n) {\n        const c1 = (P - _5n) / _8n;\n        return function sqrt5mod8(Fp, n) {\n            const n2 = Fp.mul(n, _2n);\n            const v = Fp.pow(n2, c1);\n            const nv = Fp.mul(n, v);\n            const i = Fp.mul(Fp.mul(nv, _2n), v);\n            const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));\n            if (!Fp.eql(Fp.sqr(root), n))\n                throw new Error('Cannot find square root');\n            return root;\n        };\n    }\n    // P ≡ 9 (mod 16)\n    if (P % _16n === _9n) {\n        // NOTE: tonelli is too slow for bls-Fp2 calculations even on start\n        // Means we cannot use sqrt for constants at all!\n        //\n        // const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); //  1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F\n        // const c2 = Fp.sqrt(c1);                //  2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F\n        // const c3 = Fp.sqrt(Fp.negate(c1));     //  3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F\n        // const c4 = (P + _7n) / _16n;           //  4. c4 = (q + 7) / 16        # Integer arithmetic\n        // sqrt = (x) => {\n        //   let tv1 = Fp.pow(x, c4);             //  1. tv1 = x^c4\n        //   let tv2 = Fp.mul(c1, tv1);           //  2. tv2 = c1 * tv1\n        //   const tv3 = Fp.mul(c2, tv1);         //  3. tv3 = c2 * tv1\n        //   let tv4 = Fp.mul(c3, tv1);           //  4. tv4 = c3 * tv1\n        //   const e1 = Fp.equals(Fp.square(tv2), x); //  5.  e1 = (tv2^2) == x\n        //   const e2 = Fp.equals(Fp.square(tv3), x); //  6.  e2 = (tv3^2) == x\n        //   tv1 = Fp.cmov(tv1, tv2, e1); //  7. tv1 = CMOV(tv1, tv2, e1)  # Select tv2 if (tv2^2) == x\n        //   tv2 = Fp.cmov(tv4, tv3, e2); //  8. tv2 = CMOV(tv4, tv3, e2)  # Select tv3 if (tv3^2) == x\n        //   const e3 = Fp.equals(Fp.square(tv2), x); //  9.  e3 = (tv2^2) == x\n        //   return Fp.cmov(tv1, tv2, e3); //  10.  z = CMOV(tv1, tv2, e3)  # Select the sqrt from tv1 and tv2\n        // }\n    }\n    // Other cases: Tonelli-Shanks algorithm\n    return tonelliShanks(P);\n}\n// Little-endian check for first LE bit (last BE bit);\nconst isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n) === _1n;\n// prettier-ignore\nconst FIELD_FIELDS = [\n    'create', 'isValid', 'is0', 'neg', 'inv', 'sqrt', 'sqr',\n    'eql', 'add', 'sub', 'mul', 'pow', 'div',\n    'addN', 'subN', 'mulN', 'sqrN'\n];\nfunction validateField(field) {\n    const initial = {\n        ORDER: 'bigint',\n        MASK: 'bigint',\n        BYTES: 'isSafeInteger',\n        BITS: 'isSafeInteger',\n    };\n    const opts = FIELD_FIELDS.reduce((map, val) => {\n        map[val] = 'function';\n        return map;\n    }, initial);\n    return (0,_utils_js__WEBPACK_IMPORTED_MODULE_0__.validateObject)(field, opts);\n}\n// Generic field functions\nfunction FpPow(f, num, power) {\n    // Should have same speed as pow for bigints\n    // TODO: benchmark!\n    if (power < _0n)\n        throw new Error('Expected power > 0');\n    if (power === _0n)\n        return f.ONE;\n    if (power === _1n)\n        return num;\n    let p = f.ONE;\n    let d = num;\n    while (power > _0n) {\n        if (power & _1n)\n            p = f.mul(p, d);\n        d = f.sqr(d);\n        power >>= _1n;\n    }\n    return p;\n}\n// 0 is non-invertible: non-batched version will throw on 0\nfunction FpInvertBatch(f, nums) {\n    const tmp = new Array(nums.length);\n    // Walk from first to last, multiply them by each other MOD p\n    const lastMultiplied = nums.reduce((acc, num, i) => {\n        if (f.is0(num))\n            return acc;\n        tmp[i] = acc;\n        return f.mul(acc, num);\n    }, f.ONE);\n    // Invert last element\n    const inverted = f.inv(lastMultiplied);\n    // Walk from last to first, multiply them by inverted each other MOD p\n    nums.reduceRight((acc, num, i) => {\n        if (f.is0(num))\n            return acc;\n        tmp[i] = f.mul(acc, tmp[i]);\n        return f.mul(acc, num);\n    }, inverted);\n    return tmp;\n}\nfunction FpDiv(f, lhs, rhs) {\n    return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.inv(rhs));\n}\n// This function returns True whenever the value x is a square in the field F.\nfunction FpIsSquare(f) {\n    const legendreConst = (f.ORDER - _1n) / _2n; // Integer arithmetic\n    return (x) => {\n        const p = f.pow(x, legendreConst);\n        return f.eql(p, f.ZERO) || f.eql(p, f.ONE);\n    };\n}\n// CURVE.n lengths\nfunction nLength(n, nBitLength) {\n    // Bit size, byte size of CURVE.n\n    const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length;\n    const nByteLength = Math.ceil(_nBitLength / 8);\n    return { nBitLength: _nBitLength, nByteLength };\n}\n/**\n * Initializes a galois field over prime. Non-primes are not supported for now.\n * Do not init in loop: slow. Very fragile: always run a benchmark on change.\n * Major performance gains:\n * a) non-normalized operations like mulN instead of mul\n * b) `Object.freeze`\n * c) Same object shape: never add or remove keys\n * @param ORDER prime positive bigint\n * @param bitLen how many bits the field consumes\n * @param isLE (def: false) if encoding / decoding should be in little-endian\n * @param redef optional faster redefinitions of sqrt and other methods\n */\nfunction Field(ORDER, bitLen, isLE = false, redef = {}) {\n    if (ORDER <= _0n)\n        throw new Error(`Expected Fp ORDER > 0, got ${ORDER}`);\n    const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen);\n    if (BYTES > 2048)\n        throw new Error('Field lengths over 2048 bytes are not supported');\n    const sqrtP = FpSqrt(ORDER);\n    const f = Object.freeze({\n        ORDER,\n        BITS,\n        BYTES,\n        MASK: (0,_utils_js__WEBPACK_IMPORTED_MODULE_0__.bitMask)(BITS),\n        ZERO: _0n,\n        ONE: _1n,\n        create: (num) => mod(num, ORDER),\n        isValid: (num) => {\n            if (typeof num !== 'bigint')\n                throw new Error(`Invalid field element: expected bigint, got ${typeof num}`);\n            return _0n <= num && num < ORDER; // 0 is valid element, but it's not invertible\n        },\n        is0: (num) => num === _0n,\n        isOdd: (num) => (num & _1n) === _1n,\n        neg: (num) => mod(-num, ORDER),\n        eql: (lhs, rhs) => lhs === rhs,\n        sqr: (num) => mod(num * num, ORDER),\n        add: (lhs, rhs) => mod(lhs + rhs, ORDER),\n        sub: (lhs, rhs) => mod(lhs - rhs, ORDER),\n        mul: (lhs, rhs) => mod(lhs * rhs, ORDER),\n        pow: (num, power) => FpPow(f, num, power),\n        div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),\n        // Same as above, but doesn't normalize\n        sqrN: (num) => num * num,\n        addN: (lhs, rhs) => lhs + rhs,\n        subN: (lhs, rhs) => lhs - rhs,\n        mulN: (lhs, rhs) => lhs * rhs,\n        inv: (num) => invert(num, ORDER),\n        sqrt: redef.sqrt || ((n) => sqrtP(f, n)),\n        invertBatch: (lst) => FpInvertBatch(f, lst),\n        // TODO: do we really need constant cmov?\n        // We don't have const-time bigints anyway, so probably will be not very useful\n        cmov: (a, b, c) => (c ? b : a),\n        toBytes: (num) => (isLE ? (0,_utils_js__WEBPACK_IMPORTED_MODULE_0__.numberToBytesLE)(num, BYTES) : (0,_utils_js__WEBPACK_IMPORTED_MODULE_0__.numberToBytesBE)(num, BYTES)),\n        fromBytes: (bytes) => {\n            if (bytes.length !== BYTES)\n                throw new Error(`Fp.fromBytes: expected ${BYTES}, got ${bytes.length}`);\n            return isLE ? (0,_utils_js__WEBPACK_IMPORTED_MODULE_0__.bytesToNumberLE)(bytes) : (0,_utils_js__WEBPACK_IMPORTED_MODULE_0__.bytesToNumberBE)(bytes);\n        },\n    });\n    return Object.freeze(f);\n}\nfunction FpSqrtOdd(Fp, elm) {\n    if (!Fp.isOdd)\n        throw new Error(`Field doesn't have isOdd`);\n    const root = Fp.sqrt(elm);\n    return Fp.isOdd(root) ? root : Fp.neg(root);\n}\nfunction FpSqrtEven(Fp, elm) {\n    if (!Fp.isOdd)\n        throw new Error(`Field doesn't have isOdd`);\n    const root = Fp.sqrt(elm);\n    return Fp.isOdd(root) ? Fp.neg(root) : root;\n}\n/**\n * FIPS 186 B.4.1-compliant \"constant-time\" private key generation utility.\n * Can take (n+8) or more bytes of uniform input e.g. from CSPRNG or KDF\n * and convert them into private scalar, with the modulo bias being neglible.\n * Needs at least 40 bytes of input for 32-byte private key.\n * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/\n * @param hash hash output from SHA3 or a similar function\n * @returns valid private scalar\n */\nfunction hashToPrivateScalar(hash, groupOrder, isLE = false) {\n    hash = (0,_utils_js__WEBPACK_IMPORTED_MODULE_0__.ensureBytes)('privateHash', hash);\n    const hashLen = hash.length;\n    const minLen = nLength(groupOrder).nByteLength + 8;\n    if (minLen < 24 || hashLen < minLen || hashLen > 1024)\n        throw new Error(`hashToPrivateScalar: expected ${minLen}-1024 bytes of input, got ${hashLen}`);\n    const num = isLE ? (0,_utils_js__WEBPACK_IMPORTED_MODULE_0__.bytesToNumberLE)(hash) : (0,_utils_js__WEBPACK_IMPORTED_MODULE_0__.bytesToNumberBE)(hash);\n    return mod(num, groupOrder - _1n) + _1n;\n}\n//# sourceMappingURL=modular.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQG5vYmxlL2N1cnZlcy9lc20vYWJzdHJhY3QvbW9kdWxhci5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9jdXJ2ZXMvZXNtL2Fic3RyYWN0L21vZHVsYXIuanM/NGFkNCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiEgbm9ibGUtY3VydmVzIC0gTUlUIExpY2Vuc2UgKGMpIDIwMjIgUGF1bCBNaWxsZXIgKHBhdWxtaWxsci5jb20pICovXG4vLyBVdGlsaXRpZXMgZm9yIG1vZHVsYXIgYXJpdGhtZXRpY3MgYW5kIGZpbml0ZSBmaWVsZHNcbmltcG9ydCB7IGJpdE1hc2ssIG51bWJlclRvQnl0ZXNCRSwgbnVtYmVyVG9CeXRlc0xFLCBieXRlc1RvTnVtYmVyQkUsIGJ5dGVzVG9OdW1iZXJMRSwgZW5zdXJlQnl0ZXMsIHZhbGlkYXRlT2JqZWN0LCB9IGZyb20gJy4vdXRpbHMuanMnO1xuLy8gcHJldHRpZXItaWdub3JlXG5jb25zdCBfMG4gPSBCaWdJbnQoMCksIF8xbiA9IEJpZ0ludCgxKSwgXzJuID0gQmlnSW50KDIpLCBfM24gPSBCaWdJbnQoMyk7XG4vLyBwcmV0dGllci1pZ25vcmVcbmNvbnN0IF80biA9IEJpZ0ludCg0KSwgXzVuID0gQmlnSW50KDUpLCBfOG4gPSBCaWdJbnQoOCk7XG4vLyBwcmV0dGllci1pZ25vcmVcbmNvbnN0IF85biA9IEJpZ0ludCg5KSwgXzE2biA9IEJpZ0ludCgxNik7XG4vLyBDYWxjdWxhdGVzIGEgbW9kdWxvIGJcbmV4cG9ydCBmdW5jdGlvbiBtb2QoYSwgYikge1xuICAgIGNvbnN0IHJlc3VsdCA9IGEgJSBiO1xuICAgIHJldHVybiByZXN1bHQgPj0gXzBuID8gcmVzdWx0IDogYiArIHJlc3VsdDtcbn1cbi8qKlxuICogRWZmaWNpZW50bHkgZXhwb25lbnRpYXRlIG51bSB0byBwb3dlciBhbmQgZG8gbW9kdWxhciBkaXZpc2lvbi5cbiAqIFVuc2FmZSBpbiBzb21lIGNvbnRleHRzOiB1c2VzIGxhZGRlciwgc28gY2FuIGV4cG9zZSBiaWdpbnQgYml0cy5cbiAqIEBleGFtcGxlXG4gKiBwb3dNb2QoMm4sIDZuLCAxMW4pIC8vIDY0biAlIDExbiA9PSA5blxuICovXG4vLyBUT0RPOiB1c2UgZmllbGQgdmVyc2lvbiAmJiByZW1vdmVcbmV4cG9ydCBmdW5jdGlvbiBwb3cobnVtLCBwb3dlciwgbW9kdWxvKSB7XG4gICAgaWYgKG1vZHVsbyA8PSBfMG4gfHwgcG93ZXIgPCBfMG4pXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0ZWQgcG93ZXIvbW9kdWxvID4gMCcpO1xuICAgIGlmIChtb2R1bG8gPT09IF8xbilcbiAgICAgICAgcmV0dXJuIF8wbjtcbiAgICBsZXQgcmVzID0gXzFuO1xuICAgIHdoaWxlIChwb3dlciA+IF8wbikge1xuICAgICAgICBpZiAocG93ZXIgJiBfMW4pXG4gICAgICAgICAgICByZXMgPSAocmVzICogbnVtKSAlIG1vZHVsbztcbiAgICAgICAgbnVtID0gKG51bSAqIG51bSkgJSBtb2R1bG87XG4gICAgICAgIHBvd2VyID4+PSBfMW47XG4gICAgfVxuICAgIHJldHVybiByZXM7XG59XG4vLyBEb2VzIHggXiAoMiBeIHBvd2VyKSBtb2QgcC4gcG93MigzMCwgNCkgPT0gMzAgXiAoMiBeIDQpXG5leHBvcnQgZnVuY3Rpb24gcG93Mih4LCBwb3dlciwgbW9kdWxvKSB7XG4gICAgbGV0IHJlcyA9IHg7XG4gICAgd2hpbGUgKHBvd2VyLS0gPiBfMG4pIHtcbiAgICAgICAgcmVzICo9IHJlcztcbiAgICAgICAgcmVzICU9IG1vZHVsbztcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cbi8vIEludmVyc2VzIG51bWJlciBvdmVyIG1vZHVsb1xuZXhwb3J0IGZ1bmN0aW9uIGludmVydChudW1iZXIsIG1vZHVsbykge1xuICAgIGlmIChudW1iZXIgPT09IF8wbiB8fCBtb2R1bG8gPD0gXzBuKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgaW52ZXJ0OiBleHBlY3RlZCBwb3NpdGl2ZSBpbnRlZ2VycywgZ290IG49JHtudW1iZXJ9IG1vZD0ke21vZHVsb31gKTtcbiAgICB9XG4gICAgLy8gRXVjbGVkaWFuIEdDRCBodHRwczovL2JyaWxsaWFudC5vcmcvd2lraS9leHRlbmRlZC1ldWNsaWRlYW4tYWxnb3JpdGhtL1xuICAgIC8vIEZlcm1hdCdzIGxpdHRsZSB0aGVvcmVtIFwiQ1QtbGlrZVwiIHZlcnNpb24gaW52KG4pID0gbl4obS0yKSBtb2QgbSBpcyAzMHggc2xvd2VyLlxuICAgIGxldCBhID0gbW9kKG51bWJlciwgbW9kdWxvKTtcbiAgICBsZXQgYiA9IG1vZHVsbztcbiAgICAvLyBwcmV0dGllci1pZ25vcmVcbiAgICBsZXQgeCA9IF8wbiwgeSA9IF8xbiwgdSA9IF8xbiwgdiA9IF8wbjtcbiAgICB3aGlsZSAoYSAhPT0gXzBuKSB7XG4gICAgICAgIC8vIEpJVCBhcHBsaWVzIG9wdGltaXphdGlvbiBpZiB0aG9zZSB0d28gbGluZXMgZm9sbG93IGVhY2ggb3RoZXJcbiAgICAgICAgY29uc3QgcSA9IGIgLyBhO1xuICAgICAgICBjb25zdCByID0gYiAlIGE7XG4gICAgICAgIGNvbnN0IG0gPSB4IC0gdSAqIHE7XG4gICAgICAgIGNvbnN0IG4gPSB5IC0gdiAqIHE7XG4gICAgICAgIC8vIHByZXR0aWVyLWlnbm9yZVxuICAgICAgICBiID0gYSwgYSA9IHIsIHggPSB1LCB5ID0gdiwgdSA9IG0sIHYgPSBuO1xuICAgIH1cbiAgICBjb25zdCBnY2QgPSBiO1xuICAgIGlmIChnY2QgIT09IF8xbilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZlcnQ6IGRvZXMgbm90IGV4aXN0Jyk7XG4gICAgcmV0dXJuIG1vZCh4LCBtb2R1bG8pO1xufVxuLy8gVG9uZWxsaS1TaGFua3MgYWxnb3JpdGhtXG4vLyBQYXBlciAxOiBodHRwczovL2VwcmludC5pYWNyLm9yZy8yMDEyLzY4NS5wZGYgKHBhZ2UgMTIpXG4vLyBQYXBlciAyOiBTcXVhcmUgUm9vdHMgZnJvbSAxOyAyNCwgNTEsIDEwIHRvIERhbiBTaGFua3NcbmV4cG9ydCBmdW5jdGlvbiB0b25lbGxpU2hhbmtzKFApIHtcbiAgICAvLyBMZWdlbmRyZSBjb25zdGFudDogdXNlZCB0byBjYWxjdWxhdGUgTGVnZW5kcmUgc3ltYm9sIChhIHwgcCksXG4gICAgLy8gd2hpY2ggZGVub3RlcyB0aGUgdmFsdWUgb2YgYV4oKHAtMSkvMikgKG1vZCBwKS5cbiAgICAvLyAoYSB8IHApIOKJoSAxICAgIGlmIGEgaXMgYSBzcXVhcmUgKG1vZCBwKVxuICAgIC8vIChhIHwgcCkg4omhIC0xICAgaWYgYSBpcyBub3QgYSBzcXVhcmUgKG1vZCBwKVxuICAgIC8vIChhIHwgcCkg4omhIDAgICAgaWYgYSDiiaEgMCAobW9kIHApXG4gICAgY29uc3QgbGVnZW5kcmVDID0gKFAgLSBfMW4pIC8gXzJuO1xuICAgIGxldCBRLCBTLCBaO1xuICAgIC8vIFN0ZXAgMTogQnkgZmFjdG9yaW5nIG91dCBwb3dlcnMgb2YgMiBmcm9tIHAgLSAxLFxuICAgIC8vIGZpbmQgcSBhbmQgcyBzdWNoIHRoYXQgcCAtIDEgPSBxKigyXnMpIHdpdGggcSBvZGRcbiAgICBmb3IgKFEgPSBQIC0gXzFuLCBTID0gMDsgUSAlIF8ybiA9PT0gXzBuOyBRIC89IF8ybiwgUysrKVxuICAgICAgICA7XG4gICAgLy8gU3RlcCAyOiBTZWxlY3QgYSBub24tc3F1YXJlIHogc3VjaCB0aGF0ICh6IHwgcCkg4omhIC0xIGFuZCBzZXQgYyDiiaEgenFcbiAgICBmb3IgKFogPSBfMm47IFogPCBQICYmIHBvdyhaLCBsZWdlbmRyZUMsIFApICE9PSBQIC0gXzFuOyBaKyspXG4gICAgICAgIDtcbiAgICAvLyBGYXN0LXBhdGhcbiAgICBpZiAoUyA9PT0gMSkge1xuICAgICAgICBjb25zdCBwMWRpdjQgPSAoUCArIF8xbikgLyBfNG47XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiB0b25lbGxpRmFzdChGcCwgbikge1xuICAgICAgICAgICAgY29uc3Qgcm9vdCA9IEZwLnBvdyhuLCBwMWRpdjQpO1xuICAgICAgICAgICAgaWYgKCFGcC5lcWwoRnAuc3FyKHJvb3QpLCBuKSlcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBmaW5kIHNxdWFyZSByb290Jyk7XG4gICAgICAgICAgICByZXR1cm4gcm9vdDtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLy8gU2xvdy1wYXRoXG4gICAgY29uc3QgUTFkaXYyID0gKFEgKyBfMW4pIC8gXzJuO1xuICAgIHJldHVybiBmdW5jdGlvbiB0b25lbGxpU2xvdyhGcCwgbikge1xuICAgICAgICAvLyBTdGVwIDA6IENoZWNrIHRoYXQgbiBpcyBpbmRlZWQgYSBzcXVhcmU6IChuIHwgcCkgc2hvdWxkIG5vdCBiZSDiiaEgLTFcbiAgICAgICAgaWYgKEZwLnBvdyhuLCBsZWdlbmRyZUMpID09PSBGcC5uZWcoRnAuT05FKSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGZpbmQgc3F1YXJlIHJvb3QnKTtcbiAgICAgICAgbGV0IHIgPSBTO1xuICAgICAgICAvLyBUT0RPOiB3aWxsIGZhaWwgYXQgRnAyL2V0Y1xuICAgICAgICBsZXQgZyA9IEZwLnBvdyhGcC5tdWwoRnAuT05FLCBaKSwgUSk7IC8vIHdpbGwgdXBkYXRlIGJvdGggeCBhbmQgYlxuICAgICAgICBsZXQgeCA9IEZwLnBvdyhuLCBRMWRpdjIpOyAvLyBmaXJzdCBndWVzcyBhdCB0aGUgc3F1YXJlIHJvb3RcbiAgICAgICAgbGV0IGIgPSBGcC5wb3cobiwgUSk7IC8vIGZpcnN0IGd1ZXNzIGF0IHRoZSBmdWRnZSBmYWN0b3JcbiAgICAgICAgd2hpbGUgKCFGcC5lcWwoYiwgRnAuT05FKSkge1xuICAgICAgICAgICAgaWYgKEZwLmVxbChiLCBGcC5aRVJPKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gRnAuWkVSTzsgLy8gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvVG9uZWxsaSVFMiU4MCU5M1NoYW5rc19hbGdvcml0aG0gKDQuIElmIHQgPSAwLCByZXR1cm4gciA9IDApXG4gICAgICAgICAgICAvLyBGaW5kIG0gc3VjaCBiXigyXm0pPT0xXG4gICAgICAgICAgICBsZXQgbSA9IDE7XG4gICAgICAgICAgICBmb3IgKGxldCB0MiA9IEZwLnNxcihiKTsgbSA8IHI7IG0rKykge1xuICAgICAgICAgICAgICAgIGlmIChGcC5lcWwodDIsIEZwLk9ORSkpXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIHQyID0gRnAuc3FyKHQyKTsgLy8gdDIgKj0gdDJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE5PVEU6IHItbS0xIGNhbiBiZSBiaWdnZXIgdGhhbiAzMiwgbmVlZCB0byBjb252ZXJ0IHRvIGJpZ2ludCBiZWZvcmUgc2hpZnQsIG90aGVyd2lzZSB0aGVyZSB3aWxsIGJlIG92ZXJmbG93XG4gICAgICAgICAgICBjb25zdCBnZSA9IEZwLnBvdyhnLCBfMW4gPDwgQmlnSW50KHIgLSBtIC0gMSkpOyAvLyBnZSA9IDJeKHItbS0xKVxuICAgICAgICAgICAgZyA9IEZwLnNxcihnZSk7IC8vIGcgPSBnZSAqIGdlXG4gICAgICAgICAgICB4ID0gRnAubXVsKHgsIGdlKTsgLy8geCAqPSBnZVxuICAgICAgICAgICAgYiA9IEZwLm11bChiLCBnKTsgLy8gYiAqPSBnXG4gICAgICAgICAgICByID0gbTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geDtcbiAgICB9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIEZwU3FydChQKSB7XG4gICAgLy8gTk9URTogZGlmZmVyZW50IGFsZ29yaXRobXMgY2FuIGdpdmUgZGlmZmVyZW50IHJvb3RzLCBpdCBpcyB1cCB0byB1c2VyIHRvIGRlY2lkZSB3aGljaCBvbmUgdGhleSB3YW50LlxuICAgIC8vIEZvciBleGFtcGxlIHRoZXJlIGlzIEZwU3FydE9kZC9GcFNxcnRFdmVuIHRvIGNob2ljZSByb290IGJhc2VkIG9uIG9kZG5lc3MgKHVzZWQgZm9yIGhhc2gtdG8tY3VydmUpLlxuICAgIC8vIFAg4omhIDMgKG1vZCA0KVxuICAgIC8vIOKImm4gPSBuXigoUCsxKS80KVxuICAgIGlmIChQICUgXzRuID09PSBfM24pIHtcbiAgICAgICAgLy8gTm90IGFsbCByb290cyBwb3NzaWJsZSFcbiAgICAgICAgLy8gY29uc3QgT1JERVIgPVxuICAgICAgICAvLyAgIDB4MWEwMTExZWEzOTdmZTY5YTRiMWJhN2I2NDM0YmFjZDc2NDc3NGI4NGYzODUxMmJmNjczMGQyYTBmNmIwZjYyNDFlYWJmZmZlYjE1M2ZmZmZiOWZlZmZmZmZmZmZhYWFibjtcbiAgICAgICAgLy8gY29uc3QgTlVNID0gNzIwNTc1OTQwMzc5Mjc4MTZuO1xuICAgICAgICBjb25zdCBwMWRpdjQgPSAoUCArIF8xbikgLyBfNG47XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBzcXJ0M21vZDQoRnAsIG4pIHtcbiAgICAgICAgICAgIGNvbnN0IHJvb3QgPSBGcC5wb3cobiwgcDFkaXY0KTtcbiAgICAgICAgICAgIC8vIFRocm93IGlmIHJvb3QqKjIgIT0gblxuICAgICAgICAgICAgaWYgKCFGcC5lcWwoRnAuc3FyKHJvb3QpLCBuKSlcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBmaW5kIHNxdWFyZSByb290Jyk7XG4gICAgICAgICAgICByZXR1cm4gcm9vdDtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLy8gQXRraW4gYWxnb3JpdGhtIGZvciBxIOKJoSA1IChtb2QgOCksIGh0dHBzOi8vZXByaW50LmlhY3Iub3JnLzIwMTIvNjg1LnBkZiAocGFnZSAxMClcbiAgICBpZiAoUCAlIF84biA9PT0gXzVuKSB7XG4gICAgICAgIGNvbnN0IGMxID0gKFAgLSBfNW4pIC8gXzhuO1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gc3FydDVtb2Q4KEZwLCBuKSB7XG4gICAgICAgICAgICBjb25zdCBuMiA9IEZwLm11bChuLCBfMm4pO1xuICAgICAgICAgICAgY29uc3QgdiA9IEZwLnBvdyhuMiwgYzEpO1xuICAgICAgICAgICAgY29uc3QgbnYgPSBGcC5tdWwobiwgdik7XG4gICAgICAgICAgICBjb25zdCBpID0gRnAubXVsKEZwLm11bChudiwgXzJuKSwgdik7XG4gICAgICAgICAgICBjb25zdCByb290ID0gRnAubXVsKG52LCBGcC5zdWIoaSwgRnAuT05FKSk7XG4gICAgICAgICAgICBpZiAoIUZwLmVxbChGcC5zcXIocm9vdCksIG4pKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGZpbmQgc3F1YXJlIHJvb3QnKTtcbiAgICAgICAgICAgIHJldHVybiByb290O1xuICAgICAgICB9O1xuICAgIH1cbiAgICAvLyBQIOKJoSA5IChtb2QgMTYpXG4gICAgaWYgKFAgJSBfMTZuID09PSBfOW4pIHtcbiAgICAgICAgLy8gTk9URTogdG9uZWxsaSBpcyB0b28gc2xvdyBmb3IgYmxzLUZwMiBjYWxjdWxhdGlvbnMgZXZlbiBvbiBzdGFydFxuICAgICAgICAvLyBNZWFucyB3ZSBjYW5ub3QgdXNlIHNxcnQgZm9yIGNvbnN0YW50cyBhdCBhbGwhXG4gICAgICAgIC8vXG4gICAgICAgIC8vIGNvbnN0IGMxID0gRnAuc3FydChGcC5uZWdhdGUoRnAuT05FKSk7IC8vICAxLiBjMSA9IHNxcnQoLTEpIGluIEYsIGkuZS4sIChjMV4yKSA9PSAtMSBpbiBGXG4gICAgICAgIC8vIGNvbnN0IGMyID0gRnAuc3FydChjMSk7ICAgICAgICAgICAgICAgIC8vICAyLiBjMiA9IHNxcnQoYzEpIGluIEYsIGkuZS4sIChjMl4yKSA9PSBjMSBpbiBGXG4gICAgICAgIC8vIGNvbnN0IGMzID0gRnAuc3FydChGcC5uZWdhdGUoYzEpKTsgICAgIC8vICAzLiBjMyA9IHNxcnQoLWMxKSBpbiBGLCBpLmUuLCAoYzNeMikgPT0gLWMxIGluIEZcbiAgICAgICAgLy8gY29uc3QgYzQgPSAoUCArIF83bikgLyBfMTZuOyAgICAgICAgICAgLy8gIDQuIGM0ID0gKHEgKyA3KSAvIDE2ICAgICAgICAjIEludGVnZXIgYXJpdGhtZXRpY1xuICAgICAgICAvLyBzcXJ0ID0gKHgpID0+IHtcbiAgICAgICAgLy8gICBsZXQgdHYxID0gRnAucG93KHgsIGM0KTsgICAgICAgICAgICAgLy8gIDEuIHR2MSA9IHheYzRcbiAgICAgICAgLy8gICBsZXQgdHYyID0gRnAubXVsKGMxLCB0djEpOyAgICAgICAgICAgLy8gIDIuIHR2MiA9IGMxICogdHYxXG4gICAgICAgIC8vICAgY29uc3QgdHYzID0gRnAubXVsKGMyLCB0djEpOyAgICAgICAgIC8vICAzLiB0djMgPSBjMiAqIHR2MVxuICAgICAgICAvLyAgIGxldCB0djQgPSBGcC5tdWwoYzMsIHR2MSk7ICAgICAgICAgICAvLyAgNC4gdHY0ID0gYzMgKiB0djFcbiAgICAgICAgLy8gICBjb25zdCBlMSA9IEZwLmVxdWFscyhGcC5zcXVhcmUodHYyKSwgeCk7IC8vICA1LiAgZTEgPSAodHYyXjIpID09IHhcbiAgICAgICAgLy8gICBjb25zdCBlMiA9IEZwLmVxdWFscyhGcC5zcXVhcmUodHYzKSwgeCk7IC8vICA2LiAgZTIgPSAodHYzXjIpID09IHhcbiAgICAgICAgLy8gICB0djEgPSBGcC5jbW92KHR2MSwgdHYyLCBlMSk7IC8vICA3LiB0djEgPSBDTU9WKHR2MSwgdHYyLCBlMSkgICMgU2VsZWN0IHR2MiBpZiAodHYyXjIpID09IHhcbiAgICAgICAgLy8gICB0djIgPSBGcC5jbW92KHR2NCwgdHYzLCBlMik7IC8vICA4LiB0djIgPSBDTU9WKHR2NCwgdHYzLCBlMikgICMgU2VsZWN0IHR2MyBpZiAodHYzXjIpID09IHhcbiAgICAgICAgLy8gICBjb25zdCBlMyA9IEZwLmVxdWFscyhGcC5zcXVhcmUodHYyKSwgeCk7IC8vICA5LiAgZTMgPSAodHYyXjIpID09IHhcbiAgICAgICAgLy8gICByZXR1cm4gRnAuY21vdih0djEsIHR2MiwgZTMpOyAvLyAgMTAuICB6ID0gQ01PVih0djEsIHR2MiwgZTMpICAjIFNlbGVjdCB0aGUgc3FydCBmcm9tIHR2MSBhbmQgdHYyXG4gICAgICAgIC8vIH1cbiAgICB9XG4gICAgLy8gT3RoZXIgY2FzZXM6IFRvbmVsbGktU2hhbmtzIGFsZ29yaXRobVxuICAgIHJldHVybiB0b25lbGxpU2hhbmtzKFApO1xufVxuLy8gTGl0dGxlLWVuZGlhbiBjaGVjayBmb3IgZmlyc3QgTEUgYml0IChsYXN0IEJFIGJpdCk7XG5leHBvcnQgY29uc3QgaXNOZWdhdGl2ZUxFID0gKG51bSwgbW9kdWxvKSA9PiAobW9kKG51bSwgbW9kdWxvKSAmIF8xbikgPT09IF8xbjtcbi8vIHByZXR0aWVyLWlnbm9yZVxuY29uc3QgRklFTERfRklFTERTID0gW1xuICAgICdjcmVhdGUnLCAnaXNWYWxpZCcsICdpczAnLCAnbmVnJywgJ2ludicsICdzcXJ0JywgJ3NxcicsXG4gICAgJ2VxbCcsICdhZGQnLCAnc3ViJywgJ211bCcsICdwb3cnLCAnZGl2JyxcbiAgICAnYWRkTicsICdzdWJOJywgJ211bE4nLCAnc3FyTidcbl07XG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVGaWVsZChmaWVsZCkge1xuICAgIGNvbnN0IGluaXRpYWwgPSB7XG4gICAgICAgIE9SREVSOiAnYmlnaW50JyxcbiAgICAgICAgTUFTSzogJ2JpZ2ludCcsXG4gICAgICAgIEJZVEVTOiAnaXNTYWZlSW50ZWdlcicsXG4gICAgICAgIEJJVFM6ICdpc1NhZmVJbnRlZ2VyJyxcbiAgICB9O1xuICAgIGNvbnN0IG9wdHMgPSBGSUVMRF9GSUVMRFMucmVkdWNlKChtYXAsIHZhbCkgPT4ge1xuICAgICAgICBtYXBbdmFsXSA9ICdmdW5jdGlvbic7XG4gICAgICAgIHJldHVybiBtYXA7XG4gICAgfSwgaW5pdGlhbCk7XG4gICAgcmV0dXJuIHZhbGlkYXRlT2JqZWN0KGZpZWxkLCBvcHRzKTtcbn1cbi8vIEdlbmVyaWMgZmllbGQgZnVuY3Rpb25zXG5leHBvcnQgZnVuY3Rpb24gRnBQb3coZiwgbnVtLCBwb3dlcikge1xuICAgIC8vIFNob3VsZCBoYXZlIHNhbWUgc3BlZWQgYXMgcG93IGZvciBiaWdpbnRzXG4gICAgLy8gVE9ETzogYmVuY2htYXJrIVxuICAgIGlmIChwb3dlciA8IF8wbilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3RlZCBwb3dlciA+IDAnKTtcbiAgICBpZiAocG93ZXIgPT09IF8wbilcbiAgICAgICAgcmV0dXJuIGYuT05FO1xuICAgIGlmIChwb3dlciA9PT0gXzFuKVxuICAgICAgICByZXR1cm4gbnVtO1xuICAgIGxldCBwID0gZi5PTkU7XG4gICAgbGV0IGQgPSBudW07XG4gICAgd2hpbGUgKHBvd2VyID4gXzBuKSB7XG4gICAgICAgIGlmIChwb3dlciAmIF8xbilcbiAgICAgICAgICAgIHAgPSBmLm11bChwLCBkKTtcbiAgICAgICAgZCA9IGYuc3FyKGQpO1xuICAgICAgICBwb3dlciA+Pj0gXzFuO1xuICAgIH1cbiAgICByZXR1cm4gcDtcbn1cbi8vIDAgaXMgbm9uLWludmVydGlibGU6IG5vbi1iYXRjaGVkIHZlcnNpb24gd2lsbCB0aHJvdyBvbiAwXG5leHBvcnQgZnVuY3Rpb24gRnBJbnZlcnRCYXRjaChmLCBudW1zKSB7XG4gICAgY29uc3QgdG1wID0gbmV3IEFycmF5KG51bXMubGVuZ3RoKTtcbiAgICAvLyBXYWxrIGZyb20gZmlyc3QgdG8gbGFzdCwgbXVsdGlwbHkgdGhlbSBieSBlYWNoIG90aGVyIE1PRCBwXG4gICAgY29uc3QgbGFzdE11bHRpcGxpZWQgPSBudW1zLnJlZHVjZSgoYWNjLCBudW0sIGkpID0+IHtcbiAgICAgICAgaWYgKGYuaXMwKG51bSkpXG4gICAgICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgICB0bXBbaV0gPSBhY2M7XG4gICAgICAgIHJldHVybiBmLm11bChhY2MsIG51bSk7XG4gICAgfSwgZi5PTkUpO1xuICAgIC8vIEludmVydCBsYXN0IGVsZW1lbnRcbiAgICBjb25zdCBpbnZlcnRlZCA9IGYuaW52KGxhc3RNdWx0aXBsaWVkKTtcbiAgICAvLyBXYWxrIGZyb20gbGFzdCB0byBmaXJzdCwgbXVsdGlwbHkgdGhlbSBieSBpbnZlcnRlZCBlYWNoIG90aGVyIE1PRCBwXG4gICAgbnVtcy5yZWR1Y2VSaWdodCgoYWNjLCBudW0sIGkpID0+IHtcbiAgICAgICAgaWYgKGYuaXMwKG51bSkpXG4gICAgICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgICB0bXBbaV0gPSBmLm11bChhY2MsIHRtcFtpXSk7XG4gICAgICAgIHJldHVybiBmLm11bChhY2MsIG51bSk7XG4gICAgfSwgaW52ZXJ0ZWQpO1xuICAgIHJldHVybiB0bXA7XG59XG5leHBvcnQgZnVuY3Rpb24gRnBEaXYoZiwgbGhzLCByaHMpIHtcbiAgICByZXR1cm4gZi5tdWwobGhzLCB0eXBlb2YgcmhzID09PSAnYmlnaW50JyA/IGludmVydChyaHMsIGYuT1JERVIpIDogZi5pbnYocmhzKSk7XG59XG4vLyBUaGlzIGZ1bmN0aW9uIHJldHVybnMgVHJ1ZSB3aGVuZXZlciB0aGUgdmFsdWUgeCBpcyBhIHNxdWFyZSBpbiB0aGUgZmllbGQgRi5cbmV4cG9ydCBmdW5jdGlvbiBGcElzU3F1YXJlKGYpIHtcbiAgICBjb25zdCBsZWdlbmRyZUNvbnN0ID0gKGYuT1JERVIgLSBfMW4pIC8gXzJuOyAvLyBJbnRlZ2VyIGFyaXRobWV0aWNcbiAgICByZXR1cm4gKHgpID0+IHtcbiAgICAgICAgY29uc3QgcCA9IGYucG93KHgsIGxlZ2VuZHJlQ29uc3QpO1xuICAgICAgICByZXR1cm4gZi5lcWwocCwgZi5aRVJPKSB8fCBmLmVxbChwLCBmLk9ORSk7XG4gICAgfTtcbn1cbi8vIENVUlZFLm4gbGVuZ3Roc1xuZXhwb3J0IGZ1bmN0aW9uIG5MZW5ndGgobiwgbkJpdExlbmd0aCkge1xuICAgIC8vIEJpdCBzaXplLCBieXRlIHNpemUgb2YgQ1VSVkUublxuICAgIGNvbnN0IF9uQml0TGVuZ3RoID0gbkJpdExlbmd0aCAhPT0gdW5kZWZpbmVkID8gbkJpdExlbmd0aCA6IG4udG9TdHJpbmcoMikubGVuZ3RoO1xuICAgIGNvbnN0IG5CeXRlTGVuZ3RoID0gTWF0aC5jZWlsKF9uQml0TGVuZ3RoIC8gOCk7XG4gICAgcmV0dXJuIHsgbkJpdExlbmd0aDogX25CaXRMZW5ndGgsIG5CeXRlTGVuZ3RoIH07XG59XG4vKipcbiAqIEluaXRpYWxpemVzIGEgZ2Fsb2lzIGZpZWxkIG92ZXIgcHJpbWUuIE5vbi1wcmltZXMgYXJlIG5vdCBzdXBwb3J0ZWQgZm9yIG5vdy5cbiAqIERvIG5vdCBpbml0IGluIGxvb3A6IHNsb3cuIFZlcnkgZnJhZ2lsZTogYWx3YXlzIHJ1biBhIGJlbmNobWFyayBvbiBjaGFuZ2UuXG4gKiBNYWpvciBwZXJmb3JtYW5jZSBnYWluczpcbiAqIGEpIG5vbi1ub3JtYWxpemVkIG9wZXJhdGlvbnMgbGlrZSBtdWxOIGluc3RlYWQgb2YgbXVsXG4gKiBiKSBgT2JqZWN0LmZyZWV6ZWBcbiAqIGMpIFNhbWUgb2JqZWN0IHNoYXBlOiBuZXZlciBhZGQgb3IgcmVtb3ZlIGtleXNcbiAqIEBwYXJhbSBPUkRFUiBwcmltZSBwb3NpdGl2ZSBiaWdpbnRcbiAqIEBwYXJhbSBiaXRMZW4gaG93IG1hbnkgYml0cyB0aGUgZmllbGQgY29uc3VtZXNcbiAqIEBwYXJhbSBpc0xFIChkZWY6IGZhbHNlKSBpZiBlbmNvZGluZyAvIGRlY29kaW5nIHNob3VsZCBiZSBpbiBsaXR0bGUtZW5kaWFuXG4gKiBAcGFyYW0gcmVkZWYgb3B0aW9uYWwgZmFzdGVyIHJlZGVmaW5pdGlvbnMgb2Ygc3FydCBhbmQgb3RoZXIgbWV0aG9kc1xuICovXG5leHBvcnQgZnVuY3Rpb24gRmllbGQoT1JERVIsIGJpdExlbiwgaXNMRSA9IGZhbHNlLCByZWRlZiA9IHt9KSB7XG4gICAgaWYgKE9SREVSIDw9IF8wbilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBGcCBPUkRFUiA+IDAsIGdvdCAke09SREVSfWApO1xuICAgIGNvbnN0IHsgbkJpdExlbmd0aDogQklUUywgbkJ5dGVMZW5ndGg6IEJZVEVTIH0gPSBuTGVuZ3RoKE9SREVSLCBiaXRMZW4pO1xuICAgIGlmIChCWVRFUyA+IDIwNDgpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRmllbGQgbGVuZ3RocyBvdmVyIDIwNDggYnl0ZXMgYXJlIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICBjb25zdCBzcXJ0UCA9IEZwU3FydChPUkRFUik7XG4gICAgY29uc3QgZiA9IE9iamVjdC5mcmVlemUoe1xuICAgICAgICBPUkRFUixcbiAgICAgICAgQklUUyxcbiAgICAgICAgQllURVMsXG4gICAgICAgIE1BU0s6IGJpdE1hc2soQklUUyksXG4gICAgICAgIFpFUk86IF8wbixcbiAgICAgICAgT05FOiBfMW4sXG4gICAgICAgIGNyZWF0ZTogKG51bSkgPT4gbW9kKG51bSwgT1JERVIpLFxuICAgICAgICBpc1ZhbGlkOiAobnVtKSA9PiB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG51bSAhPT0gJ2JpZ2ludCcpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGZpZWxkIGVsZW1lbnQ6IGV4cGVjdGVkIGJpZ2ludCwgZ290ICR7dHlwZW9mIG51bX1gKTtcbiAgICAgICAgICAgIHJldHVybiBfMG4gPD0gbnVtICYmIG51bSA8IE9SREVSOyAvLyAwIGlzIHZhbGlkIGVsZW1lbnQsIGJ1dCBpdCdzIG5vdCBpbnZlcnRpYmxlXG4gICAgICAgIH0sXG4gICAgICAgIGlzMDogKG51bSkgPT4gbnVtID09PSBfMG4sXG4gICAgICAgIGlzT2RkOiAobnVtKSA9PiAobnVtICYgXzFuKSA9PT0gXzFuLFxuICAgICAgICBuZWc6IChudW0pID0+IG1vZCgtbnVtLCBPUkRFUiksXG4gICAgICAgIGVxbDogKGxocywgcmhzKSA9PiBsaHMgPT09IHJocyxcbiAgICAgICAgc3FyOiAobnVtKSA9PiBtb2QobnVtICogbnVtLCBPUkRFUiksXG4gICAgICAgIGFkZDogKGxocywgcmhzKSA9PiBtb2QobGhzICsgcmhzLCBPUkRFUiksXG4gICAgICAgIHN1YjogKGxocywgcmhzKSA9PiBtb2QobGhzIC0gcmhzLCBPUkRFUiksXG4gICAgICAgIG11bDogKGxocywgcmhzKSA9PiBtb2QobGhzICogcmhzLCBPUkRFUiksXG4gICAgICAgIHBvdzogKG51bSwgcG93ZXIpID0+IEZwUG93KGYsIG51bSwgcG93ZXIpLFxuICAgICAgICBkaXY6IChsaHMsIHJocykgPT4gbW9kKGxocyAqIGludmVydChyaHMsIE9SREVSKSwgT1JERVIpLFxuICAgICAgICAvLyBTYW1lIGFzIGFib3ZlLCBidXQgZG9lc24ndCBub3JtYWxpemVcbiAgICAgICAgc3FyTjogKG51bSkgPT4gbnVtICogbnVtLFxuICAgICAgICBhZGROOiAobGhzLCByaHMpID0+IGxocyArIHJocyxcbiAgICAgICAgc3ViTjogKGxocywgcmhzKSA9PiBsaHMgLSByaHMsXG4gICAgICAgIG11bE46IChsaHMsIHJocykgPT4gbGhzICogcmhzLFxuICAgICAgICBpbnY6IChudW0pID0+IGludmVydChudW0sIE9SREVSKSxcbiAgICAgICAgc3FydDogcmVkZWYuc3FydCB8fCAoKG4pID0+IHNxcnRQKGYsIG4pKSxcbiAgICAgICAgaW52ZXJ0QmF0Y2g6IChsc3QpID0+IEZwSW52ZXJ0QmF0Y2goZiwgbHN0KSxcbiAgICAgICAgLy8gVE9ETzogZG8gd2UgcmVhbGx5IG5lZWQgY29uc3RhbnQgY21vdj9cbiAgICAgICAgLy8gV2UgZG9uJ3QgaGF2ZSBjb25zdC10aW1lIGJpZ2ludHMgYW55d2F5LCBzbyBwcm9iYWJseSB3aWxsIGJlIG5vdCB2ZXJ5IHVzZWZ1bFxuICAgICAgICBjbW92OiAoYSwgYiwgYykgPT4gKGMgPyBiIDogYSksXG4gICAgICAgIHRvQnl0ZXM6IChudW0pID0+IChpc0xFID8gbnVtYmVyVG9CeXRlc0xFKG51bSwgQllURVMpIDogbnVtYmVyVG9CeXRlc0JFKG51bSwgQllURVMpKSxcbiAgICAgICAgZnJvbUJ5dGVzOiAoYnl0ZXMpID0+IHtcbiAgICAgICAgICAgIGlmIChieXRlcy5sZW5ndGggIT09IEJZVEVTKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRnAuZnJvbUJ5dGVzOiBleHBlY3RlZCAke0JZVEVTfSwgZ290ICR7Ynl0ZXMubGVuZ3RofWApO1xuICAgICAgICAgICAgcmV0dXJuIGlzTEUgPyBieXRlc1RvTnVtYmVyTEUoYnl0ZXMpIDogYnl0ZXNUb051bWJlckJFKGJ5dGVzKTtcbiAgICAgICAgfSxcbiAgICB9KTtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShmKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBGcFNxcnRPZGQoRnAsIGVsbSkge1xuICAgIGlmICghRnAuaXNPZGQpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRmllbGQgZG9lc24ndCBoYXZlIGlzT2RkYCk7XG4gICAgY29uc3Qgcm9vdCA9IEZwLnNxcnQoZWxtKTtcbiAgICByZXR1cm4gRnAuaXNPZGQocm9vdCkgPyByb290IDogRnAubmVnKHJvb3QpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIEZwU3FydEV2ZW4oRnAsIGVsbSkge1xuICAgIGlmICghRnAuaXNPZGQpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRmllbGQgZG9lc24ndCBoYXZlIGlzT2RkYCk7XG4gICAgY29uc3Qgcm9vdCA9IEZwLnNxcnQoZWxtKTtcbiAgICByZXR1cm4gRnAuaXNPZGQocm9vdCkgPyBGcC5uZWcocm9vdCkgOiByb290O1xufVxuLyoqXG4gKiBGSVBTIDE4NiBCLjQuMS1jb21wbGlhbnQgXCJjb25zdGFudC10aW1lXCIgcHJpdmF0ZSBrZXkgZ2VuZXJhdGlvbiB1dGlsaXR5LlxuICogQ2FuIHRha2UgKG4rOCkgb3IgbW9yZSBieXRlcyBvZiB1bmlmb3JtIGlucHV0IGUuZy4gZnJvbSBDU1BSTkcgb3IgS0RGXG4gKiBhbmQgY29udmVydCB0aGVtIGludG8gcHJpdmF0ZSBzY2FsYXIsIHdpdGggdGhlIG1vZHVsbyBiaWFzIGJlaW5nIG5lZ2xpYmxlLlxuICogTmVlZHMgYXQgbGVhc3QgNDAgYnl0ZXMgb2YgaW5wdXQgZm9yIDMyLWJ5dGUgcHJpdmF0ZSBrZXkuXG4gKiBodHRwczovL3Jlc2VhcmNoLmt1ZGVsc2tpc2VjdXJpdHkuY29tLzIwMjAvMDcvMjgvdGhlLWRlZmluaXRpdmUtZ3VpZGUtdG8tbW9kdWxvLWJpYXMtYW5kLWhvdy10by1hdm9pZC1pdC9cbiAqIEBwYXJhbSBoYXNoIGhhc2ggb3V0cHV0IGZyb20gU0hBMyBvciBhIHNpbWlsYXIgZnVuY3Rpb25cbiAqIEByZXR1cm5zIHZhbGlkIHByaXZhdGUgc2NhbGFyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNoVG9Qcml2YXRlU2NhbGFyKGhhc2gsIGdyb3VwT3JkZXIsIGlzTEUgPSBmYWxzZSkge1xuICAgIGhhc2ggPSBlbnN1cmVCeXRlcygncHJpdmF0ZUhhc2gnLCBoYXNoKTtcbiAgICBjb25zdCBoYXNoTGVuID0gaGFzaC5sZW5ndGg7XG4gICAgY29uc3QgbWluTGVuID0gbkxlbmd0aChncm91cE9yZGVyKS5uQnl0ZUxlbmd0aCArIDg7XG4gICAgaWYgKG1pbkxlbiA8IDI0IHx8IGhhc2hMZW4gPCBtaW5MZW4gfHwgaGFzaExlbiA+IDEwMjQpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgaGFzaFRvUHJpdmF0ZVNjYWxhcjogZXhwZWN0ZWQgJHttaW5MZW59LTEwMjQgYnl0ZXMgb2YgaW5wdXQsIGdvdCAke2hhc2hMZW59YCk7XG4gICAgY29uc3QgbnVtID0gaXNMRSA/IGJ5dGVzVG9OdW1iZXJMRShoYXNoKSA6IGJ5dGVzVG9OdW1iZXJCRShoYXNoKTtcbiAgICByZXR1cm4gbW9kKG51bSwgZ3JvdXBPcmRlciAtIF8xbikgKyBfMW47XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1tb2R1bGFyLmpzLm1hcCJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/@noble/curves/esm/abstract/modular.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/@noble/curves/esm/abstract/montgomery.js":
+/*!***************************************************************!*\
+  !*** ./node_modules/@noble/curves/esm/abstract/montgomery.js ***!
+  \***************************************************************/
+/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   montgomery: () => (/* binding */ montgomery)\n/* harmony export */ });\n/* harmony import */ var _modular_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./modular.js */ \"./node_modules/@noble/curves/esm/abstract/modular.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils.js */ \"./node_modules/@noble/curves/esm/abstract/utils.js\");\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n\n\nconst _0n = BigInt(0);\nconst _1n = BigInt(1);\nfunction validateOpts(curve) {\n    (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.validateObject)(curve, {\n        a: 'bigint',\n    }, {\n        montgomeryBits: 'isSafeInteger',\n        nByteLength: 'isSafeInteger',\n        adjustScalarBytes: 'function',\n        domain: 'function',\n        powPminus2: 'function',\n        Gu: 'bigint',\n    });\n    // Set defaults\n    return Object.freeze({ ...curve });\n}\n// NOTE: not really montgomery curve, just bunch of very specific methods for X25519/X448 (RFC 7748, https://www.rfc-editor.org/rfc/rfc7748)\n// Uses only one coordinate instead of two\nfunction montgomery(curveDef) {\n    const CURVE = validateOpts(curveDef);\n    const { P } = CURVE;\n    const modP = (n) => (0,_modular_js__WEBPACK_IMPORTED_MODULE_0__.mod)(n, P);\n    const montgomeryBits = CURVE.montgomeryBits;\n    const montgomeryBytes = Math.ceil(montgomeryBits / 8);\n    const fieldLen = CURVE.nByteLength;\n    const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes) => bytes);\n    const powPminus2 = CURVE.powPminus2 || ((x) => (0,_modular_js__WEBPACK_IMPORTED_MODULE_0__.pow)(x, P - BigInt(2), P));\n    // cswap from RFC7748. But it is not from RFC7748!\n    /*\n      cswap(swap, x_2, x_3):\n           dummy = mask(swap) AND (x_2 XOR x_3)\n           x_2 = x_2 XOR dummy\n           x_3 = x_3 XOR dummy\n           Return (x_2, x_3)\n    Where mask(swap) is the all-1 or all-0 word of the same length as x_2\n     and x_3, computed, e.g., as mask(swap) = 0 - swap.\n    */\n    function cswap(swap, x_2, x_3) {\n        const dummy = modP(swap * (x_2 - x_3));\n        x_2 = modP(x_2 - dummy);\n        x_3 = modP(x_3 + dummy);\n        return [x_2, x_3];\n    }\n    // Accepts 0 as well\n    function assertFieldElement(n) {\n        if (typeof n === 'bigint' && _0n <= n && n < P)\n            return n;\n        throw new Error('Expected valid scalar 0 < scalar < CURVE.P');\n    }\n    // x25519 from 4\n    // The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519\n    const a24 = (CURVE.a - BigInt(2)) / BigInt(4);\n    /**\n     *\n     * @param pointU u coordinate (x) on Montgomery Curve 25519\n     * @param scalar by which the point would be multiplied\n     * @returns new Point on Montgomery curve\n     */\n    function montgomeryLadder(pointU, scalar) {\n        const u = assertFieldElement(pointU);\n        // Section 5: Implementations MUST accept non-canonical values and process them as\n        // if they had been reduced modulo the field prime.\n        const k = assertFieldElement(scalar);\n        const x_1 = u;\n        let x_2 = _1n;\n        let z_2 = _0n;\n        let x_3 = u;\n        let z_3 = _1n;\n        let swap = _0n;\n        let sw;\n        for (let t = BigInt(montgomeryBits - 1); t >= _0n; t--) {\n            const k_t = (k >> t) & _1n;\n            swap ^= k_t;\n            sw = cswap(swap, x_2, x_3);\n            x_2 = sw[0];\n            x_3 = sw[1];\n            sw = cswap(swap, z_2, z_3);\n            z_2 = sw[0];\n            z_3 = sw[1];\n            swap = k_t;\n            const A = x_2 + z_2;\n            const AA = modP(A * A);\n            const B = x_2 - z_2;\n            const BB = modP(B * B);\n            const E = AA - BB;\n            const C = x_3 + z_3;\n            const D = x_3 - z_3;\n            const DA = modP(D * A);\n            const CB = modP(C * B);\n            const dacb = DA + CB;\n            const da_cb = DA - CB;\n            x_3 = modP(dacb * dacb);\n            z_3 = modP(x_1 * modP(da_cb * da_cb));\n            x_2 = modP(AA * BB);\n            z_2 = modP(E * (AA + modP(a24 * E)));\n        }\n        // (x_2, x_3) = cswap(swap, x_2, x_3)\n        sw = cswap(swap, x_2, x_3);\n        x_2 = sw[0];\n        x_3 = sw[1];\n        // (z_2, z_3) = cswap(swap, z_2, z_3)\n        sw = cswap(swap, z_2, z_3);\n        z_2 = sw[0];\n        z_3 = sw[1];\n        // z_2^(p - 2)\n        const z2 = powPminus2(z_2);\n        // Return x_2 * (z_2^(p - 2))\n        return modP(x_2 * z2);\n    }\n    function encodeUCoordinate(u) {\n        return (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.numberToBytesLE)(modP(u), montgomeryBytes);\n    }\n    function decodeUCoordinate(uEnc) {\n        // Section 5: When receiving such an array, implementations of X25519\n        // MUST mask the most significant bit in the final byte.\n        // This is very ugly way, but it works because fieldLen-1 is outside of bounds for X448, so this becomes NOOP\n        // fieldLen - scalaryBytes = 1 for X448 and = 0 for X25519\n        const u = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.ensureBytes)('u coordinate', uEnc, montgomeryBytes);\n        // u[fieldLen-1] crashes QuickJS (TypeError: out-of-bound numeric index)\n        if (fieldLen === montgomeryBytes)\n            u[fieldLen - 1] &= 127; // 0b0111_1111\n        return (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.bytesToNumberLE)(u);\n    }\n    function decodeScalar(n) {\n        const bytes = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.ensureBytes)('scalar', n);\n        if (bytes.length !== montgomeryBytes && bytes.length !== fieldLen)\n            throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${bytes.length}`);\n        return (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.bytesToNumberLE)(adjustScalarBytes(bytes));\n    }\n    function scalarMult(scalar, u) {\n        const pointU = decodeUCoordinate(u);\n        const _scalar = decodeScalar(scalar);\n        const pu = montgomeryLadder(pointU, _scalar);\n        // The result was not contributory\n        // https://cr.yp.to/ecdh.html#validate\n        if (pu === _0n)\n            throw new Error('Invalid private or public key received');\n        return encodeUCoordinate(pu);\n    }\n    // Computes public key from private. By doing scalar multiplication of base point.\n    const GuBytes = encodeUCoordinate(CURVE.Gu);\n    function scalarMultBase(scalar) {\n        return scalarMult(scalar, GuBytes);\n    }\n    return {\n        scalarMult,\n        scalarMultBase,\n        getSharedSecret: (privateKey, publicKey) => scalarMult(privateKey, publicKey),\n        getPublicKey: (privateKey) => scalarMultBase(privateKey),\n        utils: { randomPrivateKey: () => CURVE.randomBytes(CURVE.nByteLength) },\n        GuBytes: GuBytes,\n    };\n}\n//# sourceMappingURL=montgomery.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQG5vYmxlL2N1cnZlcy9lc20vYWJzdHJhY3QvbW9udGdvbWVyeS5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9Abm9ibGUvY3VydmVzL2VzbS9hYnN0cmFjdC9tb250Z29tZXJ5LmpzPzlmZWQiXSwic291cmNlc0NvbnRlbnQiOlsiLyohIG5vYmxlLWN1cnZlcyAtIE1JVCBMaWNlbnNlIChjKSAyMDIyIFBhdWwgTWlsbGVyIChwYXVsbWlsbHIuY29tKSAqL1xuaW1wb3J0IHsgbW9kLCBwb3cgfSBmcm9tICcuL21vZHVsYXIuanMnO1xuaW1wb3J0IHsgYnl0ZXNUb051bWJlckxFLCBlbnN1cmVCeXRlcywgbnVtYmVyVG9CeXRlc0xFLCB2YWxpZGF0ZU9iamVjdCB9IGZyb20gJy4vdXRpbHMuanMnO1xuY29uc3QgXzBuID0gQmlnSW50KDApO1xuY29uc3QgXzFuID0gQmlnSW50KDEpO1xuZnVuY3Rpb24gdmFsaWRhdGVPcHRzKGN1cnZlKSB7XG4gICAgdmFsaWRhdGVPYmplY3QoY3VydmUsIHtcbiAgICAgICAgYTogJ2JpZ2ludCcsXG4gICAgfSwge1xuICAgICAgICBtb250Z29tZXJ5Qml0czogJ2lzU2FmZUludGVnZXInLFxuICAgICAgICBuQnl0ZUxlbmd0aDogJ2lzU2FmZUludGVnZXInLFxuICAgICAgICBhZGp1c3RTY2FsYXJCeXRlczogJ2Z1bmN0aW9uJyxcbiAgICAgICAgZG9tYWluOiAnZnVuY3Rpb24nLFxuICAgICAgICBwb3dQbWludXMyOiAnZnVuY3Rpb24nLFxuICAgICAgICBHdTogJ2JpZ2ludCcsXG4gICAgfSk7XG4gICAgLy8gU2V0IGRlZmF1bHRzXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeyAuLi5jdXJ2ZSB9KTtcbn1cbi8vIE5PVEU6IG5vdCByZWFsbHkgbW9udGdvbWVyeSBjdXJ2ZSwganVzdCBidW5jaCBvZiB2ZXJ5IHNwZWNpZmljIG1ldGhvZHMgZm9yIFgyNTUxOS9YNDQ4IChSRkMgNzc0OCwgaHR0cHM6Ly93d3cucmZjLWVkaXRvci5vcmcvcmZjL3JmYzc3NDgpXG4vLyBVc2VzIG9ubHkgb25lIGNvb3JkaW5hdGUgaW5zdGVhZCBvZiB0d29cbmV4cG9ydCBmdW5jdGlvbiBtb250Z29tZXJ5KGN1cnZlRGVmKSB7XG4gICAgY29uc3QgQ1VSVkUgPSB2YWxpZGF0ZU9wdHMoY3VydmVEZWYpO1xuICAgIGNvbnN0IHsgUCB9ID0gQ1VSVkU7XG4gICAgY29uc3QgbW9kUCA9IChuKSA9PiBtb2QobiwgUCk7XG4gICAgY29uc3QgbW9udGdvbWVyeUJpdHMgPSBDVVJWRS5tb250Z29tZXJ5Qml0cztcbiAgICBjb25zdCBtb250Z29tZXJ5Qnl0ZXMgPSBNYXRoLmNlaWwobW9udGdvbWVyeUJpdHMgLyA4KTtcbiAgICBjb25zdCBmaWVsZExlbiA9IENVUlZFLm5CeXRlTGVuZ3RoO1xuICAgIGNvbnN0IGFkanVzdFNjYWxhckJ5dGVzID0gQ1VSVkUuYWRqdXN0U2NhbGFyQnl0ZXMgfHwgKChieXRlcykgPT4gYnl0ZXMpO1xuICAgIGNvbnN0IHBvd1BtaW51czIgPSBDVVJWRS5wb3dQbWludXMyIHx8ICgoeCkgPT4gcG93KHgsIFAgLSBCaWdJbnQoMiksIFApKTtcbiAgICAvLyBjc3dhcCBmcm9tIFJGQzc3NDguIEJ1dCBpdCBpcyBub3QgZnJvbSBSRkM3NzQ4IVxuICAgIC8qXG4gICAgICBjc3dhcChzd2FwLCB4XzIsIHhfMyk6XG4gICAgICAgICAgIGR1bW15ID0gbWFzayhzd2FwKSBBTkQgKHhfMiBYT1IgeF8zKVxuICAgICAgICAgICB4XzIgPSB4XzIgWE9SIGR1bW15XG4gICAgICAgICAgIHhfMyA9IHhfMyBYT1IgZHVtbXlcbiAgICAgICAgICAgUmV0dXJuICh4XzIsIHhfMylcbiAgICBXaGVyZSBtYXNrKHN3YXApIGlzIHRoZSBhbGwtMSBvciBhbGwtMCB3b3JkIG9mIHRoZSBzYW1lIGxlbmd0aCBhcyB4XzJcbiAgICAgYW5kIHhfMywgY29tcHV0ZWQsIGUuZy4sIGFzIG1hc2soc3dhcCkgPSAwIC0gc3dhcC5cbiAgICAqL1xuICAgIGZ1bmN0aW9uIGNzd2FwKHN3YXAsIHhfMiwgeF8zKSB7XG4gICAgICAgIGNvbnN0IGR1bW15ID0gbW9kUChzd2FwICogKHhfMiAtIHhfMykpO1xuICAgICAgICB4XzIgPSBtb2RQKHhfMiAtIGR1bW15KTtcbiAgICAgICAgeF8zID0gbW9kUCh4XzMgKyBkdW1teSk7XG4gICAgICAgIHJldHVybiBbeF8yLCB4XzNdO1xuICAgIH1cbiAgICAvLyBBY2NlcHRzIDAgYXMgd2VsbFxuICAgIGZ1bmN0aW9uIGFzc2VydEZpZWxkRWxlbWVudChuKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbiA9PT0gJ2JpZ2ludCcgJiYgXzBuIDw9IG4gJiYgbiA8IFApXG4gICAgICAgICAgICByZXR1cm4gbjtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3RlZCB2YWxpZCBzY2FsYXIgMCA8IHNjYWxhciA8IENVUlZFLlAnKTtcbiAgICB9XG4gICAgLy8geDI1NTE5IGZyb20gNFxuICAgIC8vIFRoZSBjb25zdGFudCBhMjQgaXMgKDQ4NjY2MiAtIDIpIC8gNCA9IDEyMTY2NSBmb3IgY3VydmUyNTUxOS9YMjU1MTlcbiAgICBjb25zdCBhMjQgPSAoQ1VSVkUuYSAtIEJpZ0ludCgyKSkgLyBCaWdJbnQoNCk7XG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcG9pbnRVIHUgY29vcmRpbmF0ZSAoeCkgb24gTW9udGdvbWVyeSBDdXJ2ZSAyNTUxOVxuICAgICAqIEBwYXJhbSBzY2FsYXIgYnkgd2hpY2ggdGhlIHBvaW50IHdvdWxkIGJlIG11bHRpcGxpZWRcbiAgICAgKiBAcmV0dXJucyBuZXcgUG9pbnQgb24gTW9udGdvbWVyeSBjdXJ2ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1vbnRnb21lcnlMYWRkZXIocG9pbnRVLCBzY2FsYXIpIHtcbiAgICAgICAgY29uc3QgdSA9IGFzc2VydEZpZWxkRWxlbWVudChwb2ludFUpO1xuICAgICAgICAvLyBTZWN0aW9uIDU6IEltcGxlbWVudGF0aW9ucyBNVVNUIGFjY2VwdCBub24tY2Fub25pY2FsIHZhbHVlcyBhbmQgcHJvY2VzcyB0aGVtIGFzXG4gICAgICAgIC8vIGlmIHRoZXkgaGFkIGJlZW4gcmVkdWNlZCBtb2R1bG8gdGhlIGZpZWxkIHByaW1lLlxuICAgICAgICBjb25zdCBrID0gYXNzZXJ0RmllbGRFbGVtZW50KHNjYWxhcik7XG4gICAgICAgIGNvbnN0IHhfMSA9IHU7XG4gICAgICAgIGxldCB4XzIgPSBfMW47XG4gICAgICAgIGxldCB6XzIgPSBfMG47XG4gICAgICAgIGxldCB4XzMgPSB1O1xuICAgICAgICBsZXQgel8zID0gXzFuO1xuICAgICAgICBsZXQgc3dhcCA9IF8wbjtcbiAgICAgICAgbGV0IHN3O1xuICAgICAgICBmb3IgKGxldCB0ID0gQmlnSW50KG1vbnRnb21lcnlCaXRzIC0gMSk7IHQgPj0gXzBuOyB0LS0pIHtcbiAgICAgICAgICAgIGNvbnN0IGtfdCA9IChrID4+IHQpICYgXzFuO1xuICAgICAgICAgICAgc3dhcCBePSBrX3Q7XG4gICAgICAgICAgICBzdyA9IGNzd2FwKHN3YXAsIHhfMiwgeF8zKTtcbiAgICAgICAgICAgIHhfMiA9IHN3WzBdO1xuICAgICAgICAgICAgeF8zID0gc3dbMV07XG4gICAgICAgICAgICBzdyA9IGNzd2FwKHN3YXAsIHpfMiwgel8zKTtcbiAgICAgICAgICAgIHpfMiA9IHN3WzBdO1xuICAgICAgICAgICAgel8zID0gc3dbMV07XG4gICAgICAgICAgICBzd2FwID0ga190O1xuICAgICAgICAgICAgY29uc3QgQSA9IHhfMiArIHpfMjtcbiAgICAgICAgICAgIGNvbnN0IEFBID0gbW9kUChBICogQSk7XG4gICAgICAgICAgICBjb25zdCBCID0geF8yIC0gel8yO1xuICAgICAgICAgICAgY29uc3QgQkIgPSBtb2RQKEIgKiBCKTtcbiAgICAgICAgICAgIGNvbnN0IEUgPSBBQSAtIEJCO1xuICAgICAgICAgICAgY29uc3QgQyA9IHhfMyArIHpfMztcbiAgICAgICAgICAgIGNvbnN0IEQgPSB4XzMgLSB6XzM7XG4gICAgICAgICAgICBjb25zdCBEQSA9IG1vZFAoRCAqIEEpO1xuICAgICAgICAgICAgY29uc3QgQ0IgPSBtb2RQKEMgKiBCKTtcbiAgICAgICAgICAgIGNvbnN0IGRhY2IgPSBEQSArIENCO1xuICAgICAgICAgICAgY29uc3QgZGFfY2IgPSBEQSAtIENCO1xuICAgICAgICAgICAgeF8zID0gbW9kUChkYWNiICogZGFjYik7XG4gICAgICAgICAgICB6XzMgPSBtb2RQKHhfMSAqIG1vZFAoZGFfY2IgKiBkYV9jYikpO1xuICAgICAgICAgICAgeF8yID0gbW9kUChBQSAqIEJCKTtcbiAgICAgICAgICAgIHpfMiA9IG1vZFAoRSAqIChBQSArIG1vZFAoYTI0ICogRSkpKTtcbiAgICAgICAgfVxuICAgICAgICAvLyAoeF8yLCB4XzMpID0gY3N3YXAoc3dhcCwgeF8yLCB4XzMpXG4gICAgICAgIHN3ID0gY3N3YXAoc3dhcCwgeF8yLCB4XzMpO1xuICAgICAgICB4XzIgPSBzd1swXTtcbiAgICAgICAgeF8zID0gc3dbMV07XG4gICAgICAgIC8vICh6XzIsIHpfMykgPSBjc3dhcChzd2FwLCB6XzIsIHpfMylcbiAgICAgICAgc3cgPSBjc3dhcChzd2FwLCB6XzIsIHpfMyk7XG4gICAgICAgIHpfMiA9IHN3WzBdO1xuICAgICAgICB6XzMgPSBzd1sxXTtcbiAgICAgICAgLy8gel8yXihwIC0gMilcbiAgICAgICAgY29uc3QgejIgPSBwb3dQbWludXMyKHpfMik7XG4gICAgICAgIC8vIFJldHVybiB4XzIgKiAoel8yXihwIC0gMikpXG4gICAgICAgIHJldHVybiBtb2RQKHhfMiAqIHoyKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZW5jb2RlVUNvb3JkaW5hdGUodSkge1xuICAgICAgICByZXR1cm4gbnVtYmVyVG9CeXRlc0xFKG1vZFAodSksIG1vbnRnb21lcnlCeXRlcyk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGRlY29kZVVDb29yZGluYXRlKHVFbmMpIHtcbiAgICAgICAgLy8gU2VjdGlvbiA1OiBXaGVuIHJlY2VpdmluZyBzdWNoIGFuIGFycmF5LCBpbXBsZW1lbnRhdGlvbnMgb2YgWDI1NTE5XG4gICAgICAgIC8vIE1VU1QgbWFzayB0aGUgbW9zdCBzaWduaWZpY2FudCBiaXQgaW4gdGhlIGZpbmFsIGJ5dGUuXG4gICAgICAgIC8vIFRoaXMgaXMgdmVyeSB1Z2x5IHdheSwgYnV0IGl0IHdvcmtzIGJlY2F1c2UgZmllbGRMZW4tMSBpcyBvdXRzaWRlIG9mIGJvdW5kcyBmb3IgWDQ0OCwgc28gdGhpcyBiZWNvbWVzIE5PT1BcbiAgICAgICAgLy8gZmllbGRMZW4gLSBzY2FsYXJ5Qnl0ZXMgPSAxIGZvciBYNDQ4IGFuZCA9IDAgZm9yIFgyNTUxOVxuICAgICAgICBjb25zdCB1ID0gZW5zdXJlQnl0ZXMoJ3UgY29vcmRpbmF0ZScsIHVFbmMsIG1vbnRnb21lcnlCeXRlcyk7XG4gICAgICAgIC8vIHVbZmllbGRMZW4tMV0gY3Jhc2hlcyBRdWlja0pTIChUeXBlRXJyb3I6IG91dC1vZi1ib3VuZCBudW1lcmljIGluZGV4KVxuICAgICAgICBpZiAoZmllbGRMZW4gPT09IG1vbnRnb21lcnlCeXRlcylcbiAgICAgICAgICAgIHVbZmllbGRMZW4gLSAxXSAmPSAxMjc7IC8vIDBiMDExMV8xMTExXG4gICAgICAgIHJldHVybiBieXRlc1RvTnVtYmVyTEUodSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGRlY29kZVNjYWxhcihuKSB7XG4gICAgICAgIGNvbnN0IGJ5dGVzID0gZW5zdXJlQnl0ZXMoJ3NjYWxhcicsIG4pO1xuICAgICAgICBpZiAoYnl0ZXMubGVuZ3RoICE9PSBtb250Z29tZXJ5Qnl0ZXMgJiYgYnl0ZXMubGVuZ3RoICE9PSBmaWVsZExlbilcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgJHttb250Z29tZXJ5Qnl0ZXN9IG9yICR7ZmllbGRMZW59IGJ5dGVzLCBnb3QgJHtieXRlcy5sZW5ndGh9YCk7XG4gICAgICAgIHJldHVybiBieXRlc1RvTnVtYmVyTEUoYWRqdXN0U2NhbGFyQnl0ZXMoYnl0ZXMpKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gc2NhbGFyTXVsdChzY2FsYXIsIHUpIHtcbiAgICAgICAgY29uc3QgcG9pbnRVID0gZGVjb2RlVUNvb3JkaW5hdGUodSk7XG4gICAgICAgIGNvbnN0IF9zY2FsYXIgPSBkZWNvZGVTY2FsYXIoc2NhbGFyKTtcbiAgICAgICAgY29uc3QgcHUgPSBtb250Z29tZXJ5TGFkZGVyKHBvaW50VSwgX3NjYWxhcik7XG4gICAgICAgIC8vIFRoZSByZXN1bHQgd2FzIG5vdCBjb250cmlidXRvcnlcbiAgICAgICAgLy8gaHR0cHM6Ly9jci55cC50by9lY2RoLmh0bWwjdmFsaWRhdGVcbiAgICAgICAgaWYgKHB1ID09PSBfMG4pXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgcHJpdmF0ZSBvciBwdWJsaWMga2V5IHJlY2VpdmVkJyk7XG4gICAgICAgIHJldHVybiBlbmNvZGVVQ29vcmRpbmF0ZShwdSk7XG4gICAgfVxuICAgIC8vIENvbXB1dGVzIHB1YmxpYyBrZXkgZnJvbSBwcml2YXRlLiBCeSBkb2luZyBzY2FsYXIgbXVsdGlwbGljYXRpb24gb2YgYmFzZSBwb2ludC5cbiAgICBjb25zdCBHdUJ5dGVzID0gZW5jb2RlVUNvb3JkaW5hdGUoQ1VSVkUuR3UpO1xuICAgIGZ1bmN0aW9uIHNjYWxhck11bHRCYXNlKHNjYWxhcikge1xuICAgICAgICByZXR1cm4gc2NhbGFyTXVsdChzY2FsYXIsIEd1Qnl0ZXMpO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBzY2FsYXJNdWx0LFxuICAgICAgICBzY2FsYXJNdWx0QmFzZSxcbiAgICAgICAgZ2V0U2hhcmVkU2VjcmV0OiAocHJpdmF0ZUtleSwgcHVibGljS2V5KSA9PiBzY2FsYXJNdWx0KHByaXZhdGVLZXksIHB1YmxpY0tleSksXG4gICAgICAgIGdldFB1YmxpY0tleTogKHByaXZhdGVLZXkpID0+IHNjYWxhck11bHRCYXNlKHByaXZhdGVLZXkpLFxuICAgICAgICB1dGlsczogeyByYW5kb21Qcml2YXRlS2V5OiAoKSA9PiBDVVJWRS5yYW5kb21CeXRlcyhDVVJWRS5uQnl0ZUxlbmd0aCkgfSxcbiAgICAgICAgR3VCeXRlczogR3VCeXRlcyxcbiAgICB9O1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9bW9udGdvbWVyeS5qcy5tYXAiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/@noble/curves/esm/abstract/montgomery.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/@noble/curves/esm/abstract/utils.js":
+/*!**********************************************************!*\
+  !*** ./node_modules/@noble/curves/esm/abstract/utils.js ***!
+  \**********************************************************/
+/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   bitGet: () => (/* binding */ bitGet),\n/* harmony export */   bitLen: () => (/* binding */ bitLen),\n/* harmony export */   bitMask: () => (/* binding */ bitMask),\n/* harmony export */   bitSet: () => (/* binding */ bitSet),\n/* harmony export */   bytesToHex: () => (/* binding */ bytesToHex),\n/* harmony export */   bytesToNumberBE: () => (/* binding */ bytesToNumberBE),\n/* harmony export */   bytesToNumberLE: () => (/* binding */ bytesToNumberLE),\n/* harmony export */   concatBytes: () => (/* binding */ concatBytes),\n/* harmony export */   createHmacDrbg: () => (/* binding */ createHmacDrbg),\n/* harmony export */   ensureBytes: () => (/* binding */ ensureBytes),\n/* harmony export */   equalBytes: () => (/* binding */ equalBytes),\n/* harmony export */   hexToBytes: () => (/* binding */ hexToBytes),\n/* harmony export */   hexToNumber: () => (/* binding */ hexToNumber),\n/* harmony export */   numberToBytesBE: () => (/* binding */ numberToBytesBE),\n/* harmony export */   numberToBytesLE: () => (/* binding */ numberToBytesLE),\n/* harmony export */   numberToHexUnpadded: () => (/* binding */ numberToHexUnpadded),\n/* harmony export */   numberToVarBytesBE: () => (/* binding */ numberToVarBytesBE),\n/* harmony export */   utf8ToBytes: () => (/* binding */ utf8ToBytes),\n/* harmony export */   validateObject: () => (/* binding */ validateObject)\n/* harmony export */ });\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\nconst _0n = BigInt(0);\nconst _1n = BigInt(1);\nconst _2n = BigInt(2);\nconst u8a = (a) => a instanceof Uint8Array;\nconst hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'));\nfunction bytesToHex(bytes) {\n    if (!u8a(bytes))\n        throw new Error('Uint8Array expected');\n    // pre-caching improves the speed 6x\n    let hex = '';\n    for (let i = 0; i < bytes.length; i++) {\n        hex += hexes[bytes[i]];\n    }\n    return hex;\n}\nfunction numberToHexUnpadded(num) {\n    const hex = num.toString(16);\n    return hex.length & 1 ? `0${hex}` : hex;\n}\nfunction hexToNumber(hex) {\n    if (typeof hex !== 'string')\n        throw new Error('hex string expected, got ' + typeof hex);\n    // Big Endian\n    return BigInt(hex === '' ? '0' : `0x${hex}`);\n}\n// Caching slows it down 2-3x\nfunction hexToBytes(hex) {\n    if (typeof hex !== 'string')\n        throw new Error('hex string expected, got ' + typeof hex);\n    if (hex.length % 2)\n        throw new Error('hex string is invalid: unpadded ' + hex.length);\n    const array = new Uint8Array(hex.length / 2);\n    for (let i = 0; i < array.length; i++) {\n        const j = i * 2;\n        const hexByte = hex.slice(j, j + 2);\n        const byte = Number.parseInt(hexByte, 16);\n        if (Number.isNaN(byte) || byte < 0)\n            throw new Error('invalid byte sequence');\n        array[i] = byte;\n    }\n    return array;\n}\n// Big Endian\nfunction bytesToNumberBE(bytes) {\n    return hexToNumber(bytesToHex(bytes));\n}\nfunction bytesToNumberLE(bytes) {\n    if (!u8a(bytes))\n        throw new Error('Uint8Array expected');\n    return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));\n}\nconst numberToBytesBE = (n, len) => hexToBytes(n.toString(16).padStart(len * 2, '0'));\nconst numberToBytesLE = (n, len) => numberToBytesBE(n, len).reverse();\n// Returns variable number bytes (minimal bigint encoding?)\nconst numberToVarBytesBE = (n) => hexToBytes(numberToHexUnpadded(n));\nfunction ensureBytes(title, hex, expectedLength) {\n    let res;\n    if (typeof hex === 'string') {\n        try {\n            res = hexToBytes(hex);\n        }\n        catch (e) {\n            throw new Error(`${title} must be valid hex string, got \"${hex}\". Cause: ${e}`);\n        }\n    }\n    else if (u8a(hex)) {\n        // Uint8Array.from() instead of hash.slice() because node.js Buffer\n        // is instance of Uint8Array, and its slice() creates **mutable** copy\n        res = Uint8Array.from(hex);\n    }\n    else {\n        throw new Error(`${title} must be hex string or Uint8Array`);\n    }\n    const len = res.length;\n    if (typeof expectedLength === 'number' && len !== expectedLength)\n        throw new Error(`${title} expected ${expectedLength} bytes, got ${len}`);\n    return res;\n}\n// Copies several Uint8Arrays into one.\nfunction concatBytes(...arrs) {\n    const r = new Uint8Array(arrs.reduce((sum, a) => sum + a.length, 0));\n    let pad = 0; // walk through each item, ensure they have proper type\n    arrs.forEach((a) => {\n        if (!u8a(a))\n            throw new Error('Uint8Array expected');\n        r.set(a, pad);\n        pad += a.length;\n    });\n    return r;\n}\nfunction equalBytes(b1, b2) {\n    // We don't care about timing attacks here\n    if (b1.length !== b2.length)\n        return false;\n    for (let i = 0; i < b1.length; i++)\n        if (b1[i] !== b2[i])\n            return false;\n    return true;\n}\nfunction utf8ToBytes(str) {\n    if (typeof str !== 'string') {\n        throw new Error(`utf8ToBytes expected string, got ${typeof str}`);\n    }\n    return new TextEncoder().encode(str);\n}\n// Bit operations\n// Amount of bits inside bigint (Same as n.toString(2).length)\nfunction bitLen(n) {\n    let len;\n    for (len = 0; n > _0n; n >>= _1n, len += 1)\n        ;\n    return len;\n}\n// Gets single bit at position. NOTE: first bit position is 0 (same as arrays)\n// Same as !!+Array.from(n.toString(2)).reverse()[pos]\nconst bitGet = (n, pos) => (n >> BigInt(pos)) & _1n;\n// Sets single bit at position\nconst bitSet = (n, pos, value) => n | ((value ? _1n : _0n) << BigInt(pos));\n// Return mask for N bits (Same as BigInt(`0b${Array(i).fill('1').join('')}`))\n// Not using ** operator with bigints for old engines.\nconst bitMask = (n) => (_2n << BigInt(n - 1)) - _1n;\n// DRBG\nconst u8n = (data) => new Uint8Array(data); // creates Uint8Array\nconst u8fr = (arr) => Uint8Array.from(arr); // another shortcut\n/**\n * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.\n * @returns function that will call DRBG until 2nd arg returns something meaningful\n * @example\n *   const drbg = createHmacDRBG<Key>(32, 32, hmac);\n *   drbg(seed, bytesToKey); // bytesToKey must return Key or undefined\n */\nfunction createHmacDrbg(hashLen, qByteLen, hmacFn) {\n    if (typeof hashLen !== 'number' || hashLen < 2)\n        throw new Error('hashLen must be a number');\n    if (typeof qByteLen !== 'number' || qByteLen < 2)\n        throw new Error('qByteLen must be a number');\n    if (typeof hmacFn !== 'function')\n        throw new Error('hmacFn must be a function');\n    // Step B, Step C: set hashLen to 8*ceil(hlen/8)\n    let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.\n    let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same\n    let i = 0; // Iterations counter, will throw when over 1000\n    const reset = () => {\n        v.fill(1);\n        k.fill(0);\n        i = 0;\n    };\n    const h = (...b) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)\n    const reseed = (seed = u8n()) => {\n        // HMAC-DRBG reseed() function. Steps D-G\n        k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed)\n        v = h(); // v = hmac(k || v)\n        if (seed.length === 0)\n            return;\n        k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed)\n        v = h(); // v = hmac(k || v)\n    };\n    const gen = () => {\n        // HMAC-DRBG generate() function\n        if (i++ >= 1000)\n            throw new Error('drbg: tried 1000 values');\n        let len = 0;\n        const out = [];\n        while (len < qByteLen) {\n            v = h();\n            const sl = v.slice();\n            out.push(sl);\n            len += v.length;\n        }\n        return concatBytes(...out);\n    };\n    const genUntil = (seed, pred) => {\n        reset();\n        reseed(seed); // Steps D-G\n        let res = undefined; // Step H: grind until k is in [1..n-1]\n        while (!(res = pred(gen())))\n            reseed();\n        reset();\n        return res;\n    };\n    return genUntil;\n}\n// Validating curves and fields\nconst validatorFns = {\n    bigint: (val) => typeof val === 'bigint',\n    function: (val) => typeof val === 'function',\n    boolean: (val) => typeof val === 'boolean',\n    string: (val) => typeof val === 'string',\n    isSafeInteger: (val) => Number.isSafeInteger(val),\n    array: (val) => Array.isArray(val),\n    field: (val, object) => object.Fp.isValid(val),\n    hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),\n};\n// type Record<K extends string | number | symbol, T> = { [P in K]: T; }\nfunction validateObject(object, validators, optValidators = {}) {\n    const checkField = (fieldName, type, isOptional) => {\n        const checkVal = validatorFns[type];\n        if (typeof checkVal !== 'function')\n            throw new Error(`Invalid validator \"${type}\", expected function`);\n        const val = object[fieldName];\n        if (isOptional && val === undefined)\n            return;\n        if (!checkVal(val, object)) {\n            throw new Error(`Invalid param ${String(fieldName)}=${val} (${typeof val}), expected ${type}`);\n        }\n    };\n    for (const [fieldName, type] of Object.entries(validators))\n        checkField(fieldName, type, false);\n    for (const [fieldName, type] of Object.entries(optValidators))\n        checkField(fieldName, type, true);\n    return object;\n}\n// validate type tests\n// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 };\n// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok!\n// // Should fail type-check\n// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' });\n// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' });\n// const z3 = validateObject(o, { test: 'boolean', z: 'bug' });\n// const z4 = validateObject(o, { a: 'boolean', z: 'bug' });\n//# sourceMappingURL=utils.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQG5vYmxlL2N1cnZlcy9lc20vYWJzdHJhY3QvdXRpbHMuanMuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9Abm9ibGUvY3VydmVzL2VzbS9hYnN0cmFjdC91dGlscy5qcz8yOTNhIl0sInNvdXJjZXNDb250ZW50IjpbIi8qISBub2JsZS1jdXJ2ZXMgLSBNSVQgTGljZW5zZSAoYykgMjAyMiBQYXVsIE1pbGxlciAocGF1bG1pbGxyLmNvbSkgKi9cbmNvbnN0IF8wbiA9IEJpZ0ludCgwKTtcbmNvbnN0IF8xbiA9IEJpZ0ludCgxKTtcbmNvbnN0IF8ybiA9IEJpZ0ludCgyKTtcbmNvbnN0IHU4YSA9IChhKSA9PiBhIGluc3RhbmNlb2YgVWludDhBcnJheTtcbmNvbnN0IGhleGVzID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogMjU2IH0sICh2LCBpKSA9PiBpLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCAnMCcpKTtcbmV4cG9ydCBmdW5jdGlvbiBieXRlc1RvSGV4KGJ5dGVzKSB7XG4gICAgaWYgKCF1OGEoYnl0ZXMpKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VpbnQ4QXJyYXkgZXhwZWN0ZWQnKTtcbiAgICAvLyBwcmUtY2FjaGluZyBpbXByb3ZlcyB0aGUgc3BlZWQgNnhcbiAgICBsZXQgaGV4ID0gJyc7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBoZXggKz0gaGV4ZXNbYnl0ZXNbaV1dO1xuICAgIH1cbiAgICByZXR1cm4gaGV4O1xufVxuZXhwb3J0IGZ1bmN0aW9uIG51bWJlclRvSGV4VW5wYWRkZWQobnVtKSB7XG4gICAgY29uc3QgaGV4ID0gbnVtLnRvU3RyaW5nKDE2KTtcbiAgICByZXR1cm4gaGV4Lmxlbmd0aCAmIDEgPyBgMCR7aGV4fWAgOiBoZXg7XG59XG5leHBvcnQgZnVuY3Rpb24gaGV4VG9OdW1iZXIoaGV4KSB7XG4gICAgaWYgKHR5cGVvZiBoZXggIT09ICdzdHJpbmcnKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2hleCBzdHJpbmcgZXhwZWN0ZWQsIGdvdCAnICsgdHlwZW9mIGhleCk7XG4gICAgLy8gQmlnIEVuZGlhblxuICAgIHJldHVybiBCaWdJbnQoaGV4ID09PSAnJyA/ICcwJyA6IGAweCR7aGV4fWApO1xufVxuLy8gQ2FjaGluZyBzbG93cyBpdCBkb3duIDItM3hcbmV4cG9ydCBmdW5jdGlvbiBoZXhUb0J5dGVzKGhleCkge1xuICAgIGlmICh0eXBlb2YgaGV4ICE9PSAnc3RyaW5nJylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdoZXggc3RyaW5nIGV4cGVjdGVkLCBnb3QgJyArIHR5cGVvZiBoZXgpO1xuICAgIGlmIChoZXgubGVuZ3RoICUgMilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdoZXggc3RyaW5nIGlzIGludmFsaWQ6IHVucGFkZGVkICcgKyBoZXgubGVuZ3RoKTtcbiAgICBjb25zdCBhcnJheSA9IG5ldyBVaW50OEFycmF5KGhleC5sZW5ndGggLyAyKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGogPSBpICogMjtcbiAgICAgICAgY29uc3QgaGV4Qnl0ZSA9IGhleC5zbGljZShqLCBqICsgMik7XG4gICAgICAgIGNvbnN0IGJ5dGUgPSBOdW1iZXIucGFyc2VJbnQoaGV4Qnl0ZSwgMTYpO1xuICAgICAgICBpZiAoTnVtYmVyLmlzTmFOKGJ5dGUpIHx8IGJ5dGUgPCAwKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGJ5dGUgc2VxdWVuY2UnKTtcbiAgICAgICAgYXJyYXlbaV0gPSBieXRlO1xuICAgIH1cbiAgICByZXR1cm4gYXJyYXk7XG59XG4vLyBCaWcgRW5kaWFuXG5leHBvcnQgZnVuY3Rpb24gYnl0ZXNUb051bWJlckJFKGJ5dGVzKSB7XG4gICAgcmV0dXJuIGhleFRvTnVtYmVyKGJ5dGVzVG9IZXgoYnl0ZXMpKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBieXRlc1RvTnVtYmVyTEUoYnl0ZXMpIHtcbiAgICBpZiAoIXU4YShieXRlcykpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVWludDhBcnJheSBleHBlY3RlZCcpO1xuICAgIHJldHVybiBoZXhUb051bWJlcihieXRlc1RvSGV4KFVpbnQ4QXJyYXkuZnJvbShieXRlcykucmV2ZXJzZSgpKSk7XG59XG5leHBvcnQgY29uc3QgbnVtYmVyVG9CeXRlc0JFID0gKG4sIGxlbikgPT4gaGV4VG9CeXRlcyhuLnRvU3RyaW5nKDE2KS5wYWRTdGFydChsZW4gKiAyLCAnMCcpKTtcbmV4cG9ydCBjb25zdCBudW1iZXJUb0J5dGVzTEUgPSAobiwgbGVuKSA9PiBudW1iZXJUb0J5dGVzQkUobiwgbGVuKS5yZXZlcnNlKCk7XG4vLyBSZXR1cm5zIHZhcmlhYmxlIG51bWJlciBieXRlcyAobWluaW1hbCBiaWdpbnQgZW5jb2Rpbmc/KVxuZXhwb3J0IGNvbnN0IG51bWJlclRvVmFyQnl0ZXNCRSA9IChuKSA9PiBoZXhUb0J5dGVzKG51bWJlclRvSGV4VW5wYWRkZWQobikpO1xuZXhwb3J0IGZ1bmN0aW9uIGVuc3VyZUJ5dGVzKHRpdGxlLCBoZXgsIGV4cGVjdGVkTGVuZ3RoKSB7XG4gICAgbGV0IHJlcztcbiAgICBpZiAodHlwZW9mIGhleCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJlcyA9IGhleFRvQnl0ZXMoaGV4KTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3RpdGxlfSBtdXN0IGJlIHZhbGlkIGhleCBzdHJpbmcsIGdvdCBcIiR7aGV4fVwiLiBDYXVzZTogJHtlfWApO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKHU4YShoZXgpKSB7XG4gICAgICAgIC8vIFVpbnQ4QXJyYXkuZnJvbSgpIGluc3RlYWQgb2YgaGFzaC5zbGljZSgpIGJlY2F1c2Ugbm9kZS5qcyBCdWZmZXJcbiAgICAgICAgLy8gaXMgaW5zdGFuY2Ugb2YgVWludDhBcnJheSwgYW5kIGl0cyBzbGljZSgpIGNyZWF0ZXMgKiptdXRhYmxlKiogY29weVxuICAgICAgICByZXMgPSBVaW50OEFycmF5LmZyb20oaGV4KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0aXRsZX0gbXVzdCBiZSBoZXggc3RyaW5nIG9yIFVpbnQ4QXJyYXlgKTtcbiAgICB9XG4gICAgY29uc3QgbGVuID0gcmVzLmxlbmd0aDtcbiAgICBpZiAodHlwZW9mIGV4cGVjdGVkTGVuZ3RoID09PSAnbnVtYmVyJyAmJiBsZW4gIT09IGV4cGVjdGVkTGVuZ3RoKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7dGl0bGV9IGV4cGVjdGVkICR7ZXhwZWN0ZWRMZW5ndGh9IGJ5dGVzLCBnb3QgJHtsZW59YCk7XG4gICAgcmV0dXJuIHJlcztcbn1cbi8vIENvcGllcyBzZXZlcmFsIFVpbnQ4QXJyYXlzIGludG8gb25lLlxuZXhwb3J0IGZ1bmN0aW9uIGNvbmNhdEJ5dGVzKC4uLmFycnMpIHtcbiAgICBjb25zdCByID0gbmV3IFVpbnQ4QXJyYXkoYXJycy5yZWR1Y2UoKHN1bSwgYSkgPT4gc3VtICsgYS5sZW5ndGgsIDApKTtcbiAgICBsZXQgcGFkID0gMDsgLy8gd2FsayB0aHJvdWdoIGVhY2ggaXRlbSwgZW5zdXJlIHRoZXkgaGF2ZSBwcm9wZXIgdHlwZVxuICAgIGFycnMuZm9yRWFjaCgoYSkgPT4ge1xuICAgICAgICBpZiAoIXU4YShhKSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVWludDhBcnJheSBleHBlY3RlZCcpO1xuICAgICAgICByLnNldChhLCBwYWQpO1xuICAgICAgICBwYWQgKz0gYS5sZW5ndGg7XG4gICAgfSk7XG4gICAgcmV0dXJuIHI7XG59XG5leHBvcnQgZnVuY3Rpb24gZXF1YWxCeXRlcyhiMSwgYjIpIHtcbiAgICAvLyBXZSBkb24ndCBjYXJlIGFib3V0IHRpbWluZyBhdHRhY2tzIGhlcmVcbiAgICBpZiAoYjEubGVuZ3RoICE9PSBiMi5sZW5ndGgpXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGIxLmxlbmd0aDsgaSsrKVxuICAgICAgICBpZiAoYjFbaV0gIT09IGIyW2ldKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiB0cnVlO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHV0ZjhUb0J5dGVzKHN0cikge1xuICAgIGlmICh0eXBlb2Ygc3RyICE9PSAnc3RyaW5nJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHV0ZjhUb0J5dGVzIGV4cGVjdGVkIHN0cmluZywgZ290ICR7dHlwZW9mIHN0cn1gKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzdHIpO1xufVxuLy8gQml0IG9wZXJhdGlvbnNcbi8vIEFtb3VudCBvZiBiaXRzIGluc2lkZSBiaWdpbnQgKFNhbWUgYXMgbi50b1N0cmluZygyKS5sZW5ndGgpXG5leHBvcnQgZnVuY3Rpb24gYml0TGVuKG4pIHtcbiAgICBsZXQgbGVuO1xuICAgIGZvciAobGVuID0gMDsgbiA+IF8wbjsgbiA+Pj0gXzFuLCBsZW4gKz0gMSlcbiAgICAgICAgO1xuICAgIHJldHVybiBsZW47XG59XG4vLyBHZXRzIHNpbmdsZSBiaXQgYXQgcG9zaXRpb24uIE5PVEU6IGZpcnN0IGJpdCBwb3NpdGlvbiBpcyAwIChzYW1lIGFzIGFycmF5cylcbi8vIFNhbWUgYXMgISErQXJyYXkuZnJvbShuLnRvU3RyaW5nKDIpKS5yZXZlcnNlKClbcG9zXVxuZXhwb3J0IGNvbnN0IGJpdEdldCA9IChuLCBwb3MpID0+IChuID4+IEJpZ0ludChwb3MpKSAmIF8xbjtcbi8vIFNldHMgc2luZ2xlIGJpdCBhdCBwb3NpdGlvblxuZXhwb3J0IGNvbnN0IGJpdFNldCA9IChuLCBwb3MsIHZhbHVlKSA9PiBuIHwgKCh2YWx1ZSA/IF8xbiA6IF8wbikgPDwgQmlnSW50KHBvcykpO1xuLy8gUmV0dXJuIG1hc2sgZm9yIE4gYml0cyAoU2FtZSBhcyBCaWdJbnQoYDBiJHtBcnJheShpKS5maWxsKCcxJykuam9pbignJyl9YCkpXG4vLyBOb3QgdXNpbmcgKiogb3BlcmF0b3Igd2l0aCBiaWdpbnRzIGZvciBvbGQgZW5naW5lcy5cbmV4cG9ydCBjb25zdCBiaXRNYXNrID0gKG4pID0+IChfMm4gPDwgQmlnSW50KG4gLSAxKSkgLSBfMW47XG4vLyBEUkJHXG5jb25zdCB1OG4gPSAoZGF0YSkgPT4gbmV3IFVpbnQ4QXJyYXkoZGF0YSk7IC8vIGNyZWF0ZXMgVWludDhBcnJheVxuY29uc3QgdThmciA9IChhcnIpID0+IFVpbnQ4QXJyYXkuZnJvbShhcnIpOyAvLyBhbm90aGVyIHNob3J0Y3V0XG4vKipcbiAqIE1pbmltYWwgSE1BQy1EUkJHIGZyb20gTklTVCA4MDAtOTAgZm9yIFJGQzY5Nzkgc2lncy5cbiAqIEByZXR1cm5zIGZ1bmN0aW9uIHRoYXQgd2lsbCBjYWxsIERSQkcgdW50aWwgMm5kIGFyZyByZXR1cm5zIHNvbWV0aGluZyBtZWFuaW5nZnVsXG4gKiBAZXhhbXBsZVxuICogICBjb25zdCBkcmJnID0gY3JlYXRlSG1hY0RSQkc8S2V5PigzMiwgMzIsIGhtYWMpO1xuICogICBkcmJnKHNlZWQsIGJ5dGVzVG9LZXkpOyAvLyBieXRlc1RvS2V5IG11c3QgcmV0dXJuIEtleSBvciB1bmRlZmluZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUhtYWNEcmJnKGhhc2hMZW4sIHFCeXRlTGVuLCBobWFjRm4pIHtcbiAgICBpZiAodHlwZW9mIGhhc2hMZW4gIT09ICdudW1iZXInIHx8IGhhc2hMZW4gPCAyKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2hhc2hMZW4gbXVzdCBiZSBhIG51bWJlcicpO1xuICAgIGlmICh0eXBlb2YgcUJ5dGVMZW4gIT09ICdudW1iZXInIHx8IHFCeXRlTGVuIDwgMilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdxQnl0ZUxlbiBtdXN0IGJlIGEgbnVtYmVyJyk7XG4gICAgaWYgKHR5cGVvZiBobWFjRm4gIT09ICdmdW5jdGlvbicpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaG1hY0ZuIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgIC8vIFN0ZXAgQiwgU3RlcCBDOiBzZXQgaGFzaExlbiB0byA4KmNlaWwoaGxlbi84KVxuICAgIGxldCB2ID0gdThuKGhhc2hMZW4pOyAvLyBNaW5pbWFsIG5vbi1mdWxsLXNwZWMgSE1BQy1EUkJHIGZyb20gTklTVCA4MDAtOTAgZm9yIFJGQzY5Nzkgc2lncy5cbiAgICBsZXQgayA9IHU4bihoYXNoTGVuKTsgLy8gU3RlcHMgQiBhbmQgQyBvZiBSRkM2OTc5IDMuMjogc2V0IGhhc2hMZW4sIGluIG91ciBjYXNlIGFsd2F5cyBzYW1lXG4gICAgbGV0IGkgPSAwOyAvLyBJdGVyYXRpb25zIGNvdW50ZXIsIHdpbGwgdGhyb3cgd2hlbiBvdmVyIDEwMDBcbiAgICBjb25zdCByZXNldCA9ICgpID0+IHtcbiAgICAgICAgdi5maWxsKDEpO1xuICAgICAgICBrLmZpbGwoMCk7XG4gICAgICAgIGkgPSAwO1xuICAgIH07XG4gICAgY29uc3QgaCA9ICguLi5iKSA9PiBobWFjRm4oaywgdiwgLi4uYik7IC8vIGhtYWMoaykodiwgLi4udmFsdWVzKVxuICAgIGNvbnN0IHJlc2VlZCA9IChzZWVkID0gdThuKCkpID0+IHtcbiAgICAgICAgLy8gSE1BQy1EUkJHIHJlc2VlZCgpIGZ1bmN0aW9uLiBTdGVwcyBELUdcbiAgICAgICAgayA9IGgodThmcihbMHgwMF0pLCBzZWVkKTsgLy8gayA9IGhtYWMoayB8fCB2IHx8IDB4MDAgfHwgc2VlZClcbiAgICAgICAgdiA9IGgoKTsgLy8gdiA9IGhtYWMoayB8fCB2KVxuICAgICAgICBpZiAoc2VlZC5sZW5ndGggPT09IDApXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGsgPSBoKHU4ZnIoWzB4MDFdKSwgc2VlZCk7IC8vIGsgPSBobWFjKGsgfHwgdiB8fCAweDAxIHx8IHNlZWQpXG4gICAgICAgIHYgPSBoKCk7IC8vIHYgPSBobWFjKGsgfHwgdilcbiAgICB9O1xuICAgIGNvbnN0IGdlbiA9ICgpID0+IHtcbiAgICAgICAgLy8gSE1BQy1EUkJHIGdlbmVyYXRlKCkgZnVuY3Rpb25cbiAgICAgICAgaWYgKGkrKyA+PSAxMDAwKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkcmJnOiB0cmllZCAxMDAwIHZhbHVlcycpO1xuICAgICAgICBsZXQgbGVuID0gMDtcbiAgICAgICAgY29uc3Qgb3V0ID0gW107XG4gICAgICAgIHdoaWxlIChsZW4gPCBxQnl0ZUxlbikge1xuICAgICAgICAgICAgdiA9IGgoKTtcbiAgICAgICAgICAgIGNvbnN0IHNsID0gdi5zbGljZSgpO1xuICAgICAgICAgICAgb3V0LnB1c2goc2wpO1xuICAgICAgICAgICAgbGVuICs9IHYubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb25jYXRCeXRlcyguLi5vdXQpO1xuICAgIH07XG4gICAgY29uc3QgZ2VuVW50aWwgPSAoc2VlZCwgcHJlZCkgPT4ge1xuICAgICAgICByZXNldCgpO1xuICAgICAgICByZXNlZWQoc2VlZCk7IC8vIFN0ZXBzIEQtR1xuICAgICAgICBsZXQgcmVzID0gdW5kZWZpbmVkOyAvLyBTdGVwIEg6IGdyaW5kIHVudGlsIGsgaXMgaW4gWzEuLm4tMV1cbiAgICAgICAgd2hpbGUgKCEocmVzID0gcHJlZChnZW4oKSkpKVxuICAgICAgICAgICAgcmVzZWVkKCk7XG4gICAgICAgIHJlc2V0KCk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICByZXR1cm4gZ2VuVW50aWw7XG59XG4vLyBWYWxpZGF0aW5nIGN1cnZlcyBhbmQgZmllbGRzXG5jb25zdCB2YWxpZGF0b3JGbnMgPSB7XG4gICAgYmlnaW50OiAodmFsKSA9PiB0eXBlb2YgdmFsID09PSAnYmlnaW50JyxcbiAgICBmdW5jdGlvbjogKHZhbCkgPT4gdHlwZW9mIHZhbCA9PT0gJ2Z1bmN0aW9uJyxcbiAgICBib29sZWFuOiAodmFsKSA9PiB0eXBlb2YgdmFsID09PSAnYm9vbGVhbicsXG4gICAgc3RyaW5nOiAodmFsKSA9PiB0eXBlb2YgdmFsID09PSAnc3RyaW5nJyxcbiAgICBpc1NhZmVJbnRlZ2VyOiAodmFsKSA9PiBOdW1iZXIuaXNTYWZlSW50ZWdlcih2YWwpLFxuICAgIGFycmF5OiAodmFsKSA9PiBBcnJheS5pc0FycmF5KHZhbCksXG4gICAgZmllbGQ6ICh2YWwsIG9iamVjdCkgPT4gb2JqZWN0LkZwLmlzVmFsaWQodmFsKSxcbiAgICBoYXNoOiAodmFsKSA9PiB0eXBlb2YgdmFsID09PSAnZnVuY3Rpb24nICYmIE51bWJlci5pc1NhZmVJbnRlZ2VyKHZhbC5vdXRwdXRMZW4pLFxufTtcbi8vIHR5cGUgUmVjb3JkPEsgZXh0ZW5kcyBzdHJpbmcgfCBudW1iZXIgfCBzeW1ib2wsIFQ+ID0geyBbUCBpbiBLXTogVDsgfVxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlT2JqZWN0KG9iamVjdCwgdmFsaWRhdG9ycywgb3B0VmFsaWRhdG9ycyA9IHt9KSB7XG4gICAgY29uc3QgY2hlY2tGaWVsZCA9IChmaWVsZE5hbWUsIHR5cGUsIGlzT3B0aW9uYWwpID0+IHtcbiAgICAgICAgY29uc3QgY2hlY2tWYWwgPSB2YWxpZGF0b3JGbnNbdHlwZV07XG4gICAgICAgIGlmICh0eXBlb2YgY2hlY2tWYWwgIT09ICdmdW5jdGlvbicpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgdmFsaWRhdG9yIFwiJHt0eXBlfVwiLCBleHBlY3RlZCBmdW5jdGlvbmApO1xuICAgICAgICBjb25zdCB2YWwgPSBvYmplY3RbZmllbGROYW1lXTtcbiAgICAgICAgaWYgKGlzT3B0aW9uYWwgJiYgdmFsID09PSB1bmRlZmluZWQpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGlmICghY2hlY2tWYWwodmFsLCBvYmplY3QpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcGFyYW0gJHtTdHJpbmcoZmllbGROYW1lKX09JHt2YWx9ICgke3R5cGVvZiB2YWx9KSwgZXhwZWN0ZWQgJHt0eXBlfWApO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBmb3IgKGNvbnN0IFtmaWVsZE5hbWUsIHR5cGVdIG9mIE9iamVjdC5lbnRyaWVzKHZhbGlkYXRvcnMpKVxuICAgICAgICBjaGVja0ZpZWxkKGZpZWxkTmFtZSwgdHlwZSwgZmFsc2UpO1xuICAgIGZvciAoY29uc3QgW2ZpZWxkTmFtZSwgdHlwZV0gb2YgT2JqZWN0LmVudHJpZXMob3B0VmFsaWRhdG9ycykpXG4gICAgICAgIGNoZWNrRmllbGQoZmllbGROYW1lLCB0eXBlLCB0cnVlKTtcbiAgICByZXR1cm4gb2JqZWN0O1xufVxuLy8gdmFsaWRhdGUgdHlwZSB0ZXN0c1xuLy8gY29uc3QgbzogeyBhOiBudW1iZXI7IGI6IG51bWJlcjsgYzogbnVtYmVyIH0gPSB7IGE6IDEsIGI6IDUsIGM6IDYgfTtcbi8vIGNvbnN0IHowID0gdmFsaWRhdGVPYmplY3QobywgeyBhOiAnaXNTYWZlSW50ZWdlcicgfSwgeyBjOiAnYmlnaW50JyB9KTsgLy8gT2shXG4vLyAvLyBTaG91bGQgZmFpbCB0eXBlLWNoZWNrXG4vLyBjb25zdCB6MSA9IHZhbGlkYXRlT2JqZWN0KG8sIHsgYTogJ3RtcCcgfSwgeyBjOiAnenonIH0pO1xuLy8gY29uc3QgejIgPSB2YWxpZGF0ZU9iamVjdChvLCB7IGE6ICdpc1NhZmVJbnRlZ2VyJyB9LCB7IGM6ICd6eicgfSk7XG4vLyBjb25zdCB6MyA9IHZhbGlkYXRlT2JqZWN0KG8sIHsgdGVzdDogJ2Jvb2xlYW4nLCB6OiAnYnVnJyB9KTtcbi8vIGNvbnN0IHo0ID0gdmFsaWRhdGVPYmplY3QobywgeyBhOiAnYm9vbGVhbicsIHo6ICdidWcnIH0pO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dXRpbHMuanMubWFwIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/@noble/curves/esm/abstract/utils.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/@noble/curves/esm/ed448.js":
+/*!*************************************************!*\
+  !*** ./node_modules/@noble/curves/esm/ed448.js ***!
+  \*************************************************/
+/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   ed448: () => (/* binding */ ed448),\n/* harmony export */   ed448ph: () => (/* binding */ ed448ph),\n/* harmony export */   edwardsToMontgomery: () => (/* binding */ edwardsToMontgomery),\n/* harmony export */   encodeToCurve: () => (/* binding */ encodeToCurve),\n/* harmony export */   hashToCurve: () => (/* binding */ hashToCurve),\n/* harmony export */   x448: () => (/* binding */ x448)\n/* harmony export */ });\n/* harmony import */ var _noble_hashes_sha3__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @noble/hashes/sha3 */ \"./node_modules/@noble/hashes/esm/sha3.js\");\n/* harmony import */ var _noble_hashes_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @noble/hashes/utils */ \"./node_modules/@noble/hashes/esm/utils.js\");\n/* harmony import */ var _abstract_edwards_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./abstract/edwards.js */ \"./node_modules/@noble/curves/esm/abstract/edwards.js\");\n/* harmony import */ var _abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./abstract/modular.js */ \"./node_modules/@noble/curves/esm/abstract/modular.js\");\n/* harmony import */ var _abstract_montgomery_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./abstract/montgomery.js */ \"./node_modules/@noble/curves/esm/abstract/montgomery.js\");\n/* harmony import */ var _abstract_hash_to_curve_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./abstract/hash-to-curve.js */ \"./node_modules/@noble/curves/esm/abstract/hash-to-curve.js\");\n/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n\n\n\n\n\n\n/**\n * Edwards448 (not Ed448-Goldilocks) curve with following addons:\n * * X448 ECDH\n * Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2\n */\nconst shake256_114 = (0,_noble_hashes_utils__WEBPACK_IMPORTED_MODULE_1__.wrapConstructor)(() => _noble_hashes_sha3__WEBPACK_IMPORTED_MODULE_0__.shake256.create({ dkLen: 114 }));\nconst shake256_64 = (0,_noble_hashes_utils__WEBPACK_IMPORTED_MODULE_1__.wrapConstructor)(() => _noble_hashes_sha3__WEBPACK_IMPORTED_MODULE_0__.shake256.create({ dkLen: 64 }));\nconst ed448P = BigInt('726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439');\n// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4.\n// Used for efficient square root calculation.\n// ((P-3)/4).toString(2) would produce bits [223x 1, 0, 222x 1]\nfunction ed448_pow_Pminus3div4(x) {\n    const P = ed448P;\n    // prettier-ignore\n    const _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _11n = BigInt(11);\n    // prettier-ignore\n    const _22n = BigInt(22), _44n = BigInt(44), _88n = BigInt(88), _223n = BigInt(223);\n    const b2 = (x * x * x) % P;\n    const b3 = (b2 * b2 * x) % P;\n    const b6 = ((0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.pow2)(b3, _3n, P) * b3) % P;\n    const b9 = ((0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.pow2)(b6, _3n, P) * b3) % P;\n    const b11 = ((0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.pow2)(b9, _2n, P) * b2) % P;\n    const b22 = ((0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.pow2)(b11, _11n, P) * b11) % P;\n    const b44 = ((0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.pow2)(b22, _22n, P) * b22) % P;\n    const b88 = ((0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.pow2)(b44, _44n, P) * b44) % P;\n    const b176 = ((0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.pow2)(b88, _88n, P) * b88) % P;\n    const b220 = ((0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.pow2)(b176, _44n, P) * b44) % P;\n    const b222 = ((0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.pow2)(b220, _2n, P) * b2) % P;\n    const b223 = ((0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.pow2)(b222, _1n, P) * x) % P;\n    return ((0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.pow2)(b223, _223n, P) * b222) % P;\n}\nfunction adjustScalarBytes(bytes) {\n    // Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0, and the most\n    // significant bit of the last byte to 1.\n    bytes[0] &= 252; // 0b11111100\n    // and the most significant bit of the last byte to 1.\n    bytes[55] |= 128; // 0b10000000\n    // NOTE: is is NOOP for 56 bytes scalars (X25519/X448)\n    bytes[56] = 0; // Byte outside of group (456 buts vs 448 bits)\n    return bytes;\n}\nconst Fp = (0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.Field)(ed448P, 456, true);\nconst _4n = BigInt(4);\nconst ED448_DEF = {\n    // Param: a\n    a: BigInt(1),\n    // -39081. Negative number is P - number\n    d: BigInt('726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358'),\n    // Finite field 𝔽p over which we'll do calculations; 2n ** 448n - 2n ** 224n - 1n\n    Fp,\n    // Subgroup order: how many points curve has;\n    // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n\n    n: BigInt('181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779'),\n    nBitLength: 456,\n    // Cofactor\n    h: BigInt(4),\n    // Base point (x, y) aka generator point\n    Gx: BigInt('224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710'),\n    Gy: BigInt('298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660'),\n    // SHAKE256(dom4(phflag,context)||x, 114)\n    hash: shake256_114,\n    randomBytes: _noble_hashes_utils__WEBPACK_IMPORTED_MODULE_1__.randomBytes,\n    adjustScalarBytes,\n    // dom4\n    domain: (data, ctx, phflag) => {\n        if (ctx.length > 255)\n            throw new Error(`Context is too big: ${ctx.length}`);\n        return (0,_noble_hashes_utils__WEBPACK_IMPORTED_MODULE_1__.concatBytes)((0,_noble_hashes_utils__WEBPACK_IMPORTED_MODULE_1__.utf8ToBytes)('SigEd448'), new Uint8Array([phflag ? 1 : 0, ctx.length]), ctx, data);\n    },\n    // Constant-time ratio of u to v. Allows to combine inversion and square root u/√v.\n    // Uses algo from RFC8032 5.1.3.\n    uvRatio: (u, v) => {\n        const P = ed448P;\n        // https://datatracker.ietf.org/doc/html/rfc8032#section-5.2.3\n        // To compute the square root of (u/v), the first step is to compute the\n        //   candidate root x = (u/v)^((p+1)/4).  This can be done using the\n        // following trick, to use a single modular powering for both the\n        // inversion of v and the square root:\n        // x = (u/v)^((p+1)/4)   = u³v(u⁵v³)^((p-3)/4)   (mod p)\n        const u2v = (0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.mod)(u * u * v, P); // u²v\n        const u3v = (0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.mod)(u2v * u, P); // u³v\n        const u5v3 = (0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.mod)(u3v * u2v * v, P); // u⁵v³\n        const root = ed448_pow_Pminus3div4(u5v3);\n        const x = (0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.mod)(u3v * root, P);\n        // Verify that root is exists\n        const x2 = (0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.mod)(x * x, P); // x²\n        // If vx² = u, the recovered x-coordinate is x.  Otherwise, no\n        // square root exists, and the decoding fails.\n        return { isValid: (0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.mod)(x2 * v, P) === u, value: x };\n    },\n};\nconst ed448 = (0,_abstract_edwards_js__WEBPACK_IMPORTED_MODULE_2__.twistedEdwards)(ED448_DEF);\n// NOTE: there is no ed448ctx, since ed448 supports ctx by default\nconst ed448ph = (0,_abstract_edwards_js__WEBPACK_IMPORTED_MODULE_2__.twistedEdwards)({ ...ED448_DEF, prehash: shake256_64 });\nconst x448 = (0,_abstract_montgomery_js__WEBPACK_IMPORTED_MODULE_4__.montgomery)({\n    a: BigInt(156326),\n    montgomeryBits: 448,\n    nByteLength: 57,\n    P: ed448P,\n    Gu: BigInt(5),\n    powPminus2: (x) => {\n        const P = ed448P;\n        const Pminus3div4 = ed448_pow_Pminus3div4(x);\n        const Pminus3 = (0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.pow2)(Pminus3div4, BigInt(2), P);\n        return (0,_abstract_modular_js__WEBPACK_IMPORTED_MODULE_3__.mod)(Pminus3 * x, P); // Pminus3 * x = Pminus2\n    },\n    adjustScalarBytes,\n    randomBytes: _noble_hashes_utils__WEBPACK_IMPORTED_MODULE_1__.randomBytes,\n});\n/**\n * Converts edwards448 public key to x448 public key. Uses formula:\n * * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)`\n * * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))`\n * @example\n *   const aPub = ed448.getPublicKey(utils.randomPrivateKey());\n *   x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub))\n */\nfunction edwardsToMontgomery(edwardsPub) {\n    const { y } = ed448.ExtendedPoint.fromHex(edwardsPub);\n    const _1n = BigInt(1);\n    return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n)));\n}\n// Hash To Curve Elligator2 Map\nconst ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4         # Integer arithmetic\nconst ELL2_J = BigInt(156326);\nfunction map_to_curve_elligator2_curve448(u) {\n    let tv1 = Fp.sqr(u); // 1.  tv1 = u^2\n    let e1 = Fp.eql(tv1, Fp.ONE); // 2.   e1 = tv1 == 1\n    tv1 = Fp.cmov(tv1, Fp.ZERO, e1); // 3.  tv1 = CMOV(tv1, 0, e1)  # If Z * u^2 == -1, set tv1 = 0\n    let xd = Fp.sub(Fp.ONE, tv1); // 4.   xd = 1 - tv1\n    let x1n = Fp.neg(ELL2_J); // 5.  x1n = -J\n    let tv2 = Fp.sqr(xd); // 6.  tv2 = xd^2\n    let gxd = Fp.mul(tv2, xd); // 7.  gxd = tv2 * xd          # gxd = xd^3\n    let gx1 = Fp.mul(tv1, Fp.neg(ELL2_J)); // 8.  gx1 = -J * tv1          # x1n + J * xd\n    gx1 = Fp.mul(gx1, x1n); // 9.  gx1 = gx1 * x1n         # x1n^2 + J * x1n * xd\n    gx1 = Fp.add(gx1, tv2); // 10. gx1 = gx1 + tv2         # x1n^2 + J * x1n * xd + xd^2\n    gx1 = Fp.mul(gx1, x1n); // 11. gx1 = gx1 * x1n         # x1n^3 + J * x1n^2 * xd + x1n * xd^2\n    let tv3 = Fp.sqr(gxd); // 12. tv3 = gxd^2\n    tv2 = Fp.mul(gx1, gxd); // 13. tv2 = gx1 * gxd         # gx1 * gxd\n    tv3 = Fp.mul(tv3, tv2); // 14. tv3 = tv3 * tv2         # gx1 * gxd^3\n    let y1 = Fp.pow(tv3, ELL2_C1); // 15.  y1 = tv3^c1            # (gx1 * gxd^3)^((p - 3) / 4)\n    y1 = Fp.mul(y1, tv2); // 16.  y1 = y1 * tv2          # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4)\n    let x2n = Fp.mul(x1n, Fp.neg(tv1)); // 17. x2n = -tv1 * x1n        # x2 = x2n / xd = -1 * u^2 * x1n / xd\n    let y2 = Fp.mul(y1, u); // 18.  y2 = y1 * u\n    y2 = Fp.cmov(y2, Fp.ZERO, e1); // 19.  y2 = CMOV(y2, 0, e1)\n    tv2 = Fp.sqr(y1); // 20. tv2 = y1^2\n    tv2 = Fp.mul(tv2, gxd); // 21. tv2 = tv2 * gxd\n    let e2 = Fp.eql(tv2, gx1); // 22.  e2 = tv2 == gx1\n    let xn = Fp.cmov(x2n, x1n, e2); // 23.  xn = CMOV(x2n, x1n, e2)  # If e2, x = x1, else x = x2\n    let y = Fp.cmov(y2, y1, e2); // 24.   y = CMOV(y2, y1, e2)    # If e2, y = y1, else y = y2\n    let e3 = Fp.isOdd(y); // 25.  e3 = sgn0(y) == 1        # Fix sign of y\n    y = Fp.cmov(y, Fp.neg(y), e2 !== e3); // 26.   y = CMOV(y, -y, e2 XOR e3)\n    return { xn, xd, yn: y, yd: Fp.ONE }; // 27. return (xn, xd, y, 1)\n}\nfunction map_to_curve_elligator2_edwards448(u) {\n    let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u); // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)\n    let xn2 = Fp.sqr(xn); // 2.  xn2 = xn^2\n    let xd2 = Fp.sqr(xd); // 3.  xd2 = xd^2\n    let xd4 = Fp.sqr(xd2); // 4.  xd4 = xd2^2\n    let yn2 = Fp.sqr(yn); // 5.  yn2 = yn^2\n    let yd2 = Fp.sqr(yd); // 6.  yd2 = yd^2\n    let xEn = Fp.sub(xn2, xd2); // 7.  xEn = xn2 - xd2\n    let tv2 = Fp.sub(xEn, xd2); // 8.  tv2 = xEn - xd2\n    xEn = Fp.mul(xEn, xd2); // 9.  xEn = xEn * xd2\n    xEn = Fp.mul(xEn, yd); // 10. xEn = xEn * yd\n    xEn = Fp.mul(xEn, yn); // 11. xEn = xEn * yn\n    xEn = Fp.mul(xEn, _4n); // 12. xEn = xEn * 4\n    tv2 = Fp.mul(tv2, xn2); // 13. tv2 = tv2 * xn2\n    tv2 = Fp.mul(tv2, yd2); // 14. tv2 = tv2 * yd2\n    let tv3 = Fp.mul(yn2, _4n); // 15. tv3 = 4 * yn2\n    let tv1 = Fp.add(tv3, yd2); // 16. tv1 = tv3 + yd2\n    tv1 = Fp.mul(tv1, xd4); // 17. tv1 = tv1 * xd4\n    let xEd = Fp.add(tv1, tv2); // 18. xEd = tv1 + tv2\n    tv2 = Fp.mul(tv2, xn); // 19. tv2 = tv2 * xn\n    let tv4 = Fp.mul(xn, xd4); // 20. tv4 = xn * xd4\n    let yEn = Fp.sub(tv3, yd2); // 21. yEn = tv3 - yd2\n    yEn = Fp.mul(yEn, tv4); // 22. yEn = yEn * tv4\n    yEn = Fp.sub(yEn, tv2); // 23. yEn = yEn - tv2\n    tv1 = Fp.add(xn2, xd2); // 24. tv1 = xn2 + xd2\n    tv1 = Fp.mul(tv1, xd2); // 25. tv1 = tv1 * xd2\n    tv1 = Fp.mul(tv1, xd); // 26. tv1 = tv1 * xd\n    tv1 = Fp.mul(tv1, yn2); // 27. tv1 = tv1 * yn2\n    tv1 = Fp.mul(tv1, BigInt(-2)); // 28. tv1 = -2 * tv1\n    let yEd = Fp.add(tv2, tv1); // 29. yEd = tv2 + tv1\n    tv4 = Fp.mul(tv4, yd2); // 30. tv4 = tv4 * yd2\n    yEd = Fp.add(yEd, tv4); // 31. yEd = yEd + tv4\n    tv1 = Fp.mul(xEd, yEd); // 32. tv1 = xEd * yEd\n    let e = Fp.eql(tv1, Fp.ZERO); // 33.   e = tv1 == 0\n    xEn = Fp.cmov(xEn, Fp.ZERO, e); // 34. xEn = CMOV(xEn, 0, e)\n    xEd = Fp.cmov(xEd, Fp.ONE, e); // 35. xEd = CMOV(xEd, 1, e)\n    yEn = Fp.cmov(yEn, Fp.ONE, e); // 36. yEn = CMOV(yEn, 1, e)\n    yEd = Fp.cmov(yEd, Fp.ONE, e); // 37. yEd = CMOV(yEd, 1, e)\n    const inv = Fp.invertBatch([xEd, yEd]); // batch division\n    return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) }; // 38. return (xEn, xEd, yEn, yEd)\n}\nconst { hashToCurve, encodeToCurve } = _abstract_hash_to_curve_js__WEBPACK_IMPORTED_MODULE_5__.createHasher(ed448.ExtendedPoint, (scalars) => map_to_curve_elligator2_edwards448(scalars[0]), {\n    DST: 'edwards448_XOF:SHAKE256_ELL2_RO_',\n    encodeDST: 'edwards448_XOF:SHAKE256_ELL2_NU_',\n    p: Fp.ORDER,\n    m: 1,\n    k: 224,\n    expand: 'xof',\n    hash: _noble_hashes_sha3__WEBPACK_IMPORTED_MODULE_0__.shake256,\n});\n\n//# sourceMappingURL=ed448.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQG5vYmxlL2N1cnZlcy9lc20vZWQ0NDguanMuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9jdXJ2ZXMvZXNtL2VkNDQ4LmpzPzFhMmEiXSwic291cmNlc0NvbnRlbnQiOlsiLyohIG5vYmxlLWN1cnZlcyAtIE1JVCBMaWNlbnNlIChjKSAyMDIyIFBhdWwgTWlsbGVyIChwYXVsbWlsbHIuY29tKSAqL1xuaW1wb3J0IHsgc2hha2UyNTYgfSBmcm9tICdAbm9ibGUvaGFzaGVzL3NoYTMnO1xuaW1wb3J0IHsgY29uY2F0Qnl0ZXMsIHJhbmRvbUJ5dGVzLCB1dGY4VG9CeXRlcywgd3JhcENvbnN0cnVjdG9yIH0gZnJvbSAnQG5vYmxlL2hhc2hlcy91dGlscyc7XG5pbXBvcnQgeyB0d2lzdGVkRWR3YXJkcyB9IGZyb20gJy4vYWJzdHJhY3QvZWR3YXJkcy5qcyc7XG5pbXBvcnQgeyBtb2QsIHBvdzIsIEZpZWxkIH0gZnJvbSAnLi9hYnN0cmFjdC9tb2R1bGFyLmpzJztcbmltcG9ydCB7IG1vbnRnb21lcnkgfSBmcm9tICcuL2Fic3RyYWN0L21vbnRnb21lcnkuanMnO1xuaW1wb3J0ICogYXMgaHRmIGZyb20gJy4vYWJzdHJhY3QvaGFzaC10by1jdXJ2ZS5qcyc7XG4vKipcbiAqIEVkd2FyZHM0NDggKG5vdCBFZDQ0OC1Hb2xkaWxvY2tzKSBjdXJ2ZSB3aXRoIGZvbGxvd2luZyBhZGRvbnM6XG4gKiAqIFg0NDggRUNESFxuICogQ29uZm9ybXMgdG8gUkZDIDgwMzIgaHR0cHM6Ly93d3cucmZjLWVkaXRvci5vcmcvcmZjL3JmYzgwMzIuaHRtbCNzZWN0aW9uLTUuMlxuICovXG5jb25zdCBzaGFrZTI1Nl8xMTQgPSB3cmFwQ29uc3RydWN0b3IoKCkgPT4gc2hha2UyNTYuY3JlYXRlKHsgZGtMZW46IDExNCB9KSk7XG5jb25zdCBzaGFrZTI1Nl82NCA9IHdyYXBDb25zdHJ1Y3RvcigoKSA9PiBzaGFrZTI1Ni5jcmVhdGUoeyBka0xlbjogNjQgfSkpO1xuY29uc3QgZWQ0NDhQID0gQmlnSW50KCc3MjY4Mzg3MjQyOTU2MDY4OTA1NDkzMjM4MDc4ODgwMDQ1MzQzNTM2NDEzNjA2ODczMTgwNjAyODE0OTAxOTkxODA2MTIzMjgxNjY3MzA3NzI2ODYzOTYzODM2OTg2NzY1NDU5MzAwODg4ODQ0NjE4NDM2MzczNjEwNTM0OTgwMTgzNjU0MzknKTtcbi8vIHBvd1BtaW51czNkaXY0IGNhbGN1bGF0ZXMgeiA9IHheayBtb2QgcCwgd2hlcmUgayA9IChwLTMpLzQuXG4vLyBVc2VkIGZvciBlZmZpY2llbnQgc3F1YXJlIHJvb3QgY2FsY3VsYXRpb24uXG4vLyAoKFAtMykvNCkudG9TdHJpbmcoMikgd291bGQgcHJvZHVjZSBiaXRzIFsyMjN4IDEsIDAsIDIyMnggMV1cbmZ1bmN0aW9uIGVkNDQ4X3Bvd19QbWludXMzZGl2NCh4KSB7XG4gICAgY29uc3QgUCA9IGVkNDQ4UDtcbiAgICAvLyBwcmV0dGllci1pZ25vcmVcbiAgICBjb25zdCBfMW4gPSBCaWdJbnQoMSksIF8ybiA9IEJpZ0ludCgyKSwgXzNuID0gQmlnSW50KDMpLCBfMTFuID0gQmlnSW50KDExKTtcbiAgICAvLyBwcmV0dGllci1pZ25vcmVcbiAgICBjb25zdCBfMjJuID0gQmlnSW50KDIyKSwgXzQ0biA9IEJpZ0ludCg0NCksIF84OG4gPSBCaWdJbnQoODgpLCBfMjIzbiA9IEJpZ0ludCgyMjMpO1xuICAgIGNvbnN0IGIyID0gKHggKiB4ICogeCkgJSBQO1xuICAgIGNvbnN0IGIzID0gKGIyICogYjIgKiB4KSAlIFA7XG4gICAgY29uc3QgYjYgPSAocG93MihiMywgXzNuLCBQKSAqIGIzKSAlIFA7XG4gICAgY29uc3QgYjkgPSAocG93MihiNiwgXzNuLCBQKSAqIGIzKSAlIFA7XG4gICAgY29uc3QgYjExID0gKHBvdzIoYjksIF8ybiwgUCkgKiBiMikgJSBQO1xuICAgIGNvbnN0IGIyMiA9IChwb3cyKGIxMSwgXzExbiwgUCkgKiBiMTEpICUgUDtcbiAgICBjb25zdCBiNDQgPSAocG93MihiMjIsIF8yMm4sIFApICogYjIyKSAlIFA7XG4gICAgY29uc3QgYjg4ID0gKHBvdzIoYjQ0LCBfNDRuLCBQKSAqIGI0NCkgJSBQO1xuICAgIGNvbnN0IGIxNzYgPSAocG93MihiODgsIF84OG4sIFApICogYjg4KSAlIFA7XG4gICAgY29uc3QgYjIyMCA9IChwb3cyKGIxNzYsIF80NG4sIFApICogYjQ0KSAlIFA7XG4gICAgY29uc3QgYjIyMiA9IChwb3cyKGIyMjAsIF8ybiwgUCkgKiBiMikgJSBQO1xuICAgIGNvbnN0IGIyMjMgPSAocG93MihiMjIyLCBfMW4sIFApICogeCkgJSBQO1xuICAgIHJldHVybiAocG93MihiMjIzLCBfMjIzbiwgUCkgKiBiMjIyKSAlIFA7XG59XG5mdW5jdGlvbiBhZGp1c3RTY2FsYXJCeXRlcyhieXRlcykge1xuICAgIC8vIFNlY3Rpb24gNTogTGlrZXdpc2UsIGZvciBYNDQ4LCBzZXQgdGhlIHR3byBsZWFzdCBzaWduaWZpY2FudCBiaXRzIG9mIHRoZSBmaXJzdCBieXRlIHRvIDAsIGFuZCB0aGUgbW9zdFxuICAgIC8vIHNpZ25pZmljYW50IGJpdCBvZiB0aGUgbGFzdCBieXRlIHRvIDEuXG4gICAgYnl0ZXNbMF0gJj0gMjUyOyAvLyAwYjExMTExMTAwXG4gICAgLy8gYW5kIHRoZSBtb3N0IHNpZ25pZmljYW50IGJpdCBvZiB0aGUgbGFzdCBieXRlIHRvIDEuXG4gICAgYnl0ZXNbNTVdIHw9IDEyODsgLy8gMGIxMDAwMDAwMFxuICAgIC8vIE5PVEU6IGlzIGlzIE5PT1AgZm9yIDU2IGJ5dGVzIHNjYWxhcnMgKFgyNTUxOS9YNDQ4KVxuICAgIGJ5dGVzWzU2XSA9IDA7IC8vIEJ5dGUgb3V0c2lkZSBvZiBncm91cCAoNDU2IGJ1dHMgdnMgNDQ4IGJpdHMpXG4gICAgcmV0dXJuIGJ5dGVzO1xufVxuY29uc3QgRnAgPSBGaWVsZChlZDQ0OFAsIDQ1NiwgdHJ1ZSk7XG5jb25zdCBfNG4gPSBCaWdJbnQoNCk7XG5jb25zdCBFRDQ0OF9ERUYgPSB7XG4gICAgLy8gUGFyYW06IGFcbiAgICBhOiBCaWdJbnQoMSksXG4gICAgLy8gLTM5MDgxLiBOZWdhdGl2ZSBudW1iZXIgaXMgUCAtIG51bWJlclxuICAgIGQ6IEJpZ0ludCgnNzI2ODM4NzI0Mjk1NjA2ODkwNTQ5MzIzODA3ODg4MDA0NTM0MzUzNjQxMzYwNjg3MzE4MDYwMjgxNDkwMTk5MTgwNjEyMzI4MTY2NzMwNzcyNjg2Mzk2MzgzNjk4Njc2NTQ1OTMwMDg4ODg0NDYxODQzNjM3MzYxMDUzNDk4MDE4MzI2MzU4JyksXG4gICAgLy8gRmluaXRlIGZpZWxkIPCdlL1wIG92ZXIgd2hpY2ggd2UnbGwgZG8gY2FsY3VsYXRpb25zOyAybiAqKiA0NDhuIC0gMm4gKiogMjI0biAtIDFuXG4gICAgRnAsXG4gICAgLy8gU3ViZ3JvdXAgb3JkZXI6IGhvdyBtYW55IHBvaW50cyBjdXJ2ZSBoYXM7XG4gICAgLy8gMm4qKjQ0Nm4gLSAxMzgxODA2NjgwOTg5NTExNTM1MjAwNzM4Njc0ODUxNTQyNjg4MDMzNjY5MjQ3NDg4MjE3ODYwOTg5NDU0NzUwMzg4NW5cbiAgICBuOiBCaWdJbnQoJzE4MTcwOTY4MTA3MzkwMTcyMjYzNzMzMDk1MTk3MjAwMTEzMzU4ODQxMDM0MDE3MTgyOTUxNTA3MDM3MjU0OTc5NTE0NjAwMzk2MTUzOTU4NTcxNjE5NTc1NTI5MTY5MjM3NTk2MzMxMDI5MzcwOTA5MTY2MjMwNDc3Mzc1NTg1OTY0OTc3OScpLFxuICAgIG5CaXRMZW5ndGg6IDQ1NixcbiAgICAvLyBDb2ZhY3RvclxuICAgIGg6IEJpZ0ludCg0KSxcbiAgICAvLyBCYXNlIHBvaW50ICh4LCB5KSBha2EgZ2VuZXJhdG9yIHBvaW50XG4gICAgR3g6IEJpZ0ludCgnMjI0NTgwMDQwMjk1OTI0MzAwMTg3NjA0MzM0MDk5ODk2MDM2MjQ2Nzg5NjQxNjMyNTY0MTM0MjQ2MTI1NDYxNjg2OTUwNDE1NDY3NDA2MDMyOTA5MDI5MTkyODY5MzU3OTUzMjgyNTc4MDMyMDc1MTQ2NDQ2MTczNjc0NjAyNjM1MjQ3NzEwJyksXG4gICAgR3k6IEJpZ0ludCgnMjk4ODE5MjEwMDc4NDgxNDkyNjc2MDE3OTMwNDQzOTMwNjczNDM3NTQ0MDQwMTU0MDgwMjQyMDk1OTI4MjQxMzcyMzMxNTA2MTg5ODM1ODc2MDAzNTM2ODc4NjU1NDE4Nzg0NzMzOTgyMzAzMjMzNTAzNDYyNTAwNTMxNTQ1MDYyODMyNjYwJyksXG4gICAgLy8gU0hBS0UyNTYoZG9tNChwaGZsYWcsY29udGV4dCl8fHgsIDExNClcbiAgICBoYXNoOiBzaGFrZTI1Nl8xMTQsXG4gICAgcmFuZG9tQnl0ZXMsXG4gICAgYWRqdXN0U2NhbGFyQnl0ZXMsXG4gICAgLy8gZG9tNFxuICAgIGRvbWFpbjogKGRhdGEsIGN0eCwgcGhmbGFnKSA9PiB7XG4gICAgICAgIGlmIChjdHgubGVuZ3RoID4gMjU1KVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb250ZXh0IGlzIHRvbyBiaWc6ICR7Y3R4Lmxlbmd0aH1gKTtcbiAgICAgICAgcmV0dXJuIGNvbmNhdEJ5dGVzKHV0ZjhUb0J5dGVzKCdTaWdFZDQ0OCcpLCBuZXcgVWludDhBcnJheShbcGhmbGFnID8gMSA6IDAsIGN0eC5sZW5ndGhdKSwgY3R4LCBkYXRhKTtcbiAgICB9LFxuICAgIC8vIENvbnN0YW50LXRpbWUgcmF0aW8gb2YgdSB0byB2LiBBbGxvd3MgdG8gY29tYmluZSBpbnZlcnNpb24gYW5kIHNxdWFyZSByb290IHUv4oiadi5cbiAgICAvLyBVc2VzIGFsZ28gZnJvbSBSRkM4MDMyIDUuMS4zLlxuICAgIHV2UmF0aW86ICh1LCB2KSA9PiB7XG4gICAgICAgIGNvbnN0IFAgPSBlZDQ0OFA7XG4gICAgICAgIC8vIGh0dHBzOi8vZGF0YXRyYWNrZXIuaWV0Zi5vcmcvZG9jL2h0bWwvcmZjODAzMiNzZWN0aW9uLTUuMi4zXG4gICAgICAgIC8vIFRvIGNvbXB1dGUgdGhlIHNxdWFyZSByb290IG9mICh1L3YpLCB0aGUgZmlyc3Qgc3RlcCBpcyB0byBjb21wdXRlIHRoZVxuICAgICAgICAvLyAgIGNhbmRpZGF0ZSByb290IHggPSAodS92KV4oKHArMSkvNCkuICBUaGlzIGNhbiBiZSBkb25lIHVzaW5nIHRoZVxuICAgICAgICAvLyBmb2xsb3dpbmcgdHJpY2ssIHRvIHVzZSBhIHNpbmdsZSBtb2R1bGFyIHBvd2VyaW5nIGZvciBib3RoIHRoZVxuICAgICAgICAvLyBpbnZlcnNpb24gb2YgdiBhbmQgdGhlIHNxdWFyZSByb290OlxuICAgICAgICAvLyB4ID0gKHUvdileKChwKzEpLzQpICAgPSB1wrN2KHXigbV2wrMpXigocC0zKS80KSAgIChtb2QgcClcbiAgICAgICAgY29uc3QgdTJ2ID0gbW9kKHUgKiB1ICogdiwgUCk7IC8vIHXCsnZcbiAgICAgICAgY29uc3QgdTN2ID0gbW9kKHUydiAqIHUsIFApOyAvLyB1wrN2XG4gICAgICAgIGNvbnN0IHU1djMgPSBtb2QodTN2ICogdTJ2ICogdiwgUCk7IC8vIHXigbV2wrNcbiAgICAgICAgY29uc3Qgcm9vdCA9IGVkNDQ4X3Bvd19QbWludXMzZGl2NCh1NXYzKTtcbiAgICAgICAgY29uc3QgeCA9IG1vZCh1M3YgKiByb290LCBQKTtcbiAgICAgICAgLy8gVmVyaWZ5IHRoYXQgcm9vdCBpcyBleGlzdHNcbiAgICAgICAgY29uc3QgeDIgPSBtb2QoeCAqIHgsIFApOyAvLyB4wrJcbiAgICAgICAgLy8gSWYgdnjCsiA9IHUsIHRoZSByZWNvdmVyZWQgeC1jb29yZGluYXRlIGlzIHguICBPdGhlcndpc2UsIG5vXG4gICAgICAgIC8vIHNxdWFyZSByb290IGV4aXN0cywgYW5kIHRoZSBkZWNvZGluZyBmYWlscy5cbiAgICAgICAgcmV0dXJuIHsgaXNWYWxpZDogbW9kKHgyICogdiwgUCkgPT09IHUsIHZhbHVlOiB4IH07XG4gICAgfSxcbn07XG5leHBvcnQgY29uc3QgZWQ0NDggPSB0d2lzdGVkRWR3YXJkcyhFRDQ0OF9ERUYpO1xuLy8gTk9URTogdGhlcmUgaXMgbm8gZWQ0NDhjdHgsIHNpbmNlIGVkNDQ4IHN1cHBvcnRzIGN0eCBieSBkZWZhdWx0XG5leHBvcnQgY29uc3QgZWQ0NDhwaCA9IHR3aXN0ZWRFZHdhcmRzKHsgLi4uRUQ0NDhfREVGLCBwcmVoYXNoOiBzaGFrZTI1Nl82NCB9KTtcbmV4cG9ydCBjb25zdCB4NDQ4ID0gbW9udGdvbWVyeSh7XG4gICAgYTogQmlnSW50KDE1NjMyNiksXG4gICAgbW9udGdvbWVyeUJpdHM6IDQ0OCxcbiAgICBuQnl0ZUxlbmd0aDogNTcsXG4gICAgUDogZWQ0NDhQLFxuICAgIEd1OiBCaWdJbnQoNSksXG4gICAgcG93UG1pbnVzMjogKHgpID0+IHtcbiAgICAgICAgY29uc3QgUCA9IGVkNDQ4UDtcbiAgICAgICAgY29uc3QgUG1pbnVzM2RpdjQgPSBlZDQ0OF9wb3dfUG1pbnVzM2RpdjQoeCk7XG4gICAgICAgIGNvbnN0IFBtaW51czMgPSBwb3cyKFBtaW51czNkaXY0LCBCaWdJbnQoMiksIFApO1xuICAgICAgICByZXR1cm4gbW9kKFBtaW51czMgKiB4LCBQKTsgLy8gUG1pbnVzMyAqIHggPSBQbWludXMyXG4gICAgfSxcbiAgICBhZGp1c3RTY2FsYXJCeXRlcyxcbiAgICByYW5kb21CeXRlcyxcbn0pO1xuLyoqXG4gKiBDb252ZXJ0cyBlZHdhcmRzNDQ4IHB1YmxpYyBrZXkgdG8geDQ0OCBwdWJsaWMga2V5LiBVc2VzIGZvcm11bGE6XG4gKiAqIGAodSwgdikgPSAoKHktMSkvKHkrMSksIHNxcnQoMTU2MzI0KSp1L3gpYFxuICogKiBgKHgsIHkpID0gKHNxcnQoMTU2MzI0KSp1L3YsICgxK3UpLygxLXUpKWBcbiAqIEBleGFtcGxlXG4gKiAgIGNvbnN0IGFQdWIgPSBlZDQ0OC5nZXRQdWJsaWNLZXkodXRpbHMucmFuZG9tUHJpdmF0ZUtleSgpKTtcbiAqICAgeDQ0OC5nZXRTaGFyZWRTZWNyZXQoZWR3YXJkc1RvTW9udGdvbWVyeShhUHViKSwgZWR3YXJkc1RvTW9udGdvbWVyeShzb21lb25lc1B1YikpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlZHdhcmRzVG9Nb250Z29tZXJ5KGVkd2FyZHNQdWIpIHtcbiAgICBjb25zdCB7IHkgfSA9IGVkNDQ4LkV4dGVuZGVkUG9pbnQuZnJvbUhleChlZHdhcmRzUHViKTtcbiAgICBjb25zdCBfMW4gPSBCaWdJbnQoMSk7XG4gICAgcmV0dXJuIEZwLnRvQnl0ZXMoRnAuY3JlYXRlKCh5IC0gXzFuKSAqIEZwLmludih5ICsgXzFuKSkpO1xufVxuLy8gSGFzaCBUbyBDdXJ2ZSBFbGxpZ2F0b3IyIE1hcFxuY29uc3QgRUxMMl9DMSA9IChGcC5PUkRFUiAtIEJpZ0ludCgzKSkgLyBCaWdJbnQoNCk7IC8vIDEuIGMxID0gKHEgLSAzKSAvIDQgICAgICAgICAjIEludGVnZXIgYXJpdGhtZXRpY1xuY29uc3QgRUxMMl9KID0gQmlnSW50KDE1NjMyNik7XG5mdW5jdGlvbiBtYXBfdG9fY3VydmVfZWxsaWdhdG9yMl9jdXJ2ZTQ0OCh1KSB7XG4gICAgbGV0IHR2MSA9IEZwLnNxcih1KTsgLy8gMS4gIHR2MSA9IHVeMlxuICAgIGxldCBlMSA9IEZwLmVxbCh0djEsIEZwLk9ORSk7IC8vIDIuICAgZTEgPSB0djEgPT0gMVxuICAgIHR2MSA9IEZwLmNtb3YodHYxLCBGcC5aRVJPLCBlMSk7IC8vIDMuICB0djEgPSBDTU9WKHR2MSwgMCwgZTEpICAjIElmIFogKiB1XjIgPT0gLTEsIHNldCB0djEgPSAwXG4gICAgbGV0IHhkID0gRnAuc3ViKEZwLk9ORSwgdHYxKTsgLy8gNC4gICB4ZCA9IDEgLSB0djFcbiAgICBsZXQgeDFuID0gRnAubmVnKEVMTDJfSik7IC8vIDUuICB4MW4gPSAtSlxuICAgIGxldCB0djIgPSBGcC5zcXIoeGQpOyAvLyA2LiAgdHYyID0geGReMlxuICAgIGxldCBneGQgPSBGcC5tdWwodHYyLCB4ZCk7IC8vIDcuICBneGQgPSB0djIgKiB4ZCAgICAgICAgICAjIGd4ZCA9IHhkXjNcbiAgICBsZXQgZ3gxID0gRnAubXVsKHR2MSwgRnAubmVnKEVMTDJfSikpOyAvLyA4LiAgZ3gxID0gLUogKiB0djEgICAgICAgICAgIyB4MW4gKyBKICogeGRcbiAgICBneDEgPSBGcC5tdWwoZ3gxLCB4MW4pOyAvLyA5LiAgZ3gxID0gZ3gxICogeDFuICAgICAgICAgIyB4MW5eMiArIEogKiB4MW4gKiB4ZFxuICAgIGd4MSA9IEZwLmFkZChneDEsIHR2Mik7IC8vIDEwLiBneDEgPSBneDEgKyB0djIgICAgICAgICAjIHgxbl4yICsgSiAqIHgxbiAqIHhkICsgeGReMlxuICAgIGd4MSA9IEZwLm11bChneDEsIHgxbik7IC8vIDExLiBneDEgPSBneDEgKiB4MW4gICAgICAgICAjIHgxbl4zICsgSiAqIHgxbl4yICogeGQgKyB4MW4gKiB4ZF4yXG4gICAgbGV0IHR2MyA9IEZwLnNxcihneGQpOyAvLyAxMi4gdHYzID0gZ3hkXjJcbiAgICB0djIgPSBGcC5tdWwoZ3gxLCBneGQpOyAvLyAxMy4gdHYyID0gZ3gxICogZ3hkICAgICAgICAgIyBneDEgKiBneGRcbiAgICB0djMgPSBGcC5tdWwodHYzLCB0djIpOyAvLyAxNC4gdHYzID0gdHYzICogdHYyICAgICAgICAgIyBneDEgKiBneGReM1xuICAgIGxldCB5MSA9IEZwLnBvdyh0djMsIEVMTDJfQzEpOyAvLyAxNS4gIHkxID0gdHYzXmMxICAgICAgICAgICAgIyAoZ3gxICogZ3hkXjMpXigocCAtIDMpIC8gNClcbiAgICB5MSA9IEZwLm11bCh5MSwgdHYyKTsgLy8gMTYuICB5MSA9IHkxICogdHYyICAgICAgICAgICMgZ3gxICogZ3hkICogKGd4MSAqIGd4ZF4zKV4oKHAgLSAzKSAvIDQpXG4gICAgbGV0IHgybiA9IEZwLm11bCh4MW4sIEZwLm5lZyh0djEpKTsgLy8gMTcuIHgybiA9IC10djEgKiB4MW4gICAgICAgICMgeDIgPSB4Mm4gLyB4ZCA9IC0xICogdV4yICogeDFuIC8geGRcbiAgICBsZXQgeTIgPSBGcC5tdWwoeTEsIHUpOyAvLyAxOC4gIHkyID0geTEgKiB1XG4gICAgeTIgPSBGcC5jbW92KHkyLCBGcC5aRVJPLCBlMSk7IC8vIDE5LiAgeTIgPSBDTU9WKHkyLCAwLCBlMSlcbiAgICB0djIgPSBGcC5zcXIoeTEpOyAvLyAyMC4gdHYyID0geTFeMlxuICAgIHR2MiA9IEZwLm11bCh0djIsIGd4ZCk7IC8vIDIxLiB0djIgPSB0djIgKiBneGRcbiAgICBsZXQgZTIgPSBGcC5lcWwodHYyLCBneDEpOyAvLyAyMi4gIGUyID0gdHYyID09IGd4MVxuICAgIGxldCB4biA9IEZwLmNtb3YoeDJuLCB4MW4sIGUyKTsgLy8gMjMuICB4biA9IENNT1YoeDJuLCB4MW4sIGUyKSAgIyBJZiBlMiwgeCA9IHgxLCBlbHNlIHggPSB4MlxuICAgIGxldCB5ID0gRnAuY21vdih5MiwgeTEsIGUyKTsgLy8gMjQuICAgeSA9IENNT1YoeTIsIHkxLCBlMikgICAgIyBJZiBlMiwgeSA9IHkxLCBlbHNlIHkgPSB5MlxuICAgIGxldCBlMyA9IEZwLmlzT2RkKHkpOyAvLyAyNS4gIGUzID0gc2duMCh5KSA9PSAxICAgICAgICAjIEZpeCBzaWduIG9mIHlcbiAgICB5ID0gRnAuY21vdih5LCBGcC5uZWcoeSksIGUyICE9PSBlMyk7IC8vIDI2LiAgIHkgPSBDTU9WKHksIC15LCBlMiBYT1IgZTMpXG4gICAgcmV0dXJuIHsgeG4sIHhkLCB5bjogeSwgeWQ6IEZwLk9ORSB9OyAvLyAyNy4gcmV0dXJuICh4biwgeGQsIHksIDEpXG59XG5mdW5jdGlvbiBtYXBfdG9fY3VydmVfZWxsaWdhdG9yMl9lZHdhcmRzNDQ4KHUpIHtcbiAgICBsZXQgeyB4biwgeGQsIHluLCB5ZCB9ID0gbWFwX3RvX2N1cnZlX2VsbGlnYXRvcjJfY3VydmU0NDgodSk7IC8vIDEuICh4biwgeGQsIHluLCB5ZCkgPSBtYXBfdG9fY3VydmVfZWxsaWdhdG9yMl9jdXJ2ZTQ0OCh1KVxuICAgIGxldCB4bjIgPSBGcC5zcXIoeG4pOyAvLyAyLiAgeG4yID0geG5eMlxuICAgIGxldCB4ZDIgPSBGcC5zcXIoeGQpOyAvLyAzLiAgeGQyID0geGReMlxuICAgIGxldCB4ZDQgPSBGcC5zcXIoeGQyKTsgLy8gNC4gIHhkNCA9IHhkMl4yXG4gICAgbGV0IHluMiA9IEZwLnNxcih5bik7IC8vIDUuICB5bjIgPSB5bl4yXG4gICAgbGV0IHlkMiA9IEZwLnNxcih5ZCk7IC8vIDYuICB5ZDIgPSB5ZF4yXG4gICAgbGV0IHhFbiA9IEZwLnN1Yih4bjIsIHhkMik7IC8vIDcuICB4RW4gPSB4bjIgLSB4ZDJcbiAgICBsZXQgdHYyID0gRnAuc3ViKHhFbiwgeGQyKTsgLy8gOC4gIHR2MiA9IHhFbiAtIHhkMlxuICAgIHhFbiA9IEZwLm11bCh4RW4sIHhkMik7IC8vIDkuICB4RW4gPSB4RW4gKiB4ZDJcbiAgICB4RW4gPSBGcC5tdWwoeEVuLCB5ZCk7IC8vIDEwLiB4RW4gPSB4RW4gKiB5ZFxuICAgIHhFbiA9IEZwLm11bCh4RW4sIHluKTsgLy8gMTEuIHhFbiA9IHhFbiAqIHluXG4gICAgeEVuID0gRnAubXVsKHhFbiwgXzRuKTsgLy8gMTIuIHhFbiA9IHhFbiAqIDRcbiAgICB0djIgPSBGcC5tdWwodHYyLCB4bjIpOyAvLyAxMy4gdHYyID0gdHYyICogeG4yXG4gICAgdHYyID0gRnAubXVsKHR2MiwgeWQyKTsgLy8gMTQuIHR2MiA9IHR2MiAqIHlkMlxuICAgIGxldCB0djMgPSBGcC5tdWwoeW4yLCBfNG4pOyAvLyAxNS4gdHYzID0gNCAqIHluMlxuICAgIGxldCB0djEgPSBGcC5hZGQodHYzLCB5ZDIpOyAvLyAxNi4gdHYxID0gdHYzICsgeWQyXG4gICAgdHYxID0gRnAubXVsKHR2MSwgeGQ0KTsgLy8gMTcuIHR2MSA9IHR2MSAqIHhkNFxuICAgIGxldCB4RWQgPSBGcC5hZGQodHYxLCB0djIpOyAvLyAxOC4geEVkID0gdHYxICsgdHYyXG4gICAgdHYyID0gRnAubXVsKHR2MiwgeG4pOyAvLyAxOS4gdHYyID0gdHYyICogeG5cbiAgICBsZXQgdHY0ID0gRnAubXVsKHhuLCB4ZDQpOyAvLyAyMC4gdHY0ID0geG4gKiB4ZDRcbiAgICBsZXQgeUVuID0gRnAuc3ViKHR2MywgeWQyKTsgLy8gMjEuIHlFbiA9IHR2MyAtIHlkMlxuICAgIHlFbiA9IEZwLm11bCh5RW4sIHR2NCk7IC8vIDIyLiB5RW4gPSB5RW4gKiB0djRcbiAgICB5RW4gPSBGcC5zdWIoeUVuLCB0djIpOyAvLyAyMy4geUVuID0geUVuIC0gdHYyXG4gICAgdHYxID0gRnAuYWRkKHhuMiwgeGQyKTsgLy8gMjQuIHR2MSA9IHhuMiArIHhkMlxuICAgIHR2MSA9IEZwLm11bCh0djEsIHhkMik7IC8vIDI1LiB0djEgPSB0djEgKiB4ZDJcbiAgICB0djEgPSBGcC5tdWwodHYxLCB4ZCk7IC8vIDI2LiB0djEgPSB0djEgKiB4ZFxuICAgIHR2MSA9IEZwLm11bCh0djEsIHluMik7IC8vIDI3LiB0djEgPSB0djEgKiB5bjJcbiAgICB0djEgPSBGcC5tdWwodHYxLCBCaWdJbnQoLTIpKTsgLy8gMjguIHR2MSA9IC0yICogdHYxXG4gICAgbGV0IHlFZCA9IEZwLmFkZCh0djIsIHR2MSk7IC8vIDI5LiB5RWQgPSB0djIgKyB0djFcbiAgICB0djQgPSBGcC5tdWwodHY0LCB5ZDIpOyAvLyAzMC4gdHY0ID0gdHY0ICogeWQyXG4gICAgeUVkID0gRnAuYWRkKHlFZCwgdHY0KTsgLy8gMzEuIHlFZCA9IHlFZCArIHR2NFxuICAgIHR2MSA9IEZwLm11bCh4RWQsIHlFZCk7IC8vIDMyLiB0djEgPSB4RWQgKiB5RWRcbiAgICBsZXQgZSA9IEZwLmVxbCh0djEsIEZwLlpFUk8pOyAvLyAzMy4gICBlID0gdHYxID09IDBcbiAgICB4RW4gPSBGcC5jbW92KHhFbiwgRnAuWkVSTywgZSk7IC8vIDM0LiB4RW4gPSBDTU9WKHhFbiwgMCwgZSlcbiAgICB4RWQgPSBGcC5jbW92KHhFZCwgRnAuT05FLCBlKTsgLy8gMzUuIHhFZCA9IENNT1YoeEVkLCAxLCBlKVxuICAgIHlFbiA9IEZwLmNtb3YoeUVuLCBGcC5PTkUsIGUpOyAvLyAzNi4geUVuID0gQ01PVih5RW4sIDEsIGUpXG4gICAgeUVkID0gRnAuY21vdih5RWQsIEZwLk9ORSwgZSk7IC8vIDM3LiB5RWQgPSBDTU9WKHlFZCwgMSwgZSlcbiAgICBjb25zdCBpbnYgPSBGcC5pbnZlcnRCYXRjaChbeEVkLCB5RWRdKTsgLy8gYmF0Y2ggZGl2aXNpb25cbiAgICByZXR1cm4geyB4OiBGcC5tdWwoeEVuLCBpbnZbMF0pLCB5OiBGcC5tdWwoeUVuLCBpbnZbMV0pIH07IC8vIDM4LiByZXR1cm4gKHhFbiwgeEVkLCB5RW4sIHlFZClcbn1cbmNvbnN0IHsgaGFzaFRvQ3VydmUsIGVuY29kZVRvQ3VydmUgfSA9IGh0Zi5jcmVhdGVIYXNoZXIoZWQ0NDguRXh0ZW5kZWRQb2ludCwgKHNjYWxhcnMpID0+IG1hcF90b19jdXJ2ZV9lbGxpZ2F0b3IyX2Vkd2FyZHM0NDgoc2NhbGFyc1swXSksIHtcbiAgICBEU1Q6ICdlZHdhcmRzNDQ4X1hPRjpTSEFLRTI1Nl9FTEwyX1JPXycsXG4gICAgZW5jb2RlRFNUOiAnZWR3YXJkczQ0OF9YT0Y6U0hBS0UyNTZfRUxMMl9OVV8nLFxuICAgIHA6IEZwLk9SREVSLFxuICAgIG06IDEsXG4gICAgazogMjI0LFxuICAgIGV4cGFuZDogJ3hvZicsXG4gICAgaGFzaDogc2hha2UyNTYsXG59KTtcbmV4cG9ydCB7IGhhc2hUb0N1cnZlLCBlbmNvZGVUb0N1cnZlIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1lZDQ0OC5qcy5tYXAiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/@noble/curves/esm/ed448.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/@noble/hashes/esm/_assert.js":
+/*!***************************************************!*\
+  !*** ./node_modules/@noble/hashes/esm/_assert.js ***!
+  \***************************************************/
+/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   bool: () => (/* binding */ bool),\n/* harmony export */   bytes: () => (/* binding */ bytes),\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */   exists: () => (/* binding */ exists),\n/* harmony export */   hash: () => (/* binding */ hash),\n/* harmony export */   number: () => (/* binding */ number),\n/* harmony export */   output: () => (/* binding */ output)\n/* harmony export */ });\nfunction number(n) {\n    if (!Number.isSafeInteger(n) || n < 0)\n        throw new Error(`Wrong positive integer: ${n}`);\n}\nfunction bool(b) {\n    if (typeof b !== 'boolean')\n        throw new Error(`Expected boolean, not ${b}`);\n}\nfunction bytes(b, ...lengths) {\n    if (!(b instanceof Uint8Array))\n        throw new TypeError('Expected Uint8Array');\n    if (lengths.length > 0 && !lengths.includes(b.length))\n        throw new TypeError(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`);\n}\nfunction hash(hash) {\n    if (typeof hash !== 'function' || typeof hash.create !== 'function')\n        throw new Error('Hash should be wrapped by utils.wrapConstructor');\n    number(hash.outputLen);\n    number(hash.blockLen);\n}\nfunction exists(instance, checkFinished = true) {\n    if (instance.destroyed)\n        throw new Error('Hash instance has been destroyed');\n    if (checkFinished && instance.finished)\n        throw new Error('Hash#digest() has already been called');\n}\nfunction output(out, instance) {\n    bytes(out);\n    const min = instance.outputLen;\n    if (out.length < min) {\n        throw new Error(`digestInto() expects output buffer of length at least ${min}`);\n    }\n}\nconst assert = {\n    number,\n    bool,\n    bytes,\n    hash,\n    exists,\n    output,\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (assert);\n//# sourceMappingURL=_assert.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQG5vYmxlL2hhc2hlcy9lc20vX2Fzc2VydC5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvQG5vYmxlL2hhc2hlcy9lc20vX2Fzc2VydC5qcz83NjAwIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBmdW5jdGlvbiBudW1iZXIobikge1xuICAgIGlmICghTnVtYmVyLmlzU2FmZUludGVnZXIobikgfHwgbiA8IDApXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgV3JvbmcgcG9zaXRpdmUgaW50ZWdlcjogJHtufWApO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGJvb2woYikge1xuICAgIGlmICh0eXBlb2YgYiAhPT0gJ2Jvb2xlYW4nKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGJvb2xlYW4sIG5vdCAke2J9YCk7XG59XG5leHBvcnQgZnVuY3Rpb24gYnl0ZXMoYiwgLi4ubGVuZ3Rocykge1xuICAgIGlmICghKGIgaW5zdGFuY2VvZiBVaW50OEFycmF5KSlcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignRXhwZWN0ZWQgVWludDhBcnJheScpO1xuICAgIGlmIChsZW5ndGhzLmxlbmd0aCA+IDAgJiYgIWxlbmd0aHMuaW5jbHVkZXMoYi5sZW5ndGgpKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBFeHBlY3RlZCBVaW50OEFycmF5IG9mIGxlbmd0aCAke2xlbmd0aHN9LCBub3Qgb2YgbGVuZ3RoPSR7Yi5sZW5ndGh9YCk7XG59XG5leHBvcnQgZnVuY3Rpb24gaGFzaChoYXNoKSB7XG4gICAgaWYgKHR5cGVvZiBoYXNoICE9PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBoYXNoLmNyZWF0ZSAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdIYXNoIHNob3VsZCBiZSB3cmFwcGVkIGJ5IHV0aWxzLndyYXBDb25zdHJ1Y3RvcicpO1xuICAgIG51bWJlcihoYXNoLm91dHB1dExlbik7XG4gICAgbnVtYmVyKGhhc2guYmxvY2tMZW4pO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGV4aXN0cyhpbnN0YW5jZSwgY2hlY2tGaW5pc2hlZCA9IHRydWUpIHtcbiAgICBpZiAoaW5zdGFuY2UuZGVzdHJveWVkKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0hhc2ggaW5zdGFuY2UgaGFzIGJlZW4gZGVzdHJveWVkJyk7XG4gICAgaWYgKGNoZWNrRmluaXNoZWQgJiYgaW5zdGFuY2UuZmluaXNoZWQpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSGFzaCNkaWdlc3QoKSBoYXMgYWxyZWFkeSBiZWVuIGNhbGxlZCcpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIG91dHB1dChvdXQsIGluc3RhbmNlKSB7XG4gICAgYnl0ZXMob3V0KTtcbiAgICBjb25zdCBtaW4gPSBpbnN0YW5jZS5vdXRwdXRMZW47XG4gICAgaWYgKG91dC5sZW5ndGggPCBtaW4pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBkaWdlc3RJbnRvKCkgZXhwZWN0cyBvdXRwdXQgYnVmZmVyIG9mIGxlbmd0aCBhdCBsZWFzdCAke21pbn1gKTtcbiAgICB9XG59XG5jb25zdCBhc3NlcnQgPSB7XG4gICAgbnVtYmVyLFxuICAgIGJvb2wsXG4gICAgYnl0ZXMsXG4gICAgaGFzaCxcbiAgICBleGlzdHMsXG4gICAgb3V0cHV0LFxufTtcbmV4cG9ydCBkZWZhdWx0IGFzc2VydDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPV9hc3NlcnQuanMubWFwIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/@noble/hashes/esm/_assert.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/@noble/hashes/esm/_u64.js":
+/*!************************************************!*\
+  !*** ./node_modules/@noble/hashes/esm/_u64.js ***!
+  \************************************************/
+/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   add: () => (/* binding */ add),\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */   fromBig: () => (/* binding */ fromBig),\n/* harmony export */   split: () => (/* binding */ split),\n/* harmony export */   toBig: () => (/* binding */ toBig)\n/* harmony export */ });\nconst U32_MASK64 = BigInt(2 ** 32 - 1);\nconst _32n = BigInt(32);\n// We are not using BigUint64Array, because they are extremely slow as per 2022\nfunction fromBig(n, le = false) {\n    if (le)\n        return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };\n    return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };\n}\nfunction split(lst, le = false) {\n    let Ah = new Uint32Array(lst.length);\n    let Al = new Uint32Array(lst.length);\n    for (let i = 0; i < lst.length; i++) {\n        const { h, l } = fromBig(lst[i], le);\n        [Ah[i], Al[i]] = [h, l];\n    }\n    return [Ah, Al];\n}\nconst toBig = (h, l) => (BigInt(h >>> 0) << _32n) | BigInt(l >>> 0);\n// for Shift in [0, 32)\nconst shrSH = (h, l, s) => h >>> s;\nconst shrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);\n// Right rotate for Shift in [1, 32)\nconst rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s));\nconst rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);\n// Right rotate for Shift in (32, 64), NOTE: 32 is special case.\nconst rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32));\nconst rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s));\n// Right rotate for shift===32 (just swaps l&h)\nconst rotr32H = (h, l) => l;\nconst rotr32L = (h, l) => h;\n// Left rotate for Shift in [1, 32)\nconst rotlSH = (h, l, s) => (h << s) | (l >>> (32 - s));\nconst rotlSL = (h, l, s) => (l << s) | (h >>> (32 - s));\n// Left rotate for Shift in (32, 64), NOTE: 32 is special case.\nconst rotlBH = (h, l, s) => (l << (s - 32)) | (h >>> (64 - s));\nconst rotlBL = (h, l, s) => (h << (s - 32)) | (l >>> (64 - s));\n// JS uses 32-bit signed integers for bitwise operations which means we cannot\n// simple take carry out of low bit sum by shift, we need to use division.\n// Removing \"export\" has 5% perf penalty -_-\nfunction add(Ah, Al, Bh, Bl) {\n    const l = (Al >>> 0) + (Bl >>> 0);\n    return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 };\n}\n// Addition with more than 2 elements\nconst add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);\nconst add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0;\nconst add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);\nconst add4H = (low, Ah, Bh, Ch, Dh) => (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0;\nconst add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);\nconst add5H = (low, Ah, Bh, Ch, Dh, Eh) => (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0;\n// prettier-ignore\nconst u64 = {\n    fromBig, split, toBig,\n    shrSH, shrSL,\n    rotrSH, rotrSL, rotrBH, rotrBL,\n    rotr32H, rotr32L,\n    rotlSH, rotlSL, rotlBH, rotlBL,\n    add, add3L, add3H, add4L, add4H, add5H, add5L,\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (u64);\n//# sourceMappingURL=_u64.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQG5vYmxlL2hhc2hlcy9lc20vX3U2NC5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9oYXNoZXMvZXNtL191NjQuanM/YjYyYSJdLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBVMzJfTUFTSzY0ID0gQmlnSW50KDIgKiogMzIgLSAxKTtcbmNvbnN0IF8zMm4gPSBCaWdJbnQoMzIpO1xuLy8gV2UgYXJlIG5vdCB1c2luZyBCaWdVaW50NjRBcnJheSwgYmVjYXVzZSB0aGV5IGFyZSBleHRyZW1lbHkgc2xvdyBhcyBwZXIgMjAyMlxuZXhwb3J0IGZ1bmN0aW9uIGZyb21CaWcobiwgbGUgPSBmYWxzZSkge1xuICAgIGlmIChsZSlcbiAgICAgICAgcmV0dXJuIHsgaDogTnVtYmVyKG4gJiBVMzJfTUFTSzY0KSwgbDogTnVtYmVyKChuID4+IF8zMm4pICYgVTMyX01BU0s2NCkgfTtcbiAgICByZXR1cm4geyBoOiBOdW1iZXIoKG4gPj4gXzMybikgJiBVMzJfTUFTSzY0KSB8IDAsIGw6IE51bWJlcihuICYgVTMyX01BU0s2NCkgfCAwIH07XG59XG5leHBvcnQgZnVuY3Rpb24gc3BsaXQobHN0LCBsZSA9IGZhbHNlKSB7XG4gICAgbGV0IEFoID0gbmV3IFVpbnQzMkFycmF5KGxzdC5sZW5ndGgpO1xuICAgIGxldCBBbCA9IG5ldyBVaW50MzJBcnJheShsc3QubGVuZ3RoKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCB7IGgsIGwgfSA9IGZyb21CaWcobHN0W2ldLCBsZSk7XG4gICAgICAgIFtBaFtpXSwgQWxbaV1dID0gW2gsIGxdO1xuICAgIH1cbiAgICByZXR1cm4gW0FoLCBBbF07XG59XG5leHBvcnQgY29uc3QgdG9CaWcgPSAoaCwgbCkgPT4gKEJpZ0ludChoID4+PiAwKSA8PCBfMzJuKSB8IEJpZ0ludChsID4+PiAwKTtcbi8vIGZvciBTaGlmdCBpbiBbMCwgMzIpXG5jb25zdCBzaHJTSCA9IChoLCBsLCBzKSA9PiBoID4+PiBzO1xuY29uc3Qgc2hyU0wgPSAoaCwgbCwgcykgPT4gKGggPDwgKDMyIC0gcykpIHwgKGwgPj4+IHMpO1xuLy8gUmlnaHQgcm90YXRlIGZvciBTaGlmdCBpbiBbMSwgMzIpXG5jb25zdCByb3RyU0ggPSAoaCwgbCwgcykgPT4gKGggPj4+IHMpIHwgKGwgPDwgKDMyIC0gcykpO1xuY29uc3Qgcm90clNMID0gKGgsIGwsIHMpID0+IChoIDw8ICgzMiAtIHMpKSB8IChsID4+PiBzKTtcbi8vIFJpZ2h0IHJvdGF0ZSBmb3IgU2hpZnQgaW4gKDMyLCA2NCksIE5PVEU6IDMyIGlzIHNwZWNpYWwgY2FzZS5cbmNvbnN0IHJvdHJCSCA9IChoLCBsLCBzKSA9PiAoaCA8PCAoNjQgLSBzKSkgfCAobCA+Pj4gKHMgLSAzMikpO1xuY29uc3Qgcm90ckJMID0gKGgsIGwsIHMpID0+IChoID4+PiAocyAtIDMyKSkgfCAobCA8PCAoNjQgLSBzKSk7XG4vLyBSaWdodCByb3RhdGUgZm9yIHNoaWZ0PT09MzIgKGp1c3Qgc3dhcHMgbCZoKVxuY29uc3Qgcm90cjMySCA9IChoLCBsKSA9PiBsO1xuY29uc3Qgcm90cjMyTCA9IChoLCBsKSA9PiBoO1xuLy8gTGVmdCByb3RhdGUgZm9yIFNoaWZ0IGluIFsxLCAzMilcbmNvbnN0IHJvdGxTSCA9IChoLCBsLCBzKSA9PiAoaCA8PCBzKSB8IChsID4+PiAoMzIgLSBzKSk7XG5jb25zdCByb3RsU0wgPSAoaCwgbCwgcykgPT4gKGwgPDwgcykgfCAoaCA+Pj4gKDMyIC0gcykpO1xuLy8gTGVmdCByb3RhdGUgZm9yIFNoaWZ0IGluICgzMiwgNjQpLCBOT1RFOiAzMiBpcyBzcGVjaWFsIGNhc2UuXG5jb25zdCByb3RsQkggPSAoaCwgbCwgcykgPT4gKGwgPDwgKHMgLSAzMikpIHwgKGggPj4+ICg2NCAtIHMpKTtcbmNvbnN0IHJvdGxCTCA9IChoLCBsLCBzKSA9PiAoaCA8PCAocyAtIDMyKSkgfCAobCA+Pj4gKDY0IC0gcykpO1xuLy8gSlMgdXNlcyAzMi1iaXQgc2lnbmVkIGludGVnZXJzIGZvciBiaXR3aXNlIG9wZXJhdGlvbnMgd2hpY2ggbWVhbnMgd2UgY2Fubm90XG4vLyBzaW1wbGUgdGFrZSBjYXJyeSBvdXQgb2YgbG93IGJpdCBzdW0gYnkgc2hpZnQsIHdlIG5lZWQgdG8gdXNlIGRpdmlzaW9uLlxuLy8gUmVtb3ZpbmcgXCJleHBvcnRcIiBoYXMgNSUgcGVyZiBwZW5hbHR5IC1fLVxuZXhwb3J0IGZ1bmN0aW9uIGFkZChBaCwgQWwsIEJoLCBCbCkge1xuICAgIGNvbnN0IGwgPSAoQWwgPj4+IDApICsgKEJsID4+PiAwKTtcbiAgICByZXR1cm4geyBoOiAoQWggKyBCaCArICgobCAvIDIgKiogMzIpIHwgMCkpIHwgMCwgbDogbCB8IDAgfTtcbn1cbi8vIEFkZGl0aW9uIHdpdGggbW9yZSB0aGFuIDIgZWxlbWVudHNcbmNvbnN0IGFkZDNMID0gKEFsLCBCbCwgQ2wpID0+IChBbCA+Pj4gMCkgKyAoQmwgPj4+IDApICsgKENsID4+PiAwKTtcbmNvbnN0IGFkZDNIID0gKGxvdywgQWgsIEJoLCBDaCkgPT4gKEFoICsgQmggKyBDaCArICgobG93IC8gMiAqKiAzMikgfCAwKSkgfCAwO1xuY29uc3QgYWRkNEwgPSAoQWwsIEJsLCBDbCwgRGwpID0+IChBbCA+Pj4gMCkgKyAoQmwgPj4+IDApICsgKENsID4+PiAwKSArIChEbCA+Pj4gMCk7XG5jb25zdCBhZGQ0SCA9IChsb3csIEFoLCBCaCwgQ2gsIERoKSA9PiAoQWggKyBCaCArIENoICsgRGggKyAoKGxvdyAvIDIgKiogMzIpIHwgMCkpIHwgMDtcbmNvbnN0IGFkZDVMID0gKEFsLCBCbCwgQ2wsIERsLCBFbCkgPT4gKEFsID4+PiAwKSArIChCbCA+Pj4gMCkgKyAoQ2wgPj4+IDApICsgKERsID4+PiAwKSArIChFbCA+Pj4gMCk7XG5jb25zdCBhZGQ1SCA9IChsb3csIEFoLCBCaCwgQ2gsIERoLCBFaCkgPT4gKEFoICsgQmggKyBDaCArIERoICsgRWggKyAoKGxvdyAvIDIgKiogMzIpIHwgMCkpIHwgMDtcbi8vIHByZXR0aWVyLWlnbm9yZVxuY29uc3QgdTY0ID0ge1xuICAgIGZyb21CaWcsIHNwbGl0LCB0b0JpZyxcbiAgICBzaHJTSCwgc2hyU0wsXG4gICAgcm90clNILCByb3RyU0wsIHJvdHJCSCwgcm90ckJMLFxuICAgIHJvdHIzMkgsIHJvdHIzMkwsXG4gICAgcm90bFNILCByb3RsU0wsIHJvdGxCSCwgcm90bEJMLFxuICAgIGFkZCwgYWRkM0wsIGFkZDNILCBhZGQ0TCwgYWRkNEgsIGFkZDVILCBhZGQ1TCxcbn07XG5leHBvcnQgZGVmYXVsdCB1NjQ7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1fdTY0LmpzLm1hcCJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/@noble/hashes/esm/_u64.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/@noble/hashes/esm/crypto.js":
+/*!**************************************************!*\
+  !*** ./node_modules/@noble/hashes/esm/crypto.js ***!
+  \**************************************************/
+/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   crypto: () => (/* binding */ crypto)\n/* harmony export */ });\nconst crypto = typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined;\n//# sourceMappingURL=crypto.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQG5vYmxlL2hhc2hlcy9lc20vY3J5cHRvLmpzLmpzIiwibWFwcGluZ3MiOiI7Ozs7QUFBQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9oYXNoZXMvZXNtL2NyeXB0by5qcz8xNTMwIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjb25zdCBjcnlwdG8gPSB0eXBlb2YgZ2xvYmFsVGhpcyA9PT0gJ29iamVjdCcgJiYgJ2NyeXB0bycgaW4gZ2xvYmFsVGhpcyA/IGdsb2JhbFRoaXMuY3J5cHRvIDogdW5kZWZpbmVkO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y3J5cHRvLmpzLm1hcCJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/@noble/hashes/esm/crypto.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/@noble/hashes/esm/sha3.js":
+/*!************************************************!*\
+  !*** ./node_modules/@noble/hashes/esm/sha3.js ***!
+  \************************************************/
+/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   Keccak: () => (/* binding */ Keccak),\n/* harmony export */   keccakP: () => (/* binding */ keccakP),\n/* harmony export */   keccak_224: () => (/* binding */ keccak_224),\n/* harmony export */   keccak_256: () => (/* binding */ keccak_256),\n/* harmony export */   keccak_384: () => (/* binding */ keccak_384),\n/* harmony export */   keccak_512: () => (/* binding */ keccak_512),\n/* harmony export */   sha3_224: () => (/* binding */ sha3_224),\n/* harmony export */   sha3_256: () => (/* binding */ sha3_256),\n/* harmony export */   sha3_384: () => (/* binding */ sha3_384),\n/* harmony export */   sha3_512: () => (/* binding */ sha3_512),\n/* harmony export */   shake128: () => (/* binding */ shake128),\n/* harmony export */   shake256: () => (/* binding */ shake256)\n/* harmony export */ });\n/* harmony import */ var _assert_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./_assert.js */ \"./node_modules/@noble/hashes/esm/_assert.js\");\n/* harmony import */ var _u64_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./_u64.js */ \"./node_modules/@noble/hashes/esm/_u64.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils.js */ \"./node_modules/@noble/hashes/esm/utils.js\");\n\n\n\n// Various per round constants calculations\nconst [SHA3_PI, SHA3_ROTL, _SHA3_IOTA] = [[], [], []];\nconst _0n = BigInt(0);\nconst _1n = BigInt(1);\nconst _2n = BigInt(2);\nconst _7n = BigInt(7);\nconst _256n = BigInt(256);\nconst _0x71n = BigInt(0x71);\nfor (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) {\n    // Pi\n    [x, y] = [y, (2 * x + 3 * y) % 5];\n    SHA3_PI.push(2 * (5 * y + x));\n    // Rotational\n    SHA3_ROTL.push((((round + 1) * (round + 2)) / 2) % 64);\n    // Iota\n    let t = _0n;\n    for (let j = 0; j < 7; j++) {\n        R = ((R << _1n) ^ ((R >> _7n) * _0x71n)) % _256n;\n        if (R & _2n)\n            t ^= _1n << ((_1n << BigInt(j)) - _1n);\n    }\n    _SHA3_IOTA.push(t);\n}\nconst [SHA3_IOTA_H, SHA3_IOTA_L] = _u64_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].split(_SHA3_IOTA, true);\n// Left rotation (without 0, 32, 64)\nconst rotlH = (h, l, s) => s > 32 ? _u64_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].rotlBH(h, l, s) : _u64_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].rotlSH(h, l, s);\nconst rotlL = (h, l, s) => s > 32 ? _u64_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].rotlBL(h, l, s) : _u64_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].rotlSL(h, l, s);\n// Same as keccakf1600, but allows to skip some rounds\nfunction keccakP(s, rounds = 24) {\n    const B = new Uint32Array(5 * 2);\n    // NOTE: all indices are x2 since we store state as u32 instead of u64 (bigints to slow in js)\n    for (let round = 24 - rounds; round < 24; round++) {\n        // Theta θ\n        for (let x = 0; x < 10; x++)\n            B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];\n        for (let x = 0; x < 10; x += 2) {\n            const idx1 = (x + 8) % 10;\n            const idx0 = (x + 2) % 10;\n            const B0 = B[idx0];\n            const B1 = B[idx0 + 1];\n            const Th = rotlH(B0, B1, 1) ^ B[idx1];\n            const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1];\n            for (let y = 0; y < 50; y += 10) {\n                s[x + y] ^= Th;\n                s[x + y + 1] ^= Tl;\n            }\n        }\n        // Rho (ρ) and Pi (π)\n        let curH = s[2];\n        let curL = s[3];\n        for (let t = 0; t < 24; t++) {\n            const shift = SHA3_ROTL[t];\n            const Th = rotlH(curH, curL, shift);\n            const Tl = rotlL(curH, curL, shift);\n            const PI = SHA3_PI[t];\n            curH = s[PI];\n            curL = s[PI + 1];\n            s[PI] = Th;\n            s[PI + 1] = Tl;\n        }\n        // Chi (χ)\n        for (let y = 0; y < 50; y += 10) {\n            for (let x = 0; x < 10; x++)\n                B[x] = s[y + x];\n            for (let x = 0; x < 10; x++)\n                s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];\n        }\n        // Iota (ι)\n        s[0] ^= SHA3_IOTA_H[round];\n        s[1] ^= SHA3_IOTA_L[round];\n    }\n    B.fill(0);\n}\nclass Keccak extends _utils_js__WEBPACK_IMPORTED_MODULE_2__.Hash {\n    // NOTE: we accept arguments in bytes instead of bits here.\n    constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) {\n        super();\n        this.blockLen = blockLen;\n        this.suffix = suffix;\n        this.outputLen = outputLen;\n        this.enableXOF = enableXOF;\n        this.rounds = rounds;\n        this.pos = 0;\n        this.posOut = 0;\n        this.finished = false;\n        this.destroyed = false;\n        // Can be passed from user as dkLen\n        _assert_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].number(outputLen);\n        // 1600 = 5x5 matrix of 64bit.  1600 bits === 200 bytes\n        if (0 >= this.blockLen || this.blockLen >= 200)\n            throw new Error('Sha3 supports only keccak-f1600 function');\n        this.state = new Uint8Array(200);\n        this.state32 = (0,_utils_js__WEBPACK_IMPORTED_MODULE_2__.u32)(this.state);\n    }\n    keccak() {\n        keccakP(this.state32, this.rounds);\n        this.posOut = 0;\n        this.pos = 0;\n    }\n    update(data) {\n        _assert_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].exists(this);\n        const { blockLen, state } = this;\n        data = (0,_utils_js__WEBPACK_IMPORTED_MODULE_2__.toBytes)(data);\n        const len = data.length;\n        for (let pos = 0; pos < len;) {\n            const take = Math.min(blockLen - this.pos, len - pos);\n            for (let i = 0; i < take; i++)\n                state[this.pos++] ^= data[pos++];\n            if (this.pos === blockLen)\n                this.keccak();\n        }\n        return this;\n    }\n    finish() {\n        if (this.finished)\n            return;\n        this.finished = true;\n        const { state, suffix, pos, blockLen } = this;\n        // Do the padding\n        state[pos] ^= suffix;\n        if ((suffix & 0x80) !== 0 && pos === blockLen - 1)\n            this.keccak();\n        state[blockLen - 1] ^= 0x80;\n        this.keccak();\n    }\n    writeInto(out) {\n        _assert_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].exists(this, false);\n        _assert_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].bytes(out);\n        this.finish();\n        const bufferOut = this.state;\n        const { blockLen } = this;\n        for (let pos = 0, len = out.length; pos < len;) {\n            if (this.posOut >= blockLen)\n                this.keccak();\n            const take = Math.min(blockLen - this.posOut, len - pos);\n            out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);\n            this.posOut += take;\n            pos += take;\n        }\n        return out;\n    }\n    xofInto(out) {\n        // Sha3/Keccak usage with XOF is probably mistake, only SHAKE instances can do XOF\n        if (!this.enableXOF)\n            throw new Error('XOF is not possible for this instance');\n        return this.writeInto(out);\n    }\n    xof(bytes) {\n        _assert_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].number(bytes);\n        return this.xofInto(new Uint8Array(bytes));\n    }\n    digestInto(out) {\n        _assert_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].output(out, this);\n        if (this.finished)\n            throw new Error('digest() was already called');\n        this.writeInto(out);\n        this.destroy();\n        return out;\n    }\n    digest() {\n        return this.digestInto(new Uint8Array(this.outputLen));\n    }\n    destroy() {\n        this.destroyed = true;\n        this.state.fill(0);\n    }\n    _cloneInto(to) {\n        const { blockLen, suffix, outputLen, rounds, enableXOF } = this;\n        to || (to = new Keccak(blockLen, suffix, outputLen, enableXOF, rounds));\n        to.state32.set(this.state32);\n        to.pos = this.pos;\n        to.posOut = this.posOut;\n        to.finished = this.finished;\n        to.rounds = rounds;\n        // Suffix can change in cSHAKE\n        to.suffix = suffix;\n        to.outputLen = outputLen;\n        to.enableXOF = enableXOF;\n        to.destroyed = this.destroyed;\n        return to;\n    }\n}\nconst gen = (suffix, blockLen, outputLen) => (0,_utils_js__WEBPACK_IMPORTED_MODULE_2__.wrapConstructor)(() => new Keccak(blockLen, suffix, outputLen));\nconst sha3_224 = gen(0x06, 144, 224 / 8);\n/**\n * SHA3-256 hash function\n * @param message - that would be hashed\n */\nconst sha3_256 = gen(0x06, 136, 256 / 8);\nconst sha3_384 = gen(0x06, 104, 384 / 8);\nconst sha3_512 = gen(0x06, 72, 512 / 8);\nconst keccak_224 = gen(0x01, 144, 224 / 8);\n/**\n * keccak-256 hash function. Different from SHA3-256.\n * @param message - that would be hashed\n */\nconst keccak_256 = gen(0x01, 136, 256 / 8);\nconst keccak_384 = gen(0x01, 104, 384 / 8);\nconst keccak_512 = gen(0x01, 72, 512 / 8);\nconst genShake = (suffix, blockLen, outputLen) => (0,_utils_js__WEBPACK_IMPORTED_MODULE_2__.wrapConstructorWithOpts)((opts = {}) => new Keccak(blockLen, suffix, opts.dkLen === undefined ? outputLen : opts.dkLen, true));\nconst shake128 = genShake(0x1f, 168, 128 / 8);\nconst shake256 = genShake(0x1f, 136, 256 / 8);\n//# sourceMappingURL=sha3.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQG5vYmxlL2hhc2hlcy9lc20vc2hhMy5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9oYXNoZXMvZXNtL3NoYTMuanM/YWJjYiJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgYXNzZXJ0IGZyb20gJy4vX2Fzc2VydC5qcyc7XG5pbXBvcnQgdTY0IGZyb20gJy4vX3U2NC5qcyc7XG5pbXBvcnQgeyBIYXNoLCB1MzIsIHRvQnl0ZXMsIHdyYXBDb25zdHJ1Y3Rvciwgd3JhcENvbnN0cnVjdG9yV2l0aE9wdHMsIH0gZnJvbSAnLi91dGlscy5qcyc7XG4vLyBWYXJpb3VzIHBlciByb3VuZCBjb25zdGFudHMgY2FsY3VsYXRpb25zXG5jb25zdCBbU0hBM19QSSwgU0hBM19ST1RMLCBfU0hBM19JT1RBXSA9IFtbXSwgW10sIFtdXTtcbmNvbnN0IF8wbiA9IEJpZ0ludCgwKTtcbmNvbnN0IF8xbiA9IEJpZ0ludCgxKTtcbmNvbnN0IF8ybiA9IEJpZ0ludCgyKTtcbmNvbnN0IF83biA9IEJpZ0ludCg3KTtcbmNvbnN0IF8yNTZuID0gQmlnSW50KDI1Nik7XG5jb25zdCBfMHg3MW4gPSBCaWdJbnQoMHg3MSk7XG5mb3IgKGxldCByb3VuZCA9IDAsIFIgPSBfMW4sIHggPSAxLCB5ID0gMDsgcm91bmQgPCAyNDsgcm91bmQrKykge1xuICAgIC8vIFBpXG4gICAgW3gsIHldID0gW3ksICgyICogeCArIDMgKiB5KSAlIDVdO1xuICAgIFNIQTNfUEkucHVzaCgyICogKDUgKiB5ICsgeCkpO1xuICAgIC8vIFJvdGF0aW9uYWxcbiAgICBTSEEzX1JPVEwucHVzaCgoKChyb3VuZCArIDEpICogKHJvdW5kICsgMikpIC8gMikgJSA2NCk7XG4gICAgLy8gSW90YVxuICAgIGxldCB0ID0gXzBuO1xuICAgIGZvciAobGV0IGogPSAwOyBqIDwgNzsgaisrKSB7XG4gICAgICAgIFIgPSAoKFIgPDwgXzFuKSBeICgoUiA+PiBfN24pICogXzB4NzFuKSkgJSBfMjU2bjtcbiAgICAgICAgaWYgKFIgJiBfMm4pXG4gICAgICAgICAgICB0IF49IF8xbiA8PCAoKF8xbiA8PCBCaWdJbnQoaikpIC0gXzFuKTtcbiAgICB9XG4gICAgX1NIQTNfSU9UQS5wdXNoKHQpO1xufVxuY29uc3QgW1NIQTNfSU9UQV9ILCBTSEEzX0lPVEFfTF0gPSB1NjQuc3BsaXQoX1NIQTNfSU9UQSwgdHJ1ZSk7XG4vLyBMZWZ0IHJvdGF0aW9uICh3aXRob3V0IDAsIDMyLCA2NClcbmNvbnN0IHJvdGxIID0gKGgsIGwsIHMpID0+IHMgPiAzMiA/IHU2NC5yb3RsQkgoaCwgbCwgcykgOiB1NjQucm90bFNIKGgsIGwsIHMpO1xuY29uc3Qgcm90bEwgPSAoaCwgbCwgcykgPT4gcyA+IDMyID8gdTY0LnJvdGxCTChoLCBsLCBzKSA6IHU2NC5yb3RsU0woaCwgbCwgcyk7XG4vLyBTYW1lIGFzIGtlY2Nha2YxNjAwLCBidXQgYWxsb3dzIHRvIHNraXAgc29tZSByb3VuZHNcbmV4cG9ydCBmdW5jdGlvbiBrZWNjYWtQKHMsIHJvdW5kcyA9IDI0KSB7XG4gICAgY29uc3QgQiA9IG5ldyBVaW50MzJBcnJheSg1ICogMik7XG4gICAgLy8gTk9URTogYWxsIGluZGljZXMgYXJlIHgyIHNpbmNlIHdlIHN0b3JlIHN0YXRlIGFzIHUzMiBpbnN0ZWFkIG9mIHU2NCAoYmlnaW50cyB0byBzbG93IGluIGpzKVxuICAgIGZvciAobGV0IHJvdW5kID0gMjQgLSByb3VuZHM7IHJvdW5kIDwgMjQ7IHJvdW5kKyspIHtcbiAgICAgICAgLy8gVGhldGEgzrhcbiAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCAxMDsgeCsrKVxuICAgICAgICAgICAgQlt4XSA9IHNbeF0gXiBzW3ggKyAxMF0gXiBzW3ggKyAyMF0gXiBzW3ggKyAzMF0gXiBzW3ggKyA0MF07XG4gICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgMTA7IHggKz0gMikge1xuICAgICAgICAgICAgY29uc3QgaWR4MSA9ICh4ICsgOCkgJSAxMDtcbiAgICAgICAgICAgIGNvbnN0IGlkeDAgPSAoeCArIDIpICUgMTA7XG4gICAgICAgICAgICBjb25zdCBCMCA9IEJbaWR4MF07XG4gICAgICAgICAgICBjb25zdCBCMSA9IEJbaWR4MCArIDFdO1xuICAgICAgICAgICAgY29uc3QgVGggPSByb3RsSChCMCwgQjEsIDEpIF4gQltpZHgxXTtcbiAgICAgICAgICAgIGNvbnN0IFRsID0gcm90bEwoQjAsIEIxLCAxKSBeIEJbaWR4MSArIDFdO1xuICAgICAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCA1MDsgeSArPSAxMCkge1xuICAgICAgICAgICAgICAgIHNbeCArIHldIF49IFRoO1xuICAgICAgICAgICAgICAgIHNbeCArIHkgKyAxXSBePSBUbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBSaG8gKM+BKSBhbmQgUGkgKM+AKVxuICAgICAgICBsZXQgY3VySCA9IHNbMl07XG4gICAgICAgIGxldCBjdXJMID0gc1szXTtcbiAgICAgICAgZm9yIChsZXQgdCA9IDA7IHQgPCAyNDsgdCsrKSB7XG4gICAgICAgICAgICBjb25zdCBzaGlmdCA9IFNIQTNfUk9UTFt0XTtcbiAgICAgICAgICAgIGNvbnN0IFRoID0gcm90bEgoY3VySCwgY3VyTCwgc2hpZnQpO1xuICAgICAgICAgICAgY29uc3QgVGwgPSByb3RsTChjdXJILCBjdXJMLCBzaGlmdCk7XG4gICAgICAgICAgICBjb25zdCBQSSA9IFNIQTNfUElbdF07XG4gICAgICAgICAgICBjdXJIID0gc1tQSV07XG4gICAgICAgICAgICBjdXJMID0gc1tQSSArIDFdO1xuICAgICAgICAgICAgc1tQSV0gPSBUaDtcbiAgICAgICAgICAgIHNbUEkgKyAxXSA9IFRsO1xuICAgICAgICB9XG4gICAgICAgIC8vIENoaSAoz4cpXG4gICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgNTA7IHkgKz0gMTApIHtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgMTA7IHgrKylcbiAgICAgICAgICAgICAgICBCW3hdID0gc1t5ICsgeF07XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IDEwOyB4KyspXG4gICAgICAgICAgICAgICAgc1t5ICsgeF0gXj0gfkJbKHggKyAyKSAlIDEwXSAmIEJbKHggKyA0KSAlIDEwXTtcbiAgICAgICAgfVxuICAgICAgICAvLyBJb3RhICjOuSlcbiAgICAgICAgc1swXSBePSBTSEEzX0lPVEFfSFtyb3VuZF07XG4gICAgICAgIHNbMV0gXj0gU0hBM19JT1RBX0xbcm91bmRdO1xuICAgIH1cbiAgICBCLmZpbGwoMCk7XG59XG5leHBvcnQgY2xhc3MgS2VjY2FrIGV4dGVuZHMgSGFzaCB7XG4gICAgLy8gTk9URTogd2UgYWNjZXB0IGFyZ3VtZW50cyBpbiBieXRlcyBpbnN0ZWFkIG9mIGJpdHMgaGVyZS5cbiAgICBjb25zdHJ1Y3RvcihibG9ja0xlbiwgc3VmZml4LCBvdXRwdXRMZW4sIGVuYWJsZVhPRiA9IGZhbHNlLCByb3VuZHMgPSAyNCkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLmJsb2NrTGVuID0gYmxvY2tMZW47XG4gICAgICAgIHRoaXMuc3VmZml4ID0gc3VmZml4O1xuICAgICAgICB0aGlzLm91dHB1dExlbiA9IG91dHB1dExlbjtcbiAgICAgICAgdGhpcy5lbmFibGVYT0YgPSBlbmFibGVYT0Y7XG4gICAgICAgIHRoaXMucm91bmRzID0gcm91bmRzO1xuICAgICAgICB0aGlzLnBvcyA9IDA7XG4gICAgICAgIHRoaXMucG9zT3V0ID0gMDtcbiAgICAgICAgdGhpcy5maW5pc2hlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmRlc3Ryb3llZCA9IGZhbHNlO1xuICAgICAgICAvLyBDYW4gYmUgcGFzc2VkIGZyb20gdXNlciBhcyBka0xlblxuICAgICAgICBhc3NlcnQubnVtYmVyKG91dHB1dExlbik7XG4gICAgICAgIC8vIDE2MDAgPSA1eDUgbWF0cml4IG9mIDY0Yml0LiAgMTYwMCBiaXRzID09PSAyMDAgYnl0ZXNcbiAgICAgICAgaWYgKDAgPj0gdGhpcy5ibG9ja0xlbiB8fCB0aGlzLmJsb2NrTGVuID49IDIwMClcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignU2hhMyBzdXBwb3J0cyBvbmx5IGtlY2Nhay1mMTYwMCBmdW5jdGlvbicpO1xuICAgICAgICB0aGlzLnN0YXRlID0gbmV3IFVpbnQ4QXJyYXkoMjAwKTtcbiAgICAgICAgdGhpcy5zdGF0ZTMyID0gdTMyKHRoaXMuc3RhdGUpO1xuICAgIH1cbiAgICBrZWNjYWsoKSB7XG4gICAgICAgIGtlY2Nha1AodGhpcy5zdGF0ZTMyLCB0aGlzLnJvdW5kcyk7XG4gICAgICAgIHRoaXMucG9zT3V0ID0gMDtcbiAgICAgICAgdGhpcy5wb3MgPSAwO1xuICAgIH1cbiAgICB1cGRhdGUoZGF0YSkge1xuICAgICAgICBhc3NlcnQuZXhpc3RzKHRoaXMpO1xuICAgICAgICBjb25zdCB7IGJsb2NrTGVuLCBzdGF0ZSB9ID0gdGhpcztcbiAgICAgICAgZGF0YSA9IHRvQnl0ZXMoZGF0YSk7XG4gICAgICAgIGNvbnN0IGxlbiA9IGRhdGEubGVuZ3RoO1xuICAgICAgICBmb3IgKGxldCBwb3MgPSAwOyBwb3MgPCBsZW47KSB7XG4gICAgICAgICAgICBjb25zdCB0YWtlID0gTWF0aC5taW4oYmxvY2tMZW4gLSB0aGlzLnBvcywgbGVuIC0gcG9zKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGFrZTsgaSsrKVxuICAgICAgICAgICAgICAgIHN0YXRlW3RoaXMucG9zKytdIF49IGRhdGFbcG9zKytdO1xuICAgICAgICAgICAgaWYgKHRoaXMucG9zID09PSBibG9ja0xlbilcbiAgICAgICAgICAgICAgICB0aGlzLmtlY2NhaygpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBmaW5pc2goKSB7XG4gICAgICAgIGlmICh0aGlzLmZpbmlzaGVkKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB0aGlzLmZpbmlzaGVkID0gdHJ1ZTtcbiAgICAgICAgY29uc3QgeyBzdGF0ZSwgc3VmZml4LCBwb3MsIGJsb2NrTGVuIH0gPSB0aGlzO1xuICAgICAgICAvLyBEbyB0aGUgcGFkZGluZ1xuICAgICAgICBzdGF0ZVtwb3NdIF49IHN1ZmZpeDtcbiAgICAgICAgaWYgKChzdWZmaXggJiAweDgwKSAhPT0gMCAmJiBwb3MgPT09IGJsb2NrTGVuIC0gMSlcbiAgICAgICAgICAgIHRoaXMua2VjY2FrKCk7XG4gICAgICAgIHN0YXRlW2Jsb2NrTGVuIC0gMV0gXj0gMHg4MDtcbiAgICAgICAgdGhpcy5rZWNjYWsoKTtcbiAgICB9XG4gICAgd3JpdGVJbnRvKG91dCkge1xuICAgICAgICBhc3NlcnQuZXhpc3RzKHRoaXMsIGZhbHNlKTtcbiAgICAgICAgYXNzZXJ0LmJ5dGVzKG91dCk7XG4gICAgICAgIHRoaXMuZmluaXNoKCk7XG4gICAgICAgIGNvbnN0IGJ1ZmZlck91dCA9IHRoaXMuc3RhdGU7XG4gICAgICAgIGNvbnN0IHsgYmxvY2tMZW4gfSA9IHRoaXM7XG4gICAgICAgIGZvciAobGV0IHBvcyA9IDAsIGxlbiA9IG91dC5sZW5ndGg7IHBvcyA8IGxlbjspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBvc091dCA+PSBibG9ja0xlbilcbiAgICAgICAgICAgICAgICB0aGlzLmtlY2NhaygpO1xuICAgICAgICAgICAgY29uc3QgdGFrZSA9IE1hdGgubWluKGJsb2NrTGVuIC0gdGhpcy5wb3NPdXQsIGxlbiAtIHBvcyk7XG4gICAgICAgICAgICBvdXQuc2V0KGJ1ZmZlck91dC5zdWJhcnJheSh0aGlzLnBvc091dCwgdGhpcy5wb3NPdXQgKyB0YWtlKSwgcG9zKTtcbiAgICAgICAgICAgIHRoaXMucG9zT3V0ICs9IHRha2U7XG4gICAgICAgICAgICBwb3MgKz0gdGFrZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH1cbiAgICB4b2ZJbnRvKG91dCkge1xuICAgICAgICAvLyBTaGEzL0tlY2NhayB1c2FnZSB3aXRoIFhPRiBpcyBwcm9iYWJseSBtaXN0YWtlLCBvbmx5IFNIQUtFIGluc3RhbmNlcyBjYW4gZG8gWE9GXG4gICAgICAgIGlmICghdGhpcy5lbmFibGVYT0YpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1hPRiBpcyBub3QgcG9zc2libGUgZm9yIHRoaXMgaW5zdGFuY2UnKTtcbiAgICAgICAgcmV0dXJuIHRoaXMud3JpdGVJbnRvKG91dCk7XG4gICAgfVxuICAgIHhvZihieXRlcykge1xuICAgICAgICBhc3NlcnQubnVtYmVyKGJ5dGVzKTtcbiAgICAgICAgcmV0dXJuIHRoaXMueG9mSW50byhuZXcgVWludDhBcnJheShieXRlcykpO1xuICAgIH1cbiAgICBkaWdlc3RJbnRvKG91dCkge1xuICAgICAgICBhc3NlcnQub3V0cHV0KG91dCwgdGhpcyk7XG4gICAgICAgIGlmICh0aGlzLmZpbmlzaGVkKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkaWdlc3QoKSB3YXMgYWxyZWFkeSBjYWxsZWQnKTtcbiAgICAgICAgdGhpcy53cml0ZUludG8ob3V0KTtcbiAgICAgICAgdGhpcy5kZXN0cm95KCk7XG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfVxuICAgIGRpZ2VzdCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGlnZXN0SW50byhuZXcgVWludDhBcnJheSh0aGlzLm91dHB1dExlbikpO1xuICAgIH1cbiAgICBkZXN0cm95KCkge1xuICAgICAgICB0aGlzLmRlc3Ryb3llZCA9IHRydWU7XG4gICAgICAgIHRoaXMuc3RhdGUuZmlsbCgwKTtcbiAgICB9XG4gICAgX2Nsb25lSW50byh0bykge1xuICAgICAgICBjb25zdCB7IGJsb2NrTGVuLCBzdWZmaXgsIG91dHB1dExlbiwgcm91bmRzLCBlbmFibGVYT0YgfSA9IHRoaXM7XG4gICAgICAgIHRvIHx8ICh0byA9IG5ldyBLZWNjYWsoYmxvY2tMZW4sIHN1ZmZpeCwgb3V0cHV0TGVuLCBlbmFibGVYT0YsIHJvdW5kcykpO1xuICAgICAgICB0by5zdGF0ZTMyLnNldCh0aGlzLnN0YXRlMzIpO1xuICAgICAgICB0by5wb3MgPSB0aGlzLnBvcztcbiAgICAgICAgdG8ucG9zT3V0ID0gdGhpcy5wb3NPdXQ7XG4gICAgICAgIHRvLmZpbmlzaGVkID0gdGhpcy5maW5pc2hlZDtcbiAgICAgICAgdG8ucm91bmRzID0gcm91bmRzO1xuICAgICAgICAvLyBTdWZmaXggY2FuIGNoYW5nZSBpbiBjU0hBS0VcbiAgICAgICAgdG8uc3VmZml4ID0gc3VmZml4O1xuICAgICAgICB0by5vdXRwdXRMZW4gPSBvdXRwdXRMZW47XG4gICAgICAgIHRvLmVuYWJsZVhPRiA9IGVuYWJsZVhPRjtcbiAgICAgICAgdG8uZGVzdHJveWVkID0gdGhpcy5kZXN0cm95ZWQ7XG4gICAgICAgIHJldHVybiB0bztcbiAgICB9XG59XG5jb25zdCBnZW4gPSAoc3VmZml4LCBibG9ja0xlbiwgb3V0cHV0TGVuKSA9PiB3cmFwQ29uc3RydWN0b3IoKCkgPT4gbmV3IEtlY2NhayhibG9ja0xlbiwgc3VmZml4LCBvdXRwdXRMZW4pKTtcbmV4cG9ydCBjb25zdCBzaGEzXzIyNCA9IGdlbigweDA2LCAxNDQsIDIyNCAvIDgpO1xuLyoqXG4gKiBTSEEzLTI1NiBoYXNoIGZ1bmN0aW9uXG4gKiBAcGFyYW0gbWVzc2FnZSAtIHRoYXQgd291bGQgYmUgaGFzaGVkXG4gKi9cbmV4cG9ydCBjb25zdCBzaGEzXzI1NiA9IGdlbigweDA2LCAxMzYsIDI1NiAvIDgpO1xuZXhwb3J0IGNvbnN0IHNoYTNfMzg0ID0gZ2VuKDB4MDYsIDEwNCwgMzg0IC8gOCk7XG5leHBvcnQgY29uc3Qgc2hhM181MTIgPSBnZW4oMHgwNiwgNzIsIDUxMiAvIDgpO1xuZXhwb3J0IGNvbnN0IGtlY2Nha18yMjQgPSBnZW4oMHgwMSwgMTQ0LCAyMjQgLyA4KTtcbi8qKlxuICoga2VjY2FrLTI1NiBoYXNoIGZ1bmN0aW9uLiBEaWZmZXJlbnQgZnJvbSBTSEEzLTI1Ni5cbiAqIEBwYXJhbSBtZXNzYWdlIC0gdGhhdCB3b3VsZCBiZSBoYXNoZWRcbiAqL1xuZXhwb3J0IGNvbnN0IGtlY2Nha18yNTYgPSBnZW4oMHgwMSwgMTM2LCAyNTYgLyA4KTtcbmV4cG9ydCBjb25zdCBrZWNjYWtfMzg0ID0gZ2VuKDB4MDEsIDEwNCwgMzg0IC8gOCk7XG5leHBvcnQgY29uc3Qga2VjY2FrXzUxMiA9IGdlbigweDAxLCA3MiwgNTEyIC8gOCk7XG5jb25zdCBnZW5TaGFrZSA9IChzdWZmaXgsIGJsb2NrTGVuLCBvdXRwdXRMZW4pID0+IHdyYXBDb25zdHJ1Y3RvcldpdGhPcHRzKChvcHRzID0ge30pID0+IG5ldyBLZWNjYWsoYmxvY2tMZW4sIHN1ZmZpeCwgb3B0cy5ka0xlbiA9PT0gdW5kZWZpbmVkID8gb3V0cHV0TGVuIDogb3B0cy5ka0xlbiwgdHJ1ZSkpO1xuZXhwb3J0IGNvbnN0IHNoYWtlMTI4ID0gZ2VuU2hha2UoMHgxZiwgMTY4LCAxMjggLyA4KTtcbmV4cG9ydCBjb25zdCBzaGFrZTI1NiA9IGdlblNoYWtlKDB4MWYsIDEzNiwgMjU2IC8gOCk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1zaGEzLmpzLm1hcCJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/@noble/hashes/esm/sha3.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/@noble/hashes/esm/utils.js":
+/*!*************************************************!*\
+  !*** ./node_modules/@noble/hashes/esm/utils.js ***!
+  \*************************************************/
+/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   Hash: () => (/* binding */ Hash),\n/* harmony export */   asyncLoop: () => (/* binding */ asyncLoop),\n/* harmony export */   bytesToHex: () => (/* binding */ bytesToHex),\n/* harmony export */   checkOpts: () => (/* binding */ checkOpts),\n/* harmony export */   concatBytes: () => (/* binding */ concatBytes),\n/* harmony export */   createView: () => (/* binding */ createView),\n/* harmony export */   hexToBytes: () => (/* binding */ hexToBytes),\n/* harmony export */   isLE: () => (/* binding */ isLE),\n/* harmony export */   nextTick: () => (/* binding */ nextTick),\n/* harmony export */   randomBytes: () => (/* binding */ randomBytes),\n/* harmony export */   rotr: () => (/* binding */ rotr),\n/* harmony export */   toBytes: () => (/* binding */ toBytes),\n/* harmony export */   u32: () => (/* binding */ u32),\n/* harmony export */   u8: () => (/* binding */ u8),\n/* harmony export */   utf8ToBytes: () => (/* binding */ utf8ToBytes),\n/* harmony export */   wrapConstructor: () => (/* binding */ wrapConstructor),\n/* harmony export */   wrapConstructorWithOpts: () => (/* binding */ wrapConstructorWithOpts)\n/* harmony export */ });\n/* harmony import */ var _noble_hashes_crypto__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @noble/hashes/crypto */ \"./node_modules/@noble/hashes/esm/crypto.js\");\n/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// We use `globalThis.crypto`, but node.js versions earlier than v19 don't\n// declare it in global scope. For node.js, package.json#exports field mapping\n// rewrites import from `crypto` to `cryptoNode`, which imports native module.\n// Makes the utils un-importable in browsers without a bundler.\n// Once node.js 18 is deprecated, we can just drop the import.\n\n// Cast array to different type\nconst u8 = (arr) => new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\nconst u32 = (arr) => new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));\n// Cast array to view\nconst createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);\n// The rotate right (circular right shift) operation for uint32\nconst rotr = (word, shift) => (word << (32 - shift)) | (word >>> shift);\n// big-endian hardware is rare. Just in case someone still decides to run hashes:\n// early-throw an error because we don't support BE yet.\nconst isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44;\nif (!isLE)\n    throw new Error('Non little-endian hardware is not supported');\nconst hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'));\n/**\n * @example bytesToHex(Uint8Array.from([0xde, 0xad, 0xbe, 0xef])) // 'deadbeef'\n */\nfunction bytesToHex(uint8a) {\n    // pre-caching improves the speed 6x\n    if (!(uint8a instanceof Uint8Array))\n        throw new Error('Uint8Array expected');\n    let hex = '';\n    for (let i = 0; i < uint8a.length; i++) {\n        hex += hexes[uint8a[i]];\n    }\n    return hex;\n}\n/**\n * @example hexToBytes('deadbeef') // Uint8Array.from([0xde, 0xad, 0xbe, 0xef])\n */\nfunction hexToBytes(hex) {\n    if (typeof hex !== 'string') {\n        throw new TypeError('hexToBytes: expected string, got ' + typeof hex);\n    }\n    if (hex.length % 2)\n        throw new Error('hexToBytes: received invalid unpadded hex');\n    const array = new Uint8Array(hex.length / 2);\n    for (let i = 0; i < array.length; i++) {\n        const j = i * 2;\n        const hexByte = hex.slice(j, j + 2);\n        const byte = Number.parseInt(hexByte, 16);\n        if (Number.isNaN(byte) || byte < 0)\n            throw new Error('Invalid byte sequence');\n        array[i] = byte;\n    }\n    return array;\n}\n// There is no setImmediate in browser and setTimeout is slow.\n// call of async fn will return Promise, which will be fullfiled only on\n// next scheduler queue processing step and this is exactly what we need.\nconst nextTick = async () => { };\n// Returns control to thread each 'tick' ms to avoid blocking\nasync function asyncLoop(iters, tick, cb) {\n    let ts = Date.now();\n    for (let i = 0; i < iters; i++) {\n        cb(i);\n        // Date.now() is not monotonic, so in case if clock goes backwards we return return control too\n        const diff = Date.now() - ts;\n        if (diff >= 0 && diff < tick)\n            continue;\n        await nextTick();\n        ts += diff;\n    }\n}\nfunction utf8ToBytes(str) {\n    if (typeof str !== 'string') {\n        throw new TypeError(`utf8ToBytes expected string, got ${typeof str}`);\n    }\n    return new TextEncoder().encode(str);\n}\nfunction toBytes(data) {\n    if (typeof data === 'string')\n        data = utf8ToBytes(data);\n    if (!(data instanceof Uint8Array))\n        throw new TypeError(`Expected input type is Uint8Array (got ${typeof data})`);\n    return data;\n}\n/**\n * Concats Uint8Array-s into one; like `Buffer.concat([buf1, buf2])`\n * @example concatBytes(buf1, buf2)\n */\nfunction concatBytes(...arrays) {\n    if (!arrays.every((a) => a instanceof Uint8Array))\n        throw new Error('Uint8Array list expected');\n    if (arrays.length === 1)\n        return arrays[0];\n    const length = arrays.reduce((a, arr) => a + arr.length, 0);\n    const result = new Uint8Array(length);\n    for (let i = 0, pad = 0; i < arrays.length; i++) {\n        const arr = arrays[i];\n        result.set(arr, pad);\n        pad += arr.length;\n    }\n    return result;\n}\n// For runtime check if class implements interface\nclass Hash {\n    // Safe version that clones internal state\n    clone() {\n        return this._cloneInto();\n    }\n}\n// Check if object doens't have custom constructor (like Uint8Array/Array)\nconst isPlainObject = (obj) => Object.prototype.toString.call(obj) === '[object Object]' && obj.constructor === Object;\nfunction checkOpts(defaults, opts) {\n    if (opts !== undefined && (typeof opts !== 'object' || !isPlainObject(opts)))\n        throw new TypeError('Options should be object or undefined');\n    const merged = Object.assign(defaults, opts);\n    return merged;\n}\nfunction wrapConstructor(hashConstructor) {\n    const hashC = (message) => hashConstructor().update(toBytes(message)).digest();\n    const tmp = hashConstructor();\n    hashC.outputLen = tmp.outputLen;\n    hashC.blockLen = tmp.blockLen;\n    hashC.create = () => hashConstructor();\n    return hashC;\n}\nfunction wrapConstructorWithOpts(hashCons) {\n    const hashC = (msg, opts) => hashCons(opts).update(toBytes(msg)).digest();\n    const tmp = hashCons({});\n    hashC.outputLen = tmp.outputLen;\n    hashC.blockLen = tmp.blockLen;\n    hashC.create = (opts) => hashCons(opts);\n    return hashC;\n}\n/**\n * Secure PRNG. Uses `globalThis.crypto` or node.js crypto module.\n */\nfunction randomBytes(bytesLength = 32) {\n    if (_noble_hashes_crypto__WEBPACK_IMPORTED_MODULE_0__.crypto && typeof _noble_hashes_crypto__WEBPACK_IMPORTED_MODULE_0__.crypto.getRandomValues === 'function') {\n        return _noble_hashes_crypto__WEBPACK_IMPORTED_MODULE_0__.crypto.getRandomValues(new Uint8Array(bytesLength));\n    }\n    throw new Error('crypto.getRandomValues must be defined');\n}\n//# sourceMappingURL=utils.js.map//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQG5vYmxlL2hhc2hlcy9lc20vdXRpbHMuanMuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvQG5vYmxlL2hhc2hlcy9lc20vdXRpbHMuanM/M2Y5MiJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiEgbm9ibGUtaGFzaGVzIC0gTUlUIExpY2Vuc2UgKGMpIDIwMjIgUGF1bCBNaWxsZXIgKHBhdWxtaWxsci5jb20pICovXG4vLyBXZSB1c2UgYGdsb2JhbFRoaXMuY3J5cHRvYCwgYnV0IG5vZGUuanMgdmVyc2lvbnMgZWFybGllciB0aGFuIHYxOSBkb24ndFxuLy8gZGVjbGFyZSBpdCBpbiBnbG9iYWwgc2NvcGUuIEZvciBub2RlLmpzLCBwYWNrYWdlLmpzb24jZXhwb3J0cyBmaWVsZCBtYXBwaW5nXG4vLyByZXdyaXRlcyBpbXBvcnQgZnJvbSBgY3J5cHRvYCB0byBgY3J5cHRvTm9kZWAsIHdoaWNoIGltcG9ydHMgbmF0aXZlIG1vZHVsZS5cbi8vIE1ha2VzIHRoZSB1dGlscyB1bi1pbXBvcnRhYmxlIGluIGJyb3dzZXJzIHdpdGhvdXQgYSBidW5kbGVyLlxuLy8gT25jZSBub2RlLmpzIDE4IGlzIGRlcHJlY2F0ZWQsIHdlIGNhbiBqdXN0IGRyb3AgdGhlIGltcG9ydC5cbmltcG9ydCB7IGNyeXB0byB9IGZyb20gJ0Bub2JsZS9oYXNoZXMvY3J5cHRvJztcbi8vIENhc3QgYXJyYXkgdG8gZGlmZmVyZW50IHR5cGVcbmV4cG9ydCBjb25zdCB1OCA9IChhcnIpID0+IG5ldyBVaW50OEFycmF5KGFyci5idWZmZXIsIGFyci5ieXRlT2Zmc2V0LCBhcnIuYnl0ZUxlbmd0aCk7XG5leHBvcnQgY29uc3QgdTMyID0gKGFycikgPT4gbmV3IFVpbnQzMkFycmF5KGFyci5idWZmZXIsIGFyci5ieXRlT2Zmc2V0LCBNYXRoLmZsb29yKGFyci5ieXRlTGVuZ3RoIC8gNCkpO1xuLy8gQ2FzdCBhcnJheSB0byB2aWV3XG5leHBvcnQgY29uc3QgY3JlYXRlVmlldyA9IChhcnIpID0+IG5ldyBEYXRhVmlldyhhcnIuYnVmZmVyLCBhcnIuYnl0ZU9mZnNldCwgYXJyLmJ5dGVMZW5ndGgpO1xuLy8gVGhlIHJvdGF0ZSByaWdodCAoY2lyY3VsYXIgcmlnaHQgc2hpZnQpIG9wZXJhdGlvbiBmb3IgdWludDMyXG5leHBvcnQgY29uc3Qgcm90ciA9ICh3b3JkLCBzaGlmdCkgPT4gKHdvcmQgPDwgKDMyIC0gc2hpZnQpKSB8ICh3b3JkID4+PiBzaGlmdCk7XG4vLyBiaWctZW5kaWFuIGhhcmR3YXJlIGlzIHJhcmUuIEp1c3QgaW4gY2FzZSBzb21lb25lIHN0aWxsIGRlY2lkZXMgdG8gcnVuIGhhc2hlczpcbi8vIGVhcmx5LXRocm93IGFuIGVycm9yIGJlY2F1c2Ugd2UgZG9uJ3Qgc3VwcG9ydCBCRSB5ZXQuXG5leHBvcnQgY29uc3QgaXNMRSA9IG5ldyBVaW50OEFycmF5KG5ldyBVaW50MzJBcnJheShbMHgxMTIyMzM0NF0pLmJ1ZmZlcilbMF0gPT09IDB4NDQ7XG5pZiAoIWlzTEUpXG4gICAgdGhyb3cgbmV3IEVycm9yKCdOb24gbGl0dGxlLWVuZGlhbiBoYXJkd2FyZSBpcyBub3Qgc3VwcG9ydGVkJyk7XG5jb25zdCBoZXhlcyA9IEFycmF5LmZyb20oeyBsZW5ndGg6IDI1NiB9LCAodiwgaSkgPT4gaS50b1N0cmluZygxNikucGFkU3RhcnQoMiwgJzAnKSk7XG4vKipcbiAqIEBleGFtcGxlIGJ5dGVzVG9IZXgoVWludDhBcnJheS5mcm9tKFsweGRlLCAweGFkLCAweGJlLCAweGVmXSkpIC8vICdkZWFkYmVlZidcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ5dGVzVG9IZXgodWludDhhKSB7XG4gICAgLy8gcHJlLWNhY2hpbmcgaW1wcm92ZXMgdGhlIHNwZWVkIDZ4XG4gICAgaWYgKCEodWludDhhIGluc3RhbmNlb2YgVWludDhBcnJheSkpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVWludDhBcnJheSBleHBlY3RlZCcpO1xuICAgIGxldCBoZXggPSAnJztcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHVpbnQ4YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBoZXggKz0gaGV4ZXNbdWludDhhW2ldXTtcbiAgICB9XG4gICAgcmV0dXJuIGhleDtcbn1cbi8qKlxuICogQGV4YW1wbGUgaGV4VG9CeXRlcygnZGVhZGJlZWYnKSAvLyBVaW50OEFycmF5LmZyb20oWzB4ZGUsIDB4YWQsIDB4YmUsIDB4ZWZdKVxuICovXG5leHBvcnQgZnVuY3Rpb24gaGV4VG9CeXRlcyhoZXgpIHtcbiAgICBpZiAodHlwZW9mIGhleCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaGV4VG9CeXRlczogZXhwZWN0ZWQgc3RyaW5nLCBnb3QgJyArIHR5cGVvZiBoZXgpO1xuICAgIH1cbiAgICBpZiAoaGV4Lmxlbmd0aCAlIDIpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaGV4VG9CeXRlczogcmVjZWl2ZWQgaW52YWxpZCB1bnBhZGRlZCBoZXgnKTtcbiAgICBjb25zdCBhcnJheSA9IG5ldyBVaW50OEFycmF5KGhleC5sZW5ndGggLyAyKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGogPSBpICogMjtcbiAgICAgICAgY29uc3QgaGV4Qnl0ZSA9IGhleC5zbGljZShqLCBqICsgMik7XG4gICAgICAgIGNvbnN0IGJ5dGUgPSBOdW1iZXIucGFyc2VJbnQoaGV4Qnl0ZSwgMTYpO1xuICAgICAgICBpZiAoTnVtYmVyLmlzTmFOKGJ5dGUpIHx8IGJ5dGUgPCAwKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGJ5dGUgc2VxdWVuY2UnKTtcbiAgICAgICAgYXJyYXlbaV0gPSBieXRlO1xuICAgIH1cbiAgICByZXR1cm4gYXJyYXk7XG59XG4vLyBUaGVyZSBpcyBubyBzZXRJbW1lZGlhdGUgaW4gYnJvd3NlciBhbmQgc2V0VGltZW91dCBpcyBzbG93LlxuLy8gY2FsbCBvZiBhc3luYyBmbiB3aWxsIHJldHVybiBQcm9taXNlLCB3aGljaCB3aWxsIGJlIGZ1bGxmaWxlZCBvbmx5IG9uXG4vLyBuZXh0IHNjaGVkdWxlciBxdWV1ZSBwcm9jZXNzaW5nIHN0ZXAgYW5kIHRoaXMgaXMgZXhhY3RseSB3aGF0IHdlIG5lZWQuXG5leHBvcnQgY29uc3QgbmV4dFRpY2sgPSBhc3luYyAoKSA9PiB7IH07XG4vLyBSZXR1cm5zIGNvbnRyb2wgdG8gdGhyZWFkIGVhY2ggJ3RpY2snIG1zIHRvIGF2b2lkIGJsb2NraW5nXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXN5bmNMb29wKGl0ZXJzLCB0aWNrLCBjYikge1xuICAgIGxldCB0cyA9IERhdGUubm93KCk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpdGVyczsgaSsrKSB7XG4gICAgICAgIGNiKGkpO1xuICAgICAgICAvLyBEYXRlLm5vdygpIGlzIG5vdCBtb25vdG9uaWMsIHNvIGluIGNhc2UgaWYgY2xvY2sgZ29lcyBiYWNrd2FyZHMgd2UgcmV0dXJuIHJldHVybiBjb250cm9sIHRvb1xuICAgICAgICBjb25zdCBkaWZmID0gRGF0ZS5ub3coKSAtIHRzO1xuICAgICAgICBpZiAoZGlmZiA+PSAwICYmIGRpZmYgPCB0aWNrKVxuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIGF3YWl0IG5leHRUaWNrKCk7XG4gICAgICAgIHRzICs9IGRpZmY7XG4gICAgfVxufVxuZXhwb3J0IGZ1bmN0aW9uIHV0ZjhUb0J5dGVzKHN0cikge1xuICAgIGlmICh0eXBlb2Ygc3RyICE9PSAnc3RyaW5nJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGB1dGY4VG9CeXRlcyBleHBlY3RlZCBzdHJpbmcsIGdvdCAke3R5cGVvZiBzdHJ9YCk7XG4gICAgfVxuICAgIHJldHVybiBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoc3RyKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiB0b0J5dGVzKGRhdGEpIHtcbiAgICBpZiAodHlwZW9mIGRhdGEgPT09ICdzdHJpbmcnKVxuICAgICAgICBkYXRhID0gdXRmOFRvQnl0ZXMoZGF0YSk7XG4gICAgaWYgKCEoZGF0YSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBFeHBlY3RlZCBpbnB1dCB0eXBlIGlzIFVpbnQ4QXJyYXkgKGdvdCAke3R5cGVvZiBkYXRhfSlgKTtcbiAgICByZXR1cm4gZGF0YTtcbn1cbi8qKlxuICogQ29uY2F0cyBVaW50OEFycmF5LXMgaW50byBvbmU7IGxpa2UgYEJ1ZmZlci5jb25jYXQoW2J1ZjEsIGJ1ZjJdKWBcbiAqIEBleGFtcGxlIGNvbmNhdEJ5dGVzKGJ1ZjEsIGJ1ZjIpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb25jYXRCeXRlcyguLi5hcnJheXMpIHtcbiAgICBpZiAoIWFycmF5cy5ldmVyeSgoYSkgPT4gYSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VpbnQ4QXJyYXkgbGlzdCBleHBlY3RlZCcpO1xuICAgIGlmIChhcnJheXMubGVuZ3RoID09PSAxKVxuICAgICAgICByZXR1cm4gYXJyYXlzWzBdO1xuICAgIGNvbnN0IGxlbmd0aCA9IGFycmF5cy5yZWR1Y2UoKGEsIGFycikgPT4gYSArIGFyci5sZW5ndGgsIDApO1xuICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCk7XG4gICAgZm9yIChsZXQgaSA9IDAsIHBhZCA9IDA7IGkgPCBhcnJheXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgYXJyID0gYXJyYXlzW2ldO1xuICAgICAgICByZXN1bHQuc2V0KGFyciwgcGFkKTtcbiAgICAgICAgcGFkICs9IGFyci5sZW5ndGg7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG59XG4vLyBGb3IgcnVudGltZSBjaGVjayBpZiBjbGFzcyBpbXBsZW1lbnRzIGludGVyZmFjZVxuZXhwb3J0IGNsYXNzIEhhc2gge1xuICAgIC8vIFNhZmUgdmVyc2lvbiB0aGF0IGNsb25lcyBpbnRlcm5hbCBzdGF0ZVxuICAgIGNsb25lKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2xvbmVJbnRvKCk7XG4gICAgfVxufVxuLy8gQ2hlY2sgaWYgb2JqZWN0IGRvZW5zJ3QgaGF2ZSBjdXN0b20gY29uc3RydWN0b3IgKGxpa2UgVWludDhBcnJheS9BcnJheSlcbmNvbnN0IGlzUGxhaW5PYmplY3QgPSAob2JqKSA9PiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKSA9PT0gJ1tvYmplY3QgT2JqZWN0XScgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBPYmplY3Q7XG5leHBvcnQgZnVuY3Rpb24gY2hlY2tPcHRzKGRlZmF1bHRzLCBvcHRzKSB7XG4gICAgaWYgKG9wdHMgIT09IHVuZGVmaW5lZCAmJiAodHlwZW9mIG9wdHMgIT09ICdvYmplY3QnIHx8ICFpc1BsYWluT2JqZWN0KG9wdHMpKSlcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignT3B0aW9ucyBzaG91bGQgYmUgb2JqZWN0IG9yIHVuZGVmaW5lZCcpO1xuICAgIGNvbnN0IG1lcmdlZCA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIG9wdHMpO1xuICAgIHJldHVybiBtZXJnZWQ7XG59XG5leHBvcnQgZnVuY3Rpb24gd3JhcENvbnN0cnVjdG9yKGhhc2hDb25zdHJ1Y3Rvcikge1xuICAgIGNvbnN0IGhhc2hDID0gKG1lc3NhZ2UpID0+IGhhc2hDb25zdHJ1Y3RvcigpLnVwZGF0ZSh0b0J5dGVzKG1lc3NhZ2UpKS5kaWdlc3QoKTtcbiAgICBjb25zdCB0bXAgPSBoYXNoQ29uc3RydWN0b3IoKTtcbiAgICBoYXNoQy5vdXRwdXRMZW4gPSB0bXAub3V0cHV0TGVuO1xuICAgIGhhc2hDLmJsb2NrTGVuID0gdG1wLmJsb2NrTGVuO1xuICAgIGhhc2hDLmNyZWF0ZSA9ICgpID0+IGhhc2hDb25zdHJ1Y3RvcigpO1xuICAgIHJldHVybiBoYXNoQztcbn1cbmV4cG9ydCBmdW5jdGlvbiB3cmFwQ29uc3RydWN0b3JXaXRoT3B0cyhoYXNoQ29ucykge1xuICAgIGNvbnN0IGhhc2hDID0gKG1zZywgb3B0cykgPT4gaGFzaENvbnMob3B0cykudXBkYXRlKHRvQnl0ZXMobXNnKSkuZGlnZXN0KCk7XG4gICAgY29uc3QgdG1wID0gaGFzaENvbnMoe30pO1xuICAgIGhhc2hDLm91dHB1dExlbiA9IHRtcC5vdXRwdXRMZW47XG4gICAgaGFzaEMuYmxvY2tMZW4gPSB0bXAuYmxvY2tMZW47XG4gICAgaGFzaEMuY3JlYXRlID0gKG9wdHMpID0+IGhhc2hDb25zKG9wdHMpO1xuICAgIHJldHVybiBoYXNoQztcbn1cbi8qKlxuICogU2VjdXJlIFBSTkcuIFVzZXMgYGdsb2JhbFRoaXMuY3J5cHRvYCBvciBub2RlLmpzIGNyeXB0byBtb2R1bGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5kb21CeXRlcyhieXRlc0xlbmd0aCA9IDMyKSB7XG4gICAgaWYgKGNyeXB0byAmJiB0eXBlb2YgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhuZXcgVWludDhBcnJheShieXRlc0xlbmd0aCkpO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NyeXB0by5nZXRSYW5kb21WYWx1ZXMgbXVzdCBiZSBkZWZpbmVkJyk7XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD11dGlscy5qcy5tYXAiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/@noble/hashes/esm/utils.js\n");
+
+/***/ })
+
+/******/ 	});
+/************************************************************************/
+/******/ 	// The module cache
+/******/ 	var __webpack_module_cache__ = {};
+/******/ 	
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/ 		// Check if module is in cache
+/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
+/******/ 		if (cachedModule !== undefined) {
+/******/ 			return cachedModule.exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = __webpack_module_cache__[moduleId] = {
+/******/ 			// no module.id needed
+/******/ 			// no module.loaded needed
+/******/ 			exports: {}
+/******/ 		};
+/******/ 	
+/******/ 		// Execute the module function
+/******/ 		__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/ 	
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/ 	
+/************************************************************************/
+/******/ 	/* webpack/runtime/compat get default export */
+/******/ 	(() => {
+/******/ 		// getDefaultExport function for compatibility with non-harmony modules
+/******/ 		__webpack_require__.n = (module) => {
+/******/ 			var getter = module && module.__esModule ?
+/******/ 				() => (module['default']) :
+/******/ 				() => (module);
+/******/ 			__webpack_require__.d(getter, { a: getter });
+/******/ 			return getter;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/define property getters */
+/******/ 	(() => {
+/******/ 		// define getter functions for harmony exports
+/******/ 		__webpack_require__.d = (exports, definition) => {
+/******/ 			for(var key in definition) {
+/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ 				}
+/******/ 			}
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/global */
+/******/ 	(() => {
+/******/ 		__webpack_require__.g = (function() {
+/******/ 			if (typeof globalThis === 'object') return globalThis;
+/******/ 			try {
+/******/ 				return this || new Function('return this')();
+/******/ 			} catch (e) {
+/******/ 				if (typeof window === 'object') return window;
+/******/ 			}
+/******/ 		})();
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
+/******/ 	(() => {
+/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/make namespace object */
+/******/ 	(() => {
+/******/ 		// define __esModule on exports
+/******/ 		__webpack_require__.r = (exports) => {
+/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 			}
+/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/************************************************************************/
+/******/ 	
+/******/ 	// startup
+/******/ 	// Load entry module and return exports
+/******/ 	// This entry module can't be inlined because the eval-source-map devtool is used.
+/******/ 	var __webpack_exports__ = __webpack_require__("./src/js/main.js");
+/******/ 	lib = __webpack_exports__;
+/******/ 	
+/******/ })()
+;
\ No newline at end of file
diff --git a/dist/checkout.html b/dist/checkout.html
index 1efc975..5e39969 100644
--- a/dist/checkout.html
+++ b/dist/checkout.html
@@ -1 +1 @@
-<!DOCTYPE html><html lang="de"><head><title>Paketshop: Checkout</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon shortcut" href="data:image/x-icon;," type="image/x-icon"><link rel="stylesheet" type="text/css" href="/bootstrap.min.css"><link rel="stylesheet" type="text/css" href="/bootstrap-icons.css"><link rel="stylesheet" type="text/css" href="/index.css"></head><body> <div class="container"> <h1>Checkout</h1> <div class="row"> <button onclick="lib.scanReceiver()" class="btn btn-primary">Scan Code</button> </div> <div class="row"> <input class="form-control" id="checkoutByTag" type="text" placeholder="tag"><button onclick="lib.checkoutByTag()" class="btn btn-primary">Checkout By Tag</button> </div> <div class="row"> <div id="reader" style="width: 500px; margin 0 auto;"></div> </div> <div class="row"> <h2 id="storage"></h2> <div class="col-md-6"> <strong id="tag"></strong><br> <span id="uuid"></span> </div> <div class="col-md-6"> <strong id="addressee"></strong><br> <span id="team"></span> </div> </div> </div>  <script src="./bundle.js"></script> <script>window.onload=function(){lib.onPageLoad(!1)};</script> </body></html>
\ No newline at end of file
+<!DOCTYPE html><html lang="de"><head><title>Paketshop: Checkout</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon shortcut" href="data:image/x-icon;," type="image/x-icon"><link rel="stylesheet" type="text/css" href="/bootstrap.min.css"><link rel="stylesheet" type="text/css" href="/bootstrap-icons.css"><link rel="stylesheet" type="text/css" href="/index.css"></head><body> <div class="container"> <h1>Checkout</h1> <div class="row"> <button onclick="lib.scanReceiver()" class="btn btn-primary">Scan Code</button> </div> <div class="row"> <input class="form-control" id="checkoutByTag" type="text" placeholder="tag"><button onclick="lib.checkoutByTag()" class="btn btn-primary">Checkout By Tag</button> </div> <div class="row"> <div id="reader" style="width: 500px; margin 0 auto;"></div> </div> <div class="row" onclick="lib.checkoutItem()"> <h2 id="storage"></h2> <div class="col-md-6"> <strong id="tag"></strong><br> <span id="uuid"></span> </div> <div class="col-md-6"> <strong id="addressee"></strong><br> <span id="team"></span> </div> </div> </div>  <script src="./bundle.js"></script> <script>window.onload=function(){lib.onPageLoad(!1)};</script> </body></html>
\ No newline at end of file
diff --git a/src/js/main.js b/src/js/main.js
index c1675d7..5c93af6 100644
--- a/src/js/main.js
+++ b/src/js/main.js
@@ -359,6 +359,15 @@ function updateCheckoutItem(tracking_item) {
   document.querySelector("#team").innerHTML = tracking_item.team;
 }
 
+export async function checkoutItem() {
+    let confirmed = confirm("Did you make sure the recipient is really the right person?");
+    if(!confirmed) {
+      console.log("Recipient confirmation denied.");
+      return;
+    }
+    var response = await fetchWithAuth(config.backend_url + "/checkout/" + document.querySelector("#uuid").innerHTML);
+}
+
 async function onRecevierScanSuccess(scannedCode) {
   debounceScanner();
   var [uuid,signature] = scannedCode.split("/");
@@ -439,11 +448,6 @@ export async function checkoutByTag() {
   var response = await fetchWithAuth(config.backend_url + "/tag/" + el.value);
   if (response.status == 200) {
     var tracking_item = await response.json();
-    let confirmed = confirm("Did you make sure the recipient is really the right person?");
-    if(!confirmed) {
-      console.log("Recipient confirmation denied.");
-      return;
-    }
     if(tracking_item.storage == undefined || tracking_item.storage == null || tracking_item.storage.length == 0) {
       alert("Item not yet received.");
       console.log("Item not yet received.");
diff --git a/src/views/checkout.html b/src/views/checkout.html
index 4fe8ea9..8c66dae 100644
--- a/src/views/checkout.html
+++ b/src/views/checkout.html
@@ -17,7 +17,7 @@
       <div class="row">
         <div id="reader" style="width: 500px; margin 0 auto;"></div>
       </div>
-      <div class="row">
+      <div class="row" onclick="lib.checkoutItem()">
         <h2 id="storage"></h2>
         <div class="col-md-6">
           <strong id="tag"></strong><br>
-- 
GitLab